From aefa21c76b6bfc6d2baff450389249599ac3a4c3 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 11 Oct 2016 13:05:24 +0200 Subject: [PATCH 01/38] Moved functions to better place. CURA-2449 CURA-2589 --- cura/CuraApplication.py | 50 ++++------------------------------------- 1 file changed, 4 insertions(+), 46 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index fa22227a43..f993cfcb01 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -49,43 +49,12 @@ from PyQt5.QtGui import QColor, QIcon from PyQt5.QtWidgets import QMessageBox from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qmlRegisterType -from contextlib import contextmanager - import sys import os.path import numpy import copy import urllib import os -import time - -CONFIG_LOCK_FILENAME = "cura.lock" - -## Contextmanager to create a lock file and remove it afterwards. -@contextmanager -def lockFile(filename): - try: - with open(filename, 'w') as lock_file: - lock_file.write("Lock file - Cura is currently writing") - except: - Logger.log("e", "Could not create lock file [%s]" % filename) - yield - try: - if os.path.exists(filename): - os.remove(filename) - except: - Logger.log("e", "Could not delete lock file [%s]" % filename) - - -## Wait for a lock file to disappear -# the maximum allowable age is settable; if the file is too old, it will be ignored too -def waitFileDisappear(filename, max_age_seconds=10, msg=""): - now = time.time() - while os.path.exists(filename) and now < os.path.getmtime(filename) + max_age_seconds and now > os.path.getmtime(filename): - if msg: - Logger.log("d", msg) - time.sleep(1) - now = time.time() numpy.seterr(all="ignore") @@ -234,10 +203,8 @@ class CuraApplication(QtApplication): empty_quality_changes_container.addMetaDataEntry("type", "quality_changes") ContainerRegistry.getInstance().addContainer(empty_quality_changes_container) - # Set the filename to create if cura is writing in the config dir. - self._config_lock_filename = os.path.join(Resources.getConfigStoragePath(), CONFIG_LOCK_FILENAME) - self.waitConfigLockFile() - ContainerRegistry.getInstance().load() + with ContainerRegistry.getInstance().lockFile(): + ContainerRegistry.getInstance().load() Preferences.getInstance().addPreference("cura/active_mode", "simple") Preferences.getInstance().addPreference("cura/recent_files", "") @@ -317,12 +284,6 @@ class CuraApplication(QtApplication): self._recent_files.append(QUrl.fromLocalFile(f)) - ## Lock file check: if (another) Cura is writing in the Config dir. - # one may not be able to read a valid set of files while writing. Not entirely fool-proof, - # but works when you start Cura shortly after shutting down. - def waitConfigLockFile(self): - waitFileDisappear(self._config_lock_filename, max_age_seconds=10, msg="Waiting for Cura to finish writing in the config dir...") - def _onEngineCreated(self): self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider()) @@ -350,11 +311,8 @@ class CuraApplication(QtApplication): if not self._started: # Do not do saving during application start return - self.waitConfigLockFile() - - # When starting Cura, we check for the lockFile which is created and deleted here - with lockFile(self._config_lock_filename): - + # Lock file for "more" atomically loading and saving to/from config dir. + with ContainerRegistry.getInstance().lockFile(): for instance in ContainerRegistry.getInstance().findInstanceContainers(): if not instance.isDirty(): continue From 9449d30d87a20cc56469ffe33a5195b8a0c88156 Mon Sep 17 00:00:00 2001 From: Vincent Marchetti Date: Wed, 9 Nov 2016 07:18:14 -0500 Subject: [PATCH 02/38] Modify reading of Coordinate/@point attribute to allow comma separators --- plugins/X3DReader/X3DReader.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/X3DReader/X3DReader.py b/plugins/X3DReader/X3DReader.py index 4ce21f3f8c..ba31c9ea86 100644 --- a/plugins/X3DReader/X3DReader.py +++ b/plugins/X3DReader/X3DReader.py @@ -700,7 +700,11 @@ class X3DReader(MeshReader): if not c is None: pt = c.attrib.get("point") if pt: - co = [float(x) for x in pt.split()] + # allow the list of float values in 'point' attribute to + # be separated by commas or whitespace as per spec of + # XML encoding of X3D + # Ref ISO/IEC 19776-1:2015 : Section 5.1.2 + co = [float(x) for vec in pt.split(',') for x in vec.split()] num_verts = len(co) // 3 self.verts = numpy.empty((4, num_verts), dtype=numpy.float32) self.verts[3,:] = numpy.ones((num_verts), dtype=numpy.float32) From 7100c84136496d6d0284db15a22fcd6464b3ce31 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 21 Oct 2016 14:14:06 +0200 Subject: [PATCH 03/38] JSON feat: cubic subdivision settings (CURA-2602) --- resources/definitions/fdmprinter.def.json | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 1962476424..b742847894 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1001,6 +1001,7 @@ "lines": "Lines", "triangles": "Triangles", "cubic": "Cubic", + "cubicsubdiv": "Cubic Subdivision", "tetrahedral": "Tetrahedral", "concentric": "Concentric", "concentric_3d": "Concentric 3D", @@ -1011,6 +1012,31 @@ "value": "'lines' if infill_sparse_density > 25 else 'grid'", "settable_per_mesh": true }, + "sub_div_rad_mult": + { + "label": "Cubic Subdivision Radius", + "description": "A multiplier on the radius from the center of each cube to check for the boundary of the model, as to decide whether this cube should be subdivided. Larger values lead to more subdivisions, i.e. more small cubes.", + "unit": "%", + "type": "float", + "default_value": 100, + "minimum_value": "0", + "maximum_value_warning": "200", + "enabled": "infill_sparse_density > 0 and infill_pattern == 'cubicsubdiv'", + "settable_per_mesh": true + }, + "sub_div_rad_add": + { + "label": "Cubic Subdivision Shell", + "description": "An addition to the radius from the center of each cube to check for the boundary of the model, as to decide whether this cube should be subdivided. Larger values lead to a thicker shell of small cubes near the boundary of the model.", + "unit": "mm", + "type": "float", + "default_value": 0.4, + "value": "wall_line_width_x", + "minimum_value_warning": "-1 * infill_line_distance", + "maximum_value_warning": "5 * infill_line_distance", + "enabled": "infill_sparse_density > 0 and infill_pattern == 'cubicsubdiv'", + "settable_per_mesh": true + }, "infill_overlap": { "label": "Infill Overlap Percentage", From b441b1afb02e2a55916747e433ee8c0c41ba4ce5 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Mon, 21 Nov 2016 17:18:22 +0100 Subject: [PATCH 04/38] JSON fix: add a min value warning for cubicsubdiv radius < 100% (CURA-2602) --- 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 b742847894..1b2164cdbc 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1020,6 +1020,7 @@ "type": "float", "default_value": 100, "minimum_value": "0", + "minimum_value_warning": "100", "maximum_value_warning": "200", "enabled": "infill_sparse_density > 0 and infill_pattern == 'cubicsubdiv'", "settable_per_mesh": true From 2c1028e13728a6c306402106bb239710b5eb9835 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 11 Nov 2016 12:01:41 +0100 Subject: [PATCH 05/38] JSON feat: z seam position (CURA-1461) --- cura/CuraApplication.py | 2 ++ resources/definitions/fdmprinter.def.json | 28 ++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 7be20305c4..ce0b3525b6 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -264,6 +264,8 @@ class CuraApplication(QtApplication): shell wall_thickness top_bottom_thickness + z_seam_x + z_seam_y infill infill_sparse_density material diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 45a1d491af..59c269a1fc 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -950,13 +950,39 @@ "type": "enum", "options": { - "back": "Back", + "back": "User Specified", "shortest": "Shortest", "random": "Random" }, "default_value": "shortest", "settable_per_mesh": true }, + "z_seam_x": + { + "label": "Z Seam X", + "description": "The X coordinate of the position near where to start printing each part in a layer.", + "unit": "mm", + "type": "float", + "default_value": 100.0, + "value": "machine_width / 2", + "enabled": "'back' in extruderValues('z_seam_type')", + "settable_per_mesh": false, + "settable_per_extruder": false, + "settable_per_meshgroup": true + }, + "z_seam_y": + { + "label": "Z Seam Y", + "description": "The Y coordinate of the position near where to start printing each part in a layer.", + "unit": "mm", + "type": "float", + "default_value": 100.0, + "value": "machine_depth / 2", + "enabled": "'back' in extruderValues('z_seam_type')", + "settable_per_mesh": true, + "settable_per_extruder": false, + "settable_per_meshgroup": true + }, "skin_no_small_gaps_heuristic": { "label": "Ignore Small Z Gaps", From 84ca1f9cd7ac9b609872ba5881c688f6d8291446 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 25 Nov 2016 16:44:09 +0100 Subject: [PATCH 06/38] JSON fix: make z_seam_pos settable per mesh (CURA-1461) --- resources/definitions/fdmprinter.def.json | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 59c269a1fc..d2bcbe0d9c 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -965,10 +965,8 @@ "type": "float", "default_value": 100.0, "value": "machine_width / 2", - "enabled": "'back' in extruderValues('z_seam_type')", - "settable_per_mesh": false, - "settable_per_extruder": false, - "settable_per_meshgroup": true + "enabled": "z_seam_type == 'back'", + "settable_per_mesh": true }, "z_seam_y": { @@ -978,10 +976,8 @@ "type": "float", "default_value": 100.0, "value": "machine_depth / 2", - "enabled": "'back' in extruderValues('z_seam_type')", - "settable_per_mesh": true, - "settable_per_extruder": false, - "settable_per_meshgroup": true + "enabled": "z_seam_type == 'back'", + "settable_per_mesh": true }, "skin_no_small_gaps_heuristic": { From 9c604bb67494ea5160edf89db67694f4e471725a Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sat, 26 Nov 2016 22:46:21 +0100 Subject: [PATCH 07/38] Fixes two minor issues introduced in the feature_find_settings merge --- resources/qml/Sidebar.qml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index 9c0d641d77..77e82b5f92 100644 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -166,15 +166,6 @@ Rectangle anchors.topMargin: UM.Theme.getSize("default_margin").height } - currentModeIndex: - { - var index = parseInt(UM.Preferences.getValue("cura/active_mode")) - if(index) - { - return index; - } - return 0; - } onCurrentModeIndexChanged: { UM.Preferences.setValue("cura/active_mode", currentModeIndex); @@ -268,7 +259,7 @@ Rectangle height: settingsModeSelection.height width: visible ? height : 0 - visible: !monitoringPrint && modesListModel.get(base.currentModeIndex).showFilterButton + visible: !monitoringPrint && modesListModel.get(base.currentModeIndex) != undefined && modesListModel.get(base.currentModeIndex).showFilterButton opacity: visible ? 1 : 0 onClicked: sidebarContents.currentItem.toggleFilterField() @@ -284,7 +275,7 @@ Rectangle } label: UM.RecolorImage { - anchors.verticalCenter: control.verticalCenter + anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right anchors.rightMargin: UM.Theme.getSize("default_margin").width / 2 @@ -420,6 +411,12 @@ Rectangle modesListModel.append({ text: catalog.i18nc("@title:tab", "Recommended"), item: sidebarSimple, showFilterButton: false }) modesListModel.append({ text: catalog.i18nc("@title:tab", "Custom"), item: sidebarAdvanced, showFilterButton: true }) sidebarContents.push({ "item": modesListModel.get(base.currentModeIndex).item, "immediate": true }); + + var index = parseInt(UM.Preferences.getValue("cura/active_mode")) + if(index) + { + currentModeIndex = index; + } } UM.SettingPropertyProvider From 87587ffd40c4a7c797798b84a94f0f01df4ef261 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 28 Nov 2016 14:11:44 +0100 Subject: [PATCH 08/38] Fix reloading meshes Not tested with 3MF, but for normal cases this should hotfix it. --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index e8c8ba981a..04c7feedc7 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1000,7 +1000,7 @@ 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! - mesh_data = job.getResult().getMeshData() + mesh_data = job.getResult()[0].getMeshData() if mesh_data: job._node.setMeshData(mesh_data) else: From 389bdd3c1bcd9f7b8b32ae4b5a53c84c5fd353d7 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Mon, 28 Nov 2016 15:05:22 +0100 Subject: [PATCH 09/38] JSOn fix: use cubicsubdiv when determining the infill line distance (CURA-2602) --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 1b2164cdbc..dc72766112 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -985,7 +985,7 @@ "default_value": 2, "minimum_value": "0", "minimum_value_warning": "infill_line_width", - "value": "0 if infill_sparse_density == 0 else (infill_line_width * 100) / infill_sparse_density * (2 if infill_pattern == 'grid' else (3 if infill_pattern == 'triangles' or infill_pattern == 'cubic' else (4 if infill_pattern == 'tetrahedral' else 1)))", + "value": "0 if infill_sparse_density == 0 else (infill_line_width * 100) / infill_sparse_density * (2 if infill_pattern == 'grid' else (3 if infill_pattern == 'triangles' or infill_pattern == 'cubic' or infill_pattern == 'cubicsubdiv' else (4 if infill_pattern == 'tetrahedral' else 1)))", "settable_per_mesh": true } } From 5db582437783517722963fa342e32307d8289bb8 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 28 Nov 2016 17:34:16 +0100 Subject: [PATCH 10/38] Hide gradual infill when cubic subdivision infill pattern is selected The setting has no effect then, so it doesn't matter what the value is while it's hidden either. Contributes to issue CURA-2602. --- 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 dc72766112..104ab5ecd2 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1132,7 +1132,7 @@ "minimum_value": "0", "maximum_value_warning": "4", "maximum_value": "20 - math.log(infill_line_distance) / math.log(2)", - "enabled": "infill_sparse_density > 0", + "enabled": "infill_sparse_density > 0 and infill_pattern != 'cubicsubdiv'", "settable_per_mesh": true }, "gradual_infill_step_height": @@ -1145,7 +1145,7 @@ "minimum_value": "0.0001", "minimum_value_warning": "3 * resolveOrValue('layer_height')", "maximum_value_warning": "100", - "enabled": "infill_sparse_density > 0 and gradual_infill_steps > 0", + "enabled": "infill_sparse_density > 0 and gradual_infill_steps > 0 and infill_pattern != 'cubicsubdiv'", "settable_per_mesh": true }, "infill_before_walls": From b9280fef12936ace6ab82f10176b4c4e27165188 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 5 Sep 2016 10:50:48 +0200 Subject: [PATCH 11/38] Allow setting build plate shape --- .../MachineSettingsAction.qml | 40 ++++++++++++++++--- resources/definitions/fdmprinter.def.json | 15 +++++++ 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.qml b/plugins/MachineSettingsAction/MachineSettingsAction.qml index ea299438f0..e52b912459 100644 --- a/plugins/MachineSettingsAction/MachineSettingsAction.qml +++ b/plugins/MachineSettingsAction/MachineSettingsAction.qml @@ -120,12 +120,25 @@ Cura.MachineAction Column { - CheckBox + Row { - id: heatedBedCheckBox - text: catalog.i18nc("@option:check", "Heated Bed") - checked: String(machineHeatedBedProvider.properties.value).toLowerCase() != 'false' - onClicked: machineHeatedBedProvider.setPropertyValue("value", checked) + spacing: UM.Theme.getSize("default_margin").width + + Label + { + text: catalog.i18nc("@label", "Build Plate Shape") + } + + ComboBox + { + model: ["Rectangular", "Elliptic"] + currentIndex: machineShapeProvider.properties.value.toLowerCase() != model[1].toLowerCase() ? 0 : 1 + onActivated: + { + machineShapeProvider.setPropertyValue("value", model[index]); + manager.forceUpdate(); + } + } } CheckBox { @@ -134,6 +147,13 @@ Cura.MachineAction checked: String(machineCenterIsZeroProvider.properties.value).toLowerCase() != 'false' onClicked: machineCenterIsZeroProvider.setPropertyValue("value", checked) } + CheckBox + { + id: heatedBedCheckBox + text: catalog.i18nc("@option:check", "Heated Bed") + checked: String(machineHeatedBedProvider.properties.value).toLowerCase() != 'false' + onClicked: machineHeatedBedProvider.setPropertyValue("value", checked) + } } Row @@ -428,6 +448,16 @@ Cura.MachineAction storeIndex: manager.containerIndex } + UM.SettingPropertyProvider + { + id: machineShapeProvider + + containerStackId: Cura.MachineManager.activeMachineId + key: "machine_shape" + watchedProperties: [ "value" ] + storeIndex: manager.containerIndex + } + UM.SettingPropertyProvider { id: machineHeatedBedProvider diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 45a1d491af..b18971dda8 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -137,6 +137,21 @@ "settable_per_extruder": false, "settable_per_meshgroup": false }, + "machine_shape": + { + "label": "Build plate shape", + "description": "The shape of the build plate without taking unprintable areas into account.", + "default_value": "Rectangular", + "type": "enum", + "options": + { + "rectangular": "Rectangular", + "elliptic": "Elliptic" + }, + "settable_per_mesh": false, + "settable_per_extruder": false, + "settable_per_meshgroup": false + }, "machine_height": { "label": "Machine height", From 2c5a4de2642690b05a53d8a030e71a6241b4ff33 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 5 Sep 2016 10:53:03 +0200 Subject: [PATCH 12/38] Draw circular build plate for polar printers --- cura/BuildVolume.py | 82 +++++++++++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index e5300526d4..8ff241e5ff 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -45,6 +45,7 @@ class BuildVolume(SceneNode): self._width = 0 self._height = 0 self._depth = 0 + self._shape = "" self._shader = None @@ -139,6 +140,9 @@ class BuildVolume(SceneNode): def setDepth(self, depth): if depth: self._depth = depth + def setShape(self, shape): + if shape: self._shape = shape + def getDisallowedAreas(self): return self._disallowed_areas @@ -177,25 +181,59 @@ class BuildVolume(SceneNode): min_d = -self._depth / 2 max_d = self._depth / 2 - mb = MeshBuilder() + if self._shape.lower() != "elliptic": + # Outline 'cube' of the build volume + mb = MeshBuilder() + mb.addLine(Vector(min_w, min_h, min_d), Vector(max_w, min_h, min_d), color = self.VolumeOutlineColor) + mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, max_h, min_d), color = self.VolumeOutlineColor) + mb.addLine(Vector(min_w, max_h, min_d), Vector(max_w, max_h, min_d), color = self.VolumeOutlineColor) + mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, max_h, min_d), color = self.VolumeOutlineColor) - # Outline 'cube' of the build volume - mb.addLine(Vector(min_w, min_h, min_d), Vector(max_w, min_h, min_d), color = self.VolumeOutlineColor) - mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, max_h, min_d), color = self.VolumeOutlineColor) - mb.addLine(Vector(min_w, max_h, min_d), Vector(max_w, max_h, min_d), color = self.VolumeOutlineColor) - mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, max_h, min_d), color = self.VolumeOutlineColor) + mb.addLine(Vector(min_w, min_h, max_d), Vector(max_w, min_h, max_d), color = self.VolumeOutlineColor) + mb.addLine(Vector(min_w, min_h, max_d), Vector(min_w, max_h, max_d), color = self.VolumeOutlineColor) + mb.addLine(Vector(min_w, max_h, max_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor) + mb.addLine(Vector(max_w, min_h, max_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor) - mb.addLine(Vector(min_w, min_h, max_d), Vector(max_w, min_h, max_d), color = self.VolumeOutlineColor) - mb.addLine(Vector(min_w, min_h, max_d), Vector(min_w, max_h, max_d), color = self.VolumeOutlineColor) - mb.addLine(Vector(min_w, max_h, max_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor) - mb.addLine(Vector(max_w, min_h, max_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor) + mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, min_h, max_d), color = self.VolumeOutlineColor) + mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, min_h, max_d), color = self.VolumeOutlineColor) + mb.addLine(Vector(min_w, max_h, min_d), Vector(min_w, max_h, max_d), color = self.VolumeOutlineColor) + mb.addLine(Vector(max_w, max_h, min_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor) - mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, min_h, max_d), color = self.VolumeOutlineColor) - mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, min_h, max_d), color = self.VolumeOutlineColor) - mb.addLine(Vector(min_w, max_h, min_d), Vector(min_w, max_h, max_d), color = self.VolumeOutlineColor) - mb.addLine(Vector(max_w, max_h, min_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor) + self.setMeshData(mb.build()) - self.setMeshData(mb.build()) + # Build plate grid mesh + mb = MeshBuilder() + mb.addQuad( + Vector(min_w, min_h - 0.2, min_d), + Vector(max_w, min_h - 0.2, min_d), + Vector(max_w, min_h - 0.2, max_d), + Vector(min_w, min_h - 0.2, max_d) + ) + + for n in range(0, 6): + v = mb.getVertex(n) + mb.setVertexUVCoordinates(n, v[0], v[2]) + self._grid_mesh = mb.build() + + else: + # Bottom and top 'ellipse' of the build volume + mb = MeshBuilder() + mb.addArc(max_w, Vector.Unit_Y, center = (0, min_h - 0.2, 0), color = self.VolumeOutlineColor) + mb.addArc(max_w, Vector.Unit_Y, center = (0, max_h, 0), color = self.VolumeOutlineColor) + self.setMeshData(mb.build()) + + # Build plate grid mesh + mb = MeshBuilder() + mb.addArc(max_w, Vector.Unit_Y) + sections = mb.getVertexCount() + mb.addVertex(0, 0, 0) + for n in range(0, sections-1): + mb.addIndices([sections, n + 1, n]) + + for n in range(0, mb.getVertexCount()): + v = mb.getVertex(n) + mb.setVertexUVCoordinates(n, v[0], v[2]) + self._grid_mesh = mb.build() mb = MeshBuilder() @@ -228,19 +266,6 @@ class BuildVolume(SceneNode): ) self._origin_mesh = mb.build() - mb = MeshBuilder() - mb.addQuad( - Vector(min_w, min_h - 0.2, min_d), - Vector(max_w, min_h - 0.2, min_d), - Vector(max_w, min_h - 0.2, max_d), - Vector(min_w, min_h - 0.2, max_d) - ) - - for n in range(0, 6): - v = mb.getVertex(n) - mb.setVertexUVCoordinates(n, v[0], v[2]) - self._grid_mesh = mb.build() - disallowed_area_height = 0.1 disallowed_area_size = 0 if self._disallowed_areas: @@ -353,6 +378,7 @@ class BuildVolume(SceneNode): self._height = self._global_container_stack.getProperty("machine_height", "value") self._build_volume_message.hide() self._depth = self._global_container_stack.getProperty("machine_depth", "value") + self._shape = self._global_container_stack.getProperty("machine_shape", "value") self._updateDisallowedAreas() self._updateRaftThickness() From 70bc8d88894a31a46140c4dd8cf964480925a3ad Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 28 Nov 2016 22:15:47 +0100 Subject: [PATCH 13/38] Fix z-fighting --- cura/BuildVolume.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 8ff241e5ff..3c40fbe1ef 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -219,14 +219,14 @@ class BuildVolume(SceneNode): # Bottom and top 'ellipse' of the build volume mb = MeshBuilder() mb.addArc(max_w, Vector.Unit_Y, center = (0, min_h - 0.2, 0), color = self.VolumeOutlineColor) - mb.addArc(max_w, Vector.Unit_Y, center = (0, max_h, 0), color = self.VolumeOutlineColor) + mb.addArc(max_w, Vector.Unit_Y, center = (0, max_h, 0), color = self.VolumeOutlineColor) self.setMeshData(mb.build()) # Build plate grid mesh mb = MeshBuilder() - mb.addArc(max_w, Vector.Unit_Y) + mb.addArc(max_w, Vector.Unit_Y, center = Vector(0, min_h - 0.2, 0)) sections = mb.getVertexCount() - mb.addVertex(0, 0, 0) + mb.addVertex(0, min_h - 0.2, 0) for n in range(0, sections-1): mb.addIndices([sections, n + 1, n]) From 31ca80d4078e0931f93b7a240bba8fd984e53d4e Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 28 Nov 2016 22:55:22 +0100 Subject: [PATCH 14/38] Create disallowed areas for polar printers --- cura/BuildVolume.py | 101 ++++++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 28 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 3c40fbe1ef..3ffa4a2a70 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -22,6 +22,7 @@ catalog = i18nCatalog("cura") import numpy import copy +import math import UM.Settings.ContainerRegistry @@ -607,34 +608,78 @@ class BuildVolume(SceneNode): bottom_unreachable_border = max(bottom_unreachable_border, other_offset_y - offset_y) half_machine_width = self._global_container_stack.getProperty("machine_width", "value") / 2 half_machine_depth = self._global_container_stack.getProperty("machine_depth", "value") / 2 - if border_size - left_unreachable_border > 0: - result[extruder_id].append(Polygon(numpy.array([ - [-half_machine_width, -half_machine_depth], - [-half_machine_width, half_machine_depth], - [-half_machine_width + border_size - left_unreachable_border, half_machine_depth - border_size - bottom_unreachable_border], - [-half_machine_width + border_size - left_unreachable_border, -half_machine_depth + border_size - top_unreachable_border] - ], numpy.float32))) - if border_size + right_unreachable_border > 0: - result[extruder_id].append(Polygon(numpy.array([ - [half_machine_width, half_machine_depth], - [half_machine_width, -half_machine_depth], - [half_machine_width - border_size - right_unreachable_border, -half_machine_depth + border_size - top_unreachable_border], - [half_machine_width - border_size - right_unreachable_border, half_machine_depth - border_size - bottom_unreachable_border] - ], numpy.float32))) - if border_size + bottom_unreachable_border > 0: - result[extruder_id].append(Polygon(numpy.array([ - [-half_machine_width, half_machine_depth], - [half_machine_width, half_machine_depth], - [half_machine_width - border_size - right_unreachable_border, half_machine_depth - border_size - bottom_unreachable_border], - [-half_machine_width + border_size - left_unreachable_border, half_machine_depth - border_size - bottom_unreachable_border] - ], numpy.float32))) - if border_size - top_unreachable_border > 0: - result[extruder_id].append(Polygon(numpy.array([ - [half_machine_width, -half_machine_depth], - [-half_machine_width, -half_machine_depth], - [-half_machine_width + border_size - left_unreachable_border, -half_machine_depth + border_size - top_unreachable_border], - [half_machine_width - border_size - right_unreachable_border, -half_machine_depth + border_size - top_unreachable_border] - ], numpy.float32))) + if self._shape.lower() != "elliptic": + if border_size - left_unreachable_border > 0: + result[extruder_id].append(Polygon(numpy.array([ + [-half_machine_width, -half_machine_depth], + [-half_machine_width, half_machine_depth], + [-half_machine_width + border_size - left_unreachable_border, half_machine_depth - border_size - bottom_unreachable_border], + [-half_machine_width + border_size - left_unreachable_border, -half_machine_depth + border_size - top_unreachable_border] + ], numpy.float32))) + if border_size + right_unreachable_border > 0: + result[extruder_id].append(Polygon(numpy.array([ + [half_machine_width, half_machine_depth], + [half_machine_width, -half_machine_depth], + [half_machine_width - border_size - right_unreachable_border, -half_machine_depth + border_size - top_unreachable_border], + [half_machine_width - border_size - right_unreachable_border, half_machine_depth - border_size - bottom_unreachable_border] + ], numpy.float32))) + if border_size + bottom_unreachable_border > 0: + result[extruder_id].append(Polygon(numpy.array([ + [-half_machine_width, half_machine_depth], + [half_machine_width, half_machine_depth], + [half_machine_width - border_size - right_unreachable_border, half_machine_depth - border_size - bottom_unreachable_border], + [-half_machine_width + border_size - left_unreachable_border, half_machine_depth - border_size - bottom_unreachable_border] + ], numpy.float32))) + if border_size - top_unreachable_border > 0: + result[extruder_id].append(Polygon(numpy.array([ + [half_machine_width, -half_machine_depth], + [-half_machine_width, -half_machine_depth], + [-half_machine_width + border_size - left_unreachable_border, -half_machine_depth + border_size - top_unreachable_border], + [half_machine_width - border_size - right_unreachable_border, -half_machine_depth + border_size - top_unreachable_border] + ], numpy.float32))) + else: + sections = 32 + arc_vertex = [0, half_machine_depth - border_size] + for i in range(0, sections): + quadrant = math.floor(4 * i / sections) + vertices = [] + if quadrant == 0: + vertices.append([-half_machine_width, half_machine_depth]) + elif quadrant == 1: + vertices.append([-half_machine_width, -half_machine_depth]) + elif quadrant == 2: + vertices.append([half_machine_width, -half_machine_depth]) + elif quadrant == 3: + vertices.append([half_machine_width, half_machine_depth]) + vertices.append(arc_vertex) + + angle = 2 * math.pi * (i + 1) / sections + arc_vertex = [-(half_machine_width - border_size) * math.sin(angle), (half_machine_depth - border_size) * math.cos(angle)] + vertices.append(arc_vertex) + + result[extruder_id].append(Polygon(numpy.array(vertices, numpy.float32))) + + if border_size > 0: + result[extruder_id].append(Polygon(numpy.array([ + [-half_machine_width, -half_machine_depth], + [-half_machine_width, half_machine_depth], + [-half_machine_width + border_size, 0] + ], numpy.float32))) + result[extruder_id].append(Polygon(numpy.array([ + [-half_machine_width, half_machine_depth], + [ half_machine_width, half_machine_depth], + [ 0, half_machine_depth - border_size] + ], numpy.float32))) + result[extruder_id].append(Polygon(numpy.array([ + [ half_machine_width, half_machine_depth], + [ half_machine_width, -half_machine_depth], + [ half_machine_width - border_size, 0] + ], numpy.float32))) + result[extruder_id].append(Polygon(numpy.array([ + [ half_machine_width,-half_machine_depth], + [-half_machine_width,-half_machine_depth], + [ 0, -half_machine_depth + border_size] + ], numpy.float32))) return result From 8651a9a9023620b7f62ca80c6f105b7df6ec647b Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 29 Nov 2016 00:17:56 +0100 Subject: [PATCH 15/38] Force update when changing origin --- plugins/MachineSettingsAction/MachineSettingsAction.qml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.qml b/plugins/MachineSettingsAction/MachineSettingsAction.qml index e52b912459..a0815b9f2c 100644 --- a/plugins/MachineSettingsAction/MachineSettingsAction.qml +++ b/plugins/MachineSettingsAction/MachineSettingsAction.qml @@ -145,7 +145,11 @@ Cura.MachineAction id: centerIsZeroCheckBox text: catalog.i18nc("@option:check", "Machine Center is Zero") checked: String(machineCenterIsZeroProvider.properties.value).toLowerCase() != 'false' - onClicked: machineCenterIsZeroProvider.setPropertyValue("value", checked) + onClicked: + { + machineCenterIsZeroProvider.setPropertyValue("value", checked); + manager.forceUpdate(); + } } CheckBox { From 4756168178dfb2222a722abc51d2b500cfec22dd Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 29 Nov 2016 10:04:53 +0100 Subject: [PATCH 16/38] Fix elliptic bedshapes (vs circular) MeshBuilder.addArc only supports circular arcs, not elliptic arcs. To work around this, the resulting MeshData is scaled. --- cura/BuildVolume.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 3ffa4a2a70..ce379d35fe 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -10,6 +10,7 @@ from UM.Application import Application from UM.Resources import Resources from UM.Mesh.MeshBuilder import MeshBuilder from UM.Math.Vector import Vector +from UM.Math.Matrix import Matrix from UM.Math.Color import Color from UM.Math.AxisAlignedBox import AxisAlignedBox from UM.Math.Polygon import Polygon @@ -218,10 +219,16 @@ class BuildVolume(SceneNode): else: # Bottom and top 'ellipse' of the build volume + aspect = 1.0 + scale_matrix = Matrix() + if self._width != 0: + # Scale circular meshes by aspect ratio if width != height + aspect = self._height / self._width + scale_matrix.compose(Vector(1, 1, aspect)) mb = MeshBuilder() mb.addArc(max_w, Vector.Unit_Y, center = (0, min_h - 0.2, 0), color = self.VolumeOutlineColor) mb.addArc(max_w, Vector.Unit_Y, center = (0, max_h, 0), color = self.VolumeOutlineColor) - self.setMeshData(mb.build()) + self.setMeshData(mb.build().getTransformed(scale_matrix)) # Build plate grid mesh mb = MeshBuilder() @@ -233,10 +240,8 @@ class BuildVolume(SceneNode): for n in range(0, mb.getVertexCount()): v = mb.getVertex(n) - mb.setVertexUVCoordinates(n, v[0], v[2]) - self._grid_mesh = mb.build() - - mb = MeshBuilder() + mb.setVertexUVCoordinates(n, v[0], v[2] * aspect) + self._grid_mesh = mb.build().getTransformed(scale_matrix) # Indication of the machine origin if self._global_container_stack.getProperty("machine_center_is_zero", "value"): @@ -244,6 +249,7 @@ class BuildVolume(SceneNode): else: origin = Vector(min_w, min_h, max_d) + mb = MeshBuilder() mb.addCube( width = self._origin_line_length, height = self._origin_line_width, From dc33d96e8ca16c6210ca0cfb867169ec5e67ba40 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 29 Nov 2016 10:42:24 +0100 Subject: [PATCH 17/38] Make build plate shapes translatable --- cura/BuildVolume.py | 5 +++-- .../MachineSettingsAction.qml | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index ce379d35fe..f63abf9713 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -183,7 +183,7 @@ class BuildVolume(SceneNode): min_d = -self._depth / 2 max_d = self._depth / 2 - if self._shape.lower() != "elliptic": + if self._shape != "elliptic": # Outline 'cube' of the build volume mb = MeshBuilder() mb.addLine(Vector(min_w, min_h, min_d), Vector(max_w, min_h, min_d), color = self.VolumeOutlineColor) @@ -614,7 +614,8 @@ class BuildVolume(SceneNode): bottom_unreachable_border = max(bottom_unreachable_border, other_offset_y - offset_y) half_machine_width = self._global_container_stack.getProperty("machine_width", "value") / 2 half_machine_depth = self._global_container_stack.getProperty("machine_depth", "value") / 2 - if self._shape.lower() != "elliptic": + + if self._shape != "elliptic": if border_size - left_unreachable_border > 0: result[extruder_id].append(Polygon(numpy.array([ [-half_machine_width, -half_machine_depth], diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.qml b/plugins/MachineSettingsAction/MachineSettingsAction.qml index a0815b9f2c..a2a8425b22 100644 --- a/plugins/MachineSettingsAction/MachineSettingsAction.qml +++ b/plugins/MachineSettingsAction/MachineSettingsAction.qml @@ -131,11 +131,20 @@ Cura.MachineAction ComboBox { - model: ["Rectangular", "Elliptic"] - currentIndex: machineShapeProvider.properties.value.toLowerCase() != model[1].toLowerCase() ? 0 : 1 + id: shapeComboBox + model: ListModel + { + id: shapesModel + Component.onCompleted: + { + shapesModel.append({ text: catalog.i18nc("@option:build plate shape", "Rectangular"), value: "rectangular" }); + shapesModel.append({ text: catalog.i18nc("@option:build plate shape", "Elliptic"), value: "elliptic" }); + shapeComboBox.currentIndex = machineShapeProvider.properties.value != shapesModel.get(1).value ? 0 : 1 + } + } onActivated: { - machineShapeProvider.setPropertyValue("value", model[index]); + machineShapeProvider.setPropertyValue("value", shapesModel.get(index).value); manager.forceUpdate(); } } From ff0f63eb9481e768355da4661daf62955c966b6f Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 29 Nov 2016 10:44:10 +0100 Subject: [PATCH 18/38] Document z fighting hack --- cura/BuildVolume.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index f63abf9713..d7ca937009 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -183,6 +183,8 @@ class BuildVolume(SceneNode): min_d = -self._depth / 2 max_d = self._depth / 2 + z_fight_distance = 0.2 # Distance between buildplate and disallowed area meshes to prevent z-fighting + if self._shape != "elliptic": # Outline 'cube' of the build volume mb = MeshBuilder() @@ -206,10 +208,10 @@ class BuildVolume(SceneNode): # Build plate grid mesh mb = MeshBuilder() mb.addQuad( - Vector(min_w, min_h - 0.2, min_d), - Vector(max_w, min_h - 0.2, min_d), - Vector(max_w, min_h - 0.2, max_d), - Vector(min_w, min_h - 0.2, max_d) + Vector(min_w, min_h - z_fight_distance, min_d), + Vector(max_w, min_h - z_fight_distance, min_d), + Vector(max_w, min_h - z_fight_distance, max_d), + Vector(min_w, min_h - z_fight_distance, max_d) ) for n in range(0, 6): @@ -226,15 +228,15 @@ class BuildVolume(SceneNode): aspect = self._height / self._width scale_matrix.compose(Vector(1, 1, aspect)) mb = MeshBuilder() - mb.addArc(max_w, Vector.Unit_Y, center = (0, min_h - 0.2, 0), color = self.VolumeOutlineColor) + mb.addArc(max_w, Vector.Unit_Y, center = (0, min_h - z_fight_distance, 0), color = self.VolumeOutlineColor) mb.addArc(max_w, Vector.Unit_Y, center = (0, max_h, 0), color = self.VolumeOutlineColor) self.setMeshData(mb.build().getTransformed(scale_matrix)) # Build plate grid mesh mb = MeshBuilder() - mb.addArc(max_w, Vector.Unit_Y, center = Vector(0, min_h - 0.2, 0)) + mb.addArc(max_w, Vector.Unit_Y, center = Vector(0, min_h - z_fight_distance, 0)) sections = mb.getVertexCount() - mb.addVertex(0, min_h - 0.2, 0) + mb.addVertex(0, min_h - z_fight_distance, 0) for n in range(0, sections-1): mb.addIndices([sections, n + 1, n]) From 86383b2be0842204fecf263ee3f8d75ba6142abb Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 29 Nov 2016 10:54:48 +0100 Subject: [PATCH 19/38] Get build plate shape options from the fdmprinter definition --- .../MachineSettingsAction.qml | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.qml b/plugins/MachineSettingsAction/MachineSettingsAction.qml index a2a8425b22..26bbccd44a 100644 --- a/plugins/MachineSettingsAction/MachineSettingsAction.qml +++ b/plugins/MachineSettingsAction/MachineSettingsAction.qml @@ -137,11 +137,32 @@ Cura.MachineAction id: shapesModel Component.onCompleted: { - shapesModel.append({ text: catalog.i18nc("@option:build plate shape", "Rectangular"), value: "rectangular" }); - shapesModel.append({ text: catalog.i18nc("@option:build plate shape", "Elliptic"), value: "elliptic" }); - shapeComboBox.currentIndex = machineShapeProvider.properties.value != shapesModel.get(1).value ? 0 : 1 + // Options come in as a string-representation of an OrderedDict + var options = machineShapeProvider.properties.options.match(/^OrderedDict\(\[\((.*)\)\]\)$/); + if(options) + { + options = options[1].split("), (") + for(var i = 0; i < options.length; i++) + { + var option = options[i].substring(1, options[i].length - 1).split("', '") + shapesModel.append({text: option[1], value: option[0]}); + } + } } } + currentIndex: + { + var currentValue = machineShapeProvider.properties.value; + var index = 0; + for(var i = 0; i < shapesModel.count; i++) + { + if(shapesModel.get(i).value == currentValue) { + index = i; + break; + } + } + return index + } onActivated: { machineShapeProvider.setPropertyValue("value", shapesModel.get(index).value); @@ -467,7 +488,7 @@ Cura.MachineAction containerStackId: Cura.MachineManager.activeMachineId key: "machine_shape" - watchedProperties: [ "value" ] + watchedProperties: [ "value", "options" ] storeIndex: manager.containerIndex } From 68fd0814e55051540430eab1337a0d98c95a0caf Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 29 Nov 2016 12:33:35 +0100 Subject: [PATCH 20/38] Minor code-style-related fixes --- cura/BuildVolume.py | 2 +- resources/definitions/fdmprinter.def.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index d7ca937009..ed3e77ec2a 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -226,7 +226,7 @@ class BuildVolume(SceneNode): if self._width != 0: # Scale circular meshes by aspect ratio if width != height aspect = self._height / self._width - scale_matrix.compose(Vector(1, 1, aspect)) + scale_matrix.compose(scale = Vector(1, 1, aspect)) mb = MeshBuilder() mb.addArc(max_w, Vector.Unit_Y, center = (0, min_h - z_fight_distance, 0), color = self.VolumeOutlineColor) mb.addArc(max_w, Vector.Unit_Y, center = (0, max_h, 0), color = self.VolumeOutlineColor) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index b18971dda8..0835167775 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -141,7 +141,7 @@ { "label": "Build plate shape", "description": "The shape of the build plate without taking unprintable areas into account.", - "default_value": "Rectangular", + "default_value": "rectangular", "type": "enum", "options": { From 7082ff7d68893c3d3df9b4bd27db7ea4d9f9d042 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 29 Nov 2016 13:11:27 +0100 Subject: [PATCH 21/38] Don't hide the dual extrusion category for single extrusion The category gets hidden automatically if all of its child settings are disabled. --- resources/definitions/fdmprinter.def.json | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 2d77d62670..28b5b6c854 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3616,7 +3616,6 @@ "type": "category", "icon": "category_dual", "description": "Settings used for printing with multiple extruders.", - "enabled": "machine_extruder_count > 1", "children": { "prime_tower_enable": From f7ebed945e448dad21b7349239d32ba3790849a2 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 29 Nov 2016 14:25:53 +0100 Subject: [PATCH 22/38] Fix creation of indices on elliptic build plate --- cura/BuildVolume.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index ed3e77ec2a..8263355dda 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -234,11 +234,14 @@ class BuildVolume(SceneNode): # Build plate grid mesh mb = MeshBuilder() - mb.addArc(max_w, Vector.Unit_Y, center = Vector(0, min_h - z_fight_distance, 0)) - sections = mb.getVertexCount() mb.addVertex(0, min_h - z_fight_distance, 0) - for n in range(0, sections-1): - mb.addIndices([sections, n + 1, n]) + mb.addArc(max_w, Vector.Unit_Y, center = Vector(0, min_h - z_fight_distance, 0)) + sections = mb.getVertexCount() - 1 # Center point is not an arc section + indices = [] + for n in range(0, sections - 1): + indices.append([0, n + 2, n + 1]) + mb.addIndices(numpy.asarray(indices, dtype = numpy.int32)) + mb.calculateNormals() for n in range(0, mb.getVertexCount()): v = mb.getVertex(n) From b9dd2ef6f91f3a1cc5940dadbce25484df4baed3 Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Tue, 29 Nov 2016 15:13:10 +0100 Subject: [PATCH 23/38] Numpy magic to speed up the expansion of indices-to-vectors to just vectors. CURA-2548 Sending models to engine that have indices is slow --- plugins/CuraEngineBackend/StartSliceJob.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 0319186518..dc9c4c2e06 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -163,22 +163,17 @@ class StartSliceJob(Job): obj.id = id(object) verts = mesh_data.getVertices() indices = mesh_data.getIndices() + if indices is not None: - #TODO: This is a very slow way of doing it! It also locks up the GUI. - flat_vert_list = [] - for face in indices: - for vert_index in face: - flat_vert_list.append(verts[vert_index]) - Job.yieldThread() - verts = numpy.array(flat_vert_list) + flat_verts = numpy.take(verts, indices.flatten(), axis=0) else: - verts = numpy.array(verts) + flat_verts = numpy.array(verts) # Convert from Y up axes to Z up axes. Equals a 90 degree rotation. - verts[:, [1, 2]] = verts[:, [2, 1]] - verts[:, 1] *= -1 + flat_verts[:, [1, 2]] = flat_verts[:, [2, 1]] + flat_verts[:, 1] *= -1 - obj.vertices = verts + obj.vertices = flat_verts self._handlePerObjectSettings(object, obj) From 91e8ac6868762595a73363230234d223c1270753 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 29 Nov 2016 17:20:10 +0100 Subject: [PATCH 24/38] Allow postprocessing before sending data to the printer From OutputDevice.py: "output device subclasses are completely free to implement writing however they want, though you should emit writeStarted and related signals whenever certain events happen related to the write process." --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 20552a6843..19692492e4 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -532,6 +532,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): Application.getInstance().showPrintMonitor.emit(True) self._print_finished = True + self.writeStarted.emit(self) self._gcode = getattr(Application.getInstance().getController().getScene(), "gcode_list") print_information = Application.getInstance().getPrintInformation() From df7d685ef7020200dbbf573c8179dd25b738fea7 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 29 Nov 2016 17:49:54 +0100 Subject: [PATCH 25/38] Add link to OctoPrintPlugin --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 077e6d1ab7..0ab3de61a4 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ Third party plugins * [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. * [Auto orientation](https://github.com/nallath/CuraOrientationPlugin): Calculate the optimal orientation for a model. +* [OctoPrint Plugin](https://github.com/fieldofview/OctoPrintPlugin): Send printjobs directly to OctoPrint and monitor their progress in Cura. Making profiles for other printers ---------------------------------- From 50a61e56f79ec6eef4e5f1250d847cc7212f85a5 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Tue, 29 Nov 2016 17:40:17 +0100 Subject: [PATCH 26/38] JSON refactor: Dual Extrusion Overlap => Merged Objects Overlap (CURA-2444) --- 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 c848d03ad5..6a991632a6 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3770,8 +3770,8 @@ }, "multiple_mesh_overlap": { - "label": "Dual Extrusion Overlap", - "description": "Make the models printed with different extruder trains overlap a bit. This makes the different materials bond together better.", + "label": "Merged Objects Overlap", + "description": "Make models which are placed directly close to each other overlap a bit. This makes them bond together better.", "type": "float", "unit": "mm", "default_value": 0.15, From 32a102a9e7968480f9fb75773c32dd4424a55a04 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Tue, 29 Nov 2016 17:41:57 +0100 Subject: [PATCH 27/38] JSON refactor: move multiple_mesh_overlap to meshfixes category (CURA-2444) --- resources/definitions/fdmprinter.def.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 6a991632a6..e4911064d4 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3768,17 +3768,6 @@ "settable_per_mesh": false, "settable_per_extruder": true }, - "multiple_mesh_overlap": - { - "label": "Merged Objects Overlap", - "description": "Make models which are placed directly close to each other overlap a bit. This makes them bond together better.", - "type": "float", - "unit": "mm", - "default_value": 0.15, - "minimum_value": "0", - "maximum_value_warning": "1.0", - "settable_per_mesh": true - }, "ooze_shield_enabled": { "label": "Enable Ooze Shield", @@ -3859,6 +3848,17 @@ "default_value": false, "settable_per_mesh": true }, + "multiple_mesh_overlap": + { + "label": "Merged Objects Overlap", + "description": "Make models which are placed directly close to each other overlap a bit. This makes them bond together better.", + "type": "float", + "unit": "mm", + "default_value": 0.15, + "minimum_value": "0", + "maximum_value_warning": "1.0", + "settable_per_mesh": true + }, "carve_multiple_volumes": { "label": "Remove Mesh Intersection", From 383eba9930c81ec123954fba783c052675f4d13b Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Tue, 29 Nov 2016 17:45:35 +0100 Subject: [PATCH 28/38] JSON refactor: multiple_mesh_overlap: Objects ==> Meshes (CURA-2444) --- 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 e4911064d4..23dc454d30 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3850,8 +3850,8 @@ }, "multiple_mesh_overlap": { - "label": "Merged Objects Overlap", - "description": "Make models which are placed directly close to each other overlap a bit. This makes them bond together better.", + "label": "Merged Meshes Overlap", + "description": "Make meshes which are placed directly close to each other overlap a bit. This makes them bond together better.", "type": "float", "unit": "mm", "default_value": 0.15, From e60f05c2fd44ef80c4726c3479292487ddf585ae Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Tue, 29 Nov 2016 17:54:01 +0100 Subject: [PATCH 29/38] JSON fix: limit_to_extruder for support_conical_enabled (CURA-2896) --- 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 23dc454d30..44552a934a 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -4132,6 +4132,7 @@ "type": "bool", "default_value": false, "enabled": "support_enable", + "limit_to_extruder": "support_infill_extruder_nr", "settable_per_mesh": true }, "support_conical_angle": From 09e884fd921b566b542d7cf0e693246dccc4bf85 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Wed, 30 Nov 2016 10:27:10 +0100 Subject: [PATCH 30/38] JSON refactor: moved Initial Fan Speed out of the children of Fan Speed (CURA-3068) we don't want it to inherit from Fan Speed, but children must always inherit from their parent. --- resources/definitions/fdmprinter.def.json | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 5c768b4edd..2c3b7762e8 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -2476,20 +2476,6 @@ "settable_per_extruder": true, "children": { - "cool_fan_speed_0": - { - "label": "Initial Fan Speed", - "description": "The speed at which the fans spin at the start of the print. In subsequent layers the fan speed is gradually increased up to the layer corresponding to Regular Fan Speed at Height.", - "unit": "%", - "type": "float", - "minimum_value": "0", - "maximum_value": "100", - "value": "cool_fan_speed", - "default_value": 100, - "enabled": "cool_fan_enabled", - "settable_per_mesh": false, - "settable_per_extruder": true - }, "cool_fan_speed_min": { "label": "Regular Fan Speed", @@ -2532,6 +2518,20 @@ "settable_per_mesh": false, "settable_per_extruder": true }, + "cool_fan_speed_0": + { + "label": "Initial Fan Speed", + "description": "The speed at which the fans spin at the start of the print. In subsequent layers the fan speed is gradually increased up to the layer corresponding to Regular Fan Speed at Height.", + "unit": "%", + "type": "float", + "minimum_value": "0", + "maximum_value": "100", + "value": "cool_fan_speed", + "default_value": 100, + "enabled": "cool_fan_enabled", + "settable_per_mesh": false, + "settable_per_extruder": true + }, "cool_fan_full_at_height": { "label": "Regular Fan Speed at Height", From b8ff7acb688815ac06885051b1514145b797dcdd Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Wed, 30 Nov 2016 10:27:47 +0100 Subject: [PATCH 31/38] JSON fix: initial fan speed zero by default (CURA-3068) --- resources/definitions/fdmprinter.def.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 2c3b7762e8..8d5fdba9ae 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -2526,8 +2526,7 @@ "type": "float", "minimum_value": "0", "maximum_value": "100", - "value": "cool_fan_speed", - "default_value": 100, + "default_value": 0, "enabled": "cool_fan_enabled", "settable_per_mesh": false, "settable_per_extruder": true From dcdfe612e739fbb2a6937eb3eee6d6f2401f6a19 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 30 Nov 2016 12:04:30 +0100 Subject: [PATCH 32/38] Added more robust fault handling for preferences while loading workspace CURA-1263 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index e1f0173235..27993a4a47 100644 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -144,8 +144,19 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Copy a number of settings from the temp preferences to the global global_preferences = Preferences.getInstance() - global_preferences.setValue("general/visible_settings", temp_preferences.getValue("general/visible_settings")) - global_preferences.setValue("cura/categories_expanded", temp_preferences.getValue("cura/categories_expanded")) + + visible_settings = temp_preferences.getValue("general/visible_settings") + if visible_settings is None: + Logger.log("w", "Workspace did not contain visible settings. Leaving visibility unchanged") + else: + global_preferences.setValue("general/visible_settings", visible_settings) + + categories_expanded = temp_preferences.getValue("cura/categories_expanded") + if categories_expanded is None: + Logger.log("w", "Workspace did not contain expanded categories. Leaving them unchanged") + else: + global_preferences.setValue("cura/categories_expanded", categories_expanded) + Application.getInstance().expandedCategoriesChanged.emit() # Notify the GUI of the change self._id_mapping = {} From 61db5b42b7105fa5fc375b5c09e3811c928d7f24 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 30 Nov 2016 12:57:10 +0100 Subject: [PATCH 33/38] Moved loading of meshdata in workspace to after machine has changed This fixes the issue where the location of the objects was not correct. CURA-1263 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 27993a4a47..f5d7466ad4 100644 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -128,11 +128,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader): return WorkspaceReader.PreReadResult.accepted def read(self, file_name): - # Load all the nodes / meshdata of the workspace - nodes = self._3mf_mesh_reader.read(file_name) - if nodes is None: - nodes = [] - archive = zipfile.ZipFile(file_name, "r") cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")] @@ -399,6 +394,11 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Actually change the active machine. Application.getInstance().setGlobalContainerStack(global_stack) + + # Load all the nodes / meshdata of the workspace + nodes = self._3mf_mesh_reader.read(file_name) + if nodes is None: + nodes = [] return nodes def _stripFileToId(self, file): From 86019c2df0e17b5a31786f6d7cfcde3c4f5e20b9 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 30 Nov 2016 12:59:09 +0100 Subject: [PATCH 34/38] Renamed load&save workspace to import&export project CURA-1263 --- resources/qml/Actions.qml | 2 +- resources/qml/Cura.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index bb4e28eae7..be8a7b8c49 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -290,7 +290,7 @@ Item Action { id: loadWorkspaceAction - text: catalog.i18nc("@action:inmenu menubar:file","&Open Workspace..."); + text: catalog.i18nc("@action:inmenu menubar:file","&Import project..."); } Action diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 85be3342e9..a5240b5726 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -110,7 +110,7 @@ UM.MainWindow MenuItem { id: saveWorkspaceMenu - text: catalog.i18nc("@title:menu menubar:file","Save Workspace") + text: catalog.i18nc("@title:menu menubar:file","Import project") onTriggered: UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, { "filter_by_machine": false, "file_type": "workspace" }); } From d08c1b73bf0f8824a996e310481a08f03d45ecae Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 30 Nov 2016 13:13:47 +0100 Subject: [PATCH 35/38] Fixed export profile derp CURA-1263 --- resources/qml/Cura.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index a5240b5726..5b5e71b07b 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -110,7 +110,7 @@ UM.MainWindow MenuItem { id: saveWorkspaceMenu - text: catalog.i18nc("@title:menu menubar:file","Import project") + text: catalog.i18nc("@title:menu menubar:file","Export project") onTriggered: UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, { "filter_by_machine": false, "file_type": "workspace" }); } From e941d417f1fd570ed836d05b5816cf3e588e94b5 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 30 Nov 2016 14:15:19 +0100 Subject: [PATCH 36/38] Added CuraVersion to 3mf metadata --- plugins/3MFWriter/ThreeMFWriter.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index d86b119276..882740c4ed 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -5,7 +5,7 @@ from UM.Mesh.MeshWriter import MeshWriter from UM.Math.Vector import Vector from UM.Logger import Logger from UM.Math.Matrix import Matrix -from UM.Settings.SettingRelation import RelationType +from UM.Application import Application try: import xml.etree.cElementTree as ET @@ -78,6 +78,12 @@ class ThreeMFWriter(MeshWriter): model_relation_element = ET.SubElement(relations_element, "Relationship", Target = "/3D/3dmodel.model", Id = "rel0", Type = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel") model = ET.Element("model", unit = "millimeter", xmlns = self._namespaces["3mf"]) + + # Add the version of Cura this was created with. As "CuraVersion" is not a recognised metadata name + # by 3mf itself, we place it in our own namespace. + version_metadata = ET.SubElement(model, "metadata", xmlns = self._namespaces["cura"], name = "CuraVersion") + version_metadata.text = Application.getInstance().getVersion() + resources = ET.SubElement(model, "resources") build = ET.SubElement(model, "build") From 8da058d95d8d24ec2991f2efd64c73b00a11860b Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Wed, 30 Nov 2016 16:25:40 +0100 Subject: [PATCH 37/38] JSON fix: description of z_seam_type still mentioned 'Back' (CURA-1461) --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index d2bcbe0d9c..4abb9e547d 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -946,7 +946,7 @@ "z_seam_type": { "label": "Z Seam Alignment", - "description": "Starting point of each path in a layer. When paths in consecutive layers start at the same point a vertical seam may show on the print. When aligning these at the back, the seam is easiest to remove. When placed randomly the inaccuracies at the paths' start will be less noticeable. When taking the shortest path the print will be quicker.", + "description": "Starting point of each path in a layer. When paths in consecutive layers start at the same point a vertical seam may show on the print. When aligning these near a user specified location, the seam is easiest to remove. When placed randomly the inaccuracies at the paths' start will be less noticeable. When taking the shortest path the print will be quicker.", "type": "enum", "options": { From 1305b518061508adafcce7252cf2f22eb0c18875 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Wed, 30 Nov 2016 16:28:26 +0100 Subject: [PATCH 38/38] JSON fix: multiple_mesh_overlap description was clumsy (CURA-2444) --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 8d5fdba9ae..4a424f807d 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3865,7 +3865,7 @@ "multiple_mesh_overlap": { "label": "Merged Meshes Overlap", - "description": "Make meshes which are placed directly close to each other overlap a bit. This makes them bond together better.", + "description": "Make meshes which are touching each other overlap a bit. This makes them bond together better.", "type": "float", "unit": "mm", "default_value": 0.15,