From dc9813b916c198dbce477f1a7799233eba0e9f01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Garc=C3=ADa?= Date: Sat, 26 May 2018 01:56:57 +0200 Subject: [PATCH 001/243] Fix for detecting Malyan M200 and Monoprice Mini --- plugins/USBPrinting/AutoDetectBaudJob.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/USBPrinting/AutoDetectBaudJob.py b/plugins/USBPrinting/AutoDetectBaudJob.py index 50bb831ba8..6d30615eb4 100644 --- a/plugins/USBPrinting/AutoDetectBaudJob.py +++ b/plugins/USBPrinting/AutoDetectBaudJob.py @@ -58,7 +58,7 @@ class AutoDetectBaudJob(Job): while timeout_time > time(): line = serial.readline() - if b"ok T:" in line: + if b"ok " in line and b"T:" in line: successful_responses += 1 if successful_responses >= 3: self.setResult(baud_rate) From 4bd87e2164489209e242c127e68f446dcbe10589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Garc=C3=ADa?= Date: Sat, 26 May 2018 13:15:36 +0200 Subject: [PATCH 002/243] Fix for showing temperatures for Malyan M200 and Monoprice Mini --- plugins/USBPrinting/USBPrinterOutputDevice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index 00eb2f0b25..fe6a12623b 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -305,7 +305,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice): if self._firmware_name is None: self.sendCommand("M115") - if b"ok T:" in line or line.startswith(b"T:") or b"ok B:" in line or line.startswith(b"B:"): # Temperature message. 'T:' for extruder and 'B:' for bed + if (b"ok " in line and b"T:" in line) or b"ok T:" in line or line.startswith(b"T:") or b"ok B:" in line or line.startswith(b"B:"): # Temperature message. 'T:' for extruder and 'B:' for bed extruder_temperature_matches = re.findall(b"T(\d*): ?([\d\.]+) ?\/?([\d\.]+)?", line) # Update all temperature values matched_extruder_nrs = [] From 23d6f7ba0b7f101a9d27df1cb57956ad6b90a88e Mon Sep 17 00:00:00 2001 From: Orel Date: Tue, 5 Jun 2018 17:36:44 +0200 Subject: [PATCH 003/243] Enhance Dagoma printers profiles and add printer-specific quality profiles. --- .../definitions/dagoma_discoeasy200.def.json | 25 ++++-- resources/definitions/dagoma_neva.def.json | 26 ++++-- .../definitions/dagoma_neva_magis.def.json | 81 +++++++++++++++++++ .../dagoma_discoeasy200_pla_fast.inst.cfg | 17 ++++ .../dagoma_discoeasy200_pla_fine.inst.cfg | 14 ++++ .../dagoma_discoeasy200_pla_standard.inst.cfg | 17 ++++ .../dagoma_neva_magis_pla_fast.inst.cfg | 17 ++++ .../dagoma_neva_magis_pla_fine.inst.cfg | 14 ++++ .../dagoma_neva_magis_pla_standard.inst.cfg | 17 ++++ .../dagoma/dagoma_neva_pla_fast.inst.cfg | 17 ++++ .../dagoma/dagoma_neva_pla_fine.inst.cfg | 14 ++++ .../dagoma/dagoma_neva_pla_standard.inst.cfg | 17 ++++ 12 files changed, 263 insertions(+), 13 deletions(-) create mode 100644 resources/definitions/dagoma_neva_magis.def.json create mode 100644 resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg create mode 100644 resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg create mode 100644 resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg create mode 100644 resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg create mode 100644 resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg create mode 100644 resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg create mode 100644 resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg create mode 100644 resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg create mode 100644 resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg diff --git a/resources/definitions/dagoma_discoeasy200.def.json b/resources/definitions/dagoma_discoeasy200.def.json index 4f0fddc41d..9df8829ec5 100644 --- a/resources/definitions/dagoma_discoeasy200.def.json +++ b/resources/definitions/dagoma_discoeasy200.def.json @@ -1,4 +1,5 @@ { + "id": "dagoma_discoeasy200", "name": "Dagoma DiscoEasy200", "version": 2, "inherits": "fdmprinter", @@ -28,17 +29,17 @@ }, "machine_head_with_fans_polygon": { "default_value": [ - [17, 70], - [17, -40], - [-17, -40], - [17, 70] + [-17, -70], + [-17, 40], + [17, 40], + [17, -70] ] }, "gantry_height": { "default_value": 10 }, "machine_start_gcode": { - "default_value": ";Gcode by Cura\nG90\nM106 S250\nG28 X Y\nG1 X50\nM109 S180\nG28\nM104 S{material_print_temperature_layer_0}\nG29\nM107\nG1 X100 Y20 F3000\nG1 Z0.5\nM109 S{material_print_temperature_layer_0}\nM82\nG92 E0\nG1 F200 E10\nG92 E0\nG1 Z3\nG1 F6000\n" + "default_value": ";Gcode by Cura\nG90\nM106 S255\nG28 X Y\nG1 X50\nM109 R90\nG28\nM104 S{material_print_temperature_layer_0}\nG29\nM107\nG1 X100 Y20 F3000\nG1 Z0.5\nM109 S{material_print_temperature_layer_0}\nM82\nG92 E0\nG1 F200 E10\nG92 E0\nG1 Z3\nG1 F6000\n" }, "machine_end_gcode": { "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 F3000\nG90\nG28 X Y\nM107\nM84\n" @@ -46,17 +47,29 @@ "material_diameter": { "default_value": 1.75 }, + "default_material_print_temperature": { + "default_value": 205 + }, "speed_print": { "default_value": 60 }, "speed_travel": { - "value": "100" + "default_value": 100 }, "retraction_amount": { "default_value": 3.5 }, "retraction_speed": { "default_value": 50 + }, + "adhesion_type": { + "default_value": "skirt" + }, + "skirt_line_count": { + "default_value": 2 + }, + "layer_height_0": { + "default_value": 0.26 } } } diff --git a/resources/definitions/dagoma_neva.def.json b/resources/definitions/dagoma_neva.def.json index 21a557ac22..d133ec820c 100644 --- a/resources/definitions/dagoma_neva.def.json +++ b/resources/definitions/dagoma_neva.def.json @@ -1,5 +1,5 @@ { - "id": "Dagoma_neva", + "id": "dagoma_neva", "name": "Dagoma NEVA", "version": 2, "inherits": "fdmprinter", @@ -29,10 +29,10 @@ }, "machine_head_with_fans_polygon": { "default_value": [ - [17, 40], - [17, -70], - [-17, -70], - [17, 40] + [-36, -42], + [-36, 42], + [36, 42], + [36, -42] ] }, "gantry_height": { @@ -42,10 +42,10 @@ "default_value": "elliptic" }, "machine_gcode_flavor": { - "default_value": "RepRap (RepRap)" + "default_value": "RepRap" }, "machine_start_gcode": { - "default_value": ";Gcode by Cura\nG90\nG28\nM109 S100\nG29\nM104 S{material_print_temperature_layer_0}\nG0 X0 Y-85\nG0 Z0.26\nM109 S{material_print_temperature_layer_0}\nM82\nG92 E0\nG1 F200 E6\nG92 E0\nG1 F200 E-3.5\nG0 Z0.15\nG0 X10\nG0 Z3\nG1 F6000\n" + "default_value": ";Gcode by Cura\nG90\nG28\nM107\nM109 R100\nG29\nM109 S{material_print_temperature_layer_0} U-55 X55 V-85 Y-85 W0.26 Z0.26\nM82\nG92 E0\nG1 F200 E6\nG92 E0\nG1 F200 E-3.5\nG0 Z0.15\nG0 X10\nG0 Z3\nG1 F6000\n" }, "machine_end_gcode": { "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 E-2 F9000\nG90\nG28\n" @@ -53,6 +53,9 @@ "material_diameter": { "default_value": 1.75 }, + "default_material_print_temperature": { + "default_value": 205 + }, "speed_print": { "default_value": 40 }, @@ -64,6 +67,15 @@ }, "retraction_speed": { "default_value": 60 + }, + "adhesion_type": { + "default_value": "skirt" + }, + "skirt_line_count": { + "default_value": 2 + }, + "layer_height_0": { + "default_value": 0.26 } } } diff --git a/resources/definitions/dagoma_neva_magis.def.json b/resources/definitions/dagoma_neva_magis.def.json new file mode 100644 index 0000000000..9f599cf85d --- /dev/null +++ b/resources/definitions/dagoma_neva_magis.def.json @@ -0,0 +1,81 @@ +{ + "id": "dagoma_neva_magis", + "name": "Dagoma NEVA", + "version": 2, + "inherits": "fdmprinter", + "metadata": { + "visible": true, + "author": "Dagoma", + "manufacturer": "Dagoma", + "file_formats": "text/x-gcode", + "platform": "neva.stl", + "platform_offset": [ 0, 0, 0] + }, + "overrides": { + "machine_width": { + "default_value": 195.55 + }, + "machine_height": { + "default_value": 205 + }, + "machine_depth": { + "default_value": 195.55 + }, + "machine_center_is_zero": { + "default_value": true + }, + "machine_nozzle_size": { + "default_value": 0.4 + }, + "machine_head_with_fans_polygon": { + "default_value": [ + [-36, -42], + [-36, 42], + [36, 42], + [36, -42] + ] + }, + "gantry_height": { + "default_value": 0 + }, + "machine_shape": { + "default_value": "elliptic" + }, + "machine_gcode_flavor": { + "default_value": "RepRap" + }, + "machine_start_gcode": { + "default_value": ";Gcode by Cura\nG90\nG28\nM107\nM109 R100\nG29\nM109 S{material_print_temperature_layer_0} U-55 X55 V-85 Y-85 W0.26 Z0.26\nM82\nG92 E0\nG1 F200 E6\nG92 E0\nG1 F200 E-3.5\nG0 Z0.15\nG0 X10\nG0 Z3\nG1 F6000\n" + }, + "machine_end_gcode": { + "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 E-2 F9000\nG90\nG28\n" + }, + "material_diameter": { + "default_value": 1.75 + }, + "default_material_print_temperature": { + "default_value": 205 + }, + "speed_print": { + "default_value": 40 + }, + "speed_travel": { + "default_value": 120 + }, + "retraction_amount": { + "default_value": 3.8 + }, + "retraction_speed": { + "default_value": 60 + }, + "adhesion_type": { + "default_value": "skirt" + }, + "skirt_line_count": { + "default_value": 2 + }, + "layer_height_0": { + "default_value": 0.26 + } + } +} diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg new file mode 100644 index 0000000000..6cd88f819c --- /dev/null +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg @@ -0,0 +1,17 @@ +[general] +version = 3 +name = Fast +definition = dagoma_discoeasy200 + +[metadata] +setting_version = 4 +type = quality +quality_type = draft +weight = -2 +material = generic_pla + +[values] +layer_height = 0.2 + +material_print_temperature = =default_material_print_temperature + 10 +material_bed_temperature_layer_0 = =default_material_print_temperature + 10 diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg new file mode 100644 index 0000000000..0f59401dd5 --- /dev/null +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 3 +name = Fine +definition = dagoma_discoeasy200 + +[metadata] +setting_version = 4 +type = quality +quality_type = high +weight = 0 +material = generic_pla + +[values] +layer_height = 0.1 diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg new file mode 100644 index 0000000000..9c1cc19f9e --- /dev/null +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg @@ -0,0 +1,17 @@ +[general] +version = 3 +name = Standard +definition = dagoma_discoeasy200 + +[metadata] +setting_version = 4 +type = quality +quality_type = normal +weight = -1 +material = generic_pla + +[values] +layer_height = 0.15 + +material_print_temperature = =default_material_print_temperature + 5 +material_bed_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg new file mode 100644 index 0000000000..f0f5810e82 --- /dev/null +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg @@ -0,0 +1,17 @@ +[general] +version = 3 +name = Fast +definition = dagoma_neva + +[metadata] +setting_version = 4 +type = quality +quality_type = draft +weight = -2 +material = generic_pla + +[values] +layer_height = 0.2 + +material_print_temperature = =default_material_print_temperature + 10 +material_bed_temperature_layer_0 = =default_material_print_temperature + 10 diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg new file mode 100644 index 0000000000..3dc4ce5627 --- /dev/null +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 3 +name = Fine +definition = dagoma_neva + +[metadata] +setting_version = 4 +type = quality +quality_type = high +weight = 0 +material = generic_pla + +[values] +layer_height = 0.1 diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg new file mode 100644 index 0000000000..ce2157c90b --- /dev/null +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg @@ -0,0 +1,17 @@ +[general] +version = 3 +name = Standard +definition = dagoma_neva + +[metadata] +setting_version = 4 +type = quality +quality_type = normal +weight = -1 +material = generic_pla + +[values] +layer_height = 0.15 + +material_print_temperature = =default_material_print_temperature + 5 +material_bed_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg new file mode 100644 index 0000000000..f0f5810e82 --- /dev/null +++ b/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg @@ -0,0 +1,17 @@ +[general] +version = 3 +name = Fast +definition = dagoma_neva + +[metadata] +setting_version = 4 +type = quality +quality_type = draft +weight = -2 +material = generic_pla + +[values] +layer_height = 0.2 + +material_print_temperature = =default_material_print_temperature + 10 +material_bed_temperature_layer_0 = =default_material_print_temperature + 10 diff --git a/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg new file mode 100644 index 0000000000..3dc4ce5627 --- /dev/null +++ b/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 3 +name = Fine +definition = dagoma_neva + +[metadata] +setting_version = 4 +type = quality +quality_type = high +weight = 0 +material = generic_pla + +[values] +layer_height = 0.1 diff --git a/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg new file mode 100644 index 0000000000..ce2157c90b --- /dev/null +++ b/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg @@ -0,0 +1,17 @@ +[general] +version = 3 +name = Standard +definition = dagoma_neva + +[metadata] +setting_version = 4 +type = quality +quality_type = normal +weight = -1 +material = generic_pla + +[values] +layer_height = 0.15 + +material_print_temperature = =default_material_print_temperature + 5 +material_bed_temperature_layer_0 = =default_material_print_temperature + 5 From 0cf46ca48ecab544c0441808fb916406d750de1e Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Sat, 23 Jun 2018 16:14:50 +0200 Subject: [PATCH 004/243] Changed SettingView to show custom menu items --- resources/qml/Settings/SettingView.qml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 1b3f0cbc20..30160cb5fb 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -561,6 +561,27 @@ Item visible: machineExtruderCount.properties.value > 1 } + Instantiator + { + id: customMenuItems + model: Cura.SidebarCustomMenuItemsModel { } + MenuItem + { + text: model.name + onTriggered: + { + customMenuItems.model.callMenuItemMethod(name, model.actions) + } + } + onObjectAdded: contextMenu.insertItem(index, object) + onObjectRemoved: contextMenu.removeItem(object) + } + + MenuSeparator + { + visible: customMenuItems.count > 0 + } + MenuItem { //: Settings context menu action From 0906e3f1e79d74736b96cd5c0dbd7158c0f70b2f Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Sat, 23 Jun 2018 16:16:06 +0200 Subject: [PATCH 005/243] Store custom Menu items in CuraApplication --- cura/CuraApplication.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 08f267d0e1..e5562745de 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -101,6 +101,7 @@ from cura.Settings.UserChangesModel import UserChangesModel from cura.Settings.ExtrudersModel import ExtrudersModel from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler from cura.Settings.ContainerManager import ContainerManager +from cura.Settings.SidebarCustomMenuItemsModel import SidebarCustomMenuItemsModel from cura.ObjectsModel import ObjectsModel @@ -219,6 +220,8 @@ class CuraApplication(QtApplication): self._need_to_show_user_agreement = True + self._sidebar_custom_menu_items = [] # type: list # Keeps list of custom menu items for the side bar + # Backups self._auto_save = None self._save_data_enabled = True @@ -943,6 +946,7 @@ class CuraApplication(QtApplication): qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator") qmlRegisterType(UserChangesModel, "Cura", 1, 0, "UserChangesModel") qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.getInstance) + qmlRegisterType(SidebarCustomMenuItemsModel, "Cura", 1, 0, "SidebarCustomMenuItemsModel") # As of Qt5.7, it is necessary to get rid of any ".." in the path for the singleton to work. actions_url = QUrl.fromLocalFile(os.path.abspath(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml"))) @@ -1729,3 +1733,10 @@ class CuraApplication(QtApplication): @pyqtSlot() def showMoreInformationDialogForAnonymousDataCollection(self): self._plugin_registry.getPluginObject("SliceInfoPlugin").showMoreInfoDialog() + + + def addSidebarCustomMenuItem(self, menu_item: list) -> None: + self._sidebar_custom_menu_items.append(menu_item) + + def getSidebarCustomMenuItems(self) -> list: + return self._sidebar_custom_menu_items \ No newline at end of file From f577789859952ca1bfcd607268583b0ef650dd6d Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Sat, 23 Jun 2018 16:22:33 +0200 Subject: [PATCH 006/243] Added extra SettingsModel for a QML --- cura/Settings/SidebarCustomMenuItemsModel.py | 32 ++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 cura/Settings/SidebarCustomMenuItemsModel.py diff --git a/cura/Settings/SidebarCustomMenuItemsModel.py b/cura/Settings/SidebarCustomMenuItemsModel.py new file mode 100644 index 0000000000..71abb0d2ed --- /dev/null +++ b/cura/Settings/SidebarCustomMenuItemsModel.py @@ -0,0 +1,32 @@ +from UM.Qt.ListModel import ListModel +from PyQt5.QtCore import pyqtSlot, Qt + +class SidebarCustomMenuItemsModel(ListModel): + NameRole = Qt.UserRole + 1 + ActionsRole = Qt.UserRole + 2 + MenuItemRole = Qt.UserRole + 3 + + def __init__(self, parent=None): + super().__init__(parent) + self.addRoleName(self.NameRole, "name") + self.addRoleName(self.ActionsRole, "actions") + self.addRoleName(self.MenuItemRole, "menu_item") + self._updateExtensionList() + + def _updateExtensionList(self)-> None: + from cura.CuraApplication import CuraApplication + for menu_item in CuraApplication.getInstance().getSidebarCustomMenuItems(): + + self.appendItem({ + "name": menu_item["name"], + "actions": menu_item["actions"], + "menu_item": menu_item["menu_item"] + }) + + @pyqtSlot(str, "QVariantList") + def callMenuItemMethod(self, menu_item_name: str, menu_item_actions: list)-> None: + for item in self._items: + if menu_item_name == item["name"]: + for method in menu_item_actions: + getattr(item["menu_item"], method)() + break \ No newline at end of file From c4fa50a8fc1ffd9879b973d61a7ab9dfad7c9405 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Mon, 25 Jun 2018 16:51:40 +0200 Subject: [PATCH 007/243] Added icon for custom Menu items --- cura/Settings/SidebarCustomMenuItemsModel.py | 9 ++++++--- resources/qml/Settings/SettingView.qml | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cura/Settings/SidebarCustomMenuItemsModel.py b/cura/Settings/SidebarCustomMenuItemsModel.py index 71abb0d2ed..8c82d288bf 100644 --- a/cura/Settings/SidebarCustomMenuItemsModel.py +++ b/cura/Settings/SidebarCustomMenuItemsModel.py @@ -5,12 +5,14 @@ class SidebarCustomMenuItemsModel(ListModel): NameRole = Qt.UserRole + 1 ActionsRole = Qt.UserRole + 2 MenuItemRole = Qt.UserRole + 3 + MenuItemIconNameRole = Qt.UserRole + 5 def __init__(self, parent=None): super().__init__(parent) self.addRoleName(self.NameRole, "name") self.addRoleName(self.ActionsRole, "actions") self.addRoleName(self.MenuItemRole, "menu_item") + self.addRoleName(self.MenuItemIconNameRole, "iconName") self._updateExtensionList() def _updateExtensionList(self)-> None: @@ -19,14 +21,15 @@ class SidebarCustomMenuItemsModel(ListModel): self.appendItem({ "name": menu_item["name"], + "iconName": menu_item["iconName"], "actions": menu_item["actions"], "menu_item": menu_item["menu_item"] }) - @pyqtSlot(str, "QVariantList") - def callMenuItemMethod(self, menu_item_name: str, menu_item_actions: list)-> None: + @pyqtSlot(str, "QVariantList", "QVariantMap") + def callMenuItemMethod(self, menu_item_name: str, menu_item_actions: list, kwargs)-> None: for item in self._items: if menu_item_name == item["name"]: for method in menu_item_actions: - getattr(item["menu_item"], method)() + getattr(item["menu_item"], method)(kwargs) break \ No newline at end of file diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 30160cb5fb..88876123fe 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -568,9 +568,10 @@ Item MenuItem { text: model.name + iconName: model.iconName onTriggered: { - customMenuItems.model.callMenuItemMethod(name, model.actions) + customMenuItems.model.callMenuItemMethod(name, model.actions, {"key": contextMenu.key}) } } onObjectAdded: contextMenu.insertItem(index, object) From 7e9054616358f237d8c0615ff739dd7e43e48b31 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Fri, 29 Jun 2018 10:34:15 +0200 Subject: [PATCH 008/243] Fix firmware upload on Windows... by correctly creating a local path from a url-encoded path Fixes #3731 and #3987 --- plugins/USBPrinting/USBPrinterOutputDevice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index 00eb2f0b25..926cd9001d 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -15,7 +15,7 @@ from cura.PrinterOutput.GenericOutputController import GenericOutputController from .AutoDetectBaudJob import AutoDetectBaudJob from .avr_isp import stk500v2, intelHex -from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty +from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty, QUrl from serial import Serial, SerialException, SerialTimeoutException from threading import Thread, Event @@ -128,7 +128,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice): @pyqtSlot(str) def updateFirmware(self, file): # the file path is qurl encoded. - self._firmware_location = file.replace("file://", "") + self._firmware_location = QUrl(file).toLocalFile() self.showFirmwareInterface() self.setFirmwareUpdateState(FirmwareUpdateState.updating) self._update_firmware_thread.start() From 46ce90c803cea95a68c76d151f76d5934d2aec35 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 16 Jul 2018 16:54:50 +0200 Subject: [PATCH 009/243] Fix-up Dagoma definitions - Removed nozzle size in magis def because it's in the extruder def on other machines - Removed material diam from disco extruder def because its in the disco machine - Remove material diam from neva extruder def because its in the neva machine Contributes to CURA-5499 --- .../definitions/dagoma_neva_magis.def.json | 3 --- .../dagoma_discoeasy200_extruder_0.def.json | 9 ++++++--- .../extruders/dagoma_neva_extruder_0.def.json | 9 ++++++--- .../dagoma_neva_magis_extruder_0.def.json | 19 +++++++++++++++++++ 4 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 resources/extruders/dagoma_neva_magis_extruder_0.def.json diff --git a/resources/definitions/dagoma_neva_magis.def.json b/resources/definitions/dagoma_neva_magis.def.json index fe5cff471e..91f99146ba 100644 --- a/resources/definitions/dagoma_neva_magis.def.json +++ b/resources/definitions/dagoma_neva_magis.def.json @@ -24,9 +24,6 @@ "machine_center_is_zero": { "default_value": true }, - "machine_nozzle_size": { - "default_value": 0.4 - }, "machine_head_with_fans_polygon": { "default_value": [ [-36, -42], diff --git a/resources/extruders/dagoma_discoeasy200_extruder_0.def.json b/resources/extruders/dagoma_discoeasy200_extruder_0.def.json index eb2b8ef1f7..342741c559 100644 --- a/resources/extruders/dagoma_discoeasy200_extruder_0.def.json +++ b/resources/extruders/dagoma_discoeasy200_extruder_0.def.json @@ -9,8 +9,11 @@ }, "overrides": { - "extruder_nr": { "default_value": 0 }, - "machine_nozzle_size": { "default_value": 0.4 }, - "material_diameter": { "default_value": 1.75 } + "extruder_nr": { + "default_value": 0 + }, + "machine_nozzle_size": { + "default_value": 0.4 + } } } diff --git a/resources/extruders/dagoma_neva_extruder_0.def.json b/resources/extruders/dagoma_neva_extruder_0.def.json index dcb8311be4..eeb8a42a3a 100644 --- a/resources/extruders/dagoma_neva_extruder_0.def.json +++ b/resources/extruders/dagoma_neva_extruder_0.def.json @@ -9,8 +9,11 @@ }, "overrides": { - "extruder_nr": { "default_value": 0 }, - "machine_nozzle_size": { "default_value": 0.4 }, - "material_diameter": { "default_value": 1.75 } + "extruder_nr": { + "default_value": 0 + }, + "machine_nozzle_size": { + "default_value": 0.4 + } } } diff --git a/resources/extruders/dagoma_neva_magis_extruder_0.def.json b/resources/extruders/dagoma_neva_magis_extruder_0.def.json new file mode 100644 index 0000000000..4a20b64fe8 --- /dev/null +++ b/resources/extruders/dagoma_neva_magis_extruder_0.def.json @@ -0,0 +1,19 @@ +{ + "id": "dagoma_neva_magis_extruder_0", + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "dagoma_neva_magis", + "position": "0" + }, + + "overrides": { + "extruder_nr": { + "default_value": 0 + }, + "machine_nozzle_size": { + "default_value": 0.4 + } + } +} From 65ada30c9c45687f6fe860af7ecc74889978a3a1 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 16 Jul 2018 13:26:51 +0200 Subject: [PATCH 010/243] Fix flashing "default" firmware The url is not QUrl encoded if the "default" firmware is flashed --- plugins/USBPrinting/USBPrinterOutputDevice.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index 926cd9001d..6a97a3c163 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -127,8 +127,11 @@ class USBPrinterOutputDevice(PrinterOutputDevice): @pyqtSlot(str) def updateFirmware(self, file): - # the file path is qurl encoded. - self._firmware_location = QUrl(file).toLocalFile() + # the file path could be qurl encoded. + if file[:7] == "file://": + self._firmware_location = QUrl(file).toLocalFile() + else: + self._firmware_location = file self.showFirmwareInterface() self.setFirmwareUpdateState(FirmwareUpdateState.updating) self._update_firmware_thread.start() From ed1e47dcc99e79d05f80fdd7d7e8d899b2347ea9 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 17 Jul 2018 10:56:33 +0200 Subject: [PATCH 011/243] Moved material diameters to extruders defs Contributes to CURA-5499 --- resources/definitions/dagoma_discoeasy200.def.json | 3 --- resources/definitions/dagoma_neva.def.json | 4 ---- resources/definitions/dagoma_neva_magis.def.json | 4 ---- resources/extruders/dagoma_discoeasy200_extruder_0.def.json | 4 +++- resources/extruders/dagoma_neva_extruder_0.def.json | 4 +++- resources/extruders/dagoma_neva_magis_extruder_0.def.json | 4 +++- 6 files changed, 9 insertions(+), 14 deletions(-) diff --git a/resources/definitions/dagoma_discoeasy200.def.json b/resources/definitions/dagoma_discoeasy200.def.json index 60f371ec88..5e45947393 100644 --- a/resources/definitions/dagoma_discoeasy200.def.json +++ b/resources/definitions/dagoma_discoeasy200.def.json @@ -44,9 +44,6 @@ "machine_end_gcode": { "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 F3000\nG90\nG28 X Y\nM107\nM84\n" }, - "material_diameter": { - "default_value": 1.75 - }, "default_material_print_temperature": { "default_value": 205 }, diff --git a/resources/definitions/dagoma_neva.def.json b/resources/definitions/dagoma_neva.def.json index b7a15995c3..be429e32af 100644 --- a/resources/definitions/dagoma_neva.def.json +++ b/resources/definitions/dagoma_neva.def.json @@ -1,5 +1,4 @@ { - "id": "dagoma_neva", "name": "Dagoma NEVA", "version": 2, "inherits": "fdmprinter", @@ -51,9 +50,6 @@ "machine_end_gcode": { "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 E-2 F9000\nG90\nG28\n" }, - "material_diameter": { - "default_value": 1.75 - }, "default_material_print_temperature": { "default_value": 205 }, diff --git a/resources/definitions/dagoma_neva_magis.def.json b/resources/definitions/dagoma_neva_magis.def.json index 91f99146ba..6a856044b2 100644 --- a/resources/definitions/dagoma_neva_magis.def.json +++ b/resources/definitions/dagoma_neva_magis.def.json @@ -1,5 +1,4 @@ { - "id": "dagoma_neva_magis", "name": "Dagoma NEVA Magis", "version": 2, "inherits": "fdmprinter", @@ -47,9 +46,6 @@ "machine_end_gcode": { "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 E-2 F9000\nG90\nG28\n" }, - "material_diameter": { - "default_value": 1.75 - }, "default_material_print_temperature": { "default_value": 205 }, diff --git a/resources/extruders/dagoma_discoeasy200_extruder_0.def.json b/resources/extruders/dagoma_discoeasy200_extruder_0.def.json index 342741c559..c885ac971e 100644 --- a/resources/extruders/dagoma_discoeasy200_extruder_0.def.json +++ b/resources/extruders/dagoma_discoeasy200_extruder_0.def.json @@ -1,5 +1,4 @@ { - "id": "dagoma_discoeasy200_extruder_0", "version": 2, "name": "Extruder 1", "inherits": "fdmextruder", @@ -14,6 +13,9 @@ }, "machine_nozzle_size": { "default_value": 0.4 + }, + "material_diameter": { + "default_value": 1.75 } } } diff --git a/resources/extruders/dagoma_neva_extruder_0.def.json b/resources/extruders/dagoma_neva_extruder_0.def.json index eeb8a42a3a..95035f63f2 100644 --- a/resources/extruders/dagoma_neva_extruder_0.def.json +++ b/resources/extruders/dagoma_neva_extruder_0.def.json @@ -1,5 +1,4 @@ { - "id": "dagoma_neva_extruder_0", "version": 2, "name": "Extruder 1", "inherits": "fdmextruder", @@ -14,6 +13,9 @@ }, "machine_nozzle_size": { "default_value": 0.4 + }, + "material_diameter": { + "default_value": 1.75 } } } diff --git a/resources/extruders/dagoma_neva_magis_extruder_0.def.json b/resources/extruders/dagoma_neva_magis_extruder_0.def.json index 4a20b64fe8..0d5fd3c9b4 100644 --- a/resources/extruders/dagoma_neva_magis_extruder_0.def.json +++ b/resources/extruders/dagoma_neva_magis_extruder_0.def.json @@ -1,5 +1,4 @@ { - "id": "dagoma_neva_magis_extruder_0", "version": 2, "name": "Extruder 1", "inherits": "fdmextruder", @@ -14,6 +13,9 @@ }, "machine_nozzle_size": { "default_value": 0.4 + }, + "material_diameter": { + "default_value": 1.75 } } } From 139ac5c5460da2e118b9258f472edc09160304b5 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 17 Jul 2018 13:18:22 +0200 Subject: [PATCH 012/243] Quality profile fixes Contributes to CURA-5499 --- .../quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg | 2 +- .../quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg | 4 ++-- .../quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg | 4 ++-- resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg | 2 +- resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg | 4 ++-- .../quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg | 4 ++-- resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg | 2 +- resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg | 4 ++-- resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg | 4 ++-- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg index 6cd88f819c..b1b742935d 100644 --- a/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg @@ -4,7 +4,7 @@ name = Fast definition = dagoma_discoeasy200 [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = draft weight = -2 diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg index 0f59401dd5..e6ac921430 100644 --- a/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg @@ -4,9 +4,9 @@ name = Fine definition = dagoma_discoeasy200 [metadata] -setting_version = 4 +setting_version = 5 type = quality -quality_type = high +quality_type = normal weight = 0 material = generic_pla diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg index 9c1cc19f9e..7261c2c416 100644 --- a/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg @@ -4,9 +4,9 @@ name = Standard definition = dagoma_discoeasy200 [metadata] -setting_version = 4 +setting_version = 5 type = quality -quality_type = normal +quality_type = fast weight = -1 material = generic_pla diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg index f0f5810e82..8f75d6733d 100644 --- a/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg @@ -4,7 +4,7 @@ name = Fast definition = dagoma_neva [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = draft weight = -2 diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg index 3dc4ce5627..018e7f1e63 100644 --- a/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg @@ -4,9 +4,9 @@ name = Fine definition = dagoma_neva [metadata] -setting_version = 4 +setting_version = 5 type = quality -quality_type = high +quality_type = normal weight = 0 material = generic_pla diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg index ce2157c90b..9456eb25f8 100644 --- a/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg @@ -4,9 +4,9 @@ name = Standard definition = dagoma_neva [metadata] -setting_version = 4 +setting_version = 5 type = quality -quality_type = normal +quality_type = fast weight = -1 material = generic_pla diff --git a/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg index f0f5810e82..8f75d6733d 100644 --- a/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg @@ -4,7 +4,7 @@ name = Fast definition = dagoma_neva [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = draft weight = -2 diff --git a/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg index 3dc4ce5627..018e7f1e63 100644 --- a/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg @@ -4,9 +4,9 @@ name = Fine definition = dagoma_neva [metadata] -setting_version = 4 +setting_version = 5 type = quality -quality_type = high +quality_type = normal weight = 0 material = generic_pla diff --git a/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg index ce2157c90b..9456eb25f8 100644 --- a/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg @@ -4,9 +4,9 @@ name = Standard definition = dagoma_neva [metadata] -setting_version = 4 +setting_version = 5 type = quality -quality_type = normal +quality_type = fast weight = -1 material = generic_pla From f1efaa78b7719efaf425316e3896d013a2ce6b28 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 17 Jul 2018 13:22:15 +0200 Subject: [PATCH 013/243] General version to v4, fixed bed temp Contributes to CURA-5499 --- .../quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg | 2 +- .../quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg | 2 +- .../quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg | 4 ++-- resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg | 4 ++-- resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg | 2 +- .../quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg | 4 ++-- resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg | 4 ++-- resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg | 2 +- resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg | 4 ++-- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg index b1b742935d..5ba805a4fa 100644 --- a/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg @@ -1,5 +1,5 @@ [general] -version = 3 +version = 4 name = Fast definition = dagoma_discoeasy200 diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg index e6ac921430..695fd7bc7e 100644 --- a/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg @@ -1,5 +1,5 @@ [general] -version = 3 +version = 4 name = Fine definition = dagoma_discoeasy200 diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg index 7261c2c416..b6b086403d 100644 --- a/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg @@ -1,5 +1,5 @@ [general] -version = 3 +version = 4 name = Standard definition = dagoma_discoeasy200 @@ -14,4 +14,4 @@ material = generic_pla layer_height = 0.15 material_print_temperature = =default_material_print_temperature + 5 -material_bed_temperature_layer_0 = =default_material_print_temperature + 5 +material_bed_temperature_layer_0 = =default_material_bed_temperature + 5 diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg index 8f75d6733d..51fb17a5cc 100644 --- a/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg @@ -1,5 +1,5 @@ [general] -version = 3 +version = 4 name = Fast definition = dagoma_neva @@ -14,4 +14,4 @@ material = generic_pla layer_height = 0.2 material_print_temperature = =default_material_print_temperature + 10 -material_bed_temperature_layer_0 = =default_material_print_temperature + 10 +material_bed_temperature_layer_0 = =default_material_bed_temperature + 10 diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg index 018e7f1e63..1ff947d766 100644 --- a/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg @@ -1,5 +1,5 @@ [general] -version = 3 +version = 4 name = Fine definition = dagoma_neva diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg index 9456eb25f8..dfcc1c967b 100644 --- a/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg @@ -1,5 +1,5 @@ [general] -version = 3 +version = 4 name = Standard definition = dagoma_neva @@ -14,4 +14,4 @@ material = generic_pla layer_height = 0.15 material_print_temperature = =default_material_print_temperature + 5 -material_bed_temperature_layer_0 = =default_material_print_temperature + 5 +material_bed_temperature_layer_0 = =default_material_bed_temperature + 5 diff --git a/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg index 8f75d6733d..51fb17a5cc 100644 --- a/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg @@ -1,5 +1,5 @@ [general] -version = 3 +version = 4 name = Fast definition = dagoma_neva @@ -14,4 +14,4 @@ material = generic_pla layer_height = 0.2 material_print_temperature = =default_material_print_temperature + 10 -material_bed_temperature_layer_0 = =default_material_print_temperature + 10 +material_bed_temperature_layer_0 = =default_material_bed_temperature + 10 diff --git a/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg index 018e7f1e63..1ff947d766 100644 --- a/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg @@ -1,5 +1,5 @@ [general] -version = 3 +version = 4 name = Fine definition = dagoma_neva diff --git a/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg index 9456eb25f8..dfcc1c967b 100644 --- a/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg @@ -1,5 +1,5 @@ [general] -version = 3 +version = 4 name = Standard definition = dagoma_neva @@ -14,4 +14,4 @@ material = generic_pla layer_height = 0.15 material_print_temperature = =default_material_print_temperature + 5 -material_bed_temperature_layer_0 = =default_material_print_temperature + 5 +material_bed_temperature_layer_0 = =default_material_bed_temperature + 5 From 350f9caa2a69259b82527f68bf3d539f8234a554 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 17 Jul 2018 14:15:16 +0200 Subject: [PATCH 014/243] Use material bed temperature as reference for the bed temperature of the first layer. Contributes to CURA-5499. --- resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg index 5ba805a4fa..a75d01c9f0 100644 --- a/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg @@ -14,4 +14,4 @@ material = generic_pla layer_height = 0.2 material_print_temperature = =default_material_print_temperature + 10 -material_bed_temperature_layer_0 = =default_material_print_temperature + 10 +material_bed_temperature_layer_0 = =default_material_bed_temperature + 10 From eab10401eeaefdaecf0e5cf3499be2f476410c34 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 17 Jul 2018 18:02:11 +0200 Subject: [PATCH 015/243] Add global profiles and define that the printers have materials and quality profiles, in the definition files. Contributes to CURA-5499 --- cura/Settings/MachineManager.py | 2 ++ resources/definitions/dagoma_discoeasy200.def.json | 2 ++ resources/definitions/dagoma_neva.def.json | 2 ++ resources/definitions/dagoma_neva_magis.def.json | 8 +++++++- .../dagoma/dagoma_discoeasy200_pla_fast.inst.cfg | 2 -- .../dagoma/dagoma_discoeasy200_pla_fine.inst.cfg | 1 - .../dagoma_discoeasy200_pla_standard.inst.cfg | 2 -- .../quality/dagoma/dagoma_global_fast.inst.cfg | 14 ++++++++++++++ .../quality/dagoma/dagoma_global_fine.inst.cfg | 14 ++++++++++++++ .../quality/dagoma/dagoma_global_standard.inst.cfg | 14 ++++++++++++++ .../dagoma/dagoma_neva_magis_pla_fast.inst.cfg | 2 -- .../dagoma/dagoma_neva_magis_pla_fine.inst.cfg | 1 - .../dagoma/dagoma_neva_magis_pla_standard.inst.cfg | 2 -- .../quality/dagoma/dagoma_neva_pla_fast.inst.cfg | 2 -- .../quality/dagoma/dagoma_neva_pla_fine.inst.cfg | 1 - .../dagoma/dagoma_neva_pla_standard.inst.cfg | 2 -- 16 files changed, 55 insertions(+), 16 deletions(-) create mode 100644 resources/quality/dagoma/dagoma_global_fast.inst.cfg create mode 100644 resources/quality/dagoma/dagoma_global_fine.inst.cfg create mode 100644 resources/quality/dagoma/dagoma_global_standard.inst.cfg diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 26f5a490dd..1f1e940100 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -335,6 +335,7 @@ class MachineManager(QObject): global_stack.getName(), new_quality_changes_group.name) else: new_quality_group = quality_groups.get(quality_type) + print(quality_groups) if new_quality_group is not None: self._setQualityGroup(new_quality_group, empty_quality_changes = True) same_quality_found = True @@ -1107,6 +1108,7 @@ class MachineManager(QObject): # Set quality and quality_changes for each ExtruderStack for position, node in quality_group.nodes_for_extruders.items(): self._global_container_stack.extruders[str(position)].quality = node.getContainer() + print("#######", node.getContainer().getName()) if empty_quality_changes: self._global_container_stack.extruders[str(position)].qualityChanges = self._empty_quality_changes_container diff --git a/resources/definitions/dagoma_discoeasy200.def.json b/resources/definitions/dagoma_discoeasy200.def.json index 5e45947393..89d94ff6b7 100644 --- a/resources/definitions/dagoma_discoeasy200.def.json +++ b/resources/definitions/dagoma_discoeasy200.def.json @@ -9,6 +9,8 @@ "file_formats": "text/x-gcode", "platform": "discoeasy200.stl", "platform_offset": [ 105, -59, 280], + "has_machine_quality": true, + "has_materials": true, "machine_extruder_trains": { "0": "dagoma_discoeasy200_extruder_0" diff --git a/resources/definitions/dagoma_neva.def.json b/resources/definitions/dagoma_neva.def.json index be429e32af..cdd5725765 100644 --- a/resources/definitions/dagoma_neva.def.json +++ b/resources/definitions/dagoma_neva.def.json @@ -9,6 +9,8 @@ "file_formats": "text/x-gcode", "platform": "neva.stl", "platform_offset": [ 0, 0, 0], + "has_machine_quality": true, + "has_materials": true, "machine_extruder_trains": { "0": "dagoma_neva_extruder_0" diff --git a/resources/definitions/dagoma_neva_magis.def.json b/resources/definitions/dagoma_neva_magis.def.json index 6a856044b2..07bf5987f5 100644 --- a/resources/definitions/dagoma_neva_magis.def.json +++ b/resources/definitions/dagoma_neva_magis.def.json @@ -8,7 +8,13 @@ "manufacturer": "Dagoma", "file_formats": "text/x-gcode", "platform": "neva.stl", - "platform_offset": [ 0, 0, 0] + "platform_offset": [ 0, 0, 0], + "has_machine_quality": true, + "has_materials": true, + "machine_extruder_trains": + { + "0": "dagoma_neva_extruder_0" + } }, "overrides": { "machine_width": { diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg index a75d01c9f0..a302f5b513 100644 --- a/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_fast.inst.cfg @@ -11,7 +11,5 @@ weight = -2 material = generic_pla [values] -layer_height = 0.2 - material_print_temperature = =default_material_print_temperature + 10 material_bed_temperature_layer_0 = =default_material_bed_temperature + 10 diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg index 695fd7bc7e..b26eb1d910 100644 --- a/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_fine.inst.cfg @@ -11,4 +11,3 @@ weight = 0 material = generic_pla [values] -layer_height = 0.1 diff --git a/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg index b6b086403d..9ec56f696a 100644 --- a/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg +++ b/resources/quality/dagoma/dagoma_discoeasy200_pla_standard.inst.cfg @@ -11,7 +11,5 @@ weight = -1 material = generic_pla [values] -layer_height = 0.15 - material_print_temperature = =default_material_print_temperature + 5 material_bed_temperature_layer_0 = =default_material_bed_temperature + 5 diff --git a/resources/quality/dagoma/dagoma_global_fast.inst.cfg b/resources/quality/dagoma/dagoma_global_fast.inst.cfg new file mode 100644 index 0000000000..28569387f2 --- /dev/null +++ b/resources/quality/dagoma/dagoma_global_fast.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Fast +definition = dagoma_discoeasy200 + +[metadata] +setting_version = 5 +type = quality +quality_type = draft +weight = -2 +global_quality = True + +[values] +layer_height = 0.2 diff --git a/resources/quality/dagoma/dagoma_global_fine.inst.cfg b/resources/quality/dagoma/dagoma_global_fine.inst.cfg new file mode 100644 index 0000000000..1f7d577c1b --- /dev/null +++ b/resources/quality/dagoma/dagoma_global_fine.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Fine +definition = dagoma_discoeasy200 + +[metadata] +setting_version = 5 +type = quality +quality_type = normal +weight = 0 +global_quality = True + +[values] +layer_height = 0.1 diff --git a/resources/quality/dagoma/dagoma_global_standard.inst.cfg b/resources/quality/dagoma/dagoma_global_standard.inst.cfg new file mode 100644 index 0000000000..167062c1d7 --- /dev/null +++ b/resources/quality/dagoma/dagoma_global_standard.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Standard +definition = dagoma_discoeasy200 + +[metadata] +setting_version = 5 +type = quality +quality_type = fast +weight = -1 +global_quality = True + +[values] +layer_height = 0.15 diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg index 51fb17a5cc..efdf2f7d32 100644 --- a/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg @@ -11,7 +11,5 @@ weight = -2 material = generic_pla [values] -layer_height = 0.2 - material_print_temperature = =default_material_print_temperature + 10 material_bed_temperature_layer_0 = =default_material_bed_temperature + 10 diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg index 1ff947d766..50915db112 100644 --- a/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg @@ -11,4 +11,3 @@ weight = 0 material = generic_pla [values] -layer_height = 0.1 diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg index dfcc1c967b..ed67800eac 100644 --- a/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg @@ -11,7 +11,5 @@ weight = -1 material = generic_pla [values] -layer_height = 0.15 - material_print_temperature = =default_material_print_temperature + 5 material_bed_temperature_layer_0 = =default_material_bed_temperature + 5 diff --git a/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg index 51fb17a5cc..efdf2f7d32 100644 --- a/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_pla_fast.inst.cfg @@ -11,7 +11,5 @@ weight = -2 material = generic_pla [values] -layer_height = 0.2 - material_print_temperature = =default_material_print_temperature + 10 material_bed_temperature_layer_0 = =default_material_bed_temperature + 10 diff --git a/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg index 1ff947d766..50915db112 100644 --- a/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_pla_fine.inst.cfg @@ -11,4 +11,3 @@ weight = 0 material = generic_pla [values] -layer_height = 0.1 diff --git a/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg index dfcc1c967b..ed67800eac 100644 --- a/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_pla_standard.inst.cfg @@ -11,7 +11,5 @@ weight = -1 material = generic_pla [values] -layer_height = 0.15 - material_print_temperature = =default_material_print_temperature + 5 material_bed_temperature_layer_0 = =default_material_bed_temperature + 5 From 327eaf9564b7369e35041c234b0e966bb5b45da0 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 17 Jul 2018 18:09:59 +0200 Subject: [PATCH 016/243] Remove debug printing Contributes to CURA-5499 --- cura/Settings/MachineManager.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 1f1e940100..26f5a490dd 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -335,7 +335,6 @@ class MachineManager(QObject): global_stack.getName(), new_quality_changes_group.name) else: new_quality_group = quality_groups.get(quality_type) - print(quality_groups) if new_quality_group is not None: self._setQualityGroup(new_quality_group, empty_quality_changes = True) same_quality_found = True @@ -1108,7 +1107,6 @@ class MachineManager(QObject): # Set quality and quality_changes for each ExtruderStack for position, node in quality_group.nodes_for_extruders.items(): self._global_container_stack.extruders[str(position)].quality = node.getContainer() - print("#######", node.getContainer().getName()) if empty_quality_changes: self._global_container_stack.extruders[str(position)].qualityChanges = self._empty_quality_changes_container From e96c59223434705c99df915f68594783d0fb43d9 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 17 Jul 2018 18:12:22 +0200 Subject: [PATCH 017/243] Add correct name to the Dagoma Neva Magis extruder. Contributes to CURA-5499 --- resources/definitions/dagoma_neva_magis.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/dagoma_neva_magis.def.json b/resources/definitions/dagoma_neva_magis.def.json index 07bf5987f5..0b7b50cb5f 100644 --- a/resources/definitions/dagoma_neva_magis.def.json +++ b/resources/definitions/dagoma_neva_magis.def.json @@ -13,7 +13,7 @@ "has_materials": true, "machine_extruder_trains": { - "0": "dagoma_neva_extruder_0" + "0": "dagoma_neva_magis_extruder_0" } }, "overrides": { From f90f5f5180937b0251ebc927ad751541fb9d4826 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Thu, 19 Jul 2018 12:18:53 +0200 Subject: [PATCH 018/243] Update available configuration button --- .../ConfigurationMenu/ConfigurationItem.qml | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml b/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml index 6f0130d5ca..942dd81d9c 100644 --- a/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml +++ b/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml @@ -103,9 +103,24 @@ Rectangle id: mouse anchors.fill: parent onClicked: activateConfiguration() + cursorShape: Qt.PointingHandCursor hoverEnabled: true - onEntered: parent.border.color = UM.Theme.getColor("configuration_item_border_hover") - onExited: updateBorderColor() + onEntered: + { + parent.border.color = UM.Theme.getColor("configuration_item_border_hover") + if (configurationItem.selected == false) + { + configurationItem.color = UM.Theme.getColor("sidebar_lining") + } + } + onExited: + { + updateBorderColor() + if (configurationItem.selected == false) + { + configurationItem.color = UM.Theme.getColor("configuration_item") + } + } } Connections @@ -122,4 +137,13 @@ Rectangle configurationItem.selected = Cura.MachineManager.matchesConfiguration(configuration) updateBorderColor() } + + onVisibleChanged: + { + if(visible) + { + // I cannot trigger function updateBorderColor() after visibility change + color = selected ? UM.Theme.getColor("configuration_item_active") : UM.Theme.getColor("configuration_item") + } + } } \ No newline at end of file From 3848ec66bdff51a34011bd9df5b84ebb8d8bbc11 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Thu, 19 Jul 2018 16:32:36 +0200 Subject: [PATCH 019/243] Disable 'Alternate Mesh Removal' and 'Remove Mesh Intersection' if Surface Model == 'Surface' CURA-5580 --- resources/definitions/fdmprinter.def.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index e376d8a9c2..04b4f34f8b 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5173,6 +5173,7 @@ "type": "bool", "default_value": true, "value": "extruders_enabled_count > 1", + "enabled": "all(p != 'surface' for p in extruderValues('magic_mesh_surface_mode'))", "settable_per_mesh": false, "settable_per_extruder": false, "settable_per_meshgroup": true @@ -5183,7 +5184,7 @@ "description": "Switch to which mesh intersecting volumes will belong with every layer, so that the overlapping meshes become interwoven. Turning this setting off will cause one of the meshes to obtain all of the volume in the overlap, while it is removed from the other meshes.", "type": "bool", "default_value": true, - "enabled": "carve_multiple_volumes", + "enabled": "carve_multiple_volumes and all(p != 'surface' for p in extruderValues('magic_mesh_surface_mode'))", "settable_per_mesh": false, "settable_per_extruder": false, "settable_per_meshgroup": true From 2a8a52c0d9adc801f4643f53a05c48162053c375 Mon Sep 17 00:00:00 2001 From: THeijmans Date: Fri, 20 Jul 2018 10:22:17 +0200 Subject: [PATCH 020/243] TPU 08 profiles cleanup Removed an unneccesary line and changed first layer print temperature formula to use the set temperature, and not the default temperature. --- .../quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg | 3 +-- .../quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg | 3 +-- .../quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg | 3 +-- .../quality/ultimaker_s5/um_s5_aa0.8_TPU_Draft_Print.inst.cfg | 3 +-- .../ultimaker_s5/um_s5_aa0.8_TPU_Superdraft_Print.inst.cfg | 3 +-- .../ultimaker_s5/um_s5_aa0.8_TPU_Verydraft_Print.inst.cfg | 3 +-- 6 files changed, 6 insertions(+), 12 deletions(-) diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg index 52fe1cb01d..1d5cea601f 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg @@ -25,12 +25,11 @@ jerk_support = =math.ceil(jerk_print * 25 / 25) jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) machine_nozzle_cool_down_speed = 0.5 machine_nozzle_heat_up_speed = 2.5 -material_bed_temperature_layer_0 = 0 material_final_print_temperature = =material_print_temperature - 21 material_flow = 105 material_initial_print_temperature = =material_print_temperature - 16 material_print_temperature = =default_material_print_temperature - 2 -material_print_temperature_layer_0 = =default_material_print_temperature + 2 +material_print_temperature_layer_0 = =material_print_temperature + 4 material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg index 857ea39491..9535685efe 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg @@ -26,12 +26,11 @@ jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) layer_height = 0.4 machine_nozzle_cool_down_speed = 0.5 machine_nozzle_heat_up_speed = 2.5 -material_bed_temperature_layer_0 = 0 material_final_print_temperature = =material_print_temperature - 21 material_flow = 105 material_initial_print_temperature = =material_print_temperature - 16 material_print_temperature = =default_material_print_temperature + 2 -material_print_temperature_layer_0 = =default_material_print_temperature + 2 +material_print_temperature_layer_0 = =material_print_temperature + 2 material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg index 10673c133a..50282f8b49 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg @@ -26,11 +26,10 @@ jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) layer_height = 0.3 machine_nozzle_cool_down_speed = 0.5 machine_nozzle_heat_up_speed = 2.5 -material_bed_temperature_layer_0 = 0 material_final_print_temperature = =material_print_temperature - 21 material_flow = 105 material_initial_print_temperature = =material_print_temperature - 16 -material_print_temperature_layer_0 = =default_material_print_temperature + 2 +material_print_temperature_layer_0 = =material_print_temperature + 2 material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Draft_Print.inst.cfg index 889ffaf567..f88da43ac1 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Draft_Print.inst.cfg @@ -23,12 +23,11 @@ jerk_support = =math.ceil(jerk_print * 25 / 25) jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) machine_nozzle_cool_down_speed = 0.5 machine_nozzle_heat_up_speed = 2.5 -material_bed_temperature_layer_0 = 0 material_final_print_temperature = =material_print_temperature - 21 material_flow = 105 material_initial_print_temperature = =material_print_temperature - 16 material_print_temperature = =default_material_print_temperature - 2 -material_print_temperature_layer_0 = =default_material_print_temperature + 2 +material_print_temperature_layer_0 = =material_print_temperature + 4 material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Superdraft_Print.inst.cfg index fca907e8fd..2967f3539b 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Superdraft_Print.inst.cfg @@ -24,12 +24,11 @@ jerk_support = =math.ceil(jerk_print * 25 / 25) jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) machine_nozzle_cool_down_speed = 0.5 machine_nozzle_heat_up_speed = 2.5 -material_bed_temperature_layer_0 = 0 material_final_print_temperature = =material_print_temperature - 21 material_flow = 105 material_initial_print_temperature = =material_print_temperature - 16 material_print_temperature = =default_material_print_temperature + 2 -material_print_temperature_layer_0 = =default_material_print_temperature + 2 +material_print_temperature_layer_0 = =material_print_temperature material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Verydraft_Print.inst.cfg index 673d64d432..caa87f9437 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Verydraft_Print.inst.cfg @@ -24,11 +24,10 @@ jerk_support = =math.ceil(jerk_print * 25 / 25) jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) machine_nozzle_cool_down_speed = 0.5 machine_nozzle_heat_up_speed = 2.5 -material_bed_temperature_layer_0 = 0 material_final_print_temperature = =material_print_temperature - 21 material_flow = 105 material_initial_print_temperature = =material_print_temperature - 16 -material_print_temperature_layer_0 = =default_material_print_temperature + 2 +material_print_temperature_layer_0 = =material_print_temperature + 2 material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True From e75a2eaaf296a475037581075920ad2e39f32259 Mon Sep 17 00:00:00 2001 From: THeijmans Date: Fri, 20 Jul 2018 10:29:05 +0200 Subject: [PATCH 021/243] small error fixed with first layer print temperature Set the first layer temperature 2 degrees too high --- .../quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg index 9535685efe..0c94b64159 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg @@ -30,7 +30,7 @@ material_final_print_temperature = =material_print_temperature - 21 material_flow = 105 material_initial_print_temperature = =material_print_temperature - 16 material_print_temperature = =default_material_print_temperature + 2 -material_print_temperature_layer_0 = =material_print_temperature + 2 +material_print_temperature_layer_0 = =material_print_temperature material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True From 97dad9c1c4d5273ee56ad61aef6e2d3cb0276666 Mon Sep 17 00:00:00 2001 From: kaleidoscopeit Date: Fri, 20 Jul 2018 12:38:19 +0200 Subject: [PATCH 022/243] Updated Deltacomb 3D machine and quality definitions --- resources/definitions/deltacomb.def.json | 5 +- ...g => deltacomb_abs_Draft_Quality.inst.cfg} | 12 ++-- ...fg => deltacomb_abs_Fast_Quality.inst.cfg} | 11 ++-- .../deltacomb_abs_High_Quality.inst.cfg | 25 ++++++++ ... => deltacomb_abs_Normal_Quality.inst.cfg} | 11 ++-- .../deltacomb_abs_Superdraft_Quality.inst.cfg | 25 ++++++++ .../deltacomb_abs_Verydraft_Quality.inst.cfg | 25 ++++++++ .../deltacomb_global_Draft_Quality.inst.cfg | 14 +++++ .../deltacomb_global_Fast_Quality.inst.cfg | 14 +++++ .../deltacomb_global_High_Quality.inst.cfg | 14 +++++ .../deltacomb_global_Normal_Quality.inst.cfg | 14 +++++ ...ltacomb_global_Superdraft_Quality.inst.cfg | 14 +++++ ...eltacomb_global_Verydraft_Quality.inst.cfg | 14 +++++ .../deltacomb/deltacomb_nylon_fast.inst.cfg | 57 ------------------- .../deltacomb/deltacomb_nylon_high.inst.cfg | 57 ------------------- .../deltacomb/deltacomb_nylon_normal.inst.cfg | 57 ------------------- ...g => deltacomb_pla_Draft_Quality.inst.cfg} | 11 ++-- ...fg => deltacomb_pla_Fast_Quality.inst.cfg} | 11 ++-- .../deltacomb_pla_High_Quality.inst.cfg | 24 ++++++++ ... => deltacomb_pla_Normal_Quality.inst.cfg} | 10 ++-- .../deltacomb_pla_Superdraft_Quality.inst.cfg | 24 ++++++++ .../deltacomb_pla_Verydraft_Quality.inst.cfg | 24 ++++++++ 22 files changed, 271 insertions(+), 202 deletions(-) rename resources/quality/deltacomb/{deltacomb_abs_fast.inst.cfg => deltacomb_abs_Draft_Quality.inst.cfg} (66%) rename resources/quality/deltacomb/{deltacomb_abs_normal.inst.cfg => deltacomb_abs_Fast_Quality.inst.cfg} (66%) create mode 100644 resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg rename resources/quality/deltacomb/{deltacomb_abs_high.inst.cfg => deltacomb_abs_Normal_Quality.inst.cfg} (66%) create mode 100644 resources/quality/deltacomb/deltacomb_abs_Superdraft_Quality.inst.cfg create mode 100644 resources/quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg create mode 100755 resources/quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg create mode 100755 resources/quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg create mode 100755 resources/quality/deltacomb/deltacomb_global_High_Quality.inst.cfg create mode 100755 resources/quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg create mode 100755 resources/quality/deltacomb/deltacomb_global_Superdraft_Quality.inst.cfg create mode 100755 resources/quality/deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg delete mode 100644 resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg delete mode 100644 resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg delete mode 100644 resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg rename resources/quality/deltacomb/{deltacomb_pla_fast.inst.cfg => deltacomb_pla_Draft_Quality.inst.cfg} (64%) rename resources/quality/deltacomb/{deltacomb_pla_normal.inst.cfg => deltacomb_pla_Fast_Quality.inst.cfg} (63%) create mode 100644 resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg rename resources/quality/deltacomb/{deltacomb_pla_high.inst.cfg => deltacomb_pla_Normal_Quality.inst.cfg} (79%) create mode 100644 resources/quality/deltacomb/deltacomb_pla_Superdraft_Quality.inst.cfg create mode 100644 resources/quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg diff --git a/resources/definitions/deltacomb.def.json b/resources/definitions/deltacomb.def.json index f1114583c0..1eb816b945 100644 --- a/resources/definitions/deltacomb.def.json +++ b/resources/definitions/deltacomb.def.json @@ -52,6 +52,9 @@ "top_bottom_thickness": { "default_value": 0.6 }, "support_z_distance": { "value": "layer_height * 2" }, "support_bottom_distance": { "value": "layer_height" }, - "support_use_towers" : { "default_value": false } + "support_use_towers" : { "default_value": false }, + "jerk_wall_0" : { "value": "30" }, + "jerk_travel" : { "default_value": 20 }, + "acceleration_travel" : { "value": 10000 } } } diff --git a/resources/quality/deltacomb/deltacomb_abs_fast.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Draft_Quality.inst.cfg similarity index 66% rename from resources/quality/deltacomb/deltacomb_abs_fast.inst.cfg rename to resources/quality/deltacomb/deltacomb_abs_Draft_Quality.inst.cfg index 87d4031f28..1a3d0ceb1e 100644 --- a/resources/quality/deltacomb/deltacomb_abs_fast.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_Draft_Quality.inst.cfg @@ -1,13 +1,13 @@ [general] version = 4 +name = Fast (beta) definition = deltacomb -name = Fast Quality (beta) [metadata] -setting_version = 5 +setting_version = 4 type = quality -quality_type = fast -weight = -1 +quality_type = draft +weight = -2 material = generic_abs [values] @@ -19,6 +19,8 @@ cool_fan_full_at_height = 0.4 cool_fan_speed = 50 cool_fan_speed_max = 50 cool_fan_speed_min = 50 -cool_min_layer_time = 3 +cool_min_layer_time = 5 cool_min_speed = 20 material_bed_temperature = 80 +material_print_temperature_layer_0 = =default_material_print_temperature + 5 + diff --git a/resources/quality/deltacomb/deltacomb_abs_normal.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Fast_Quality.inst.cfg similarity index 66% rename from resources/quality/deltacomb/deltacomb_abs_normal.inst.cfg rename to resources/quality/deltacomb/deltacomb_abs_Fast_Quality.inst.cfg index a5069cd827..ed47c1d4d5 100644 --- a/resources/quality/deltacomb/deltacomb_abs_normal.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_Fast_Quality.inst.cfg @@ -1,13 +1,13 @@ [general] version = 4 +name = Normal (beta) definition = deltacomb -name = Normal Quality (beta) [metadata] -setting_version = 5 +setting_version = 4 type = quality -quality_type = normal -weight = 0 +quality_type = fast +weight = -1 material = generic_abs [values] @@ -19,6 +19,7 @@ cool_fan_full_at_height = 0.3 cool_fan_speed = 50 cool_fan_speed_max = 50 cool_fan_speed_min = 50 -cool_min_layer_time = 3 +cool_min_layer_time = 5 cool_min_speed = 20 material_bed_temperature = 80 +material_print_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg new file mode 100644 index 0000000000..2fc0db1aff --- /dev/null +++ b/resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg @@ -0,0 +1,25 @@ +[general] +version = 4 +name = Extra Fine (beta) +definition = deltacomb + +[metadata] +setting_version = 4 +type = quality +quality_type = high +weight = 0 +material = generic_abs + +[values] +adhesion_type = raft +layer_height = 0.05 +layer_height_0 = 0.05 +cool_fan_enabled = True +cool_fan_full_at_height = 0.1 +cool_fan_speed = 50 +cool_fan_speed_max = 50 +cool_fan_speed_min = 50 +cool_min_layer_time = 5 +cool_min_speed = 20 +material_bed_temperature = 80 +material_print_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/deltacomb/deltacomb_abs_high.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Normal_Quality.inst.cfg similarity index 66% rename from resources/quality/deltacomb/deltacomb_abs_high.inst.cfg rename to resources/quality/deltacomb/deltacomb_abs_Normal_Quality.inst.cfg index f24b6f9662..22ea1dde21 100644 --- a/resources/quality/deltacomb/deltacomb_abs_high.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_Normal_Quality.inst.cfg @@ -1,13 +1,13 @@ [general] version = 4 +name = Fine (beta) definition = deltacomb -name = High Quality (beta) [metadata] -setting_version = 5 +setting_version = 4 type = quality -quality_type = high -weight = 1 +quality_type = normal +weight = 0 material = generic_abs [values] @@ -19,6 +19,7 @@ cool_fan_full_at_height = 0.2 cool_fan_speed = 50 cool_fan_speed_max = 50 cool_fan_speed_min = 50 -cool_min_layer_time = 3 +cool_min_layer_time = 5 cool_min_speed = 20 material_bed_temperature = 80 +material_print_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/deltacomb/deltacomb_abs_Superdraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Superdraft_Quality.inst.cfg new file mode 100644 index 0000000000..408be4dbc9 --- /dev/null +++ b/resources/quality/deltacomb/deltacomb_abs_Superdraft_Quality.inst.cfg @@ -0,0 +1,25 @@ +[general] +version = 4 +name = Sprint (beta) +definition = deltacomb + +[metadata] +setting_version = 4 +type = quality +quality_type = superdraft +weight = -4 +material = generic_abs + +[values] +adhesion_type = raft +layer_height = 0.4 +layer_height_0 = 0.4 +cool_fan_enabled = True +cool_fan_full_at_height = 0.8 +cool_fan_speed = 50 +cool_fan_speed_max = 50 +cool_fan_speed_min = 50 +cool_min_layer_time = 5 +cool_min_speed = 20 +material_bed_temperature = 80 +material_print_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg new file mode 100644 index 0000000000..0d231b4776 --- /dev/null +++ b/resources/quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg @@ -0,0 +1,25 @@ +[general] +version = 4 +name = Extra Fast (beta) +definition = deltacomb + +[metadata] +setting_version = 4 +type = quality +quality_type = verydraft +weight = -3 +material = generic_abs + +[values] +adhesion_type = raft +layer_height = 0.3 +layer_height_0 = 0.3 +cool_fan_enabled = True +cool_fan_full_at_height = 0.6 +cool_fan_speed = 50 +cool_fan_speed_max = 50 +cool_fan_speed_min = 50 +cool_min_layer_time = 5 +cool_min_speed = 20 +material_bed_temperature = 80 +material_print_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg new file mode 100755 index 0000000000..2f8b6ae80d --- /dev/null +++ b/resources/quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Fast +definition = deltacomb + +[metadata] +setting_version = 4 +type = quality +quality_type = draft +weight = -2 +global_quality = True + +[values] +layer_height = 0.2 diff --git a/resources/quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg new file mode 100755 index 0000000000..0483503583 --- /dev/null +++ b/resources/quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Normal +definition = deltacomb + +[metadata] +setting_version = 4 +type = quality +quality_type = fast +weight = -1 +global_quality = True + +[values] +layer_height = 0.15 diff --git a/resources/quality/deltacomb/deltacomb_global_High_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_High_Quality.inst.cfg new file mode 100755 index 0000000000..ce1e787847 --- /dev/null +++ b/resources/quality/deltacomb/deltacomb_global_High_Quality.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Extra Fine +definition = deltacomb + +[metadata] +setting_version = 4 +type = quality +quality_type = high +weight = 0 +global_quality = True + +[values] +layer_height = 0.06 diff --git a/resources/quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg new file mode 100755 index 0000000000..817fdf62b5 --- /dev/null +++ b/resources/quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Fine +definition = deltacomb + +[metadata] +setting_version = 4 +type = quality +quality_type = normal +weight = 0 +global_quality = True + +[values] +layer_height = 0.1 diff --git a/resources/quality/deltacomb/deltacomb_global_Superdraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Superdraft_Quality.inst.cfg new file mode 100755 index 0000000000..ab211efc24 --- /dev/null +++ b/resources/quality/deltacomb/deltacomb_global_Superdraft_Quality.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Sprint +definition = deltacomb + +[metadata] +setting_version = 4 +type = quality +quality_type = superdraft +weight = -4 +global_quality = True + +[values] +layer_height = 0.4 diff --git a/resources/quality/deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg new file mode 100755 index 0000000000..687cda0aa6 --- /dev/null +++ b/resources/quality/deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Extra Fast +definition = deltacomb + +[metadata] +setting_version = 4 +type = quality +quality_type = verydraft +weight = -3 +global_quality = True + +[values] +layer_height = 0.3 diff --git a/resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg b/resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg deleted file mode 100644 index 0deac00593..0000000000 --- a/resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg +++ /dev/null @@ -1,57 +0,0 @@ -[general] -version = 4 -name = Fast Quality (beta) -definition = deltacomb - -[metadata] -setting_version = 5 -type = quality -quality_type = fast -weight = -1 -material = generic_nylon - -[values] -adhesion_type = raft -brim_width = 4 -cool_fan_enabled = False -cool_fan_full_at_height = 0.45 -cool_fan_speed = 0 -cool_fan_speed_max = 0 -cool_fan_speed_min = 0 -cool_min_layer_time = 5 -cool_min_speed = 0 -infill_overlap = 15 -infill_sparse_density = 24 -layer_height = 0.20 -layer_height_0 = 0.15 -line_width = =machine_nozzle_size -material_flow = 100 -raft_airgap = 0.22 -raft_base_line_width= =line_width * 2 -raft_base_thickness = =layer_height_0 * 2 -raft_interface_line_width = =line_width -raft_interface_thickness = =layer_height -raft_margin = 5 -raft_surface_layers = 2 -raft_surface_line_width = =line_width -raft_surface_thickness = =layer_height -retraction_hop = 0.5 -retraction_hop_enabled = False -retraction_hop_only_when_collides = True -skin_overlap = 10 -skirt_brim_minimal_length = 75 -skirt_gap = 1.5 -skirt_line_count = 5 -speed_infill = =speed_print -speed_layer_0 = =math.ceil(speed_print * 25 / 50) -speed_print = 50 -speed_topbottom = =math.ceil(speed_print * 40 / 50) -speed_travel = 200 -speed_wall_0 = =math.ceil(speed_print * 40 / 50) -speed_wall_x = =speed_print -support_angle = 70 -support_type = buildplate -support_z_distance = 0.15 -top_bottom_thickness = 0.8 -wall_thickness = 0.8 -z_seam_type = random diff --git a/resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg b/resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg deleted file mode 100644 index a5d00b40e7..0000000000 --- a/resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg +++ /dev/null @@ -1,57 +0,0 @@ -[general] -version = 4 -name = High Quality (beta) -definition = deltacomb - -[metadata] -setting_version = 5 -type = quality -quality_type = high -weight = 1 -material = generic_nylon - -[values] -adhesion_type = raft -brim_width = 4 -cool_fan_enabled = False -cool_fan_full_at_height = 0.45 -cool_fan_speed = 0 -cool_fan_speed_max = 0 -cool_fan_speed_min = 0 -cool_min_layer_time = 5 -cool_min_speed = 0 -infill_overlap = 15 -infill_sparse_density = 24 -layer_height = 0.10 -layer_height_0 = 0.10 -line_width = =machine_nozzle_size -material_flow = 100 -raft_airgap = 0.22 -raft_base_line_width= =line_width * 2 -raft_base_thickness = =layer_height_0 * 2 -raft_interface_line_width = =line_width -raft_interface_thickness = =layer_height -raft_margin = 5 -raft_surface_layers = 2 -raft_surface_line_width = =line_width -raft_surface_thickness = =layer_height -retraction_hop = 0.5 -retraction_hop_enabled = False -retraction_hop_only_when_collides = True -skin_overlap = 10 -skirt_brim_minimal_length = 75 -skirt_gap = 1.5 -skirt_line_count = 5 -speed_infill = =speed_print -speed_layer_0 = =math.ceil(speed_print * 25 / 50) -speed_print = 50 -speed_topbottom = =math.ceil(speed_print * 40 / 50) -speed_travel = 200 -speed_wall_0 = =math.ceil(speed_print * 40 / 50) -speed_wall_x = =speed_print -support_angle = 70 -support_type = buildplate -support_z_distance = 0.15 -top_bottom_thickness = 0.8 -wall_thickness = 0.8 -z_seam_type = random diff --git a/resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg b/resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg deleted file mode 100644 index 06e79c8dc2..0000000000 --- a/resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg +++ /dev/null @@ -1,57 +0,0 @@ -[general] -version = 4 -name = Normal Quality (beta) -definition = deltacomb - -[metadata] -setting_version = 5 -type = quality -quality_type = normal -weight = 0 -material = generic_nylon - -[values] -adhesion_type = raft -brim_width = 4 -cool_fan_enabled = False -cool_fan_full_at_height = 0.45 -cool_fan_speed = 0 -cool_fan_speed_max = 0 -cool_fan_speed_min = 0 -cool_min_layer_time = 5 -cool_min_speed = 0 -infill_overlap = 15 -infill_sparse_density = 24 -layer_height = 0.15 -layer_height_0 = 0.10 -line_width = =machine_nozzle_size -material_flow = 100 -raft_airgap = 0.22 -raft_base_line_width= =line_width * 2 -raft_base_thickness = =layer_height_0 * 2 -raft_interface_line_width = =line_width -raft_interface_thickness = =layer_height -raft_margin = 5 -raft_surface_layers = 2 -raft_surface_line_width = =line_width -raft_surface_thickness = =layer_height -retraction_hop = 0.5 -retraction_hop_enabled = False -retraction_hop_only_when_collides = True -skin_overlap = 10 -skirt_brim_minimal_length = 75 -skirt_gap = 1.5 -skirt_line_count = 5 -speed_infill = =speed_print -speed_layer_0 = =math.ceil(speed_print * 25 / 50) -speed_print = 50 -speed_topbottom = =math.ceil(speed_print * 40 / 50) -speed_travel = 200 -speed_wall_0 = =math.ceil(speed_print * 40 / 50) -speed_wall_x = =speed_print -support_angle = 70 -support_type = buildplate -support_z_distance = 0.15 -top_bottom_thickness = 0.8 -wall_thickness = 0.8 -z_seam_type = random diff --git a/resources/quality/deltacomb/deltacomb_pla_fast.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Draft_Quality.inst.cfg similarity index 64% rename from resources/quality/deltacomb/deltacomb_pla_fast.inst.cfg rename to resources/quality/deltacomb/deltacomb_pla_Draft_Quality.inst.cfg index ea4a2908b3..d1f70b65fc 100644 --- a/resources/quality/deltacomb/deltacomb_pla_fast.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_Draft_Quality.inst.cfg @@ -1,13 +1,13 @@ [general] version = 4 +name = Fast definition = deltacomb -name = Fast Quality [metadata] -setting_version = 5 +setting_version = 4 type = quality -quality_type = fast -weight = -1 +quality_type = draft +weight = -2 material = generic_pla [values] @@ -15,9 +15,10 @@ adhesion_type = skirt layer_height = 0.2 layer_height_0 = 0.2 cool_fan_enabled = True -cool_fan_full_at_height = 0.4 +cool_fan_full_at_height = 0.2 cool_fan_speed = 100 cool_fan_speed_max = 100 cool_fan_speed_min = 100 cool_min_layer_time = 5 cool_min_speed = 20 +material_print_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/deltacomb/deltacomb_pla_normal.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Fast_Quality.inst.cfg similarity index 63% rename from resources/quality/deltacomb/deltacomb_pla_normal.inst.cfg rename to resources/quality/deltacomb/deltacomb_pla_Fast_Quality.inst.cfg index 2e9dca5c25..e0899d65c7 100644 --- a/resources/quality/deltacomb/deltacomb_pla_normal.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_Fast_Quality.inst.cfg @@ -1,13 +1,13 @@ [general] version = 4 +name = Normal definition = deltacomb -name = Normal Quality [metadata] -setting_version = 5 +setting_version = 4 type = quality -quality_type = normal -weight = 0 +quality_type = fast +weight = -1 material = generic_pla [values] @@ -15,9 +15,10 @@ adhesion_type = skirt layer_height = 0.15 layer_height_0 = 0.15 cool_fan_enabled = True -cool_fan_full_at_height = 0.3 +cool_fan_full_at_height = 0.15 cool_fan_speed = 100 cool_fan_speed_max = 100 cool_fan_speed_min = 100 cool_min_layer_time = 5 cool_min_speed = 20 +material_print_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg new file mode 100644 index 0000000000..c46b2639ca --- /dev/null +++ b/resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg @@ -0,0 +1,24 @@ +[general] +version = 4 +name = Extra Fine +definition = deltacomb + +[metadata] +setting_version = 4 +type = quality +quality_type = high +weight = 0 +material = generic_pla + +[values] +adhesion_type = skirt +layer_height = 0.05 +layer_height_0 = 0.05 +cool_fan_enabled = True +cool_fan_full_at_height = 0.05 +cool_fan_speed = 100 +cool_fan_speed_max = 100 +cool_fan_speed_min = 100 +cool_min_layer_time = 5 +cool_min_speed = 20 +material_print_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/deltacomb/deltacomb_pla_high.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Normal_Quality.inst.cfg similarity index 79% rename from resources/quality/deltacomb/deltacomb_pla_high.inst.cfg rename to resources/quality/deltacomb/deltacomb_pla_Normal_Quality.inst.cfg index 69f8478cfe..9aaaf294e0 100644 --- a/resources/quality/deltacomb/deltacomb_pla_high.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_Normal_Quality.inst.cfg @@ -1,13 +1,13 @@ [general] version = 4 +name = Fine definition = deltacomb -name = High Quality [metadata] -setting_version = 5 +setting_version = 4 type = quality -quality_type = high -weight = 1 +quality_type = normal +weight = 0 material = generic_pla [values] @@ -15,7 +15,7 @@ adhesion_type = skirt layer_height = 0.1 layer_height_0 = 0.1 cool_fan_enabled = True -cool_fan_full_at_height = 0.2 +cool_fan_full_at_height = 0.1 cool_fan_speed = 100 cool_fan_speed_max = 100 cool_fan_speed_min = 100 diff --git a/resources/quality/deltacomb/deltacomb_pla_Superdraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Superdraft_Quality.inst.cfg new file mode 100644 index 0000000000..88ed9a13bd --- /dev/null +++ b/resources/quality/deltacomb/deltacomb_pla_Superdraft_Quality.inst.cfg @@ -0,0 +1,24 @@ +[general] +version = 4 +name = Sprint +definition = deltacomb + +[metadata] +setting_version = 4 +type = quality +quality_type = superdraft +weight = -4 +material = generic_pla + +[values] +adhesion_type = skirt +layer_height = 0.4 +layer_height_0 = 0.4 +cool_fan_enabled = True +cool_fan_full_at_height = 0.4 +cool_fan_speed = 100 +cool_fan_speed_max = 100 +cool_fan_speed_min = 100 +cool_min_layer_time = 5 +cool_min_speed = 20 +material_print_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg new file mode 100644 index 0000000000..2c39b34e36 --- /dev/null +++ b/resources/quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg @@ -0,0 +1,24 @@ +[general] +version = 4 +name = Extra Fast +definition = deltacomb + +[metadata] +setting_version = 4 +type = quality +quality_type = verydraft +weight = -3 +material = generic_pla + +[values] +adhesion_type = skirt +layer_height = 0.3 +layer_height_0 = 0.3 +cool_fan_enabled = True +cool_fan_full_at_height = 0.3 +cool_fan_speed = 100 +cool_fan_speed_max = 100 +cool_fan_speed_min = 100 +cool_min_layer_time = 5 +cool_min_speed = 20 +material_print_temperature_layer_0 = =default_material_print_temperature + 5 From 94954ea40f06ee9dd7cc3553b6c8cd49b99cb317 Mon Sep 17 00:00:00 2001 From: kaleidoscopeit Date: Fri, 20 Jul 2018 16:41:48 +0200 Subject: [PATCH 023/243] Quality corrections in Deltacomb 3D --- resources/definitions/deltacomb.def.json | 4 +-- .../deltacomb_abs_Draft_Quality.inst.cfg | 4 +-- .../deltacomb_abs_Fast_Quality.inst.cfg | 4 +-- .../deltacomb_abs_High_Quality.inst.cfg | 4 +-- .../deltacomb_abs_Normal_Quality.inst.cfg | 4 +-- .../deltacomb_abs_Superdraft_Quality.inst.cfg | 25 ------------------- .../deltacomb_abs_Verydraft_Quality.inst.cfg | 4 +-- .../deltacomb_global_Draft_Quality.inst.cfg | 1 + .../deltacomb_global_Fast_Quality.inst.cfg | 1 + .../deltacomb_global_High_Quality.inst.cfg | 3 ++- .../deltacomb_global_Normal_Quality.inst.cfg | 1 + ...ltacomb_global_Superdraft_Quality.inst.cfg | 14 ----------- ...eltacomb_global_Verydraft_Quality.inst.cfg | 1 + .../deltacomb_pla_Draft_Quality.inst.cfg | 4 +-- .../deltacomb_pla_Fast_Quality.inst.cfg | 4 +-- .../deltacomb_pla_High_Quality.inst.cfg | 4 +-- .../deltacomb_pla_Normal_Quality.inst.cfg | 4 +-- .../deltacomb_pla_Superdraft_Quality.inst.cfg | 24 ------------------ .../deltacomb_pla_Verydraft_Quality.inst.cfg | 4 +-- 19 files changed, 18 insertions(+), 96 deletions(-) delete mode 100644 resources/quality/deltacomb/deltacomb_abs_Superdraft_Quality.inst.cfg delete mode 100755 resources/quality/deltacomb/deltacomb_global_Superdraft_Quality.inst.cfg delete mode 100644 resources/quality/deltacomb/deltacomb_pla_Superdraft_Quality.inst.cfg diff --git a/resources/definitions/deltacomb.def.json b/resources/definitions/deltacomb.def.json index 1eb816b945..a4b2d47a7b 100644 --- a/resources/definitions/deltacomb.def.json +++ b/resources/definitions/deltacomb.def.json @@ -34,7 +34,7 @@ "material_initial_print_temperature": { "value": "material_print_temperature" }, "material_print_temperature_layer_0": { "value": "material_print_temperature + 5" }, "travel_avoid_distance": { "default_value": 1, "value": "1" }, - "speed_print" : { "default_value": 60 }, + "speed_print" : { "default_value": 70 }, "speed_travel": { "value": "150.0" }, "speed_infill": { "value": "round(speed_print * 1.05, 0)" }, "speed_topbottom": { "value": "round(speed_print * 0.95, 0)" }, @@ -54,7 +54,7 @@ "support_bottom_distance": { "value": "layer_height" }, "support_use_towers" : { "default_value": false }, "jerk_wall_0" : { "value": "30" }, - "jerk_travel" : { "default_value": 20 }, + "jerk_travel" : { "default_value": 20 }, "acceleration_travel" : { "value": 10000 } } } diff --git a/resources/quality/deltacomb/deltacomb_abs_Draft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Draft_Quality.inst.cfg index 1a3d0ceb1e..fe16999e8c 100644 --- a/resources/quality/deltacomb/deltacomb_abs_Draft_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_Draft_Quality.inst.cfg @@ -12,10 +12,8 @@ material = generic_abs [values] adhesion_type = raft -layer_height = 0.2 -layer_height_0 = 0.2 cool_fan_enabled = True -cool_fan_full_at_height = 0.4 +cool_fan_full_at_height = =layer_height * 2 cool_fan_speed = 50 cool_fan_speed_max = 50 cool_fan_speed_min = 50 diff --git a/resources/quality/deltacomb/deltacomb_abs_Fast_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Fast_Quality.inst.cfg index ed47c1d4d5..82ba40c81b 100644 --- a/resources/quality/deltacomb/deltacomb_abs_Fast_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_Fast_Quality.inst.cfg @@ -12,10 +12,8 @@ material = generic_abs [values] adhesion_type = raft -layer_height = 0.15 -layer_height_0 = 0.15 cool_fan_enabled = True -cool_fan_full_at_height = 0.3 +cool_fan_full_at_height = =layer_height * 2 cool_fan_speed = 50 cool_fan_speed_max = 50 cool_fan_speed_min = 50 diff --git a/resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg index 2fc0db1aff..6f0b7fbb94 100644 --- a/resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg @@ -12,10 +12,8 @@ material = generic_abs [values] adhesion_type = raft -layer_height = 0.05 -layer_height_0 = 0.05 cool_fan_enabled = True -cool_fan_full_at_height = 0.1 +cool_fan_full_at_height = =layer_height * 2 cool_fan_speed = 50 cool_fan_speed_max = 50 cool_fan_speed_min = 50 diff --git a/resources/quality/deltacomb/deltacomb_abs_Normal_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Normal_Quality.inst.cfg index 22ea1dde21..b9a14d6128 100644 --- a/resources/quality/deltacomb/deltacomb_abs_Normal_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_Normal_Quality.inst.cfg @@ -12,10 +12,8 @@ material = generic_abs [values] adhesion_type = raft -layer_height = 0.1 -layer_height_0 = 0.1 cool_fan_enabled = True -cool_fan_full_at_height = 0.2 +cool_fan_full_at_height = =layer_height * 2 cool_fan_speed = 50 cool_fan_speed_max = 50 cool_fan_speed_min = 50 diff --git a/resources/quality/deltacomb/deltacomb_abs_Superdraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Superdraft_Quality.inst.cfg deleted file mode 100644 index 408be4dbc9..0000000000 --- a/resources/quality/deltacomb/deltacomb_abs_Superdraft_Quality.inst.cfg +++ /dev/null @@ -1,25 +0,0 @@ -[general] -version = 4 -name = Sprint (beta) -definition = deltacomb - -[metadata] -setting_version = 4 -type = quality -quality_type = superdraft -weight = -4 -material = generic_abs - -[values] -adhesion_type = raft -layer_height = 0.4 -layer_height_0 = 0.4 -cool_fan_enabled = True -cool_fan_full_at_height = 0.8 -cool_fan_speed = 50 -cool_fan_speed_max = 50 -cool_fan_speed_min = 50 -cool_min_layer_time = 5 -cool_min_speed = 20 -material_bed_temperature = 80 -material_print_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg index 0d231b4776..925473e933 100644 --- a/resources/quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg @@ -12,10 +12,8 @@ material = generic_abs [values] adhesion_type = raft -layer_height = 0.3 -layer_height_0 = 0.3 cool_fan_enabled = True -cool_fan_full_at_height = 0.6 +cool_fan_full_at_height = =layer_height * 2 cool_fan_speed = 50 cool_fan_speed_max = 50 cool_fan_speed_min = 50 diff --git a/resources/quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg index 2f8b6ae80d..71bc28185f 100755 --- a/resources/quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg @@ -12,3 +12,4 @@ global_quality = True [values] layer_height = 0.2 +layer_height_0 = =layer_height diff --git a/resources/quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg index 0483503583..0a1d1aa4bf 100755 --- a/resources/quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg @@ -12,3 +12,4 @@ global_quality = True [values] layer_height = 0.15 +layer_height_0 = =layer_height diff --git a/resources/quality/deltacomb/deltacomb_global_High_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_High_Quality.inst.cfg index ce1e787847..d8c10de5e3 100755 --- a/resources/quality/deltacomb/deltacomb_global_High_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_global_High_Quality.inst.cfg @@ -11,4 +11,5 @@ weight = 0 global_quality = True [values] -layer_height = 0.06 +layer_height = 0.05 +layer_height_0 = =layer_height * 2 diff --git a/resources/quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg index 817fdf62b5..2ae0c58845 100755 --- a/resources/quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg @@ -12,3 +12,4 @@ global_quality = True [values] layer_height = 0.1 +layer_height_0 = =layer_height * 2 diff --git a/resources/quality/deltacomb/deltacomb_global_Superdraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Superdraft_Quality.inst.cfg deleted file mode 100755 index ab211efc24..0000000000 --- a/resources/quality/deltacomb/deltacomb_global_Superdraft_Quality.inst.cfg +++ /dev/null @@ -1,14 +0,0 @@ -[general] -version = 4 -name = Sprint -definition = deltacomb - -[metadata] -setting_version = 4 -type = quality -quality_type = superdraft -weight = -4 -global_quality = True - -[values] -layer_height = 0.4 diff --git a/resources/quality/deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg index 687cda0aa6..4dd79b6a5e 100755 --- a/resources/quality/deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg @@ -12,3 +12,4 @@ global_quality = True [values] layer_height = 0.3 +layer_height_0 = =layer_height diff --git a/resources/quality/deltacomb/deltacomb_pla_Draft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Draft_Quality.inst.cfg index d1f70b65fc..109b241a1f 100644 --- a/resources/quality/deltacomb/deltacomb_pla_Draft_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_Draft_Quality.inst.cfg @@ -12,10 +12,8 @@ material = generic_pla [values] adhesion_type = skirt -layer_height = 0.2 -layer_height_0 = 0.2 cool_fan_enabled = True -cool_fan_full_at_height = 0.2 +cool_fan_full_at_height = =layer_height cool_fan_speed = 100 cool_fan_speed_max = 100 cool_fan_speed_min = 100 diff --git a/resources/quality/deltacomb/deltacomb_pla_Fast_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Fast_Quality.inst.cfg index e0899d65c7..32e49fb209 100644 --- a/resources/quality/deltacomb/deltacomb_pla_Fast_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_Fast_Quality.inst.cfg @@ -12,10 +12,8 @@ material = generic_pla [values] adhesion_type = skirt -layer_height = 0.15 -layer_height_0 = 0.15 cool_fan_enabled = True -cool_fan_full_at_height = 0.15 +cool_fan_full_at_height = =layer_height cool_fan_speed = 100 cool_fan_speed_max = 100 cool_fan_speed_min = 100 diff --git a/resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg index c46b2639ca..3c3fa9513f 100644 --- a/resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg @@ -12,10 +12,8 @@ material = generic_pla [values] adhesion_type = skirt -layer_height = 0.05 -layer_height_0 = 0.05 cool_fan_enabled = True -cool_fan_full_at_height = 0.05 +cool_fan_full_at_height = =layer_height cool_fan_speed = 100 cool_fan_speed_max = 100 cool_fan_speed_min = 100 diff --git a/resources/quality/deltacomb/deltacomb_pla_Normal_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Normal_Quality.inst.cfg index 9aaaf294e0..c836c6a5a6 100644 --- a/resources/quality/deltacomb/deltacomb_pla_Normal_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_Normal_Quality.inst.cfg @@ -12,10 +12,8 @@ material = generic_pla [values] adhesion_type = skirt -layer_height = 0.1 -layer_height_0 = 0.1 cool_fan_enabled = True -cool_fan_full_at_height = 0.1 +cool_fan_full_at_height = =layer_height cool_fan_speed = 100 cool_fan_speed_max = 100 cool_fan_speed_min = 100 diff --git a/resources/quality/deltacomb/deltacomb_pla_Superdraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Superdraft_Quality.inst.cfg deleted file mode 100644 index 88ed9a13bd..0000000000 --- a/resources/quality/deltacomb/deltacomb_pla_Superdraft_Quality.inst.cfg +++ /dev/null @@ -1,24 +0,0 @@ -[general] -version = 4 -name = Sprint -definition = deltacomb - -[metadata] -setting_version = 4 -type = quality -quality_type = superdraft -weight = -4 -material = generic_pla - -[values] -adhesion_type = skirt -layer_height = 0.4 -layer_height_0 = 0.4 -cool_fan_enabled = True -cool_fan_full_at_height = 0.4 -cool_fan_speed = 100 -cool_fan_speed_max = 100 -cool_fan_speed_min = 100 -cool_min_layer_time = 5 -cool_min_speed = 20 -material_print_temperature_layer_0 = =default_material_print_temperature + 5 diff --git a/resources/quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg index 2c39b34e36..64c84fa3a9 100644 --- a/resources/quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg @@ -12,10 +12,8 @@ material = generic_pla [values] adhesion_type = skirt -layer_height = 0.3 -layer_height_0 = 0.3 cool_fan_enabled = True -cool_fan_full_at_height = 0.3 +cool_fan_full_at_height = =layer_height cool_fan_speed = 100 cool_fan_speed_max = 100 cool_fan_speed_min = 100 From a883c9ebb07a5dadca8bbc039931b6d380e2a409 Mon Sep 17 00:00:00 2001 From: kaleidoscopeit Date: Fri, 20 Jul 2018 16:57:59 +0200 Subject: [PATCH 024/243] settings_vesion to 5 in quality --- .../quality/deltacomb/deltacomb_abs_Draft_Quality.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_abs_Fast_Quality.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg | 2 +- .../quality/deltacomb/deltacomb_abs_Normal_Quality.inst.cfg | 2 +- .../quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg | 2 +- .../quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg | 2 +- .../quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg | 2 +- .../quality/deltacomb/deltacomb_global_High_Quality.inst.cfg | 2 +- .../quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg | 2 +- .../deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg | 2 +- .../quality/deltacomb/deltacomb_pla_Draft_Quality.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_pla_Fast_Quality.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg | 2 +- .../quality/deltacomb/deltacomb_pla_Normal_Quality.inst.cfg | 2 +- .../quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/resources/quality/deltacomb/deltacomb_abs_Draft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Draft_Quality.inst.cfg index fe16999e8c..f540400575 100644 --- a/resources/quality/deltacomb/deltacomb_abs_Draft_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_Draft_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Fast (beta) definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = draft weight = -2 diff --git a/resources/quality/deltacomb/deltacomb_abs_Fast_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Fast_Quality.inst.cfg index 82ba40c81b..2214813913 100644 --- a/resources/quality/deltacomb/deltacomb_abs_Fast_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_Fast_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Normal (beta) definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = fast weight = -1 diff --git a/resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg index 6f0b7fbb94..c196209553 100644 --- a/resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_High_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Extra Fine (beta) definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = high weight = 0 diff --git a/resources/quality/deltacomb/deltacomb_abs_Normal_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Normal_Quality.inst.cfg index b9a14d6128..332e1890c6 100644 --- a/resources/quality/deltacomb/deltacomb_abs_Normal_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_Normal_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Fine (beta) definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = normal weight = 0 diff --git a/resources/quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg index 925473e933..674174c0bd 100644 --- a/resources/quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_Verydraft_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Extra Fast (beta) definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = verydraft weight = -3 diff --git a/resources/quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg index 71bc28185f..f8887810d5 100755 --- a/resources/quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_global_Draft_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Fast definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = draft weight = -2 diff --git a/resources/quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg index 0a1d1aa4bf..99030a084b 100755 --- a/resources/quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_global_Fast_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Normal definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = fast weight = -1 diff --git a/resources/quality/deltacomb/deltacomb_global_High_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_High_Quality.inst.cfg index d8c10de5e3..d6d853466a 100755 --- a/resources/quality/deltacomb/deltacomb_global_High_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_global_High_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Extra Fine definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = high weight = 0 diff --git a/resources/quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg index 2ae0c58845..a3bafadeec 100755 --- a/resources/quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_global_Normal_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Fine definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = normal weight = 0 diff --git a/resources/quality/deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg index 4dd79b6a5e..84c6e66f61 100755 --- a/resources/quality/deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_global_Verydraft_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Extra Fast definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = verydraft weight = -3 diff --git a/resources/quality/deltacomb/deltacomb_pla_Draft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Draft_Quality.inst.cfg index 109b241a1f..c4f884486e 100644 --- a/resources/quality/deltacomb/deltacomb_pla_Draft_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_Draft_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Fast definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = draft weight = -2 diff --git a/resources/quality/deltacomb/deltacomb_pla_Fast_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Fast_Quality.inst.cfg index 32e49fb209..714d4e3517 100644 --- a/resources/quality/deltacomb/deltacomb_pla_Fast_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_Fast_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Normal definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = fast weight = -1 diff --git a/resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg index 3c3fa9513f..774b8969c0 100644 --- a/resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_High_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Extra Fine definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = high weight = 0 diff --git a/resources/quality/deltacomb/deltacomb_pla_Normal_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Normal_Quality.inst.cfg index c836c6a5a6..58470ed650 100644 --- a/resources/quality/deltacomb/deltacomb_pla_Normal_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_Normal_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Fine definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = normal weight = 0 diff --git a/resources/quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg index 64c84fa3a9..9c00877c24 100644 --- a/resources/quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_Verydraft_Quality.inst.cfg @@ -4,7 +4,7 @@ name = Extra Fast definition = deltacomb [metadata] -setting_version = 4 +setting_version = 5 type = quality quality_type = verydraft weight = -3 From 75d8cba8a91c1275eb84059b2752cb34448227cc Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 24 Jul 2018 09:09:26 +0200 Subject: [PATCH 025/243] Fix start g-code of Monoprice Select Mini v2 Apparently the original start code caused it to move outside the build volume or beyond the limit in the Y direction. Fixes #3924. --- resources/definitions/monoprice_select_mini_v2.def.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/definitions/monoprice_select_mini_v2.def.json b/resources/definitions/monoprice_select_mini_v2.def.json index 4e3d63044e..bed4fb1adb 100644 --- a/resources/definitions/monoprice_select_mini_v2.def.json +++ b/resources/definitions/monoprice_select_mini_v2.def.json @@ -20,6 +20,10 @@ "overrides": { "machine_name": { "default_value": "Monoprice Select Mini V2" }, + "machine_end_gcode": + { + "default_value": "G0 X0 Y120;(Stick out the part)\nM190 S0;(Turn off heat bed, don't wait.)\nG92 E10;(Set extruder to 10)\nG1 E7 F200;(retract 3mm)\nM104 S0;(Turn off nozzle, don't wait)\nG4 S300;(Delay 5 minutes)\nM107;(Turn off part fan)\nM84;(Turn off stepper motors.)" + }, "adhesion_type": { "default_value": "brim" }, "retraction_combing": { "default_value": "noskin" }, "retraction_amount" : { "default_value": 2.5}, From 988de2b68c7681d1aa7b3a163cc17d21d6f44070 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 24 Jul 2018 09:09:54 +0200 Subject: [PATCH 026/243] Fix z-fighting with build plate mesh --- resources/definitions/malyan_m200.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/malyan_m200.def.json b/resources/definitions/malyan_m200.def.json index b3b0651e1a..f2c01b3831 100644 --- a/resources/definitions/malyan_m200.def.json +++ b/resources/definitions/malyan_m200.def.json @@ -9,6 +9,7 @@ "category": "Other", "file_formats": "text/x-gcode", "platform": "malyan_m200_platform.stl", + "platform_offset": [0, -0.25, 0], "has_machine_quality": true, "has_materials": true, "preferred_quality_type": "normal", From 296b74b03244ee4ca42c934c8feb43c6c69bb76c Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 24 Jul 2018 10:48:52 +0200 Subject: [PATCH 027/243] Set negative values to retraction in the filament change script. Fixes #4114 --- plugins/PostProcessingPlugin/scripts/FilamentChange.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/FilamentChange.py b/plugins/PostProcessingPlugin/scripts/FilamentChange.py index 1246bc8b43..0fa52de4f1 100644 --- a/plugins/PostProcessingPlugin/scripts/FilamentChange.py +++ b/plugins/PostProcessingPlugin/scripts/FilamentChange.py @@ -58,10 +58,10 @@ class FilamentChange(Script): color_change = "M600" if initial_retract is not None and initial_retract > 0.: - color_change = color_change + (" E%.2f" % initial_retract) + color_change = color_change + (" E-%.2f" % initial_retract) if later_retract is not None and later_retract > 0.: - color_change = color_change + (" L%.2f" % later_retract) + color_change = color_change + (" L-%.2f" % later_retract) color_change = color_change + " ; Generated by FilamentChange plugin" From 795dc9b9e1df32df053cfa45bc3e775251f170d3 Mon Sep 17 00:00:00 2001 From: milkok Date: Tue, 24 Jul 2018 17:08:15 +0800 Subject: [PATCH 028/243] Create winbo_superhelper105.def.json --- .../definitions/winbo_superhelper105.def.json | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 resources/definitions/winbo_superhelper105.def.json diff --git a/resources/definitions/winbo_superhelper105.def.json b/resources/definitions/winbo_superhelper105.def.json new file mode 100644 index 0000000000..f51d5d9070 --- /dev/null +++ b/resources/definitions/winbo_superhelper105.def.json @@ -0,0 +1,127 @@ +{ + "version": 2, + "name": "Winbo Super Helper 105", + "inherits": "fdmprinter", + "metadata": { + "author": "Winbo", + "manufacturer": "Winbo Smart Tech Co., Ltd.", + "category": "Other", + "visible": true, + "file_formats": "text/x-gcode", + "supports_usb_connection": true, + "machine_extruder_trains": + { + "0": "winbo_superhelper105_extruder" + } + }, + + "overrides": { + "machine_name": { "default_value": "Winbo Super Helper 105" }, + "machine_width": { "default_value": 108 }, + "machine_depth": { "default_value": 108 }, + "machine_height": { "default_value": 158 }, + "machine_heated_bed": { "default_value": false }, + "material_bed_temp_wait": { "default_value": false }, + "machine_filament_park_distance": { "value": "machine_heat_zone_length" }, + "machine_nozzle_heat_up_speed": { "default_value": 1.4 }, + "machine_nozzle_cool_down_speed": { "default_value": 0.8 }, + "machine_head_with_fans_polygon": + { + "default_value": + [ + [ -110, 50 ],[ -110, -30 ],[ 110, -30 ],[ 110, 50 ] + ] + }, + "machine_gcode_flavor": { "default_value": "Marlin" }, + "machine_max_feedrate_x": { "default_value": 250 }, + "machine_max_feedrate_y": { "default_value": 200 }, + "machine_max_feedrate_z": { "default_value": 40 }, + "machine_acceleration": { "default_value": 2000 }, + "gantry_height": { "default_value": 200 }, + "machine_extruder_count": { "default_value": 1 }, + "machine_start_gcode": { "default_value": "G21\nG90\nM82\nM107\nG28 X0 Y0\nG28 Z0\nG1 F6000 Z0.3\nG92 E0\nG1 F1000 X30 E8\nG92 E0\nM117 Printing." }, + "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\nG92 E2\nG1 E0 F200\nG28 X0 Y0\nM84 X Y E" }, + "material_diameter": { "default_value": 1.75 }, + "prime_blob_enable": { "enabled": true }, + "acceleration_enabled": { "value": "True" }, + "acceleration_layer_0": { "value": "acceleration_topbottom" }, + "acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" }, + "acceleration_print": { "value": "2000" }, + "acceleration_travel": { "value": "1500" }, + "acceleration_support": { "value": "math.ceil(acceleration_print * 2000 / 4000)" }, + "acceleration_support_interface": { "value": "acceleration_topbottom" }, + "acceleration_topbottom": { "value": "math.ceil(acceleration_print * 500 / 4000)" }, + "acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 4000)" }, + "acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 500 / 1000)" }, + "brim_width": { "value": "3" }, + "cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" }, + "cool_fan_speed": { "value": "100" }, + "cool_fan_speed_max": { "value": "100" }, + "cool_min_speed": { "value": "5" }, + "fill_outline_gaps": { "value": "True" }, + "infill_overlap": { "value": "0" }, + "min_infill_area": { "value": "1" }, + "min_skin_width_for_expansion": { "value": "2" }, + "jerk_enabled": { "value": "True" }, + "jerk_layer_0": { "value": "jerk_topbottom" }, + "jerk_prime_tower": { "value": "math.ceil(jerk_print * 15 / 25)" }, + "jerk_print": { "value": "25" }, + "jerk_support": { "value": "math.ceil(jerk_print * 15 / 25)" }, + "jerk_support_interface": { "value": "jerk_topbottom" }, + "jerk_topbottom": { "value": "math.ceil(jerk_print * 5 / 25)" }, + "jerk_wall": { "value": "math.ceil(jerk_print * 10 / 25)" }, + "jerk_wall_0": { "value": "math.ceil(jerk_wall * 5 / 10)" }, + "wall_thickness": { "value": "0.8"}, + "line_width": { "value": "extruderValue(-1,'machine_nozzle_size')" }, + "raft_base_thickness": { "value": "0.3" }, + "raft_interface_line_spacing": { "value": "0.5" }, + "raft_interface_line_width": { "value": "0.5" }, + "raft_interface_thickness": { "value": "0.2" }, + "raft_jerk": { "value": "jerk_layer_0" }, + "raft_margin": { "value": "10" }, + "raft_surface_layers": { "value": "1" }, + "retraction_amount": { "value": "4" }, + "retraction_count_max": { "value": "10" }, + "retraction_extrusion_window": { "value": "1" }, + "retraction_hop": { "value": "0.5" }, + "retraction_hop_enabled": { "value": "True" }, + "retraction_hop_only_when_collides": { "value": "True" }, + "retraction_min_travel": { "value": "5" }, + "retraction_prime_speed": { "value": "25" }, + "skin_overlap": { "value": "10" }, + "speed_layer_0": { "value": "20" }, + "speed_print": { "value": "52" }, + "speed_support": { "value": "speed_print*line_width/support_line_width" }, + "speed_support_interface": { "value": "speed_print*line_width/support_interface_line_width" }, + "speed_topbottom": { "value": "speed_print*line_width/skin_line_width" }, + "speed_travel": { "value": "80" }, + "speed_infill": { "value": "speed_print*line_width/infill_line_width" }, + "speed_wall": { "value": "speed_print*wall_line_width_0/line_width" }, + "speed_wall_0": { "value": "math.ceil(speed_wall * 0.6)" }, + "speed_wall_x": { "value": "speed_wall" }, + "speed_equalize_flow_enabled": { "value": "False" }, + "support_angle": { "value": "50" }, + "support_xy_distance": { "value": "1" }, + "support_z_distance": { "value": "max((0.2 if(0.2%layer_height==0) else layer_height*int((0.2+layer_height)/layer_height)),layer_height)" }, + "support_bottom_distance": { "value": "max(support_z_distance,layer_height*int(0.45/layer_height))" }, + "top_bottom_thickness": { "value": "max(1.2,layer_height*6)" }, + "travel_avoid_distance": { "value": "3" }, + "gradual_support_infill_step_height": { "value": "0.2" }, + "gradual_support_infill_steps": { "value": "1" }, + "infill_sparse_density": { "value": "20" }, + "gradual_infill_step_height": { "value": "1" }, + "initial_layer_line_width_factor": { "value": "120" }, + "jerk_travel": { "value": "25" }, + "support_bottom_enable": { "value": "True" }, + "support_bottom_height": { "value": "max((0.15 if(0.15%layer_height==0) else layer_height*int((0.15+layer_height)/layer_height)),layer_height)" }, + "support_bottom_pattern": { "value": "'zigzag'" }, + "support_connect_zigzags": { "value": "False" }, + "support_infill_rate": { "value": "8" }, + "support_interface_density": { "value": "80" }, + "support_interface_enable": { "value": "True" }, + "support_interface_height": { "value": "0.5" }, + "support_roof_pattern": { "value": "'concentric'" }, + "z_seam_type": { "value": "'shortest'" }, + "speed_equalize_flow_max": { "value": "65" } + } +} From a5bc2769aadbcf219ac03c33ec701dd211c76c3c Mon Sep 17 00:00:00 2001 From: milkok Date: Tue, 24 Jul 2018 17:15:07 +0800 Subject: [PATCH 029/243] Create winbo_superhelper155.def.json --- .../definitions/winbo_superhelper155.def.json | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 resources/definitions/winbo_superhelper155.def.json diff --git a/resources/definitions/winbo_superhelper155.def.json b/resources/definitions/winbo_superhelper155.def.json new file mode 100644 index 0000000000..65bb4e7b73 --- /dev/null +++ b/resources/definitions/winbo_superhelper155.def.json @@ -0,0 +1,30 @@ +{ + "version": 2, + "name": "Winbo Super Helper 155", + "inherits": "winbo_superhelper105", + "metadata": { + "author": "Winbo", + "manufacturer": "Winbo Smart Tech Co., Ltd.", + "category": "Other", + "visible": true, + "file_formats": "text/x-gcode", + "supports_usb_connection": true, + "machine_extruder_trains": + { + "0": "winbo_superhelper155_extruder" + } + }, + "overrides": { + "machine_name": { "default_value": "Winbo Super Helper 155" }, + "machine_width": { "default_value": 158 }, + "machine_depth": { "default_value": 158 }, + "machine_height": { "default_value": 208 }, + "machine_head_with_fans_polygon": + { + "default_value": + [ + [ -160, 50 ],[ -160, -30 ],[ 160, -30 ],[ 160, 50 ] + ] + } + } +} From 494fcb98b833a8505b037bd5b37bbb3ed45de9d1 Mon Sep 17 00:00:00 2001 From: milkok Date: Tue, 24 Jul 2018 17:17:40 +0800 Subject: [PATCH 030/243] Create winbo_mini2.def.json --- resources/definitions/winbo_mini2.def.json | 138 +++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 resources/definitions/winbo_mini2.def.json diff --git a/resources/definitions/winbo_mini2.def.json b/resources/definitions/winbo_mini2.def.json new file mode 100644 index 0000000000..d166b7847e --- /dev/null +++ b/resources/definitions/winbo_mini2.def.json @@ -0,0 +1,138 @@ +{ + "version": 2, + "name": "Winbo FDM-Mini2", + "inherits": "fdmprinter", + "metadata": { + "author": "Winbo", + "manufacturer": "Winbo Smart Tech Co., Ltd.", + "category": "Other", + "visible": true, + "file_formats": "text/x-gcode", + "supports_usb_connection": true, + "machine_extruder_trains": + { + "0": "winbo_mini2_extruder" + } + }, + + "overrides": { + "machine_name": { "default_value": "Winbo FDM-Mini2" }, + "machine_width": { "default_value": 205 }, + "machine_depth": { "default_value": 155 }, + "machine_height": { "default_value": 205 }, + "machine_heated_bed": { "default_value": false }, + "material_bed_temp_wait": { "default_value": false }, + "machine_filament_park_distance": { "value": "machine_heat_zone_length" }, + "machine_nozzle_heat_up_speed": { "default_value": 1.4 }, + "machine_nozzle_cool_down_speed": { "default_value": 0.8 }, + "machine_head_with_fans_polygon": + { + "default_value": + [ + [ -52, 30 ],[ -52, -40 ],[ 13, -40 ],[ 13, 30 ] + ] + }, + "machine_gcode_flavor": { "default_value": "Marlin" }, + "machine_max_feedrate_x": { "default_value": 250 }, + "machine_max_feedrate_y": { "default_value": 200 }, + "machine_max_feedrate_z": { "default_value": 40 }, + "machine_acceleration": { "default_value": 3000 }, + "gantry_height": { "default_value": 75 }, + "machine_extruder_count": { "default_value": 1 }, + "machine_start_gcode": { "default_value": "G21\nG90\nM82\nM107\nG28 X0 Y0\nG28 Z0\nG1 F1000 Z3\nG1 F4000 X0\nG1 F4000 Y0\nG1 F1000 Z0.2\nG92 E0\nG1 F1000 X30 E8\nG92 E0\nM117 Printing." }, + "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\nG92 E2\nG1 E0 F200\nG28 X0 Y0\nM84 X Y E" }, + "material_diameter": { "default_value": 1.75 }, + "prime_blob_enable": { "enabled": true }, + "acceleration_enabled": { "value": "True" }, + "acceleration_layer_0": { "value": "acceleration_topbottom" }, + "acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" }, + "acceleration_print": { "value": "2000" }, + "acceleration_travel": { "value": "2500" }, + "acceleration_support": { "value": "math.ceil(acceleration_print * 2000 / 4000)" }, + "acceleration_support_interface": { "value": "acceleration_topbottom" }, + "acceleration_topbottom": { "value": "math.ceil(acceleration_print * 500 / 4000)" }, + "acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 4000)" }, + "acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 500 / 1000)" }, + "brim_width": { "value": "3" }, + "cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" }, + "cool_fan_speed": { "value": "100" }, + "cool_fan_speed_max": { "value": "100" }, + "cool_min_speed": { "value": "5" }, + "fill_outline_gaps": { "value": "True" }, + "infill_overlap": { "value": "0" }, + "min_infill_area": { "value": "1" }, + "min_skin_width_for_expansion": { "value": "2" }, + "jerk_enabled": { "value": "True" }, + "jerk_layer_0": { "value": "jerk_topbottom" }, + "jerk_prime_tower": { "value": "math.ceil(jerk_print * 15 / 25)" }, + "jerk_print": { "value": "25" }, + "jerk_support": { "value": "math.ceil(jerk_print * 15 / 25)" }, + "jerk_support_interface": { "value": "jerk_topbottom" }, + "jerk_topbottom": { "value": "math.ceil(jerk_print * 5 / 25)" }, + "jerk_wall": { "value": "math.ceil(jerk_print * 10 / 25)" }, + "jerk_wall_0": { "value": "math.ceil(jerk_wall * 5 / 10)" }, + "wall_thickness": { "value": "1.2"}, + "line_width": { "value": "extruderValue(-1,'machine_nozzle_size')" }, + "wall_0_inset": { "value": "0.05" }, + "wall_line_width_x": { "value": "line_width" }, + "wall_line_width_0": { "value": "line_width-0.05" }, + "support_line_width": { "value": "max(min(line_width,0.4),line_width/2)" }, + "support_interface_line_width": { "value": "support_line_width" }, + "machine_min_cool_heat_time_window": { "value": "15" }, + "default_material_print_temperature": { "value": "200" }, + "material_print_temperature_layer_0": { "value": "material_print_temperature - 5" }, + "material_bed_temperature": { "maximum_value": "115" }, + "material_bed_temperature_layer_0": { "maximum_value": "115" }, + "raft_airgap": { "value": "0" }, + "raft_base_thickness": { "value": "0.3" }, + "raft_interface_line_spacing": { "value": "0.5" }, + "raft_interface_line_width": { "value": "0.5" }, + "raft_interface_thickness": { "value": "0.2" }, + "raft_jerk": { "value": "jerk_layer_0" }, + "raft_margin": { "value": "10" }, + "raft_surface_layers": { "value": "1" }, + "retraction_amount": { "value": "4" }, + "retraction_count_max": { "value": "10" }, + "retraction_extrusion_window": { "value": "1" }, + "retraction_hop": { "value": "0.5" }, + "retraction_hop_enabled": { "value": "True" }, + "retraction_hop_only_when_collides": { "value": "True" }, + "retraction_min_travel": { "value": "5" }, + "retraction_prime_speed": { "value": "25" }, + "skin_overlap": { "value": "10" }, + "speed_layer_0": { "value": "20" }, + "speed_print": { "value": "50" }, + "speed_support": { "value": "speed_print*line_width/support_line_width" }, + "speed_support_interface": { "value": "speed_print*line_width/support_interface_line_width" }, + "speed_topbottom": { "value": "speed_print*line_width/skin_line_width" }, + "speed_travel": { "value": "90" }, + "speed_infill": { "value": "speed_print*line_width/infill_line_width" }, + "speed_wall": { "value": "speed_print*wall_line_width_0/line_width" }, + "speed_wall_0": { "value": "math.ceil(speed_wall * 0.6)" }, + "speed_wall_x": { "value": "speed_wall" }, + "speed_equalize_flow_enabled": { "value": "False" }, + "support_angle": { "value": "50" }, + "support_xy_distance": { "value": "1" }, + "support_z_distance": { "value": "max((0.2 if(0.2%layer_height==0) else layer_height*int((0.2+layer_height)/layer_height)),layer_height)" }, + "support_bottom_distance": { "value": "max(support_z_distance,layer_height*int(0.45/layer_height))" }, + "top_bottom_thickness": { "value": "max(1.2,layer_height*6)" }, + "travel_avoid_distance": { "value": "3" }, + "gradual_support_infill_step_height": { "value": "0.2" }, + "gradual_support_infill_steps": { "value": "1" }, + "infill_sparse_density": { "value": "20" }, + "gradual_infill_step_height": { "value": "1" }, + "initial_layer_line_width_factor": { "value": "120" }, + "jerk_travel": { "value": "25" }, + "support_bottom_enable": { "value": "True" }, + "support_bottom_height": { "value": "max((0.15 if(0.15%layer_height==0) else layer_height*int((0.15+layer_height)/layer_height)),layer_height)" }, + "support_bottom_pattern": { "value": "'zigzag'" }, + "support_connect_zigzags": { "value": "False" }, + "support_infill_rate": { "value": "8" }, + "support_interface_density": { "value": "80" }, + "support_interface_enable": { "value": "True" }, + "support_interface_height": { "value": "0.5" }, + "support_roof_pattern": { "value": "'concentric'" }, + "z_seam_type": { "value": "'shortest'" }, + "speed_equalize_flow_max": { "value": "65" } + } +} From dd9d4d1e2b5ef0336e0b3adcbe49da1c4d9cc185 Mon Sep 17 00:00:00 2001 From: milkok Date: Tue, 24 Jul 2018 17:19:36 +0800 Subject: [PATCH 031/243] Create winbo_dragonl4.def.json --- resources/definitions/winbo_dragonl4.def.json | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 resources/definitions/winbo_dragonl4.def.json diff --git a/resources/definitions/winbo_dragonl4.def.json b/resources/definitions/winbo_dragonl4.def.json new file mode 100644 index 0000000000..cb5566c46b --- /dev/null +++ b/resources/definitions/winbo_dragonl4.def.json @@ -0,0 +1,139 @@ +{ + "version": 2, + "name": "Winbo FDM-Dragon(L)4", + "inherits": "fdmprinter", + "metadata": { + "author": "Winbo", + "manufacturer": "Winbo Smart Tech Co., Ltd.", + "category": "Other", + "visible": true, + "file_formats": "text/x-gcode", + "supports_usb_connection": false, + "machine_extruder_trains": + { + "0": "winbo_dragonl4_extruder" + } + }, + + "overrides": { + "machine_name": { "default_value": "Winbo FDM-Dragon(L)4" }, + "machine_width": { "default_value": 615 }, + "machine_depth": { "default_value": 463 }, + "machine_height": { "default_value": 615 }, + "machine_heated_bed": { "default_value": true }, + "material_bed_temp_wait": { "default_value": false }, + "machine_filament_park_distance": { "value": "machine_heat_zone_length" }, + "machine_nozzle_heat_up_speed": { "default_value": 1.4 }, + "machine_nozzle_cool_down_speed": { "default_value": 0.8 }, + "machine_nozzle_size": { "default_value": 0.8 }, + "machine_head_with_fans_polygon": + { + "default_value": + [ + [ -50, 90 ],[ -50, -60 ],[ 50, -60 ],[ 50, 90 ] + ] + }, + "machine_gcode_flavor": { "default_value": "Marlin" }, + "machine_max_feedrate_x": { "default_value": 300 }, + "machine_max_feedrate_y": { "default_value": 300 }, + "machine_max_feedrate_z": { "default_value": 40 }, + "machine_acceleration": { "default_value": 2000 }, + "gantry_height": { "default_value": 80 }, + "machine_extruder_count": { "default_value": 1 }, + "machine_start_gcode": { "default_value": "G21\nG90\nM82\nM107\nM9998\nG28 X0 Y0\nG28 Z0\nG1 F6000 Z0.3\nG92 E0\nG1 F800 X585 E12\nG92 E0" }, + "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\nG92 E2\nG1 E0 F200\nG28 X0 Y0\nM84 X Y E" }, + "material_diameter": { "default_value": 3.0 }, + "prime_blob_enable": { "enabled": true }, + "acceleration_enabled": { "value": "True" }, + "acceleration_layer_0": { "value": "acceleration_topbottom" }, + "acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" }, + "acceleration_print": { "value": "1800" }, + "acceleration_travel": { "value": "2000" }, + "acceleration_support": { "value": "math.ceil(acceleration_print * 2000 / 4000)" }, + "acceleration_support_interface": { "value": "acceleration_topbottom" }, + "acceleration_topbottom": { "value": "math.ceil(acceleration_print * 500 / 4000)" }, + "acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 4000)" }, + "acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 500 / 1000)" }, + "brim_width": { "value": "4" }, + "cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" }, + "cool_fan_speed": { "value": "100" }, + "cool_fan_speed_max": { "value": "100" }, + "cool_min_speed": { "value": "5" }, + "fill_outline_gaps": { "value": "True" }, + "infill_overlap": { "value": "0" }, + "min_infill_area": { "value": "1" }, + "min_skin_width_for_expansion": { "value": "2" }, + "jerk_enabled": { "value": "True" }, + "jerk_layer_0": { "value": "jerk_topbottom" }, + "jerk_prime_tower": { "value": "math.ceil(jerk_print * 15 / 25)" }, + "jerk_print": { "value": "25" }, + "jerk_support": { "value": "math.ceil(jerk_print * 15 / 25)" }, + "jerk_support_interface": { "value": "jerk_topbottom" }, + "jerk_topbottom": { "value": "math.ceil(jerk_print * 5 / 25)" }, + "jerk_wall": { "value": "math.ceil(jerk_print * 10 / 25)" }, + "jerk_wall_0": { "value": "math.ceil(jerk_wall * 5 / 10)" }, + "wall_thickness": { "value": "2.4"}, + "line_width": { "value": "extruderValue(-1,'machine_nozzle_size')" }, + "wall_0_inset": { "value": "0.05" }, + "wall_line_width_x": { "value": "line_width" }, + "wall_line_width_0": { "value": "line_width-0.05" }, + "support_line_width": { "value": "max(min(line_width,0.4),line_width/2)" }, + "support_interface_line_width": { "value": "support_line_width" }, + "machine_min_cool_heat_time_window": { "value": "15" }, + "default_material_print_temperature": { "value": "200" }, + "material_print_temperature_layer_0": { "value": "material_print_temperature - 5" }, + "material_bed_temperature": { "maximum_value": "100" }, + "material_bed_temperature_layer_0": { "maximum_value": "100" }, + "raft_airgap": { "value": "0" }, + "raft_base_thickness": { "value": "0.3" }, + "raft_interface_line_spacing": { "value": "0.5" }, + "raft_interface_line_width": { "value": "0.5" }, + "raft_interface_thickness": { "value": "0.2" }, + "raft_jerk": { "value": "jerk_layer_0" }, + "raft_margin": { "value": "5" }, + "raft_surface_layers": { "value": "2" }, + "retraction_amount": { "value": "4" }, + "retraction_count_max": { "value": "10" }, + "retraction_extrusion_window": { "value": "1" }, + "retraction_hop": { "value": "0.5" }, + "retraction_hop_enabled": { "value": "True" }, + "retraction_hop_only_when_collides": { "value": "True" }, + "retraction_min_travel": { "value": "5" }, + "retraction_prime_speed": { "value": "25" }, + "skin_overlap": { "value": "10" }, + "speed_layer_0": { "value": "25" }, + "speed_print": { "value": "70" }, + "speed_support": { "value": "speed_print*line_width/support_line_width" }, + "speed_support_interface": { "value": "speed_print*line_width/support_interface_line_width" }, + "speed_topbottom": { "value": "speed_print*line_width/skin_line_width" }, + "speed_travel": { "value": "100" }, + "speed_infill": { "value": "speed_print*line_width/infill_line_width" }, + "speed_wall": { "value": "speed_print*wall_line_width_0/line_width" }, + "speed_wall_0": { "value": "math.ceil(speed_wall * 0.6)" }, + "speed_wall_x": { "value": "speed_wall" }, + "speed_equalize_flow_enabled": { "value": "False" }, + "support_angle": { "value": "50" }, + "support_xy_distance": { "value": "1" }, + "support_z_distance": { "value": "max((0.2 if(0.2%layer_height==0) else layer_height*int((0.2+layer_height)/layer_height)),layer_height)" }, + "support_bottom_distance": { "value": "max(support_z_distance,layer_height*int(0.45/layer_height))" }, + "top_bottom_thickness": { "value": "max(1.2,layer_height*6)" }, + "travel_avoid_distance": { "value": "3" }, + "gradual_support_infill_step_height": { "value": "0.2" }, + "gradual_support_infill_steps": { "value": "1" }, + "infill_sparse_density": { "value": "20" }, + "gradual_infill_step_height": { "value": "1" }, + "initial_layer_line_width_factor": { "value": "120" }, + "jerk_travel": { "value": "25" }, + "support_bottom_enable": { "value": "True" }, + "support_bottom_height": { "value": "max((0.15 if(0.15%layer_height==0) else layer_height*int((0.15+layer_height)/layer_height)),layer_height)" }, + "support_bottom_pattern": { "value": "'zigzag'" }, + "support_connect_zigzags": { "value": "False" }, + "support_infill_rate": { "value": "8" }, + "support_interface_density": { "value": "80" }, + "support_interface_enable": { "value": "True" }, + "support_interface_height": { "value": "0.5" }, + "support_roof_pattern": { "value": "'concentric'" }, + "z_seam_type": { "value": "'shortest'" }, + "speed_equalize_flow_max": { "value": "65" } + } +} From 405eccfa9ceafd481f1497125649a173b3715f80 Mon Sep 17 00:00:00 2001 From: milkok Date: Tue, 24 Jul 2018 17:20:40 +0800 Subject: [PATCH 032/243] Create winbo_superhelper105_extruder.def.json --- .../winbo_superhelper105_extruder.def.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 resources/extruders/winbo_superhelper105_extruder.def.json diff --git a/resources/extruders/winbo_superhelper105_extruder.def.json b/resources/extruders/winbo_superhelper105_extruder.def.json new file mode 100644 index 0000000000..1224a5a29a --- /dev/null +++ b/resources/extruders/winbo_superhelper105_extruder.def.json @@ -0,0 +1,19 @@ +{ + "id": "winbo_superhelper105_extruder", + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "winbo_superhelper105", + "position": "0" + }, + + "overrides": { + "extruder_nr": { + "default_value": 0, + "maximum_value": "2" + }, + "machine_nozzle_offset_x": { "default_value": 0.0 }, + "machine_nozzle_offset_y": { "default_value": 0.0 } + } +} From 937a4c68e3537477d62b0d40f5d2ea9c4c5b8d78 Mon Sep 17 00:00:00 2001 From: milkok Date: Tue, 24 Jul 2018 17:21:58 +0800 Subject: [PATCH 033/243] Create winbo_superhelper155_extruder.def.json --- .../winbo_superhelper155_extruder.def.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 resources/extruders/winbo_superhelper155_extruder.def.json diff --git a/resources/extruders/winbo_superhelper155_extruder.def.json b/resources/extruders/winbo_superhelper155_extruder.def.json new file mode 100644 index 0000000000..9935084872 --- /dev/null +++ b/resources/extruders/winbo_superhelper155_extruder.def.json @@ -0,0 +1,19 @@ +{ + "id": "winbo_superhelper155_extruder", + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "winbo_superhelper155", + "position": "0" + }, + + "overrides": { + "extruder_nr": { + "default_value": 0, + "maximum_value": "2" + }, + "machine_nozzle_offset_x": { "default_value": 0.0 }, + "machine_nozzle_offset_y": { "default_value": 0.0 } + } +} From 147b66845e89dd95550e33f49b0e6bd1d7566821 Mon Sep 17 00:00:00 2001 From: milkok Date: Tue, 24 Jul 2018 17:22:58 +0800 Subject: [PATCH 034/243] Create winbo_mini2_extruder.def.json --- .../extruders/winbo_mini2_extruder.def.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 resources/extruders/winbo_mini2_extruder.def.json diff --git a/resources/extruders/winbo_mini2_extruder.def.json b/resources/extruders/winbo_mini2_extruder.def.json new file mode 100644 index 0000000000..5348e6ad43 --- /dev/null +++ b/resources/extruders/winbo_mini2_extruder.def.json @@ -0,0 +1,19 @@ +{ + "id": "winbo_mini2_extruder", + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "winbo_mini2", + "position": "0" + }, + + "overrides": { + "extruder_nr": { + "default_value": 0, + "maximum_value": "2" + }, + "machine_nozzle_offset_x": { "default_value": 0.0 }, + "machine_nozzle_offset_y": { "default_value": 0.0 } + } +} From 17493d92a0fd79dea2719ecb906be8a7d5bbc09f Mon Sep 17 00:00:00 2001 From: milkok Date: Tue, 24 Jul 2018 17:24:01 +0800 Subject: [PATCH 035/243] Create winbo_dragonl4_extruder.def.json --- .../winbo_dragonl4_extruder.def.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 resources/extruders/winbo_dragonl4_extruder.def.json diff --git a/resources/extruders/winbo_dragonl4_extruder.def.json b/resources/extruders/winbo_dragonl4_extruder.def.json new file mode 100644 index 0000000000..a4f65bbf0e --- /dev/null +++ b/resources/extruders/winbo_dragonl4_extruder.def.json @@ -0,0 +1,19 @@ +{ + "id": "winbo_dragonl4_extruder", + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "winbo_dragonl4", + "position": "0" + }, + + "overrides": { + "extruder_nr": { + "default_value": 0, + "maximum_value": "2" + }, + "machine_nozzle_offset_x": { "default_value": 0.0 }, + "machine_nozzle_offset_y": { "default_value": 0.0 } + } +} From 320d73c6e51f8ec59bfce65fcd97c7b058c52236 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 24 Jul 2018 12:17:53 +0200 Subject: [PATCH 036/243] Retain 3MF mesh positions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contributes to CURA-5465 Fixed bug by preventing read jobs for 3mf files from being auto-arranged. Boyscout changes: - Fixed typo in `ThreeMFReader.py` (`splitted` → `split`) - Fixed code style in `CuraApplication.py` (`filename` → `file_name`) --- cura/CuraApplication.py | 23 ++++++++++++----------- plugins/3MFReader/ThreeMFReader.py | 26 +++++++++++++------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 3f0a5b9cb2..4513d7edff 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1599,10 +1599,12 @@ class CuraApplication(QtApplication): def _readMeshFinished(self, job): nodes = job.getResult() - filename = job.getFileName() - self._currently_loading_files.remove(filename) + file_name = job.getFileName() + file_name_lower = file_name.lower() + file_extension = file_name_lower.split(".")[-1] + self._currently_loading_files.remove(file_name) - self.fileLoaded.emit(filename) + self.fileLoaded.emit(file_name) arrange_objects_on_load = not self.getPreferences().getValue("cura/use_multi_build_plate") target_build_plate = self.getMultiBuildPlateModel().activeBuildPlate if arrange_objects_on_load else -1 @@ -1635,15 +1637,14 @@ class CuraApplication(QtApplication): node.scale(original_node.getScale()) node.setSelectable(True) - node.setName(os.path.basename(filename)) + node.setName(os.path.basename(file_name)) self.getBuildVolume().checkBoundsAndUpdate(node) is_non_sliceable = False - filename_lower = filename.lower() - for extension in self._non_sliceable_extensions: - if filename_lower.endswith(extension): - is_non_sliceable = True - break + + if file_extension in self._non_sliceable_extensions: + is_non_sliceable = True + if is_non_sliceable: self.callLater(lambda: self.getController().setActiveView("SimulationView")) @@ -1662,7 +1663,7 @@ class CuraApplication(QtApplication): if not child.getDecorator(ConvexHullDecorator): child.addDecorator(ConvexHullDecorator()) - if arrange_objects_on_load: + if file_extension != "3mf" and arrange_objects_on_load: if node.callDecoration("isSliceable"): # Only check position if it's not already blatantly obvious that it won't fit. if node.getBoundingBox() is None or self._volume.getBoundingBox() is None or node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth: @@ -1696,7 +1697,7 @@ class CuraApplication(QtApplication): if select_models_on_load: Selection.add(node) - self.fileCompleted.emit(filename) + self.fileCompleted.emit(file_name) def addNonSliceableExtension(self, extension): self._non_sliceable_extensions.append(extension) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 0280600834..9ba82364e8 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -59,7 +59,7 @@ class ThreeMFReader(MeshReader): if transformation == "": return Matrix() - splitted_transformation = transformation.split() + split_transformation = transformation.split() ## Transformation is saved as: ## M00 M01 M02 0.0 ## M10 M11 M12 0.0 @@ -68,20 +68,20 @@ class ThreeMFReader(MeshReader): ## We switch the row & cols as that is how everyone else uses matrices! temp_mat = Matrix() # Rotation & Scale - temp_mat._data[0, 0] = splitted_transformation[0] - temp_mat._data[1, 0] = splitted_transformation[1] - temp_mat._data[2, 0] = splitted_transformation[2] - temp_mat._data[0, 1] = splitted_transformation[3] - temp_mat._data[1, 1] = splitted_transformation[4] - temp_mat._data[2, 1] = splitted_transformation[5] - temp_mat._data[0, 2] = splitted_transformation[6] - temp_mat._data[1, 2] = splitted_transformation[7] - temp_mat._data[2, 2] = splitted_transformation[8] + temp_mat._data[0, 0] = split_transformation[0] + temp_mat._data[1, 0] = split_transformation[1] + temp_mat._data[2, 0] = split_transformation[2] + temp_mat._data[0, 1] = split_transformation[3] + temp_mat._data[1, 1] = split_transformation[4] + temp_mat._data[2, 1] = split_transformation[5] + temp_mat._data[0, 2] = split_transformation[6] + temp_mat._data[1, 2] = split_transformation[7] + temp_mat._data[2, 2] = split_transformation[8] # Translation - temp_mat._data[0, 3] = splitted_transformation[9] - temp_mat._data[1, 3] = splitted_transformation[10] - temp_mat._data[2, 3] = splitted_transformation[11] + temp_mat._data[0, 3] = split_transformation[9] + temp_mat._data[1, 3] = split_transformation[10] + temp_mat._data[2, 3] = split_transformation[11] return temp_mat From 1f15599b4de0cbb2f78c91b867b6713c60717fcb Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 24 Jul 2018 15:53:52 +0200 Subject: [PATCH 037/243] Fix non-slicable check CURA-5465 --- cura/CuraApplication.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 4513d7edff..8dd17896bb 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1640,10 +1640,7 @@ class CuraApplication(QtApplication): node.setName(os.path.basename(file_name)) self.getBuildVolume().checkBoundsAndUpdate(node) - is_non_sliceable = False - - if file_extension in self._non_sliceable_extensions: - is_non_sliceable = True + is_non_sliceable = "." + file_extension in self._non_sliceable_extensions if is_non_sliceable: self.callLater(lambda: self.getController().setActiveView("SimulationView")) From 952bc54452b6692d7c1bbe597585dbe0c85accf4 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 24 Jul 2018 15:59:00 +0200 Subject: [PATCH 038/243] Make stretch script work with relative movements CURA-5480 --- .../PostProcessingPlugin/scripts/Stretch.py | 54 ++++++++++++++----- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/Stretch.py b/plugins/PostProcessingPlugin/scripts/Stretch.py index c7a36ab7d6..945483c321 100644 --- a/plugins/PostProcessingPlugin/scripts/Stretch.py +++ b/plugins/PostProcessingPlugin/scripts/Stretch.py @@ -35,25 +35,40 @@ class GCodeStep(): Class to store the current value of each G_Code parameter for any G-Code step """ - def __init__(self, step): + def __init__(self, step, in_relative_movement: bool = False): self.step = step self.step_x = 0 self.step_y = 0 self.step_z = 0 self.step_e = 0 self.step_f = 0 + + self.in_relative_movement = in_relative_movement + self.comment = "" def readStep(self, line): """ Reads gcode from line into self """ - self.step_x = _getValue(line, "X", self.step_x) - self.step_y = _getValue(line, "Y", self.step_y) - self.step_z = _getValue(line, "Z", self.step_z) - self.step_e = _getValue(line, "E", self.step_e) - self.step_f = _getValue(line, "F", self.step_f) - return + if not self.in_relative_movement: + self.step_x = _getValue(line, "X", self.step_x) + self.step_y = _getValue(line, "Y", self.step_y) + self.step_z = _getValue(line, "Z", self.step_z) + self.step_e = _getValue(line, "E", self.step_e) + self.step_f = _getValue(line, "F", self.step_f) + else: + delta_step_x = _getValue(line, "X", 0) + delta_step_y = _getValue(line, "Y", 0) + delta_step_z = _getValue(line, "Z", 0) + delta_step_e = _getValue(line, "E", 0) + delta_step_f = _getValue(line, "F", 0) + + self.step_x += delta_step_x + self.step_y += delta_step_y + self.step_z += delta_step_z + self.step_e += delta_step_e + self.step_f += delta_step_f def copyPosFrom(self, step): """ @@ -65,7 +80,9 @@ class GCodeStep(): self.step_e = step.step_e self.step_f = step.step_f self.comment = step.comment - return + + def setInRelativeMovement(self, value: bool) -> None: + self.in_relative_movement = value # Execution part of the stretch plugin @@ -86,6 +103,7 @@ class Stretcher(): # of already deposited material for current layer self.layer_z = 0 # Z position of the extrusion moves of the current layer self.layergcode = "" + self._in_relative_movement = False def execute(self, data): """ @@ -96,7 +114,8 @@ class Stretcher(): + " and push wall stretch " + str(self.pw_stretch) + "mm") retdata = [] layer_steps = [] - current = GCodeStep(0) + in_relative_movement = False + current = GCodeStep(0, in_relative_movement) self.layer_z = 0. current_e = 0. for layer in data: @@ -107,20 +126,29 @@ class Stretcher(): current.comment = line[line.find(";"):] if _getValue(line, "G") == 0: current.readStep(line) - onestep = GCodeStep(0) + onestep = GCodeStep(0, in_relative_movement) onestep.copyPosFrom(current) elif _getValue(line, "G") == 1: current.readStep(line) - onestep = GCodeStep(1) + onestep = GCodeStep(1, in_relative_movement) onestep.copyPosFrom(current) + + # end of relative movement + elif _getValue(line, "G") == 90: + in_relative_movement = False + # start of relative movement + elif _getValue(line, "G") == 91: + in_relative_movement = True + elif _getValue(line, "G") == 92: current.readStep(line) - onestep = GCodeStep(-1) + onestep = GCodeStep(-1, in_relative_movement) onestep.copyPosFrom(current) else: - onestep = GCodeStep(-1) + onestep = GCodeStep(-1, in_relative_movement) onestep.copyPosFrom(current) onestep.comment = line + if line.find(";LAYER:") >= 0 and len(layer_steps): # Previous plugin "forgot" to separate two layers... Logger.log("d", "Layer Z " + "{:.3f}".format(self.layer_z) From e89983b171d8c6975ce1be61a62e3ad915940ac7 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 24 Jul 2018 16:17:53 +0200 Subject: [PATCH 039/243] When dismissing the print window, also reset the "sending_gcode" flag CL-913 --- plugins/UM3NetworkPrinting/PrintWindow.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/UM3NetworkPrinting/PrintWindow.qml b/plugins/UM3NetworkPrinting/PrintWindow.qml index 0553db0eb2..9793b218fc 100644 --- a/plugins/UM3NetworkPrinting/PrintWindow.qml +++ b/plugins/UM3NetworkPrinting/PrintWindow.qml @@ -26,6 +26,10 @@ UM.Dialog { resetPrintersModel() } + else + { + OutputDevice.cancelPrintSelection() + } } title: catalog.i18nc("@title:window", "Print over network") From 1cb896904b870baadf15fefe1f374bc11574ddeb Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 24 Jul 2018 16:24:28 +0200 Subject: [PATCH 040/243] Fixed missed renames of onFinished keyword --- .../ClusterUM3PrinterOutputController.py | 2 +- .../UM3NetworkPrinting/LegacyUM3OutputDevice.py | 14 +++++++------- .../LegacyUM3PrinterOutputController.py | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/UM3NetworkPrinting/ClusterUM3PrinterOutputController.py b/plugins/UM3NetworkPrinting/ClusterUM3PrinterOutputController.py index 707443b9ea..4a0319cafc 100644 --- a/plugins/UM3NetworkPrinting/ClusterUM3PrinterOutputController.py +++ b/plugins/UM3NetworkPrinting/ClusterUM3PrinterOutputController.py @@ -19,5 +19,5 @@ class ClusterUM3PrinterOutputController(PrinterOutputController): def setJobState(self, job: "PrintJobOutputModel", state: str): data = "{\"action\": \"%s\"}" % state - self._output_device.put("print_jobs/%s/action" % job.key, data, onFinished=None) + self._output_device.put("print_jobs/%s/action" % job.key, data, on_finished=None) diff --git a/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py b/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py index f38c1a1c7a..8617b5b2ff 100644 --- a/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py @@ -165,7 +165,7 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice): file_name = "none.xml" - self.postForm("materials", "form-data; name=\"file\";filename=\"%s\"" % file_name, xml_data.encode(), onFinished=None) + self.postForm("materials", "form-data; name=\"file\";filename=\"%s\"" % file_name, xml_data.encode(), on_finished=None) except NotImplementedError: # If the material container is not the most "generic" one it can't be serialized an will raise a @@ -270,7 +270,7 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice): file_name = "%s.gcode.gz" % CuraApplication.getInstance().getPrintInformation().jobName self.postForm("print_job", "form-data; name=\"file\";filename=\"%s\"" % file_name, compressed_gcode, - onFinished=self._onPostPrintJobFinished) + on_finished=self._onPostPrintJobFinished) return @@ -381,8 +381,8 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice): self._checkAuthentication() # We don't need authentication for requesting info, so we can go right ahead with requesting this. - self.get("printer", onFinished=self._onGetPrinterDataFinished) - self.get("print_job", onFinished=self._onGetPrintJobFinished) + self.get("printer", on_finished=self._onGetPrinterDataFinished) + self.get("print_job", on_finished=self._onGetPrintJobFinished) def _resetAuthenticationRequestedMessage(self): if self._authentication_requested_message: @@ -404,7 +404,7 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice): def _verifyAuthentication(self): Logger.log("d", "Attempting to verify authentication") # This will ensure that the "_onAuthenticationRequired" is triggered, which will setup the authenticator. - self.get("auth/verify", onFinished=self._onVerifyAuthenticationCompleted) + self.get("auth/verify", on_finished=self._onVerifyAuthenticationCompleted) def _onVerifyAuthenticationCompleted(self, reply): status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) @@ -426,7 +426,7 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice): def _checkAuthentication(self): Logger.log("d", "Checking if authentication is correct for id %s and key %s", self._authentication_id, self._getSafeAuthKey()) - self.get("auth/check/" + str(self._authentication_id), onFinished=self._onCheckAuthenticationFinished) + self.get("auth/check/" + str(self._authentication_id), on_finished=self._onCheckAuthenticationFinished) def _onCheckAuthenticationFinished(self, reply): if str(self._authentication_id) not in reply.url().toString(): @@ -502,7 +502,7 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice): self.post("auth/request", json.dumps({"application": "Cura-" + CuraApplication.getInstance().getVersion(), "user": self._getUserName()}).encode(), - onFinished=self._onRequestAuthenticationFinished) + on_finished=self._onRequestAuthenticationFinished) self.setAuthenticationState(AuthState.AuthenticationRequested) diff --git a/plugins/UM3NetworkPrinting/LegacyUM3PrinterOutputController.py b/plugins/UM3NetworkPrinting/LegacyUM3PrinterOutputController.py index b12a31b6cf..702b48ce15 100644 --- a/plugins/UM3NetworkPrinting/LegacyUM3PrinterOutputController.py +++ b/plugins/UM3NetworkPrinting/LegacyUM3PrinterOutputController.py @@ -31,11 +31,11 @@ class LegacyUM3PrinterOutputController(PrinterOutputController): def setJobState(self, job: "PrintJobOutputModel", state: str): data = "{\"target\": \"%s\"}" % state - self._output_device.put("print_job/state", data, onFinished=None) + self._output_device.put("print_job/state", data, on_finished=None) def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: int): data = str(temperature) - self._output_device.put("printer/bed/temperature/target", data, onFinished=self._onPutBedTemperatureCompleted) + self._output_device.put("printer/bed/temperature/target", data, on_finished=self._onPutBedTemperatureCompleted) def _onPutBedTemperatureCompleted(self, reply): if Version(self._preheat_printer.firmwareVersion) < Version("3.5.92"): @@ -51,10 +51,10 @@ class LegacyUM3PrinterOutputController(PrinterOutputController): new_y = head_pos.y + y new_z = head_pos.z + z data = "{\n\"x\":%s,\n\"y\":%s,\n\"z\":%s\n}" %(new_x, new_y, new_z) - self._output_device.put("printer/heads/0/position", data, onFinished=None) + self._output_device.put("printer/heads/0/position", data, on_finished=None) def homeBed(self, printer): - self._output_device.put("printer/heads/0/position/z", "0", onFinished=None) + self._output_device.put("printer/heads/0/position/z", "0", on_finished=None) def _onPreheatBedTimerFinished(self): self.setTargetBedTemperature(self._preheat_printer, 0) @@ -89,7 +89,7 @@ class LegacyUM3PrinterOutputController(PrinterOutputController): printer.updateIsPreheating(True) return - self._output_device.put("printer/bed/pre_heat", data, onFinished = self._onPutPreheatBedCompleted) + self._output_device.put("printer/bed/pre_heat", data, on_finished = self._onPutPreheatBedCompleted) printer.updateIsPreheating(True) self._preheat_request_in_progress = True From 31d1c9f92cdc06043d008986b5dd917ba4ab64ca Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 11 May 2018 19:25:55 +0200 Subject: [PATCH 041/243] setting for infill_multiplier --- resources/definitions/fdmprinter.def.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 04b4f34f8b..07fc28354d 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1680,6 +1680,18 @@ "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true }, + "infill_multiplier": + { + "label": "Infill Line Multiplier", + "description": "Convert each infill line to this many lines. This makes the ", + "default_value": 1, + "type": "int", + "minimum_value": "1", + "maximum_value_warning": "infill_line_distance / infill_line_width", + "enabled": "infill_sparse_density > 0 and not spaghetti_infill_enabled", + "limit_to_extruder": "infill_extruder_nr", + "settable_per_mesh": true + }, "sub_div_rad_add": { "label": "Cubic Subdivision Shell", From 790321833ba0ac4c29d248d1b6c8da6c83ffede1 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 11 May 2018 19:40:38 +0200 Subject: [PATCH 042/243] setting description and enabled fixes to infill_multiplier --- 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 07fc28354d..7799276efe 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1683,12 +1683,12 @@ "infill_multiplier": { "label": "Infill Line Multiplier", - "description": "Convert each infill line to this many lines. This makes the ", + "description": "Convert each infill line to this many lines. The extra lines do not cross over each other, but avoid each other. This makes the infill stiffer, but increases print time and material usage.", "default_value": 1, "type": "int", "minimum_value": "1", "maximum_value_warning": "infill_line_distance / infill_line_width", - "enabled": "infill_sparse_density > 0 and not spaghetti_infill_enabled", + "enabled": "infill_sparse_density > 0 and not spaghetti_infill_enabled and infill_pattern != 'zigzag'", "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true }, From 3f4aa0abafb7fc816f7a361df644276599fc2c3b Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 11 May 2018 19:41:02 +0200 Subject: [PATCH 043/243] allow zig_zaggify for linear infill because of infill_multiplier --- 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 7799276efe..9af56e55b6 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1644,7 +1644,7 @@ "type": "bool", "default_value": false, "value": "infill_pattern == 'cross' or infill_pattern == 'cross_3d'", - "enabled": "infill_pattern == 'grid' or infill_pattern == 'triangles' or infill_pattern == 'trihexagon' or infill_pattern == 'cubic' or infill_pattern == 'tetrahedral' or infill_pattern == 'quarter_cubic' or infill_pattern == 'cross' or infill_pattern == 'cross_3d'", + "enabled": "infill_pattern == 'lines' or infill_pattern == 'grid' or infill_pattern == 'triangles' or infill_pattern == 'trihexagon' or infill_pattern == 'cubic' or infill_pattern == 'tetrahedral' or infill_pattern == 'quarter_cubic' or infill_pattern == 'cross' or infill_pattern == 'cross_3d'", "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true }, From 285f1368561f84b1e6ff40dbb88485afcae16ead Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Thu, 17 May 2018 18:02:25 +0200 Subject: [PATCH 044/243] settings: connect_skin_polygons and connect_infill_polygons --- resources/definitions/fdmprinter.def.json | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 9af56e55b6..db40ab2f6a 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1196,6 +1196,16 @@ "limit_to_extruder": "top_bottom_extruder_nr", "settable_per_mesh": true }, + "connect_skin_polygons": + { + "label": "Connect Top/Bottom Polygons", + "description": "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happend midway over infill this feature can reduce the top surface quality.", + "type": "bool", + "default_value": false, + "enabled": "top_bottom_pattern == 'concentric'", + "limit_to_extruder": "infill_extruder_nr", + "settable_per_mesh": true + }, "skin_angles": { "label": "Top/Bottom Line Directions", @@ -1648,6 +1658,17 @@ "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true }, + "connect_infill_polygons": + { + "label": "Connect Infill Polygons", + "description": "Connect infill paths where they run next to each other. For infill patterns which consist of several closed polygons, enabling this setting greatly reduces the travel time.", + "type": "bool", + "default_value": false, + "value": "infill_pattern == 'cross' or infill_pattern == 'cross_3d'", + "enabled": "infill_pattern == 'concentric_3d' or infill_pattern == 'cross' or infill_pattern == 'cross_3d'", + "limit_to_extruder": "infill_extruder_nr", + "settable_per_mesh": true + }, "infill_angles": { "label": "Infill Line Directions", From 5cb5e63dcc41d887c9e6bfa49832fae110611238 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Thu, 17 May 2018 18:41:50 +0200 Subject: [PATCH 045/243] setting fix: make Connect Infill Polygons available for Multiplied Infill --- 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 db40ab2f6a..947c8c86f3 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1664,8 +1664,8 @@ "description": "Connect infill paths where they run next to each other. For infill patterns which consist of several closed polygons, enabling this setting greatly reduces the travel time.", "type": "bool", "default_value": false, - "value": "infill_pattern == 'cross' or infill_pattern == 'cross_3d'", - "enabled": "infill_pattern == 'concentric_3d' or infill_pattern == 'cross' or infill_pattern == 'cross_3d'", + "value": "infill_pattern == 'cross' or infill_pattern == 'cross_3d' or infill_multiplier % 2 = 0", + "enabled": "infill_pattern == 'concentric_3d' or infill_pattern == 'cross' or infill_pattern == 'cross_3d' or infill_multiplier % 2 == 0", "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true }, From 8ccc33d302eac2d3d03d2dc82194210d1a4d593d Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Mon, 23 Jul 2018 14:58:34 +0200 Subject: [PATCH 046/243] make connect_infill_polygons true by default concentric_3d was removed and then the value function is the same as the enabled function, so the default value should be true --- 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 947c8c86f3..10dd0a4171 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1663,9 +1663,9 @@ "label": "Connect Infill Polygons", "description": "Connect infill paths where they run next to each other. For infill patterns which consist of several closed polygons, enabling this setting greatly reduces the travel time.", "type": "bool", - "default_value": false, + "default_value": true, "value": "infill_pattern == 'cross' or infill_pattern == 'cross_3d' or infill_multiplier % 2 = 0", - "enabled": "infill_pattern == 'concentric_3d' or infill_pattern == 'cross' or infill_pattern == 'cross_3d' or infill_multiplier % 2 == 0", + "enabled": "infill_pattern == 'cross' or infill_pattern == 'cross_3d' or infill_multiplier % 2 == 0", "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true }, From fca51ac41f916d315e16a5d90af0e4f405016954 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Wed, 25 Jul 2018 13:44:58 +0200 Subject: [PATCH 047/243] Set relative after getting to line G91 --- plugins/PostProcessingPlugin/scripts/Stretch.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/PostProcessingPlugin/scripts/Stretch.py b/plugins/PostProcessingPlugin/scripts/Stretch.py index 945483c321..377bc4e8da 100644 --- a/plugins/PostProcessingPlugin/scripts/Stretch.py +++ b/plugins/PostProcessingPlugin/scripts/Stretch.py @@ -136,9 +136,11 @@ class Stretcher(): # end of relative movement elif _getValue(line, "G") == 90: in_relative_movement = False + current.setInRelativeMovement(in_relative_movement) # start of relative movement elif _getValue(line, "G") == 91: in_relative_movement = True + current.setInRelativeMovement(in_relative_movement) elif _getValue(line, "G") == 92: current.readStep(line) From 1016564df048077148cf7ec0e729559ebe950e27 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 25 Jul 2018 16:48:32 +0200 Subject: [PATCH 048/243] Fix spelling --- cura/PrintInformation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 1b8ba575db..41faa7cef8 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -369,8 +369,9 @@ class PrintInformation(QObject): def baseName(self): return self._base_name - ## Created an acronymn-like abbreviated machine name from the currently active machine name - # Called each time the global stack is switched + ## Created an acronym-like abbreviated machine name from the currently + # active machine name. + # Called each time the global stack is switched. def _setAbbreviatedMachineName(self): global_container_stack = self._application.getGlobalContainerStack() if not global_container_stack: From 30a7132a688748cad47639263d81f22940810904 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Wed, 25 Jul 2018 17:10:23 +0200 Subject: [PATCH 049/243] Add latest version upgrade plugin to the bundled plugins. --- resources/bundled_packages.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/resources/bundled_packages.json b/resources/bundled_packages.json index 6d9b9d1a95..f281d0d01a 100644 --- a/resources/bundled_packages.json +++ b/resources/bundled_packages.json @@ -662,6 +662,23 @@ } } }, + "VersionUpgrade34to40": { + "package_info": { + "package_id": "VersionUpgrade34to40", + "package_type": "plugin", + "display_name": "Version Upgrade 3.4 to 4.0", + "description": "Upgrades configurations from Cura 3.4 to Cura 4.0.", + "package_version": "1.0.0", + "sdk_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, "X3DReader": { "package_info": { "package_id": "X3DReader", From 9c6b676660bca4d2f8e69afb844f4fc35dbd5b97 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Thu, 26 Jul 2018 10:10:20 +0200 Subject: [PATCH 050/243] fix: typo in setting formula --- 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 10dd0a4171..ed40b32851 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1664,7 +1664,7 @@ "description": "Connect infill paths where they run next to each other. For infill patterns which consist of several closed polygons, enabling this setting greatly reduces the travel time.", "type": "bool", "default_value": true, - "value": "infill_pattern == 'cross' or infill_pattern == 'cross_3d' or infill_multiplier % 2 = 0", + "value": "infill_pattern == 'cross' or infill_pattern == 'cross_3d' or infill_multiplier % 2 == 0", "enabled": "infill_pattern == 'cross' or infill_pattern == 'cross_3d' or infill_multiplier % 2 == 0", "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true From 812816de112bf8b5b7c04a96244e153e53ca4a28 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Thu, 26 Jul 2018 12:53:12 +0200 Subject: [PATCH 051/243] Show Preparing text after clicking Prepare button CURA-5551 --- resources/qml/SaveButton.qml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index 0e0eec7277..b06acdb8d5 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -168,6 +168,8 @@ Item { Button { id: prepareButton + property bool showPrepare : false; + tooltip: [1, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@info:tooltip","Slice current printjob") : catalog.i18nc("@info:tooltip","Cancel slicing process") // 1 = not started, 2 = Processing enabled: base.backendState != "undefined" && ([1, 2].indexOf(base.backendState) != -1) && base.activity @@ -180,9 +182,19 @@ Item { anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width // 1 = not started, 4 = error, 5 = disabled - text: [1, 4, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@label:Printjob", "Prepare") : catalog.i18nc("@label:Printjob", "Cancel") + text: { + + if (base.backendState == 1 && showPrepare) + { + showPrepare = false + return catalog.i18nc("@label:Printjob", "Preparing") + } + + return [1, 4, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@label:Printjob", "Prepare") : catalog.i18nc("@label:Printjob", "Cancel") + } onClicked: { + showPrepare = true sliceOrStopSlicing(); } From 9584b8c579c20b1c0ea92a7e015a7237934dd4d3 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 26 Jul 2018 13:52:51 +0200 Subject: [PATCH 052/243] Bind Top Surface Skin Layers value to Top Surface Skin Extruder CURA-5563 Otherwise, if you set the layers to 2 for extruder 1 and use extruder 2 for Top Surface Skin, it will use the Top Surface Skin Layers value from extruder 2, which is most likely 0, and no top surface skin layers will be printed. --- 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 ed40b32851..e29e08228b 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1074,7 +1074,7 @@ "maximum_value_warning": "top_layers - 1", "type": "int", "value": "0", - "limit_to_extruder": "roofing_extruder_nr", + "limit_to_extruder": "top_bottom_extruder_nr", "settable_per_mesh": true, "enabled": "top_layers > 0" }, From bf219c382170fe8502ba4810d0b9200714d21cbc Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Thu, 26 Jul 2018 13:54:35 +0200 Subject: [PATCH 053/243] Added typing CURA-5595 --- cura/Settings/SidebarCustomMenuItemsModel.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cura/Settings/SidebarCustomMenuItemsModel.py b/cura/Settings/SidebarCustomMenuItemsModel.py index 8c82d288bf..d2a4d1a2b1 100644 --- a/cura/Settings/SidebarCustomMenuItemsModel.py +++ b/cura/Settings/SidebarCustomMenuItemsModel.py @@ -1,6 +1,12 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from typing import Any + from UM.Qt.ListModel import ListModel from PyQt5.QtCore import pyqtSlot, Qt + class SidebarCustomMenuItemsModel(ListModel): NameRole = Qt.UserRole + 1 ActionsRole = Qt.UserRole + 2 @@ -27,7 +33,7 @@ class SidebarCustomMenuItemsModel(ListModel): }) @pyqtSlot(str, "QVariantList", "QVariantMap") - def callMenuItemMethod(self, menu_item_name: str, menu_item_actions: list, kwargs)-> None: + def callMenuItemMethod(self, menu_item_name: str, menu_item_actions: list, kwargs: Any)-> None: for item in self._items: if menu_item_name == item["name"]: for method in menu_item_actions: From e50907894394ea0793b9cddef89238f560825102 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 26 Jul 2018 20:12:42 +0200 Subject: [PATCH 054/243] Fix bug with libSavitar not loading due to SIP The same crash as libArcus actually. --- cura_app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura_app.py b/cura_app.py index c3c766fdb1..164e32e738 100755 --- a/cura_app.py +++ b/cura_app.py @@ -131,6 +131,7 @@ faulthandler.enable(all_threads = True) # first seems to prevent Sip from going into a state where it # tries to create PyQt objects on a non-main thread. import Arcus #@UnusedImport +import Savitar #@UnusedImport from cura.CuraApplication import CuraApplication app = CuraApplication() From b8cca17d46dfd00e55d4d22b0c097962158211a7 Mon Sep 17 00:00:00 2001 From: Mark Burton Date: Fri, 27 Jul 2018 10:01:16 +0100 Subject: [PATCH 055/243] Added the "Within Infill" combing option that functions identically to the original "Not in Skin" option. I've tweaked the blurb to let people know that the original behaviour is still available. --- resources/definitions/fdmprinter.def.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index e29e08228b..0352ae59fd 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3344,13 +3344,14 @@ "retraction_combing": { "label": "Combing Mode", - "description": "Combing keeps the nozzle within already printed areas when traveling. This results in slightly longer travel moves but reduces the need for retractions. If combing is off, the material will retract and the nozzle moves in a straight line to the next point. It is also possible to avoid combing over top/bottom skin areas by combing within the infill only.", + "description": "Combing keeps the nozzle within already printed areas when traveling. This results in slightly longer travel moves but reduces the need for retractions. If combing is off, the material will retract and the nozzle moves in a straight line to the next point. It is also possible to avoid combing over top/bottom skin areas and also to only comb within the infill. Note that the 'Within Infill' option behaves exactly like the 'Not in Skin' option in earlier Cura releases.", "type": "enum", "options": { "off": "Off", "all": "All", - "noskin": "Not in Skin" + "noskin": "Not in Skin", + "infill": "Within Infill" }, "default_value": "all", "resolve": "'noskin' if 'noskin' in extruderValues('retraction_combing') else ('all' if 'all' in extruderValues('retraction_combing') else 'off')", From 403394d5f6264453c26880a4083cebae9296d145 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 27 Jul 2018 11:34:12 +0200 Subject: [PATCH 056/243] Added settings Multiply infill and Connect Infill to Visibility list( Advanced and Expert) CURA-5400 --- resources/setting_visibility/advanced.cfg | 1 + resources/setting_visibility/expert.cfg | 3 +++ 2 files changed, 4 insertions(+) diff --git a/resources/setting_visibility/advanced.cfg b/resources/setting_visibility/advanced.cfg index 43edb13495..9cee353f0c 100644 --- a/resources/setting_visibility/advanced.cfg +++ b/resources/setting_visibility/advanced.cfg @@ -37,6 +37,7 @@ infill_extruder_nr infill_sparse_density infill_line_distance infill_pattern +infill_multiplier infill_overlap infill_sparse_thickness gradual_infill_steps diff --git a/resources/setting_visibility/expert.cfg b/resources/setting_visibility/expert.cfg index 0f15247eb7..0ca2cbab70 100644 --- a/resources/setting_visibility/expert.cfg +++ b/resources/setting_visibility/expert.cfg @@ -37,6 +37,7 @@ bottom_thickness bottom_layers top_bottom_pattern top_bottom_pattern_0 +connect_skin_polygons skin_angles wall_0_inset optimize_wall_printing_order @@ -73,6 +74,8 @@ infill_sparse_density infill_line_distance infill_pattern zig_zaggify_infill +connect_infill_polygons +infill_multiplier infill_angles infill_offset_x infill_offset_y From 8e1c116b5dd6526a849c2a393a7ad1a12f136749 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 27 Jul 2018 13:58:17 +0200 Subject: [PATCH 057/243] Revert "Show Preparing text after clicking Prepare button" This reverts commit 812816de112bf8b5b7c04a96244e153e53ca4a28. --- resources/qml/SaveButton.qml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index b06acdb8d5..0e0eec7277 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -168,8 +168,6 @@ Item { Button { id: prepareButton - property bool showPrepare : false; - tooltip: [1, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@info:tooltip","Slice current printjob") : catalog.i18nc("@info:tooltip","Cancel slicing process") // 1 = not started, 2 = Processing enabled: base.backendState != "undefined" && ([1, 2].indexOf(base.backendState) != -1) && base.activity @@ -182,19 +180,9 @@ Item { anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width // 1 = not started, 4 = error, 5 = disabled - text: { - - if (base.backendState == 1 && showPrepare) - { - showPrepare = false - return catalog.i18nc("@label:Printjob", "Preparing") - } - - return [1, 4, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@label:Printjob", "Prepare") : catalog.i18nc("@label:Printjob", "Cancel") - } + text: [1, 4, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@label:Printjob", "Prepare") : catalog.i18nc("@label:Printjob", "Cancel") onClicked: { - showPrepare = true sliceOrStopSlicing(); } From 5854ae544f7757103e18af25631a525aef898ec4 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 27 Jul 2018 15:32:51 +0200 Subject: [PATCH 058/243] Indicate when "Prepare" button has already been clicked Contributes to CURA-5551 --- resources/qml/SaveButton.qml | 51 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index 0e0eec7277..86339b6795 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -48,14 +48,15 @@ Item { } function sliceOrStopSlicing() { - try { - if ([1, 5].indexOf(base.backendState) != -1) { - CuraApplication.backend.forceSlice(); - } else { - CuraApplication.backend.stopSlicing(); - } - } catch (e) { - console.log('Could not start or stop slicing', e) + if ( [ 1, 5 ].indexOf( base.backendState ) != -1 ) + { + prepareButton.preparingToSlice = true; + CuraApplication.backend.forceSlice(); + } + else + { + prepareButton.preparingToSlice = false; + CuraApplication.backend.stopSlicing(); } } @@ -167,10 +168,10 @@ Item { // Prepare button, only shows if auto_slice is off Button { id: prepareButton - + property bool preparingToSlice: false tooltip: [1, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@info:tooltip","Slice current printjob") : catalog.i18nc("@info:tooltip","Cancel slicing process") // 1 = not started, 2 = Processing - enabled: base.backendState != "undefined" && ([1, 2].indexOf(base.backendState) != -1) && base.activity + enabled: !preparingToSlice && base.backendState != "undefined" && ([1, 2].indexOf(base.backendState) != -1) && base.activity visible: base.backendState != "undefined" && !autoSlice && ([1, 2, 4].indexOf(base.backendState) != -1) && base.activity property bool autoSlice height: UM.Theme.getSize("save_button_save_to_button").height @@ -180,7 +181,23 @@ Item { anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width // 1 = not started, 4 = error, 5 = disabled - text: [1, 4, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@label:Printjob", "Prepare") : catalog.i18nc("@label:Printjob", "Cancel") + text: { + if ( preparingToSlice ) + { + return catalog.i18nc("@label:Printjob", "Preparing"); + } + else + { + if ( [ 1, 4, 5 ].indexOf( base.backendState ) != -1 ) + { + return catalog.i18nc("@label:Printjob", "Prepare"); + } + else + { + return catalog.i18nc("@label:Printjob", "Cancel") + } + } + } onClicked: { sliceOrStopSlicing(); @@ -237,6 +254,18 @@ Item { } label: Item { } } + + Connections { + target: UM.Backend + onStateChanged: + { + if ( [ 2, 3 ].indexOf( UM.Backend.state) != -1 ) + { + prepareButton.preparingToSlice = false; + } + + } + } } Button { From 6694b7ac8186bc2ad429eaade6dd7e8bd8c14588 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 27 Jul 2018 15:56:29 +0200 Subject: [PATCH 059/243] CURA-5541 Change is_enabled field to is_active field to be consistent with the fields in the PackageManager. --- plugins/Toolbox/src/PackagesModel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/Toolbox/src/PackagesModel.py b/plugins/Toolbox/src/PackagesModel.py index 23aa639bde..8b9199b127 100644 --- a/plugins/Toolbox/src/PackagesModel.py +++ b/plugins/Toolbox/src/PackagesModel.py @@ -28,7 +28,7 @@ class PackagesModel(ListModel): self.addRoleName(Qt.UserRole + 11, "download_url") self.addRoleName(Qt.UserRole + 12, "last_updated") self.addRoleName(Qt.UserRole + 13, "is_bundled") - self.addRoleName(Qt.UserRole + 14, "is_enabled") + self.addRoleName(Qt.UserRole + 14, "is_active") self.addRoleName(Qt.UserRole + 15, "is_installed") # Scheduled pkgs are included in the model but should not be marked as actually installed self.addRoleName(Qt.UserRole + 16, "has_configs") self.addRoleName(Qt.UserRole + 17, "supported_configs") @@ -75,7 +75,7 @@ class PackagesModel(ListModel): "download_url": package["download_url"] if "download_url" in package else None, "last_updated": package["last_updated"] if "last_updated" in package else None, "is_bundled": package["is_bundled"] if "is_bundled" in package else False, - "is_enabled": package["is_enabled"] if "is_enabled" in package else False, + "is_active": package["is_active"] if "is_active" in package else False, "is_installed": package["is_installed"] if "is_installed" in package else False, "has_configs": has_configs, "supported_configs": configs_model, From 9418b241d19093229fa39917105b61d7988255fb Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 27 Jul 2018 16:04:36 +0200 Subject: [PATCH 060/243] CURA-5541 Remove duplicated bundled packages. Packages that belong to Uranium must stay in the Uranium's file. --- resources/bundled_packages.json | 272 -------------------------------- 1 file changed, 272 deletions(-) diff --git a/resources/bundled_packages.json b/resources/bundled_packages.json index f281d0d01a..40ed0a9aa2 100644 --- a/resources/bundled_packages.json +++ b/resources/bundled_packages.json @@ -1384,276 +1384,4 @@ } } }, - "ConsoleLogger": { - "package_info": { - "package_id": "ConsoleLogger", - "package_type": "plugin", - "display_name": "Console Logger", - "description": "Outputs log information to the console.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "OBJReader": { - "package_info": { - "package_id": "OBJReader", - "package_type": "plugin", - "display_name": "Wavefront OBJ Reader", - "description": "Makes it possible to read Wavefront OBJ files.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "OBJWriter": { - "package_info": { - "package_id": "OBJWriter", - "package_type": "plugin", - "display_name": "Wavefront OBJ Writer", - "description": "Makes it possible to write Wavefront OBJ files.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "STLReader": { - "package_info": { - "package_id": "STLReader", - "package_type": "plugin", - "display_name": "STL Reader", - "description": "Provides support for reading STL files.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "STLWriter": { - "package_info": { - "package_id": "STLWriter", - "package_type": "plugin", - "display_name": "STL Writer", - "description": "Provides support for writing STL files.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "FileLogger": { - "package_info": { - "package_id": "FileLogger", - "package_type": "plugin", - "display_name": "File Logger", - "description": "Outputs log information to a file in your settings folder.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "LocalContainerProvider": { - "package_info": { - "package_id": "LocalContainerProvider", - "package_type": "plugin", - "display_name": "Local Container Provider", - "description": "Provides built-in setting containers that come with the installation of the application.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "LocalFileOutputDevice": { - "package_info": { - "package_id": "LocalFileOutputDevice", - "package_type": "plugin", - "display_name": "Local File Output Device", - "description": "Enables saving to local files.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "CameraTool": { - "package_info": { - "package_id": "CameraTool", - "package_type": "plugin", - "display_name": "Camera Tool", - "description": "Provides the tool to manipulate the camera.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "MirrorTool": { - "package_info": { - "package_id": "MirrorTool", - "package_type": "plugin", - "display_name": "Mirror Tool", - "description": "Provides the Mirror tool.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "RotateTool": { - "package_info": { - "package_id": "RotateTool", - "package_type": "plugin", - "display_name": "Rotate Tool", - "description": "Provides the Rotate tool.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "ScaleTool": { - "package_info": { - "package_id": "ScaleTool", - "package_type": "plugin", - "display_name": "Scale Tool", - "description": "Provides the Scale tool.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "SelectionTool": { - "package_info": { - "package_id": "SelectionTool", - "package_type": "plugin", - "display_name": "Selection Tool", - "description": "Provides the Selection tool.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "TranslateTool": { - "package_info": { - "package_id": "TranslateTool", - "package_type": "plugin", - "display_name": "Move Tool", - "description": "Provides the Move tool.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "UpdateChecker": { - "package_info": { - "package_id": "UpdateChecker", - "package_type": "plugin", - "display_name": "Update Checker", - "description": "Checks for updates of the software.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, - "SimpleView": { - "package_info": { - "package_id": "SimpleView", - "package_type": "plugin", - "display_name": "Simple View", - "description": "Provides a simple solid mesh view.", - "package_version": "1.0.0", - "sdk_version": 4, - "website": "https://ultimaker.com", - "author": { - "author_id": "Ultimaker", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - } } From 729569034d38c9b7d599f63347bcce1c691a9c95 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 27 Jul 2018 16:12:29 +0200 Subject: [PATCH 061/243] Rename setting Raft Line Spacing -> Raft Base Line Spacing --- resources/definitions/fdmprinter.def.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index e29e08228b..74b36e8d94 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1713,6 +1713,16 @@ "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true }, + "infill_wall_line_count": + { + "label": "infill_wall_line_count", + "description": "Convert each infill line to this many lines. The extra lines do not cross over each other, but avoid each other. This makes the infill stiffer, but increases print time and material usage.", + "default_value": 0, + "type": "int", + "minimum_value": "0", + "maximum_value_warning": "infill_line_distance / infill_line_width", + "settable_per_mesh": true + }, "sub_div_rad_add": { "label": "Cubic Subdivision Shell", @@ -4723,7 +4733,7 @@ }, "raft_base_line_spacing": { - "label": "Raft Line Spacing", + "label": "Raft Base Line Spacing", "description": "The distance between the raft lines for the base raft layer. Wide spacing makes for easy removal of the raft from the build plate.", "unit": "mm", "type": "float", From e1db7eb83148053b5f8d39fbcb2e4519711fce76 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Fri, 18 May 2018 12:17:28 +0200 Subject: [PATCH 062/243] setting: infill_wall_line_count --- resources/definitions/fdmprinter.def.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 74b36e8d94..373ddc879c 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1715,12 +1715,13 @@ }, "infill_wall_line_count": { - "label": "infill_wall_line_count", - "description": "Convert each infill line to this many lines. The extra lines do not cross over each other, but avoid each other. This makes the infill stiffer, but increases print time and material usage.", + "label": "Extra Infill Wall Count", + "description": "Add extra wals around the infill area. Such walls can make top/bottom skin lines sag down less which means you need less top/bottom skin layers for the same quality at the cost of some extra material.\nThis feature can combine with the Connect Infill Polygons to connect all the infill into a single extrusion path without the need for travels or retractions if configured right.", "default_value": 0, "type": "int", "minimum_value": "0", - "maximum_value_warning": "infill_line_distance / infill_line_width", + "enabled": "infill_sparse_density > 0 and not spaghetti_infill_enabled", + "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true }, "sub_div_rad_add": From a1661df9d794cb63355dcdb5a09a74a094d4806a Mon Sep 17 00:00:00 2001 From: milkok Date: Sat, 28 Jul 2018 17:04:30 +0800 Subject: [PATCH 063/243] Update winbo_superhelper105_extruder.def.json --- resources/extruders/winbo_superhelper105_extruder.def.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/extruders/winbo_superhelper105_extruder.def.json b/resources/extruders/winbo_superhelper105_extruder.def.json index 1224a5a29a..a974317937 100644 --- a/resources/extruders/winbo_superhelper105_extruder.def.json +++ b/resources/extruders/winbo_superhelper105_extruder.def.json @@ -1,5 +1,4 @@ { - "id": "winbo_superhelper105_extruder", "version": 2, "name": "Extruder 1", "inherits": "fdmextruder", @@ -13,6 +12,8 @@ "default_value": 0, "maximum_value": "2" }, + "material_diameter": { "default_value": 1.75 }, + "machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_offset_x": { "default_value": 0.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 } } From 29f9beb55000d96f3d50f20f811af5e7abc86839 Mon Sep 17 00:00:00 2001 From: milkok Date: Sat, 28 Jul 2018 17:06:23 +0800 Subject: [PATCH 064/243] Update winbo_superhelper105.def.json --- resources/definitions/winbo_superhelper105.def.json | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/definitions/winbo_superhelper105.def.json b/resources/definitions/winbo_superhelper105.def.json index f51d5d9070..59e71fb446 100644 --- a/resources/definitions/winbo_superhelper105.def.json +++ b/resources/definitions/winbo_superhelper105.def.json @@ -41,7 +41,6 @@ "machine_extruder_count": { "default_value": 1 }, "machine_start_gcode": { "default_value": "G21\nG90\nM82\nM107\nG28 X0 Y0\nG28 Z0\nG1 F6000 Z0.3\nG92 E0\nG1 F1000 X30 E8\nG92 E0\nM117 Printing." }, "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\nG92 E2\nG1 E0 F200\nG28 X0 Y0\nM84 X Y E" }, - "material_diameter": { "default_value": 1.75 }, "prime_blob_enable": { "enabled": true }, "acceleration_enabled": { "value": "True" }, "acceleration_layer_0": { "value": "acceleration_topbottom" }, From 66a9c885a79965be7fc24b4a9f585834c50ece1c Mon Sep 17 00:00:00 2001 From: milkok Date: Sat, 28 Jul 2018 17:09:09 +0800 Subject: [PATCH 065/243] Update winbo_superhelper155_extruder.def.json --- resources/extruders/winbo_superhelper155_extruder.def.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/extruders/winbo_superhelper155_extruder.def.json b/resources/extruders/winbo_superhelper155_extruder.def.json index 9935084872..2b406ed43c 100644 --- a/resources/extruders/winbo_superhelper155_extruder.def.json +++ b/resources/extruders/winbo_superhelper155_extruder.def.json @@ -13,6 +13,8 @@ "default_value": 0, "maximum_value": "2" }, + "material_diameter": { "default_value": 1.75 }, + "machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_offset_x": { "default_value": 0.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 } } From 43e5110db666c487a5eccdb0656192b580aba941 Mon Sep 17 00:00:00 2001 From: milkok Date: Sat, 28 Jul 2018 17:12:32 +0800 Subject: [PATCH 066/243] Update winbo_mini2_extruder.def.json --- resources/extruders/winbo_mini2_extruder.def.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/extruders/winbo_mini2_extruder.def.json b/resources/extruders/winbo_mini2_extruder.def.json index 5348e6ad43..a57ec28109 100644 --- a/resources/extruders/winbo_mini2_extruder.def.json +++ b/resources/extruders/winbo_mini2_extruder.def.json @@ -1,5 +1,4 @@ { - "id": "winbo_mini2_extruder", "version": 2, "name": "Extruder 1", "inherits": "fdmextruder", @@ -13,6 +12,8 @@ "default_value": 0, "maximum_value": "2" }, + "material_diameter": { "default_value": 1.75 }, + "machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_offset_x": { "default_value": 0.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 } } From c4647cd8ad25305148ef3b5e22d57cca986af6c3 Mon Sep 17 00:00:00 2001 From: milkok Date: Sat, 28 Jul 2018 17:12:49 +0800 Subject: [PATCH 067/243] Update winbo_superhelper155_extruder.def.json --- resources/extruders/winbo_superhelper155_extruder.def.json | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/extruders/winbo_superhelper155_extruder.def.json b/resources/extruders/winbo_superhelper155_extruder.def.json index 2b406ed43c..6d83689bf4 100644 --- a/resources/extruders/winbo_superhelper155_extruder.def.json +++ b/resources/extruders/winbo_superhelper155_extruder.def.json @@ -1,5 +1,4 @@ { - "id": "winbo_superhelper155_extruder", "version": 2, "name": "Extruder 1", "inherits": "fdmextruder", From c05d85f1e426bba65f646830f5e51cda80084640 Mon Sep 17 00:00:00 2001 From: milkok Date: Sat, 28 Jul 2018 17:14:04 +0800 Subject: [PATCH 068/243] Update winbo_dragonl4_extruder.def.json --- resources/extruders/winbo_dragonl4_extruder.def.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/extruders/winbo_dragonl4_extruder.def.json b/resources/extruders/winbo_dragonl4_extruder.def.json index a4f65bbf0e..37a08c8d08 100644 --- a/resources/extruders/winbo_dragonl4_extruder.def.json +++ b/resources/extruders/winbo_dragonl4_extruder.def.json @@ -1,5 +1,4 @@ { - "id": "winbo_dragonl4_extruder", "version": 2, "name": "Extruder 1", "inherits": "fdmextruder", @@ -13,6 +12,8 @@ "default_value": 0, "maximum_value": "2" }, + "material_diameter": { "default_value": 3.0 }, + "machine_nozzle_size": { "default_value": 0.8 }, "machine_nozzle_offset_x": { "default_value": 0.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 } } From 29f2bb8a3a6344f66ee1bd64118dbd2759e3ca52 Mon Sep 17 00:00:00 2001 From: milkok Date: Sat, 28 Jul 2018 17:15:36 +0800 Subject: [PATCH 069/243] Update winbo_dragonl4.def.json --- resources/definitions/winbo_dragonl4.def.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/resources/definitions/winbo_dragonl4.def.json b/resources/definitions/winbo_dragonl4.def.json index cb5566c46b..5aa004414a 100644 --- a/resources/definitions/winbo_dragonl4.def.json +++ b/resources/definitions/winbo_dragonl4.def.json @@ -25,7 +25,6 @@ "machine_filament_park_distance": { "value": "machine_heat_zone_length" }, "machine_nozzle_heat_up_speed": { "default_value": 1.4 }, "machine_nozzle_cool_down_speed": { "default_value": 0.8 }, - "machine_nozzle_size": { "default_value": 0.8 }, "machine_head_with_fans_polygon": { "default_value": @@ -42,7 +41,6 @@ "machine_extruder_count": { "default_value": 1 }, "machine_start_gcode": { "default_value": "G21\nG90\nM82\nM107\nM9998\nG28 X0 Y0\nG28 Z0\nG1 F6000 Z0.3\nG92 E0\nG1 F800 X585 E12\nG92 E0" }, "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\nG92 E2\nG1 E0 F200\nG28 X0 Y0\nM84 X Y E" }, - "material_diameter": { "default_value": 3.0 }, "prime_blob_enable": { "enabled": true }, "acceleration_enabled": { "value": "True" }, "acceleration_layer_0": { "value": "acceleration_topbottom" }, From 380ab22c4237a39f36ba50e351f23e45cb9b3832 Mon Sep 17 00:00:00 2001 From: milkok Date: Sat, 28 Jul 2018 17:19:13 +0800 Subject: [PATCH 070/243] Update winbo_mini2.def.json --- resources/definitions/winbo_mini2.def.json | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/definitions/winbo_mini2.def.json b/resources/definitions/winbo_mini2.def.json index d166b7847e..85c5a445bd 100644 --- a/resources/definitions/winbo_mini2.def.json +++ b/resources/definitions/winbo_mini2.def.json @@ -41,7 +41,6 @@ "machine_extruder_count": { "default_value": 1 }, "machine_start_gcode": { "default_value": "G21\nG90\nM82\nM107\nG28 X0 Y0\nG28 Z0\nG1 F1000 Z3\nG1 F4000 X0\nG1 F4000 Y0\nG1 F1000 Z0.2\nG92 E0\nG1 F1000 X30 E8\nG92 E0\nM117 Printing." }, "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\nG92 E2\nG1 E0 F200\nG28 X0 Y0\nM84 X Y E" }, - "material_diameter": { "default_value": 1.75 }, "prime_blob_enable": { "enabled": true }, "acceleration_enabled": { "value": "True" }, "acceleration_layer_0": { "value": "acceleration_topbottom" }, From 2ef48c725ec59fb7fa422c77dd783763f1051941 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 28 Jul 2018 16:13:14 +0200 Subject: [PATCH 071/243] add new definition/quality/mesh of 3D printer by TiZYX --- resources/definitions/tizyx_k25.def.json | 47 ++++++++++++++++++ resources/meshes/tizyx_k25_platform.stl | Bin 0 -> 63884 bytes .../tizyx_k25/tizyx_k25_normal.inst.cfg | 31 ++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 resources/definitions/tizyx_k25.def.json create mode 100644 resources/meshes/tizyx_k25_platform.stl create mode 100644 resources/quality/tizyx_k25/tizyx_k25_normal.inst.cfg diff --git a/resources/definitions/tizyx_k25.def.json b/resources/definitions/tizyx_k25.def.json new file mode 100644 index 0000000000..f460b524a2 --- /dev/null +++ b/resources/definitions/tizyx_k25.def.json @@ -0,0 +1,47 @@ +{ + "version": 2, + "name": "TiZYX K25", + "inherits": "fdmprinter", + "metadata": + { + "visible": true, + "author": "TiZYX", + "manufacturer": "TiZYX", + "file_formats": "text/x-gcode", + "platform": "tizyx_k25_platform.stl", + "exclude_materials": ["chromatik_pla", "dsm_arnitel2045_175", "dsm_novamid1070_175", "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu", "fiberlogy_hd_pla", "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red", "generic_abs", "generic_abs_175", "generic_bam", "generic_cpe", "generic_cpe_175", "generic_cpe_plus", "generic_hips", "generic_hips_175", "generic_nylon", "generic_nylon_175", "generic_pc", "generic_pc_175", "generic_petg", "generic_petg_175", "generic_pla", "generic_pla_175", "generic_pp", "generic_pva", "generic_pva_175", "generic_tough_pla", "generic_tpu", "imade3d_petg_green", "imade3d_petg_pink", "imade3d_pla_green", "imade3d_pla_pink", "innofill_innoflex60_175", "octofiber_pla", "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla", "ultimaker_abs_black", "ultimaker_abs_blue", "ultimaker_abs_green", "ultimaker_abs_grey", "ultimaker_abs_orange", "ultimaker_abs_pearl-gold", "ultimaker_abs_red", "ultimaker_abs_silver-metallic", "ultimaker_abs_white", "ultimaker_abs_yellow", "ultimaker_bam", "ultimaker_cpe_black", "ultimaker_cpe_blue", "ultimaker_cpe_dark-grey", "ultimaker_cpe_green", "ultimaker_cpe_light-grey", "ultimaker_cpe_plus_black", "ultimaker_cpe_plus_transparent", "ultimaker_cpe_plus_white", "ultimaker_cpe_red", "ultimaker_cpe_transparent", "ultimaker_cpe_white", "ultimaker_cpe_yellow", "ultimaker_nylon_black", "ultimaker_nylon_transparent", "ultimaker_pc_black", "ultimaker_pc_transparent", "ultimaker_pc_white", "ultimaker_pla_black", "ultimaker_pla_blue", "ultimaker_pla_green", "ultimaker_pla_magenta", "ultimaker_pla_orange", "ultimaker_pla_pearl-white", "ultimaker_pla_red", "ultimaker_pla_silver-metallic", "ultimaker_pla_transparent", "ultimaker_pla_white", "ultimaker_pla_yellow", "ultimaker_pp_transparent", "ultimaker_pva", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "ultimaker_tpu_black", "ultimaker_tpu_blue", "ultimaker_tpu_red", "ultimaker_tpu_white", "verbatim_bvoh_175", "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_TPU", "zyyx_pro_flex", "zyyx_pro_pla" ], + "preferred_material": "tizyx_pla", + "has_machine_quality": true, + "has_materials": true + + }, + + "overrides": + { + "machine_heated_bed": { "default_value": true }, + "machine_width": { "default_value": 255 }, + "machine_height": { "default_value": 255 }, + "machine_depth": { "default_value": 255 }, + "machine_center_is_zero": { "default_value": false }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 }, + "gantry_height": { "default_value": 500 }, + "machine_head_with_fans_polygon": { + "default_value": [ + [25, 49], + [25, -49], + [-25, -49], + [25, 49] + ] + }, + "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, + "machine_start_gcode": + { + "default_value": "M82\nG90\nG28 X\nG28 Y\nG28 Z\nG29\nG91\nG1 Z0\nG90\nM82\nG92 E0\nG1 X125 Y245 F3000\nG1 Z0" + }, + "machine_end_gcode": + { + "default_value": "M104 S0\nM140 S0\nG91\nG1 E-5 F300\nG1 Z+3 F3000\nG1 Y245 F3000\nM84" + } + } +} diff --git a/resources/meshes/tizyx_k25_platform.stl b/resources/meshes/tizyx_k25_platform.stl new file mode 100644 index 0000000000000000000000000000000000000000..5417aaed5f7ec2e8b4c62467bfc6b115b07a6bb5 GIT binary patch literal 63884 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 ZB7k7|Sf(rM57&|4Xkl^l4H$gA% z)uaR!?zS*?N^qXw-n$?Fzvn0tZfgyvDC!?n+_ss4`|#;mxtFCyFSoUZV+<;8+swdy z_%w!lSz7dRTWdJRpyIa84BUrLW4M>4MK8CthGPsWZrjM&+Sv|}O4q$CEqb}#o(-I^ zbh*FpM0;$fLV`Q@F&Cwe?XKAB&IwyhdP?oHqC&#Ywk|7+(YI(^8*0Ys#k--JiF(!j zTJv;*3JJ|o;ZAkD&uQ+X2zt4l%xdwhsJLzEYAw;Lu50a_su(4eQAFJmOFt_TZkw0Z zM7`>|Hil4Hl~hI%b&slJkZ{|)w6^P2*R_m6WfW1540Q|=Zkw0ZsOepqSmz~`QA9Fc z#rh!Ows~px85M&H35|)p_}qc=?e#%|UK)2t#HjB4NFm{NvTl$0pyIaWLu2L0`l#+< z+gLk_sOuwSMm>sYxjh_%N3|=BqEbc?b-Su#kZ^lA29N3=8bzgyBI^E8#~|VMa18EM z`&X(%wJVJ>QbrN=$WX^1;kJ2c9P3s0&l!WtC?XjXW1Tx;3JHym8toLpYmfxJ{JyHL zws}^r*h=3CTj_gB$!w6El_@0r4C^tmE-Ur}w})%^QT>BGY7|kg^h?jV6Q+>R`mtBt z8AZ;kUFTlBUqdhMa?8JpQSz=8?~*ZILe%}-a!Z1D<+=%a@$O{9RxBIME?z}g_noVLPHAsSYPr3$5$EFQ~h|mpHm^>D<|D)P!!D{B(^b literal 0 HcmV?d00001 diff --git a/resources/quality/tizyx_k25/tizyx_k25_normal.inst.cfg b/resources/quality/tizyx_k25/tizyx_k25_normal.inst.cfg new file mode 100644 index 0000000000..399a7a51ab --- /dev/null +++ b/resources/quality/tizyx_k25/tizyx_k25_normal.inst.cfg @@ -0,0 +1,31 @@ +[general] +version = 4 +name = TiZYX K25 Normal +definition = tizyx_k25 + +[metadata] +quality_type = normal +setting_version = 4 +type = quality +global_quality = True + +[values] +adhesion_type = skirt +skirt_line_count = 2 +skirt_gap = 2 +cool_fan_speed_0 = 100 +fill_outline_gaps = True +infill_angles = [0,90 ] +infill_sparse_density = 15 +layer_height = 0.2 +layer_height_0 = 0.25 +material_diameter = 1.75 +retraction_amount = 2.5 +retraction_min_travel = 2 +retraction_speed = 30 +skin_angles = [0,90] +speed_print = 60 +speed_topbottom = 50 +speed_wall_0 = 40 +top_layers = 4 +wall_line_count = 2 From 2790650686e8d0487381f4adfab3928595f9fb19 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 30 Jul 2018 09:39:10 +0200 Subject: [PATCH 072/243] Code style improvements Contributes to CURA-5551 --- resources/qml/SaveButton.qml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index 86339b6795..9b5e3befb0 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -48,7 +48,7 @@ Item { } function sliceOrStopSlicing() { - if ( [ 1, 5 ].indexOf( base.backendState ) != -1 ) + if ([1, 5].indexOf(base.backendState) != -1) { prepareButton.preparingToSlice = true; CuraApplication.backend.forceSlice(); @@ -182,13 +182,13 @@ Item { // 1 = not started, 4 = error, 5 = disabled text: { - if ( preparingToSlice ) + if (preparingToSlice) { return catalog.i18nc("@label:Printjob", "Preparing"); } else { - if ( [ 1, 4, 5 ].indexOf( base.backendState ) != -1 ) + if ([1, 4, 5].indexOf(base.backendState) != -1) { return catalog.i18nc("@label:Printjob", "Prepare"); } @@ -259,11 +259,10 @@ Item { target: UM.Backend onStateChanged: { - if ( [ 2, 3 ].indexOf( UM.Backend.state) != -1 ) + if ([2, 3].indexOf(UM.Backend.state) != -1) { prepareButton.preparingToSlice = false; } - } } } From 6a083e91b0c6b7a2f26466235af3a0a4c8306cec Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 30 Jul 2018 11:05:14 +0200 Subject: [PATCH 073/243] Fix typo. Remove comma. --- resources/bundled_packages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/bundled_packages.json b/resources/bundled_packages.json index 40ed0a9aa2..d216415921 100644 --- a/resources/bundled_packages.json +++ b/resources/bundled_packages.json @@ -1383,5 +1383,5 @@ "website": "https://www.vellemanprojects.eu" } } - }, + } } From 7215b8081d64d724ace6967f096c9334eddff556 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 30 Jul 2018 13:08:13 +0200 Subject: [PATCH 074/243] Fix the scrolling when the cursor is hovering the combobox settings. --- resources/qml/Settings/SettingComboBox.qml | 7 ------- resources/qml/Settings/SettingExtruder.qml | 7 ------- resources/qml/Settings/SettingOptionalExtruder.qml | 7 ------- 3 files changed, 21 deletions(-) diff --git a/resources/qml/Settings/SettingComboBox.qml b/resources/qml/Settings/SettingComboBox.qml index 5462c26398..5d283d5ebb 100644 --- a/resources/qml/Settings/SettingComboBox.qml +++ b/resources/qml/Settings/SettingComboBox.qml @@ -20,13 +20,6 @@ SettingItem anchors.fill: parent - MouseArea - { - anchors.fill: parent - acceptedButtons: Qt.NoButton - onWheel: wheel.accepted = true - } - background: Rectangle { color: diff --git a/resources/qml/Settings/SettingExtruder.qml b/resources/qml/Settings/SettingExtruder.qml index 83f06ebc5f..4c00a60d0e 100644 --- a/resources/qml/Settings/SettingExtruder.qml +++ b/resources/qml/Settings/SettingExtruder.qml @@ -71,13 +71,6 @@ SettingItem currentIndex: propertyProvider.properties.value - MouseArea - { - anchors.fill: parent - acceptedButtons: Qt.NoButton - onWheel: wheel.accepted = true; - } - property string color: "#fff" Binding diff --git a/resources/qml/Settings/SettingOptionalExtruder.qml b/resources/qml/Settings/SettingOptionalExtruder.qml index db79468315..2d4f25125f 100644 --- a/resources/qml/Settings/SettingOptionalExtruder.qml +++ b/resources/qml/Settings/SettingOptionalExtruder.qml @@ -76,13 +76,6 @@ SettingItem when: control.model.items.length > 0 } - MouseArea - { - anchors.fill: parent - acceptedButtons: Qt.NoButton - onWheel: wheel.accepted = true; - } - property string color: "#fff" Binding From c036912752df2f47f674c6196f83e9df54f90200 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 30 Jul 2018 13:31:10 +0200 Subject: [PATCH 075/243] Pressing enter on project window will now open the file dialog to save instead of just closing the window --- resources/qml/WorkspaceSummaryDialog.qml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/resources/qml/WorkspaceSummaryDialog.qml b/resources/qml/WorkspaceSummaryDialog.qml index 079d840ae7..24e94beb88 100644 --- a/resources/qml/WorkspaceSummaryDialog.qml +++ b/resources/qml/WorkspaceSummaryDialog.qml @@ -24,6 +24,10 @@ UM.Dialog signal yes(); + function accept() { // pressing enter will call this function + close(); + yes(); + } onClosing: { @@ -290,4 +294,4 @@ UM.Dialog } } } -} \ No newline at end of file +} From 2584d58904c01f14c7a5fa3ca60717ff60bdf1e9 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 30 Jul 2018 22:51:02 +0200 Subject: [PATCH 076/243] correction extruder --- resources/definitions/tizyx_k25.def.json | 12 +++++++----- .../extruders/tizyx_k25_extruder_0.def.json | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 resources/extruders/tizyx_k25_extruder_0.def.json diff --git a/resources/definitions/tizyx_k25.def.json b/resources/definitions/tizyx_k25.def.json index f460b524a2..55256a29d6 100644 --- a/resources/definitions/tizyx_k25.def.json +++ b/resources/definitions/tizyx_k25.def.json @@ -12,20 +12,22 @@ "exclude_materials": ["chromatik_pla", "dsm_arnitel2045_175", "dsm_novamid1070_175", "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu", "fiberlogy_hd_pla", "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red", "generic_abs", "generic_abs_175", "generic_bam", "generic_cpe", "generic_cpe_175", "generic_cpe_plus", "generic_hips", "generic_hips_175", "generic_nylon", "generic_nylon_175", "generic_pc", "generic_pc_175", "generic_petg", "generic_petg_175", "generic_pla", "generic_pla_175", "generic_pp", "generic_pva", "generic_pva_175", "generic_tough_pla", "generic_tpu", "imade3d_petg_green", "imade3d_petg_pink", "imade3d_pla_green", "imade3d_pla_pink", "innofill_innoflex60_175", "octofiber_pla", "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla", "ultimaker_abs_black", "ultimaker_abs_blue", "ultimaker_abs_green", "ultimaker_abs_grey", "ultimaker_abs_orange", "ultimaker_abs_pearl-gold", "ultimaker_abs_red", "ultimaker_abs_silver-metallic", "ultimaker_abs_white", "ultimaker_abs_yellow", "ultimaker_bam", "ultimaker_cpe_black", "ultimaker_cpe_blue", "ultimaker_cpe_dark-grey", "ultimaker_cpe_green", "ultimaker_cpe_light-grey", "ultimaker_cpe_plus_black", "ultimaker_cpe_plus_transparent", "ultimaker_cpe_plus_white", "ultimaker_cpe_red", "ultimaker_cpe_transparent", "ultimaker_cpe_white", "ultimaker_cpe_yellow", "ultimaker_nylon_black", "ultimaker_nylon_transparent", "ultimaker_pc_black", "ultimaker_pc_transparent", "ultimaker_pc_white", "ultimaker_pla_black", "ultimaker_pla_blue", "ultimaker_pla_green", "ultimaker_pla_magenta", "ultimaker_pla_orange", "ultimaker_pla_pearl-white", "ultimaker_pla_red", "ultimaker_pla_silver-metallic", "ultimaker_pla_transparent", "ultimaker_pla_white", "ultimaker_pla_yellow", "ultimaker_pp_transparent", "ultimaker_pva", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "ultimaker_tpu_black", "ultimaker_tpu_blue", "ultimaker_tpu_red", "ultimaker_tpu_white", "verbatim_bvoh_175", "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_TPU", "zyyx_pro_flex", "zyyx_pro_pla" ], "preferred_material": "tizyx_pla", "has_machine_quality": true, - "has_materials": true - + "has_materials": true, + "machine_extruder_trains": + { + "0": "tizyx_k25_extruder_0" + } }, "overrides": { + "machine_name": { "default_value": "TiZYX K25" }, "machine_heated_bed": { "default_value": true }, "machine_width": { "default_value": 255 }, "machine_height": { "default_value": 255 }, "machine_depth": { "default_value": 255 }, "machine_center_is_zero": { "default_value": false }, - "machine_nozzle_size": { "default_value": 0.4 }, - "material_diameter": { "default_value": 1.75 }, - "gantry_height": { "default_value": 500 }, + "gantry_height": { "default_value": 500 }, "machine_head_with_fans_polygon": { "default_value": [ [25, 49], diff --git a/resources/extruders/tizyx_k25_extruder_0.def.json b/resources/extruders/tizyx_k25_extruder_0.def.json new file mode 100644 index 0000000000..409198d77c --- /dev/null +++ b/resources/extruders/tizyx_k25_extruder_0.def.json @@ -0,0 +1,16 @@ +{ + "id": "tizyx_k25_extruder_0", + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "tizyx_k25", + "position": "0" + }, + + "overrides": { + "extruder_nr": { "default_value": 0 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} \ No newline at end of file From 846c55a99d0486bea3623e47412c36d0ab71f0fe Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 31 Jul 2018 09:47:18 +0200 Subject: [PATCH 077/243] Simplify detection of url-encoded filepatch --- plugins/USBPrinting/USBPrinterOutputDevice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index 6a97a3c163..7c4d85a5cd 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -127,8 +127,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice): @pyqtSlot(str) def updateFirmware(self, file): - # the file path could be qurl encoded. - if file[:7] == "file://": + # the file path could be url-encoded. + if file.startswith("file://"): self._firmware_location = QUrl(file).toLocalFile() else: self._firmware_location = file From 1e2c590c54aa77d7945c6eb4953c4a0d0d823bf7 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 31 Jul 2018 09:50:43 +0200 Subject: [PATCH 078/243] In multi build plate mode objects are now always arranged instead of never. CURA-5606 --- cura/CuraApplication.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 8dd17896bb..9f4ea7b3d3 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1605,8 +1605,7 @@ class CuraApplication(QtApplication): self._currently_loading_files.remove(file_name) self.fileLoaded.emit(file_name) - arrange_objects_on_load = not self.getPreferences().getValue("cura/use_multi_build_plate") - target_build_plate = self.getMultiBuildPlateModel().activeBuildPlate if arrange_objects_on_load else -1 + target_build_plate = self.getMultiBuildPlateModel().activeBuildPlate root = self.getController().getScene().getRoot() fixed_nodes = [] @@ -1660,7 +1659,7 @@ class CuraApplication(QtApplication): if not child.getDecorator(ConvexHullDecorator): child.addDecorator(ConvexHullDecorator()) - if file_extension != "3mf" and arrange_objects_on_load: + if file_extension != "3mf": if node.callDecoration("isSliceable"): # Only check position if it's not already blatantly obvious that it won't fit. if node.getBoundingBox() is None or self._volume.getBoundingBox() is None or node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth: From e55775175230efeb4a87eeb82d14b9498619dd4c Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 31 Jul 2018 11:31:46 +0200 Subject: [PATCH 079/243] Add the active build plate name to default (not user specified) job name --- cura/PrintInformation.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 41faa7cef8..1e09cd9baa 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -267,6 +267,7 @@ class PrintInformation(QObject): new_active_build_plate = self._multi_build_plate_model.activeBuildPlate if new_active_build_plate != self._active_build_plate: self._active_build_plate = new_active_build_plate + self._updateJobName() self._initVariablesWithBuildPlate(self._active_build_plate) @@ -310,15 +311,18 @@ class PrintInformation(QObject): # Only update the job name when it's not user-specified. if not self._is_user_specified_job_name: if self._pre_sliced: - self._job_name = catalog.i18nc("@label", "Pre-sliced file {0}", base_name) + job_name = catalog.i18nc("@label", "Pre-sliced file {0}", base_name) elif self._application.getInstance().getPreferences().getValue("cura/jobname_prefix"): # Don't add abbreviation if it already has the exact same abbreviation. if base_name.startswith(self._abbr_machine + "_"): - self._job_name = base_name + job_name = base_name else: - self._job_name = self._abbr_machine + "_" + base_name + job_name = self._abbr_machine + "_" + base_name else: - self._job_name = base_name + job_name = base_name + if self._active_build_plate != 0: + job_name += "-{}".format(self._active_build_plate) + self._job_name = job_name self.jobNameChanged.emit() From be177939b56be6dcb605bc4e5c44f01769b546d7 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 31 Jul 2018 17:09:33 +0200 Subject: [PATCH 080/243] Reverts other commit bound to CURA-5563, that was not correct. --- 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 373ddc879c..b767aac7b9 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1074,7 +1074,7 @@ "maximum_value_warning": "top_layers - 1", "type": "int", "value": "0", - "limit_to_extruder": "top_bottom_extruder_nr", + "limit_to_extruder": "roofing_extruder_nr", "settable_per_mesh": true, "enabled": "top_layers > 0" }, From d1b6aa8c375f070f49fdf3b8c216ecf4564bf69e Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Wed, 1 Aug 2018 08:33:47 +0200 Subject: [PATCH 081/243] Set the focus in the upper handle in the layer view instead of in the text field. That makes it easier to release the focus by clicking in the main view and use the arrow keys to rotate the view. --- plugins/SimulationView/LayerSlider.qml | 4 ++++ plugins/SimulationView/SimulationSliderLabel.qml | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/SimulationView/LayerSlider.qml b/plugins/SimulationView/LayerSlider.qml index 22f9d91340..ab752419db 100644 --- a/plugins/SimulationView/LayerSlider.qml +++ b/plugins/SimulationView/LayerSlider.qml @@ -67,6 +67,10 @@ Item { activeHandle = handle } + // make sure the upper handle is focussed when pressing the parent handle + // needed to connect the key bindings when switching active handle + onVisibleChanged: if (visible) upperHandleLabel.forceActiveFocus() + // slider track Rectangle { id: track diff --git a/plugins/SimulationView/SimulationSliderLabel.qml b/plugins/SimulationView/SimulationSliderLabel.qml index 8615a382da..94167d001e 100644 --- a/plugins/SimulationView/SimulationSliderLabel.qml +++ b/plugins/SimulationView/SimulationSliderLabel.qml @@ -25,10 +25,6 @@ UM.PointingRectangle { width: valueLabel.width + UM.Theme.getSize("default_margin").width visible: false - // make sure the text field is focussed when pressing the parent handle - // needed to connect the key bindings when switching active handle - onVisibleChanged: if (visible) valueLabel.forceActiveFocus() - color: UM.Theme.getColor("tool_panel_background") borderColor: UM.Theme.getColor("lining") borderWidth: UM.Theme.getSize("default_lining").width From 4406b621a5d3935ca55ba9b737d53127f1a14924 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Wed, 1 Aug 2018 08:46:44 +0200 Subject: [PATCH 082/243] Fix quality profiles for Dagoma Neva Magis. Contributes to CURA-5499. --- resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg | 2 +- resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg | 2 +- .../quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg index efdf2f7d32..e52cba165c 100644 --- a/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_fast.inst.cfg @@ -1,7 +1,7 @@ [general] version = 4 name = Fast -definition = dagoma_neva +definition = dagoma_neva_magis [metadata] setting_version = 5 diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg index 50915db112..033cfbc8fa 100644 --- a/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_fine.inst.cfg @@ -1,7 +1,7 @@ [general] version = 4 name = Fine -definition = dagoma_neva +definition = dagoma_neva_magis [metadata] setting_version = 5 diff --git a/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg index ed67800eac..d07d5b58d5 100644 --- a/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg +++ b/resources/quality/dagoma/dagoma_neva_magis_pla_standard.inst.cfg @@ -1,7 +1,7 @@ [general] version = 4 name = Standard -definition = dagoma_neva +definition = dagoma_neva_magis [metadata] setting_version = 5 From 56437af4d2a892c8789d433d67046de467188314 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 1 Aug 2018 10:50:29 +0200 Subject: [PATCH 083/243] CURA-5613 Don't focus on slider This way arrow keys are able to rotate the viewport --- plugins/SimulationView/LayerSlider.qml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/SimulationView/LayerSlider.qml b/plugins/SimulationView/LayerSlider.qml index ab752419db..22f9d91340 100644 --- a/plugins/SimulationView/LayerSlider.qml +++ b/plugins/SimulationView/LayerSlider.qml @@ -67,10 +67,6 @@ Item { activeHandle = handle } - // make sure the upper handle is focussed when pressing the parent handle - // needed to connect the key bindings when switching active handle - onVisibleChanged: if (visible) upperHandleLabel.forceActiveFocus() - // slider track Rectangle { id: track From b8ec1d0fa768d790b6fb172d212060a9b500f1ae Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 1 Aug 2018 10:52:31 +0200 Subject: [PATCH 084/243] In relative mode, the feedback is still absolute and not relative. CURA-5480 --- plugins/PostProcessingPlugin/scripts/Stretch.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/Stretch.py b/plugins/PostProcessingPlugin/scripts/Stretch.py index 377bc4e8da..9757296041 100644 --- a/plugins/PostProcessingPlugin/scripts/Stretch.py +++ b/plugins/PostProcessingPlugin/scripts/Stretch.py @@ -62,13 +62,12 @@ class GCodeStep(): delta_step_y = _getValue(line, "Y", 0) delta_step_z = _getValue(line, "Z", 0) delta_step_e = _getValue(line, "E", 0) - delta_step_f = _getValue(line, "F", 0) self.step_x += delta_step_x self.step_y += delta_step_y self.step_z += delta_step_z self.step_e += delta_step_e - self.step_f += delta_step_f + self.step_f = _getValue(line, "F", self.step_f) # the feedrate is not relative def copyPosFrom(self, step): """ From d57090c049f43cb5d3f62894bc0bada3ef654b2c Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Wed, 1 Aug 2018 12:53:07 +0200 Subject: [PATCH 085/243] Allow the user to change the name and even though the name in the different buildplates will change accordingly to the build plate number. --- cura/PrintInformation.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 1e09cd9baa..21e2040dc1 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -311,18 +311,24 @@ class PrintInformation(QObject): # Only update the job name when it's not user-specified. if not self._is_user_specified_job_name: if self._pre_sliced: - job_name = catalog.i18nc("@label", "Pre-sliced file {0}", base_name) + self._job_name = catalog.i18nc("@label", "Pre-sliced file {0}", base_name) elif self._application.getInstance().getPreferences().getValue("cura/jobname_prefix"): # Don't add abbreviation if it already has the exact same abbreviation. if base_name.startswith(self._abbr_machine + "_"): - job_name = base_name + self._job_name = base_name else: - job_name = self._abbr_machine + "_" + base_name + self._job_name = self._abbr_machine + "_" + base_name else: - job_name = base_name + self._job_name = base_name + + # In case there are several buildplates, a suffix is attached + if self._multi_build_plate_model.maxBuildPlate > 0: + connector = "_#" + suffix = connector + str(self._active_build_plate + 1) + if connector in self._job_name: + self._job_name = self._job_name.split(connector)[0] # get the real name if self._active_build_plate != 0: - job_name += "-{}".format(self._active_build_plate) - self._job_name = job_name + self._job_name += suffix self.jobNameChanged.emit() From aca4ebec50ac4245f2203e10d65325aac24b4ffb Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Wed, 1 Aug 2018 17:03:49 +0200 Subject: [PATCH 086/243] Update version number for quality profile. Contributes to CURA-5610. --- resources/quality/tizyx_k25/tizyx_k25_normal.inst.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/quality/tizyx_k25/tizyx_k25_normal.inst.cfg b/resources/quality/tizyx_k25/tizyx_k25_normal.inst.cfg index 399a7a51ab..8c6349d27a 100644 --- a/resources/quality/tizyx_k25/tizyx_k25_normal.inst.cfg +++ b/resources/quality/tizyx_k25/tizyx_k25_normal.inst.cfg @@ -5,7 +5,7 @@ definition = tizyx_k25 [metadata] quality_type = normal -setting_version = 4 +setting_version = 5 type = quality global_quality = True From c14539d63ae56836ec3840c3bed7f620d53b6573 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Thu, 2 Aug 2018 13:12:01 +0200 Subject: [PATCH 087/243] Fix the sliders that went out of range when using the arrow keys. --- plugins/SimulationView/LayerSlider.qml | 24 ++++++++++++++++++------ plugins/SimulationView/PathSlider.qml | 11 +++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/plugins/SimulationView/LayerSlider.qml b/plugins/SimulationView/LayerSlider.qml index 22f9d91340..d7e22d601e 100644 --- a/plugins/SimulationView/LayerSlider.qml +++ b/plugins/SimulationView/LayerSlider.qml @@ -40,33 +40,41 @@ Item { property bool layersVisible: true - function getUpperValueFromSliderHandle () { + function getUpperValueFromSliderHandle() { return upperHandle.getValue() } - function setUpperValue (value) { + function setUpperValue(value) { upperHandle.setValue(value) updateRangeHandle() } - function getLowerValueFromSliderHandle () { + function getLowerValueFromSliderHandle() { return lowerHandle.getValue() } - function setLowerValue (value) { + function setLowerValue(value) { lowerHandle.setValue(value) updateRangeHandle() } - function updateRangeHandle () { + function updateRangeHandle() { rangeHandle.height = lowerHandle.y - (upperHandle.y + upperHandle.height) } // set the active handle to show only one label at a time - function setActiveHandle (handle) { + function setActiveHandle(handle) { activeHandle = handle } + function normalizeValue(value) { + if (value > sliderRoot.maximumValue) + return sliderRoot.maximumValue + else if (value < sliderRoot.minimumValue) + return sliderRoot.minimumValue + return value + } + // slider track Rectangle { id: track @@ -188,6 +196,8 @@ Item { // set the slider position based on the upper value function setValue (value) { + // Normalize values between range, since using arrow keys will create out-of-the-range values + value = sliderRoot.normalizeValue(value) UM.SimulationView.setCurrentLayer(value) @@ -274,6 +284,8 @@ Item { // set the slider position based on the lower value function setValue (value) { + // Normalize values between range, since using arrow keys will create out-of-the-range values + value = sliderRoot.normalizeValue(value) UM.SimulationView.setMinimumLayer(value) diff --git a/plugins/SimulationView/PathSlider.qml b/plugins/SimulationView/PathSlider.qml index 0a4af904aa..a73cacee69 100644 --- a/plugins/SimulationView/PathSlider.qml +++ b/plugins/SimulationView/PathSlider.qml @@ -29,6 +29,7 @@ Item { // value properties property real maximumValue: 100 + property real minimumValue: 0 property bool roundValues: true property real handleValue: maximumValue @@ -47,6 +48,14 @@ Item { rangeHandle.width = handle.x - sliderRoot.handleSize } + function normalizeValue(value) { + if (value > sliderRoot.maximumValue) + return sliderRoot.maximumValue + else if (value < sliderRoot.minimumValue) + return sliderRoot.minimumValue + return value + } + // slider track Rectangle { id: track @@ -110,6 +119,8 @@ Item { // set the slider position based on the value function setValue (value) { + // Normalize values between range, since using arrow keys will create out-of-the-range values + value = sliderRoot.normalizeValue(value) UM.SimulationView.setCurrentPath(value) From a303f394c8744eba3afee74c53462511ca5250f3 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 2 Aug 2018 16:09:31 +0200 Subject: [PATCH 088/243] Move VariantType to VariantType.py Less circular dependencies for imports. --- cura/Machines/Models/BuildPlateModel.py | 2 +- cura/Machines/Models/NozzleModel.py | 3 ++- cura/Machines/VariantManager.py | 10 +--------- cura/Machines/VariantType.py | 15 +++++++++++++++ cura/Settings/CuraStackBuilder.py | 2 +- plugins/3MFReader/ThreeMFWorkspaceReader.py | 3 +-- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 4 +++- 7 files changed, 24 insertions(+), 15 deletions(-) create mode 100644 cura/Machines/VariantType.py diff --git a/cura/Machines/Models/BuildPlateModel.py b/cura/Machines/Models/BuildPlateModel.py index e1b4f40d8e..82b9db4d64 100644 --- a/cura/Machines/Models/BuildPlateModel.py +++ b/cura/Machines/Models/BuildPlateModel.py @@ -8,7 +8,7 @@ from UM.Logger import Logger from UM.Qt.ListModel import ListModel from UM.Util import parseBool -from cura.Machines.VariantManager import VariantType +from cura.Machines.VariantType import VariantType class BuildPlateModel(ListModel): diff --git a/cura/Machines/Models/NozzleModel.py b/cura/Machines/Models/NozzleModel.py index 0879998b7d..9d97106d6b 100644 --- a/cura/Machines/Models/NozzleModel.py +++ b/cura/Machines/Models/NozzleModel.py @@ -8,6 +8,8 @@ from UM.Logger import Logger from UM.Qt.ListModel import ListModel from UM.Util import parseBool +from cura.Machines.VariantType import VariantType + class NozzleModel(ListModel): IdRole = Qt.UserRole + 1 @@ -43,7 +45,6 @@ class NozzleModel(ListModel): self.setItems([]) return - from cura.Machines.VariantManager import VariantType variant_node_dict = self._variant_manager.getVariantNodes(global_stack, VariantType.NOZZLE) if not variant_node_dict: self.setItems([]) diff --git a/cura/Machines/VariantManager.py b/cura/Machines/VariantManager.py index 036c79d6c7..969fed670e 100644 --- a/cura/Machines/VariantManager.py +++ b/cura/Machines/VariantManager.py @@ -1,7 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from enum import Enum from collections import OrderedDict from typing import Optional, TYPE_CHECKING @@ -11,20 +10,13 @@ from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Util import parseBool from cura.Machines.ContainerNode import ContainerNode +from cura.Machines.VariantType import VariantType, ALL_VARIANT_TYPES from cura.Settings.GlobalStack import GlobalStack if TYPE_CHECKING: from UM.Settings.DefinitionContainer import DefinitionContainer -class VariantType(Enum): - BUILD_PLATE = "buildplate" - NOZZLE = "nozzle" - - -ALL_VARIANT_TYPES = (VariantType.BUILD_PLATE, VariantType.NOZZLE) - - # # VariantManager is THE place to look for a specific variant. It maintains two variant lookup tables with the following # structure: diff --git a/cura/Machines/VariantType.py b/cura/Machines/VariantType.py new file mode 100644 index 0000000000..82bb86d7d9 --- /dev/null +++ b/cura/Machines/VariantType.py @@ -0,0 +1,15 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from enum import Enum + + +class VariantType(Enum): + BUILD_PLATE = "buildplate" + NOZZLE = "nozzle" + + +ALL_VARIANT_TYPES = (VariantType.BUILD_PLATE, VariantType.NOZZLE) + + +__all__ = ["VariantType", "ALL_VARIANT_TYPES"] diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 841d45ed31..a794dde651 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -8,7 +8,7 @@ from UM.Logger import Logger from UM.Settings.Interfaces import DefinitionContainerInterface from UM.Settings.InstanceContainer import InstanceContainer -from cura.Machines.VariantManager import VariantType +from cura.Machines.VariantType import VariantType from .GlobalStack import GlobalStack from .ExtruderStack import ExtruderStack diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index f72029524e..389a7da704 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -24,6 +24,7 @@ from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType from UM.Job import Job from UM.Preferences import Preferences +from cura.Machines.VariantType import VariantType from cura.Settings.CuraStackBuilder import CuraStackBuilder from cura.Settings.ExtruderStack import ExtruderStack from cura.Settings.GlobalStack import GlobalStack @@ -889,7 +890,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader): parser = self._machine_info.variant_info.parser variant_name = parser["general"]["name"] - from cura.Machines.VariantManager import VariantType variant_type = VariantType.BUILD_PLATE node = variant_manager.getVariantNode(global_stack.definition.getId(), variant_name, variant_type) @@ -905,7 +905,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader): parser = extruder_info.variant_info.parser variant_name = parser["general"]["name"] - from cura.Machines.VariantManager import VariantType variant_type = VariantType.NOZZLE node = variant_manager.getVariantNode(global_stack.definition.getId(), variant_name, variant_type) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index eac6646197..a799f948c4 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -19,8 +19,11 @@ from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.ContainerRegistry import ContainerRegistry from UM.ConfigurationErrorMessage import ConfigurationErrorMessage +from cura.Machines.VariantType import VariantType + from .XmlMaterialValidator import XmlMaterialValidator + ## Handles serializing and deserializing material containers from an XML file class XmlMaterialProfile(InstanceContainer): CurrentFdmMaterialVersion = "1.3" @@ -269,7 +272,6 @@ class XmlMaterialProfile(InstanceContainer): buildplate_dict = {} # type: Dict[str, Any] for variant_name, variant_dict in machine_variant_map[definition_id].items(): variant_type = variant_dict["variant_node"].metadata["hardware_type"] - from cura.Machines.VariantManager import VariantType variant_type = VariantType(variant_type) if variant_type == VariantType.NOZZLE: # The hotend identifier is not the containers name, but its "name". From 066a00653ab6ba62fcd5267a352646a7078af142 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 2 Aug 2018 17:15:30 +0200 Subject: [PATCH 089/243] Add one more layer to the decision tree --- cura/Machines/MaterialManager.py | 200 +++++++++++------- cura/Machines/QualityManager.py | 125 ++++++----- cura/Settings/GlobalStack.py | 6 + cura/Settings/MachineManager.py | 22 +- .../XmlMaterialProfile/XmlMaterialProfile.py | 199 ++++++++++++----- resources/definitions/fdmprinter.def.json | 1 + 6 files changed, 368 insertions(+), 185 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 5d691fcef4..86f7dea81f 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -4,8 +4,7 @@ from collections import defaultdict, OrderedDict import copy import uuid -from typing import Dict, cast -from typing import Optional, TYPE_CHECKING +from typing import Dict, Optional, TYPE_CHECKING from PyQt5.Qt import QTimer, QObject, pyqtSignal, pyqtSlot @@ -18,6 +17,7 @@ from UM.Util import parseBool from .MaterialNode import MaterialNode from .MaterialGroup import MaterialGroup +from .VariantType import VariantType if TYPE_CHECKING: from UM.Settings.DefinitionContainer import DefinitionContainer @@ -47,7 +47,7 @@ class MaterialManager(QObject): self._fallback_materials_map = dict() # material_type -> generic material metadata self._material_group_map = dict() # root_material_id -> MaterialGroup - self._diameter_machine_variant_material_map = dict() # approximate diameter str -> dict(machine_definition_id -> MaterialNode) + self._diameter_machine_nozzle_buildplate_material_map = dict() # approximate diameter str -> dict(machine_definition_id -> MaterialNode) # We're using these two maps to convert between the specific diameter material id and the generic material id # because the generic material ids are used in qualities and definitions, while the specific diameter material is meant @@ -186,10 +186,11 @@ class MaterialManager(QObject): for root_material_id in data_dict.values(): self._diameter_material_map[root_material_id] = default_root_material_id + variant_manager = self._application.getVariantManager() + # Map #4 - # "machine" -> "variant_name" -> "root material ID" -> specific material InstanceContainer - # Construct the "machine" -> "variant" -> "root material ID" -> specific material InstanceContainer - self._diameter_machine_variant_material_map = dict() + # "machine" -> "nozzle name" -> "buildplate name" -> "root material ID" -> specific material InstanceContainer + self._diameter_machine_nozzle_buildplate_material_map = dict() for material_metadata in material_metadatas.values(): # We don't store empty material in the lookup tables if material_metadata["id"] == "empty_material": @@ -199,36 +200,62 @@ class MaterialManager(QObject): definition = material_metadata["definition"] approximate_diameter = material_metadata["approximate_diameter"] - if approximate_diameter not in self._diameter_machine_variant_material_map: - self._diameter_machine_variant_material_map[approximate_diameter] = {} + if approximate_diameter not in self._diameter_machine_nozzle_buildplate_material_map: + self._diameter_machine_nozzle_buildplate_material_map[approximate_diameter] = {} - machine_variant_material_map = self._diameter_machine_variant_material_map[approximate_diameter] - if definition not in machine_variant_material_map: - machine_variant_material_map[definition] = MaterialNode() + machine_nozzle_buildplate_material_map = self._diameter_machine_nozzle_buildplate_material_map[approximate_diameter] + if definition not in machine_nozzle_buildplate_material_map: + machine_nozzle_buildplate_material_map[definition] = MaterialNode() - machine_node = machine_variant_material_map[definition] - variant_name = material_metadata.get("variant_name") - if not variant_name: - # if there is no variant, this material is for the machine, so put its metadata in the machine node. + machine_node = machine_nozzle_buildplate_material_map[definition] + nozzle_name = material_metadata.get("variant_name") + buildplate_name = material_metadata.get("buildplate_name") + if not nozzle_name: + # if there is no nozzle, this material is for the machine, so put its metadata in the machine node. machine_node.material_map[root_material_id] = MaterialNode(material_metadata) else: - # this material is variant-specific, so we save it in a variant-specific node under the + # this material is nozzle-specific, so we save it in a nozzle-specific node under the # machine-specific node - # Check first if the variant exist in the manager - existing_variant = self._application.getVariantManager().getVariantNode(definition, variant_name) - if existing_variant is not None: - if variant_name not in machine_node.children_map: - machine_node.children_map[variant_name] = MaterialNode() + # Check first if the nozzle exists in the manager + existing_nozzle = variant_manager.getVariantNode(definition, nozzle_name, VariantType.NOZZLE) + if existing_nozzle is not None: + if nozzle_name not in machine_node.children_map: + machine_node.children_map[nozzle_name] = MaterialNode() + + nozzle_node = machine_node.children_map[nozzle_name] + + # Check build plate node + if not buildplate_name: + # if there is no buildplate, this material is for the machine, so put its metadata in the machine node. + if root_material_id in nozzle_node.material_map: # We shouldn't have duplicated nozzle-specific materials for the same machine. + ConfigurationErrorMessage.getInstance().addFaultyContainers(root_material_id) + continue + nozzle_node.material_map[root_material_id] = MaterialNode(material_metadata) + else: + # this material is nozzle-and-buildplate-specific, so we save it in a buildplate-specific node + # under the machine-specific node + + # Check first if the buildplate exists in the manager + existing_buildplate = variant_manager.getVariantNode(definition, buildplate_name, VariantType.BUILD_PLATE) + if existing_buildplate is not None: + if buildplate_name not in nozzle_node.children_map: + nozzle_node.children_map[buildplate_name] = MaterialNode() + + buildplate_node = nozzle_node.children_map[buildplate_name] + if root_material_id in buildplate_node.material_map: # We shouldn't have duplicated nozzle-and-buildplate-specific materials for the same machine. + ConfigurationErrorMessage.getInstance().addFaultyContainers(root_material_id) + continue + buildplate_node.material_map[root_material_id] = MaterialNode(material_metadata) + + else: + # Add this container id to the wrong containers list in the registry + Logger.log("w", "Not adding {id} to the material manager because the buildplate does not exist.".format(id = material_metadata["id"])) + self._container_registry.addWrongContainerId(material_metadata["id"]) - variant_node = machine_node.children_map[variant_name] - if root_material_id in variant_node.material_map: # We shouldn't have duplicated variant-specific materials for the same machine. - ConfigurationErrorMessage.getInstance().addFaultyContainers(root_material_id) - continue - variant_node.material_map[root_material_id] = MaterialNode(material_metadata) else: # Add this container id to the wrong containers list in the registry - Logger.log("w", "Not adding {id} to the material manager because the variant does not exist.".format(id = material_metadata["id"])) + Logger.log("w", "Not adding {id} to the material manager because the nozzle does not exist.".format(id = material_metadata["id"])) self._container_registry.addWrongContainerId(material_metadata["id"]) self.materialsUpdated.emit() @@ -263,45 +290,52 @@ class MaterialManager(QObject): # # Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup. # - def getAvailableMaterials(self, machine_definition: "DefinitionContainer", extruder_variant_name: Optional[str], - diameter: float) -> Dict[str, MaterialNode]: + def getAvailableMaterials(self, machine_definition: "DefinitionContainer", extruder_nozzle_name: Optional[str], + buildplate_name: Optional[str], diameter: float) -> Dict[str, MaterialNode]: # round the diameter to get the approximate diameter rounded_diameter = str(round(diameter)) - if rounded_diameter not in self._diameter_machine_variant_material_map: + if rounded_diameter not in self._diameter_machine_nozzle_buildplate_material_map: Logger.log("i", "Cannot find materials with diameter [%s] (rounded to [%s])", diameter, rounded_diameter) return dict() machine_definition_id = machine_definition.getId() - # If there are variant materials, get the variant material - machine_variant_material_map = self._diameter_machine_variant_material_map[rounded_diameter] - machine_node = machine_variant_material_map.get(machine_definition_id) - default_machine_node = machine_variant_material_map.get(self._default_machine_definition_id) - variant_node = None - if extruder_variant_name is not None and machine_node is not None: - variant_node = machine_node.getChildNode(extruder_variant_name) + # If there are nozzle-and-or-buildplate materials, get the nozzle-and-or-buildplate material + machine_nozzle_buildplate_material_map = self._diameter_machine_nozzle_buildplate_material_map[rounded_diameter] + machine_node = machine_nozzle_buildplate_material_map.get(machine_definition_id) + default_machine_node = machine_nozzle_buildplate_material_map.get(self._default_machine_definition_id) + nozzle_node = None + buildplate_node = None + if extruder_nozzle_name is not None and machine_node is not None: + nozzle_node = machine_node.getChildNode(extruder_nozzle_name) + # Get buildplate node if possible + if nozzle_node is not None and buildplate_name is not None: + buildplate_node = nozzle_node.getChildNode(buildplate_name) - nodes_to_check = [variant_node, machine_node, default_machine_node] + nodes_to_check = [buildplate_node, nozzle_node, machine_node, default_machine_node] # Fallback mechanism of finding materials: - # 1. variant-specific material - # 2. machine-specific material - # 3. generic material (for fdmprinter) + # 1. buildplate-specific material + # 2. nozzle-specific material + # 3. machine-specific material + # 4. generic material (for fdmprinter) machine_exclude_materials = machine_definition.getMetaDataEntry("exclude_materials", []) - material_id_metadata_dict = dict() # type: Dict[str, MaterialNode] - for node in nodes_to_check: - if node is not None: - # Only exclude the materials that are explicitly specified in the "exclude_materials" field. - # Do not exclude other materials that are of the same type. - for material_id, node in node.material_map.items(): - if material_id in machine_exclude_materials: - Logger.log("d", "Exclude material [%s] for machine [%s]", - material_id, machine_definition.getId()) - continue + material_id_metadata_dict = dict() # type: Dict[str, MaterialNode] + for current_node in nodes_to_check: + if current_node is None: + continue - if material_id not in material_id_metadata_dict: - material_id_metadata_dict[material_id] = node + # Only exclude the materials that are explicitly specified in the "exclude_materials" field. + # Do not exclude other materials that are of the same type. + for material_id, node in current_node.material_map.items(): + if material_id in machine_exclude_materials: + Logger.log("d", "Exclude material [%s] for machine [%s]", + material_id, machine_definition.getId()) + continue + + if material_id not in material_id_metadata_dict: + material_id_metadata_dict[material_id] = node return material_id_metadata_dict @@ -310,13 +344,14 @@ class MaterialManager(QObject): # def getAvailableMaterialsForMachineExtruder(self, machine: "GlobalStack", extruder_stack: "ExtruderStack") -> Optional[dict]: - variant_name = None + buildplate_name = machine.getBuildplateName() + nozzle_name = None if extruder_stack.variant.getId() != "empty_variant": - variant_name = extruder_stack.variant.getName() + nozzle_name = extruder_stack.variant.getName() diameter = extruder_stack.approximateMaterialDiameter # Fetch the available materials (ContainerNode) for the current active machine and extruder setup. - return self.getAvailableMaterials(machine.definition, variant_name, diameter) + return self.getAvailableMaterials(machine.definition, nozzle_name, buildplate_name, diameter) # # Gets MaterialNode for the given extruder and machine with the given material name. @@ -324,32 +359,36 @@ class MaterialManager(QObject): # 1. the given machine doesn't have materials; # 2. cannot find any material InstanceContainers with the given settings. # - def getMaterialNode(self, machine_definition_id: str, extruder_variant_name: Optional[str], - diameter: float, root_material_id: str) -> Optional["InstanceContainer"]: + def getMaterialNode(self, machine_definition_id: str, nozzle_name: Optional[str], + buildplate_name: Optional[str], diameter: float, root_material_id: str) -> Optional["InstanceContainer"]: # round the diameter to get the approximate diameter rounded_diameter = str(round(diameter)) - if rounded_diameter not in self._diameter_machine_variant_material_map: + if rounded_diameter not in self._diameter_machine_nozzle_buildplate_material_map: Logger.log("i", "Cannot find materials with diameter [%s] (rounded to [%s]) for root material id [%s]", diameter, rounded_diameter, root_material_id) return None - # If there are variant materials, get the variant material - machine_variant_material_map = self._diameter_machine_variant_material_map[rounded_diameter] - machine_node = machine_variant_material_map.get(machine_definition_id) - variant_node = None + # If there are nozzle materials, get the nozzle-specific material + machine_nozzle_buildplate_material_map = self._diameter_machine_nozzle_buildplate_material_map[rounded_diameter] + machine_node = machine_nozzle_buildplate_material_map.get(machine_definition_id) + nozzle_node = None + buildplate_node = None # Fallback for "fdmprinter" if the machine-specific materials cannot be found if machine_node is None: - machine_node = machine_variant_material_map.get(self._default_machine_definition_id) - if machine_node is not None and extruder_variant_name is not None: - variant_node = machine_node.getChildNode(extruder_variant_name) + machine_node = machine_nozzle_buildplate_material_map.get(self._default_machine_definition_id) + if machine_node is not None and nozzle_name is not None: + nozzle_node = machine_node.getChildNode(nozzle_name) + if nozzle_node is not None and buildplate_name is not None: + buildplate_node = nozzle_node.getChildNode(buildplate_name) # Fallback mechanism of finding materials: - # 1. variant-specific material - # 2. machine-specific material - # 3. generic material (for fdmprinter) - nodes_to_check = [variant_node, machine_node, - machine_variant_material_map.get(self._default_machine_definition_id)] + # 1. buildplate-specific material + # 2. nozzle-specific material + # 3. machine-specific material + # 4. generic material (for fdmprinter) + nodes_to_check = [buildplate_node, nozzle_node, machine_node, + machine_nozzle_buildplate_material_map.get(self._default_machine_definition_id)] material_node = None for node in nodes_to_check: @@ -366,7 +405,8 @@ class MaterialManager(QObject): # 1. the given machine doesn't have materials; # 2. cannot find any material InstanceContainers with the given settings. # - def getMaterialNodeByType(self, global_stack: "GlobalStack", position: str, extruder_variant_name: str, material_guid: str) -> Optional["MaterialNode"]: + def getMaterialNodeByType(self, global_stack: "GlobalStack", position: str, nozzle_name: str, + buildplate_name: Optional[str], material_guid: str) -> Optional["MaterialNode"]: node = None machine_definition = global_stack.definition extruder_definition = global_stack.extruders[position].definition @@ -385,7 +425,7 @@ class MaterialManager(QObject): Logger.log("i", "Cannot find materials with guid [%s] ", material_guid) return None - node = self.getMaterialNode(machine_definition.getId(), extruder_variant_name, + node = self.getMaterialNode(machine_definition.getId(), nozzle_name, buildplate_name, material_diameter, root_material_id) return node @@ -413,13 +453,17 @@ class MaterialManager(QObject): else: return None - ## Get default material for given global stack, extruder position and extruder variant name + ## Get default material for given global stack, extruder position and extruder nozzle name # you can provide the extruder_definition and then the position is ignored (useful when building up global stack in CuraStackBuilder) - def getDefaultMaterial(self, global_stack: "GlobalStack", position: str, extruder_variant_name: Optional[str], extruder_definition: Optional["DefinitionContainer"] = None) -> Optional["MaterialNode"]: + def getDefaultMaterial(self, global_stack: "GlobalStack", position: str, nozzle_name: Optional[str], + extruder_definition: Optional["DefinitionContainer"] = None) -> Optional["MaterialNode"]: node = None + + buildplate_name = global_stack.getBuildplateName() machine_definition = global_stack.definition if extruder_definition is None: extruder_definition = global_stack.extruders[position].definition + if extruder_definition and parseBool(global_stack.getMetaDataEntry("has_materials", False)): # At this point the extruder_definition is not None material_diameter = extruder_definition.getProperty("material_diameter", "value") @@ -428,7 +472,7 @@ class MaterialManager(QObject): approximate_material_diameter = str(round(material_diameter)) root_material_id = machine_definition.getMetaDataEntry("preferred_material") root_material_id = self.getRootMaterialIDForDiameter(root_material_id, approximate_material_diameter) - node = self.getMaterialNode(machine_definition.getId(), extruder_variant_name, + node = self.getMaterialNode(machine_definition.getId(), nozzle_name, buildplate_name, material_diameter, root_material_id) return node @@ -515,8 +559,8 @@ class MaterialManager(QObject): if container_to_copy.getMetaDataEntry("definition") != "fdmprinter": new_id += "_" + container_to_copy.getMetaDataEntry("definition") if container_to_copy.getMetaDataEntry("variant_name"): - variant_name = container_to_copy.getMetaDataEntry("variant_name") - new_id += "_" + variant_name.replace(" ", "_") + nozzle_name = container_to_copy.getMetaDataEntry("variant_name") + new_id += "_" + nozzle_name.replace(" ", "_") new_container = copy.deepcopy(container_to_copy) new_container.getMetaData()["id"] = new_id diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 82a11f9960..273f1ae11f 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -45,7 +45,7 @@ class QualityManager(QObject): self._empty_quality_container = self._application.empty_quality_container self._empty_quality_changes_container = self._application.empty_quality_changes_container - self._machine_variant_material_quality_type_to_quality_dict = {} # for quality lookup + self._machine_nozzle_buildplate_material_quality_type_to_quality_dict = {} # for quality lookup self._machine_quality_type_to_quality_changes_dict = {} # for quality_changes lookup self._default_machine_definition_id = "fdmprinter" @@ -64,10 +64,10 @@ class QualityManager(QObject): def initialize(self): # Initialize the lookup tree for quality profiles with following structure: - # -> -> - # -> + # -> -> -> + # -> - self._machine_variant_material_quality_type_to_quality_dict = {} # for quality lookup + self._machine_nozzle_buildplate_material_quality_type_to_quality_dict = {} # for quality lookup self._machine_quality_type_to_quality_changes_dict = {} # for quality_changes lookup quality_metadata_list = self._container_registry.findContainersMetadata(type = "quality") @@ -79,47 +79,58 @@ class QualityManager(QObject): quality_type = metadata["quality_type"] root_material_id = metadata.get("material") - variant_name = metadata.get("variant") + nozzle_name = metadata.get("variant") + buildplate_name = metadata.get("buildplate") is_global_quality = metadata.get("global_quality", False) - is_global_quality = is_global_quality or (root_material_id is None and variant_name is None) + is_global_quality = is_global_quality or (root_material_id is None and nozzle_name is None and buildplate_name is None) # Sanity check: material+variant and is_global_quality cannot be present at the same time - if is_global_quality and (root_material_id or variant_name): + if is_global_quality and (root_material_id or nozzle_name): ConfigurationErrorMessage.getInstance().addFaultyContainers(metadata["id"]) continue - if definition_id not in self._machine_variant_material_quality_type_to_quality_dict: - self._machine_variant_material_quality_type_to_quality_dict[definition_id] = QualityNode() - machine_node = cast(QualityNode, self._machine_variant_material_quality_type_to_quality_dict[definition_id]) + if definition_id not in self._machine_nozzle_buildplate_material_quality_type_to_quality_dict: + self._machine_nozzle_buildplate_material_quality_type_to_quality_dict[definition_id] = QualityNode() + machine_node = cast(QualityNode, self._machine_nozzle_buildplate_material_quality_type_to_quality_dict[definition_id]) if is_global_quality: # For global qualities, save data in the machine node machine_node.addQualityMetadata(quality_type, metadata) continue - if variant_name is not None: - # If variant_name is specified in the quality/quality_changes profile, check if material is specified, - # too. - if variant_name not in machine_node.children_map: - machine_node.children_map[variant_name] = QualityNode() - variant_node = cast(QualityNode, machine_node.children_map[variant_name]) + # Check if nozzle si specified + if nozzle_name is not None: + if nozzle_name not in machine_node.children_map: + machine_node.children_map[nozzle_name] = QualityNode() + nozzle_node = cast(QualityNode, machine_node.children_map[nozzle_name]) + + # Check if buildplate is specified + if buildplate_name is not None: + if buildplate_name not in nozzle_node.children_map: + nozzle_node.children_map[buildplate_name] = QualityNode() + buildplate_node = cast(QualityNode, nozzle_node.children_map[buildplate_name]) + + if root_material_id is None: + buildplate_node.addQualityMetadata(quality_type, metadata) + else: + if root_material_id not in buildplate_node.children_map: + buildplate_node.children_map[root_material_id] = QualityNode() + material_node = cast(QualityNode, buildplate_node.children_map[root_material_id]) + + material_node.addQualityMetadata(quality_type, metadata) - if root_material_id is None: - # If only variant_name is specified but material is not, add the quality/quality_changes metadata - # into the current variant node. - variant_node.addQualityMetadata(quality_type, metadata) else: - # If only variant_name and material are both specified, go one level deeper: create a material node - # under the current variant node, and then add the quality/quality_changes metadata into the - # material node. - if root_material_id not in variant_node.children_map: - variant_node.children_map[root_material_id] = QualityNode() - material_node = cast(QualityNode, variant_node.children_map[root_material_id]) + if root_material_id is None: + nozzle_node.addQualityMetadata(quality_type, metadata) + else: + if root_material_id not in nozzle_node.children_map: + nozzle_node.children_map[root_material_id] = QualityNode() + material_node = cast(QualityNode, nozzle_node.children_map[root_material_id]) - material_node.addQualityMetadata(quality_type, metadata) + material_node.addQualityMetadata(quality_type, metadata) else: - # If variant_name is not specified, check if material is specified. + # If nozzle is not specified, check if material is specified. if root_material_id is not None: if root_material_id not in machine_node.children_map: machine_node.children_map[root_material_id] = QualityNode() @@ -217,8 +228,8 @@ class QualityManager(QObject): # To find the quality container for the GlobalStack, check in the following fall-back manner: # (1) the machine-specific node # (2) the generic node - machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(machine_definition_id) - default_machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(self._default_machine_definition_id) + machine_node = self._machine_nozzle_buildplate_material_quality_type_to_quality_dict.get(machine_definition_id) + default_machine_node = self._machine_nozzle_buildplate_material_quality_type_to_quality_dict.get(self._default_machine_definition_id) nodes_to_check = [machine_node, default_machine_node] # Iterate over all quality_types in the machine node @@ -238,11 +249,13 @@ class QualityManager(QObject): quality_group_dict[quality_type] = quality_group break + buildplate_name = machine.getBuildplateName() + # Iterate over all extruders to find quality containers for each extruder for position, extruder in machine.extruders.items(): - variant_name = None + nozzle_name = None if extruder.variant.getId() != "empty_variant": - variant_name = extruder.variant.getName() + nozzle_name = extruder.variant.getName() # This is a list of root material IDs to use for searching for suitable quality profiles. # The root material IDs in this list are in prioritized order. @@ -258,34 +271,47 @@ class QualityManager(QObject): # Also try to get the fallback material material_type = extruder.material.getMetaDataEntry("material") fallback_root_material_id = self._material_manager.getFallbackMaterialIdByMaterialType(material_type) - if fallback_root_material_id: + if fallback_root_material_id and root_material_id not in root_material_id_list: root_material_id_list.append(fallback_root_material_id) # Here we construct a list of nodes we want to look for qualities with the highest priority first. # The use case is that, when we look for qualities for a machine, we first want to search in the following # order: - # 1. machine-variant-and-material-specific qualities if exist - # 2. machine-variant-specific qualities if exist - # 3. machine-material-specific qualities if exist - # 4. machine-specific qualities if exist - # 5. generic qualities if exist + # 1. machine-nozzle-buildplate-and-material-specific qualities if exist + # 2. machine-nozzle-and-material-specific qualities if exist + # 3. machine-nozzle-specific qualities if exist + # 4. machine-material-specific qualities if exist + # 5. machine-specific qualities if exist + # 6. generic qualities if exist # Each points above can be represented as a node in the lookup tree, so here we simply put those nodes into # the list with priorities as the order. Later, we just need to loop over each node in this list and fetch # qualities from there. nodes_to_check = [] - if variant_name: - # In this case, we have both a specific variant and a specific material - variant_node = machine_node.getChildNode(variant_name) - if variant_node and has_material: + if nozzle_name: + # In this case, we have both a specific nozzle and a specific material + nozzle_node = machine_node.getChildNode(nozzle_name) + if nozzle_node and has_material: + # Check build plate if exists + if buildplate_name: + buildplate_node = nozzle_node.getChildNode(buildplate_name) + if buildplate_node and has_material: + for root_material_id in root_material_id_list: + material_node = buildplate_node.getChildNode(root_material_id) + if material_node: + nodes_to_check.append(material_node) + break + nodes_to_check.append(buildplate_node) + + # Then add nozzle specific materials for root_material_id in root_material_id_list: - material_node = variant_node.getChildNode(root_material_id) + material_node = nozzle_node.getChildNode(root_material_id) if material_node: nodes_to_check.append(material_node) break - nodes_to_check.append(variant_node) + nodes_to_check.append(nozzle_node) - # In this case, we only have a specific material but NOT a variant + # In this case, we only have a specific material but NOT a nozzle if has_material: for root_material_id in root_material_id_list: material_node = machine_node.getChildNode(root_material_id) @@ -309,8 +335,9 @@ class QualityManager(QObject): quality_group_dict[quality_type] = quality_group quality_group = quality_group_dict[quality_type] - quality_group.nodes_for_extruders[position] = quality_node - break + if position not in quality_group.nodes_for_extruders: + quality_group.nodes_for_extruders[position] = quality_node + #break # Update availabilities for each quality group self._updateQualityGroupsAvailability(machine, quality_group_dict.values()) @@ -323,8 +350,8 @@ class QualityManager(QObject): # To find the quality container for the GlobalStack, check in the following fall-back manner: # (1) the machine-specific node # (2) the generic node - machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(machine_definition_id) - default_machine_node = self._machine_variant_material_quality_type_to_quality_dict.get( + machine_node = self._machine_nozzle_buildplate_material_quality_type_to_quality_dict.get(machine_definition_id) + default_machine_node = self._machine_nozzle_buildplate_material_quality_type_to_quality_dict.get( self._default_machine_definition_id) nodes_to_check = [machine_node, default_machine_node] diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 66f3290b85..35edfe1053 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -55,6 +55,12 @@ class GlobalStack(CuraContainerStack): return "machine_stack" return configuration_type + def getBuildplateName(self) -> Optional[str]: + name = None + if self.variant.getId() != "empty_variant": + name = self.variant.getName() + return name + ## Add an extruder to the list of extruders of this stack. # # \param extruder The extruder to add. diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index ff585deb54..733340e0ce 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1256,13 +1256,17 @@ class MachineManager(QObject): else: position_list = [position] + buildplate_name = None + if self._global_container_stack.variant.getId() != "empty_variant": + buildplate_name = self._global_container_stack.variant.getName() + for position_item in position_list: extruder = self._global_container_stack.extruders[position_item] current_material_base_name = extruder.material.getMetaDataEntry("base_file") - current_variant_name = None + current_nozzle_name = None if extruder.variant.getId() != self._empty_variant_container.getId(): - current_variant_name = extruder.variant.getMetaDataEntry("name") + current_nozzle_name = extruder.variant.getMetaDataEntry("name") from UM.Settings.Interfaces import PropertyEvaluationContext from cura.Settings.CuraContainerStack import _ContainerIndexes @@ -1271,7 +1275,8 @@ class MachineManager(QObject): material_diameter = extruder.getProperty("material_diameter", "value", context) candidate_materials = self._material_manager.getAvailableMaterials( self._global_container_stack.definition, - current_variant_name, + current_nozzle_name, + buildplate_name, material_diameter) if not candidate_materials: @@ -1284,7 +1289,7 @@ class MachineManager(QObject): continue # The current material is not available, find the preferred one - material_node = self._material_manager.getDefaultMaterial(self._global_container_stack, position_item, current_variant_name) + material_node = self._material_manager.getDefaultMaterial(self._global_container_stack, position_item, current_nozzle_name) if material_node is not None: self._setMaterial(position_item, material_node) @@ -1389,12 +1394,17 @@ class MachineManager(QObject): def setMaterialById(self, position: str, root_material_id: str) -> None: if self._global_container_stack is None: return + buildplate_name = None + if self._global_container_stack.variant.getId() != "empty_variant": + buildplate_name = self._global_container_stack.variant.getName() + machine_definition_id = self._global_container_stack.definition.id position = str(position) extruder_stack = self._global_container_stack.extruders[position] - variant_name = extruder_stack.variant.getName() + nozzle_name = extruder_stack.variant.getName() material_diameter = extruder_stack.approximateMaterialDiameter - material_node = self._material_manager.getMaterialNode(machine_definition_id, variant_name, material_diameter, root_material_id) + material_node = self._material_manager.getMaterialNode(machine_definition_id, nozzle_name, buildplate_name, + material_diameter, root_material_id) self.setMaterial(position, material_node) ## global_stack: if you want to provide your own global_stack instead of the current active one diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index a799f948c4..7d9b2aacc3 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -6,19 +6,17 @@ import io import json #To parse the product-to-id mapping file. import os.path #To find the product-to-id mapping. import sys -from typing import Any, Dict, List, Optional, cast +from typing import Any, Dict, List, Optional, Tuple, cast import xml.etree.ElementTree as ET -from typing import Dict -from typing import Iterator from UM.Resources import Resources from UM.Logger import Logger -from cura.CuraApplication import CuraApplication import UM.Dictionary from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.ContainerRegistry import ContainerRegistry from UM.ConfigurationErrorMessage import ConfigurationErrorMessage +from cura.CuraApplication import CuraApplication from cura.Machines.VariantType import VariantType from .XmlMaterialValidator import XmlMaterialValidator @@ -695,74 +693,38 @@ class XmlMaterialProfile(InstanceContainer): if buildplate_id is None: continue - from cura.Machines.VariantManager import VariantType variant_manager = CuraApplication.getInstance().getVariantManager() variant_node = variant_manager.getVariantNode(machine_id, buildplate_id, variant_type = VariantType.BUILD_PLATE) if not variant_node: continue - buildplate_compatibility = machine_compatibility - buildplate_recommended = machine_compatibility - settings = buildplate.iterfind("./um:setting", self.__namespaces) - for entry in settings: - key = entry.get("key") - if key in self.__unmapped_settings: - if key == "hardware compatible": - buildplate_compatibility = self._parseCompatibleValue(entry.text) - elif key == "hardware recommended": - buildplate_recommended = self._parseCompatibleValue(entry.text) - else: - Logger.log("d", "Unsupported material setting %s", key) + _, buildplate_unmapped_settings_dict = self._getSettingsDictForNode(buildplate) + + buildplate_compatibility = buildplate_unmapped_settings_dict.get("hardware compatible", + machine_compatibility) + buildplate_recommended = buildplate_unmapped_settings_dict.get("hardware recommended", + machine_compatibility) buildplate_map["buildplate_compatible"][buildplate_id] = buildplate_compatibility buildplate_map["buildplate_recommended"][buildplate_id] = buildplate_recommended hotends = machine.iterfind("./um:hotend", self.__namespaces) for hotend in hotends: - # The "id" field for hotends in material profiles are actually + # The "id" field for hotends in material profiles is actually name hotend_name = hotend.get("id") if hotend_name is None: continue variant_manager = CuraApplication.getInstance().getVariantManager() - variant_node = variant_manager.getVariantNode(machine_id, hotend_name) + variant_node = variant_manager.getVariantNode(machine_id, hotend_name, VariantType.NOZZLE) if not variant_node: continue - hotend_compatibility = machine_compatibility - hotend_setting_values = {} - settings = hotend.iterfind("./um:setting", self.__namespaces) - for entry in settings: - key = entry.get("key") - if key in self.__material_settings_setting_map: - if key == "processing temperature graph": #This setting has no setting text but subtags. - graph_nodes = entry.iterfind("./um:point", self.__namespaces) - graph_points = [] - for graph_node in graph_nodes: - flow = float(graph_node.get("flow")) - temperature = float(graph_node.get("temperature")) - graph_points.append([flow, temperature]) - hotend_setting_values[self.__material_settings_setting_map[key]] = str(graph_points) - else: - hotend_setting_values[self.__material_settings_setting_map[key]] = entry.text - elif key in self.__unmapped_settings: - if key == "hardware compatible": - hotend_compatibility = self._parseCompatibleValue(entry.text) - else: - Logger.log("d", "Unsupported material setting %s", key) - - # Add namespaced Cura-specific settings - settings = hotend.iterfind("./cura:setting", self.__namespaces) - for entry in settings: - value = entry.text - if value.lower() == "yes": - value = True - elif value.lower() == "no": - value = False - key = entry.get("key") - hotend_setting_values[key] = value + hotend_mapped_settings, hotend_unmapped_settings = self._getSettingsDictForNode(hotend) + hotend_compatibility = hotend_unmapped_settings.get("hardware compatible", machine_compatibility) + # Generate container ID for the hotend-specific material container new_hotend_specific_material_id = self.getId() + "_" + machine_id + "_" + hotend_name.replace(" ", "_") # Same as machine compatibility, keep the derived material containers consistent with the parent material @@ -787,7 +749,7 @@ class XmlMaterialProfile(InstanceContainer): new_hotend_material.getMetaData()["buildplate_recommended"] = buildplate_map["buildplate_recommended"] cached_hotend_setting_properties = cached_machine_setting_properties.copy() - cached_hotend_setting_properties.update(hotend_setting_values) + cached_hotend_setting_properties.update(hotend_mapped_settings) new_hotend_material.setCachedValues(cached_hotend_setting_properties) @@ -796,6 +758,61 @@ class XmlMaterialProfile(InstanceContainer): if is_new_material: containers_to_add.append(new_hotend_material) + # + # Build plates in hotend + # + buildplates = hotend.iterfind("./um:buildplate", self.__namespaces) + for buildplate in buildplates: + # The "id" field for buildplate in material profiles is actually name + buildplate_name = buildplate.get("id") + if buildplate_name is None: + continue + + variant_manager = CuraApplication.getInstance().getVariantManager() + variant_node = variant_manager.getVariantNode(machine_id, buildplate_name, VariantType.BUILD_PLATE) + if not variant_node: + continue + + buildplate_mapped_settings, buildplate_unmapped_settings = self._getSettingsDictForNode(buildplate) + buildplate_compatibility = buildplate_unmapped_settings.get("hardware compatible", + buildplate_map["buildplate_compatible"]) + buildplate_recommended = buildplate_unmapped_settings.get("hardware recommended", + buildplate_map["buildplate_recommended"]) + + # Generate container ID for the hotend-and-buildplate-specific material container + new_hotend_and_buildplate_specific_material_id = new_hotend_specific_material_id + "_" + buildplate_name.replace(" ", "_") + + # Same as machine compatibility, keep the derived material containers consistent with the parent material + if ContainerRegistry.getInstance().isLoaded(new_hotend_and_buildplate_specific_material_id): + new_hotend_and_buildplate_material = ContainerRegistry.getInstance().findContainers(id = new_hotend_and_buildplate_specific_material_id)[0] + is_new_material = False + else: + new_hotend_and_buildplate_material = XmlMaterialProfile(new_hotend_and_buildplate_specific_material_id) + is_new_material = True + + new_hotend_and_buildplate_material.setMetaData(copy.deepcopy(new_hotend_material.getMetaData())) + new_hotend_and_buildplate_material.getMetaData()["id"] = new_hotend_and_buildplate_specific_material_id + new_hotend_and_buildplate_material.getMetaData()["name"] = self.getName() + new_hotend_and_buildplate_material.getMetaData()["variant_name"] = hotend_name + new_hotend_and_buildplate_material.getMetaData()["buildplate_name"] = buildplate_name + new_hotend_and_buildplate_material.setDefinition(machine_id) + # Don't use setMetadata, as that overrides it for all materials with same base file + new_hotend_and_buildplate_material.getMetaData()["compatible"] = buildplate_compatibility + new_hotend_and_buildplate_material.getMetaData()["machine_manufacturer"] = machine_manufacturer + new_hotend_and_buildplate_material.getMetaData()["definition"] = machine_id + new_hotend_and_buildplate_material.getMetaData()["buildplate_compatible"] = buildplate_compatibility + new_hotend_and_buildplate_material.getMetaData()["buildplate_recommended"] = buildplate_recommended + + cached_hotend_and_buildplate_setting_properties = cached_hotend_setting_properties.copy() + cached_hotend_and_buildplate_setting_properties.update(buildplate_mapped_settings) + + new_hotend_and_buildplate_material.setCachedValues(cached_hotend_and_buildplate_setting_properties) + + new_hotend_and_buildplate_material._dirty = False + + if is_new_material: + containers_to_add.append(new_hotend_and_buildplate_material) + # there is only one ID for a machine. Once we have reached here, it means we have already found # a workable ID for that machine, so there is no need to continue break @@ -803,6 +820,54 @@ class XmlMaterialProfile(InstanceContainer): for container_to_add in containers_to_add: ContainerRegistry.getInstance().addContainer(container_to_add) + @classmethod + def _getSettingsDictForNode(cls, node) -> Tuple[dict, dict]: + node_mapped_settings_dict = dict() + node_unmapped_settings_dict = dict() + + # Fetch settings in the "um" namespace + um_settings = node.iterfind("./um:setting", cls.__namespaces) + for um_setting_entry in um_settings: + setting_key = um_setting_entry.get("key") + + # Mapped settings + if setting_key in cls.__material_settings_setting_map: + if setting_key == "processing temperature graph": # This setting has no setting text but subtags. + graph_nodes = um_setting_entry.iterfind("./um:point", cls.__namespaces) + graph_points = [] + for graph_node in graph_nodes: + flow = float(graph_node.get("flow")) + temperature = float(graph_node.get("temperature")) + graph_points.append([flow, temperature]) + node_mapped_settings_dict[cls.__material_settings_setting_map[setting_key]] = str( + graph_points) + else: + node_mapped_settings_dict[cls.__material_settings_setting_map[setting_key]] = um_setting_entry.text + + # Unmapped settings + elif setting_key in cls.__unmapped_settings: + if setting_key in ("hardware compatible", "hardware recommended"): + node_unmapped_settings_dict[setting_key] = cls._parseCompatibleValue(um_setting_entry.text) + + # Unknown settings + else: + Logger.log("w", "Unsupported material setting %s", setting_key) + + # Fetch settings in the "cura" namespace + cura_settings = node.iterfind("./cura:setting", cls.__namespaces) + for cura_setting_entry in cura_settings: + value = cura_setting_entry.text + if value.lower() == "yes": + value = True + elif value.lower() == "no": + value = False + key = cura_setting_entry.get("key") + + # Cura settings are all mapped + node_mapped_settings_dict[key] = value + + return node_mapped_settings_dict, node_unmapped_settings_dict + @classmethod def deserializeMetadata(cls, serialized: str, container_id: str) -> List[Dict[str, Any]]: result_metadata = [] #All the metadata that we found except the base (because the base is returned). @@ -985,6 +1050,36 @@ class XmlMaterialProfile(InstanceContainer): result_metadata.append(new_hotend_material_metadata) + # + # Buildplates in Hotends + # + buildplates = hotend.iterfind("./um:buildplate", cls.__namespaces) + for buildplate in buildplates: + # The "id" field for buildplate in material profiles is actually name + buildplate_name = buildplate.get("id") + if buildplate_name is None: + continue + + buildplate_mapped_settings, buildplate_unmapped_settings = cls._getSettingsDictForNode(buildplate) + buildplate_compatibility = buildplate_unmapped_settings.get("hardware compatible", + buildplate_map["buildplate_compatible"]) + buildplate_recommended = buildplate_unmapped_settings.get("hardware recommended", + buildplate_map["buildplate_recommended"]) + + # Generate container ID for the hotend-and-buildplate-specific material container + new_hotend_and_buildplate_specific_material_id = new_hotend_specific_material_id + "_" + buildplate_name.replace( + " ", "_") + + new_hotend_and_buildplate_material_metadata = {} + new_hotend_and_buildplate_material_metadata.update(new_hotend_material_metadata) + new_hotend_and_buildplate_material_metadata["id"] = new_hotend_and_buildplate_specific_material_id + new_hotend_and_buildplate_material_metadata["buildplate_name"] = buildplate_name + new_hotend_and_buildplate_material_metadata["compatible"] = buildplate_compatibility + new_hotend_and_buildplate_material_metadata["buildplate_compatible"] = buildplate_compatibility + new_hotend_and_buildplate_material_metadata["buildplate_recommended"] = buildplate_recommended + + result_metadata.append(new_hotend_and_buildplate_material_metadata) + # there is only one ID for a machine. Once we have reached here, it means we have already found # a workable ID for that machine, so there is no need to continue break diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index b767aac7b9..6134a43b8e 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -2127,6 +2127,7 @@ "type": "float", "default_value": 60, "value": "default_material_bed_temperature", + "resolve": "max(extruderValues('material_bed_temperature'))", "minimum_value": "-273.15", "minimum_value_warning": "0", "maximum_value_warning": "130", From cc39ca09b8568c79f3c045189dda2a262c851eb1 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 2 Aug 2018 17:16:16 +0200 Subject: [PATCH 090/243] Enable build plate selection menu --- 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 09c66f98f9..e1bf8c8b77 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -232,7 +232,7 @@ UM.MainWindow } // TODO Temporary hidden, add back again when feature ready -// BuildplateMenu { title: catalog.i18nc("@title:menu", "&Build plate"); visible: Cura.MachineManager.hasVariantBuildplates } + BuildplateMenu { title: catalog.i18nc("@title:menu", "&Build plate"); visible: Cura.MachineManager.hasVariantBuildplates } ProfileMenu { title: catalog.i18nc("@title:menu", "&Profile"); } MenuSeparator { } From e817d94a8310e37fd0a81b3bbbd15f9a46f97165 Mon Sep 17 00:00:00 2001 From: Matteo Spinelli Date: Thu, 2 Aug 2018 17:30:06 +0200 Subject: [PATCH 091/243] Add user editable snap distance This PR requires an update to CuraEngine as well (I'm posting the update right after) --- resources/definitions/fdmprinter.def.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index b767aac7b9..8b3e4e1f05 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5625,6 +5625,19 @@ "settable_per_mesh": false, "settable_per_extruder": true }, + "snap_distance": + { + "label": "Snap Distance", + "description": "Snap distance between polygons in mm. Controls the polygons that may be filtered out when the model is sliced. Lower values lead to higher resolution mesh at the cost of slicing time. It is meant mostly for high resolution SLA printers and very tiny 3D models with a lot of details.", + "unit": "mm", + "type": "float", + "default_value": 1.0, + "minimum_value": "0.001", + "minimum_value_warning": "0.05", + "maximum_value_warning": "1.0", + "settable_per_mesh": true, + "settable_per_extruder": false + }, "meshfix_maximum_resolution": { "label": "Maximum Resolution", From 7157118889d2520b1fa630092d10e03eadb351a2 Mon Sep 17 00:00:00 2001 From: milkok Date: Fri, 3 Aug 2018 09:53:25 +0800 Subject: [PATCH 092/243] Update winbo_mini2.def.json --- resources/definitions/winbo_mini2.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/winbo_mini2.def.json b/resources/definitions/winbo_mini2.def.json index 85c5a445bd..7393fdf910 100644 --- a/resources/definitions/winbo_mini2.def.json +++ b/resources/definitions/winbo_mini2.def.json @@ -1,6 +1,6 @@ { "version": 2, - "name": "Winbo FDM-Mini2", + "name": "Winbo Mini2", "inherits": "fdmprinter", "metadata": { "author": "Winbo", @@ -16,7 +16,7 @@ }, "overrides": { - "machine_name": { "default_value": "Winbo FDM-Mini2" }, + "machine_name": { "default_value": "Winbo Mini2" }, "machine_width": { "default_value": 205 }, "machine_depth": { "default_value": 155 }, "machine_height": { "default_value": 205 }, From 85575f67820570c3188965a0b464aeec8b86723b Mon Sep 17 00:00:00 2001 From: milkok Date: Fri, 3 Aug 2018 09:58:23 +0800 Subject: [PATCH 093/243] Update winbo_dragonl4.def.json --- resources/definitions/winbo_dragonl4.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/winbo_dragonl4.def.json b/resources/definitions/winbo_dragonl4.def.json index 5aa004414a..0ca68cdcee 100644 --- a/resources/definitions/winbo_dragonl4.def.json +++ b/resources/definitions/winbo_dragonl4.def.json @@ -1,6 +1,6 @@ { "version": 2, - "name": "Winbo FDM-Dragon(L)4", + "name": "Winbo Dragon(L)4", "inherits": "fdmprinter", "metadata": { "author": "Winbo", @@ -16,7 +16,7 @@ }, "overrides": { - "machine_name": { "default_value": "Winbo FDM-Dragon(L)4" }, + "machine_name": { "default_value": "Winbo Dragon(L)4" }, "machine_width": { "default_value": 615 }, "machine_depth": { "default_value": 463 }, "machine_height": { "default_value": 615 }, From 1a189ba4f5be0d0a377ddcdd8671e0a59b5d7533 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 3 Aug 2018 09:13:19 +0200 Subject: [PATCH 094/243] Simplify normalization formula. --- plugins/SimulationView/LayerSlider.qml | 6 +----- plugins/SimulationView/PathSlider.qml | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/plugins/SimulationView/LayerSlider.qml b/plugins/SimulationView/LayerSlider.qml index d7e22d601e..6dcaa3f475 100644 --- a/plugins/SimulationView/LayerSlider.qml +++ b/plugins/SimulationView/LayerSlider.qml @@ -68,11 +68,7 @@ Item { } function normalizeValue(value) { - if (value > sliderRoot.maximumValue) - return sliderRoot.maximumValue - else if (value < sliderRoot.minimumValue) - return sliderRoot.minimumValue - return value + return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue) } // slider track diff --git a/plugins/SimulationView/PathSlider.qml b/plugins/SimulationView/PathSlider.qml index a73cacee69..999912e3ba 100644 --- a/plugins/SimulationView/PathSlider.qml +++ b/plugins/SimulationView/PathSlider.qml @@ -49,11 +49,7 @@ Item { } function normalizeValue(value) { - if (value > sliderRoot.maximumValue) - return sliderRoot.maximumValue - else if (value < sliderRoot.minimumValue) - return sliderRoot.minimumValue - return value + return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue) } // slider track From 5320d05b2009bdbd73496698d5ffade0dea5b944 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 2 Aug 2018 17:22:31 +0200 Subject: [PATCH 095/243] Add special quality profiles --- ...5_aa0.4_aluminum_ABS_High_Quality.inst.cfg | 34 +++++++++ ..._aa0.4_aluminum_CPEP_High_Quality.inst.cfg | 53 ++++++++++++++ ...5_aa0.4_aluminum_CPE_High_Quality.inst.cfg | 32 +++++++++ ...s5_aa0.4_aluminum_PC_High_Quality.inst.cfg | 71 +++++++++++++++++++ ...s5_aa0.8_aluminum_ABS_Draft_Print.inst.cfg | 27 +++++++ ...s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg | 43 +++++++++++ ...s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg | 29 ++++++++ ...m_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg | 36 ++++++++++ ..._s5_aa0.8_aluminum_PP_Draft_Print.inst.cfg | 53 ++++++++++++++ 9 files changed, 378 insertions(+) create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_High_Quality.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_High_Quality.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_High_Quality.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_High_Quality.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Draft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Draft_Print.inst.cfg diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_High_Quality.inst.cfg new file mode 100644 index 0000000000..9a3eef5762 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_High_Quality.inst.cfg @@ -0,0 +1,34 @@ +[general] +version = 4 +name = Extra Fine +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = high +weight = 1 +material = generic_abs +variant = AA 0.4 +buildplate = Aluminum + +[values] +cool_min_speed = 12 +layer_height_0 = 0.17 +machine_nozzle_cool_down_speed = 0.8 +machine_nozzle_heat_up_speed = 1.5 +material_bed_temperature = 90 +material_bed_temperature_layer_0 = 100 +material_print_temperature = =default_material_print_temperature + 5 +material_initial_print_temperature = =material_print_temperature - 15 +material_final_print_temperature = =material_print_temperature - 20 +prime_blob_enable = False +prime_tower_enable = False +speed_print = 50 +speed_layer_0 = =math.ceil(speed_print * 20 / 50) +speed_topbottom = =math.ceil(speed_print * 30 / 50) +speed_wall = =math.ceil(speed_print * 30 / 50) + +infill_line_width = =round(line_width * 0.4 / 0.35, 2) +speed_infill = =math.ceil(speed_print * 40 / 50) + diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_High_Quality.inst.cfg new file mode 100644 index 0000000000..8b0b08f731 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_High_Quality.inst.cfg @@ -0,0 +1,53 @@ +[general] +version = 4 +name = Extra Fine +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = high +weight = 1 +material = generic_cpe_plus +variant = AA 0.4 +buildplate = Aluminum + +[values] +acceleration_enabled = True +acceleration_print = 4000 +cool_fan_speed_max = 50 +cool_min_speed = 5 +infill_line_width = =round(line_width * 0.35 / 0.35, 2) +infill_overlap = 0 +infill_wipe_dist = 0 +jerk_enabled = True +jerk_print = 25 +layer_height_0 = 0.17 +machine_min_cool_heat_time_window = 15 +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_bed_temperature = 105 +material_bed_temperature_layer_0 = 115 +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_print_temperature = =default_material_print_temperature + 2 +material_print_temperature_layer_0 = =material_print_temperature +multiple_mesh_overlap = 0 +prime_blob_enable = False +prime_tower_enable = True +prime_tower_wipe_enabled = True +retraction_combing = off +retraction_extrusion_window = 1 +retraction_hop = 0.2 +retraction_hop_enabled = False +retraction_hop_only_when_collides = True +skin_overlap = 20 +speed_layer_0 = =math.ceil(speed_print * 20 / 40) +speed_print = 40 +speed_topbottom = =math.ceil(speed_print * 30 / 35) + +speed_wall = =math.ceil(speed_print * 35 / 40) +speed_wall_0 = =math.ceil(speed_wall * 30 / 35) +support_bottom_distance = =support_z_distance +support_z_distance = =layer_height +wall_0_inset = 0 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_High_Quality.inst.cfg new file mode 100644 index 0000000000..6299071194 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_High_Quality.inst.cfg @@ -0,0 +1,32 @@ +[general] +version = 4 +name = Extra Fine +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = high +weight = 1 +material = generic_cpe +variant = AA 0.4 +buildplate = Aluminum + +[values] +cool_min_speed = 12 +layer_height_0 = 0.17 +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_bed_temperature = 80 +material_bed_temperature_layer_0 = 90 +material_print_temperature = =default_material_print_temperature - 5 +material_initial_print_temperature = =material_print_temperature - 5 +material_final_print_temperature = =material_print_temperature - 10 +prime_blob_enable = False +speed_print = 50 +speed_layer_0 = =math.ceil(speed_print * 20 / 50) +speed_topbottom = =math.ceil(speed_print * 30 / 50) +speed_wall = =math.ceil(speed_print * 30 / 50) + +infill_pattern = zigzag +speed_infill = =math.ceil(speed_print * 40 / 50) \ No newline at end of file diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_High_Quality.inst.cfg new file mode 100644 index 0000000000..2afaf21de1 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_High_Quality.inst.cfg @@ -0,0 +1,71 @@ +[general] +version = 4 +name = Extra Fine +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = high +weight = 1 +material = generic_pc +variant = AA 0.4 +buildplate = Aluminum + +[values] +acceleration_enabled = True +acceleration_print = 4000 +adhesion_type = brim +brim_width = 10 +cool_fan_full_at_height = =layer_height_0 + layer_height +cool_fan_speed_max = 50 +cool_min_layer_time_fan_speed_max = 5 +cool_min_speed = 8 +infill_line_width = =round(line_width * 0.4 / 0.35, 2) +infill_overlap = 0 +infill_overlap_mm = 0.05 +infill_pattern = triangles +infill_wipe_dist = 0.1 +jerk_enabled = True +jerk_print = 25 +layer_height_0 = 0.17 +machine_min_cool_heat_time_window = 15 +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_bed_temperature = 115 +material_bed_temperature_layer_0 = 125 +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_print_temperature = =default_material_print_temperature - 10 +material_standby_temperature = 100 +multiple_mesh_overlap = 0 +ooze_shield_angle = 40 +prime_blob_enable = False +prime_tower_enable = True +prime_tower_wipe_enabled = True +raft_airgap = 0.25 +raft_interface_thickness = =max(layer_height * 1.5, 0.225) +retraction_count_max = 80 +retraction_extrusion_window = 1 +retraction_hop = 2 +retraction_hop_only_when_collides = True +retraction_min_travel = 0.8 +retraction_prime_speed = 15 +skin_overlap = 30 +speed_layer_0 = =math.ceil(speed_print * 25 / 50) +speed_print = 50 +speed_topbottom = =math.ceil(speed_print * 25 / 50) + +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 25 / 40) +support_bottom_distance = =support_z_distance +support_interface_density = 87.5 +support_interface_pattern = lines +switch_extruder_prime_speed = 15 +switch_extruder_retraction_amount = 20 +switch_extruder_retraction_speeds = 35 +wall_0_inset = 0 +wall_line_width_x = =round(line_width * 0.4 / 0.35, 2) +wall_thickness = 1.2 + + diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Draft_Print.inst.cfg new file mode 100644 index 0000000000..3d984e1dff --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Draft_Print.inst.cfg @@ -0,0 +1,27 @@ +[general] +version = 4 +name = Fast +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = draft +weight = -2 +material = generic_abs +variant = AA 0.8 +buildplate = Aluminum + +[values] +layer_height_0 = 0.3 +line_width = =machine_nozzle_size * 0.875 +material_bed_temperature = 90 +material_bed_temperature_layer_0 = 100 +material_print_temperature = =default_material_print_temperature + 20 +material_standby_temperature = 100 +prime_blob_enable = False +speed_print = 50 +speed_topbottom = =math.ceil(speed_print * 30 / 50) +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 30 / 40) +retract_at_layer_change = False diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg new file mode 100644 index 0000000000..6fd60c197a --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg @@ -0,0 +1,43 @@ +[general] +version = 4 +name = Fast - Experimental +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = draft +weight = -2 +material = generic_cpe_plus +variant = AA 0.8 +buildplate = Aluminum + +[values] +brim_width = 14 +cool_fan_full_at_height = =layer_height_0 + 14 * layer_height +infill_before_walls = True +layer_height_0 = 0.3 +line_width = =machine_nozzle_size * 0.9375 +machine_nozzle_cool_down_speed = 0.9 +machine_nozzle_heat_up_speed = 1.4 +material_bed_temperature = 105 +material_bed_temperature_layer_0 = 115 +material_print_temperature = =default_material_print_temperature - 10 +material_print_temperature_layer_0 = =material_print_temperature +material_standby_temperature = 100 +prime_blob_enable = False +prime_tower_enable = True +retraction_combing = off +retraction_hop = 0.1 +retraction_hop_enabled = False +skin_overlap = 0 +speed_layer_0 = =math.ceil(speed_print * 15 / 50) +speed_print = 50 +speed_slowdown_layers = 15 +speed_topbottom = =math.ceil(speed_print * 35 / 50) +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 35 / 40) +support_bottom_distance = =support_z_distance +support_line_width = =round(line_width * 0.6 / 0.7, 2) +support_z_distance = =layer_height +top_bottom_thickness = 1.2 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg new file mode 100644 index 0000000000..37aa25f9d8 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg @@ -0,0 +1,29 @@ +[general] +version = 4 +name = Fast +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = draft +weight = -2 +material = generic_cpe +variant = AA 0.8 +buildplate = Aluminum + +[values] +brim_width = 15 +layer_height_0 = 0.3 +line_width = =machine_nozzle_size * 0.875 +material_bed_temperature = 80 +material_bed_temperature_layer_0 = 90 +material_print_temperature = =default_material_print_temperature + 15 +material_standby_temperature = 100 +prime_blob_enable = False +prime_tower_enable = True +speed_print = 40 +speed_topbottom = =math.ceil(speed_print * 25 / 40) +speed_wall = =math.ceil(speed_print * 30 / 40) + +jerk_travel = 50 \ No newline at end of file diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg new file mode 100644 index 0000000000..9ebf2ea151 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Fast - Experimental +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = draft +weight = 0 +material = generic_pc +variant = AA 0.8 +buildplate = Aluminum + +[values] +brim_width = 10 +cool_fan_full_at_height = =layer_height_0 + 14 * layer_height +infill_before_walls = True +layer_height_0 = 0.3 +line_width = =machine_nozzle_size * 0.875 +material_bed_temperature = 115 +material_bed_temperature_layer_0 = 125 +material_print_temperature = =default_material_print_temperature - 5 +material_print_temperature_layer_0 = =material_print_temperature +material_standby_temperature = 100 +prime_blob_enable = False +raft_airgap = 0.5 +raft_margin = 15 +skin_overlap = 0 +speed_layer_0 = =math.ceil(speed_print * 15 / 50) +speed_print = 50 +speed_slowdown_layers = 15 +speed_topbottom = =math.ceil(speed_print * 25 / 50) +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 30 / 40) +support_line_width = =round(line_width * 0.6 / 0.7, 2) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Draft_Print.inst.cfg new file mode 100644 index 0000000000..94bede16bd --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Draft_Print.inst.cfg @@ -0,0 +1,53 @@ +[general] +version = 4 +name = Fast +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = draft +weight = -2 +material = generic_pp +variant = AA 0.8 +buildplate = Aluminum + +[values] +brim_width = 25 +cool_min_layer_time_fan_speed_max = 6 +cool_min_speed = 17 +top_skin_expand_distance = =line_width * 2 +infill_before_walls = True +infill_line_width = =round(line_width * 0.7 / 0.8, 2) +infill_pattern = tetrahedral +jerk_prime_tower = =math.ceil(jerk_print * 25 / 25) +jerk_support = =math.ceil(jerk_print * 25 / 25) +jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) +material_bed_temperature_layer_0 = =material_bed_temperature + 5 +material_print_temperature = =default_material_print_temperature - 2 +material_print_temperature_layer_0 = =default_material_print_temperature + 2 +material_standby_temperature = 100 +multiple_mesh_overlap = 0.2 +prime_tower_enable = True +prime_tower_flow = 100 +prime_tower_min_volume = 10 +retract_at_layer_change = False +retraction_count_max = 12 +retraction_extra_prime_amount = 0.5 +retraction_hop = 0.5 +retraction_min_travel = 1.5 +retraction_prime_speed = 15 +skin_line_width = =round(line_width * 0.78 / 0.8, 2) + +speed_wall_x = =math.ceil(speed_wall * 30 / 30) +support_bottom_distance = =support_z_distance +support_line_width = =round(line_width * 0.7 / 0.8, 2) +support_offset = =line_width +switch_extruder_prime_speed = 15 +switch_extruder_retraction_amount = 20 +switch_extruder_retraction_speeds = 45 +top_bottom_thickness = 1.6 +travel_compensate_overlapping_walls_0_enabled = False +wall_0_wipe_dist = =line_width * 2 +wall_line_width_x = =round(line_width * 0.8 / 0.8, 2) +wall_thickness = 1.6 From a7448e4970e9f1e72a82035dc12f2814e4437801 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 3 Aug 2018 09:59:23 +0200 Subject: [PATCH 096/243] Refactor material lookup tree creation --- cura/Machines/MaterialManager.py | 137 ++++++++++++++++--------------- 1 file changed, 69 insertions(+), 68 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 86f7dea81f..3c9a7bfd59 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -192,74 +192,75 @@ class MaterialManager(QObject): # "machine" -> "nozzle name" -> "buildplate name" -> "root material ID" -> specific material InstanceContainer self._diameter_machine_nozzle_buildplate_material_map = dict() for material_metadata in material_metadatas.values(): - # We don't store empty material in the lookup tables - if material_metadata["id"] == "empty_material": - continue - - root_material_id = material_metadata["base_file"] - definition = material_metadata["definition"] - approximate_diameter = material_metadata["approximate_diameter"] - - if approximate_diameter not in self._diameter_machine_nozzle_buildplate_material_map: - self._diameter_machine_nozzle_buildplate_material_map[approximate_diameter] = {} - - machine_nozzle_buildplate_material_map = self._diameter_machine_nozzle_buildplate_material_map[approximate_diameter] - if definition not in machine_nozzle_buildplate_material_map: - machine_nozzle_buildplate_material_map[definition] = MaterialNode() - - machine_node = machine_nozzle_buildplate_material_map[definition] - nozzle_name = material_metadata.get("variant_name") - buildplate_name = material_metadata.get("buildplate_name") - if not nozzle_name: - # if there is no nozzle, this material is for the machine, so put its metadata in the machine node. - machine_node.material_map[root_material_id] = MaterialNode(material_metadata) - else: - # this material is nozzle-specific, so we save it in a nozzle-specific node under the - # machine-specific node - - # Check first if the nozzle exists in the manager - existing_nozzle = variant_manager.getVariantNode(definition, nozzle_name, VariantType.NOZZLE) - if existing_nozzle is not None: - if nozzle_name not in machine_node.children_map: - machine_node.children_map[nozzle_name] = MaterialNode() - - nozzle_node = machine_node.children_map[nozzle_name] - - # Check build plate node - if not buildplate_name: - # if there is no buildplate, this material is for the machine, so put its metadata in the machine node. - if root_material_id in nozzle_node.material_map: # We shouldn't have duplicated nozzle-specific materials for the same machine. - ConfigurationErrorMessage.getInstance().addFaultyContainers(root_material_id) - continue - nozzle_node.material_map[root_material_id] = MaterialNode(material_metadata) - else: - # this material is nozzle-and-buildplate-specific, so we save it in a buildplate-specific node - # under the machine-specific node - - # Check first if the buildplate exists in the manager - existing_buildplate = variant_manager.getVariantNode(definition, buildplate_name, VariantType.BUILD_PLATE) - if existing_buildplate is not None: - if buildplate_name not in nozzle_node.children_map: - nozzle_node.children_map[buildplate_name] = MaterialNode() - - buildplate_node = nozzle_node.children_map[buildplate_name] - if root_material_id in buildplate_node.material_map: # We shouldn't have duplicated nozzle-and-buildplate-specific materials for the same machine. - ConfigurationErrorMessage.getInstance().addFaultyContainers(root_material_id) - continue - buildplate_node.material_map[root_material_id] = MaterialNode(material_metadata) - - else: - # Add this container id to the wrong containers list in the registry - Logger.log("w", "Not adding {id} to the material manager because the buildplate does not exist.".format(id = material_metadata["id"])) - self._container_registry.addWrongContainerId(material_metadata["id"]) - - else: - # Add this container id to the wrong containers list in the registry - Logger.log("w", "Not adding {id} to the material manager because the nozzle does not exist.".format(id = material_metadata["id"])) - self._container_registry.addWrongContainerId(material_metadata["id"]) + self.__addMaterialMetadataIntoLookupTree(material_metadata) self.materialsUpdated.emit() + def __addMaterialMetadataIntoLookupTree(self, material_metadata: dict) -> None: + material_id = material_metadata["id"] + + # We don't store empty material in the lookup tables + if material_id == "empty_material": + return + + root_material_id = material_metadata["base_file"] + definition = material_metadata["definition"] + approximate_diameter = material_metadata["approximate_diameter"] + + if approximate_diameter not in self._diameter_machine_nozzle_buildplate_material_map: + self._diameter_machine_nozzle_buildplate_material_map[approximate_diameter] = {} + + machine_nozzle_buildplate_material_map = self._diameter_machine_nozzle_buildplate_material_map[ + approximate_diameter] + if definition not in machine_nozzle_buildplate_material_map: + machine_nozzle_buildplate_material_map[definition] = MaterialNode() + + # This is a list of information regarding the intermediate nodes: + # nozzle -> buildplate + nozzle_name = material_metadata.get("variant_name") + buildplate_name = material_metadata.get("buildplate_name") + intermediate_node_info_list = [(nozzle_name, VariantType.NOZZLE), + (buildplate_name, VariantType.BUILD_PLATE), + ] + + variant_manager = self._application.getVariantManager() + + machine_node = machine_nozzle_buildplate_material_map[definition] + current_node = machine_node + current_intermediate_node_info_idx = 0 + error_message = None # type: Optional[str] + while current_intermediate_node_info_idx < len(intermediate_node_info_list): + variant_name, variant_type = intermediate_node_info_list[current_intermediate_node_info_idx] + if variant_name is not None: + # The new material has a specific variant, so it needs to be added to that specific branch in the tree. + variant = variant_manager.getVariantNode(definition, variant_name, variant_type) + if variant is None: + error_message = "Material {id} contains a variant {name} that does not exist.".format( + id = material_metadata["id"], name = variant_name) + break + + # Update the current node to advance to a more specific branch + if variant_name not in current_node.children_map: + current_node.children_map[variant_name] = MaterialNode() + current_node = current_node.children_map[variant_name] + + current_intermediate_node_info_idx += 1 + + if error_message is not None: + Logger.log("e", "%s It will not be added into the material lookup tree.", error_message) + self._container_registry.addWrongContainerId(material_metadata["id"]) + return + + # Add the material to the current tree node, which is the deepest (the most specific) branch we can find. + # Sanity check: Make sure that there is no duplicated materials. + if root_material_id in current_node.material_map: + Logger.log("e", "Duplicated material [%s] with root ID [%s]. It has already been added.", + material_id, root_material_id) + ConfigurationErrorMessage.getInstance().addFaultyContainers(root_material_id) + return + + current_node.material_map[root_material_id] = MaterialNode(material_metadata) + def _updateMaps(self): Logger.log("i", "Updating material lookup data ...") self.initialize() @@ -290,7 +291,7 @@ class MaterialManager(QObject): # # Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup. # - def getAvailableMaterials(self, machine_definition: "DefinitionContainer", extruder_nozzle_name: Optional[str], + def getAvailableMaterials(self, machine_definition: "DefinitionContainer", nozzle_name: Optional[str], buildplate_name: Optional[str], diameter: float) -> Dict[str, MaterialNode]: # round the diameter to get the approximate diameter rounded_diameter = str(round(diameter)) @@ -306,8 +307,8 @@ class MaterialManager(QObject): default_machine_node = machine_nozzle_buildplate_material_map.get(self._default_machine_definition_id) nozzle_node = None buildplate_node = None - if extruder_nozzle_name is not None and machine_node is not None: - nozzle_node = machine_node.getChildNode(extruder_nozzle_name) + if nozzle_name is not None and machine_node is not None: + nozzle_node = machine_node.getChildNode(nozzle_name) # Get buildplate node if possible if nozzle_node is not None and buildplate_name is not None: buildplate_node = nozzle_node.getChildNode(buildplate_name) From e2a97e3a012287ad8b50affc7692149e10b8669c Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 3 Aug 2018 10:28:21 +0200 Subject: [PATCH 097/243] Refactor quality lookup table creation --- cura/Machines/QualityManager.py | 50 +++++++++------------------------ 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 273f1ae11f..263b3a9620 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -98,45 +98,22 @@ class QualityManager(QObject): machine_node.addQualityMetadata(quality_type, metadata) continue - # Check if nozzle si specified - if nozzle_name is not None: - if nozzle_name not in machine_node.children_map: - machine_node.children_map[nozzle_name] = QualityNode() - nozzle_node = cast(QualityNode, machine_node.children_map[nozzle_name]) + current_node = machine_node + intermediate_node_info_list = [nozzle_name, buildplate_name, root_material_id] + current_intermediate_node_info_idx = 0 - # Check if buildplate is specified - if buildplate_name is not None: - if buildplate_name not in nozzle_node.children_map: - nozzle_node.children_map[buildplate_name] = QualityNode() - buildplate_node = cast(QualityNode, nozzle_node.children_map[buildplate_name]) + while current_intermediate_node_info_idx < len(intermediate_node_info_list): + node_name = intermediate_node_info_list[current_intermediate_node_info_idx] + if node_name is not None: + # There is specific information, update the current node to go deeper so we can add this quality + # at the most specific branch in the lookup tree. + if node_name not in current_node.children_map: + current_node.children_map[node_name] = QualityNode() + current_node = cast(QualityNode, current_node.children_map[node_name]) - if root_material_id is None: - buildplate_node.addQualityMetadata(quality_type, metadata) - else: - if root_material_id not in buildplate_node.children_map: - buildplate_node.children_map[root_material_id] = QualityNode() - material_node = cast(QualityNode, buildplate_node.children_map[root_material_id]) + current_intermediate_node_info_idx += 1 - material_node.addQualityMetadata(quality_type, metadata) - - else: - if root_material_id is None: - nozzle_node.addQualityMetadata(quality_type, metadata) - else: - if root_material_id not in nozzle_node.children_map: - nozzle_node.children_map[root_material_id] = QualityNode() - material_node = cast(QualityNode, nozzle_node.children_map[root_material_id]) - - material_node.addQualityMetadata(quality_type, metadata) - - else: - # If nozzle is not specified, check if material is specified. - if root_material_id is not None: - if root_material_id not in machine_node.children_map: - machine_node.children_map[root_material_id] = QualityNode() - material_node = cast(QualityNode, machine_node.children_map[root_material_id]) - - material_node.addQualityMetadata(quality_type, metadata) + current_node.addQualityMetadata(quality_type, metadata) # Initialize the lookup tree for quality_changes profiles with following structure: # -> -> @@ -337,7 +314,6 @@ class QualityManager(QObject): quality_group = quality_group_dict[quality_type] if position not in quality_group.nodes_for_extruders: quality_group.nodes_for_extruders[position] = quality_node - #break # Update availabilities for each quality group self._updateQualityGroupsAvailability(machine, quality_group_dict.values()) From 206a32ae5011f7c703a34c542a3eb84ddae7c067 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 3 Aug 2018 10:41:36 +0200 Subject: [PATCH 098/243] Refactor quality lookup --- cura/Machines/QualityManager.py | 45 ++++++++++++++------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 263b3a9620..c0954c005c 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -263,38 +263,31 @@ class QualityManager(QObject): # Each points above can be represented as a node in the lookup tree, so here we simply put those nodes into # the list with priorities as the order. Later, we just need to loop over each node in this list and fetch # qualities from there. + node_info_list_0 = [nozzle_name, buildplate_name, root_material_id] + current_node_info_idx = 0 nodes_to_check = [] - if nozzle_name: - # In this case, we have both a specific nozzle and a specific material - nozzle_node = machine_node.getChildNode(nozzle_name) - if nozzle_node and has_material: - # Check build plate if exists - if buildplate_name: - buildplate_node = nozzle_node.getChildNode(buildplate_name) - if buildplate_node and has_material: - for root_material_id in root_material_id_list: - material_node = buildplate_node.getChildNode(root_material_id) - if material_node: - nodes_to_check.append(material_node) - break - nodes_to_check.append(buildplate_node) + # This function tries to recursively find the deepest (the most specific) branch and add those nodes to + # the search list in the order described above. So, by iterating over that search node list, we first look + # in the more specific branches and then the less specific (generic) ones. + def addNodesToCheck(node, nodes_to_check_list, node_info_list, node_info_idx): + if current_node_info_idx < len(node_info_list): + node_name = node_info_list[node_info_idx] + if node_name is not None: + current_node = node.getChildNode(node_name) + if current_node is not None and has_material: + addNodesToCheck(current_node, nodes_to_check_list, node_info_list, node_info_idx + 1) - # Then add nozzle specific materials - for root_material_id in root_material_id_list: - material_node = nozzle_node.getChildNode(root_material_id) + if has_material: + for rmid in root_material_id_list: + material_node = node.getChildNode(rmid) if material_node: - nodes_to_check.append(material_node) + nodes_to_check_list.append(material_node) break - nodes_to_check.append(nozzle_node) - # In this case, we only have a specific material but NOT a nozzle - if has_material: - for root_material_id in root_material_id_list: - material_node = machine_node.getChildNode(root_material_id) - if material_node: - nodes_to_check.append(material_node) - break + nodes_to_check_list.append(node) + + addNodesToCheck(machine_node, nodes_to_check, node_info_list_0, 0) nodes_to_check += [machine_node, default_machine_node] for node in nodes_to_check: From 1a050968a51f6f1e91e9ff72a8b856b2510ecc28 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 3 Aug 2018 10:51:01 +0200 Subject: [PATCH 099/243] Clear out old gcode This way if you move the model, and don't hit prepare again, you can end up exporting the old gcode again thinking its new gcode. --- plugins/CuraEngineBackend/CuraEngineBackend.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index beec374d8d..796495fef8 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -541,6 +541,9 @@ class CuraEngineBackend(QObject, Backend): ## Remove old layer data (if any) def _clearLayerData(self, build_plate_numbers: Set = None) -> None: + # Clear out any old gcode + self._scene.gcode_dict = {} # type: dict + for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax. if node.callDecoration("getLayerData"): if not build_plate_numbers or node.callDecoration("getBuildPlateNumber") in build_plate_numbers: From 1d0e88dc161844f4342176b1da4b810348bf0ba0 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 3 Aug 2018 11:00:56 +0200 Subject: [PATCH 100/243] Fix typing issue --- plugins/CuraEngineBackend/CuraEngineBackend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 796495fef8..56763a6632 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -542,7 +542,7 @@ class CuraEngineBackend(QObject, Backend): ## Remove old layer data (if any) def _clearLayerData(self, build_plate_numbers: Set = None) -> None: # Clear out any old gcode - self._scene.gcode_dict = {} # type: dict + self._scene.gcode_dict = {} # type: ignore for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax. if node.callDecoration("getLayerData"): From aadbebd4572c8be0886c9a78c99daa89ba45a52d Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 3 Aug 2018 11:13:35 +0200 Subject: [PATCH 101/243] After enabling the video strem from a printer the first image is Null CURA-5612 --- cura/CameraImageProvider.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cura/CameraImageProvider.py b/cura/CameraImageProvider.py index ddf978f625..428b174ed4 100644 --- a/cura/CameraImageProvider.py +++ b/cura/CameraImageProvider.py @@ -12,7 +12,13 @@ class CameraImageProvider(QQuickImageProvider): def requestImage(self, id, size): for output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices(): try: - return output_device.activePrinter.camera.getImage(), QSize(15, 15) + + image = output_device.activePrinter.camera.getImage() + + if image.isNull(): + return QImage(), QSize(15, 15) + + return image, QSize(15, 15) except AttributeError: pass return QImage(), QSize(15, 15) \ No newline at end of file From bcedef3bbeffbe3317fbb49b43bd97efd9860d2a Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 3 Aug 2018 11:38:42 +0200 Subject: [PATCH 102/243] Continue scrolling over compatibility charts Contributes to CURA-5598 --- .../Toolbox/resources/qml/ToolboxCompatibilityChart.qml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml b/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml index 4978af6168..f4ee82e7cf 100644 --- a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml +++ b/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml @@ -29,6 +29,14 @@ Item anchors.topMargin: UM.Theme.getSize("default_margin").height width: parent.width frameVisible: false + + // Workaround for scroll issues (QTBUG-49652) + flickableItem.interactive: false + Component.onCompleted: { + for (var i = 0; i < flickableItem.children.length; ++i) { + flickableItem.children[i].enabled = false + } + } selectionMode: 0 model: packageData.supported_configs headerDelegate: Rectangle From c47de049830f236ebbfd2479a59c8a4b585c5a66 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 3 Aug 2018 11:41:08 +0200 Subject: [PATCH 103/243] Fix bracket style Contributes to CURA-5598 --- plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml b/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml index f4ee82e7cf..1efcde2110 100644 --- a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml +++ b/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml @@ -32,8 +32,10 @@ Item // Workaround for scroll issues (QTBUG-49652) flickableItem.interactive: false - Component.onCompleted: { - for (var i = 0; i < flickableItem.children.length; ++i) { + Component.onCompleted: + { + for (var i = 0; i < flickableItem.children.length; ++i) + { flickableItem.children[i].enabled = false } } From 9c8ac6e9ed25a52e9370f520fae703404be7f6c5 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 3 Aug 2018 11:42:55 +0200 Subject: [PATCH 104/243] After switching the Monitor Tab set Null to active output printer CURA-5612 --- plugins/UM3NetworkPrinting/ClusterMonitorItem.qml | 11 +++++++++++ plugins/UM3NetworkPrinting/PrinterVideoStream.qml | 10 ++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml b/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml index 86bdaae0a5..c21ff3f472 100644 --- a/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml +++ b/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml @@ -9,6 +9,7 @@ Component { Rectangle { + id: rectangle width: maximumWidth height: maximumHeight color: UM.Theme.getColor("viewport_background") @@ -103,5 +104,15 @@ Component visible: OutputDevice.activePrinter != null anchors.fill:parent } + + onVisibleChanged: + { + if(rectangle != null && !rectangle.visible) + { + // After switching the Tab ensure that active printer is Null, the video stream image + // might be active + OutputDevice.setActivePrinter(null) + } + } } } diff --git a/plugins/UM3NetworkPrinting/PrinterVideoStream.qml b/plugins/UM3NetworkPrinting/PrinterVideoStream.qml index 7f7b2ad546..e34924ba88 100644 --- a/plugins/UM3NetworkPrinting/PrinterVideoStream.qml +++ b/plugins/UM3NetworkPrinting/PrinterVideoStream.qml @@ -89,9 +89,11 @@ Item MouseArea { - anchors.fill: cameraImage - onClicked: { /* no-op */ } - z: 1 + anchors.fill: cameraImage + onClicked: + { + OutputDevice.setActivePrinter(null) + } + z: 1 } - } From 38a0c9b66de36f46390b42834f595557a56d1df0 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 3 Aug 2018 12:02:11 +0200 Subject: [PATCH 105/243] Add some extra information when the Cura can't write the files. --- plugins/3MFWriter/ThreeMFWriter.py | 4 ++++ plugins/GCodeGzWriter/GCodeGzWriter.py | 8 +++++++- plugins/GCodeWriter/GCodeWriter.py | 5 +++++ plugins/UFPWriter/UFPWriter.py | 10 +++++++++- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 8d54f475d6..640aabd30c 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -25,6 +25,9 @@ except ImportError: import zipfile import UM.Application +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") + class ThreeMFWriter(MeshWriter): def __init__(self): @@ -173,6 +176,7 @@ class ThreeMFWriter(MeshWriter): archive.writestr(relations_file, b' \n' + ET.tostring(relations_element)) except Exception as e: Logger.logException("e", "Error writing zip file") + self.setInformation(catalog.i18nc("@error:zip", "Error writing 3mf file.")) return False finally: if not self._store_archive: diff --git a/plugins/GCodeGzWriter/GCodeGzWriter.py b/plugins/GCodeGzWriter/GCodeGzWriter.py index 6ddecdb0bd..e191a9c427 100644 --- a/plugins/GCodeGzWriter/GCodeGzWriter.py +++ b/plugins/GCodeGzWriter/GCodeGzWriter.py @@ -10,6 +10,9 @@ from UM.Mesh.MeshWriter import MeshWriter #The class we're extending/implementin from UM.PluginRegistry import PluginRegistry from UM.Scene.SceneNode import SceneNode #For typing. +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") + ## A file writer that writes gzipped g-code. # # If you're zipping g-code, you might as well use gzip! @@ -28,12 +31,15 @@ class GCodeGzWriter(MeshWriter): def write(self, stream: BufferedIOBase, nodes: List[SceneNode], mode = MeshWriter.OutputMode.BinaryMode) -> bool: if mode != MeshWriter.OutputMode.BinaryMode: Logger.log("e", "GCodeGzWriter does not support text mode.") + self.setInformation(catalog.i18nc("@error:not supported", "GCodeGzWriter does not support text mode.")) return False #Get the g-code from the g-code writer. gcode_textio = StringIO() #We have to convert the g-code into bytes. - success = cast(MeshWriter, PluginRegistry.getInstance().getPluginObject("GCodeWriter")).write(gcode_textio, None) + gcode_writer = cast(MeshWriter, PluginRegistry.getInstance().getPluginObject("GCodeWriter")) + success = gcode_writer.write(gcode_textio, None) if not success: #Writing the g-code failed. Then I can also not write the gzipped g-code. + self.setInformation(gcode_writer.getInformation()) return False result = gzip.compress(gcode_textio.getvalue().encode("utf-8")) diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index aea0698d19..59e9a29691 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -12,6 +12,8 @@ from UM.Settings.InstanceContainer import InstanceContainer from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") ## Writes g-code to a file. # @@ -62,11 +64,13 @@ class GCodeWriter(MeshWriter): def write(self, stream, nodes, mode = MeshWriter.OutputMode.TextMode): if mode != MeshWriter.OutputMode.TextMode: Logger.log("e", "GCodeWriter does not support non-text mode.") + self.setInformation(catalog.i18nc("@error:not supported", "GCodeWriter does not support non-text mode.")) return False active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate scene = Application.getInstance().getController().getScene() if not hasattr(scene, "gcode_dict"): + self.setInformation(catalog.i18nc("@warning:status", "Please generate G-code before saving.")) return False gcode_dict = getattr(scene, "gcode_dict") gcode_list = gcode_dict.get(active_build_plate, None) @@ -82,6 +86,7 @@ class GCodeWriter(MeshWriter): stream.write(settings) return True + self.setInformation(catalog.i18nc("@warning:status", "Please generate G-code before saving.")) return False ## Create a new container with container 2 as base and container 1 written over it. diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index aca293e25a..9344bf54da 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -1,5 +1,6 @@ #Copyright (c) 2018 Ultimaker B.V. #Cura is released under the terms of the LGPLv3 or higher. +from typing import cast from Charon.VirtualFile import VirtualFile #To open UFP files. from Charon.OpenMode import OpenMode #To indicate that we want to write to UFP files. @@ -13,6 +14,9 @@ from PyQt5.QtCore import QBuffer from cura.Snapshot import Snapshot +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") + class UFPWriter(MeshWriter): def __init__(self): @@ -32,7 +36,11 @@ class UFPWriter(MeshWriter): #Store the g-code from the scene. archive.addContentType(extension = "gcode", mime_type = "text/x-gcode") gcode_textio = StringIO() #We have to convert the g-code into bytes. - PluginRegistry.getInstance().getPluginObject("GCodeWriter").write(gcode_textio, None) + gcode_writer = cast(MeshWriter, PluginRegistry.getInstance().getPluginObject("GCodeWriter")) + success = gcode_writer.write(gcode_textio, None) + if not success: #Writing the g-code failed. Then I can also not write the gzipped g-code. + self.setInformation(gcode_writer.getInformation()) + return False gcode = archive.getStream("/3D/model.gcode") gcode.write(gcode_textio.getvalue().encode("UTF-8")) archive.addRelation(virtual_path = "/3D/model.gcode", relation_type = "http://schemas.ultimaker.org/package/2018/relationships/gcode") From 977c0958a337505b3ef982bc6d77c11e5b8614b6 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 3 Aug 2018 13:40:54 +0200 Subject: [PATCH 106/243] The manually added priters by IP have "(manual) suffix --- plugins/UM3NetworkPrinting/DiscoverUM3Action.qml | 7 +------ plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml index 8ecbe016f1..e4d75e8f6d 100644 --- a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml +++ b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml @@ -349,11 +349,6 @@ Cura.MachineAction addressField.focus = true; } - onAccepted: - { - manager.setManualDevice(printerKey, addressText) - } - Column { anchors.fill: parent spacing: UM.Theme.getSize("default_margin").height @@ -393,7 +388,7 @@ Cura.MachineAction text: catalog.i18nc("@action:button", "OK") onClicked: { - manualPrinterDialog.accept() + manager.setManualDevice(manualPrinterDialog.printerKey, manualPrinterDialog.addressText) manualPrinterDialog.hide() } enabled: manualPrinterDialog.addressText.trim() != "" diff --git a/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py index 3644bbf056..f4749a6747 100644 --- a/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py @@ -198,7 +198,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): has_cluster_capable_firmware = Version(system_info["firmware"]) > self._min_cluster_version instance_name = "manual:%s" % address properties = { - b"name": system_info["name"].encode("utf-8"), + b"name": (system_info["name"] + " (manual)").encode("utf-8"), b"address": address.encode("utf-8"), b"firmware_version": system_info["firmware"].encode("utf-8"), b"manual": b"true", From 38ce73365a8315e0b5ccaa52dab3b5dc49ac8469 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 3 Aug 2018 13:45:08 +0200 Subject: [PATCH 107/243] Manually added printers have suffix "( manual)" --- plugins/UM3NetworkPrinting/DiscoverUM3Action.qml | 7 +------ plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml index 8ecbe016f1..e4d75e8f6d 100644 --- a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml +++ b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml @@ -349,11 +349,6 @@ Cura.MachineAction addressField.focus = true; } - onAccepted: - { - manager.setManualDevice(printerKey, addressText) - } - Column { anchors.fill: parent spacing: UM.Theme.getSize("default_margin").height @@ -393,7 +388,7 @@ Cura.MachineAction text: catalog.i18nc("@action:button", "OK") onClicked: { - manualPrinterDialog.accept() + manager.setManualDevice(manualPrinterDialog.printerKey, manualPrinterDialog.addressText) manualPrinterDialog.hide() } enabled: manualPrinterDialog.addressText.trim() != "" diff --git a/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py index 3644bbf056..f4749a6747 100644 --- a/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py @@ -198,7 +198,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): has_cluster_capable_firmware = Version(system_info["firmware"]) > self._min_cluster_version instance_name = "manual:%s" % address properties = { - b"name": system_info["name"].encode("utf-8"), + b"name": (system_info["name"] + " (manual)").encode("utf-8"), b"address": address.encode("utf-8"), b"firmware_version": system_info["firmware"].encode("utf-8"), b"manual": b"true", From 99cb9e93b30fcc8ca061ef379d0df81b7b9ba1d4 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 3 Aug 2018 13:46:22 +0200 Subject: [PATCH 108/243] Revert "The manually added priters by IP have "(manual) suffix" This reverts commit 977c0958a337505b3ef982bc6d77c11e5b8614b6. --- plugins/UM3NetworkPrinting/DiscoverUM3Action.qml | 7 ++++++- plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml index e4d75e8f6d..8ecbe016f1 100644 --- a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml +++ b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml @@ -349,6 +349,11 @@ Cura.MachineAction addressField.focus = true; } + onAccepted: + { + manager.setManualDevice(printerKey, addressText) + } + Column { anchors.fill: parent spacing: UM.Theme.getSize("default_margin").height @@ -388,7 +393,7 @@ Cura.MachineAction text: catalog.i18nc("@action:button", "OK") onClicked: { - manager.setManualDevice(manualPrinterDialog.printerKey, manualPrinterDialog.addressText) + manualPrinterDialog.accept() manualPrinterDialog.hide() } enabled: manualPrinterDialog.addressText.trim() != "" diff --git a/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py index f4749a6747..3644bbf056 100644 --- a/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py @@ -198,7 +198,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): has_cluster_capable_firmware = Version(system_info["firmware"]) > self._min_cluster_version instance_name = "manual:%s" % address properties = { - b"name": (system_info["name"] + " (manual)").encode("utf-8"), + b"name": system_info["name"].encode("utf-8"), b"address": address.encode("utf-8"), b"firmware_version": system_info["firmware"].encode("utf-8"), b"manual": b"true", From ea8d10783ce1e3ba58309c2e5fe1cdbb6654c0a3 Mon Sep 17 00:00:00 2001 From: DavidGergely Date: Fri, 3 Aug 2018 14:12:36 +0200 Subject: [PATCH 109/243] Cura-5457 prime tower settings New settings for the prime towers for all profiles expect PP0.8 printcore --- resources/definitions/fdmprinter.def.json | 2 +- .../quality/ultimaker3/um3_aa0.25_ABS_Normal_Quality.inst.cfg | 2 -- .../quality/ultimaker3/um3_aa0.25_CPE_Normal_Quality.inst.cfg | 2 -- resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg | 1 - .../quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg | 1 - .../quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg | 1 - .../ultimaker_s5/um_s5_aa0.25_ABS_Normal_Quality.inst.cfg | 2 -- .../ultimaker_s5/um_s5_aa0.25_CPE_Normal_Quality.inst.cfg | 2 -- .../quality/ultimaker_s5/um_s5_aa0.8_TPU_Draft_Print.inst.cfg | 1 - .../ultimaker_s5/um_s5_aa0.8_TPU_Superdraft_Print.inst.cfg | 1 - .../ultimaker_s5/um_s5_aa0.8_TPU_Verydraft_Print.inst.cfg | 1 - resources/variants/ultimaker3_bb0.8.inst.cfg | 1 - resources/variants/ultimaker3_bb04.inst.cfg | 1 - resources/variants/ultimaker3_extended_bb0.8.inst.cfg | 1 - resources/variants/ultimaker3_extended_bb04.inst.cfg | 1 - resources/variants/ultimaker_s5_bb0.8.inst.cfg | 1 - resources/variants/ultimaker_s5_bb04.inst.cfg | 1 - 17 files changed, 1 insertion(+), 21 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index b767aac7b9..daf09d2701 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5057,7 +5057,7 @@ "description": "The minimum volume for each layer of the prime tower in order to purge enough material.", "unit": "mm³", "type": "float", - "default_value": 5, + "default_value": 6, "minimum_value": "0", "maximum_value_warning": "((resolveOrValue('prime_tower_size') * 0.5) ** 2 * 3.14159 * resolveOrValue('layer_height') if prime_tower_circular else resolveOrValue('prime_tower_size') ** 2 * resolveOrValue('layer_height')) - sum(extruderValues('prime_tower_min_volume')) + prime_tower_min_volume", "enabled": "resolveOrValue('prime_tower_enable')", diff --git a/resources/quality/ultimaker3/um3_aa0.25_ABS_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.25_ABS_Normal_Quality.inst.cfg index 428f5c1101..5139a1fea8 100644 --- a/resources/quality/ultimaker3/um3_aa0.25_ABS_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.25_ABS_Normal_Quality.inst.cfg @@ -15,8 +15,6 @@ variant = AA 0.25 cool_fan_speed = 40 infill_overlap = 15 material_final_print_temperature = =material_print_temperature - 5 -prime_tower_size = 12 -prime_tower_min_volume = 2 retraction_prime_speed = 25 speed_topbottom = =math.ceil(speed_print * 30 / 55) wall_thickness = 0.92 diff --git a/resources/quality/ultimaker3/um3_aa0.25_CPE_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.25_CPE_Normal_Quality.inst.cfg index 127032e118..4e81b4f39e 100644 --- a/resources/quality/ultimaker3/um3_aa0.25_CPE_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.25_CPE_Normal_Quality.inst.cfg @@ -12,8 +12,6 @@ material = generic_cpe variant = AA 0.25 [values] -prime_tower_size = 12 -prime_tower_min_volume = 2 retraction_extrusion_window = 0.5 speed_infill = =math.ceil(speed_print * 40 / 55) speed_topbottom = =math.ceil(speed_print * 30 / 55) diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg index 1d5cea601f..b6e6fdecb6 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg @@ -34,7 +34,6 @@ material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True prime_tower_flow = 100 -prime_tower_min_volume = 10 retract_at_layer_change = False retraction_count_max = 12 retraction_extra_prime_amount = 0.5 diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg index 0c94b64159..b64d37310e 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg @@ -35,7 +35,6 @@ material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True prime_tower_flow = 100 -prime_tower_min_volume = 15 retract_at_layer_change = False retraction_count_max = 12 retraction_extra_prime_amount = 0.5 diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg index 50282f8b49..d9e8f9ec2e 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg @@ -34,7 +34,6 @@ material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True prime_tower_flow = 100 -prime_tower_min_volume = 20 retract_at_layer_change = False retraction_count_max = 12 retraction_extra_prime_amount = 0.5 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_ABS_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_ABS_Normal_Quality.inst.cfg index e58a1bd87d..f2e05b08e8 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_ABS_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_ABS_Normal_Quality.inst.cfg @@ -15,8 +15,6 @@ variant = AA 0.25 cool_fan_speed = 40 infill_overlap = 15 material_final_print_temperature = =material_print_temperature - 5 -prime_tower_size = 12 -prime_tower_min_volume = 2 retraction_prime_speed = 25 speed_topbottom = =math.ceil(speed_print * 30 / 55) wall_thickness = 0.92 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_CPE_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_CPE_Normal_Quality.inst.cfg index 1c1833a385..2068ed51c0 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_CPE_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_CPE_Normal_Quality.inst.cfg @@ -12,8 +12,6 @@ material = generic_cpe variant = AA 0.25 [values] -prime_tower_size = 12 -prime_tower_min_volume = 2 retraction_extrusion_window = 0.5 speed_infill = =math.ceil(speed_print * 40 / 55) speed_topbottom = =math.ceil(speed_print * 30 / 55) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Draft_Print.inst.cfg index f88da43ac1..e8c58ce32c 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Draft_Print.inst.cfg @@ -32,7 +32,6 @@ material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True prime_tower_flow = 100 -prime_tower_min_volume = 10 retract_at_layer_change = False retraction_count_max = 12 retraction_extra_prime_amount = 0.5 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Superdraft_Print.inst.cfg index 2967f3539b..ff723c4ed4 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Superdraft_Print.inst.cfg @@ -33,7 +33,6 @@ material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True prime_tower_flow = 100 -prime_tower_min_volume = 20 retract_at_layer_change = False retraction_count_max = 12 retraction_extra_prime_amount = 0.5 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Verydraft_Print.inst.cfg index caa87f9437..7e36e9d354 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_TPU_Verydraft_Print.inst.cfg @@ -32,7 +32,6 @@ material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True prime_tower_flow = 100 -prime_tower_min_volume = 15 retract_at_layer_change = False retraction_count_max = 12 retraction_extra_prime_amount = 0.5 diff --git a/resources/variants/ultimaker3_bb0.8.inst.cfg b/resources/variants/ultimaker3_bb0.8.inst.cfg index 9ad4284b40..ace0bf3a94 100644 --- a/resources/variants/ultimaker3_bb0.8.inst.cfg +++ b/resources/variants/ultimaker3_bb0.8.inst.cfg @@ -40,7 +40,6 @@ material_print_temperature = =default_material_print_temperature + 10 material_standby_temperature = 100 multiple_mesh_overlap = 0 prime_tower_enable = False -prime_tower_min_volume = 20 prime_tower_wipe_enabled = True raft_acceleration = =acceleration_layer_0 raft_airgap = 0 diff --git a/resources/variants/ultimaker3_bb04.inst.cfg b/resources/variants/ultimaker3_bb04.inst.cfg index f07a4a55f9..d571cabc9b 100644 --- a/resources/variants/ultimaker3_bb04.inst.cfg +++ b/resources/variants/ultimaker3_bb04.inst.cfg @@ -22,7 +22,6 @@ jerk_support_bottom = =math.ceil(jerk_support_interface * 1 / 10) machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = BB 0.4 machine_nozzle_tip_outer_diameter = 1.0 -prime_tower_min_volume = 15 raft_base_speed = 20 raft_interface_speed = 20 raft_speed = 25 diff --git a/resources/variants/ultimaker3_extended_bb0.8.inst.cfg b/resources/variants/ultimaker3_extended_bb0.8.inst.cfg index d7a76d538a..fe760c93b8 100644 --- a/resources/variants/ultimaker3_extended_bb0.8.inst.cfg +++ b/resources/variants/ultimaker3_extended_bb0.8.inst.cfg @@ -40,7 +40,6 @@ material_print_temperature = =default_material_print_temperature + 10 material_standby_temperature = 100 multiple_mesh_overlap = 0 prime_tower_enable = False -prime_tower_min_volume = 20 prime_tower_wipe_enabled = True raft_acceleration = =acceleration_layer_0 raft_airgap = 0 diff --git a/resources/variants/ultimaker3_extended_bb04.inst.cfg b/resources/variants/ultimaker3_extended_bb04.inst.cfg index 6e882cfa04..742dc9896e 100644 --- a/resources/variants/ultimaker3_extended_bb04.inst.cfg +++ b/resources/variants/ultimaker3_extended_bb04.inst.cfg @@ -22,7 +22,6 @@ jerk_support_bottom = =math.ceil(jerk_support_interface * 1 / 10) machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = BB 0.4 machine_nozzle_tip_outer_diameter = 1.0 -prime_tower_min_volume = 15 raft_base_speed = 20 raft_interface_speed = 20 raft_speed = 25 diff --git a/resources/variants/ultimaker_s5_bb0.8.inst.cfg b/resources/variants/ultimaker_s5_bb0.8.inst.cfg index 6b954041ab..c1c5c1a10b 100644 --- a/resources/variants/ultimaker_s5_bb0.8.inst.cfg +++ b/resources/variants/ultimaker_s5_bb0.8.inst.cfg @@ -40,7 +40,6 @@ material_print_temperature = =default_material_print_temperature + 10 material_standby_temperature = 100 multiple_mesh_overlap = 0 prime_tower_enable = False -prime_tower_min_volume = 20 prime_tower_wipe_enabled = True raft_acceleration = =acceleration_layer_0 raft_airgap = 0 diff --git a/resources/variants/ultimaker_s5_bb04.inst.cfg b/resources/variants/ultimaker_s5_bb04.inst.cfg index 634920ca65..b5ff8d51f6 100644 --- a/resources/variants/ultimaker_s5_bb04.inst.cfg +++ b/resources/variants/ultimaker_s5_bb04.inst.cfg @@ -22,7 +22,6 @@ jerk_support_bottom = =math.ceil(jerk_support_interface * 1 / 10) machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = BB 0.4 machine_nozzle_tip_outer_diameter = 1.0 -prime_tower_min_volume = 20 raft_base_speed = 20 raft_interface_speed = 20 raft_speed = 25 From 2a6da9fe8ea901aaa3942b20363285ec78fe55c8 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 3 Aug 2018 14:28:45 +0200 Subject: [PATCH 110/243] Only show material packages when clicking an author Contributes to CURA-5604 --- .../resources/qml/ToolboxDownloadsGridTile.qml | 4 ++++ plugins/Toolbox/src/Toolbox.py | 11 ++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml index 392b867071..f7b964b957 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml @@ -115,6 +115,10 @@ Item { toolbox.viewPage = "author" toolbox.filterModelByProp("packages", "author_id", model.id) + toolbox.setFilters("packages", { + "author_id": model.id, + "type": "material" + }) } break default: diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index a9d0bb03d1..fbc2f98b3b 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -783,7 +783,16 @@ class Toolbox(QObject, Extension): self._models[modelType].setFilter({ filterType: parameter }) self.filterChanged.emit() - @pyqtSlot() + @pyqtSlot(str, "QVariantMap") + def setFilters(self, modelType: str, filterDict: dict): + if not self._models[modelType]: + Logger.log("w", "Toolbox: Couldn't filter %s model because it doesn't exist.", modelType) + return + print(filterDict) + self._models[modelType].setFilter(filterDict) + self.filterChanged.emit() + + @pyqtSlot(str) def removeFilters(self, modelType: str): if not self._models[modelType]: Logger.log("w", "Toolbox: Couldn't remove filters on %s model because it doesn't exist.", modelType) From 7856e4746711c648a24d34b25a9d95f821495763 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 3 Aug 2018 14:30:49 +0200 Subject: [PATCH 111/243] Remove old filtering Contributes to CURA-5604 --- plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml index f7b964b957..ebd4c006f8 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml @@ -114,7 +114,6 @@ Item else { toolbox.viewPage = "author" - toolbox.filterModelByProp("packages", "author_id", model.id) toolbox.setFilters("packages", { "author_id": model.id, "type": "material" From 8268419eda658541ca03e793047a0ff064954aad Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 3 Aug 2018 14:31:30 +0200 Subject: [PATCH 112/243] Remove debug print() Contributes to CURA-5604 --- plugins/Toolbox/src/Toolbox.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index fbc2f98b3b..e948236baf 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -788,7 +788,6 @@ class Toolbox(QObject, Extension): if not self._models[modelType]: Logger.log("w", "Toolbox: Couldn't filter %s model because it doesn't exist.", modelType) return - print(filterDict) self._models[modelType].setFilter(filterDict) self.filterChanged.emit() From 20806eeb72afeae35b33808381986978a982088c Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 3 Aug 2018 14:37:09 +0200 Subject: [PATCH 113/243] Refactor some code CURA-5612 --- cura/CameraImageProvider.py | 9 ++++----- plugins/UM3NetworkPrinting/ClusterMonitorItem.qml | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cura/CameraImageProvider.py b/cura/CameraImageProvider.py index 428b174ed4..ff5c51f24b 100644 --- a/cura/CameraImageProvider.py +++ b/cura/CameraImageProvider.py @@ -4,21 +4,20 @@ from PyQt5.QtCore import QSize from UM.Application import Application + class CameraImageProvider(QQuickImageProvider): def __init__(self): - QQuickImageProvider.__init__(self, QQuickImageProvider.Image) + super().__init__(QQuickImageProvider.Image) ## Request a new image. def requestImage(self, id, size): for output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices(): try: - image = output_device.activePrinter.camera.getImage() - if image.isNull(): - return QImage(), QSize(15, 15) + image = QImage() return image, QSize(15, 15) except AttributeError: pass - return QImage(), QSize(15, 15) \ No newline at end of file + return QImage(), QSize(15, 15) diff --git a/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml b/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml index c21ff3f472..0e86d55de8 100644 --- a/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml +++ b/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml @@ -9,7 +9,7 @@ Component { Rectangle { - id: rectangle + id: monitorFrame width: maximumWidth height: maximumHeight color: UM.Theme.getColor("viewport_background") @@ -107,7 +107,7 @@ Component onVisibleChanged: { - if(rectangle != null && !rectangle.visible) + if (!monitorFrame.visible) { // After switching the Tab ensure that active printer is Null, the video stream image // might be active From 1bacdabf358ae8a52342aca8b29263cc680c42f2 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 3 Aug 2018 14:42:34 +0200 Subject: [PATCH 114/243] Minor refactor --- plugins/Toolbox/src/Toolbox.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index e948236baf..c4205b8ed5 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -776,25 +776,25 @@ class Toolbox(QObject, Extension): # Filter Models: # -------------------------------------------------------------------------- @pyqtSlot(str, str, str) - def filterModelByProp(self, modelType: str, filterType: str, parameter: str): - if not self._models[modelType]: - Logger.log("w", "Toolbox: Couldn't filter %s model because it doesn't exist.", modelType) + def filterModelByProp(self, model_type: str, filter_type: str, parameter: str) -> None: + if not self._models[model_type]: + Logger.log("w", "Toolbox: Couldn't filter %s model because it doesn't exist.", model_type) return - self._models[modelType].setFilter({ filterType: parameter }) + self._models[model_type].setFilter({filter_type: parameter}) self.filterChanged.emit() @pyqtSlot(str, "QVariantMap") - def setFilters(self, modelType: str, filterDict: dict): - if not self._models[modelType]: - Logger.log("w", "Toolbox: Couldn't filter %s model because it doesn't exist.", modelType) + def setFilters(self, model_type: str, filter_dict: dict) -> None: + if not self._models[model_type]: + Logger.log("w", "Toolbox: Couldn't filter %s model because it doesn't exist.", model_type) return - self._models[modelType].setFilter(filterDict) + self._models[model_type].setFilter(filter_dict) self.filterChanged.emit() @pyqtSlot(str) - def removeFilters(self, modelType: str): - if not self._models[modelType]: - Logger.log("w", "Toolbox: Couldn't remove filters on %s model because it doesn't exist.", modelType) + def removeFilters(self, model_type: str) -> None: + if not self._models[model_type]: + Logger.log("w", "Toolbox: Couldn't remove filters on %s model because it doesn't exist.", model_type) return - self._models[modelType].setFilter({}) + self._models[model_type].setFilter({}) self.filterChanged.emit() From 944ababa1cb44e7c33249e81692ce2a5c8d5994e Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 3 Aug 2018 14:48:04 +0200 Subject: [PATCH 115/243] Copy normal tile behavior to showcase tiles Contributes to CURA-5604 --- .../qml/ToolboxDownloadsShowcaseTile.qml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml index 2ca0b522fe..15d1ae302c 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml @@ -105,8 +105,21 @@ Rectangle switch(toolbox.viewCategory) { case "material": - toolbox.viewPage = "author" - toolbox.filterModelByProp("packages", "author_name", model.name) + + // If model has a type, it must be a package + if (model.type !== undefined) + { + toolbox.viewPage = "detail" + toolbox.filterModelByProp("packages", "id", model.id) + } + else + { + toolbox.viewPage = "author" + toolbox.setFilters("packages", { + "author_id": model.id, + "type": "material" + }) + } break default: toolbox.viewPage = "detail" From 4491d5164a91b6ba5d5b4fe9b6fa7ba3daedb81b Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 6 Aug 2018 09:24:48 +0200 Subject: [PATCH 116/243] Fix the gcode start/end formatter. Fixes #4181. --- plugins/CuraEngineBackend/StartSliceJob.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index eb392de121..76ff1cfc85 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -41,7 +41,7 @@ class StartJobResult(IntEnum): ## Formatter class that handles token expansion in start/end gcode class GcodeStartEndFormatter(Formatter): - def get_value(self, key: str, *args: str, default_extruder_nr: str = "-1", **kwargs) -> str: #type: ignore # [CodeStyle: get_value is an overridden function from the Formatter class] + def get_value(self, key: str, args: str, kwargs: Dict[int, Dict[str, Any]], default_extruder_nr: str = "-1") -> str: #type: ignore # [CodeStyle: get_value is an overridden function from the Formatter class] # The kwargs dictionary contains a dictionary for each stack (with a string of the extruder_nr as their key), # and a default_extruder_nr to use when no extruder_nr is specified From bfaaa4a47103da633ce57a34862eb8fd61282944 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 6 Aug 2018 09:32:12 +0200 Subject: [PATCH 117/243] Fix code-style --- plugins/CuraEngineBackend/StartSliceJob.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 76ff1cfc85..0ebcafdbb2 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -41,7 +41,7 @@ class StartJobResult(IntEnum): ## Formatter class that handles token expansion in start/end gcode class GcodeStartEndFormatter(Formatter): - def get_value(self, key: str, args: str, kwargs: Dict[int, Dict[str, Any]], default_extruder_nr: str = "-1") -> str: #type: ignore # [CodeStyle: get_value is an overridden function from the Formatter class] + def get_value(self, key: str, args: str, kwargs: dict, default_extruder_nr: str = "-1") -> str: #type: ignore # [CodeStyle: get_value is an overridden function from the Formatter class] # The kwargs dictionary contains a dictionary for each stack (with a string of the extruder_nr as their key), # and a default_extruder_nr to use when no extruder_nr is specified From 5eb9ae9177cf8f114efd6eb7b8773922a85dcbc1 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Mon, 6 Aug 2018 14:32:59 +0200 Subject: [PATCH 118/243] removed unnecessary variable --- cura/Machines/MaterialManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 3c9a7bfd59..7c5c901b32 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -186,7 +186,6 @@ class MaterialManager(QObject): for root_material_id in data_dict.values(): self._diameter_material_map[root_material_id] = default_root_material_id - variant_manager = self._application.getVariantManager() # Map #4 # "machine" -> "nozzle name" -> "buildplate name" -> "root material ID" -> specific material InstanceContainer From 95481b856061f18aac6f4a0c58b90366cb90dd40 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 6 Aug 2018 17:11:28 +0200 Subject: [PATCH 119/243] Fix print order for one-at-a-time mode --- cura/OneAtATimeIterator.py | 183 +++++++++++++++--------------- cura/Scene/ConvexHullDecorator.py | 2 +- cura/Settings/GlobalStack.py | 3 + 3 files changed, 93 insertions(+), 95 deletions(-) diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py index 84d65bae8e..cb063bfde5 100644 --- a/cura/OneAtATimeIterator.py +++ b/cura/OneAtATimeIterator.py @@ -1,112 +1,107 @@ -# Copyright (c) 2015 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +import sys + from UM.Scene.Iterator import Iterator from UM.Scene.SceneNode import SceneNode -from functools import cmp_to_key -from UM.Application import Application -## Iterator that returns a list of nodes in the order that they need to be printed -# If there is no solution an empty list is returned. -# Take note that the list of nodes can have children (that may or may not contain mesh data) + +# Iterator that determines the object print order when one-at a time mode is enabled. +# +# In one-at-a-time mode, only one extruder can be enabled to print. In order to maximize the number of objects we can +# print, we need to print from the corner that's closest to the extruder that's being used. Here is an illustration: +# +# +--------------------------------+ +# | | +# | | +# | | - Rectangle represents the complete print head including fans, etc. +# | X X | y - X's are the nozzles +# | (1) (2) | | +# | | | +# +--------------------------------+ +--> x +# +# In this case, the nozzles are symmetric, nozzle (1) is closer to the bottom left corner while (2) is closer to the +# bottom right. If we use nozzle (1) to print, then we better off printing from the bottom left corner so the print +# head will not collide into an object on its top-right side, which is a very large unused area. Following the same +# logic, if we are printing with nozzle (2), then it's better to print from the bottom-right side. +# +# This iterator determines the print order following the rules above. +# class OneAtATimeIterator(Iterator.Iterator): + def __init__(self, scene_node): - super().__init__(scene_node) # Call super to make multiple inheritence work. - self._hit_map = [[]] + from cura.CuraApplication import CuraApplication + self._global_stack = CuraApplication.getInstance().getGlobalContainerStack() self._original_node_list = [] - + super().__init__(scene_node) # Call super to make multiple inheritance work. + + def getMachineNearestCornerToExtruder(self, global_stack): + head_and_fans_coordinates = global_stack.getHeadAndFansCoordinates() + + used_extruder = None + for extruder in global_stack.extruders.values(): + if extruder.isEnabled: + used_extruder = extruder + break + + extruder_offsets = [used_extruder.getProperty("machine_nozzle_offset_x", "value"), + used_extruder.getProperty("machine_nozzle_offset_y", "value")] + + # find the corner that's closest to the origin + min_distance2 = sys.maxsize + min_coord = None + for coord in head_and_fans_coordinates: + x = coord[0] - extruder_offsets[0] + y = coord[1] - extruder_offsets[1] + + distance2 = x**2 + y**2 + if distance2 <= min_distance2: + min_distance2 = distance2 + min_coord = coord + + return min_coord + def _fillStack(self): + min_coord = self.getMachineNearestCornerToExtruder(self._global_stack) + transform_x = -int(round(min_coord[0] / abs(min_coord[0]))) + transform_y = -int(round(min_coord[1] / abs(min_coord[1]))) + + machine_size = [self._global_stack.getProperty("machine_width", "value"), + self._global_stack.getProperty("machine_depth", "value")] + + def flip_x(polygon): + tm2 = [-1, 0, 0, 1, 0, 0] + return affinity.affine_transform(affinity.translate(polygon, xoff = -machine_size[0]), tm2) + def flip_y(polygon): + tm2 = [1, 0, 0, -1, 0, 0] + return affinity.affine_transform(affinity.translate(polygon, yoff = -machine_size[1]), tm2) + + from shapely import affinity + from shapely.geometry import Polygon + node_list = [] for node in self._scene_node.getChildren(): if not issubclass(type(node), SceneNode): continue - if node.callDecoration("getConvexHull"): - node_list.append(node) + convex_hull = node.callDecoration("getConvexHull") + if convex_hull: + xmin = min(x for x, _ in convex_hull._points) + xmax = max(x for x, _ in convex_hull._points) + ymin = min(y for _, y in convex_hull._points) + ymax = max(y for _, y in convex_hull._points) + convex_hull_polygon = Polygon.from_bounds(xmin, ymin, xmax, ymax) + if transform_x < 0: + convex_hull_polygon = flip_x(convex_hull_polygon) + if transform_y < 0: + convex_hull_polygon = flip_y(convex_hull_polygon) - if len(node_list) < 2: - self._node_stack = node_list[:] - return + node_list.append({"node": node, + "min_coord": [convex_hull_polygon.bounds[0], convex_hull_polygon.bounds[1]], + }) - # Copy the list - self._original_node_list = node_list[:] - - ## Initialise the hit map (pre-compute all hits between all objects) - self._hit_map = [[self._checkHit(i,j) for i in node_list] for j in node_list] - - # Check if we have to files that block eachother. If this is the case, there is no solution! - for a in range(0,len(node_list)): - for b in range(0,len(node_list)): - if a != b and self._hit_map[a][b] and self._hit_map[b][a]: - return - - # Sort the original list so that items that block the most other objects are at the beginning. - # This does not decrease the worst case running time, but should improve it in most cases. - sorted(node_list, key = cmp_to_key(self._calculateScore)) - - todo_node_list = [_ObjectOrder([], node_list)] - while len(todo_node_list) > 0: - current = todo_node_list.pop() - for node in current.todo: - # Check if the object can be placed with what we have and still allows for a solution in the future - if not self._checkHitMultiple(node, current.order) and not self._checkBlockMultiple(node, current.todo): - # We found a possible result. Create new todo & order list. - new_todo_list = current.todo[:] - new_todo_list.remove(node) - new_order = current.order[:] + [node] - if len(new_todo_list) == 0: - # We have no more nodes to check, so quit looking. - todo_node_list = None - self._node_stack = new_order - - return - todo_node_list.append(_ObjectOrder(new_order, new_todo_list)) - self._node_stack = [] #No result found! - - - # Check if first object can be printed before the provided list (using the hit map) - def _checkHitMultiple(self, node, other_nodes): - node_index = self._original_node_list.index(node) - for other_node in other_nodes: - other_node_index = self._original_node_list.index(other_node) - if self._hit_map[node_index][other_node_index]: - return True - return False - - def _checkBlockMultiple(self, node, other_nodes): - node_index = self._original_node_list.index(node) - for other_node in other_nodes: - other_node_index = self._original_node_list.index(other_node) - if self._hit_map[other_node_index][node_index] and node_index != other_node_index: - return True - return False - - ## Calculate score simply sums the number of other objects it 'blocks' - def _calculateScore(self, a, b): - score_a = sum(self._hit_map[self._original_node_list.index(a)]) - score_b = sum(self._hit_map[self._original_node_list.index(b)]) - return score_a - score_b - - # Checks if A can be printed before B - def _checkHit(self, a, b): - if a == b: - return False - - overlap = a.callDecoration("getConvexHullBoundary").intersectsPolygon(b.callDecoration("getConvexHullHeadFull")) - if overlap: - return True - else: - return False - - -## Internal object used to keep track of a possible order in which to print objects. -class _ObjectOrder(): - def __init__(self, order, todo): - """ - :param order: List of indexes in which to print objects, ordered by printing order. - :param todo: List of indexes which are not yet inserted into the order list. - """ - self.order = order - self.todo = todo + node_list = sorted(node_list, key = lambda d: d["min_coord"]) + self._node_stack = [d["node"] for d in node_list] diff --git a/cura/Scene/ConvexHullDecorator.py b/cura/Scene/ConvexHullDecorator.py index 66bc8a7fc3..367144abfc 100644 --- a/cura/Scene/ConvexHullDecorator.py +++ b/cura/Scene/ConvexHullDecorator.py @@ -229,7 +229,7 @@ class ConvexHullDecorator(SceneNodeDecorator): return offset_hull def _getHeadAndFans(self): - return Polygon(numpy.array(self._global_stack.getProperty("machine_head_with_fans_polygon", "value"), numpy.float32)) + return Polygon(numpy.array(self._global_stack.getHeadAndFansCoordinates(), numpy.float32)) def _compute2DConvexHeadFull(self): return self._compute2DConvexHull().getMinkowskiHull(self._getHeadAndFans()) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 66f3290b85..ea955d24b0 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -172,6 +172,9 @@ class GlobalStack(CuraContainerStack): return False return True + def getHeadAndFansCoordinates(self): + return self.getProperty("machine_head_with_fans_polygon", "value") + ## private: global_stack_mime = MimeType( From aac6fe486066d7244d53c3337f64a03103e2ebc6 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 7 Aug 2018 09:35:50 +0200 Subject: [PATCH 120/243] Fix some code style --- cura/OneAtATimeIterator.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py index cb063bfde5..990ed37ab7 100644 --- a/cura/OneAtATimeIterator.py +++ b/cura/OneAtATimeIterator.py @@ -3,6 +3,9 @@ import sys +from shapely import affinity +from shapely.geometry import Polygon + from UM.Scene.Iterator import Iterator from UM.Scene.SceneNode import SceneNode @@ -73,13 +76,11 @@ class OneAtATimeIterator(Iterator.Iterator): def flip_x(polygon): tm2 = [-1, 0, 0, 1, 0, 0] return affinity.affine_transform(affinity.translate(polygon, xoff = -machine_size[0]), tm2) + def flip_y(polygon): tm2 = [1, 0, 0, -1, 0, 0] return affinity.affine_transform(affinity.translate(polygon, yoff = -machine_size[1]), tm2) - from shapely import affinity - from shapely.geometry import Polygon - node_list = [] for node in self._scene_node.getChildren(): if not issubclass(type(node), SceneNode): From 59bb7744368626df2b5333f7b139d8c56c47b0d9 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Aug 2018 10:51:56 +0200 Subject: [PATCH 121/243] Remove unused variables --- plugins/USBPrinting/AutoDetectBaudJob.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/USBPrinting/AutoDetectBaudJob.py b/plugins/USBPrinting/AutoDetectBaudJob.py index 30ab65bc55..f8af61c567 100644 --- a/plugins/USBPrinting/AutoDetectBaudJob.py +++ b/plugins/USBPrinting/AutoDetectBaudJob.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. from UM.Job import Job @@ -21,7 +21,6 @@ class AutoDetectBaudJob(Job): def run(self): Logger.log("d", "Auto detect baud rate started.") - timeout = 3 wait_response_timeouts = [3, 15, 30] wait_bootloader_times = [1.5, 5, 15] write_timeout = 3 @@ -52,7 +51,7 @@ class AutoDetectBaudJob(Job): if serial is None: try: serial = Serial(str(self._serial_port), baud_rate, timeout = read_timeout, writeTimeout = write_timeout) - except SerialException as e: + except SerialException: Logger.logException("w", "Unable to create serial") continue else: From 58e5a8123625eaf14279efb3e4c9ac9032cea44d Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Aug 2018 13:10:03 +0200 Subject: [PATCH 122/243] Fix units for initial layer print/travel acceleration These two were wrong. Contributes to issue CURA-5495. --- 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 daf09d2701..2ea87a890d 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3025,7 +3025,7 @@ { "label": "Initial Layer Print Acceleration", "description": "The acceleration during the printing of the initial layer.", - "unit": "mm/s", + "unit": "mm/s²", "type": "float", "default_value": 3000, "value": "acceleration_layer_0", @@ -3039,7 +3039,7 @@ { "label": "Initial Layer Travel Acceleration", "description": "The acceleration for travel moves in the initial layer.", - "unit": "mm/s", + "unit": "mm/s²", "type": "float", "default_value": 3000, "value": "acceleration_layer_0 * acceleration_travel / acceleration_print", From 910ffe0ad53dd71e83d46b74cfad932061a92cd5 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 7 Aug 2018 16:15:03 +0200 Subject: [PATCH 123/243] Fix quality reset upon material deletion CURA-5621 --- cura/Settings/MachineManager.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index ff585deb54..f945cbb30c 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1455,9 +1455,13 @@ class MachineManager(QObject): if quality_group.node_for_global is None: Logger.log("e", "Could not set quality group [%s] because it has no node_for_global", str(quality_group)) return + # This is not changing the quality for the active machine !!!!!!!! global_stack.quality = quality_group.node_for_global.getContainer() for extruder_nr, extruder_stack in global_stack.extruders.items(): - extruder_stack.quality = quality_group.nodes_for_extruders[extruder_nr].getContainer() + quality_container = self._empty_quality_container + if extruder_nr in quality_group.nodes_for_extruders: + quality_container = quality_group.nodes_for_extruders[extruder_nr].getContainer() + extruder_stack.quality = quality_container return self.blurSettings.emit() From 55cf1fa137bac81d3f83564e9e656456ac4dfa32 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Aug 2018 16:51:31 +0200 Subject: [PATCH 124/243] Turn on CuraEngine debug mode when front-end is in debug mode You can test this by running Cura's front-end with parameter --debug. --- plugins/CuraEngineBackend/CuraEngineBackend.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 56763a6632..9a5c95b04d 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -1,6 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +import argparse #To run the engine in debug mode if the front-end is in debug mode. from collections import defaultdict import os from PyQt5.QtCore import QObject, QTimer, pyqtSlot @@ -179,7 +180,15 @@ class CuraEngineBackend(QObject, Backend): # \return list of commands and args / parameters. def getEngineCommand(self) -> List[str]: json_path = Resources.getPath(Resources.DefinitionContainers, "fdmprinter.def.json") - return [self._application.getPreferences().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), "-j", json_path, ""] + command = [self._application.getPreferences().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), "-j", json_path, ""] + + parser = argparse.ArgumentParser(prog = "cura", add_help = False) + parser.add_argument("--debug", action = "store_true", default = False, help = "Turn on the debug mode by setting this option.") + known_args = vars(parser.parse_known_args()[0]) + if known_args["debug"]: + command.append("-vvv") + + return command ## Emitted when we get a message containing print duration and material amount. # This also implies the slicing has finished. From 387fb3ce1f7af5f6e8b37c966291e4710cb2d143 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 8 Aug 2018 11:31:21 +0200 Subject: [PATCH 125/243] Fix missing attribute CURA-5622 self._plugins_loaded should be there in the beginning or Cura will crash when it gets used. --- cura/CuraApplication.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 9f4ea7b3d3..6164fc8756 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -226,6 +226,8 @@ class CuraApplication(QtApplication): self._need_to_show_user_agreement = True + self._plugins_loaded = False + # Backups self._auto_save = None self._save_data_enabled = True From 9239e82b1f16e112aaa9da042515f995c6532e93 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 8 Aug 2018 12:56:46 +0200 Subject: [PATCH 126/243] Make mypy happy CURA-5578 --- cura/Settings/MachineManager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index f945cbb30c..a14977df03 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1460,7 +1460,8 @@ class MachineManager(QObject): for extruder_nr, extruder_stack in global_stack.extruders.items(): quality_container = self._empty_quality_container if extruder_nr in quality_group.nodes_for_extruders: - quality_container = quality_group.nodes_for_extruders[extruder_nr].getContainer() + container = quality_group.nodes_for_extruders[extruder_nr].getContainer() + quality_container = container if container is not None else quality_container extruder_stack.quality = quality_container return From d7e8cc9224dfe16028ce46cad2b5e676dbf4173b Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 8 Aug 2018 17:03:57 +0200 Subject: [PATCH 127/243] Fix rendering support eraser cubes MeshBuilder.addCube creates cubes that don't have per-vertex normals. Geometry like that does not render properly in most shaders used in Cura. This becomes obvious when a user changes the "Mesh Type" using Per Model Settings. --- plugins/SupportEraser/SupportEraser.py | 30 ++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/plugins/SupportEraser/SupportEraser.py b/plugins/SupportEraser/SupportEraser.py index 44d4831c04..9f7e3269bc 100644 --- a/plugins/SupportEraser/SupportEraser.py +++ b/plugins/SupportEraser/SupportEraser.py @@ -25,6 +25,8 @@ from cura.Scene.BuildPlateDecorator import BuildPlateDecorator from UM.Settings.SettingInstance import SettingInstance +import numpy + class SupportEraser(Tool): def __init__(self): super().__init__() @@ -96,8 +98,7 @@ class SupportEraser(Tool): node.setName("Eraser") node.setSelectable(True) - mesh = MeshBuilder() - mesh.addCube(10,10,10) + mesh = self._createCube(10) node.setMeshData(mesh.build()) active_build_plate = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate @@ -160,3 +161,28 @@ class SupportEraser(Tool): self._skip_press = False self._had_selection = has_selection + + def _createCube(self, size): + mesh = MeshBuilder() + + # Can't use MeshBuilder.addCube() because that does not get per-vertex normals + # Per-vertex normals require duplication of vertices + s = size / 2 + verts = [ # 6 faces with 4 corners each + [-s, -s, s], [-s, s, s], [ s, s, s], [ s, -s, s], + [-s, s, -s], [-s, -s, -s], [ s, -s, -s], [ s, s, -s], + [ s, -s, -s], [-s, -s, -s], [-s, -s, s], [ s, -s, s], + [-s, s, -s], [ s, s, -s], [ s, s, s], [-s, s, s], + [-s, -s, s], [-s, -s, -s], [-s, s, -s], [-s, s, s], + [ s, -s, -s], [ s, -s, s], [ s, s, s], [ s, s, -s] + ] + mesh.setVertices(numpy.asarray(verts, dtype=numpy.float32)) + + indices = [] + for i in range(0, 24, 4): # All 6 quads (12 triangles) + indices.append([i, i+2, i+1]) + indices.append([i, i+3, i+2]) + mesh.setIndices(numpy.asarray(indices, dtype=numpy.int32)) + + mesh.calculateNormals() + return mesh From ea770a26a37e8673b24067e814344f01b29bf488 Mon Sep 17 00:00:00 2001 From: ValentinPitre <35694201+ValentinPitre@users.noreply.github.com> Date: Wed, 8 Aug 2018 23:23:32 +0200 Subject: [PATCH 128/243] Add mesh offset --- resources/definitions/tizyx_k25.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/tizyx_k25.def.json b/resources/definitions/tizyx_k25.def.json index 55256a29d6..94a20b371e 100644 --- a/resources/definitions/tizyx_k25.def.json +++ b/resources/definitions/tizyx_k25.def.json @@ -9,6 +9,7 @@ "manufacturer": "TiZYX", "file_formats": "text/x-gcode", "platform": "tizyx_k25_platform.stl", + "platform_offset": [0, -4, 0], "exclude_materials": ["chromatik_pla", "dsm_arnitel2045_175", "dsm_novamid1070_175", "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu", "fiberlogy_hd_pla", "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red", "generic_abs", "generic_abs_175", "generic_bam", "generic_cpe", "generic_cpe_175", "generic_cpe_plus", "generic_hips", "generic_hips_175", "generic_nylon", "generic_nylon_175", "generic_pc", "generic_pc_175", "generic_petg", "generic_petg_175", "generic_pla", "generic_pla_175", "generic_pp", "generic_pva", "generic_pva_175", "generic_tough_pla", "generic_tpu", "imade3d_petg_green", "imade3d_petg_pink", "imade3d_pla_green", "imade3d_pla_pink", "innofill_innoflex60_175", "octofiber_pla", "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla", "ultimaker_abs_black", "ultimaker_abs_blue", "ultimaker_abs_green", "ultimaker_abs_grey", "ultimaker_abs_orange", "ultimaker_abs_pearl-gold", "ultimaker_abs_red", "ultimaker_abs_silver-metallic", "ultimaker_abs_white", "ultimaker_abs_yellow", "ultimaker_bam", "ultimaker_cpe_black", "ultimaker_cpe_blue", "ultimaker_cpe_dark-grey", "ultimaker_cpe_green", "ultimaker_cpe_light-grey", "ultimaker_cpe_plus_black", "ultimaker_cpe_plus_transparent", "ultimaker_cpe_plus_white", "ultimaker_cpe_red", "ultimaker_cpe_transparent", "ultimaker_cpe_white", "ultimaker_cpe_yellow", "ultimaker_nylon_black", "ultimaker_nylon_transparent", "ultimaker_pc_black", "ultimaker_pc_transparent", "ultimaker_pc_white", "ultimaker_pla_black", "ultimaker_pla_blue", "ultimaker_pla_green", "ultimaker_pla_magenta", "ultimaker_pla_orange", "ultimaker_pla_pearl-white", "ultimaker_pla_red", "ultimaker_pla_silver-metallic", "ultimaker_pla_transparent", "ultimaker_pla_white", "ultimaker_pla_yellow", "ultimaker_pp_transparent", "ultimaker_pva", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "ultimaker_tpu_black", "ultimaker_tpu_blue", "ultimaker_tpu_red", "ultimaker_tpu_white", "verbatim_bvoh_175", "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_TPU", "zyyx_pro_flex", "zyyx_pro_pla" ], "preferred_material": "tizyx_pla", "has_machine_quality": true, From 41a892796d29d6240ce135c7f5a838e14dd398c2 Mon Sep 17 00:00:00 2001 From: Andreea Scorojitu Date: Thu, 9 Aug 2018 09:14:25 +0200 Subject: [PATCH 129/243] CURA-5626 Remove UM3 from connection message "This printer is not set up to host a group of Ultimaker 3 printers.", Ultimker 3 was removed from the message. --- plugins/UM3NetworkPrinting/DiscoverUM3Action.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml index e4d75e8f6d..127b3c35bd 100644 --- a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml +++ b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml @@ -299,11 +299,11 @@ Cura.MachineAction } else if (base.selectedDevice.clusterSize === 0) { - return catalog.i18nc("@label", "This printer is not set up to host a group of Ultimaker 3 printers."); + return catalog.i18nc("@label", "This printer is not set up to host a group of printers."); } else { - return catalog.i18nc("@label", "This printer is the host for a group of %1 Ultimaker 3 printers.".arg(base.selectedDevice.clusterSize)); + return catalog.i18nc("@label", "This printer is the host for a group of %1 printers.".arg(base.selectedDevice.clusterSize)); } } From 5c860d95928204dbeccc35fed7edfcaf456abbc9 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 9 Aug 2018 11:11:41 +0200 Subject: [PATCH 130/243] Fixed typo --- cura/PrinterOutput/PrinterOutputModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/PrinterOutput/PrinterOutputModel.py b/cura/PrinterOutput/PrinterOutputModel.py index 6fafa368bb..f10d6bd75b 100644 --- a/cura/PrinterOutput/PrinterOutputModel.py +++ b/cura/PrinterOutput/PrinterOutputModel.py @@ -120,7 +120,7 @@ class PrinterOutputModel(QObject): @pyqtProperty(QVariant, notify = headPositionChanged) def headPosition(self): - return {"x": self._head_position.x, "y": self._head_position.y, "z": self.head_position_z} + return {"x": self._head_position.x, "y": self._head_position.y, "z": self.head_position.z} def updateHeadPosition(self, x, y, z): if self._head_position.x != x or self._head_position.y != y or self._head_position.z != z: From 1180fad62f41a3af08f412dc6dc220d60d6a8f36 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 9 Aug 2018 11:33:04 +0200 Subject: [PATCH 131/243] Fix binding loop --- resources/qml/PrintMonitor.qml | 1 - resources/qml/PrinterOutput/OutputDeviceHeader.qml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index b24bcb6d6c..7727f9cb52 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -26,7 +26,6 @@ Column OutputDeviceHeader { - width: parent.width outputDevice: connectedDevice } diff --git a/resources/qml/PrinterOutput/OutputDeviceHeader.qml b/resources/qml/PrinterOutput/OutputDeviceHeader.qml index d5ce32786c..03e6d78699 100644 --- a/resources/qml/PrinterOutput/OutputDeviceHeader.qml +++ b/resources/qml/PrinterOutput/OutputDeviceHeader.qml @@ -16,7 +16,7 @@ Item Rectangle { - anchors.fill: parent + height: childrenRect.height color: UM.Theme.getColor("setting_category") property var activePrinter: outputDevice != null ? outputDevice.activePrinter : null From aab0cded0ead3720adc034c57f99d94ee8066702 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 9 Aug 2018 12:02:28 +0200 Subject: [PATCH 132/243] Adjust maximum zoom to printer size Previously the maximum distance you could zoom out was 2000. Now it's variable depending on how large your printer is. I've put it to 5 so that it works out to be approximately the same maximum zoom level for normal sized printers (like 25 cube build volume approximately). This should make it possible to zoom out completely for large sized printers. --- cura/BuildVolume.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 87f0eb543e..667247eac9 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -3,6 +3,7 @@ from cura.Scene.CuraSceneNode import CuraSceneNode from cura.Settings.ExtruderManager import ExtruderManager +from UM.Application import Application #To modify the maximum zoom level. from UM.i18n import i18nCatalog from UM.Scene.Platform import Platform from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator @@ -552,6 +553,11 @@ class BuildVolume(SceneNode): if self._engine_ready: self.rebuild() + diagonal_size = math.sqrt(self._width * self._width + self._height * self._height + self._depth * self._depth) + camera = Application.getInstance().getController().getCameraTool() + if camera: + camera.setZoomRange(min = 1, max = diagonal_size * 5) #You can zoom out up to 5 times the diagonal across your screen (to see models bigger than your volume). + def _onEngineCreated(self): self._engine_ready = True self.rebuild() From d31df8ec679281280421a97458e089047e74c8a4 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 9 Aug 2018 12:47:49 +0200 Subject: [PATCH 133/243] Fixed that long printernames overlap other GUI elements --- plugins/UM3NetworkPrinting/ClusterControlItem.qml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/UM3NetworkPrinting/ClusterControlItem.qml b/plugins/UM3NetworkPrinting/ClusterControlItem.qml index b42515de51..5cf550955c 100644 --- a/plugins/UM3NetworkPrinting/ClusterControlItem.qml +++ b/plugins/UM3NetworkPrinting/ClusterControlItem.qml @@ -30,7 +30,12 @@ Component anchors.horizontalCenter: parent.horizontalCenter anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.top: parent.top + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.right:parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width text: Cura.MachineManager.printerOutputDevices[0].name + elide: Text.ElideRight } Rectangle From 4912073aedc795c2aa51cc1e858190be0cd328a1 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 9 Aug 2018 15:14:55 +0200 Subject: [PATCH 134/243] Add API abstraction layer Contributes to CURA-5595 --- cura/API/SidebarContextMenu.py | 34 ++++++++++++++++++++++++++++++++++ cura/API/__init__.py | 4 ++++ 2 files changed, 38 insertions(+) create mode 100644 cura/API/SidebarContextMenu.py diff --git a/cura/API/SidebarContextMenu.py b/cura/API/SidebarContextMenu.py new file mode 100644 index 0000000000..9c7ad4c4b6 --- /dev/null +++ b/cura/API/SidebarContextMenu.py @@ -0,0 +1,34 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from cura.CuraApplication import CuraApplication + +## The back-ups API provides a version-proof bridge between Cura's +# Sidebar Context Menu and plug-ins that hook into it. +# +# Usage: +# ``from cura.API import CuraAPI +# api = CuraAPI() +# api.sidebar_context_menu.getSidebarMenuItems() +# menu_actions = [] +# menu_actions.append("sidebarMenuItemOnClickHander") +# data = { +# "name": "My Plugin Action", +# "iconName": "my-plugin-icon", +# "actions": menu_actions, +# "menu_item": MyPluginAction(self) +# } +# api.sidebar_context_menu.addSidebarMenuItems([])`` +class SidebarContextMenu: + + _application = CuraApplication.getInstance() # type: CuraApplication + + ## Add items to the sidebar context menu. + # \param menu_item dict containing the menu item to add. + def addSidebarMenuItem(self, menu_items: dict) -> None: + self._application.addSidebarCustomMenuItem(menu_items) + + ## Get all custom items currently added to the sidebar context menu. + # \return List containing all custom context menu items. + def getSidebarMenuItems(self) -> list: + return self._application.getSidebarCustomMenuItems() \ No newline at end of file diff --git a/cura/API/__init__.py b/cura/API/__init__.py index 13f6722336..40c07b8371 100644 --- a/cura/API/__init__.py +++ b/cura/API/__init__.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from UM.PluginRegistry import PluginRegistry from cura.API.Backups import Backups +from cura.API.SidebarContextMenu import SidebarContextMenu ## The official Cura API that plug-ins can use to interact with Cura. # @@ -16,3 +17,6 @@ class CuraAPI: # Backups API. backups = Backups() + + # Sidebar Context Menu API + sidebar_context_menu = SidebarContextMenu() From 3217085ebedbdfb0cd763db9c37bca4df2816b07 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 9 Aug 2018 15:20:53 +0200 Subject: [PATCH 135/243] Fix plural Contributes to CURA-5595 --- cura/API/SidebarContextMenu.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/API/SidebarContextMenu.py b/cura/API/SidebarContextMenu.py index 9c7ad4c4b6..fdd2d3ed88 100644 --- a/cura/API/SidebarContextMenu.py +++ b/cura/API/SidebarContextMenu.py @@ -25,8 +25,8 @@ class SidebarContextMenu: ## Add items to the sidebar context menu. # \param menu_item dict containing the menu item to add. - def addSidebarMenuItem(self, menu_items: dict) -> None: - self._application.addSidebarCustomMenuItem(menu_items) + def addSidebarMenuItem(self, menu_item: dict) -> None: + self._application.addSidebarCustomMenuItem(menu_item) ## Get all custom items currently added to the sidebar context menu. # \return List containing all custom context menu items. From 88c4240e3b06a64d6c021cb5f9756a66d3e71e2b Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 9 Aug 2018 15:21:38 +0200 Subject: [PATCH 136/243] Remove back-ups traces Contributes to CURA-5595 --- cura/API/SidebarContextMenu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/API/SidebarContextMenu.py b/cura/API/SidebarContextMenu.py index fdd2d3ed88..f47b3a062a 100644 --- a/cura/API/SidebarContextMenu.py +++ b/cura/API/SidebarContextMenu.py @@ -3,7 +3,7 @@ from cura.CuraApplication import CuraApplication -## The back-ups API provides a version-proof bridge between Cura's +## The sidebar context menu API provides a version-proof bridge between Cura's # Sidebar Context Menu and plug-ins that hook into it. # # Usage: From 57f04d8940876b6a4b46a4569dc501272c2c90b3 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Thu, 9 Aug 2018 15:39:10 +0200 Subject: [PATCH 137/243] Load 3mf projects CURA-5570 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 389a7da704..e33b88375e 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -928,12 +928,16 @@ class ThreeMFWorkspaceReader(WorkspaceReader): root_material_id = extruder_info.root_material_id root_material_id = self._old_new_materials.get(root_material_id, root_material_id) + build_plate_id = global_stack.variant.getId() + # get material diameter of this extruder machine_material_diameter = extruder_stack.materialDiameter material_node = material_manager.getMaterialNode(global_stack.definition.getId(), extruder_stack.variant.getName(), + build_plate_id, machine_material_diameter, root_material_id) + if material_node is not None and material_node.getContainer() is not None: extruder_stack.material = material_node.getContainer() From 033a00ec20bc952b981af97384700240617db7e7 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Thu, 9 Aug 2018 16:06:09 +0200 Subject: [PATCH 138/243] fixed addNodesToCheck function, wrong max index value CURA-5570 --- cura/Machines/QualityManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index c0954c005c..5496ca9f87 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -271,7 +271,7 @@ class QualityManager(QObject): # the search list in the order described above. So, by iterating over that search node list, we first look # in the more specific branches and then the less specific (generic) ones. def addNodesToCheck(node, nodes_to_check_list, node_info_list, node_info_idx): - if current_node_info_idx < len(node_info_list): + if node_info_idx < len(node_info_list): node_name = node_info_list[node_info_idx] if node_name is not None: current_node = node.getChildNode(node_name) From e4bdd8096a3e99ca304938c8ad26a819add31cd2 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Aug 2018 11:02:16 +0200 Subject: [PATCH 139/243] Remap shortcut This is a bit more logical than 'G', I'd say. E is now available since other shortcuts were remapped as well. Contributes to issue CURA-5634 and fixes #3969. --- plugins/SupportEraser/SupportEraser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/SupportEraser/SupportEraser.py b/plugins/SupportEraser/SupportEraser.py index 44d4831c04..97850c3f3d 100644 --- a/plugins/SupportEraser/SupportEraser.py +++ b/plugins/SupportEraser/SupportEraser.py @@ -28,7 +28,7 @@ from UM.Settings.SettingInstance import SettingInstance class SupportEraser(Tool): def __init__(self): super().__init__() - self._shortcut_key = Qt.Key_G + self._shortcut_key = Qt.Key_E self._controller = self.getController() self._selection_pass = None From 4a22bb3b695e531a9ddf6f89f3a3d53109d13580 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Aug 2018 11:06:25 +0200 Subject: [PATCH 140/243] Code style --- resources/qml/Toolbar.qml | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/resources/qml/Toolbar.qml b/resources/qml/Toolbar.qml index 613a462db9..6483804c38 100644 --- a/resources/qml/Toolbar.qml +++ b/resources/qml/Toolbar.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2015 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 @@ -21,8 +21,8 @@ Item { id: buttons; - anchors.bottom: parent.bottom; - anchors.left: parent.left; + anchors.bottom: parent.bottom + anchors.left: parent.left spacing: UM.Theme.getSize("button_lining").width Repeater @@ -41,13 +41,15 @@ Item enabled: model.enabled && UM.Selection.hasSelection && UM.Controller.toolsEnabled style: UM.Theme.styles.tool_button - onCheckedChanged: { - if (checked) { - base.activeY = y + onCheckedChanged: + { + if (checked) + { + base.activeY = y; } } - //Workaround since using ToolButton"s onClicked would break the binding of the checked property, instead + //Workaround since using ToolButton's onClicked would break the binding of the checked property, instead //just catch the click so we do not trigger that behaviour. MouseArea { @@ -57,7 +59,7 @@ Item forceActiveFocus() //First grab focus, so all the text fields are updated if(parent.checked) { - UM.Controller.setActiveTool(null) + UM.Controller.setActiveTool(null); } else { @@ -96,11 +98,13 @@ Item width: { - if (panel.item && panel.width > 0){ - return Math.max(panel.width + 2 * UM.Theme.getSize("default_margin").width) + if (panel.item && panel.width > 0) + { + return Math.max(panel.width + 2 * UM.Theme.getSize("default_margin").width); } - else { - return 0 + else + { + return 0; } } height: panel.item ? panel.height + 2 * UM.Theme.getSize("default_margin").height : 0; @@ -124,7 +128,7 @@ Item x: UM.Theme.getSize("default_margin").width; y: UM.Theme.getSize("default_margin").height; - source: UM.ActiveTool.valid ? UM.ActiveTool.activeToolPanel : ""; + source: UM.ActiveTool.valid ? UM.ActiveTool.activeToolPanel : "" enabled: UM.Controller.toolsEnabled; } } @@ -148,6 +152,6 @@ Item anchors.horizontalCenter: parent.horizontalCenter } - visible: toolHint.text != ""; + visible: toolHint.text != "" } } From f247c328c695ba27d9273c53b06cf7f8a73cdc61 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Aug 2018 11:22:33 +0200 Subject: [PATCH 141/243] Show shortcut key in tool tooltips In brackets. I couldn't translate it to an icon easily. It was possible but I'd have to create a giant mapping from every key to the key icons and add a bunch of icons and I don't think that's necessary. Contributes to issue CURA-5634. --- resources/qml/Toolbar.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Toolbar.qml b/resources/qml/Toolbar.qml index 6483804c38..a04b3650df 100644 --- a/resources/qml/Toolbar.qml +++ b/resources/qml/Toolbar.qml @@ -34,7 +34,7 @@ Item height: childrenRect.height Button { - text: model.name + text: model.name + (model.shortcut ? (" (" + model.shortcut + ")") : "") iconSource: (UM.Theme.getIcon(model.icon) != "") ? UM.Theme.getIcon(model.icon) : "file:///" + model.location + "/" + model.icon checkable: true checked: model.active From 89ed2bcff80a7a414f77c455baa0023c631eae7c Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 10 Aug 2018 11:45:25 +0200 Subject: [PATCH 142/243] Revert "Merge pull request #4203 from Ultimaker/CURA-5538-fix-one-at-a-time-order-2" This reverts commit 82e1a7c5fc43a12d1498779d392286c6e49ee4ea, reversing changes made to 1915659393b72f7e4d4dbd9b73e92b8a665efcdc. --- cura/OneAtATimeIterator.py | 184 +++++++++++++++--------------- cura/Scene/ConvexHullDecorator.py | 2 +- cura/Settings/GlobalStack.py | 3 - 3 files changed, 95 insertions(+), 94 deletions(-) diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py index 990ed37ab7..84d65bae8e 100644 --- a/cura/OneAtATimeIterator.py +++ b/cura/OneAtATimeIterator.py @@ -1,108 +1,112 @@ -# Copyright (c) 2018 Ultimaker B.V. +# Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -import sys - -from shapely import affinity -from shapely.geometry import Polygon - from UM.Scene.Iterator import Iterator from UM.Scene.SceneNode import SceneNode +from functools import cmp_to_key +from UM.Application import Application - -# Iterator that determines the object print order when one-at a time mode is enabled. -# -# In one-at-a-time mode, only one extruder can be enabled to print. In order to maximize the number of objects we can -# print, we need to print from the corner that's closest to the extruder that's being used. Here is an illustration: -# -# +--------------------------------+ -# | | -# | | -# | | - Rectangle represents the complete print head including fans, etc. -# | X X | y - X's are the nozzles -# | (1) (2) | | -# | | | -# +--------------------------------+ +--> x -# -# In this case, the nozzles are symmetric, nozzle (1) is closer to the bottom left corner while (2) is closer to the -# bottom right. If we use nozzle (1) to print, then we better off printing from the bottom left corner so the print -# head will not collide into an object on its top-right side, which is a very large unused area. Following the same -# logic, if we are printing with nozzle (2), then it's better to print from the bottom-right side. -# -# This iterator determines the print order following the rules above. -# +## Iterator that returns a list of nodes in the order that they need to be printed +# If there is no solution an empty list is returned. +# Take note that the list of nodes can have children (that may or may not contain mesh data) class OneAtATimeIterator(Iterator.Iterator): - def __init__(self, scene_node): - from cura.CuraApplication import CuraApplication - self._global_stack = CuraApplication.getInstance().getGlobalContainerStack() + super().__init__(scene_node) # Call super to make multiple inheritence work. + self._hit_map = [[]] self._original_node_list = [] - super().__init__(scene_node) # Call super to make multiple inheritance work. - - def getMachineNearestCornerToExtruder(self, global_stack): - head_and_fans_coordinates = global_stack.getHeadAndFansCoordinates() - - used_extruder = None - for extruder in global_stack.extruders.values(): - if extruder.isEnabled: - used_extruder = extruder - break - - extruder_offsets = [used_extruder.getProperty("machine_nozzle_offset_x", "value"), - used_extruder.getProperty("machine_nozzle_offset_y", "value")] - - # find the corner that's closest to the origin - min_distance2 = sys.maxsize - min_coord = None - for coord in head_and_fans_coordinates: - x = coord[0] - extruder_offsets[0] - y = coord[1] - extruder_offsets[1] - - distance2 = x**2 + y**2 - if distance2 <= min_distance2: - min_distance2 = distance2 - min_coord = coord - - return min_coord - + def _fillStack(self): - min_coord = self.getMachineNearestCornerToExtruder(self._global_stack) - transform_x = -int(round(min_coord[0] / abs(min_coord[0]))) - transform_y = -int(round(min_coord[1] / abs(min_coord[1]))) - - machine_size = [self._global_stack.getProperty("machine_width", "value"), - self._global_stack.getProperty("machine_depth", "value")] - - def flip_x(polygon): - tm2 = [-1, 0, 0, 1, 0, 0] - return affinity.affine_transform(affinity.translate(polygon, xoff = -machine_size[0]), tm2) - - def flip_y(polygon): - tm2 = [1, 0, 0, -1, 0, 0] - return affinity.affine_transform(affinity.translate(polygon, yoff = -machine_size[1]), tm2) - node_list = [] for node in self._scene_node.getChildren(): if not issubclass(type(node), SceneNode): continue - convex_hull = node.callDecoration("getConvexHull") - if convex_hull: - xmin = min(x for x, _ in convex_hull._points) - xmax = max(x for x, _ in convex_hull._points) - ymin = min(y for _, y in convex_hull._points) - ymax = max(y for _, y in convex_hull._points) + if node.callDecoration("getConvexHull"): + node_list.append(node) - convex_hull_polygon = Polygon.from_bounds(xmin, ymin, xmax, ymax) - if transform_x < 0: - convex_hull_polygon = flip_x(convex_hull_polygon) - if transform_y < 0: - convex_hull_polygon = flip_y(convex_hull_polygon) - node_list.append({"node": node, - "min_coord": [convex_hull_polygon.bounds[0], convex_hull_polygon.bounds[1]], - }) + if len(node_list) < 2: + self._node_stack = node_list[:] + return - node_list = sorted(node_list, key = lambda d: d["min_coord"]) + # Copy the list + self._original_node_list = node_list[:] + + ## Initialise the hit map (pre-compute all hits between all objects) + self._hit_map = [[self._checkHit(i,j) for i in node_list] for j in node_list] + + # Check if we have to files that block eachother. If this is the case, there is no solution! + for a in range(0,len(node_list)): + for b in range(0,len(node_list)): + if a != b and self._hit_map[a][b] and self._hit_map[b][a]: + return + + # Sort the original list so that items that block the most other objects are at the beginning. + # This does not decrease the worst case running time, but should improve it in most cases. + sorted(node_list, key = cmp_to_key(self._calculateScore)) + + todo_node_list = [_ObjectOrder([], node_list)] + while len(todo_node_list) > 0: + current = todo_node_list.pop() + for node in current.todo: + # Check if the object can be placed with what we have and still allows for a solution in the future + if not self._checkHitMultiple(node, current.order) and not self._checkBlockMultiple(node, current.todo): + # We found a possible result. Create new todo & order list. + new_todo_list = current.todo[:] + new_todo_list.remove(node) + new_order = current.order[:] + [node] + if len(new_todo_list) == 0: + # We have no more nodes to check, so quit looking. + todo_node_list = None + self._node_stack = new_order + + return + todo_node_list.append(_ObjectOrder(new_order, new_todo_list)) + self._node_stack = [] #No result found! + + + # Check if first object can be printed before the provided list (using the hit map) + def _checkHitMultiple(self, node, other_nodes): + node_index = self._original_node_list.index(node) + for other_node in other_nodes: + other_node_index = self._original_node_list.index(other_node) + if self._hit_map[node_index][other_node_index]: + return True + return False + + def _checkBlockMultiple(self, node, other_nodes): + node_index = self._original_node_list.index(node) + for other_node in other_nodes: + other_node_index = self._original_node_list.index(other_node) + if self._hit_map[other_node_index][node_index] and node_index != other_node_index: + return True + return False + + ## Calculate score simply sums the number of other objects it 'blocks' + def _calculateScore(self, a, b): + score_a = sum(self._hit_map[self._original_node_list.index(a)]) + score_b = sum(self._hit_map[self._original_node_list.index(b)]) + return score_a - score_b + + # Checks if A can be printed before B + def _checkHit(self, a, b): + if a == b: + return False + + overlap = a.callDecoration("getConvexHullBoundary").intersectsPolygon(b.callDecoration("getConvexHullHeadFull")) + if overlap: + return True + else: + return False + + +## Internal object used to keep track of a possible order in which to print objects. +class _ObjectOrder(): + def __init__(self, order, todo): + """ + :param order: List of indexes in which to print objects, ordered by printing order. + :param todo: List of indexes which are not yet inserted into the order list. + """ + self.order = order + self.todo = todo - self._node_stack = [d["node"] for d in node_list] diff --git a/cura/Scene/ConvexHullDecorator.py b/cura/Scene/ConvexHullDecorator.py index 367144abfc..66bc8a7fc3 100644 --- a/cura/Scene/ConvexHullDecorator.py +++ b/cura/Scene/ConvexHullDecorator.py @@ -229,7 +229,7 @@ class ConvexHullDecorator(SceneNodeDecorator): return offset_hull def _getHeadAndFans(self): - return Polygon(numpy.array(self._global_stack.getHeadAndFansCoordinates(), numpy.float32)) + return Polygon(numpy.array(self._global_stack.getProperty("machine_head_with_fans_polygon", "value"), numpy.float32)) def _compute2DConvexHeadFull(self): return self._compute2DConvexHull().getMinkowskiHull(self._getHeadAndFans()) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index ea955d24b0..66f3290b85 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -172,9 +172,6 @@ class GlobalStack(CuraContainerStack): return False return True - def getHeadAndFansCoordinates(self): - return self.getProperty("machine_head_with_fans_polygon", "value") - ## private: global_stack_mime = MimeType( From 6924d28ee7eb92c47e5d1df63874a7da5b2b0be4 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Aug 2018 11:52:35 +0200 Subject: [PATCH 143/243] Disambiguate translation of 'Settings' from 'Preferences' The 'settings' entry contains the set-up of the printer so Konfiguration is a better word there. Discovered during investigation of #3971. --- resources/i18n/de_DE/cura.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/i18n/de_DE/cura.po b/resources/i18n/de_DE/cura.po index 37b8840468..31ce980615 100644 --- a/resources/i18n/de_DE/cura.po +++ b/resources/i18n/de_DE/cura.po @@ -4036,7 +4036,7 @@ msgstr "&Ansicht" #: /home/ruben/Projects/Cura/resources/qml/Cura.qml:184 msgctxt "@title:menu" msgid "&Settings" -msgstr "&Einstellungen" +msgstr "&Konfiguration" #: /home/ruben/Projects/Cura/resources/qml/Cura.qml:186 msgctxt "@title:menu menubar:toplevel" From f91c696e4bfaa1ace21dabfdb91d4651599768ea Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Aug 2018 13:17:20 +0200 Subject: [PATCH 144/243] Clarify error message a bit more The QA engineer was a bit confused by this one. Let's make the language a bit easier. --- plugins/UM3NetworkPrinting/SendMaterialJob.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/SendMaterialJob.py b/plugins/UM3NetworkPrinting/SendMaterialJob.py index 0ac38843a1..8491e79c29 100644 --- a/plugins/UM3NetworkPrinting/SendMaterialJob.py +++ b/plugins/UM3NetworkPrinting/SendMaterialJob.py @@ -39,12 +39,12 @@ class SendMaterialJob(Job): try: remote_materials_list = json.loads(remote_materials_list) except json.JSONDecodeError: - Logger.log("e", "Current material storage on printer was a corrupted reply.") + Logger.log("e", "Request material storage on printer: I didn't understand the printer's answer.") return try: remote_materials_by_guid = {material["guid"]: material for material in remote_materials_list} #Index by GUID. except KeyError: - Logger.log("e", "Current material storage on printer was an invalid reply (missing GUIDs).") + Logger.log("e", "Request material storage on printer: Printer's answer was missing GUIDs.") return container_registry = ContainerRegistry.getInstance() From 6d237b09e842b9930d377f3b039a869d0de1acd7 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 10 Aug 2018 16:08:54 +0200 Subject: [PATCH 145/243] Proposed improvement on API naming --- cura/API/{SidebarContextMenu.py => Sidebar.py} | 12 ++++++------ cura/API/__init__.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) rename cura/API/{SidebarContextMenu.py => Sidebar.py} (72%) diff --git a/cura/API/SidebarContextMenu.py b/cura/API/Sidebar.py similarity index 72% rename from cura/API/SidebarContextMenu.py rename to cura/API/Sidebar.py index f47b3a062a..dd001739f5 100644 --- a/cura/API/SidebarContextMenu.py +++ b/cura/API/Sidebar.py @@ -9,26 +9,26 @@ from cura.CuraApplication import CuraApplication # Usage: # ``from cura.API import CuraAPI # api = CuraAPI() -# api.sidebar_context_menu.getSidebarMenuItems() +# api.sidebar.getContextMenuItems() # menu_actions = [] -# menu_actions.append("sidebarMenuItemOnClickHander") +# menu_actions.append("sidebarMenuItemOnClickHandler") # data = { # "name": "My Plugin Action", # "iconName": "my-plugin-icon", # "actions": menu_actions, # "menu_item": MyPluginAction(self) # } -# api.sidebar_context_menu.addSidebarMenuItems([])`` -class SidebarContextMenu: +# api.sidebar.addContextMenuItem(data)`` +class Sidebar: _application = CuraApplication.getInstance() # type: CuraApplication ## Add items to the sidebar context menu. # \param menu_item dict containing the menu item to add. - def addSidebarMenuItem(self, menu_item: dict) -> None: + def addContextMenuItem(self, menu_item: dict) -> None: self._application.addSidebarCustomMenuItem(menu_item) ## Get all custom items currently added to the sidebar context menu. # \return List containing all custom context menu items. - def getSidebarMenuItems(self) -> list: + def getContextMenuItems(self) -> list: return self._application.getSidebarCustomMenuItems() \ No newline at end of file diff --git a/cura/API/__init__.py b/cura/API/__init__.py index 40c07b8371..4cd0c9436a 100644 --- a/cura/API/__init__.py +++ b/cura/API/__init__.py @@ -2,7 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from UM.PluginRegistry import PluginRegistry from cura.API.Backups import Backups -from cura.API.SidebarContextMenu import SidebarContextMenu +from cura.API.Sidebar import Sidebar ## The official Cura API that plug-ins can use to interact with Cura. # @@ -19,4 +19,4 @@ class CuraAPI: backups = Backups() # Sidebar Context Menu API - sidebar_context_menu = SidebarContextMenu() + sidebar = Sidebar() From 16db29761327adbd9d8463debf3b7bc69d3a0c04 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 10 Aug 2018 16:28:02 +0200 Subject: [PATCH 146/243] Some final tweaks Contributes to CURA-5595 --- cura/API/Backups.py | 1 + .../API/{Sidebar.py => Interface/Settings.py} | 21 ++++++++-------- cura/API/Interface/__init__.py | 24 +++++++++++++++++++ cura/API/__init__.py | 9 +++---- 4 files changed, 40 insertions(+), 15 deletions(-) rename cura/API/{Sidebar.py => Interface/Settings.py} (56%) create mode 100644 cura/API/Interface/__init__.py diff --git a/cura/API/Backups.py b/cura/API/Backups.py index 5964557264..f31933c844 100644 --- a/cura/API/Backups.py +++ b/cura/API/Backups.py @@ -13,6 +13,7 @@ from cura.Backups.BackupsManager import BackupsManager # api = CuraAPI() # api.backups.createBackup() # api.backups.restoreBackup(my_zip_file, {"cura_release": "3.1"})`` + class Backups: manager = BackupsManager() # Re-used instance of the backups manager. diff --git a/cura/API/Sidebar.py b/cura/API/Interface/Settings.py similarity index 56% rename from cura/API/Sidebar.py rename to cura/API/Interface/Settings.py index dd001739f5..2889db7022 100644 --- a/cura/API/Sidebar.py +++ b/cura/API/Interface/Settings.py @@ -3,32 +3,31 @@ from cura.CuraApplication import CuraApplication -## The sidebar context menu API provides a version-proof bridge between Cura's -# Sidebar Context Menu and plug-ins that hook into it. +## The Interface.Settings API provides a version-proof bridge between Cura's +# (currently) sidebar UI and plug-ins that hook into it. # # Usage: # ``from cura.API import CuraAPI # api = CuraAPI() -# api.sidebar.getContextMenuItems() -# menu_actions = [] -# menu_actions.append("sidebarMenuItemOnClickHandler") +# api.interface.settings.getContextMenuItems() # data = { # "name": "My Plugin Action", # "iconName": "my-plugin-icon", -# "actions": menu_actions, +# "actions": my_menu_actions, # "menu_item": MyPluginAction(self) # } -# api.sidebar.addContextMenuItem(data)`` -class Sidebar: +# api.interface.settings.addContextMenuItem(data)`` - _application = CuraApplication.getInstance() # type: CuraApplication +class Settings: + # Re-used instance of Cura: + application = CuraApplication.getInstance() # type: CuraApplication ## Add items to the sidebar context menu. # \param menu_item dict containing the menu item to add. def addContextMenuItem(self, menu_item: dict) -> None: - self._application.addSidebarCustomMenuItem(menu_item) + self.application.addSidebarCustomMenuItem(menu_item) ## Get all custom items currently added to the sidebar context menu. # \return List containing all custom context menu items. def getContextMenuItems(self) -> list: - return self._application.getSidebarCustomMenuItems() \ No newline at end of file + return self.application.getSidebarCustomMenuItems() \ No newline at end of file diff --git a/cura/API/Interface/__init__.py b/cura/API/Interface/__init__.py new file mode 100644 index 0000000000..b38118949b --- /dev/null +++ b/cura/API/Interface/__init__.py @@ -0,0 +1,24 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from UM.PluginRegistry import PluginRegistry +from cura.API.Interface.Settings import Settings + +## The Interface class serves as a common root for the specific API +# methods for each interface element. +# +# Usage: +# ``from cura.API import CuraAPI +# api = CuraAPI() +# api.interface.settings.addContextMenuItem() +# api.interface.viewport.addOverlay() # Not implemented, just a hypothetical +# api.interface.toolbar.getToolButtonCount() # Not implemented, just a hypothetical +# # etc.`` + +class Interface: + + # For now we use the same API version to be consistent. + VERSION = PluginRegistry.APIVersion + + # API methods specific to the settings portion of the UI + settings = Settings() diff --git a/cura/API/__init__.py b/cura/API/__init__.py index 4cd0c9436a..64d636903d 100644 --- a/cura/API/__init__.py +++ b/cura/API/__init__.py @@ -2,7 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from UM.PluginRegistry import PluginRegistry from cura.API.Backups import Backups -from cura.API.Sidebar import Sidebar +from cura.API.Interface import Interface ## The official Cura API that plug-ins can use to interact with Cura. # @@ -10,13 +10,14 @@ from cura.API.Sidebar import Sidebar # this API provides a version-safe interface with proper deprecation warnings # etc. Usage of any other methods than the ones provided in this API can cause # plug-ins to be unstable. + class CuraAPI: # For now we use the same API version to be consistent. VERSION = PluginRegistry.APIVersion - # Backups API. + # Backups API backups = Backups() - # Sidebar Context Menu API - sidebar = Sidebar() + # Interface API + interface = Interface() From 825a3cd08fc5b796cadf6bea10442f73492d545d Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 13 Aug 2018 09:55:57 +0200 Subject: [PATCH 147/243] CURA-5570 Fix the configuration sync feature. It crashed Cura because it was using an outdated signature of the method getMaterialNodeByType. --- cura/Machines/MaterialManager.py | 1 - cura/Machines/QualityManager.py | 1 - cura/Settings/MachineManager.py | 7 ++++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 7c5c901b32..d5a7d5d089 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -186,7 +186,6 @@ class MaterialManager(QObject): for root_material_id in data_dict.values(): self._diameter_material_map[root_material_id] = default_root_material_id - # Map #4 # "machine" -> "nozzle name" -> "buildplate name" -> "root material ID" -> specific material InstanceContainer self._diameter_machine_nozzle_buildplate_material_map = dict() diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 5496ca9f87..8b4a396164 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -264,7 +264,6 @@ class QualityManager(QObject): # the list with priorities as the order. Later, we just need to loop over each node in this list and fetch # qualities from there. node_info_list_0 = [nozzle_name, buildplate_name, root_material_id] - current_node_info_idx = 0 nodes_to_check = [] # This function tries to recursively find the deepest (the most specific) branch and add those nodes to diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 733340e0ce..2f81f78c95 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1331,7 +1331,12 @@ class MachineManager(QObject): for extruder_configuration in configuration.extruderConfigurations: position = str(extruder_configuration.position) variant_container_node = self._variant_manager.getVariantNode(self._global_container_stack.definition.getId(), extruder_configuration.hotendID) - material_container_node = self._material_manager.getMaterialNodeByType(self._global_container_stack, position, extruder_configuration.hotendID, extruder_configuration.material.guid) + material_container_node = self._material_manager.getMaterialNodeByType(self._global_container_stack, + position, + extruder_configuration.hotendID, + configuration.buildplateConfiguration, + extruder_configuration.material.guid) + if variant_container_node: self._setVariantNode(position, variant_container_node) else: From 787948f4015b03ab760b5378df11f16899f6c207 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Mon, 13 Aug 2018 10:42:22 +0200 Subject: [PATCH 148/243] Removed "Preparing" button state CURA-5551 --- resources/qml/SaveButton.qml | 50 ++++++++---------------------------- 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index 9b5e3befb0..0e0eec7277 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -48,15 +48,14 @@ Item { } function sliceOrStopSlicing() { - if ([1, 5].indexOf(base.backendState) != -1) - { - prepareButton.preparingToSlice = true; - CuraApplication.backend.forceSlice(); - } - else - { - prepareButton.preparingToSlice = false; - CuraApplication.backend.stopSlicing(); + try { + if ([1, 5].indexOf(base.backendState) != -1) { + CuraApplication.backend.forceSlice(); + } else { + CuraApplication.backend.stopSlicing(); + } + } catch (e) { + console.log('Could not start or stop slicing', e) } } @@ -168,10 +167,10 @@ Item { // Prepare button, only shows if auto_slice is off Button { id: prepareButton - property bool preparingToSlice: false + tooltip: [1, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@info:tooltip","Slice current printjob") : catalog.i18nc("@info:tooltip","Cancel slicing process") // 1 = not started, 2 = Processing - enabled: !preparingToSlice && base.backendState != "undefined" && ([1, 2].indexOf(base.backendState) != -1) && base.activity + enabled: base.backendState != "undefined" && ([1, 2].indexOf(base.backendState) != -1) && base.activity visible: base.backendState != "undefined" && !autoSlice && ([1, 2, 4].indexOf(base.backendState) != -1) && base.activity property bool autoSlice height: UM.Theme.getSize("save_button_save_to_button").height @@ -181,23 +180,7 @@ Item { anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width // 1 = not started, 4 = error, 5 = disabled - text: { - if (preparingToSlice) - { - return catalog.i18nc("@label:Printjob", "Preparing"); - } - else - { - if ([1, 4, 5].indexOf(base.backendState) != -1) - { - return catalog.i18nc("@label:Printjob", "Prepare"); - } - else - { - return catalog.i18nc("@label:Printjob", "Cancel") - } - } - } + text: [1, 4, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@label:Printjob", "Prepare") : catalog.i18nc("@label:Printjob", "Cancel") onClicked: { sliceOrStopSlicing(); @@ -254,17 +237,6 @@ Item { } label: Item { } } - - Connections { - target: UM.Backend - onStateChanged: - { - if ([2, 3].indexOf(UM.Backend.state) != -1) - { - prepareButton.preparingToSlice = false; - } - } - } } Button { From 3fad11e07fa6acc9b2354721ef6e2c82ed6b0098 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 13 Aug 2018 10:45:03 +0200 Subject: [PATCH 149/243] Code style fixes Contributes to CURA-5595 --- cura/CuraApplication.py | 3 +-- cura/Settings/SidebarCustomMenuItemsModel.py | 28 ++++++++++---------- resources/qml/Settings/SettingView.qml | 2 +- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 2680c9a89c..85aa5a8322 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1736,8 +1736,7 @@ class CuraApplication(QtApplication): def showMoreInformationDialogForAnonymousDataCollection(self): cast(SliceInfo, self._plugin_registry.getPluginObject("SliceInfoPlugin")).showMoreInfoDialog() - - def addSidebarCustomMenuItem(self, menu_item: list) -> None: + def addSidebarCustomMenuItem(self, menu_item: dict) -> None: self._sidebar_custom_menu_items.append(menu_item) def getSidebarCustomMenuItems(self) -> list: diff --git a/cura/Settings/SidebarCustomMenuItemsModel.py b/cura/Settings/SidebarCustomMenuItemsModel.py index d2a4d1a2b1..ec926363f5 100644 --- a/cura/Settings/SidebarCustomMenuItemsModel.py +++ b/cura/Settings/SidebarCustomMenuItemsModel.py @@ -8,17 +8,17 @@ from PyQt5.QtCore import pyqtSlot, Qt class SidebarCustomMenuItemsModel(ListModel): - NameRole = Qt.UserRole + 1 - ActionsRole = Qt.UserRole + 2 - MenuItemRole = Qt.UserRole + 3 - MenuItemIconNameRole = Qt.UserRole + 5 + name_role = Qt.UserRole + 1 + actions_role = Qt.UserRole + 2 + menu_item_role = Qt.UserRole + 3 + menu_item_icon_name_role = Qt.UserRole + 5 def __init__(self, parent=None): super().__init__(parent) - self.addRoleName(self.NameRole, "name") - self.addRoleName(self.ActionsRole, "actions") - self.addRoleName(self.MenuItemRole, "menu_item") - self.addRoleName(self.MenuItemIconNameRole, "iconName") + self.addRoleName(self.name_role, "name") + self.addRoleName(self.actions_role, "actions") + self.addRoleName(self.menu_item_role, "menu_item") + self.addRoleName(self.menu_item_icon_name_role, "iconName") self._updateExtensionList() def _updateExtensionList(self)-> None: @@ -26,14 +26,14 @@ class SidebarCustomMenuItemsModel(ListModel): for menu_item in CuraApplication.getInstance().getSidebarCustomMenuItems(): self.appendItem({ - "name": menu_item["name"], - "iconName": menu_item["iconName"], - "actions": menu_item["actions"], - "menu_item": menu_item["menu_item"] - }) + "name": menu_item["name"], + "icon_name": menu_item["icon_name"], + "actions": menu_item["actions"], + "menu_item": menu_item["menu_item"] + }) @pyqtSlot(str, "QVariantList", "QVariantMap") - def callMenuItemMethod(self, menu_item_name: str, menu_item_actions: list, kwargs: Any)-> None: + def callMenuItemMethod(self, menu_item_name: str, menu_item_actions: list, kwargs: Any) -> None: for item in self._items: if menu_item_name == item["name"]: for method in menu_item_actions: diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 88876123fe..e17f11bf99 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -568,7 +568,7 @@ Item MenuItem { text: model.name - iconName: model.iconName + iconName: model.icon_name onTriggered: { customMenuItems.model.callMenuItemMethod(name, model.actions, {"key": contextMenu.key}) From 98a0bb50025ba71739834a82ebebf48340ea39df Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 13 Aug 2018 11:15:32 +0200 Subject: [PATCH 150/243] CURA-5570 Remove a check that caused empty list of profiles. --- cura/Machines/QualityManager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 8b4a396164..df3bec0827 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -238,6 +238,7 @@ class QualityManager(QObject): # The root material IDs in this list are in prioritized order. root_material_id_list = [] has_material = False # flag indicating whether this extruder has a material assigned + root_material_id = None if extruder.material.getId() != "empty_material": has_material = True root_material_id = extruder.material.getMetaDataEntry("base_file") @@ -248,7 +249,7 @@ class QualityManager(QObject): # Also try to get the fallback material material_type = extruder.material.getMetaDataEntry("material") fallback_root_material_id = self._material_manager.getFallbackMaterialIdByMaterialType(material_type) - if fallback_root_material_id and root_material_id not in root_material_id_list: + if fallback_root_material_id: root_material_id_list.append(fallback_root_material_id) # Here we construct a list of nodes we want to look for qualities with the highest priority first. From bd47dfef754c6d979d563c0817de3e70ec767a4f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 13 Aug 2018 11:23:10 +0200 Subject: [PATCH 151/243] Revert "Revert "Merge pull request #4203 from Ultimaker/CURA-5538-fix-one-at-a-time-order-2"" This reverts commit 89ed2bcff80a7a414f77c455baa0023c631eae7c. --- cura/OneAtATimeIterator.py | 184 +++++++++++++++--------------- cura/Scene/ConvexHullDecorator.py | 2 +- cura/Settings/GlobalStack.py | 3 + 3 files changed, 94 insertions(+), 95 deletions(-) diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py index 84d65bae8e..990ed37ab7 100644 --- a/cura/OneAtATimeIterator.py +++ b/cura/OneAtATimeIterator.py @@ -1,112 +1,108 @@ -# Copyright (c) 2015 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +import sys + +from shapely import affinity +from shapely.geometry import Polygon + from UM.Scene.Iterator import Iterator from UM.Scene.SceneNode import SceneNode -from functools import cmp_to_key -from UM.Application import Application -## Iterator that returns a list of nodes in the order that they need to be printed -# If there is no solution an empty list is returned. -# Take note that the list of nodes can have children (that may or may not contain mesh data) + +# Iterator that determines the object print order when one-at a time mode is enabled. +# +# In one-at-a-time mode, only one extruder can be enabled to print. In order to maximize the number of objects we can +# print, we need to print from the corner that's closest to the extruder that's being used. Here is an illustration: +# +# +--------------------------------+ +# | | +# | | +# | | - Rectangle represents the complete print head including fans, etc. +# | X X | y - X's are the nozzles +# | (1) (2) | | +# | | | +# +--------------------------------+ +--> x +# +# In this case, the nozzles are symmetric, nozzle (1) is closer to the bottom left corner while (2) is closer to the +# bottom right. If we use nozzle (1) to print, then we better off printing from the bottom left corner so the print +# head will not collide into an object on its top-right side, which is a very large unused area. Following the same +# logic, if we are printing with nozzle (2), then it's better to print from the bottom-right side. +# +# This iterator determines the print order following the rules above. +# class OneAtATimeIterator(Iterator.Iterator): + def __init__(self, scene_node): - super().__init__(scene_node) # Call super to make multiple inheritence work. - self._hit_map = [[]] + from cura.CuraApplication import CuraApplication + self._global_stack = CuraApplication.getInstance().getGlobalContainerStack() self._original_node_list = [] - + super().__init__(scene_node) # Call super to make multiple inheritance work. + + def getMachineNearestCornerToExtruder(self, global_stack): + head_and_fans_coordinates = global_stack.getHeadAndFansCoordinates() + + used_extruder = None + for extruder in global_stack.extruders.values(): + if extruder.isEnabled: + used_extruder = extruder + break + + extruder_offsets = [used_extruder.getProperty("machine_nozzle_offset_x", "value"), + used_extruder.getProperty("machine_nozzle_offset_y", "value")] + + # find the corner that's closest to the origin + min_distance2 = sys.maxsize + min_coord = None + for coord in head_and_fans_coordinates: + x = coord[0] - extruder_offsets[0] + y = coord[1] - extruder_offsets[1] + + distance2 = x**2 + y**2 + if distance2 <= min_distance2: + min_distance2 = distance2 + min_coord = coord + + return min_coord + def _fillStack(self): + min_coord = self.getMachineNearestCornerToExtruder(self._global_stack) + transform_x = -int(round(min_coord[0] / abs(min_coord[0]))) + transform_y = -int(round(min_coord[1] / abs(min_coord[1]))) + + machine_size = [self._global_stack.getProperty("machine_width", "value"), + self._global_stack.getProperty("machine_depth", "value")] + + def flip_x(polygon): + tm2 = [-1, 0, 0, 1, 0, 0] + return affinity.affine_transform(affinity.translate(polygon, xoff = -machine_size[0]), tm2) + + def flip_y(polygon): + tm2 = [1, 0, 0, -1, 0, 0] + return affinity.affine_transform(affinity.translate(polygon, yoff = -machine_size[1]), tm2) + node_list = [] for node in self._scene_node.getChildren(): if not issubclass(type(node), SceneNode): continue - if node.callDecoration("getConvexHull"): - node_list.append(node) + convex_hull = node.callDecoration("getConvexHull") + if convex_hull: + xmin = min(x for x, _ in convex_hull._points) + xmax = max(x for x, _ in convex_hull._points) + ymin = min(y for _, y in convex_hull._points) + ymax = max(y for _, y in convex_hull._points) + convex_hull_polygon = Polygon.from_bounds(xmin, ymin, xmax, ymax) + if transform_x < 0: + convex_hull_polygon = flip_x(convex_hull_polygon) + if transform_y < 0: + convex_hull_polygon = flip_y(convex_hull_polygon) - if len(node_list) < 2: - self._node_stack = node_list[:] - return + node_list.append({"node": node, + "min_coord": [convex_hull_polygon.bounds[0], convex_hull_polygon.bounds[1]], + }) - # Copy the list - self._original_node_list = node_list[:] - - ## Initialise the hit map (pre-compute all hits between all objects) - self._hit_map = [[self._checkHit(i,j) for i in node_list] for j in node_list] - - # Check if we have to files that block eachother. If this is the case, there is no solution! - for a in range(0,len(node_list)): - for b in range(0,len(node_list)): - if a != b and self._hit_map[a][b] and self._hit_map[b][a]: - return - - # Sort the original list so that items that block the most other objects are at the beginning. - # This does not decrease the worst case running time, but should improve it in most cases. - sorted(node_list, key = cmp_to_key(self._calculateScore)) - - todo_node_list = [_ObjectOrder([], node_list)] - while len(todo_node_list) > 0: - current = todo_node_list.pop() - for node in current.todo: - # Check if the object can be placed with what we have and still allows for a solution in the future - if not self._checkHitMultiple(node, current.order) and not self._checkBlockMultiple(node, current.todo): - # We found a possible result. Create new todo & order list. - new_todo_list = current.todo[:] - new_todo_list.remove(node) - new_order = current.order[:] + [node] - if len(new_todo_list) == 0: - # We have no more nodes to check, so quit looking. - todo_node_list = None - self._node_stack = new_order - - return - todo_node_list.append(_ObjectOrder(new_order, new_todo_list)) - self._node_stack = [] #No result found! - - - # Check if first object can be printed before the provided list (using the hit map) - def _checkHitMultiple(self, node, other_nodes): - node_index = self._original_node_list.index(node) - for other_node in other_nodes: - other_node_index = self._original_node_list.index(other_node) - if self._hit_map[node_index][other_node_index]: - return True - return False - - def _checkBlockMultiple(self, node, other_nodes): - node_index = self._original_node_list.index(node) - for other_node in other_nodes: - other_node_index = self._original_node_list.index(other_node) - if self._hit_map[other_node_index][node_index] and node_index != other_node_index: - return True - return False - - ## Calculate score simply sums the number of other objects it 'blocks' - def _calculateScore(self, a, b): - score_a = sum(self._hit_map[self._original_node_list.index(a)]) - score_b = sum(self._hit_map[self._original_node_list.index(b)]) - return score_a - score_b - - # Checks if A can be printed before B - def _checkHit(self, a, b): - if a == b: - return False - - overlap = a.callDecoration("getConvexHullBoundary").intersectsPolygon(b.callDecoration("getConvexHullHeadFull")) - if overlap: - return True - else: - return False - - -## Internal object used to keep track of a possible order in which to print objects. -class _ObjectOrder(): - def __init__(self, order, todo): - """ - :param order: List of indexes in which to print objects, ordered by printing order. - :param todo: List of indexes which are not yet inserted into the order list. - """ - self.order = order - self.todo = todo + node_list = sorted(node_list, key = lambda d: d["min_coord"]) + self._node_stack = [d["node"] for d in node_list] diff --git a/cura/Scene/ConvexHullDecorator.py b/cura/Scene/ConvexHullDecorator.py index 66bc8a7fc3..367144abfc 100644 --- a/cura/Scene/ConvexHullDecorator.py +++ b/cura/Scene/ConvexHullDecorator.py @@ -229,7 +229,7 @@ class ConvexHullDecorator(SceneNodeDecorator): return offset_hull def _getHeadAndFans(self): - return Polygon(numpy.array(self._global_stack.getProperty("machine_head_with_fans_polygon", "value"), numpy.float32)) + return Polygon(numpy.array(self._global_stack.getHeadAndFansCoordinates(), numpy.float32)) def _compute2DConvexHeadFull(self): return self._compute2DConvexHull().getMinkowskiHull(self._getHeadAndFans()) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 66f3290b85..ea955d24b0 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -172,6 +172,9 @@ class GlobalStack(CuraContainerStack): return False return True + def getHeadAndFansCoordinates(self): + return self.getProperty("machine_head_with_fans_polygon", "value") + ## private: global_stack_mime = MimeType( From b1c073aab63ba5869b0cc9d6efad05ef09d15dcd Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 13 Aug 2018 11:50:50 +0200 Subject: [PATCH 152/243] CURA-5570 Expose the CuraSDKVersion to qml and show the buildplate selector only when "dev" version is selected. --- cura/CuraApplication.py | 4 +++- resources/qml/Cura.qml | 4 ++-- resources/qml/SidebarHeader.qml | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 6164fc8756..a2c4f6ae4c 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -117,11 +117,12 @@ if TYPE_CHECKING: numpy.seterr(all = "ignore") try: - from cura.CuraVersion import CuraVersion, CuraBuildType, CuraDebugMode + from cura.CuraVersion import CuraVersion, CuraBuildType, CuraDebugMode, CuraSDKVersion except ImportError: CuraVersion = "master" # [CodeStyle: Reflecting imported value] CuraBuildType = "" CuraDebugMode = False + CuraSDKVerion = "" class CuraApplication(QtApplication): @@ -910,6 +911,7 @@ class CuraApplication(QtApplication): engine.rootContext().setContextProperty("CuraApplication", self) engine.rootContext().setContextProperty("PrintInformation", self._print_information) engine.rootContext().setContextProperty("CuraActions", self._cura_actions) + engine.rootContext().setContextProperty("CuraSDKVersion", CuraSDKVersion) qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type") diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index e1bf8c8b77..60f6e77ea9 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -231,8 +231,8 @@ UM.MainWindow onObjectRemoved: settingsMenu.removeItem(object) } - // TODO Temporary hidden, add back again when feature ready - BuildplateMenu { title: catalog.i18nc("@title:menu", "&Build plate"); visible: Cura.MachineManager.hasVariantBuildplates } + // TODO Only show in dev mode. Remove check when feature ready + BuildplateMenu { title: catalog.i18nc("@title:menu", "&Build plate"); visible: CuraSDKVersion == "dev" ? Cura.MachineManager.hasVariantBuildplates : false } ProfileMenu { title: catalog.i18nc("@title:menu", "&Profile"); } MenuSeparator { } diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index 4e8911b3c1..4bc0e8b2ef 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -476,8 +476,8 @@ Column { id: buildplateRow height: UM.Theme.getSize("sidebar_setup").height - // TODO Temporary hidden, add back again when feature ready - visible: false //Cura.MachineManager.hasVariantBuildplates && !sidebar.hideSettings + // TODO Only show in dev mode. Remove check when feature ready + visible: CuraSDKVersion == "dev" ? Cura.MachineManager.hasVariantBuildplates && !sidebar.hideSettings : false anchors { From d45d6add4026f898e4c47fc3ecfbe069215d5b5f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 13 Aug 2018 12:56:41 +0200 Subject: [PATCH 153/243] Add collision detection in on-at-a-time iterator --- cura/OneAtATimeIterator.py | 45 +++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py index 990ed37ab7..e7ad833e1c 100644 --- a/cura/OneAtATimeIterator.py +++ b/cura/OneAtATimeIterator.py @@ -6,7 +6,7 @@ import sys from shapely import affinity from shapely.geometry import Polygon -from UM.Scene.Iterator import Iterator +from UM.Scene.Iterator.Iterator import Iterator from UM.Scene.SceneNode import SceneNode @@ -20,7 +20,7 @@ from UM.Scene.SceneNode import SceneNode # | | # | | - Rectangle represents the complete print head including fans, etc. # | X X | y - X's are the nozzles -# | (1) (2) | | +# | (1) (2) | ^ # | | | # +--------------------------------+ +--> x # @@ -31,12 +31,13 @@ from UM.Scene.SceneNode import SceneNode # # This iterator determines the print order following the rules above. # -class OneAtATimeIterator(Iterator.Iterator): +class OneAtATimeIterator(Iterator): def __init__(self, scene_node): from cura.CuraApplication import CuraApplication self._global_stack = CuraApplication.getInstance().getGlobalContainerStack() self._original_node_list = [] + super().__init__(scene_node) # Call super to make multiple inheritance work. def getMachineNearestCornerToExtruder(self, global_stack): @@ -65,6 +66,40 @@ class OneAtATimeIterator(Iterator.Iterator): return min_coord + def _checkForCollisions(self) -> bool: + all_nodes = [] + for node in self._scene_node.getChildren(): + if not issubclass(type(node), SceneNode): + continue + convex_hull = node.callDecoration("getConvexHullHead") + if not convex_hull: + continue + + bounding_box = node.getBoundingBox() + from UM.Math.Polygon import Polygon + bounding_box_polygon = Polygon([[bounding_box.left, bounding_box.front], + [bounding_box.left, bounding_box.back], + [bounding_box.right, bounding_box.back], + [bounding_box.right, bounding_box.front]]) + + all_nodes.append({"node": node, + "bounding_box": bounding_box_polygon, + "convex_hull": convex_hull}) + + has_collisions = False + for i, node_dict in enumerate(all_nodes): + for j, other_node_dict in enumerate(all_nodes): + if i == j: + continue + if node_dict["bounding_box"].intersectsPolygon(other_node_dict["convex_hull"]): + has_collisions = True + break + + if has_collisions: + break + + return has_collisions + def _fillStack(self): min_coord = self.getMachineNearestCornerToExtruder(self._global_stack) transform_x = -int(round(min_coord[0] / abs(min_coord[0]))) @@ -81,6 +116,10 @@ class OneAtATimeIterator(Iterator.Iterator): tm2 = [1, 0, 0, -1, 0, 0] return affinity.affine_transform(affinity.translate(polygon, yoff = -machine_size[1]), tm2) + if self._checkForCollisions(): + self._node_stack = [] + return + node_list = [] for node in self._scene_node.getChildren(): if not issubclass(type(node), SceneNode): From 42b509cd4a5eb51d66ee6474817b6a78ed97ce2b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 13 Aug 2018 13:44:07 +0200 Subject: [PATCH 154/243] Fix a wrong type hinting --- cura/Settings/MachineManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7bf4b1394c..1941324eed 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -49,7 +49,7 @@ class MachineManager(QObject): def __init__(self, parent: QObject = None) -> None: super().__init__(parent) - self._active_container_stack = None # type: Optional[ExtruderManager] + self._active_container_stack = None # type: Optional[ExtruderStack] self._global_container_stack = None # type: Optional[GlobalStack] self._current_root_material_id = {} # type: Dict[str, str] From 25e6fd8becebbb2ddf180daa8a7eb6561bcb4dc0 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 13 Aug 2018 13:47:26 +0200 Subject: [PATCH 155/243] Fix incorrect type hinting --- cura/Settings/MachineManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 1941324eed..bdb96b373e 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1183,7 +1183,7 @@ class MachineManager(QObject): if not self._global_container_stack.variant: self._global_container_stack.variant = self._application.empty_variant_container - def _setMaterial(self, position: str, container_node: ContainerNode = None) -> None: + def _setMaterial(self, position: str, container_node: Optional["ContainerNode"] = None) -> None: if self._global_container_stack is None: return if container_node and container_node.getContainer(): From 8e891b69b006d079ed98b3bdcf5434ef4b507cb5 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 13 Aug 2018 13:48:00 +0200 Subject: [PATCH 156/243] Move type hinting imports into TYPE_CHECKING block --- cura/Settings/MachineManager.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index bdb96b373e..d65bbfddd9 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -21,9 +21,6 @@ from UM.Settings.SettingFunction import SettingFunction from UM.Signal import postponeSignals, CompressTechnique import cura.CuraApplication -from cura.Machines.ContainerNode import ContainerNode #For typing. -from cura.Machines.QualityChangesGroup import QualityChangesGroup #For typing. -from cura.Machines.QualityGroup import QualityGroup #For typing. from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch from cura.PrinterOutputDevice import PrinterOutputDevice from cura.PrinterOutput.ConfigurationModel import ConfigurationModel @@ -44,6 +41,10 @@ if TYPE_CHECKING: from cura.Machines.MaterialManager import MaterialManager from cura.Machines.QualityManager import QualityManager from cura.Machines.VariantManager import VariantManager + from cura.Machines.ContainerNode import ContainerNode + from cura.Machines.QualityChangesGroup import QualityChangesGroup + from cura.Machines.QualityGroup import QualityGroup + class MachineManager(QObject): def __init__(self, parent: QObject = None) -> None: @@ -1087,7 +1088,7 @@ class MachineManager(QObject): self.activeQualityGroupChanged.emit() self.activeQualityChangesGroupChanged.emit() - def _setQualityGroup(self, quality_group: Optional[QualityGroup], empty_quality_changes: bool = True) -> None: + def _setQualityGroup(self, quality_group: Optional["QualityGroup"], empty_quality_changes: bool = True) -> None: if self._global_container_stack is None: return if quality_group is None: @@ -1118,7 +1119,7 @@ class MachineManager(QObject): self.activeQualityGroupChanged.emit() self.activeQualityChangesGroupChanged.emit() - def _fixQualityChangesGroupToNotSupported(self, quality_changes_group: QualityChangesGroup) -> None: + def _fixQualityChangesGroupToNotSupported(self, quality_changes_group: "QualityChangesGroup") -> None: nodes = [quality_changes_group.node_for_global] + list(quality_changes_group.nodes_for_extruders.values()) containers = [n.getContainer() for n in nodes if n is not None] for container in containers: @@ -1126,7 +1127,7 @@ class MachineManager(QObject): container.setMetaDataEntry("quality_type", "not_supported") quality_changes_group.quality_type = "not_supported" - def _setQualityChangesGroup(self, quality_changes_group: QualityChangesGroup) -> None: + def _setQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup") -> None: if self._global_container_stack is None: return #Can't change that. quality_type = quality_changes_group.quality_type @@ -1170,13 +1171,13 @@ class MachineManager(QObject): self.activeQualityGroupChanged.emit() self.activeQualityChangesGroupChanged.emit() - def _setVariantNode(self, position: str, container_node: ContainerNode) -> None: + def _setVariantNode(self, position: str, container_node: "ContainerNode") -> None: if container_node.getContainer() is None or self._global_container_stack is None: return self._global_container_stack.extruders[position].variant = container_node.getContainer() self.activeVariantChanged.emit() - def _setGlobalVariant(self, container_node: ContainerNode) -> None: + def _setGlobalVariant(self, container_node: "ContainerNode") -> None: if self._global_container_stack is None: return self._global_container_stack.variant = container_node.getContainer() @@ -1388,7 +1389,7 @@ class MachineManager(QObject): return bool(containers) @pyqtSlot("QVariant") - def setGlobalVariant(self, container_node: ContainerNode) -> None: + def setGlobalVariant(self, container_node: "ContainerNode") -> None: self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self._setGlobalVariant(container_node) @@ -1438,7 +1439,7 @@ class MachineManager(QObject): self.setVariant(position, variant_node) @pyqtSlot(str, "QVariant") - def setVariant(self, position: str, container_node: ContainerNode) -> None: + def setVariant(self, position: str, container_node: "ContainerNode") -> None: position = str(position) self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): @@ -1462,7 +1463,7 @@ class MachineManager(QObject): ## Optionally provide global_stack if you want to use your own # The active global_stack is treated differently. @pyqtSlot(QObject) - def setQualityGroup(self, quality_group: QualityGroup, no_dialog: bool = False, global_stack: Optional["GlobalStack"] = None) -> None: + def setQualityGroup(self, quality_group: "QualityGroup", no_dialog: bool = False, global_stack: Optional["GlobalStack"] = None) -> None: if global_stack is not None and global_stack != self._global_container_stack: if quality_group is None: Logger.log("e", "Could not set quality group because quality group is None") @@ -1489,11 +1490,11 @@ class MachineManager(QObject): self._application.discardOrKeepProfileChanges() @pyqtProperty(QObject, fset = setQualityGroup, notify = activeQualityGroupChanged) - def activeQualityGroup(self) -> Optional[QualityGroup]: + def activeQualityGroup(self) -> Optional["QualityGroup"]: return self._current_quality_group @pyqtSlot(QObject) - def setQualityChangesGroup(self, quality_changes_group: QualityChangesGroup, no_dialog: bool = False) -> None: + def setQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup", no_dialog: bool = False) -> None: self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self._setQualityChangesGroup(quality_changes_group) @@ -1512,7 +1513,7 @@ class MachineManager(QObject): stack.userChanges.clear() @pyqtProperty(QObject, fset = setQualityChangesGroup, notify = activeQualityChangesGroupChanged) - def activeQualityChangesGroup(self) -> Optional[QualityChangesGroup]: + def activeQualityChangesGroup(self) -> Optional["QualityChangesGroup"]: return self._current_quality_changes_group @pyqtProperty(str, notify = activeQualityGroupChanged) From e0ad7a9fb4bce64d3c5503877cc1b37086f8c2ab Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 13 Aug 2018 14:24:25 +0200 Subject: [PATCH 157/243] Add answer commments to some puzzling code --- cura/Settings/GlobalStack.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 49c7b4f04a..dda21f3719 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -102,6 +102,9 @@ class GlobalStack(CuraContainerStack): # Handle the "resolve" property. #TODO: Why the hell does this involve threading? + # Answer: Because if multiple threads start resolving properties that have the same underlying properties that's + # related, without taking a note of which thread a resolve paths belongs to, they can bump into each other and + # generate unexpected behaviours. if self._shouldResolve(key, property_name, context): current_thread = threading.current_thread() self._resolving_settings[current_thread.name].add(key) From 6ffe0a9083029d6f78003bd81b2a5b78d5de33ca Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 13 Aug 2018 14:47:25 +0200 Subject: [PATCH 158/243] Fix indent and typo --- plugins/UM3NetworkPrinting/PrinterVideoStream.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/UM3NetworkPrinting/PrinterVideoStream.qml b/plugins/UM3NetworkPrinting/PrinterVideoStream.qml index e34924ba88..68758e095e 100644 --- a/plugins/UM3NetworkPrinting/PrinterVideoStream.qml +++ b/plugins/UM3NetworkPrinting/PrinterVideoStream.qml @@ -16,9 +16,9 @@ Item MouseArea { - anchors.fill: parent - onClicked: OutputDevice.setActivePrinter(null) - z: 0 + anchors.fill: parent + onClicked: OutputDevice.setActivePrinter(null) + z: 0 } Button @@ -28,7 +28,7 @@ Item anchors.bottomMargin: UM.Theme.getSize("default_margin").width anchors.right: cameraImage.right - // TODO: Harcoded sizes + // TODO: Hardcoded sizes width: 20 * screenScaleFactor height: 20 * screenScaleFactor From f91254c7c05faa7451a8dcd217b81eb0ccf1c028 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 13 Aug 2018 15:27:01 +0200 Subject: [PATCH 159/243] Fix typo in comment --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index b1a3dadc8e..78986d82ee 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -631,7 +631,7 @@ class CuraApplication(QtApplication): # Cura has multiple locations where instance containers need to be saved, so we need to handle this differently. def saveSettings(self): if not self.started or not self._save_data_enabled: - # Do not do saving during application start or when data should not be safed on quit. + # Do not do saving during application start or when data should not be saved on quit. return ContainerRegistry.getInstance().saveDirtyContainers() self.savePreferences() From 848e99a4ba46e11ed9acf498ab105ad1fce15b40 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 13 Aug 2018 17:04:13 +0200 Subject: [PATCH 160/243] Don't show the hint message when the buildplate selector is shown. Contributes to CURA-5570. --- resources/qml/SidebarHeader.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index 4bc0e8b2ef..6ee33dd2f2 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -533,6 +533,7 @@ Column rightMargin: UM.Theme.getSize("sidebar_margin").width } + // TODO This was added to replace the buildplate selector. Remove this component when the feature is ready Label { id: materialCompatibilityLabel @@ -542,7 +543,7 @@ Column text: catalog.i18nc("@label", "Use glue with this material combination") font: UM.Theme.getFont("very_small") color: UM.Theme.getColor("text") - visible: buildplateCompatibilityError || buildplateCompatibilityWarning + visible: CuraSDKVersion == "dev" ? false : buildplateCompatibilityError || buildplateCompatibilityWarning wrapMode: Text.WordWrap opacity: 0.5 } From db7f1242cd0cd028219f5ef8dfbdbc0ec039d8fb Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 14 Aug 2018 10:41:38 +0200 Subject: [PATCH 161/243] Fix some unit tests. Add fixtures to the conftest file and clean-up the code a bit. Contributes to CURA-5628 --- tests/Settings/TestCuraContainerRegistry.py | 62 +++----------------- tests/Settings/TestExtruderStack.py | 58 +++++-------------- tests/Settings/TestGlobalStack.py | 2 +- tests/Settings/conftest.py | 19 +++++++ tests/TestArrange.py | 6 +- tests/TestMachineAction.py | 63 ++++++++++----------- tests/TestProfileRequirements.py | 4 ++ tests/conftest.py | 38 +++++++++++++ 8 files changed, 118 insertions(+), 134 deletions(-) create mode 100644 tests/Settings/conftest.py create mode 100644 tests/conftest.py diff --git a/tests/Settings/TestCuraContainerRegistry.py b/tests/Settings/TestCuraContainerRegistry.py index 38b2e0f6ea..dd78f2fd68 100644 --- a/tests/Settings/TestCuraContainerRegistry.py +++ b/tests/Settings/TestCuraContainerRegistry.py @@ -1,61 +1,14 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. import os #To find the directory with test files and find the test files. -import pytest #This module contains unit tests. -import shutil #To copy files to make a temporary file. import unittest.mock #To mock and monkeypatch stuff. -import urllib.parse -import copy -import cura.CuraApplication -from cura.Settings.CuraContainerRegistry import CuraContainerRegistry #The class we're testing. from cura.Settings.ExtruderStack import ExtruderStack #Testing for returning the correct types of stacks. from cura.Settings.GlobalStack import GlobalStack #Testing for returning the correct types of stacks. -from UM.Resources import Resources #Mocking some functions of this. import UM.Settings.InstanceContainer #Creating instance containers to register. import UM.Settings.ContainerRegistry #Making empty container stacks. import UM.Settings.ContainerStack #Setting the container registry here properly. -from UM.Settings.DefinitionContainer import DefinitionContainer -from UM.Settings.ContainerRegistry import ContainerRegistry - -def creteEmptyContainers(): - empty_container = ContainerRegistry.getInstance().getEmptyInstanceContainer() - empty_variant_container = copy.deepcopy(empty_container) - empty_variant_container.setMetaDataEntry("id", "empty_variant") - empty_variant_container.setMetaDataEntry("type", "variant") - ContainerRegistry.getInstance().addContainer(empty_variant_container) - - empty_material_container = copy.deepcopy(empty_container) - empty_material_container.setMetaDataEntry("id", "empty_material") - empty_material_container.setMetaDataEntry("type", "material") - ContainerRegistry.getInstance().addContainer(empty_material_container) - - empty_quality_container = copy.deepcopy(empty_container) - empty_quality_container.setMetaDataEntry("id", "empty_quality") - empty_quality_container.setName("Not Supported") - empty_quality_container.setMetaDataEntry("quality_type", "not_supported") - empty_quality_container.setMetaDataEntry("type", "quality") - empty_quality_container.setMetaDataEntry("supported", False) - ContainerRegistry.getInstance().addContainer(empty_quality_container) - - empty_quality_changes_container = copy.deepcopy(empty_container) - empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes") - empty_quality_changes_container.setMetaDataEntry("type", "quality_changes") - ContainerRegistry.getInstance().addContainer(empty_quality_changes_container) - -## Gives a fresh CuraContainerRegistry instance. -@pytest.fixture() -def container_registry(): - registry = CuraContainerRegistry() - UM.Settings.InstanceContainer.setContainerRegistry(registry) - UM.Settings.ContainerStack.setContainerRegistry(registry) - return registry - -## Gives an arbitrary definition container. -@pytest.fixture() -def definition_container(): - return DefinitionContainer(container_id = "Test Definition") def teardown(): #If the temporary file for the legacy file rename test still exists, remove it. @@ -65,10 +18,9 @@ def teardown(): ## Tests whether addContainer properly converts to ExtruderStack. def test_addContainerExtruderStack(container_registry, definition_container): - creteEmptyContainers() container_registry.addContainer(definition_container) - container_stack = UM.Settings.ContainerStack.ContainerStack(stack_id = "Test Container Stack") #A container we're going to convert. + container_stack = UM.Settings.ContainerStack.ContainerStack(stack_id = "Test Extruder Stack") #A container we're going to convert. container_stack.setMetaDataEntry("type", "extruder_train") #This is now an extruder train. container_stack.insertContainer(0, definition_container) #Add a definition to it so it doesn't complain. @@ -84,7 +36,7 @@ def test_addContainerExtruderStack(container_registry, definition_container): def test_addContainerGlobalStack(container_registry, definition_container): container_registry.addContainer(definition_container) - container_stack = UM.Settings.ContainerStack.ContainerStack(stack_id = "Test Container Stack") #A container we're going to convert. + container_stack = UM.Settings.ContainerStack.ContainerStack(stack_id = "Test Global Stack") #A container we're going to convert. container_stack.setMetaDataEntry("type", "machine") #This is now a global stack. container_stack.insertContainer(0, definition_container) #Must have a definition. @@ -101,7 +53,7 @@ def test_addContainerGoodSettingVersion(container_registry, definition_container definition_container.getMetaData()["setting_version"] = CuraApplication.SettingVersion container_registry.addContainer(definition_container) - instance = UM.Settings.InstanceContainer.InstanceContainer(container_id = "Test Instance") + instance = UM.Settings.InstanceContainer.InstanceContainer(container_id = "Test Instance Right Version") instance.setMetaDataEntry("setting_version", CuraApplication.SettingVersion) instance.setDefinition(definition_container.getId()) @@ -116,7 +68,7 @@ def test_addContainerNoSettingVersion(container_registry, definition_container): definition_container.getMetaData()["setting_version"] = CuraApplication.SettingVersion container_registry.addContainer(definition_container) - instance = UM.Settings.InstanceContainer.InstanceContainer(container_id = "Test Instance") + instance = UM.Settings.InstanceContainer.InstanceContainer(container_id = "Test Instance No Version") #Don't add setting_version metadata. instance.setDefinition(definition_container.getId()) @@ -131,7 +83,7 @@ def test_addContainerBadSettingVersion(container_registry, definition_container) definition_container.getMetaData()["setting_version"] = CuraApplication.SettingVersion container_registry.addContainer(definition_container) - instance = UM.Settings.InstanceContainer.InstanceContainer(container_id = "Test Instance") + instance = UM.Settings.InstanceContainer.InstanceContainer(container_id = "Test Instance Wrong Version") instance.setMetaDataEntry("setting_version", 9001) #Wrong version! instance.setDefinition(definition_container.getId()) @@ -174,4 +126,4 @@ def test_addContainerBadSettingVersion(container_registry, definition_container) # assert type(container) == output_class # break # else: -# assert False #Container stack with specified ID was not loaded. \ No newline at end of file +# assert False #Container stack with specified ID was not loaded. diff --git a/tests/Settings/TestExtruderStack.py b/tests/Settings/TestExtruderStack.py index 7c463fb9be..a19f99571d 100644 --- a/tests/Settings/TestExtruderStack.py +++ b/tests/Settings/TestExtruderStack.py @@ -1,9 +1,8 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. import pytest #This module contains automated tests. import unittest.mock #For the mocking and monkeypatching functionality. -import copy import cura.CuraApplication import UM.Settings.ContainerRegistry #To create empty instance containers. @@ -14,29 +13,27 @@ import cura.Settings.ExtruderStack #The module we're testing. from cura.Settings.Exceptions import InvalidContainerError, InvalidOperationError #To check whether the correct exceptions are raised. from cura.Settings.ExtruderManager import ExtruderManager -from UM.Settings.ContainerRegistry import ContainerRegistry from cura.Settings.GlobalStack import GlobalStack ## Fake container registry that always provides all containers you ask of. -@pytest.yield_fixture() -def container_registry(): - registry = unittest.mock.MagicMock() - registry.return_value = unittest.mock.NonCallableMagicMock() - registry.findInstanceContainers = lambda *args, registry = registry, **kwargs: [registry.return_value] - registry.findDefinitionContainers = lambda *args, registry = registry, **kwargs: [registry.return_value] - - UM.Settings.ContainerRegistry.ContainerRegistry._ContainerRegistry__instance = registry - UM.Settings.ContainerStack._containerRegistry = registry - - yield registry - - UM.Settings.ContainerRegistry.ContainerRegistry._ContainerRegistry__instance = None - UM.Settings.ContainerStack._containerRegistry = None +# @pytest.yield_fixture() +# def container_registry(): +# registry = unittest.mock.MagicMock() +# registry.return_value = unittest.mock.NonCallableMagicMock() +# registry.findInstanceContainers = lambda *args, registry = registry, **kwargs: [registry.return_value] +# registry.findDefinitionContainers = lambda *args, registry = registry, **kwargs: [registry.return_value] +# +# UM.Settings.ContainerRegistry.ContainerRegistry._ContainerRegistry__instance = registry +# UM.Settings.ContainerStack._containerRegistry = registry +# +# yield registry +# +# UM.Settings.ContainerRegistry.ContainerRegistry._ContainerRegistry__instance = None +# UM.Settings.ContainerStack._containerRegistry = None ## An empty extruder stack to test with. @pytest.fixture() def extruder_stack() -> cura.Settings.ExtruderStack.ExtruderStack: - creteEmptyContainers() return cura.Settings.ExtruderStack.ExtruderStack("TestStack") ## Gets an instance container with a specified container type. @@ -48,31 +45,6 @@ def getInstanceContainer(container_type) -> InstanceContainer: container.setMetaDataEntry("type", container_type) return container -def creteEmptyContainers(): - empty_container = ContainerRegistry.getInstance().getEmptyInstanceContainer() - empty_variant_container = copy.deepcopy(empty_container) - empty_variant_container.setMetaDataEntry("id", "empty_variant") - empty_variant_container.setMetaDataEntry("type", "variant") - ContainerRegistry.getInstance().addContainer(empty_variant_container) - - empty_material_container = copy.deepcopy(empty_container) - empty_material_container.setMetaDataEntry("id", "empty_material") - empty_material_container.setMetaDataEntry("type", "material") - ContainerRegistry.getInstance().addContainer(empty_material_container) - - empty_quality_container = copy.deepcopy(empty_container) - empty_quality_container.setMetaDataEntry("id", "empty_quality") - empty_quality_container.setName("Not Supported") - empty_quality_container.setMetaDataEntry("quality_type", "not_supported") - empty_quality_container.setMetaDataEntry("type", "quality") - empty_quality_container.setMetaDataEntry("supported", False) - ContainerRegistry.getInstance().addContainer(empty_quality_container) - - empty_quality_changes_container = copy.deepcopy(empty_container) - empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes") - empty_quality_changes_container.setMetaDataEntry("type", "quality_changes") - ContainerRegistry.getInstance().addContainer(empty_quality_changes_container) - class DefinitionContainerSubClass(DefinitionContainer): def __init__(self): super().__init__(container_id = "SubDefinitionContainer") diff --git a/tests/Settings/TestGlobalStack.py b/tests/Settings/TestGlobalStack.py index 3e74e3e575..1b583a9c98 100755 --- a/tests/Settings/TestGlobalStack.py +++ b/tests/Settings/TestGlobalStack.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. import pytest #This module contains unit tests. diff --git a/tests/Settings/conftest.py b/tests/Settings/conftest.py new file mode 100644 index 0000000000..1ca3a865e9 --- /dev/null +++ b/tests/Settings/conftest.py @@ -0,0 +1,19 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Uranium is released under the terms of the LGPLv3 or higher. + +# The purpose of this class is to create fixtures or methods that can be shared among all settings tests. + +import pytest +import copy + +from UM.Settings.DefinitionContainer import DefinitionContainer #To provide definition containers in the registry fixtures. + +# Returns the CuraContainerRegistry instance with some empty containers. +@pytest.fixture() +def container_registry(application): + return application.getContainerRegistry() + +# Gives an arbitrary definition container. +@pytest.fixture() +def definition_container(): + return DefinitionContainer(container_id = "Test Definition") \ No newline at end of file diff --git a/tests/TestArrange.py b/tests/TestArrange.py index f383fc0cf3..7de3ec1d8d 100755 --- a/tests/TestArrange.py +++ b/tests/TestArrange.py @@ -1,9 +1,11 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + import numpy from cura.Arranging.Arrange import Arrange from cura.Arranging.ShapeArray import ShapeArray - ## Triangle of area 12 def gimmeTriangle(): return numpy.array([[-3, 1], [3, 1], [0, -3]], dtype=numpy.int32) @@ -102,7 +104,7 @@ def test_centerFirst_rectangular(): ## Test centerFirst -def test_centerFirst_rectangular(): +def test_centerFirst_rectangular2(): ar = Arrange(10, 20, 5, 10, scale = 1) ar.centerFirst() print(ar._priority) diff --git a/tests/TestMachineAction.py b/tests/TestMachineAction.py index 0118874a0b..7121fcc218 100755 --- a/tests/TestMachineAction.py +++ b/tests/TestMachineAction.py @@ -1,11 +1,10 @@ -#Todo: Write tests +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. import pytest -# QtApplication needs to be imported first to prevent import errors. -from UM.Qt.QtApplication import QtApplication from cura.MachineAction import MachineAction -from cura.MachineActionManager import MachineActionManager, NotUniqueMachineActionError, UnknownMachineActionError +from cura.MachineActionManager import NotUniqueMachineActionError, UnknownMachineActionError class Machine: def __init__(self, key = ""): @@ -14,66 +13,64 @@ class Machine: def getKey(self): return self._key -def test_addMachineAction(): - - machine_manager = MachineActionManager() +def test_addMachineAction(machine_action_manager): test_action = MachineAction(key = "test_action") test_action_2 = MachineAction(key = "test_action_2") test_machine = Machine("test_machine") - machine_manager.addMachineAction(test_action) - machine_manager.addMachineAction(test_action_2) + machine_action_manager.addMachineAction(test_action) + machine_action_manager.addMachineAction(test_action_2) - assert machine_manager.getMachineAction("test_action") == test_action - assert machine_manager.getMachineAction("key_that_doesnt_exist") is None + assert machine_action_manager.getMachineAction("test_action") == test_action + assert machine_action_manager.getMachineAction("key_that_doesnt_exist") is None # Adding the same machine action is not allowed. with pytest.raises(NotUniqueMachineActionError): - machine_manager.addMachineAction(test_action) + machine_action_manager.addMachineAction(test_action) # Check that the machine has no supported actions yet. - assert machine_manager.getSupportedActions(test_machine) == list() + assert machine_action_manager.getSupportedActions(test_machine) == list() # Check if adding a supported action works. - machine_manager.addSupportedAction(test_machine, "test_action") - assert machine_manager.getSupportedActions(test_machine) == [test_action, ] + machine_action_manager.addSupportedAction(test_machine, "test_action") + assert machine_action_manager.getSupportedActions(test_machine) == [test_action, ] # Check that adding a unknown action doesn't change anything. - machine_manager.addSupportedAction(test_machine, "key_that_doesnt_exist") - assert machine_manager.getSupportedActions(test_machine) == [test_action, ] + machine_action_manager.addSupportedAction(test_machine, "key_that_doesnt_exist") + assert machine_action_manager.getSupportedActions(test_machine) == [test_action, ] # Check if adding multiple supported actions works. - machine_manager.addSupportedAction(test_machine, "test_action_2") - assert machine_manager.getSupportedActions(test_machine) == [test_action, test_action_2] + machine_action_manager.addSupportedAction(test_machine, "test_action_2") + assert machine_action_manager.getSupportedActions(test_machine) == [test_action, test_action_2] # Check that the machine has no required actions yet. - assert machine_manager.getRequiredActions(test_machine) == set() + assert machine_action_manager.getRequiredActions(test_machine) == set() ## Ensure that only known actions can be added. with pytest.raises(UnknownMachineActionError): - machine_manager.addRequiredAction(test_machine, "key_that_doesnt_exist") + machine_action_manager.addRequiredAction(test_machine, "key_that_doesnt_exist") ## Check if adding single required action works - machine_manager.addRequiredAction(test_machine, "test_action") - assert machine_manager.getRequiredActions(test_machine) == [test_action, ] + machine_action_manager.addRequiredAction(test_machine, "test_action") + assert machine_action_manager.getRequiredActions(test_machine) == [test_action, ] # Check if adding multiple required actions works. - machine_manager.addRequiredAction(test_machine, "test_action_2") - assert machine_manager.getRequiredActions(test_machine) == [test_action, test_action_2] + machine_action_manager.addRequiredAction(test_machine, "test_action_2") + assert machine_action_manager.getRequiredActions(test_machine) == [test_action, test_action_2] # Ensure that firstStart actions are empty by default. - assert machine_manager.getFirstStartActions(test_machine) == [] + assert machine_action_manager.getFirstStartActions(test_machine) == [] # Check if adding multiple (the same) actions to first start actions work. - machine_manager.addFirstStartAction(test_machine, "test_action") - machine_manager.addFirstStartAction(test_machine, "test_action") - assert machine_manager.getFirstStartActions(test_machine) == [test_action, test_action] + machine_action_manager.addFirstStartAction(test_machine, "test_action") + machine_action_manager.addFirstStartAction(test_machine, "test_action") + assert machine_action_manager.getFirstStartActions(test_machine) == [test_action, test_action] # Check if inserting an action works - machine_manager.addFirstStartAction(test_machine, "test_action_2", index = 1) - assert machine_manager.getFirstStartActions(test_machine) == [test_action, test_action_2, test_action] + machine_action_manager.addFirstStartAction(test_machine, "test_action_2", index = 1) + assert machine_action_manager.getFirstStartActions(test_machine) == [test_action, test_action_2, test_action] # Check that adding a unknown action doesn't change anything. - machine_manager.addFirstStartAction(test_machine, "key_that_doesnt_exist", index = 1) - assert machine_manager.getFirstStartActions(test_machine) == [test_action, test_action_2, test_action] + machine_action_manager.addFirstStartAction(test_machine, "key_that_doesnt_exist", index = 1) + assert machine_action_manager.getFirstStartActions(test_machine) == [test_action, test_action_2, test_action] diff --git a/tests/TestProfileRequirements.py b/tests/TestProfileRequirements.py index f75ca9da8d..97641fe753 100644 --- a/tests/TestProfileRequirements.py +++ b/tests/TestProfileRequirements.py @@ -1,3 +1,6 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + import configparser #To read the profiles. import os #To join paths. import pytest @@ -11,6 +14,7 @@ import pytest # often that we updated the variants for the UM3 but forgot about the UM3E. @pytest.mark.parametrize("um3_file, um3e_file", [ #List the corresponding files below. + ("ultimaker3_aa0.25.inst.cfg", "ultimaker3_extended_aa0.25.inst.cfg"), ("ultimaker3_aa0.8.inst.cfg", "ultimaker3_extended_aa0.8.inst.cfg"), ("ultimaker3_aa04.inst.cfg", "ultimaker3_extended_aa04.inst.cfg"), ("ultimaker3_bb0.8.inst.cfg", "ultimaker3_extended_bb0.8.inst.cfg"), diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000000..32e2dc621f --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,38 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +# The purpose of this class is to create fixtures or methods that can be shared among all tests. + +import pytest +from UM.Qt.QtApplication import QtApplication #QTApplication import is required, even though it isn't used. +from cura.CuraApplication import CuraApplication +from cura.MachineActionManager import MachineActionManager + +# Create a CuraApplication object that will be shared among all tests. It needs to be initialized. +# Since we need to use it more that once, we create the application the first time and use its instance afterwards. +@pytest.fixture() +def application() -> CuraApplication: + application = CuraApplication.getInstance() + if application is None: + application = CuraApplication() + application.initialize() + return application + +# Returns a MachineActionManager instance. +@pytest.fixture() +def machine_action_manager(application) -> MachineActionManager: + return application.getMachineActionManager() + +# @pytest.fixture() +# def plugin_registry(application): +# PluginRegistry._PluginRegistry__instance = None +# plugin_registry = PluginRegistry(application) +# plugin_registry._plugin_locations = [] # Clear pre-defined plugin locations +# return plugin_registry +# +# @pytest.fixture() +# def upgrade_manager(application): +# VersionUpgradeManager._VersionUpgradeManager__instance = None +# upgrade_manager = VersionUpgradeManager(application) +# return upgrade_manager + From 5869644b0be12cc35f57f53012ae84bb58c79f1d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 14 Aug 2018 12:02:11 +0200 Subject: [PATCH 162/243] Fix typo --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 78986d82ee..df25522be3 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -123,7 +123,7 @@ except ImportError: CuraVersion = "master" # [CodeStyle: Reflecting imported value] CuraBuildType = "" CuraDebugMode = False - CuraSDKVerion = "" + CuraSDKVersion = "" class CuraApplication(QtApplication): From c8af4f45cedf1e3ae8e56df1fdbf4169a0fe6430 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 14 Aug 2018 13:25:56 +0200 Subject: [PATCH 163/243] Decouple the creation of the stack containers from the process that add them to the container registry, that is done in CuraApplication. That allow us to have access to the empty containers and so we can unit test easily without mocking up stuff. Contributes to CURA-5628. --- cura/CuraApplication.py | 46 ++++++++--------------------- cura/CuraEmptyInstanceContainers.py | 29 ++++++++++++++++++ cura/Settings/CuraContainerStack.py | 16 +++++----- 3 files changed, 49 insertions(+), 42 deletions(-) create mode 100644 cura/CuraEmptyInstanceContainers.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 78986d82ee..24043b83fe 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1,11 +1,10 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -import copy import os import sys import time -from typing import cast, TYPE_CHECKING, Optional +from typing import cast, TYPE_CHECKING import numpy @@ -105,6 +104,7 @@ from cura.Settings.ExtrudersModel import ExtrudersModel from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler from cura.Settings.ContainerManager import ContainerManager from cura.Settings.SidebarCustomMenuItemsModel import SidebarCustomMenuItemsModel +import cura.CuraEmptyInstanceContainers from cura.ObjectsModel import ObjectsModel @@ -368,42 +368,20 @@ class CuraApplication(QtApplication): # Add empty variant, material and quality containers. # Since they are empty, they should never be serialized and instead just programmatically created. # We need them to simplify the switching between materials. - empty_container = self._container_registry.getEmptyInstanceContainer() - self.empty_container = empty_container + self._container_registry.addContainer(cura.CuraEmptyInstanceContainers.empty_definition_changes_container) + self.empty_definition_changes_container = cura.CuraEmptyInstanceContainers.empty_definition_changes_container - empty_definition_changes_container = copy.deepcopy(empty_container) - empty_definition_changes_container.setMetaDataEntry("id", "empty_definition_changes") - empty_definition_changes_container.setMetaDataEntry("type", "definition_changes") - self._container_registry.addContainer(empty_definition_changes_container) - self.empty_definition_changes_container = empty_definition_changes_container + self._container_registry.addContainer(cura.CuraEmptyInstanceContainers.empty_variant_container) + self.empty_variant_container = cura.CuraEmptyInstanceContainers.empty_variant_container - empty_variant_container = copy.deepcopy(empty_container) - empty_variant_container.setMetaDataEntry("id", "empty_variant") - empty_variant_container.setMetaDataEntry("type", "variant") - self._container_registry.addContainer(empty_variant_container) - self.empty_variant_container = empty_variant_container + self._container_registry.addContainer(cura.CuraEmptyInstanceContainers.empty_material_container) + self.empty_material_container = cura.CuraEmptyInstanceContainers.empty_material_container - empty_material_container = copy.deepcopy(empty_container) - empty_material_container.setMetaDataEntry("id", "empty_material") - empty_material_container.setMetaDataEntry("type", "material") - self._container_registry.addContainer(empty_material_container) - self.empty_material_container = empty_material_container + self._container_registry.addContainer(cura.CuraEmptyInstanceContainers.empty_quality_container) + self.empty_quality_container = cura.CuraEmptyInstanceContainers.empty_quality_container - empty_quality_container = copy.deepcopy(empty_container) - empty_quality_container.setMetaDataEntry("id", "empty_quality") - empty_quality_container.setName("Not Supported") - empty_quality_container.setMetaDataEntry("quality_type", "not_supported") - empty_quality_container.setMetaDataEntry("type", "quality") - empty_quality_container.setMetaDataEntry("supported", False) - self._container_registry.addContainer(empty_quality_container) - self.empty_quality_container = empty_quality_container - - empty_quality_changes_container = copy.deepcopy(empty_container) - empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes") - empty_quality_changes_container.setMetaDataEntry("type", "quality_changes") - empty_quality_changes_container.setMetaDataEntry("quality_type", "not_supported") - self._container_registry.addContainer(empty_quality_changes_container) - self.empty_quality_changes_container = empty_quality_changes_container + self._container_registry.addContainer(cura.CuraEmptyInstanceContainers.empty_quality_changes_container) + self.empty_quality_changes_container = cura.CuraEmptyInstanceContainers.empty_quality_changes_container # Initializes the version upgrade manager with by providing the paths for each resource type and the latest # versions. diff --git a/cura/CuraEmptyInstanceContainers.py b/cura/CuraEmptyInstanceContainers.py new file mode 100644 index 0000000000..3f5d3e7c59 --- /dev/null +++ b/cura/CuraEmptyInstanceContainers.py @@ -0,0 +1,29 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from UM.Settings.EmptyInstanceContainer import empty_container +import copy + +empty_definition_changes_container = copy.deepcopy(empty_container) +empty_definition_changes_container.setMetaDataEntry("id", "empty_definition_changes") +empty_definition_changes_container.setMetaDataEntry("type", "definition_changes") + +empty_variant_container = copy.deepcopy(empty_container) +empty_variant_container.setMetaDataEntry("id", "empty_variant") +empty_variant_container.setMetaDataEntry("type", "variant") + +empty_material_container = copy.deepcopy(empty_container) +empty_material_container.setMetaDataEntry("id", "empty_material") +empty_material_container.setMetaDataEntry("type", "material") + +empty_quality_container = copy.deepcopy(empty_container) +empty_quality_container.setMetaDataEntry("id", "empty_quality") +empty_quality_container.setName("Not Supported") +empty_quality_container.setMetaDataEntry("quality_type", "not_supported") +empty_quality_container.setMetaDataEntry("type", "quality") +empty_quality_container.setMetaDataEntry("supported", False) + +empty_quality_changes_container = copy.deepcopy(empty_container) +empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes") +empty_quality_changes_container.setMetaDataEntry("type", "quality_changes") +empty_quality_changes_container.setMetaDataEntry("quality_type", "not_supported") diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py index bd3380dfb2..dabed97011 100755 --- a/cura/Settings/CuraContainerStack.py +++ b/cura/Settings/CuraContainerStack.py @@ -1,7 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Any, cast, List, Optional, Union +from typing import Any, cast, List, Optional from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject from UM.Application import Application @@ -13,6 +13,8 @@ from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.Interfaces import ContainerInterface, DefinitionContainerInterface +from UM.Settings.EmptyInstanceContainer import empty_container +from cura import CuraEmptyInstanceContainers from . import Exceptions @@ -39,14 +41,12 @@ class CuraContainerStack(ContainerStack): def __init__(self, container_id: str) -> None: super().__init__(container_id) - self._container_registry = ContainerRegistry.getInstance() #type: ContainerRegistry + self._empty_instance_container = empty_container #type: InstanceContainer - self._empty_instance_container = self._container_registry.getEmptyInstanceContainer() #type: InstanceContainer - - self._empty_quality_changes = self._container_registry.findInstanceContainers(id = "empty_quality_changes")[0] #type: InstanceContainer - self._empty_quality = self._container_registry.findInstanceContainers(id = "empty_quality")[0] #type: InstanceContainer - self._empty_material = self._container_registry.findInstanceContainers(id = "empty_material")[0] #type: InstanceContainer - self._empty_variant = self._container_registry.findInstanceContainers(id = "empty_variant")[0] #type: InstanceContainer + self._empty_quality_changes = CuraEmptyInstanceContainers.empty_quality_changes_container #type: InstanceContainer + self._empty_quality = CuraEmptyInstanceContainers.empty_quality_container #type: InstanceContainer + self._empty_material = CuraEmptyInstanceContainers.empty_material_container #type: InstanceContainer + self._empty_variant = CuraEmptyInstanceContainers.empty_variant_container #type: InstanceContainer self._containers = [self._empty_instance_container for i in range(len(_ContainerIndexes.IndexTypeMap))] #type: List[ContainerInterface] self._containers[_ContainerIndexes.QualityChanges] = self._empty_quality_changes From 1364370ede4ecbe71c077b56371a55971639a9fa Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 14 Aug 2018 13:49:37 +0200 Subject: [PATCH 164/243] Fix global stack tests. Contributes to CURA-5628. --- tests/Settings/TestGlobalStack.py | 117 +++++++----------------------- tests/Settings/conftest.py | 27 ++++++- tests/conftest.py | 17 +---- 3 files changed, 50 insertions(+), 111 deletions(-) diff --git a/tests/Settings/TestGlobalStack.py b/tests/Settings/TestGlobalStack.py index 1b583a9c98..9d52257245 100755 --- a/tests/Settings/TestGlobalStack.py +++ b/tests/Settings/TestGlobalStack.py @@ -3,41 +3,16 @@ import pytest #This module contains unit tests. import unittest.mock #To monkeypatch some mocks in place of dependencies. -import copy -import cura.CuraApplication -import cura.Settings.GlobalStack #The module we're testing. import cura.Settings.CuraContainerStack #To get the list of container types. -from cura.Settings.Exceptions import TooManyExtrudersError, InvalidContainerError, InvalidOperationError #To test raising these errors. +from cura.Settings.Exceptions import InvalidContainerError, InvalidOperationError #To test raising these errors. from UM.Settings.DefinitionContainer import DefinitionContainer #To test against the class DefinitionContainer. from UM.Settings.InstanceContainer import InstanceContainer #To test against the class InstanceContainer. from UM.Settings.SettingInstance import InstanceState +from UM.Settings.EmptyInstanceContainer import empty_container import UM.Settings.ContainerRegistry import UM.Settings.ContainerStack import UM.Settings.SettingDefinition #To add settings to the definition. -from UM.Settings.ContainerRegistry import ContainerRegistry - -## Fake container registry that always provides all containers you ask of. -@pytest.yield_fixture() -def container_registry(): - registry = unittest.mock.MagicMock() - registry.return_value = unittest.mock.NonCallableMagicMock() - registry.findInstanceContainers = lambda *args, registry = registry, **kwargs: [registry.return_value] - registry.findDefinitionContainers = lambda *args, registry = registry, **kwargs: [registry.return_value] - - UM.Settings.ContainerRegistry.ContainerRegistry._ContainerRegistry__instance = registry - UM.Settings.ContainerStack._containerRegistry = registry - - yield registry - - UM.Settings.ContainerRegistry.ContainerRegistry._ContainerRegistry__instance = None - UM.Settings.ContainerStack._containerRegistry = None - -#An empty global stack to test with. -@pytest.fixture() -def global_stack() -> cura.Settings.GlobalStack.GlobalStack: - creteEmptyContainers() - return cura.Settings.GlobalStack.GlobalStack("TestStack") ## Gets an instance container with a specified container type. # @@ -48,31 +23,6 @@ def getInstanceContainer(container_type) -> InstanceContainer: container.setMetaDataEntry("type", container_type) return container -def creteEmptyContainers(): - empty_container = ContainerRegistry.getInstance().getEmptyInstanceContainer() - empty_variant_container = copy.deepcopy(empty_container) - empty_variant_container.setMetaDataEntry("id", "empty_variant") - empty_variant_container.setMetaDataEntry("type", "variant") - ContainerRegistry.getInstance().addContainer(empty_variant_container) - - empty_material_container = copy.deepcopy(empty_container) - empty_material_container.setMetaDataEntry("id", "empty_material") - empty_material_container.setMetaDataEntry("type", "material") - ContainerRegistry.getInstance().addContainer(empty_material_container) - - empty_quality_container = copy.deepcopy(empty_container) - empty_quality_container.setMetaDataEntry("id", "empty_quality") - empty_quality_container.setName("Not Supported") - empty_quality_container.setMetaDataEntry("quality_type", "not_supported") - empty_quality_container.setMetaDataEntry("type", "quality") - empty_quality_container.setMetaDataEntry("supported", False) - ContainerRegistry.getInstance().addContainer(empty_quality_container) - - empty_quality_changes_container = copy.deepcopy(empty_container) - empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes") - empty_quality_changes_container.setMetaDataEntry("type", "quality_changes") - ContainerRegistry.getInstance().addContainer(empty_quality_changes_container) - class DefinitionContainerSubClass(DefinitionContainer): def __init__(self): super().__init__(container_id = "SubDefinitionContainer") @@ -241,23 +191,22 @@ def test_constrainVariantInvalid(container, global_stack): def test_constrainDefinitionValid(container, global_stack): global_stack.definition = container #Should not give an error. -## Tests whether deserialising completes the missing containers with empty -# ones. -@pytest.mark.skip #The test currently fails because the definition container doesn't have a category, which is wrong but we don't have time to refactor that right now. -def test_deserializeCompletesEmptyContainers(global_stack: cura.Settings.GlobalStack): - global_stack._containers = [DefinitionContainer(container_id = "definition")] #Set the internal state of this stack manually. +## Tests whether deserialising completes the missing containers with empty ones. The initial containers are just the +# definition and the definition_changes (that cannot be empty after CURA-5281) +def test_deserializeCompletesEmptyContainers(global_stack): + global_stack._containers = [DefinitionContainer(container_id = "definition"), global_stack.definitionChanges] #Set the internal state of this stack manually. with unittest.mock.patch("UM.Settings.ContainerStack.ContainerStack.deserialize", unittest.mock.MagicMock()): #Prevent calling super().deserialize. global_stack.deserialize("") assert len(global_stack.getContainers()) == len(cura.Settings.CuraContainerStack._ContainerIndexes.IndexTypeMap) #Needs a slot for every type. for container_type_index in cura.Settings.CuraContainerStack._ContainerIndexes.IndexTypeMap: - if container_type_index == cura.Settings.CuraContainerStack._ContainerIndexes.Definition: #We're not checking the definition. + if container_type_index in \ + (cura.Settings.CuraContainerStack._ContainerIndexes.Definition, cura.Settings.CuraContainerStack._ContainerIndexes.DefinitionChanges): #We're not checking the definition or definition_changes continue - assert global_stack.getContainer(container_type_index).getId() == "empty" #All others need to be empty. + assert global_stack.getContainer(container_type_index) == empty_container #All others need to be empty. -## Tests whether an instance container with the wrong type gets removed when -# deserialising. +## Tests whether an instance container with the wrong type gets removed when deserialising. def test_deserializeRemovesWrongInstanceContainer(global_stack): global_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Quality] = getInstanceContainer(container_type = "wrong type") global_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Definition] = DefinitionContainer(container_id = "some definition") @@ -267,8 +216,7 @@ def test_deserializeRemovesWrongInstanceContainer(global_stack): assert global_stack.quality == global_stack._empty_instance_container #Replaced with empty. -## Tests whether a container with the wrong class gets removed when -# deserialising. +## Tests whether a container with the wrong class gets removed when deserialising. def test_deserializeRemovesWrongContainerClass(global_stack): global_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Quality] = DefinitionContainer(container_id = "wrong class") global_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Definition] = DefinitionContainer(container_id = "some definition") @@ -278,8 +226,7 @@ def test_deserializeRemovesWrongContainerClass(global_stack): assert global_stack.quality == global_stack._empty_instance_container #Replaced with empty. -## Tests whether an instance container in the definition spot results in an -# error. +## Tests whether an instance container in the definition spot results in an error. def test_deserializeWrongDefinitionClass(global_stack): global_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Definition] = getInstanceContainer(container_type = "definition") #Correct type but wrong class. @@ -287,8 +234,7 @@ def test_deserializeWrongDefinitionClass(global_stack): with pytest.raises(UM.Settings.ContainerStack.InvalidContainerStackError): #Must raise an error that there is no definition container. global_stack.deserialize("") -## Tests whether an instance container with the wrong type is moved into the -# correct slot by deserialising. +## Tests whether an instance container with the wrong type is moved into the correct slot by deserialising. def test_deserializeMoveInstanceContainer(global_stack): global_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Quality] = getInstanceContainer(container_type = "material") #Not in the correct spot. global_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Definition] = DefinitionContainer(container_id = "some definition") @@ -296,25 +242,20 @@ def test_deserializeMoveInstanceContainer(global_stack): with unittest.mock.patch("UM.Settings.ContainerStack.ContainerStack.deserialize", unittest.mock.MagicMock()): #Prevent calling super().deserialize. global_stack.deserialize("") - assert global_stack.quality.getId() == "empty" - assert global_stack.material.getId() != "empty" + assert global_stack.quality == empty_container + assert global_stack.material != empty_container -## Tests whether a definition container in the wrong spot is moved into the -# correct spot by deserialising. -@pytest.mark.skip #The test currently fails because the definition container doesn't have a category, which is wrong but we don't have time to refactor that right now. +## Tests whether a definition container in the wrong spot is moved into the correct spot by deserialising. def test_deserializeMoveDefinitionContainer(global_stack): global_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Material] = DefinitionContainer(container_id = "some definition") #Not in the correct spot. with unittest.mock.patch("UM.Settings.ContainerStack.ContainerStack.deserialize", unittest.mock.MagicMock()): #Prevent calling super().deserialize. global_stack.deserialize("") - assert global_stack.material.getId() == "empty" - assert global_stack.definition.getId() != "empty" + assert global_stack.material == empty_container + assert global_stack.definition != empty_container - UM.Settings.ContainerStack._containerRegistry = None - -## Tests whether getProperty properly applies the stack-like behaviour on its -# containers. +## Tests whether getProperty properly applies the stack-like behaviour on its containers. def test_getPropertyFallThrough(global_stack): #A few instance container mocks to put in the stack. mock_layer_heights = {} #For each container type, a mock container that defines layer height to something unique. @@ -365,8 +306,7 @@ def test_getPropertyNoResolveInDefinition(global_stack): global_stack.definition = value assert global_stack.getProperty("material_bed_temperature", "value") == 10 #No resolve, so fall through to value. -## In definitions, when the value is asked and there is a resolve function, it -# must get the resolve first. +## In definitions, when the value is asked and there is a resolve function, it must get the resolve first. def test_getPropertyResolveInDefinition(global_stack): resolve_and_value = unittest.mock.MagicMock() #Sets the resolve and value for bed temperature. resolve_and_value.getProperty = lambda key, property, context = None: (7.5 if property == "resolve" else 5) if (key == "material_bed_temperature" and property in ("resolve", "value")) else None #7.5 resolve, 5 value. @@ -375,8 +315,7 @@ def test_getPropertyResolveInDefinition(global_stack): global_stack.definition = resolve_and_value assert global_stack.getProperty("material_bed_temperature", "value") == 7.5 #Resolve wins in the definition. -## In instance containers, when the value is asked and there is a resolve -# function, it must get the value first. +## In instance containers, when the value is asked and there is a resolve function, it must get the value first. def test_getPropertyResolveInInstance(global_stack): container_indices = cura.Settings.CuraContainerStack._ContainerIndexes instance_containers = {} @@ -402,8 +341,7 @@ def test_getPropertyResolveInInstance(global_stack): global_stack.userChanges = instance_containers[container_indices.UserChanges] assert global_stack.getProperty("material_bed_temperature", "value") == 5 -## Tests whether the value in instances gets evaluated before the resolve in -# definitions. +## Tests whether the value in instances gets evaluated before the resolve in definitions. def test_getPropertyInstancesBeforeResolve(global_stack): value = unittest.mock.MagicMock() #Sets just the value. value.getProperty = lambda key, property, context = None: (10 if property == "value" else (InstanceState.User if property != "limit_to_extruder" else "-1")) if key == "material_bed_temperature" else None @@ -417,8 +355,7 @@ def test_getPropertyInstancesBeforeResolve(global_stack): assert global_stack.getProperty("material_bed_temperature", "value") == 10 -## Tests whether the hasUserValue returns true for settings that are changed in -# the user-changes container. +## Tests whether the hasUserValue returns true for settings that are changed in the user-changes container. def test_hasUserValueUserChanges(global_stack): container = unittest.mock.MagicMock() container.getMetaDataEntry = unittest.mock.MagicMock(return_value = "user") @@ -429,8 +366,7 @@ def test_hasUserValueUserChanges(global_stack): assert not global_stack.hasUserValue("infill_sparse_density") assert not global_stack.hasUserValue("") -## Tests whether the hasUserValue returns true for settings that are changed in -# the quality-changes container. +## Tests whether the hasUserValue returns true for settings that are changed in the quality-changes container. def test_hasUserValueQualityChanges(global_stack): container = unittest.mock.MagicMock() container.getMetaDataEntry = unittest.mock.MagicMock(return_value = "quality_changes") @@ -441,8 +377,7 @@ def test_hasUserValueQualityChanges(global_stack): assert not global_stack.hasUserValue("infill_sparse_density") assert not global_stack.hasUserValue("") -## Tests whether a container in some other place on the stack is correctly not -# recognised as user value. +## Tests whether a container in some other place on the stack is correctly not recognised as user value. def test_hasNoUserValue(global_stack): container = unittest.mock.MagicMock() container.getMetaDataEntry = unittest.mock.MagicMock(return_value = "quality") @@ -481,4 +416,4 @@ def test_setPropertyUser(key, property, value, global_stack): global_stack.setProperty(key, property, value) #The actual test. - global_stack.userChanges.setProperty.assert_called_once_with(key, property, value) #Make sure that the user container gets a setProperty call. \ No newline at end of file + global_stack.userChanges.setProperty.assert_called_once_with(key, property, value, None, False) #Make sure that the user container gets a setProperty call. \ No newline at end of file diff --git a/tests/Settings/conftest.py b/tests/Settings/conftest.py index 1ca3a865e9..f7affc94b2 100644 --- a/tests/Settings/conftest.py +++ b/tests/Settings/conftest.py @@ -4,16 +4,35 @@ # The purpose of this class is to create fixtures or methods that can be shared among all settings tests. import pytest -import copy from UM.Settings.DefinitionContainer import DefinitionContainer #To provide definition containers in the registry fixtures. +from UM.Settings.InstanceContainer import InstanceContainer +from cura.Settings.CuraContainerRegistry import CuraContainerRegistry +from cura.Settings.ExtruderStack import ExtruderStack +from cura.Settings.GlobalStack import GlobalStack +import cura.Settings.CuraContainerStack # Returns the CuraContainerRegistry instance with some empty containers. @pytest.fixture() -def container_registry(application): +def container_registry(application) -> CuraContainerRegistry: return application.getContainerRegistry() # Gives an arbitrary definition container. @pytest.fixture() -def definition_container(): - return DefinitionContainer(container_id = "Test Definition") \ No newline at end of file +def definition_container() -> DefinitionContainer: + return DefinitionContainer(container_id = "Test Definition") + +#An empty global stack to test with. +@pytest.fixture() +def global_stack() -> GlobalStack: + global_stack = GlobalStack("TestGlobalStack") + # There is a restriction here that the definition changes cannot be an empty container. Added in CURA-5281 + definition_changes_container = InstanceContainer(container_id = "InstanceContainer") + definition_changes_container.setMetaDataEntry("type", "definition_changes") + global_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.DefinitionChanges] = definition_changes_container + return global_stack + +## An empty extruder stack to test with. +@pytest.fixture() +def extruder_stack() -> ExtruderStack: + return ExtruderStack("TestExtruderStack") \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 32e2dc621f..d5bb5c8109 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,7 +4,7 @@ # The purpose of this class is to create fixtures or methods that can be shared among all tests. import pytest -from UM.Qt.QtApplication import QtApplication #QTApplication import is required, even though it isn't used. +from UM.Qt.QtApplication import QtApplication #QtApplication import is required, even though it isn't used. from cura.CuraApplication import CuraApplication from cura.MachineActionManager import MachineActionManager @@ -15,24 +15,9 @@ def application() -> CuraApplication: application = CuraApplication.getInstance() if application is None: application = CuraApplication() - application.initialize() return application # Returns a MachineActionManager instance. @pytest.fixture() def machine_action_manager(application) -> MachineActionManager: return application.getMachineActionManager() - -# @pytest.fixture() -# def plugin_registry(application): -# PluginRegistry._PluginRegistry__instance = None -# plugin_registry = PluginRegistry(application) -# plugin_registry._plugin_locations = [] # Clear pre-defined plugin locations -# return plugin_registry -# -# @pytest.fixture() -# def upgrade_manager(application): -# VersionUpgradeManager._VersionUpgradeManager__instance = None -# upgrade_manager = VersionUpgradeManager(application) -# return upgrade_manager - From 05bfee81586e295073c4144dcc3e139e7597e87d Mon Sep 17 00:00:00 2001 From: DavidGergely Date: Tue, 14 Aug 2018 15:26:52 +0200 Subject: [PATCH 165/243] Fix UM3extended 0.25 variant file Set ultimaker3_extended_aa0.25.inst.cfg to be the same as the ultimaker3_aa0.25.inst.cfg. --- .../variants/ultimaker3_extended_aa0.25.inst.cfg | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/resources/variants/ultimaker3_extended_aa0.25.inst.cfg b/resources/variants/ultimaker3_extended_aa0.25.inst.cfg index b2f81e101c..714b017653 100644 --- a/resources/variants/ultimaker3_extended_aa0.25.inst.cfg +++ b/resources/variants/ultimaker3_extended_aa0.25.inst.cfg @@ -11,7 +11,6 @@ hardware_type = nozzle [values] brim_width = 7 infill_line_width = 0.23 -infill_overlap = 0 layer_height_0 = 0.17 line_width = 0.23 machine_nozzle_cool_down_speed = 0.85 @@ -21,10 +20,18 @@ machine_nozzle_size = 0.25 machine_nozzle_tip_outer_diameter = 0.65 material_final_print_temperature = =material_print_temperature - 10 material_initial_print_temperature = =material_print_temperature - 5 +raft_airgap = 0.3 +raft_base_thickness = =resolveOrValue('layer_height_0') * 1.2 +raft_interface_line_spacing = =raft_interface_line_width + 0.2 +raft_interface_line_width = =line_width * 2 raft_interface_thickness = =layer_height * 1.5 +raft_jerk = =jerk_print +raft_margin = 15 +raft_surface_layers = 2 retraction_count_max = 25 retraction_extrusion_window = 1 retraction_min_travel = 0.7 +retraction_prime_speed = =retraction_speed skin_overlap = 15 speed_layer_0 = 20 speed_print = 55 @@ -32,8 +39,12 @@ speed_topbottom = 20 speed_wall = =math.ceil(speed_print * 30 / 55) support_angle = 60 support_bottom_distance = =support_z_distance / 2 +support_pattern = zigzag support_top_distance = =support_z_distance +support_use_towers = True support_z_distance = =layer_height * 2 +switch_extruder_prime_speed = =switch_extruder_retraction_speeds +switch_extruder_retraction_amount = =machine_heat_zone_length top_bottom_thickness = 1.2 wall_line_width_x = 0.23 wall_thickness = 1.3 From ce9782b3af2e2ffbdfe79d97e92c703259c98edc Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 14 Aug 2018 15:32:04 +0200 Subject: [PATCH 166/243] Initialize the empty_container in CuraApplication. Contributes to CURA-5628. --- cura/CuraApplication.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 24043b83fe..d688052369 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -368,6 +368,8 @@ class CuraApplication(QtApplication): # Add empty variant, material and quality containers. # Since they are empty, they should never be serialized and instead just programmatically created. # We need them to simplify the switching between materials. + self.empty_container = cura.CuraEmptyInstanceContainers.empty_container + self._container_registry.addContainer(cura.CuraEmptyInstanceContainers.empty_definition_changes_container) self.empty_definition_changes_container = cura.CuraEmptyInstanceContainers.empty_definition_changes_container From e1fd9b03a4a90e5cfa5b19c39f295975cc6ba7a2 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 14 Aug 2018 15:33:35 +0200 Subject: [PATCH 167/243] Remove all dependencies of the CuraContainerStack with the ContainerRegistry. That will be very helpful for creating unit tests. Also this is not needed because the next stack is always set in the machine or extruder manager when switching printers. Contributes to CURA-5628. --- cura/Settings/ExtruderStack.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index 47846fc1dd..ca687e358b 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -139,9 +139,6 @@ class ExtruderStack(CuraContainerStack): super().deserialize(contents, file_name) if "enabled" not in self.getMetaData(): self.setMetaDataEntry("enabled", "True") - stacks = ContainerRegistry.getInstance().findContainerStacks(id=self.getMetaDataEntry("machine", "")) - if stacks: - self.setNextStack(stacks[0]) def _onPropertiesChanged(self, key: str, properties: Dict[str, Any]) -> None: # When there is a setting that is not settable per extruder that depends on a value from a setting that is, From b85950b1281c7d1498d0a51fd09a6a600bca0f84 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 14 Aug 2018 15:40:11 +0200 Subject: [PATCH 168/243] Fix tests in the ExtruderStack. Contributes to CURA-5628. --- tests/Settings/TestExtruderStack.py | 99 ++++++++++++----------------- tests/Settings/TestGlobalStack.py | 2 +- tests/Settings/conftest.py | 7 +- 3 files changed, 49 insertions(+), 59 deletions(-) diff --git a/tests/Settings/TestExtruderStack.py b/tests/Settings/TestExtruderStack.py index a19f99571d..b2fa171068 100644 --- a/tests/Settings/TestExtruderStack.py +++ b/tests/Settings/TestExtruderStack.py @@ -4,37 +4,14 @@ import pytest #This module contains automated tests. import unittest.mock #For the mocking and monkeypatching functionality. -import cura.CuraApplication +import cura.Settings.CuraContainerStack #To get the list of container types. import UM.Settings.ContainerRegistry #To create empty instance containers. import UM.Settings.ContainerStack #To set the container registry the container stacks use. from UM.Settings.DefinitionContainer import DefinitionContainer #To check against the class of DefinitionContainer. from UM.Settings.InstanceContainer import InstanceContainer #To check against the class of InstanceContainer. -import cura.Settings.ExtruderStack #The module we're testing. +from UM.Settings.EmptyInstanceContainer import empty_container from cura.Settings.Exceptions import InvalidContainerError, InvalidOperationError #To check whether the correct exceptions are raised. - from cura.Settings.ExtruderManager import ExtruderManager -from cura.Settings.GlobalStack import GlobalStack - -## Fake container registry that always provides all containers you ask of. -# @pytest.yield_fixture() -# def container_registry(): -# registry = unittest.mock.MagicMock() -# registry.return_value = unittest.mock.NonCallableMagicMock() -# registry.findInstanceContainers = lambda *args, registry = registry, **kwargs: [registry.return_value] -# registry.findDefinitionContainers = lambda *args, registry = registry, **kwargs: [registry.return_value] -# -# UM.Settings.ContainerRegistry.ContainerRegistry._ContainerRegistry__instance = registry -# UM.Settings.ContainerStack._containerRegistry = registry -# -# yield registry -# -# UM.Settings.ContainerRegistry.ContainerRegistry._ContainerRegistry__instance = None -# UM.Settings.ContainerStack._containerRegistry = None - -## An empty extruder stack to test with. -@pytest.fixture() -def extruder_stack() -> cura.Settings.ExtruderStack.ExtruderStack: - return cura.Settings.ExtruderStack.ExtruderStack("TestStack") ## Gets an instance container with a specified container type. # @@ -151,12 +128,30 @@ def test_constrainVariantInvalid(container, extruder_stack): def test_constrainVariantValid(container, extruder_stack): extruder_stack.variant = container #Should not give an error. +#Tests setting definition changes profiles to invalid containers. +@pytest.mark.parametrize("container", [ + getInstanceContainer(container_type = "wrong container type"), + getInstanceContainer(container_type = "material"), #Existing, but still wrong type. + DefinitionContainer(container_id = "wrong class") +]) +def test_constrainDefinitionChangesInvalid(container, global_stack): + with pytest.raises(InvalidContainerError): #Invalid container, should raise an error. + global_stack.definitionChanges = container + +#Test setting definition changes profiles. +@pytest.mark.parametrize("container", [ + getInstanceContainer(container_type = "definition_changes"), + InstanceContainerSubClass(container_type = "definition_changes") +]) +def test_constrainDefinitionChangesValid(container, global_stack): + global_stack.definitionChanges = container #Should not give an error. + #Tests setting definitions to invalid containers. @pytest.mark.parametrize("container", [ getInstanceContainer(container_type = "wrong class"), getInstanceContainer(container_type = "material"), #Existing, but still wrong class. ]) -def test_constrainVariantInvalid(container, extruder_stack): +def test_constrainDefinitionInvalid(container, extruder_stack): with pytest.raises(InvalidContainerError): #Invalid container, should raise an error. extruder_stack.definition = container @@ -168,23 +163,22 @@ def test_constrainVariantInvalid(container, extruder_stack): def test_constrainDefinitionValid(container, extruder_stack): extruder_stack.definition = container #Should not give an error. -## Tests whether deserialising completes the missing containers with empty -# ones. -@pytest.mark.skip #The test currently fails because the definition container doesn't have a category, which is wrong but we don't have time to refactor that right now. -def test_deserializeCompletesEmptyContainers(extruder_stack: cura.Settings.ExtruderStack): - extruder_stack._containers = [DefinitionContainer(container_id = "definition")] #Set the internal state of this stack manually. +## Tests whether deserialising completes the missing containers with empty ones. +def test_deserializeCompletesEmptyContainers(extruder_stack): + extruder_stack._containers = [DefinitionContainer(container_id = "definition"), extruder_stack.definitionChanges] #Set the internal state of this stack manually. with unittest.mock.patch("UM.Settings.ContainerStack.ContainerStack.deserialize", unittest.mock.MagicMock()): #Prevent calling super().deserialize. extruder_stack.deserialize("") assert len(extruder_stack.getContainers()) == len(cura.Settings.CuraContainerStack._ContainerIndexes.IndexTypeMap) #Needs a slot for every type. for container_type_index in cura.Settings.CuraContainerStack._ContainerIndexes.IndexTypeMap: - if container_type_index == cura.Settings.CuraContainerStack._ContainerIndexes.Definition: #We're not checking the definition. + if container_type_index in \ + (cura.Settings.CuraContainerStack._ContainerIndexes.Definition, + cura.Settings.CuraContainerStack._ContainerIndexes.DefinitionChanges): # We're not checking the definition or definition_changes continue - assert extruder_stack.getContainer(container_type_index).getId() == "empty" #All others need to be empty. + assert extruder_stack.getContainer(container_type_index) == empty_container #All others need to be empty. -## Tests whether an instance container with the wrong type gets removed when -# deserialising. +## Tests whether an instance container with the wrong type gets removed when deserialising. def test_deserializeRemovesWrongInstanceContainer(extruder_stack): extruder_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Quality] = getInstanceContainer(container_type = "wrong type") extruder_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Definition] = DefinitionContainer(container_id = "some definition") @@ -194,8 +188,7 @@ def test_deserializeRemovesWrongInstanceContainer(extruder_stack): assert extruder_stack.quality == extruder_stack._empty_instance_container #Replaced with empty. -## Tests whether a container with the wrong class gets removed when -# deserialising. +## Tests whether a container with the wrong class gets removed when deserialising. def test_deserializeRemovesWrongContainerClass(extruder_stack): extruder_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Quality] = DefinitionContainer(container_id = "wrong class") extruder_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Definition] = DefinitionContainer(container_id = "some definition") @@ -205,8 +198,7 @@ def test_deserializeRemovesWrongContainerClass(extruder_stack): assert extruder_stack.quality == extruder_stack._empty_instance_container #Replaced with empty. -## Tests whether an instance container in the definition spot results in an -# error. +## Tests whether an instance container in the definition spot results in an error. def test_deserializeWrongDefinitionClass(extruder_stack): extruder_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Definition] = getInstanceContainer(container_type = "definition") #Correct type but wrong class. @@ -214,8 +206,7 @@ def test_deserializeWrongDefinitionClass(extruder_stack): with pytest.raises(UM.Settings.ContainerStack.InvalidContainerStackError): #Must raise an error that there is no definition container. extruder_stack.deserialize("") -## Tests whether an instance container with the wrong type is moved into the -# correct slot by deserialising. +## Tests whether an instance container with the wrong type is moved into the correct slot by deserialising. def test_deserializeMoveInstanceContainer(extruder_stack): extruder_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Quality] = getInstanceContainer(container_type = "material") #Not in the correct spot. extruder_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Definition] = DefinitionContainer(container_id = "some definition") @@ -223,26 +214,21 @@ def test_deserializeMoveInstanceContainer(extruder_stack): with unittest.mock.patch("UM.Settings.ContainerStack.ContainerStack.deserialize", unittest.mock.MagicMock()): #Prevent calling super().deserialize. extruder_stack.deserialize("") - assert extruder_stack.quality.getId() == "empty" - assert extruder_stack.material.getId() != "empty" -from UM.Settings.Validator import Validator -## Tests whether a definition container in the wrong spot is moved into the -# correct spot by deserialising. -@pytest.mark.skip #The test currently fails because the definition container doesn't have a category, which is wrong but we don't have time to refactor that right now. + assert extruder_stack.quality == empty_container + assert extruder_stack.material != empty_container + +## Tests whether a definition container in the wrong spot is moved into the correct spot by deserialising. def test_deserializeMoveDefinitionContainer(extruder_stack): extruder_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.Material] = DefinitionContainer(container_id = "some definition") #Not in the correct spot. with unittest.mock.patch("UM.Settings.ContainerStack.ContainerStack.deserialize", unittest.mock.MagicMock()): #Prevent calling super().deserialize. extruder_stack.deserialize("") - assert extruder_stack.material.getId() == "empty" - assert extruder_stack.definition.getId() != "empty" + assert extruder_stack.material == empty_container + assert extruder_stack.definition != empty_container - UM.Settings.ContainerStack._containerRegistry = None - -## Tests whether getProperty properly applies the stack-like behaviour on its -# containers. -def test_getPropertyFallThrough(extruder_stack): +## Tests whether getProperty properly applies the stack-like behaviour on its containers. +def test_getPropertyFallThrough(global_stack, extruder_stack): # ExtruderStack.setNextStack calls registerExtruder for backward compatibility, but we do not need a complete extruder manager ExtruderManager._ExtruderManager__instance = unittest.mock.MagicMock() @@ -272,8 +258,7 @@ def test_getPropertyFallThrough(extruder_stack): with unittest.mock.patch("cura.Settings.CuraContainerStack.DefinitionContainer", unittest.mock.MagicMock): #To guard against the type checking. extruder_stack.definition = mock_layer_heights[container_indices.Definition] #There's a layer height in here! - stack = GlobalStack("PyTest GlobalStack") - extruder_stack.setNextStack(stack) + extruder_stack.setNextStack(global_stack) assert extruder_stack.getProperty("layer_height", "value") == container_indices.Definition extruder_stack.variant = mock_layer_heights[container_indices.Variant] @@ -312,4 +297,4 @@ def test_setPropertyUser(key, property, value, extruder_stack): extruder_stack.setProperty(key, property, value) #The actual test. - extruder_stack.userChanges.setProperty.assert_called_once_with(key, property, value) #Make sure that the user container gets a setProperty call. \ No newline at end of file + extruder_stack.userChanges.setProperty.assert_called_once_with(key, property, value, None, False) #Make sure that the user container gets a setProperty call. \ No newline at end of file diff --git a/tests/Settings/TestGlobalStack.py b/tests/Settings/TestGlobalStack.py index 9d52257245..7aba53c4e5 100755 --- a/tests/Settings/TestGlobalStack.py +++ b/tests/Settings/TestGlobalStack.py @@ -179,7 +179,7 @@ def test_constrainDefinitionChangesValid(container, global_stack): getInstanceContainer(container_type = "wrong class"), getInstanceContainer(container_type = "material"), #Existing, but still wrong class. ]) -def test_constrainVariantInvalid(container, global_stack): +def test_constrainDefinitionInvalid(container, global_stack): with pytest.raises(InvalidContainerError): #Invalid container, should raise an error. global_stack.definition = container diff --git a/tests/Settings/conftest.py b/tests/Settings/conftest.py index f7affc94b2..8b519fd261 100644 --- a/tests/Settings/conftest.py +++ b/tests/Settings/conftest.py @@ -35,4 +35,9 @@ def global_stack() -> GlobalStack: ## An empty extruder stack to test with. @pytest.fixture() def extruder_stack() -> ExtruderStack: - return ExtruderStack("TestExtruderStack") \ No newline at end of file + extruder_stack= ExtruderStack("TestExtruderStack") + # There is a restriction here that the definition changes cannot be an empty container. Added in CURA-5281 + definition_changes_container = InstanceContainer(container_id = "InstanceContainer") + definition_changes_container.setMetaDataEntry("type", "definition_changes") + extruder_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.DefinitionChanges] = definition_changes_container + return extruder_stack \ No newline at end of file From 77c5a94db2cb1f6d5ce1b88c6feff66841042b9f Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 14 Aug 2018 17:14:30 +0200 Subject: [PATCH 169/243] Fix some test in the CuraContainerRegistry. Delete a test that needs a ContainerProvider. We need to discuss if we want to add it back, depending if we are still keeping the providers. Contributes to CURA-5628. --- tests/Settings/TestCuraContainerRegistry.py | 56 +++++-------------- tests/Settings/conftest.py | 33 +++++++---- tests/Settings/stacks/Complete.extruder.cfg | 12 ---- tests/Settings/stacks/Complete.global.cfg | 13 ----- .../Settings/stacks/ExtruderLegacy.stack.cfg | 11 ---- tests/Settings/stacks/Global.global.cfg | 8 --- tests/Settings/stacks/Global.stack.cfg | 11 ---- tests/Settings/stacks/Left.extruder.cfg | 8 --- tests/Settings/stacks/MachineLegacy.stack.cfg | 11 ---- .../stacks/OnlyDefinition.extruder.cfg | 7 --- .../Settings/stacks/OnlyDefinition.global.cfg | 7 --- .../stacks/OnlyDefinitionChanges.global.cfg | 8 --- .../Settings/stacks/OnlyMaterial.extruder.cfg | 8 --- tests/Settings/stacks/OnlyMaterial.global.cfg | 8 --- .../Settings/stacks/OnlyQuality.extruder.cfg | 8 --- tests/Settings/stacks/OnlyQuality.global.cfg | 8 --- .../stacks/OnlyQualityChanges.extruder.cfg | 8 --- .../stacks/OnlyQualityChanges.global.cfg | 8 --- tests/Settings/stacks/OnlyUser.extruder.cfg | 8 --- tests/Settings/stacks/OnlyUser.global.cfg | 8 --- .../Settings/stacks/OnlyVariant.extruder.cfg | 8 --- tests/Settings/stacks/OnlyVariant.global.cfg | 8 --- tests/conftest.py | 2 +- 23 files changed, 36 insertions(+), 231 deletions(-) delete mode 100644 tests/Settings/stacks/Complete.extruder.cfg delete mode 100644 tests/Settings/stacks/Complete.global.cfg delete mode 100644 tests/Settings/stacks/ExtruderLegacy.stack.cfg delete mode 100644 tests/Settings/stacks/Global.global.cfg delete mode 100644 tests/Settings/stacks/Global.stack.cfg delete mode 100644 tests/Settings/stacks/Left.extruder.cfg delete mode 100644 tests/Settings/stacks/MachineLegacy.stack.cfg delete mode 100644 tests/Settings/stacks/OnlyDefinition.extruder.cfg delete mode 100644 tests/Settings/stacks/OnlyDefinition.global.cfg delete mode 100644 tests/Settings/stacks/OnlyDefinitionChanges.global.cfg delete mode 100644 tests/Settings/stacks/OnlyMaterial.extruder.cfg delete mode 100644 tests/Settings/stacks/OnlyMaterial.global.cfg delete mode 100644 tests/Settings/stacks/OnlyQuality.extruder.cfg delete mode 100644 tests/Settings/stacks/OnlyQuality.global.cfg delete mode 100644 tests/Settings/stacks/OnlyQualityChanges.extruder.cfg delete mode 100644 tests/Settings/stacks/OnlyQualityChanges.global.cfg delete mode 100644 tests/Settings/stacks/OnlyUser.extruder.cfg delete mode 100644 tests/Settings/stacks/OnlyUser.global.cfg delete mode 100644 tests/Settings/stacks/OnlyVariant.extruder.cfg delete mode 100644 tests/Settings/stacks/OnlyVariant.global.cfg diff --git a/tests/Settings/TestCuraContainerRegistry.py b/tests/Settings/TestCuraContainerRegistry.py index dd78f2fd68..af478c3b2b 100644 --- a/tests/Settings/TestCuraContainerRegistry.py +++ b/tests/Settings/TestCuraContainerRegistry.py @@ -4,6 +4,7 @@ import os #To find the directory with test files and find the test files. import unittest.mock #To mock and monkeypatch stuff. +from UM.Settings.DefinitionContainer import DefinitionContainer from cura.Settings.ExtruderStack import ExtruderStack #Testing for returning the correct types of stacks. from cura.Settings.GlobalStack import GlobalStack #Testing for returning the correct types of stacks. import UM.Settings.InstanceContainer #Creating instance containers to register. @@ -17,36 +18,40 @@ def teardown(): os.remove(temporary_file) ## Tests whether addContainer properly converts to ExtruderStack. -def test_addContainerExtruderStack(container_registry, definition_container): +def test_addContainerExtruderStack(container_registry, definition_container, definition_changes_container): container_registry.addContainer(definition_container) + container_registry.addContainer(definition_changes_container) container_stack = UM.Settings.ContainerStack.ContainerStack(stack_id = "Test Extruder Stack") #A container we're going to convert. container_stack.setMetaDataEntry("type", "extruder_train") #This is now an extruder train. container_stack.insertContainer(0, definition_container) #Add a definition to it so it doesn't complain. + container_stack.insertContainer(1, definition_changes_container) mock_super_add_container = unittest.mock.MagicMock() #Takes the role of the Uranium-ContainerRegistry where the resulting containers get registered. with unittest.mock.patch("UM.Settings.ContainerRegistry.ContainerRegistry.addContainer", mock_super_add_container): container_registry.addContainer(container_stack) - assert len(mock_super_add_container.call_args_list) == 2 #Called only once. - assert len(mock_super_add_container.call_args_list[1][0]) == 1 #Called with one parameter. - assert type(mock_super_add_container.call_args_list[1][0][0]) == ExtruderStack + assert len(mock_super_add_container.call_args_list) == 1 #Called only once. + assert len(mock_super_add_container.call_args_list[0][0]) == 1 #Called with one parameter. + assert type(mock_super_add_container.call_args_list[0][0][0]) == ExtruderStack ## Tests whether addContainer properly converts to GlobalStack. -def test_addContainerGlobalStack(container_registry, definition_container): +def test_addContainerGlobalStack(container_registry, definition_container, definition_changes_container): container_registry.addContainer(definition_container) + container_registry.addContainer(definition_changes_container) container_stack = UM.Settings.ContainerStack.ContainerStack(stack_id = "Test Global Stack") #A container we're going to convert. container_stack.setMetaDataEntry("type", "machine") #This is now a global stack. container_stack.insertContainer(0, definition_container) #Must have a definition. + container_stack.insertContainer(1, definition_changes_container) #Must have a definition changes. mock_super_add_container = unittest.mock.MagicMock() #Takes the role of the Uranium-ContainerRegistry where the resulting containers get registered. with unittest.mock.patch("UM.Settings.ContainerRegistry.ContainerRegistry.addContainer", mock_super_add_container): container_registry.addContainer(container_stack) - assert len(mock_super_add_container.call_args_list) == 2 #Called only once. - assert len(mock_super_add_container.call_args_list[1][0]) == 1 #Called with one parameter. - assert type(mock_super_add_container.call_args_list[1][0][0]) == GlobalStack + assert len(mock_super_add_container.call_args_list) == 1 #Called only once. + assert len(mock_super_add_container.call_args_list[0][0]) == 1 #Called with one parameter. + assert type(mock_super_add_container.call_args_list[0][0][0]) == GlobalStack def test_addContainerGoodSettingVersion(container_registry, definition_container): from cura.CuraApplication import CuraApplication @@ -92,38 +97,3 @@ def test_addContainerBadSettingVersion(container_registry, definition_container) container_registry.addContainer(instance) mock_super_add_container.assert_not_called() #Should not get passed on to UM.Settings.ContainerRegistry.addContainer, because the setting_version doesn't match its definition! - -## Tests whether loading gives objects of the correct type. -# @pytest.mark.parametrize("filename, output_class", [ -# ("ExtruderLegacy.stack.cfg", ExtruderStack), -# ("MachineLegacy.stack.cfg", GlobalStack), -# ("Left.extruder.cfg", ExtruderStack), -# ("Global.global.cfg", GlobalStack), -# ("Global.stack.cfg", GlobalStack) -# ]) -# def test_loadTypes(filename, output_class, container_registry): -# #Mock some dependencies. -# Resources.getAllResourcesOfType = unittest.mock.MagicMock(return_value = [os.path.join(os.path.dirname(os.path.abspath(__file__)), "stacks", filename)]) #Return just this tested file. -# -# def findContainers(container_type = 0, id = None): -# if id == "some_instance": -# return [UM.Settings.ContainerRegistry._EmptyInstanceContainer(id)] -# elif id == "some_definition": -# return [DefinitionContainer(container_id = id)] -# else: -# return [] -# -# container_registry.findContainers = findContainers -# -# with unittest.mock.patch("cura.Settings.GlobalStack.GlobalStack.findContainer"): -# with unittest.mock.patch("os.remove"): -# container_registry.load() -# -# #Check whether the resulting type was correct. -# stack_id = filename.split(".")[0] -# for container_id, container in container_registry._containers.items(): #Stupid ContainerRegistry class doesn't expose any way of getting at this except by prodding the privates. -# if container_id == stack_id: #This is the one we're testing. -# assert type(container) == output_class -# break -# else: -# assert False #Container stack with specified ID was not loaded. diff --git a/tests/Settings/conftest.py b/tests/Settings/conftest.py index 8b519fd261..c2d8854f05 100644 --- a/tests/Settings/conftest.py +++ b/tests/Settings/conftest.py @@ -5,6 +5,8 @@ import pytest +from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.ContainerStack import setContainerRegistry from UM.Settings.DefinitionContainer import DefinitionContainer #To provide definition containers in the registry fixtures. from UM.Settings.InstanceContainer import InstanceContainer from cura.Settings.CuraContainerRegistry import CuraContainerRegistry @@ -15,29 +17,38 @@ import cura.Settings.CuraContainerStack # Returns the CuraContainerRegistry instance with some empty containers. @pytest.fixture() def container_registry(application) -> CuraContainerRegistry: - return application.getContainerRegistry() + ContainerRegistry._ContainerRegistry__instance= None # Need to reset since we only allow one instance + registry = CuraContainerRegistry(application) + setContainerRegistry(registry) + return registry # Gives an arbitrary definition container. @pytest.fixture() def definition_container() -> DefinitionContainer: return DefinitionContainer(container_id = "Test Definition") -#An empty global stack to test with. +# Gives an arbitrary definition changes container. @pytest.fixture() -def global_stack() -> GlobalStack: - global_stack = GlobalStack("TestGlobalStack") - # There is a restriction here that the definition changes cannot be an empty container. Added in CURA-5281 - definition_changes_container = InstanceContainer(container_id = "InstanceContainer") +def definition_changes_container() -> InstanceContainer: + definition_changes_container = InstanceContainer(container_id = "Test Definition Changes") definition_changes_container.setMetaDataEntry("type", "definition_changes") + # Add current setting version to the instance container + from cura.CuraApplication import CuraApplication + definition_changes_container.getMetaData()["setting_version"] = CuraApplication.SettingVersion + return definition_changes_container + +# An empty global stack to test with. +# There is a restriction here that the definition changes cannot be an empty container. Added in CURA-5281 +@pytest.fixture() +def global_stack(definition_changes_container) -> GlobalStack: + global_stack = GlobalStack("TestGlobalStack") global_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.DefinitionChanges] = definition_changes_container return global_stack -## An empty extruder stack to test with. +# An empty extruder stack to test with. +# There is a restriction here that the definition changes cannot be an empty container. Added in CURA-5281 @pytest.fixture() -def extruder_stack() -> ExtruderStack: +def extruder_stack(definition_changes_container) -> ExtruderStack: extruder_stack= ExtruderStack("TestExtruderStack") - # There is a restriction here that the definition changes cannot be an empty container. Added in CURA-5281 - definition_changes_container = InstanceContainer(container_id = "InstanceContainer") - definition_changes_container.setMetaDataEntry("type", "definition_changes") extruder_stack._containers[cura.Settings.CuraContainerStack._ContainerIndexes.DefinitionChanges] = definition_changes_container return extruder_stack \ No newline at end of file diff --git a/tests/Settings/stacks/Complete.extruder.cfg b/tests/Settings/stacks/Complete.extruder.cfg deleted file mode 100644 index 789c0978f3..0000000000 --- a/tests/Settings/stacks/Complete.extruder.cfg +++ /dev/null @@ -1,12 +0,0 @@ -[general] -version = 3 -name = Complete -id = Complete - -[containers] -0 = some_user_changes -1 = some_quality_changes -2 = some_quality -3 = some_material -4 = some_variant -5 = some_definition diff --git a/tests/Settings/stacks/Complete.global.cfg b/tests/Settings/stacks/Complete.global.cfg deleted file mode 100644 index f7f613991a..0000000000 --- a/tests/Settings/stacks/Complete.global.cfg +++ /dev/null @@ -1,13 +0,0 @@ -[general] -version = 3 -name = Complete -id = Complete - -[containers] -0 = some_user_changes -1 = some_quality_changes -2 = some_quality -3 = some_material -4 = some_variant -5 = some_definition_changes -6 = some_definition diff --git a/tests/Settings/stacks/ExtruderLegacy.stack.cfg b/tests/Settings/stacks/ExtruderLegacy.stack.cfg deleted file mode 100644 index 4a6c419e40..0000000000 --- a/tests/Settings/stacks/ExtruderLegacy.stack.cfg +++ /dev/null @@ -1,11 +0,0 @@ -[general] -version = 3 -name = Legacy Extruder Stack -id = ExtruderLegacy - -[metadata] -type = extruder_train - -[containers] -3 = some_instance -5 = some_definition diff --git a/tests/Settings/stacks/Global.global.cfg b/tests/Settings/stacks/Global.global.cfg deleted file mode 100644 index 9034c1d0d0..0000000000 --- a/tests/Settings/stacks/Global.global.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Global -id = Global - -[containers] -3 = some_instance -6 = some_definition diff --git a/tests/Settings/stacks/Global.stack.cfg b/tests/Settings/stacks/Global.stack.cfg deleted file mode 100644 index aa1693d878..0000000000 --- a/tests/Settings/stacks/Global.stack.cfg +++ /dev/null @@ -1,11 +0,0 @@ -[general] -version = 3 -name = Global -id = Global - -[metadata] -type = machine - -[containers] -3 = some_instance -6 = some_definition diff --git a/tests/Settings/stacks/Left.extruder.cfg b/tests/Settings/stacks/Left.extruder.cfg deleted file mode 100644 index 8ba45d6754..0000000000 --- a/tests/Settings/stacks/Left.extruder.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Left -id = Left - -[containers] -3 = some_instance -5 = some_definition diff --git a/tests/Settings/stacks/MachineLegacy.stack.cfg b/tests/Settings/stacks/MachineLegacy.stack.cfg deleted file mode 100644 index 147d63c596..0000000000 --- a/tests/Settings/stacks/MachineLegacy.stack.cfg +++ /dev/null @@ -1,11 +0,0 @@ -[general] -version = 3 -name = Legacy Global Stack -id = MachineLegacy - -[metadata] -type = machine - -[containers] -3 = some_instance -6 = some_definition \ No newline at end of file diff --git a/tests/Settings/stacks/OnlyDefinition.extruder.cfg b/tests/Settings/stacks/OnlyDefinition.extruder.cfg deleted file mode 100644 index e58512b27f..0000000000 --- a/tests/Settings/stacks/OnlyDefinition.extruder.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[general] -version = 3 -name = Only Definition -id = OnlyDefinition - -[containers] -5 = some_definition diff --git a/tests/Settings/stacks/OnlyDefinition.global.cfg b/tests/Settings/stacks/OnlyDefinition.global.cfg deleted file mode 100644 index 9534353ed5..0000000000 --- a/tests/Settings/stacks/OnlyDefinition.global.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[general] -version = 3 -name = Only Definition -id = OnlyDefinition - -[containers] -6 = some_definition diff --git a/tests/Settings/stacks/OnlyDefinitionChanges.global.cfg b/tests/Settings/stacks/OnlyDefinitionChanges.global.cfg deleted file mode 100644 index 39e2105b7d..0000000000 --- a/tests/Settings/stacks/OnlyDefinitionChanges.global.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Only Definition Changes -id = OnlyDefinitionChanges - -[containers] -5 = some_instance -6 = some_definition diff --git a/tests/Settings/stacks/OnlyMaterial.extruder.cfg b/tests/Settings/stacks/OnlyMaterial.extruder.cfg deleted file mode 100644 index 49a9d12389..0000000000 --- a/tests/Settings/stacks/OnlyMaterial.extruder.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Only Material -id = OnlyMaterial - -[containers] -3 = some_instance -5 = some_definition diff --git a/tests/Settings/stacks/OnlyMaterial.global.cfg b/tests/Settings/stacks/OnlyMaterial.global.cfg deleted file mode 100644 index 715651a9b9..0000000000 --- a/tests/Settings/stacks/OnlyMaterial.global.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Only Material -id = OnlyMaterial - -[containers] -3 = some_instance -6 = some_definition diff --git a/tests/Settings/stacks/OnlyQuality.extruder.cfg b/tests/Settings/stacks/OnlyQuality.extruder.cfg deleted file mode 100644 index aaf7fb30c5..0000000000 --- a/tests/Settings/stacks/OnlyQuality.extruder.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Only Quality -id = OnlyQuality - -[containers] -2 = some_instance -5 = some_definition diff --git a/tests/Settings/stacks/OnlyQuality.global.cfg b/tests/Settings/stacks/OnlyQuality.global.cfg deleted file mode 100644 index f07a35666e..0000000000 --- a/tests/Settings/stacks/OnlyQuality.global.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Only Quality -id = OnlyQuality - -[containers] -2 = some_instance -6 = some_definition diff --git a/tests/Settings/stacks/OnlyQualityChanges.extruder.cfg b/tests/Settings/stacks/OnlyQualityChanges.extruder.cfg deleted file mode 100644 index 653bad840c..0000000000 --- a/tests/Settings/stacks/OnlyQualityChanges.extruder.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Only Quality Changes -id = OnlyQualityChanges - -[containers] -1 = some_instance -5 = some_definition diff --git a/tests/Settings/stacks/OnlyQualityChanges.global.cfg b/tests/Settings/stacks/OnlyQualityChanges.global.cfg deleted file mode 100644 index 17d279377a..0000000000 --- a/tests/Settings/stacks/OnlyQualityChanges.global.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Only Quality Changes -id = OnlyQualityChanges - -[containers] -1 = some_instance -6 = some_definition diff --git a/tests/Settings/stacks/OnlyUser.extruder.cfg b/tests/Settings/stacks/OnlyUser.extruder.cfg deleted file mode 100644 index abf812a859..0000000000 --- a/tests/Settings/stacks/OnlyUser.extruder.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Only User -id = OnlyUser - -[containers] -0 = some_instance -5 = some_definition diff --git a/tests/Settings/stacks/OnlyUser.global.cfg b/tests/Settings/stacks/OnlyUser.global.cfg deleted file mode 100644 index 31371d2c51..0000000000 --- a/tests/Settings/stacks/OnlyUser.global.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Only User -id = OnlyUser - -[containers] -0 = some_instance -6 = some_definition diff --git a/tests/Settings/stacks/OnlyVariant.extruder.cfg b/tests/Settings/stacks/OnlyVariant.extruder.cfg deleted file mode 100644 index a31997a6fd..0000000000 --- a/tests/Settings/stacks/OnlyVariant.extruder.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Only Variant -id = OnlyVariant - -[containers] -4 = some_instance -5 = some_definition diff --git a/tests/Settings/stacks/OnlyVariant.global.cfg b/tests/Settings/stacks/OnlyVariant.global.cfg deleted file mode 100644 index 158d533ac8..0000000000 --- a/tests/Settings/stacks/OnlyVariant.global.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[general] -version = 3 -name = Only Variant -id = OnlyVariant - -[containers] -4 = some_instance -6 = some_definition diff --git a/tests/conftest.py b/tests/conftest.py index d5bb5c8109..f2c709d8d8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -20,4 +20,4 @@ def application() -> CuraApplication: # Returns a MachineActionManager instance. @pytest.fixture() def machine_action_manager(application) -> MachineActionManager: - return application.getMachineActionManager() + return MachineActionManager(application) From 3a7fff42b5d8c07c1cd17b69e5170c69c2d8c001 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Wed, 15 Aug 2018 09:14:37 +0200 Subject: [PATCH 170/243] Fix code style. Contributes to CURA-5628. --- cura/OneAtATimeIterator.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py index e7ad833e1c..a08f3ed2bf 100644 --- a/cura/OneAtATimeIterator.py +++ b/cura/OneAtATimeIterator.py @@ -76,6 +76,8 @@ class OneAtATimeIterator(Iterator): continue bounding_box = node.getBoundingBox() + if not bounding_box: + continue from UM.Math.Polygon import Polygon bounding_box_polygon = Polygon([[bounding_box.left, bounding_box.front], [bounding_box.left, bounding_box.back], From da39e842f111206b9c362e4a6f354cc3b9ac06ce Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 15 Aug 2018 09:25:24 +0200 Subject: [PATCH 171/243] Move getting diagonal size out to separate function --- cura/BuildVolume.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 667247eac9..5aa3873c89 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -171,6 +171,12 @@ class BuildVolume(SceneNode): if shape: self._shape = shape + ## Get the length of the 3D diagonal through the build volume. + # + # This gives a sense of the scale of the build volume in general. + def getDiagonalSize(self) -> float: + return math.sqrt(self._width * self._width + self._height * self._height + self._depth * self._depth) + def getDisallowedAreas(self) -> List[Polygon]: return self._disallowed_areas @@ -553,10 +559,9 @@ class BuildVolume(SceneNode): if self._engine_ready: self.rebuild() - diagonal_size = math.sqrt(self._width * self._width + self._height * self._height + self._depth * self._depth) camera = Application.getInstance().getController().getCameraTool() if camera: - camera.setZoomRange(min = 1, max = diagonal_size * 5) #You can zoom out up to 5 times the diagonal across your screen (to see models bigger than your volume). + camera.setZoomRange(min = 1, max = self.getDiagonalSize() * 5) #You can zoom out up to 5 times the diagonal. This gives some space around the volume. def _onEngineCreated(self): self._engine_ready = True From f1a7b23a5ca6b517396b5a51fce28a65fb5fb1c5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 15 Aug 2018 09:52:39 +0200 Subject: [PATCH 172/243] Adjust default position of camera based on diagonal size --- cura/CuraActions.py | 3 ++- cura/CuraApplication.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cura/CuraActions.py b/cura/CuraActions.py index 1b2c6c576c..93a18318df 100644 --- a/cura/CuraActions.py +++ b/cura/CuraActions.py @@ -50,7 +50,8 @@ class CuraActions(QObject): scene = cura.CuraApplication.CuraApplication.getInstance().getController().getScene() camera = scene.getActiveCamera() if camera: - camera.setPosition(Vector(-80, 250, 700)) + diagonal_size = cura.CuraApplication.CuraApplication.getInstance().getBuildVolume().getDiagonalSize() + camera.setPosition(Vector(-80, 250, 700) * diagonal_size / 375) camera.setPerspective(True) camera.lookAt(Vector(0, 0, 0)) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 6164fc8756..955bc4df5f 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -776,7 +776,7 @@ class CuraApplication(QtApplication): # Initialize camera root = controller.getScene().getRoot() camera = Camera("3d", root) - camera.setPosition(Vector(-80, 250, 700)) + camera.setPosition(Vector(-80, 250, 700) * self.getBuildVolume().getDiagonalSize() / 375) camera.setPerspective(True) camera.lookAt(Vector(0, 0, 0)) controller.getScene().setActiveCamera("3d") From c20274e356f043e5a56393f5ae2647e48168b1fe Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 15 Aug 2018 11:04:09 +0200 Subject: [PATCH 173/243] Move constant instance containers to a separate file This way we separate the class/type definitions and the actual constants. --- cura/CuraApplication.py | 25 +++++---- cura/CuraEmptyInstanceContainers.py | 29 ---------- cura/Settings/CuraContainerStack.py | 13 ++--- .../cura_empty_instance_containers.py | 56 +++++++++++++++++++ tests/Settings/TestExtruderStack.py | 2 +- tests/Settings/TestGlobalStack.py | 3 +- 6 files changed, 78 insertions(+), 50 deletions(-) delete mode 100644 cura/CuraEmptyInstanceContainers.py create mode 100644 cura/Settings/cura_empty_instance_containers.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 908b718e1b..0d110ced54 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -104,7 +104,7 @@ from cura.Settings.ExtrudersModel import ExtrudersModel from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler from cura.Settings.ContainerManager import ContainerManager from cura.Settings.SidebarCustomMenuItemsModel import SidebarCustomMenuItemsModel -import cura.CuraEmptyInstanceContainers +import cura.Settings.cura_empty_instance_containers from cura.ObjectsModel import ObjectsModel @@ -368,22 +368,23 @@ class CuraApplication(QtApplication): # Add empty variant, material and quality containers. # Since they are empty, they should never be serialized and instead just programmatically created. # We need them to simplify the switching between materials. - self.empty_container = cura.CuraEmptyInstanceContainers.empty_container + self.empty_container = cura.Settings.cura_empty_instance_containers.empty_container - self._container_registry.addContainer(cura.CuraEmptyInstanceContainers.empty_definition_changes_container) - self.empty_definition_changes_container = cura.CuraEmptyInstanceContainers.empty_definition_changes_container + self._container_registry.addContainer( + cura.Settings.cura_empty_instance_containers.empty_definition_changes_container) + self.empty_definition_changes_container = cura.Settings.cura_empty_instance_containers.empty_definition_changes_container - self._container_registry.addContainer(cura.CuraEmptyInstanceContainers.empty_variant_container) - self.empty_variant_container = cura.CuraEmptyInstanceContainers.empty_variant_container + self._container_registry.addContainer(cura.Settings.cura_empty_instance_containers.empty_variant_container) + self.empty_variant_container = cura.Settings.cura_empty_instance_containers.empty_variant_container - self._container_registry.addContainer(cura.CuraEmptyInstanceContainers.empty_material_container) - self.empty_material_container = cura.CuraEmptyInstanceContainers.empty_material_container + self._container_registry.addContainer(cura.Settings.cura_empty_instance_containers.empty_material_container) + self.empty_material_container = cura.Settings.cura_empty_instance_containers.empty_material_container - self._container_registry.addContainer(cura.CuraEmptyInstanceContainers.empty_quality_container) - self.empty_quality_container = cura.CuraEmptyInstanceContainers.empty_quality_container + self._container_registry.addContainer(cura.Settings.cura_empty_instance_containers.empty_quality_container) + self.empty_quality_container = cura.Settings.cura_empty_instance_containers.empty_quality_container - self._container_registry.addContainer(cura.CuraEmptyInstanceContainers.empty_quality_changes_container) - self.empty_quality_changes_container = cura.CuraEmptyInstanceContainers.empty_quality_changes_container + self._container_registry.addContainer(cura.Settings.cura_empty_instance_containers.empty_quality_changes_container) + self.empty_quality_changes_container = cura.Settings.cura_empty_instance_containers.empty_quality_changes_container # Initializes the version upgrade manager with by providing the paths for each resource type and the latest # versions. diff --git a/cura/CuraEmptyInstanceContainers.py b/cura/CuraEmptyInstanceContainers.py deleted file mode 100644 index 3f5d3e7c59..0000000000 --- a/cura/CuraEmptyInstanceContainers.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2018 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from UM.Settings.EmptyInstanceContainer import empty_container -import copy - -empty_definition_changes_container = copy.deepcopy(empty_container) -empty_definition_changes_container.setMetaDataEntry("id", "empty_definition_changes") -empty_definition_changes_container.setMetaDataEntry("type", "definition_changes") - -empty_variant_container = copy.deepcopy(empty_container) -empty_variant_container.setMetaDataEntry("id", "empty_variant") -empty_variant_container.setMetaDataEntry("type", "variant") - -empty_material_container = copy.deepcopy(empty_container) -empty_material_container.setMetaDataEntry("id", "empty_material") -empty_material_container.setMetaDataEntry("type", "material") - -empty_quality_container = copy.deepcopy(empty_container) -empty_quality_container.setMetaDataEntry("id", "empty_quality") -empty_quality_container.setName("Not Supported") -empty_quality_container.setMetaDataEntry("quality_type", "not_supported") -empty_quality_container.setMetaDataEntry("type", "quality") -empty_quality_container.setMetaDataEntry("supported", False) - -empty_quality_changes_container = copy.deepcopy(empty_container) -empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes") -empty_quality_changes_container.setMetaDataEntry("type", "quality_changes") -empty_quality_changes_container.setMetaDataEntry("quality_type", "not_supported") diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py index dabed97011..c8d1d9e370 100755 --- a/cura/Settings/CuraContainerStack.py +++ b/cura/Settings/CuraContainerStack.py @@ -13,8 +13,7 @@ from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.Interfaces import ContainerInterface, DefinitionContainerInterface -from UM.Settings.EmptyInstanceContainer import empty_container -from cura import CuraEmptyInstanceContainers +from cura.Settings import cura_empty_instance_containers from . import Exceptions @@ -41,12 +40,12 @@ class CuraContainerStack(ContainerStack): def __init__(self, container_id: str) -> None: super().__init__(container_id) - self._empty_instance_container = empty_container #type: InstanceContainer + self._empty_instance_container = cura_empty_instance_containers.empty_container #type: InstanceContainer - self._empty_quality_changes = CuraEmptyInstanceContainers.empty_quality_changes_container #type: InstanceContainer - self._empty_quality = CuraEmptyInstanceContainers.empty_quality_container #type: InstanceContainer - self._empty_material = CuraEmptyInstanceContainers.empty_material_container #type: InstanceContainer - self._empty_variant = CuraEmptyInstanceContainers.empty_variant_container #type: InstanceContainer + self._empty_quality_changes = cura_empty_instance_containers.empty_quality_changes_container #type: InstanceContainer + self._empty_quality = cura_empty_instance_containers.empty_quality_container #type: InstanceContainer + self._empty_material = cura_empty_instance_containers.empty_material_container #type: InstanceContainer + self._empty_variant = cura_empty_instance_containers.empty_variant_container #type: InstanceContainer self._containers = [self._empty_instance_container for i in range(len(_ContainerIndexes.IndexTypeMap))] #type: List[ContainerInterface] self._containers[_ContainerIndexes.QualityChanges] = self._empty_quality_changes diff --git a/cura/Settings/cura_empty_instance_containers.py b/cura/Settings/cura_empty_instance_containers.py new file mode 100644 index 0000000000..d76407ed79 --- /dev/null +++ b/cura/Settings/cura_empty_instance_containers.py @@ -0,0 +1,56 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +import copy + +from UM.Settings.constant_instance_containers import EMPTY_CONTAINER_ID, empty_container + + +# Empty definition changes +EMPTY_DEFINITION_CHANGES_CONTAINER_ID = "empty_definition_changes" +empty_definition_changes_container = copy.deepcopy(empty_container) +empty_definition_changes_container.setMetaDataEntry("id", EMPTY_DEFINITION_CHANGES_CONTAINER_ID) +empty_definition_changes_container.setMetaDataEntry("type", "definition_changes") + +# Empty variant +EMPTY_VARIANT_CONTAINER_ID = "empty_variant" +empty_variant_container = copy.deepcopy(empty_container) +empty_variant_container.setMetaDataEntry("id", EMPTY_VARIANT_CONTAINER_ID) +empty_variant_container.setMetaDataEntry("type", "variant") + +# Empty material +EMPTY_MATERIAL_CONTAINER_ID = "empty_material" +empty_material_container = copy.deepcopy(empty_container) +empty_material_container.setMetaDataEntry("id", EMPTY_MATERIAL_CONTAINER_ID) +empty_material_container.setMetaDataEntry("type", "material") + +# Empty quality +EMPTY_QUALITY_CONTAINER_ID = "empty_quality" +empty_quality_container = copy.deepcopy(empty_container) +empty_quality_container.setMetaDataEntry("id", EMPTY_QUALITY_CONTAINER_ID) +empty_quality_container.setName("Not Supported") +empty_quality_container.setMetaDataEntry("quality_type", "not_supported") +empty_quality_container.setMetaDataEntry("type", "quality") +empty_quality_container.setMetaDataEntry("supported", False) + +# Empty quality changes +EMPTY_QUALITY_CHANGES_CONTAINER_ID = "empty_quality_changes" +empty_quality_changes_container = copy.deepcopy(empty_container) +empty_quality_changes_container.setMetaDataEntry("id", EMPTY_QUALITY_CHANGES_CONTAINER_ID) +empty_quality_changes_container.setMetaDataEntry("type", "quality_changes") +empty_quality_changes_container.setMetaDataEntry("quality_type", "not_supported") + + +__all__ = ["EMPTY_CONTAINER_ID", + "empty_container", # For convenience + "EMPTY_DEFINITION_CHANGES_CONTAINER_ID", + "empty_definition_changes_container", + "EMPTY_VARIANT_CONTAINER_ID", + "empty_variant_container", + "EMPTY_MATERIAL_CONTAINER_ID", + "empty_material_container", + "EMPTY_QUALITY_CHANGES_CONTAINER_ID", + "empty_quality_changes_container", + "EMPTY_QUALITY_CONTAINER_ID", + "empty_quality_container" + ] diff --git a/tests/Settings/TestExtruderStack.py b/tests/Settings/TestExtruderStack.py index b2fa171068..df2e1075d1 100644 --- a/tests/Settings/TestExtruderStack.py +++ b/tests/Settings/TestExtruderStack.py @@ -9,9 +9,9 @@ import UM.Settings.ContainerRegistry #To create empty instance containers. import UM.Settings.ContainerStack #To set the container registry the container stacks use. from UM.Settings.DefinitionContainer import DefinitionContainer #To check against the class of DefinitionContainer. from UM.Settings.InstanceContainer import InstanceContainer #To check against the class of InstanceContainer. -from UM.Settings.EmptyInstanceContainer import empty_container from cura.Settings.Exceptions import InvalidContainerError, InvalidOperationError #To check whether the correct exceptions are raised. from cura.Settings.ExtruderManager import ExtruderManager +from cura.Settings.cura_empty_instance_containers import empty_container ## Gets an instance container with a specified container type. # diff --git a/tests/Settings/TestGlobalStack.py b/tests/Settings/TestGlobalStack.py index 7aba53c4e5..f8052aa4bb 100755 --- a/tests/Settings/TestGlobalStack.py +++ b/tests/Settings/TestGlobalStack.py @@ -9,11 +9,12 @@ from cura.Settings.Exceptions import InvalidContainerError, InvalidOperationErro from UM.Settings.DefinitionContainer import DefinitionContainer #To test against the class DefinitionContainer. from UM.Settings.InstanceContainer import InstanceContainer #To test against the class InstanceContainer. from UM.Settings.SettingInstance import InstanceState -from UM.Settings.EmptyInstanceContainer import empty_container import UM.Settings.ContainerRegistry import UM.Settings.ContainerStack import UM.Settings.SettingDefinition #To add settings to the definition. +from cura.Settings.cura_empty_instance_containers import empty_container + ## Gets an instance container with a specified container type. # # \param container_type The type metadata for the instance container. From e1e9c600160aba08345771a02dfeda365f80fdce Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Wed, 15 Aug 2018 13:56:51 +0200 Subject: [PATCH 174/243] Send UFP to Ultimakers provided the firmware version is sufficient. CL-980 --- plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py index 84e0a66170..e85961f619 100644 --- a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py @@ -113,7 +113,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): machine_file_formats = global_stack.getMetaDataEntry("file_formats").split(";") machine_file_formats = [file_type.strip() for file_type in machine_file_formats] #Exception for UM3 firmware version >=4.4: UFP is now supported and should be the preferred file format. - if "application/x-ufp" not in machine_file_formats and self.printerType == "ultimaker3" and Version(self.firmwareVersion) >= Version("4.4"): + if "application/x-ufp" not in machine_file_formats and Version(self.firmwareVersion) >= Version("4.4"): machine_file_formats = ["application/x-ufp"] + machine_file_formats # Take the intersection between file_formats and machine_file_formats. @@ -590,4 +590,4 @@ def findByKey(list: List[Union[PrintJobOutputModel, PrinterOutputModel]], key: s for item in list: if item.key == key: return item - return None \ No newline at end of file + return None From 8493948ba13315c92db9f0e40c189dc7d99ce410 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 15 Aug 2018 14:06:07 +0200 Subject: [PATCH 175/243] Add a favorite materials model Contributes to CURA-5162 --- cura/CuraApplication.py | 11 +++ .../Machines/Models/FavoriteMaterialsModel.py | 70 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 cura/Machines/Models/FavoriteMaterialsModel.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 23a11a2bb3..9823c0fadf 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -69,6 +69,7 @@ from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfile from cura.Machines.Models.CustomQualityProfilesDropDownMenuModel import CustomQualityProfilesDropDownMenuModel from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel from cura.Machines.Models.MaterialManagementModel import MaterialManagementModel +from cura.Machines.Models.FavoriteMaterialsModel import FavoriteMaterialsModel from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel from cura.Machines.Models.BrandMaterialsModel import BrandMaterialsModel from cura.Machines.Models.QualityManagementModel import QualityManagementModel @@ -501,6 +502,15 @@ class CuraApplication(QtApplication): preferences.addPreference("cura/sidebar_collapsed", False) self._need_to_show_user_agreement = not self.getPreferences().getValue("general/accepted_user_agreement") + favorites = [ + "ultimaker_cpe_green_ultimaker_s5_AA_0.4", + "ultimaker_pla_green_ultimaker_s5_AA_0.4", + "ultimaker_abs_grey_ultimaker_s5_AA_0.4", + "an_incorrect_id" + ] + preferences.addPreference("cura/favorite_materials", favorites) + print("FAVORITES ARE NOW SET") + for key in [ "dialog_load_path", # dialog_save_path is in LocalFileOutputDevicePlugin @@ -931,6 +941,7 @@ class CuraApplication(QtApplication): qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer") qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") + qmlRegisterType(FavoriteMaterialsModel, "Cura", 1, 0, "FavoriteMaterialsModel") qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") qmlRegisterType(MaterialManagementModel, "Cura", 1, 0, "MaterialManagementModel") diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py new file mode 100644 index 0000000000..f6932a61b8 --- /dev/null +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -0,0 +1,70 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from UM.Logger import Logger +from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel + +class FavoriteMaterialsModel(BaseMaterialsModel): + + def __init__(self, parent = None): + super().__init__(parent) + + from cura.CuraApplication import CuraApplication + self._preferences = CuraApplication.getInstance().getPreferences() + self._machine_manager = CuraApplication.getInstance().getMachineManager() + self._extruder_manager = CuraApplication.getInstance().getExtruderManager() + self._material_manager = CuraApplication.getInstance().getMaterialManager() + + self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines. + self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes. + + self._update() + + def _update(self): + Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) + + global_stack = self._machine_manager.activeMachine + if global_stack is None: + self.setItems([]) + return + extruder_position = str(self._extruder_position) + if extruder_position not in global_stack.extruders: + self.setItems([]) + return + extruder_stack = global_stack.extruders[extruder_position] + + available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) + if available_material_dict is None: + self.setItems([]) + return + + favorite_ids = self._preferences.getValue("cura/favorite_materials") + + item_list = [] + for root_material_id, container_node in available_material_dict.items(): + metadata = container_node.metadata + + # Only add results for favorite materials + if metadata["id"] not in favorite_ids: + continue + + # Do not include the materials from a to-be-removed package + if bool(metadata.get("removed", False)): + continue + + item = { + "root_material_id": root_material_id, + "id": metadata["id"], + "name": metadata["name"], + "brand": metadata["brand"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "container_node": container_node + } + item_list.append(item) + + # Sort the item list by material name alphabetically + item_list = sorted(item_list, key = lambda d: d["name"].upper()) + + print("FINAL FAVORITE LIST:", item_list) + self.setItems(item_list) From 57d41216e174fe97093d240f8f7bcac5a51c21d8 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 16 Aug 2018 13:04:17 +0200 Subject: [PATCH 176/243] Remove dummy favorites Contributes to CURA-5162 --- cura/CuraApplication.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 9823c0fadf..3cd49e591f 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -501,16 +501,9 @@ class CuraApplication(QtApplication): preferences.addPreference("view/filter_current_build_plate", False) preferences.addPreference("cura/sidebar_collapsed", False) - self._need_to_show_user_agreement = not self.getPreferences().getValue("general/accepted_user_agreement") - favorites = [ - "ultimaker_cpe_green_ultimaker_s5_AA_0.4", - "ultimaker_pla_green_ultimaker_s5_AA_0.4", - "ultimaker_abs_grey_ultimaker_s5_AA_0.4", - "an_incorrect_id" - ] - preferences.addPreference("cura/favorite_materials", favorites) - print("FAVORITES ARE NOW SET") + preferences.addPreference("cura/favorite_materials", []) + self._need_to_show_user_agreement = not preferences.getValue("general/accepted_user_agreement") for key in [ "dialog_load_path", # dialog_save_path is in LocalFileOutputDevicePlugin From e8cda9002186e03e2c6c74405633a7cdd82906a5 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 16 Aug 2018 13:04:58 +0200 Subject: [PATCH 177/243] Add favorites to materials menu Contributes to CURA-5162 --- .../Machines/Models/FavoriteMaterialsModel.py | 3 +- resources/qml/Menus/MaterialMenu.qml | 158 +++++++++++------- 2 files changed, 95 insertions(+), 66 deletions(-) diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index f6932a61b8..cbe59a1a09 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -45,7 +45,7 @@ class FavoriteMaterialsModel(BaseMaterialsModel): metadata = container_node.metadata # Only add results for favorite materials - if metadata["id"] not in favorite_ids: + if root_material_id not in favorite_ids: continue # Do not include the materials from a to-be-removed package @@ -66,5 +66,4 @@ class FavoriteMaterialsModel(BaseMaterialsModel): # Sort the item list by material name alphabetically item_list = sorted(item_list, key = lambda d: d["name"].upper()) - print("FINAL FAVORITE LIST:", item_list) self.setItems(item_list) diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index 64b3130724..a53bc72a94 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -14,68 +14,10 @@ Menu property int extruderIndex: 0 - Instantiator + Cura.FavoriteMaterialsModel { - model: genericMaterialsModel - MenuItem - { - text: model.name - checkable: true - checked: model.root_material_id == Cura.MachineManager.currentRootMaterialId[extruderIndex] - exclusiveGroup: group - onTriggered: - { - Cura.MachineManager.setMaterial(extruderIndex, model.container_node); - } - } - onObjectAdded: menu.insertItem(index, object) - onObjectRemoved: menu.removeItem(object) - } - MenuSeparator { } - Instantiator - { - model: brandModel - Menu - { - id: brandMenu - title: brandName - property string brandName: model.name - property var brandMaterials: model.materials - - Instantiator - { - model: brandMaterials - Menu - { - id: brandMaterialsMenu - title: materialName - property string materialName: model.name - property var brandMaterialColors: model.colors - - Instantiator - { - model: brandMaterialColors - MenuItem - { - text: model.name - checkable: true - checked: model.id == Cura.MachineManager.allActiveMaterialIds[Cura.ExtruderManager.extruderIds[extruderIndex]] - exclusiveGroup: group - onTriggered: - { - Cura.MachineManager.setMaterial(extruderIndex, model.container_node); - } - } - onObjectAdded: brandMaterialsMenu.insertItem(index, object) - onObjectRemoved: brandMaterialsMenu.removeItem(object) - } - } - onObjectAdded: brandMenu.insertItem(index, object) - onObjectRemoved: brandMenu.removeItem(object) - } - } - onObjectAdded: menu.insertItem(index, object) - onObjectRemoved: menu.removeItem(object) + id: favoriteMaterialsModel + extruderPosition: menu.extruderIndex } Cura.GenericMaterialsModel @@ -90,9 +32,97 @@ Menu extruderPosition: menu.extruderIndex } - ExclusiveGroup { id: group } + Instantiator + { + model: favoriteMaterialsModel + delegate: MenuItem + { + text: model.brand + " " + model.name + checkable: true + checked: model.root_material_id == Cura.MachineManager.currentRootMaterialId[extruderIndex] + onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node) + exclusiveGroup: group + } + onObjectAdded: menu.insertItem(index, object) + onObjectRemoved: menu.removeItem(object) // TODO: This ain't gonna work, removeItem() takes an index, not object + } - MenuSeparator { } + MenuSeparator {} - MenuItem { action: Cura.Actions.manageMaterials } + Menu + { + id: genericMenu + title: "Generic" + + Instantiator + { + model: genericMaterialsModel + delegate: MenuItem + { + text: model.name + checkable: true + checked: model.root_material_id == Cura.MachineManager.currentRootMaterialId[extruderIndex] + exclusiveGroup: group + onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node) + } + onObjectAdded: genericMenu.insertItem(index, object) + onObjectRemoved: genericMenu.removeItem(object) // TODO: This ain't gonna work, removeItem() takes an index, not object + } + } + + MenuSeparator {} + + Instantiator + { + model: brandModel + Menu + { + id: brandMenu + title: brandName + property string brandName: model.name + property var brandMaterials: model.materials + + Instantiator + { + model: brandMaterials + delegate: Menu + { + id: brandMaterialsMenu + title: materialName + property string materialName: model.name + property var brandMaterialColors: model.colors + + Instantiator + { + model: brandMaterialColors + delegate: MenuItem + { + text: model.name + checkable: true + checked: model.id == Cura.MachineManager.allActiveMaterialIds[Cura.ExtruderManager.extruderIds[extruderIndex]] + exclusiveGroup: group + onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node) + } + onObjectAdded: brandMaterialsMenu.insertItem(index, object) + onObjectRemoved: brandMaterialsMenu.removeItem(object) + } + } + onObjectAdded: brandMenu.insertItem(index, object) + onObjectRemoved: brandMenu.removeItem(object) + } + } + onObjectAdded: menu.insertItem(index, object) + onObjectRemoved: menu.removeItem(object) + } + + ExclusiveGroup { + id: group + } + + MenuSeparator {} + + MenuItem + { + action: Cura.Actions.manageMaterials + } } From 6c1d380602ed9ff0fc901716d2376ff3969fb55b Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 16 Aug 2018 13:45:27 +0200 Subject: [PATCH 178/243] Renamed snap_distance to minimum_polygon_circumference and changed the description a bit. CURA-5623 --- resources/definitions/fdmprinter.def.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 8b3e4e1f05..4ea5f8a600 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5625,10 +5625,10 @@ "settable_per_mesh": false, "settable_per_extruder": true }, - "snap_distance": + "minimum_polygon_circumference": { - "label": "Snap Distance", - "description": "Snap distance between polygons in mm. Controls the polygons that may be filtered out when the model is sliced. Lower values lead to higher resolution mesh at the cost of slicing time. It is meant mostly for high resolution SLA printers and very tiny 3D models with a lot of details.", + "label": "Minimum polygon circumference", + "description": "Polygons in sliced layers that have a circumference smaller than this amount will be filtered out. Lower values lead to higher resolution mesh at the cost of slicing time. It is meant mostly for high resolution SLA printers and very tiny 3D models with a lot of details.", "unit": "mm", "type": "float", "default_value": 1.0, From 376b6a53c935035ac9dc1b0aab29360d9b18a762 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 16 Aug 2018 13:47:32 +0200 Subject: [PATCH 179/243] Capital Letters In Setting Name. CURA-5623 --- 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 daf0af4d64..d26b2b03f4 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5628,7 +5628,7 @@ }, "minimum_polygon_circumference": { - "label": "Minimum polygon circumference", + "label": "Minimum Polygon Circumference", "description": "Polygons in sliced layers that have a circumference smaller than this amount will be filtered out. Lower values lead to higher resolution mesh at the cost of slicing time. It is meant mostly for high resolution SLA printers and very tiny 3D models with a lot of details.", "unit": "mm", "type": "float", From f42dc24d950df902cae9cf76dd817e7f2d13a9a2 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 16 Aug 2018 15:16:30 +0200 Subject: [PATCH 180/243] Do not show gcode.gz as an option in save file dialog CURA-5649 --- cura/CuraApplication.py | 20 -------------------- cura/Settings/GlobalStack.py | 4 ++++ plugins/GCodeGzWriter/__init__.py | 3 ++- resources/qml/SaveButton.qml | 4 +++- 4 files changed, 9 insertions(+), 22 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 23a11a2bb3..dab3de3ab8 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -215,7 +215,6 @@ class CuraApplication(QtApplication): self._message_box_callback = None self._message_box_callback_arguments = [] - self._preferred_mimetype = "" self._i18n_catalog = None self._currently_loading_files = [] @@ -514,9 +513,6 @@ class CuraApplication(QtApplication): self.applicationShuttingDown.connect(self.saveSettings) self.engineCreatedSignal.connect(self._onEngineCreated) - self.globalContainerStackChanged.connect(self._onGlobalContainerChanged) - self._onGlobalContainerChanged() - self.getCuraSceneController().setActiveBuildPlate(0) # Initialize CuraApplication.Created = True @@ -997,30 +993,14 @@ class CuraApplication(QtApplication): self._camera_animation.setTarget(Selection.getSelectedObject(0).getWorldPosition()) self._camera_animation.start() - def _onGlobalContainerChanged(self): - if self._global_container_stack is not None: - machine_file_formats = [file_type.strip() for file_type in self._global_container_stack.getMetaDataEntry("file_formats").split(";")] - new_preferred_mimetype = "" - if machine_file_formats: - new_preferred_mimetype = machine_file_formats[0] - - if new_preferred_mimetype != self._preferred_mimetype: - self._preferred_mimetype = new_preferred_mimetype - self.preferredOutputMimetypeChanged.emit() - requestAddPrinter = pyqtSignal() activityChanged = pyqtSignal() sceneBoundingBoxChanged = pyqtSignal() - preferredOutputMimetypeChanged = pyqtSignal() @pyqtProperty(bool, notify = activityChanged) def platformActivity(self): return self._platform_activity - @pyqtProperty(str, notify=preferredOutputMimetypeChanged) - def preferredOutputMimetype(self): - return self._preferred_mimetype - @pyqtProperty(str, notify = sceneBoundingBoxChanged) def getSceneBoundingBoxString(self): return self._i18n_catalog.i18nc("@info 'width', 'depth' and 'height' are variable names that must NOT be translated; just translate the format of ##x##x## mm.", "%(width).1f x %(depth).1f x %(height).1f mm") % {'width' : self._scene_bounding_box.width.item(), 'depth': self._scene_bounding_box.depth.item(), 'height' : self._scene_bounding_box.height.item()} diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index dda21f3719..36084b7d4d 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -61,6 +61,10 @@ class GlobalStack(CuraContainerStack): name = self.variant.getName() return name + @pyqtProperty(str, constant = True) + def preferred_output_file_formats(self) -> str: + return self.getMetaDataEntry("file_formats") + ## Add an extruder to the list of extruders of this stack. # # \param extruder The extruder to add. diff --git a/plugins/GCodeGzWriter/__init__.py b/plugins/GCodeGzWriter/__init__.py index e257bcb011..95949eee74 100644 --- a/plugins/GCodeGzWriter/__init__.py +++ b/plugins/GCodeGzWriter/__init__.py @@ -16,7 +16,8 @@ def getMetaData(): "extension": file_extension, "description": catalog.i18nc("@item:inlistbox", "Compressed G-code File"), "mime_type": "application/gzip", - "mode": GCodeGzWriter.GCodeGzWriter.OutputMode.BinaryMode + "mode": GCodeGzWriter.GCodeGzWriter.OutputMode.BinaryMode, + "hide_in_file_dialog": True, }] } } diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index 0e0eec7277..2a0a523026 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -7,6 +7,7 @@ import QtQuick.Controls.Styles 1.1 import QtQuick.Layouts 1.1 import UM 1.1 as UM +import Cura 1.0 as Cura Item { id: base; @@ -257,7 +258,8 @@ Item { onClicked: { forceActiveFocus(); - UM.OutputDeviceManager.requestWriteToDevice(UM.OutputDeviceManager.activeDevice, PrintInformation.jobName, { "filter_by_machine": true, "preferred_mimetype":Printer.preferredOutputMimetype }); + UM.OutputDeviceManager.requestWriteToDevice(UM.OutputDeviceManager.activeDevice, PrintInformation.jobName, + { "filter_by_machine": true, "preferred_mimetypes": Cura.MachineManager.activeMachine.preferred_output_file_formats }); } style: ButtonStyle { From 31e283110f97189e7b5a38b025969fe25ed7e8e7 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 17 Aug 2018 09:29:08 +0200 Subject: [PATCH 181/243] Check first if preferred quality exists Fixes #3784. --- cura/Settings/CuraStackBuilder.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index a794dde651..31ebc04de2 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -108,16 +108,20 @@ class CuraStackBuilder: preferred_quality_type = machine_definition.getMetaDataEntry("preferred_quality_type") quality_group_dict = quality_manager.getQualityGroups(new_global_stack) - quality_group = quality_group_dict.get(preferred_quality_type) + if quality_group_dict: #There are any quality profiles. + if preferred_quality_type not in quality_group_dict: + Logger.log("w", "The preferred quality {quality_type} doesn't exist for this set-up. Choosing a random one.".format(quality_type = preferred_quality_type)) + preferred_quality_type = next(iter(quality_group_dict)) + quality_group = quality_group_dict.get(preferred_quality_type) - new_global_stack.quality = quality_group.node_for_global.getContainer() - if not new_global_stack.quality: - new_global_stack.quality = application.empty_quality_container - for position, extruder_stack in new_global_stack.extruders.items(): - if position in quality_group.nodes_for_extruders and quality_group.nodes_for_extruders[position].getContainer(): - extruder_stack.quality = quality_group.nodes_for_extruders[position].getContainer() - else: - extruder_stack.quality = application.empty_quality_container + new_global_stack.quality = quality_group.node_for_global.getContainer() + if not new_global_stack.quality: + new_global_stack.quality = application.empty_quality_container + for position, extruder_stack in new_global_stack.extruders.items(): + if position in quality_group.nodes_for_extruders and quality_group.nodes_for_extruders[position].getContainer(): + extruder_stack.quality = quality_group.nodes_for_extruders[position].getContainer() + else: + extruder_stack.quality = application.empty_quality_container # Register the global stack after the extruder stacks are created. This prevents the registry from adding another # extruder stack because the global stack didn't have one yet (which is enforced since Cura 3.1). From 013032279db10b858b5bbd8b2115de762723665e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 17 Aug 2018 10:00:28 +0200 Subject: [PATCH 182/243] Better handling of no quality group in CuraStackBuilder --- cura/Settings/CuraStackBuilder.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 31ebc04de2..12fe732e3e 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -108,7 +108,14 @@ class CuraStackBuilder: preferred_quality_type = machine_definition.getMetaDataEntry("preferred_quality_type") quality_group_dict = quality_manager.getQualityGroups(new_global_stack) - if quality_group_dict: #There are any quality profiles. + if not quality_group_dict: + # There is no available quality group, set all quality containers to empty. + new_global_stack.quality = application.empty_quality_container + for extruder_stack in new_global_stack.extruders.values(): + extruder_stack.quality = application.empty_quality_container + else: + # Set the quality containers to the preferred quality type if available, otherwise use the first quality + # type that's available. if preferred_quality_type not in quality_group_dict: Logger.log("w", "The preferred quality {quality_type} doesn't exist for this set-up. Choosing a random one.".format(quality_type = preferred_quality_type)) preferred_quality_type = next(iter(quality_group_dict)) From 1079a9be2c72de8d4c32895701e9842e1521fd09 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 17 Aug 2018 10:53:01 +0200 Subject: [PATCH 183/243] Do not add saved gcodes to recent files list --- plugins/GCodeGzWriter/GCodeGzWriter.py | 4 ++++ plugins/GCodeWriter/GCodeWriter.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/GCodeGzWriter/GCodeGzWriter.py b/plugins/GCodeGzWriter/GCodeGzWriter.py index e191a9c427..cbbfb8f986 100644 --- a/plugins/GCodeGzWriter/GCodeGzWriter.py +++ b/plugins/GCodeGzWriter/GCodeGzWriter.py @@ -17,6 +17,10 @@ catalog = i18nCatalog("cura") # # If you're zipping g-code, you might as well use gzip! class GCodeGzWriter(MeshWriter): + + def __init__(self) -> None: + super().__init__(add_to_recent_files = False) + ## Writes the gzipped g-code to a stream. # # Note that even though the function accepts a collection of nodes, the diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index 59e9a29691..5d5e3578cd 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -47,7 +47,7 @@ class GCodeWriter(MeshWriter): _setting_keyword = ";SETTING_" def __init__(self): - super().__init__() + super().__init__(add_to_recent_files = False) self._application = Application.getInstance() From 284f90f3ff7ec3422fe490d1bd0942f506fc35af Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 17 Aug 2018 09:57:37 +0200 Subject: [PATCH 184/243] Fix camera position before adding a printer Don't use the diagonal size then, because that returns 0. --- cura/CuraApplication.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 23a11a2bb3..ef59d5a7f6 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -780,7 +780,10 @@ class CuraApplication(QtApplication): # Initialize camera root = controller.getScene().getRoot() camera = Camera("3d", root) - camera.setPosition(Vector(-80, 250, 700) * self.getBuildVolume().getDiagonalSize() / 375) + diagonal = self.getBuildVolume().getDiagonalSize() + if diagonal < 1: #No printer added yet. Set a default camera distance for normal-sized printers. + diagonal = 375 + camera.setPosition(Vector(-80, 250, 700) * diagonal / 375) camera.setPerspective(True) camera.lookAt(Vector(0, 0, 0)) controller.getScene().setActiveCamera("3d") From 9f190590b1e5ceac0fcd0942bfcf39807071d617 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 17 Aug 2018 10:56:29 +0200 Subject: [PATCH 185/243] Only change camera range if camera range is valid This was a debugging test to see if this fixed an issue. It turned out to not be the issue in question, but this is still a defensive coding thing that would be good to have. --- cura/BuildVolume.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 5aa3873c89..a25552aac5 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -561,7 +561,9 @@ class BuildVolume(SceneNode): camera = Application.getInstance().getController().getCameraTool() if camera: - camera.setZoomRange(min = 1, max = self.getDiagonalSize() * 5) #You can zoom out up to 5 times the diagonal. This gives some space around the volume. + diagonal = self.getDiagonalSize() + if diagonal > 1: + camera.setZoomRange(min = 0.1, max = diagonal * 5) #You can zoom out up to 5 times the diagonal. This gives some space around the volume. def _onEngineCreated(self): self._engine_ready = True From 6740c2bee9a0732daf77224cd4ef34f0eb736364 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 17 Aug 2018 11:24:39 +0200 Subject: [PATCH 186/243] Fix offset of initial layer height It would detect the height of the raft by looking at what the first Z coordinate is that it encounters on layer 0. This Z coordinate also includes the initial layer height though. If you pause lower than the initial layer height (but higher than 0), you'd expect to pause in the initial layer. --- plugins/PostProcessingPlugin/scripts/PauseAtHeight.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py index 6354dd4f04..8b50a88b7f 100644 --- a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py +++ b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py @@ -28,7 +28,7 @@ class PauseAtHeight(Script): "pause_height": { "label": "Pause Height", - "description": "At what height should the pause occur", + "description": "At what height should the pause occur?", "unit": "mm", "type": "float", "default_value": 5.0, @@ -39,7 +39,7 @@ class PauseAtHeight(Script): "pause_layer": { "label": "Pause Layer", - "description": "At what layer should the pause occur", + "description": "At what layer should the pause occur?", "type": "int", "value": "math.floor((pause_height - 0.27) / 0.1) + 1", "minimum_value": "0", @@ -142,13 +142,14 @@ class PauseAtHeight(Script): standby_temperature = self.getSettingValueByKey("standby_temperature") firmware_retract = Application.getInstance().getGlobalContainerStack().getProperty("machine_firmware_retract", "value") control_temperatures = Application.getInstance().getGlobalContainerStack().getProperty("machine_nozzle_temp_enabled", "value") + initial_layer_height = Application.getInstance().getGlobalContainerStack().getProperty("layer_height_0", "value") is_griffin = False # T = ExtruderManager.getInstance().getActiveExtruderStack().getProperty("material_print_temperature", "value") # use offset to calculate the current height: = - - layer_0_z = 0. + layer_0_z = 0 current_z = 0 got_first_g_cmd_on_layer_0 = False current_t = 0 #Tracks the current extruder for tracking the target temperature. @@ -195,11 +196,10 @@ class PauseAtHeight(Script): # This block is executed once, the first time there is a G # command, to get the z offset (z for first positive layer) if not got_first_g_cmd_on_layer_0: - layer_0_z = current_z + layer_0_z = current_z - initial_layer_height got_first_g_cmd_on_layer_0 = True current_height = current_z - layer_0_z - if current_height < pause_height: break # Try the next layer. From 1468ac1d59ec4fbf4472c03b7d7a727c636c2a6e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 20 Aug 2018 13:19:49 +0200 Subject: [PATCH 187/243] Check if dict has key before accessing in BuildVolume --- cura/BuildVolume.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index a25552aac5..b029665abd 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -242,6 +242,8 @@ class BuildVolume(SceneNode): # Mark the node as outside build volume if the set extruder is disabled extruder_position = node.callDecoration("getActiveExtruderPosition") + if extruder_position not in self._global_container_stack.extruders: + continue if not self._global_container_stack.extruders[extruder_position].isEnabled: node.setOutsideBuildArea(True) continue From 2410c21839d0b0ebbb74f9c3ba7c0b9c6f602e05 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 20 Aug 2018 17:16:05 +0200 Subject: [PATCH 188/243] Move material list to separate QML file Contributes to CURA-5378 --- resources/qml/Preferences/MaterialsList.qml | 266 ++++++++++++++++++++ resources/qml/Preferences/MaterialsPage.qml | 116 +-------- 2 files changed, 279 insertions(+), 103 deletions(-) create mode 100644 resources/qml/Preferences/MaterialsList.qml diff --git a/resources/qml/Preferences/MaterialsList.qml b/resources/qml/Preferences/MaterialsList.qml new file mode 100644 index 0000000000..db0f5461ec --- /dev/null +++ b/resources/qml/Preferences/MaterialsList.qml @@ -0,0 +1,266 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.2 +import UM 1.2 as UM +import Cura 1.0 as Cura + +Item +{ + id: materialList + UM.I18nCatalog { id: catalog; name: "cura"; } + Cura.BrandMaterialsModel { id: materialsModel } + Cura.GenericMaterialsModel { id: genericMaterialsModel } + + width: materialScrollView.width - 20 + height: childrenRect.height + + + Column + { + Rectangle + { + height: 23 + width: materialList.width + Label + { + text: "Generic" + } + } + Repeater + { + model: genericMaterialsModel + delegate: Rectangle + { + height: 23 + width: materialList.width + color: "green" + Label + { + text: model.name + } + } + } + Repeater + { + id: brand_list + + model: materialsModel + delegate: Rectangle + { + id: brand_section + property var expanded: true + property var types_model: model.materials + height: childrenRect.height + width: parent.width + Rectangle + { + id: brand_header_background + color: "grey" + anchors.fill: brand_header + } + Row + { + id: brand_header + width: parent.width + Label + { + id: brand_name + text: model.name + height: 24 + width: parent.width - 24 + verticalAlignment: Text.AlignVCenter + leftPadding: 4 + } + Button + { + text: "" + implicitWidth: 24 + implicitHeight: 24 + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: "black" + source: brand_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + } + } + MouseArea + { + anchors.fill: brand_header + onPressed: + { + brand_section.expanded = !brand_section.expanded + } + } + Column + { + anchors.top: brand_header.bottom + width: parent.width - leftPadding + anchors.left: parent.left + leftPadding: 8 + height: brand_section.expanded ? childrenRect.height : 0 + visible: brand_section.expanded + Repeater + { + model: types_model + delegate: Rectangle + { + id: material_type_section + property var expanded: true + property var colors_model: model.colors + height: childrenRect.height + width: parent.width + Rectangle + { + id: material_type_header_background + color: "grey" + anchors.bottom: material_type_header.bottom + height: 1 + width: parent.width + } + Row + { + id: material_type_header + width: parent.width + + Label + { + text: model.name + height: 24 + width: parent.width - 24 + id: material_type_name + verticalAlignment: Text.AlignVCenter + } + Button + { + text: "" + implicitWidth: 24 + implicitHeight: 24 + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: "black" + source: material_type_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + } + } + MouseArea + { + anchors.fill: material_type_header + onPressed: + { + material_type_section.expanded = !material_type_section.expanded + } + } + Column + { + height: material_type_section.expanded ? childrenRect.height : 0 + visible: material_type_section.expanded + width: parent.width - leftPadding + anchors.top: material_type_header.bottom + leftPadding: 8 + anchors.left: parent.left + Repeater + { + model: colors_model + delegate: Rectangle + { + height: 24 + width: parent.width +// color: "green" + Row + { + height: parent.height + width: parent.width + Rectangle + { + id: swatch + color: model.color_code + border.width: 1 + border.color: "black" + width: 14 + height: 14 + anchors.verticalCenter: parent.verticalCenter + } + Label + { + text: model.name + verticalAlignment: Text.AlignVCenter + height: 24 + anchors.left: swatch.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: 4 + } + MouseArea + { + anchors.fill: parent + onClicked: + { + print(model.guid) + } + } + Button + { + text: "+" + implicitWidth: 24 + implicitHeight: 24 + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + onClicked: + { + if (model.is_favorite) { + base.materialManager.removeFavorite(model.root_material_id) + model.is_favorite = false + return + } + base.materialManager.addFavorite(model.root_material_id) + model.is_favorite = true + return + } + } + } + } + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index e2e3edec2f..07b5da3f4e 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -17,12 +17,19 @@ Item property QtObject materialManager: CuraApplication.getMaterialManager() property var resetEnabled: false // Keep PreferencesDialog happy - UM.I18nCatalog { id: catalog; name: "cura"; } - - Cura.MaterialManagementModel + UM.I18nCatalog + { + id: catalog + name: "cura" + } + Cura.BrandMaterialsModel { id: materialsModel } + Cura.GenericMaterialsModel + { + id: genericMaterialsModel + } Label { @@ -366,104 +373,7 @@ Item width: true ? (parent.width * 0.4) | 0 : parent.width frameVisible: true - ListView - { - id: materialListView - - model: materialsModel - - section.property: "brand" - section.criteria: ViewSection.FullString - section.delegate: Rectangle - { - width: materialScrollView.width - height: childrenRect.height - color: palette.light - - Label - { - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_lining").width - text: section - font.bold: true - color: palette.text - } - } - - delegate: Rectangle - { - width: materialScrollView.width - height: childrenRect.height - color: ListView.isCurrentItem ? palette.highlight : (model.index % 2) ? palette.base : palette.alternateBase - - Row - { - id: materialRow - spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.right: parent.right - - property bool isCurrentItem: parent.ListView.isCurrentItem - - property bool isItemActivated: - { - const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - return model.root_material_id == root_material_id; - } - - Rectangle - { - width: Math.floor(parent.height * 0.8) - height: Math.floor(parent.height * 0.8) - color: model.color_code - border.color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; - anchors.verticalCenter: parent.verticalCenter - } - Label - { - width: Math.floor((parent.width * 0.3)) - text: model.material - elide: Text.ElideRight - font.italic: materialRow.isItemActivated - color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; - } - Label - { - text: (model.name != model.material) ? model.name : "" - elide: Text.ElideRight - font.italic: materialRow.isItemActivated - color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; - } - } - - MouseArea - { - anchors.fill: parent - onClicked: - { - parent.ListView.view.currentIndex = model.index; - } - } - } - - function activateDetailsWithIndex(index) - { - var model = materialsModel.getItem(index); - base.currentItem = model; - materialDetailsView.containerId = model.container_id; - materialDetailsView.currentMaterialNode = model.container_node; - - detailsPanel.updateMaterialPropertiesObject(); - } - - onCurrentIndexChanged: - { - forceActiveFocus(); // causes the changed fields to be saved - activateDetailsWithIndex(currentIndex); - } - } + MaterialsList {} } @@ -480,9 +390,9 @@ Item right: parent.right } - function updateMaterialPropertiesObject() + function updateMaterialPropertiesObject( currentItem ) { - var currentItem = materialsModel.getItem(materialListView.currentIndex); +// var currentItem = materialsModel.getItem(materialListView.currentIndex); materialProperties.name = currentItem.name ? currentItem.name : "Unknown"; materialProperties.guid = currentItem.guid; From 68bccd8bf7cf9a6382d988fa538f7fc958ab776b Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 20 Aug 2018 17:16:54 +0200 Subject: [PATCH 189/243] Improve the Favorites, Base, and Brand materials models (WIP) Contribuetes to CURA-5378 --- cura/Machines/Models/BaseMaterialsModel.py | 4 ++ cura/Machines/Models/BrandMaterialsModel.py | 40 +++++++++++++------ .../Machines/Models/FavoriteMaterialsModel.py | 6 ++- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 4759c8b5b0..ceba1f6eeb 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -21,6 +21,8 @@ class BaseMaterialsModel(ListModel): MaterialRole = Qt.UserRole + 5 ColorRole = Qt.UserRole + 6 ContainerNodeRole = Qt.UserRole + 7 + ColorCodeRole = Qt.UserRole + 8 + GUIDRole = Qt.UserRole + 9 extruderPositionChanged = pyqtSignal() @@ -31,10 +33,12 @@ class BaseMaterialsModel(ListModel): self.addRoleName(self.RootMaterialIdRole, "root_material_id") self.addRoleName(self.IdRole, "id") + self.addRoleName(self.GUIDRole, "guid") self.addRoleName(self.NameRole, "name") self.addRoleName(self.BrandRole, "brand") self.addRoleName(self.MaterialRole, "material") self.addRoleName(self.ColorRole, "color_name") + self.addRoleName(self.ColorCodeRole, "color_code") self.addRoleName(self.ContainerNodeRole, "container_node") self._extruder_position = 0 diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py index ad48b3ea21..c5edd6e57c 100644 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ b/cura/Machines/Models/BrandMaterialsModel.py @@ -50,6 +50,7 @@ class BrandMaterialsModel(ListModel): self._extruder_stack = None from cura.CuraApplication import CuraApplication + self._container_registry = CuraApplication.getInstance().getContainerRegistry() self._machine_manager = CuraApplication.getInstance().getMachineManager() self._extruder_manager = CuraApplication.getInstance().getExtruderManager() self._material_manager = CuraApplication.getInstance().getMaterialManager() @@ -104,30 +105,45 @@ class BrandMaterialsModel(ListModel): brand_group_dict = {} for root_material_id, container_node in available_material_dict.items(): metadata = container_node.metadata - brand = metadata["brand"] - # Only add results for generic materials - if brand.lower() == "generic": - continue + # Do not include the materials from a to-be-removed package if bool(metadata.get("removed", False)): continue + # Skip generic materials, and add brands we haven't seen yet to the dict + brand = metadata["brand"] + if brand.lower() == "generic": + continue if brand not in brand_group_dict: brand_group_dict[brand] = {} + # Add material types we haven't seen yet to the dict material_type = metadata["material"] if material_type not in brand_group_dict[brand]: brand_group_dict[brand][material_type] = [] - item = {"root_material_id": root_material_id, - "id": metadata["id"], - "name": metadata["name"], - "brand": metadata["brand"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "container_node": container_node - } + # Now handle the individual materials + item = { + "root_material_id": root_material_id, + # "root_material_id": container_node.metadata["base_file"] <- as written in material management model + "id": metadata["id"], + "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml + "guid": metadata["GUID"], + "name": metadata["name"], + "brand": metadata["brand"], + "description": metadata["description"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "color_code": metadata["color_code"], + "density": metadata.get("properties", {}).get("density", ""), + "diameter": metadata.get("properties", {}).get("diameter", ""), + "approximate_diameter": metadata["approximate_diameter"], + "adhesion_info": metadata["adhesion_info"], + "is_read_only": self._container_registry.isReadOnly(metadata["id"]), + "container_node": container_node, + "is_favorite": False + } brand_group_dict[brand][material_type].append(item) for brand, material_dict in brand_group_dict.items(): diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index cbe59a1a09..9d05f8cb4a 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -17,7 +17,7 @@ class FavoriteMaterialsModel(BaseMaterialsModel): self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines. self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes. - + self._material_manager.favoritesUpdated.connect(self._update) # Update when favorites are changed self._update() def _update(self): @@ -38,7 +38,9 @@ class FavoriteMaterialsModel(BaseMaterialsModel): self.setItems([]) return - favorite_ids = self._preferences.getValue("cura/favorite_materials") + favorite_ids = self._material_manager.getFavorites() + + print("favorite_ids:", favorite_ids) item_list = [] for root_material_id, container_node in available_material_dict.items(): From 6d1fd8281ca0d5bd267b68c1fdc13922da98bab1 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 20 Aug 2018 17:17:14 +0200 Subject: [PATCH 190/243] Add favorites funcitonality to MaterialManager.py Contributes to CURA-5378 --- cura/Machines/MaterialManager.py | 40 +++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index d5a7d5d089..d59aa07590 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -4,6 +4,7 @@ from collections import defaultdict, OrderedDict import copy import uuid +import json from typing import Dict, Optional, TYPE_CHECKING from PyQt5.Qt import QTimer, QObject, pyqtSignal, pyqtSlot @@ -38,7 +39,8 @@ if TYPE_CHECKING: # class MaterialManager(QObject): - materialsUpdated = pyqtSignal() # Emitted whenever the material lookup tables are updated. + materialsUpdated = pyqtSignal() # Emitted whenever the material lookup tables are updated. + favoritesUpdated = pyqtSignal() # Emitted whenever the favorites are changed def __init__(self, container_registry, parent = None): super().__init__(parent) @@ -75,6 +77,8 @@ class MaterialManager(QObject): self._container_registry.containerAdded.connect(self._onContainerMetadataChanged) self._container_registry.containerRemoved.connect(self._onContainerMetadataChanged) + self._favorites = set() + def initialize(self): # Find all materials and put them in a matrix for quick search. material_metadatas = {metadata["id"]: metadata for metadata in @@ -194,6 +198,14 @@ class MaterialManager(QObject): self.materialsUpdated.emit() + favorites = self._application.getPreferences().getValue("cura/favorite_materials") + print(favorites) + for item in favorites: + print(item) + self._favorites.add(item) + print("LOADED FAVES", self._favorites) + self.favoritesUpdated.emit() + def __addMaterialMetadataIntoLookupTree(self, material_metadata: dict) -> None: material_id = material_metadata["id"] @@ -608,3 +620,29 @@ class MaterialManager(QObject): new_base_id = new_id, new_metadata = new_metadata) return new_id + + @pyqtSlot(str) + def addFavorite(self, root_material_id: str): + print(root_material_id) + self._favorites.add(root_material_id) + self.favoritesUpdated.emit() + print(self._favorites) + print(list(self._favorites)) + + # Ensure all settings are saved. + self._application.getPreferences().setValue("cura/favorite_materials", list(self._favorites)) + self._application.saveSettings() + + @pyqtSlot(str) + def removeFavorite(self, root_material_id: str): + self._favorites.remove(root_material_id) + self.favoritesUpdated.emit() + print(self._favorites) + + # Ensure all settings are saved. + self._application.getPreferences().setValue("cura/favorite_materials", list(self._favorites)) + self._application.saveSettings() + + @pyqtSlot() + def getFavorites(self): + return self._favorites \ No newline at end of file From ca25638c07d699002980dab7564a9b5743582b50 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 21 Aug 2018 11:01:35 +0200 Subject: [PATCH 191/243] .ufp should also not show up in recent files since it's a gcode format --- .pytest_cache/README.md | 8 +++ .pytest_cache/v/cache/lastfailed | 100 +++++++++++++++++++++++++++++++ .pytest_cache/v/cache/nodeids | 3 + plugins/UFPWriter/UFPWriter.py | 2 +- 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 .pytest_cache/README.md create mode 100644 .pytest_cache/v/cache/lastfailed create mode 100644 .pytest_cache/v/cache/nodeids diff --git a/.pytest_cache/README.md b/.pytest_cache/README.md new file mode 100644 index 0000000000..bb78ba07ee --- /dev/null +++ b/.pytest_cache/README.md @@ -0,0 +1,8 @@ +# pytest cache directory # + +This directory contains data from the pytest's cache plugin, +which provides the `--lf` and `--ff` options, as well as the `cache` fixture. + +**Do not** commit this to version control. + +See [the docs](https://docs.pytest.org/en/latest/cache.html) for more information. diff --git a/.pytest_cache/v/cache/lastfailed b/.pytest_cache/v/cache/lastfailed new file mode 100644 index 0000000000..adb96c8331 --- /dev/null +++ b/.pytest_cache/v/cache/lastfailed @@ -0,0 +1,100 @@ +{ + "tests/Settings/TestCuraContainerRegistry.py::test_addContainerBadSettingVersion": true, + "tests/Settings/TestCuraContainerRegistry.py::test_addContainerExtruderStack": true, + "tests/Settings/TestCuraContainerRegistry.py::test_addContainerGlobalStack": true, + "tests/Settings/TestCuraContainerRegistry.py::test_addContainerGoodSettingVersion": true, + "tests/Settings/TestCuraContainerRegistry.py::test_addContainerNoSettingVersion": true, + "tests/Settings/TestExtruderStack.py::test_addContainer": true, + "tests/Settings/TestExtruderStack.py::test_constrainDefinitionValid[container0]": true, + "tests/Settings/TestExtruderStack.py::test_constrainDefinitionValid[container1]": true, + "tests/Settings/TestExtruderStack.py::test_constrainMaterialInvalid[container0]": true, + "tests/Settings/TestExtruderStack.py::test_constrainMaterialInvalid[container1]": true, + "tests/Settings/TestExtruderStack.py::test_constrainMaterialInvalid[container2]": true, + "tests/Settings/TestExtruderStack.py::test_constrainMaterialValid[container0]": true, + "tests/Settings/TestExtruderStack.py::test_constrainMaterialValid[container1]": true, + "tests/Settings/TestExtruderStack.py::test_constrainQualityChangesInvalid[container0]": true, + "tests/Settings/TestExtruderStack.py::test_constrainQualityChangesInvalid[container1]": true, + "tests/Settings/TestExtruderStack.py::test_constrainQualityChangesInvalid[container2]": true, + "tests/Settings/TestExtruderStack.py::test_constrainQualityChangesValid[container0]": true, + "tests/Settings/TestExtruderStack.py::test_constrainQualityChangesValid[container1]": true, + "tests/Settings/TestExtruderStack.py::test_constrainQualityInvalid[container0]": true, + "tests/Settings/TestExtruderStack.py::test_constrainQualityInvalid[container1]": true, + "tests/Settings/TestExtruderStack.py::test_constrainQualityInvalid[container2]": true, + "tests/Settings/TestExtruderStack.py::test_constrainQualityValid[container0]": true, + "tests/Settings/TestExtruderStack.py::test_constrainQualityValid[container1]": true, + "tests/Settings/TestExtruderStack.py::test_constrainUserChangesInvalid[container0]": true, + "tests/Settings/TestExtruderStack.py::test_constrainUserChangesInvalid[container1]": true, + "tests/Settings/TestExtruderStack.py::test_constrainUserChangesInvalid[container2]": true, + "tests/Settings/TestExtruderStack.py::test_constrainUserChangesValid[container0]": true, + "tests/Settings/TestExtruderStack.py::test_constrainUserChangesValid[container1]": true, + "tests/Settings/TestExtruderStack.py::test_constrainVariantInvalid[container0]": true, + "tests/Settings/TestExtruderStack.py::test_constrainVariantInvalid[container1]": true, + "tests/Settings/TestExtruderStack.py::test_constrainVariantValid[container0]": true, + "tests/Settings/TestExtruderStack.py::test_constrainVariantValid[container1]": true, + "tests/Settings/TestExtruderStack.py::test_deserializeMoveInstanceContainer": true, + "tests/Settings/TestExtruderStack.py::test_deserializeRemovesWrongContainerClass": true, + "tests/Settings/TestExtruderStack.py::test_deserializeRemovesWrongInstanceContainer": true, + "tests/Settings/TestExtruderStack.py::test_deserializeWrongDefinitionClass": true, + "tests/Settings/TestExtruderStack.py::test_getPropertyFallThrough": true, + "tests/Settings/TestExtruderStack.py::test_insertContainer": true, + "tests/Settings/TestExtruderStack.py::test_removeContainer": true, + "tests/Settings/TestExtruderStack.py::test_setPropertyUser[foo-value-100]": true, + "tests/Settings/TestExtruderStack.py::test_setPropertyUser[layer_height-default_value-0.1337]": true, + "tests/Settings/TestExtruderStack.py::test_setPropertyUser[layer_height-is_bright_pink-of course]": true, + "tests/Settings/TestExtruderStack.py::test_setPropertyUser[layer_height-value-0.1337]": true, + "tests/Settings/TestExtruderStack.py::test_setPropertyUser[support_enabled-value-True]": true, + "tests/Settings/TestGlobalStack.py::test_addContainer": true, + "tests/Settings/TestGlobalStack.py::test_addExtruder": true, + "tests/Settings/TestGlobalStack.py::test_constrainDefinitionChangesInvalid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainDefinitionChangesInvalid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_constrainDefinitionChangesInvalid[container2]": true, + "tests/Settings/TestGlobalStack.py::test_constrainDefinitionChangesValid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainDefinitionChangesValid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_constrainDefinitionValid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainDefinitionValid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_constrainMaterialInvalid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainMaterialInvalid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_constrainMaterialInvalid[container2]": true, + "tests/Settings/TestGlobalStack.py::test_constrainMaterialValid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainMaterialValid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_constrainQualityChangesInvalid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainQualityChangesInvalid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_constrainQualityChangesInvalid[container2]": true, + "tests/Settings/TestGlobalStack.py::test_constrainQualityChangesValid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainQualityChangesValid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_constrainQualityInvalid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainQualityInvalid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_constrainQualityInvalid[container2]": true, + "tests/Settings/TestGlobalStack.py::test_constrainQualityValid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainQualityValid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_constrainUserChangesInvalid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainUserChangesInvalid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_constrainUserChangesInvalid[container2]": true, + "tests/Settings/TestGlobalStack.py::test_constrainUserChangesValid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainUserChangesValid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_constrainVariantInvalid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainVariantInvalid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_constrainVariantValid[container0]": true, + "tests/Settings/TestGlobalStack.py::test_constrainVariantValid[container1]": true, + "tests/Settings/TestGlobalStack.py::test_deserializeMoveInstanceContainer": true, + "tests/Settings/TestGlobalStack.py::test_deserializeRemovesWrongContainerClass": true, + "tests/Settings/TestGlobalStack.py::test_deserializeRemovesWrongInstanceContainer": true, + "tests/Settings/TestGlobalStack.py::test_deserializeWrongDefinitionClass": true, + "tests/Settings/TestGlobalStack.py::test_getPropertyFallThrough": true, + "tests/Settings/TestGlobalStack.py::test_getPropertyInstancesBeforeResolve": true, + "tests/Settings/TestGlobalStack.py::test_getPropertyNoResolveInDefinition": true, + "tests/Settings/TestGlobalStack.py::test_getPropertyResolveInDefinition": true, + "tests/Settings/TestGlobalStack.py::test_getPropertyResolveInInstance": true, + "tests/Settings/TestGlobalStack.py::test_hasNoUserValue": true, + "tests/Settings/TestGlobalStack.py::test_hasUserValueQualityChanges": true, + "tests/Settings/TestGlobalStack.py::test_hasUserValueUserChanges": true, + "tests/Settings/TestGlobalStack.py::test_insertContainer": true, + "tests/Settings/TestGlobalStack.py::test_removeContainer": true, + "tests/Settings/TestGlobalStack.py::test_setNextStack": true, + "tests/Settings/TestGlobalStack.py::test_setPropertyUser[foo-value-100]": true, + "tests/Settings/TestGlobalStack.py::test_setPropertyUser[layer_height-default_value-0.1337]": true, + "tests/Settings/TestGlobalStack.py::test_setPropertyUser[layer_height-is_bright_pink-of course]": true, + "tests/Settings/TestGlobalStack.py::test_setPropertyUser[layer_height-value-0.1337]": true, + "tests/Settings/TestGlobalStack.py::test_setPropertyUser[support_enabled-value-True]": true, + "tests/TestMachineAction.py::test_addMachineAction": true +} \ No newline at end of file diff --git a/.pytest_cache/v/cache/nodeids b/.pytest_cache/v/cache/nodeids new file mode 100644 index 0000000000..d548ce2ff2 --- /dev/null +++ b/.pytest_cache/v/cache/nodeids @@ -0,0 +1,3 @@ +[ + "plugins/VersionUpgrade/VersionUpgrade34to40/tests/TestVersionUpgrade34to40.py::test_upgradeVersionNr[Empty config file-[general]\\n version = 5\\n [metadata]\\n setting_version = 4\\n]" +] \ No newline at end of file diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index 9344bf54da..ceb9d79087 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -20,7 +20,7 @@ catalog = i18nCatalog("cura") class UFPWriter(MeshWriter): def __init__(self): - super().__init__() + super().__init__(add_to_recent_files = False) self._snapshot = None Application.getInstance().getOutputDeviceManager().writeStarted.connect(self._createSnapshot) From 4635c8117d9085925904d66913ce13a9636c092e Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Tue, 21 Aug 2018 11:49:13 +0200 Subject: [PATCH 192/243] Add changed_settings(retraction_combing) to Version Upgrade Cura3.4 CURA-5505 --- .../VersionUpgrade34to40/VersionUpgrade34to40.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins/VersionUpgrade/VersionUpgrade34to40/VersionUpgrade34to40.py b/plugins/VersionUpgrade/VersionUpgrade34to40/VersionUpgrade34to40.py index 83609206ef..a61aae06bb 100644 --- a/plugins/VersionUpgrade/VersionUpgrade34to40/VersionUpgrade34to40.py +++ b/plugins/VersionUpgrade/VersionUpgrade34to40/VersionUpgrade34to40.py @@ -8,6 +8,9 @@ from UM.VersionUpgrade import VersionUpgrade deleted_settings = {"prime_tower_wall_thickness", "dual_pre_wipe", "prime_tower_purge_volume"} +changed_settings = {'retraction_combing': 'noskin'} +updated_settings = {'retraction_combing': 'infill'} + _RENAMED_MATERIAL_PROFILES = { "dsm_arnitel2045_175_cartesio_0.25_mm": "dsm_arnitel2045_175_cartesio_0.25mm_thermoplastic_extruder", "dsm_arnitel2045_175_cartesio_0.4_mm": "dsm_arnitel2045_175_cartesio_0.4mm_thermoplastic_extruder", @@ -127,6 +130,13 @@ class VersionUpgrade34to40(VersionUpgrade): continue del parser["values"][deleted_setting] + for setting_key in changed_settings: + if setting_key not in parser["values"]: + continue + + if parser["values"][setting_key] == changed_settings[setting_key]: + parser["values"][setting_key] = updated_settings[setting_key] + result = io.StringIO() parser.write(result) return [filename], [result.getvalue()] From 10e474ad27929b9d4a0dc799f5fcfba8c2251312 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 21 Aug 2018 13:38:54 +0200 Subject: [PATCH 193/243] Add draft shield distance into the prime tower position fomulas CURA-5644 --- 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 c0c7e44d97..3eb7cb1c32 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5074,7 +5074,7 @@ "unit": "mm", "enabled": "resolveOrValue('prime_tower_enable')", "default_value": 200, - "value": "machine_width - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 - 1", + "value": "machine_width - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 - (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0) - 1", "maximum_value": "machine_width / 2 if machine_center_is_zero else machine_width", "minimum_value": "resolveOrValue('prime_tower_size') - machine_width / 2 if machine_center_is_zero else resolveOrValue('prime_tower_size')", "settable_per_mesh": false, @@ -5088,7 +5088,7 @@ "unit": "mm", "enabled": "resolveOrValue('prime_tower_enable')", "default_value": 200, - "value": "machine_depth - prime_tower_size - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 - 1", + "value": "machine_depth - prime_tower_size - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 - (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0) - 1", "maximum_value": "machine_depth / 2 - resolveOrValue('prime_tower_size') if machine_center_is_zero else machine_depth - resolveOrValue('prime_tower_size')", "minimum_value": "machine_depth / -2 if machine_center_is_zero else 0", "settable_per_mesh": false, From f35005c8bafe238ff36b079b28f845bd9227047b Mon Sep 17 00:00:00 2001 From: Cherubim Date: Tue, 21 Aug 2018 14:24:07 +0200 Subject: [PATCH 194/243] Brackets on new line As per our code style. --- resources/qml/Preferences/MaterialView.qml | 47 ++++++++++++++-------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 0929f1790a..97184ab558 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -30,20 +30,24 @@ TabView property bool reevaluateLinkedMaterials: false property string linkedMaterialNames: { - if (reevaluateLinkedMaterials) { + if (reevaluateLinkedMaterials) + { reevaluateLinkedMaterials = false; } - if (!base.containerId || !base.editingEnabled) { + if (!base.containerId || !base.editingEnabled) + { return "" } var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.currentMaterialNode, true); - if (linkedMaterials.length == 0) { + if (linkedMaterials.length == 0) + { return "" } return linkedMaterials.join(", "); } - function getApproximateDiameter(diameter) { + function getApproximateDiameter(diameter) + { return Math.round(diameter); } @@ -154,13 +158,15 @@ TabView } Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") } - Row { + Row + { width: scrollView.columnWidth height: parent.rowHeight spacing: Math.round(UM.Theme.getSize("default_margin").width / 2) // color indicator square - Rectangle { + Rectangle + { id: colorSelector color: properties.color_code @@ -171,7 +177,8 @@ TabView anchors.verticalCenter: parent.verticalCenter // open the color selection dialog on click - MouseArea { + MouseArea + { anchors.fill: parent onClicked: colorDialog.open() enabled: base.editingEnabled @@ -179,7 +186,8 @@ TabView } // pretty color name text field - ReadOnlyTextField { + ReadOnlyTextField + { id: colorLabel; text: properties.color_name; readOnly: !base.editingEnabled @@ -188,7 +196,8 @@ TabView // popup dialog to select a new color // if successful it sets the properties.color_code value to the new color - ColorDialog { + ColorDialog + { id: colorDialog color: properties.color_code onAccepted: base.setMetaDataEntry("color_code", properties.color_code, color) @@ -258,7 +267,8 @@ TabView decimals: 2 maximumValue: 100000000 - onValueChanged: { + onValueChanged: + { base.setMaterialPreferenceValue(properties.guid, "spool_cost", parseFloat(value)) updateCostPerMeter() } @@ -275,7 +285,8 @@ TabView decimals: 0 maximumValue: 10000 - onValueChanged: { + onValueChanged: + { base.setMaterialPreferenceValue(properties.guid, "spool_weight", parseFloat(value)) updateCostPerMeter() } @@ -401,7 +412,8 @@ TabView { id: spinBox anchors.left: label.right - value: { + value: + { // In case the setting is not in the material... if (!isNaN(parseFloat(materialPropertyProvider.properties.value))) { @@ -493,8 +505,10 @@ TabView } // Tiny convenience function to check if a value really changed before trying to set it. - function setMetaDataEntry(entry_name, old_value, new_value) { - if (old_value != new_value) { + function setMetaDataEntry(entry_name, old_value, new_value) + { + if (old_value != new_value) + { Cura.ContainerManager.setContainerMetaDataEntry(base.currentMaterialNode, entry_name, new_value) // make sure the UI properties are updated as well since we don't re-fetch the entire model here // When the entry_name is something like properties/diameter, we take the last part of the entry_name @@ -546,10 +560,11 @@ TabView } // update the display name of the material - function updateMaterialDisplayName (old_name, new_name) + function updateMaterialDisplayName(old_name, new_name) { // don't change when new name is the same - if (old_name == new_name) { + if (old_name == new_name) + { return; } From af64d91587c4363ca30a9ed38d0ce03eeae701ed Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 21 Aug 2018 16:07:16 +0200 Subject: [PATCH 195/243] Fix stack handling in project loading CURA-5663 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index e33b88375e..16ab22473b 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -630,6 +630,11 @@ class ThreeMFWorkspaceReader(WorkspaceReader): type = "extruder_train") extruder_stack_dict = {stack.getMetaDataEntry("position"): stack for stack in extruder_stacks} + # Make sure that those extruders have the global stack as the next stack or later some value evaluation + # will fail. + for stack in extruder_stacks: + stack.setNextStack(global_stack, connect_signals = False) + Logger.log("d", "Workspace loading is checking definitions...") # Get all the definition files & check if they exist. If not, add them. definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)] From 08b325ee0484da12b1afb632de7c681bae6f482b Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 22 Aug 2018 12:31:48 +0200 Subject: [PATCH 196/243] Correctly load material favorites from preferences Contributes to CURA-5378, CURA-5162 --- cura/CuraApplication.py | 2 +- cura/Machines/MaterialManager.py | 13 +++---------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 3cd49e591f..27f558bc41 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -501,7 +501,7 @@ class CuraApplication(QtApplication): preferences.addPreference("view/filter_current_build_plate", False) preferences.addPreference("cura/sidebar_collapsed", False) - preferences.addPreference("cura/favorite_materials", []) + preferences.addPreference("cura/favorite_materials", ";".join([])) self._need_to_show_user_agreement = not preferences.getValue("general/accepted_user_agreement") diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index d59aa07590..1463f2e40e 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -199,11 +199,8 @@ class MaterialManager(QObject): self.materialsUpdated.emit() favorites = self._application.getPreferences().getValue("cura/favorite_materials") - print(favorites) - for item in favorites: - print(item) + for item in favorites.split(";"): self._favorites.add(item) - print("LOADED FAVES", self._favorites) self.favoritesUpdated.emit() def __addMaterialMetadataIntoLookupTree(self, material_metadata: dict) -> None: @@ -623,24 +620,20 @@ class MaterialManager(QObject): @pyqtSlot(str) def addFavorite(self, root_material_id: str): - print(root_material_id) self._favorites.add(root_material_id) self.favoritesUpdated.emit() - print(self._favorites) - print(list(self._favorites)) # Ensure all settings are saved. - self._application.getPreferences().setValue("cura/favorite_materials", list(self._favorites)) + self._application.getPreferences().setValue("cura/favorite_materials", ";".join(list(self._favorites))) self._application.saveSettings() @pyqtSlot(str) def removeFavorite(self, root_material_id: str): self._favorites.remove(root_material_id) self.favoritesUpdated.emit() - print(self._favorites) # Ensure all settings are saved. - self._application.getPreferences().setValue("cura/favorite_materials", list(self._favorites)) + self._application.getPreferences().setValue("cura/favorite_materials", ";".join(list(self._favorites))) self._application.saveSettings() @pyqtSlot() From cb713eea6ae7b9bf9146e079da3cf4dd21400038 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 22 Aug 2018 12:33:29 +0200 Subject: [PATCH 197/243] Improve models Contributes to CURA-5162, CURA-5378 --- cura/Machines/Models/BaseMaterialsModel.py | 2 ++ cura/Machines/Models/BrandMaterialsModel.py | 4 +++- .../Machines/Models/FavoriteMaterialsModel.py | 9 ++++---- cura/Machines/Models/GenericMaterialsModel.py | 21 ++++++++++++------- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index ceba1f6eeb..ebf87e26b3 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -23,6 +23,7 @@ class BaseMaterialsModel(ListModel): ContainerNodeRole = Qt.UserRole + 7 ColorCodeRole = Qt.UserRole + 8 GUIDRole = Qt.UserRole + 9 + IsFavoriteRole = Qt.UserRole + 10 extruderPositionChanged = pyqtSignal() @@ -40,6 +41,7 @@ class BaseMaterialsModel(ListModel): self.addRoleName(self.ColorRole, "color_name") self.addRoleName(self.ColorCodeRole, "color_code") self.addRoleName(self.ContainerNodeRole, "container_node") + self.addRoleName(self.IsFavoriteRole, "is_favorite") self._extruder_position = 0 self._extruder_stack = None diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py index c5edd6e57c..1eb76ca33c 100644 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ b/cura/Machines/Models/BrandMaterialsModel.py @@ -58,6 +58,7 @@ class BrandMaterialsModel(ListModel): self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack) self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines. self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes. + # self._material_manager.favoritesUpdated.connect(self._update) # Update when favorites are changed self._update() def _updateExtruderStack(self): @@ -106,6 +107,7 @@ class BrandMaterialsModel(ListModel): for root_material_id, container_node in available_material_dict.items(): metadata = container_node.metadata + favorites = self._material_manager.getFavorites() # Do not include the materials from a to-be-removed package if bool(metadata.get("removed", False)): @@ -142,7 +144,7 @@ class BrandMaterialsModel(ListModel): "adhesion_info": metadata["adhesion_info"], "is_read_only": self._container_registry.isReadOnly(metadata["id"]), "container_node": container_node, - "is_favorite": False + "is_favorite": root_material_id in favorites } brand_group_dict[brand][material_type].append(item) diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index 9d05f8cb4a..d9ca69f4e1 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -27,6 +27,7 @@ class FavoriteMaterialsModel(BaseMaterialsModel): if global_stack is None: self.setItems([]) return + extruder_position = str(self._extruder_position) if extruder_position not in global_stack.extruders: self.setItems([]) @@ -40,8 +41,6 @@ class FavoriteMaterialsModel(BaseMaterialsModel): favorite_ids = self._material_manager.getFavorites() - print("favorite_ids:", favorite_ids) - item_list = [] for root_material_id, container_node in available_material_dict.items(): metadata = container_node.metadata @@ -61,11 +60,13 @@ class FavoriteMaterialsModel(BaseMaterialsModel): "brand": metadata["brand"], "material": metadata["material"], "color_name": metadata["color_name"], - "container_node": container_node + "color_code": metadata["color_code"], + "container_node": container_node, + "is_favorite": True } item_list.append(item) # Sort the item list by material name alphabetically - item_list = sorted(item_list, key = lambda d: d["name"].upper()) + item_list = sorted(item_list, key = lambda d: d["brand"].upper()) self.setItems(item_list) diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index f14b039c91..90c8d43026 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -38,6 +38,8 @@ class GenericMaterialsModel(BaseMaterialsModel): self.setItems([]) return + favorites = self._material_manager.getFavorites() + item_list = [] for root_material_id, container_node in available_material_dict.items(): metadata = container_node.metadata @@ -50,14 +52,17 @@ class GenericMaterialsModel(BaseMaterialsModel): if bool(metadata.get("removed", False)): continue - item = {"root_material_id": root_material_id, - "id": metadata["id"], - "name": metadata["name"], - "brand": metadata["brand"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "container_node": container_node - } + item = { + "root_material_id": root_material_id, + "id": metadata["id"], + "name": metadata["name"], + "brand": metadata["brand"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "color_code": metadata["color_code"], + "container_node": container_node, + "is_favorite": root_material_id in favorites + } item_list.append(item) # Sort the item list by material name alphabetically From 272e892179c7cdfe868cd0703e3e725da51fc552 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 22 Aug 2018 12:33:55 +0200 Subject: [PATCH 198/243] Extend Cura Light theme for material favorites Contributes to CURA-5162, CURA-5378 --- .../themes/cura-light/icons/favorites_star_empty.svg | 8 ++++++++ .../themes/cura-light/icons/favorites_star_full.svg | 6 ++++++ resources/themes/cura-light/theme.json | 12 +++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 resources/themes/cura-light/icons/favorites_star_empty.svg create mode 100644 resources/themes/cura-light/icons/favorites_star_full.svg diff --git a/resources/themes/cura-light/icons/favorites_star_empty.svg b/resources/themes/cura-light/icons/favorites_star_empty.svg new file mode 100644 index 0000000000..bb1205e7a7 --- /dev/null +++ b/resources/themes/cura-light/icons/favorites_star_empty.svg @@ -0,0 +1,8 @@ + + + + + diff --git a/resources/themes/cura-light/icons/favorites_star_full.svg b/resources/themes/cura-light/icons/favorites_star_full.svg new file mode 100644 index 0000000000..aad45c5d02 --- /dev/null +++ b/resources/themes/cura-light/icons/favorites_star_full.svg @@ -0,0 +1,6 @@ + + + + + diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 7bcdafce98..c408146669 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -315,7 +315,13 @@ "tab_status_disconnected": [200, 200, 200, 255], "printer_config_matched": [12, 169, 227, 255], - "printer_config_mismatch": [127, 127, 127, 255] + "printer_config_mismatch": [127, 127, 127, 255], + + "favorites_header_bar": [245, 245, 245, 255], + "favorites_header_hover": [245, 245, 245, 255], + "favorites_header_text": [31, 36, 39, 255], + "favorites_header_text_hover": [31, 36, 39, 255], + "favorites_row_selected": [196, 239, 255, 255] }, "sizes": { @@ -372,6 +378,10 @@ "small_button": [2, 2], "small_button_icon": [1.5, 1.5], + "favorites_row": [2, 2], + "favorites_button": [2, 2], + "favorites_button_icon": [1.2, 1.2], + "printer_status_icon": [1.8, 1.8], "printer_sync_icon": [1.2, 1.2], From 00eb8e6788eb11bbe6d6f55f4c2c4d6839d36006 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 22 Aug 2018 12:34:38 +0200 Subject: [PATCH 199/243] Organize material preferences Contributes to CURA-5378 --- resources/qml/Cura.qml | 2 +- .../Preferences/Materials/MaterialSlot.qml | 120 +++++ .../{ => Materials}/MaterialView.qml | 2 + .../Materials/MaterialsDetailsPanel.qml | 103 +++++ .../{ => Materials}/MaterialsList.qml | 265 +++++++---- .../{ => Materials}/MaterialsPage.qml | 422 +++++++----------- .../Preferences/Materials/OldMaterialList.qml | 98 ++++ 7 files changed, 656 insertions(+), 356 deletions(-) create mode 100644 resources/qml/Preferences/Materials/MaterialSlot.qml rename resources/qml/Preferences/{ => Materials}/MaterialView.qml (99%) create mode 100644 resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml rename resources/qml/Preferences/{ => Materials}/MaterialsList.qml (50%) rename resources/qml/Preferences/{ => Materials}/MaterialsPage.qml (67%) create mode 100644 resources/qml/Preferences/Materials/OldMaterialList.qml diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 60f6e77ea9..f1bb3188b3 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -541,7 +541,7 @@ UM.MainWindow insertPage(2, catalog.i18nc("@title:tab", "Printers"), Qt.resolvedUrl("Preferences/MachinesPage.qml")); - insertPage(3, catalog.i18nc("@title:tab", "Materials"), Qt.resolvedUrl("Preferences/MaterialsPage.qml")); + insertPage(3, catalog.i18nc("@title:tab", "Materials"), Qt.resolvedUrl("Preferences/Materials/MaterialsPage.qml")); insertPage(4, catalog.i18nc("@title:tab", "Profiles"), Qt.resolvedUrl("Preferences/ProfilesPage.qml")); diff --git a/resources/qml/Preferences/Materials/MaterialSlot.qml b/resources/qml/Preferences/Materials/MaterialSlot.qml new file mode 100644 index 0000000000..678a69bd54 --- /dev/null +++ b/resources/qml/Preferences/Materials/MaterialSlot.qml @@ -0,0 +1,120 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Rectangle +{ + id: material_slot + property var material + property var hovered: false + property var is_favorite: material.is_favorite + + height: UM.Theme.getSize("favorites_row").height + width: parent.width + color: base.currentItem == model ? UM.Theme.getColor("favorites_row_selected") : "transparent" + + Row + { + height: parent.height + width: parent.width + Rectangle + { + id: swatch + color: material.color_code + border.width: UM.Theme.getSize("default_lining").width + border.color: "black" + width: UM.Theme.getSize("favorites_button_icon").width + height: UM.Theme.getSize("favorites_button_icon").height + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + } + Label + { + text: material.brand + " " + material.name + verticalAlignment: Text.AlignVCenter + height: parent.height + anchors.left: swatch.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: UM.Theme.getSize("narrow_margin").width + } + MouseArea + { + anchors.fill: parent + onClicked: { base.currentItem = material } + hoverEnabled: true + onEntered: { material_slot.hovered = true } + onExited: { material_slot.hovered = false } + } + Button + { + id: favorite_button + text: "" + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height + visible: material_slot.hovered || material_slot.is_favorite || favorite_button.hovered + anchors + { + right: parent.right + verticalCenter: parent.verticalCenter + } + onClicked: + { + if (material_slot.is_favorite) { + base.materialManager.removeFavorite(material.root_material_id) + material_slot.is_favorite = false + return + } + base.materialManager.addFavorite(material.root_material_id) + material_slot.is_favorite = true + return + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("favorites_button_icon").width + height: UM.Theme.getSize("favorites_button_icon").height + sourceSize.width: width + sourceSize.height: height + color: + { + if (favorite_button.hovered) + { + return UM.Theme.getColor("primary_hover") + } + else + { + if (material_slot.is_favorite) + { + return UM.Theme.getColor("primary") + } + else + { + UM.Theme.getColor("text_inactive") + } + } + } + source: material_slot.is_favorite ? UM.Theme.getIcon("favorites_star_full") : UM.Theme.getIcon("favorites_star_empty") + } + } + } +} \ No newline at end of file diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/Materials/MaterialView.qml similarity index 99% rename from resources/qml/Preferences/MaterialView.qml rename to resources/qml/Preferences/Materials/MaterialView.qml index 0929f1790a..c3503ae646 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/Materials/MaterialView.qml @@ -8,6 +8,8 @@ import QtQuick.Dialogs 1.2 import UM 1.2 as UM import Cura 1.0 as Cura +import ".." // Access to ReadOnlyTextArea.qml + TabView { id: base diff --git a/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml new file mode 100644 index 0000000000..e18ae15201 --- /dev/null +++ b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml @@ -0,0 +1,103 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Item +{ + id: detailsPanel + + function updateMaterialPropertiesObject( currentItem ) + { +// var currentItem = materialsModel.getItem(materialListView.currentIndex); + + materialProperties.name = currentItem.name ? currentItem.name : "Unknown"; + materialProperties.guid = currentItem.guid; + materialProperties.container_id = currentItem.container_id; + + materialProperties.brand = currentItem.brand ? currentItem.brand : "Unknown"; + materialProperties.material = currentItem.material ? currentItem.material : "Unknown"; + materialProperties.color_name = currentItem.color_name ? currentItem.color_name : "Yellow"; + materialProperties.color_code = currentItem.color_code ? currentItem.color_code : "yellow"; + + materialProperties.description = currentItem.description ? currentItem.description : ""; + materialProperties.adhesion_info = currentItem.adhesion_info ? currentItem.adhesion_info : ""; + + materialProperties.density = currentItem.density ? currentItem.density : 0.0; + materialProperties.diameter = currentItem.diameter ? currentItem.diameter : 0.0; + materialProperties.approximate_diameter = currentItem.approximate_diameter ? currentItem.approximate_diameter : "0"; + } + + Item + { + anchors.fill: parent + + Item // Material title Label + { + id: profileName + + width: parent.width + height: childrenRect.height + + Label { + text: materialProperties.name + font: UM.Theme.getFont("large") + } + } + + MaterialView // Material detailed information view below the title Label + { + id: materialDetailsView + anchors + { + left: parent.left + right: parent.right + top: profileName.bottom + topMargin: UM.Theme.getSize("default_margin").height + bottom: parent.bottom + } + + editingEnabled: base.currentItem != null && !base.currentItem.is_read_only + + properties: materialProperties + containerId: base.currentItem != null ? base.currentItem.container_id : "" + currentMaterialNode: base.currentItem.container_node + + + } + + QtObject + { + id: materialProperties + + property string guid: "00000000-0000-0000-0000-000000000000" + property string container_id: "Unknown"; + property string name: "Unknown"; + property string profile_type: "Unknown"; + property string brand: "Unknown"; + property string material: "Unknown"; // This needs to be named as "material" to be consistent with + // the material container's metadata entry + + property string color_name: "Yellow"; + property color color_code: "yellow"; + + property real density: 0.0; + property real diameter: 0.0; + property string approximate_diameter: "0"; + + property real spool_cost: 0.0; + property real spool_weight: 0.0; + property real spool_length: 0.0; + property real cost_per_meter: 0.0; + + property string description: ""; + property string adhesion_info: ""; + } + } +} \ No newline at end of file diff --git a/resources/qml/Preferences/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml similarity index 50% rename from resources/qml/Preferences/MaterialsList.qml rename to resources/qml/Preferences/Materials/MaterialsList.qml index db0f5461ec..a051f55cac 100644 --- a/resources/qml/Preferences/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -6,42 +6,174 @@ import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.3 import QtQuick.Dialogs 1.2 + import UM 1.2 as UM import Cura 1.0 as Cura Item { id: materialList - UM.I18nCatalog { id: catalog; name: "cura"; } - Cura.BrandMaterialsModel { id: materialsModel } - Cura.GenericMaterialsModel { id: genericMaterialsModel } - - width: materialScrollView.width - 20 + width: materialScrollView.width - 17 height: childrenRect.height - + // Children + UM.I18nCatalog { id: catalog; name: "cura"; } + Cura.BrandMaterialsModel { id: materialsModel } + Cura.FavoriteMaterialsModel { id: favoriteMaterialsModel } + Cura.GenericMaterialsModel { id: genericMaterialsModel } Column { Rectangle { - height: 23 + property var expanded: true + + id: favorites_section + height: childrenRect.height width: materialList.width - Label + Rectangle { - text: "Generic" + id: favorites_header_background + color: UM.Theme.getColor("favorites_header_bar") + anchors.fill: favorites_header } - } - Repeater - { - model: genericMaterialsModel - delegate: Rectangle + Row { - height: 23 - width: materialList.width - color: "green" + id: favorites_header Label { - text: model.name + id: favorites_name + text: "Favorites" + height: UM.Theme.getSize("favorites_row").height + width: materialList.width - UM.Theme.getSize("favorites_button").width + verticalAlignment: Text.AlignVCenter + leftPadding: 4 + } + Button + { + text: "" + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: "black" + source: favorites_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + } + } + MouseArea + { + anchors.fill: favorites_header + onPressed: + { + favorites_section.expanded = !favorites_section.expanded + } + } + Column + { + anchors.top: favorites_header.bottom + anchors.left: parent.left + width: materialList.width + height: favorites_section.expanded ? childrenRect.height : 0 + visible: favorites_section.expanded + Repeater + { + model: favoriteMaterialsModel + delegate: MaterialSlot { + material: model + } + } + } + } + Rectangle + { + property var expanded: true + + id: generic_section + height: childrenRect.height + width: materialList.width + Rectangle + { + id: generic_header_background + color: UM.Theme.getColor("favorites_header_bar") + anchors.fill: generic_header + } + Row + { + id: generic_header + Label + { + id: generic_name + text: "Generic" + height: UM.Theme.getSize("favorites_row").height + width: materialList.width - UM.Theme.getSize("favorites_button").width + verticalAlignment: Text.AlignVCenter + leftPadding: 4 + } + Button + { + text: "" + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: "black" + source: generic_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + } + } + MouseArea + { + anchors.fill: generic_header + onPressed: + { + generic_section.expanded = !generic_section.expanded + } + } + Column + { + anchors.top: generic_header.bottom + width: materialList.width + anchors.left: parent.left + height: generic_section.expanded ? childrenRect.height : 0 + visible: generic_section.expanded + Repeater + { + model: genericMaterialsModel + delegate: MaterialSlot { + material: model + } } } } @@ -60,7 +192,7 @@ Item Rectangle { id: brand_header_background - color: "grey" + color: UM.Theme.getColor("favorites_header_bar") anchors.fill: brand_header } Row @@ -71,16 +203,16 @@ Item { id: brand_name text: model.name - height: 24 - width: parent.width - 24 + height: UM.Theme.getSize("favorites_row").height + width: parent.width - UM.Theme.getSize("favorites_button").width verticalAlignment: Text.AlignVCenter leftPadding: 4 } Button { text: "" - implicitWidth: 24 - implicitHeight: 24 + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height UM.RecolorImage { anchors { @@ -115,9 +247,8 @@ Item Column { anchors.top: brand_header.bottom - width: parent.width - leftPadding + width: parent.width anchors.left: parent.left - leftPadding: 8 height: brand_section.expanded ? childrenRect.height : 0 visible: brand_section.expanded Repeater @@ -133,29 +264,34 @@ Item Rectangle { id: material_type_header_background - color: "grey" + color: UM.Theme.getColor("lining") anchors.bottom: material_type_header.bottom - height: 1 - width: parent.width + anchors.left: material_type_header.left + height: UM.Theme.getSize("default_lining").height + width: material_type_header.width } Row { id: material_type_header - width: parent.width - + width: parent.width - 8 + anchors + { + left: parent.left + leftMargin: 8 + } Label { text: model.name - height: 24 - width: parent.width - 24 + height: UM.Theme.getSize("favorites_row").height + width: parent.width - UM.Theme.getSize("favorites_button").width id: material_type_name verticalAlignment: Text.AlignVCenter } Button { text: "" - implicitWidth: 24 - implicitHeight: 24 + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height UM.RecolorImage { anchors { @@ -191,69 +327,14 @@ Item { height: material_type_section.expanded ? childrenRect.height : 0 visible: material_type_section.expanded - width: parent.width - leftPadding + width: parent.width anchors.top: material_type_header.bottom - leftPadding: 8 anchors.left: parent.left Repeater { model: colors_model - delegate: Rectangle - { - height: 24 - width: parent.width -// color: "green" - Row - { - height: parent.height - width: parent.width - Rectangle - { - id: swatch - color: model.color_code - border.width: 1 - border.color: "black" - width: 14 - height: 14 - anchors.verticalCenter: parent.verticalCenter - } - Label - { - text: model.name - verticalAlignment: Text.AlignVCenter - height: 24 - anchors.left: swatch.right - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: 4 - } - MouseArea - { - anchors.fill: parent - onClicked: - { - print(model.guid) - } - } - Button - { - text: "+" - implicitWidth: 24 - implicitHeight: 24 - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - onClicked: - { - if (model.is_favorite) { - base.materialManager.removeFavorite(model.root_material_id) - model.is_favorite = false - return - } - base.materialManager.addFavorite(model.root_material_id) - model.is_favorite = true - return - } - } - } + delegate: MaterialSlot { + material: model } } } diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml similarity index 67% rename from resources/qml/Preferences/MaterialsPage.qml rename to resources/qml/Preferences/Materials/MaterialsPage.qml index 07b5da3f4e..0e615a8d1b 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -9,13 +9,22 @@ import QtQuick.Dialogs 1.2 import UM 1.2 as UM import Cura 1.0 as Cura - Item { id: base property QtObject materialManager: CuraApplication.getMaterialManager() - property var resetEnabled: false // Keep PreferencesDialog happy + // Keep PreferencesDialog happy + property var resetEnabled: false + property var currentItem: null + property var isCurrentItemActivated: + { + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + return base.currentItem.root_material_id == root_material_id; + } + property string newRootMaterialIdToSwitchTo: "" + property bool toActivateNewMaterial: false UM.I18nCatalog { @@ -30,11 +39,72 @@ Item { id: genericMaterialsModel } + // Component.onCompleted: + // { + // // Select the activated material when this page shows up + // const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + // const active_root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + // var itemIndex = -1; + // for (var i = 0; i < materialsModel.rowCount(); ++i) + // { + // var item = materialsModel.getItem(i); + // if (item.root_material_id == active_root_material_id) + // { + // itemIndex = i; + // break; + // } + // } + // materialListView.currentIndex = itemIndex; + // } + + // This connection makes sure that we will switch to the new + Connections + { + target: materialsModel + onItemsChanged: + { + var currentItemId = base.currentItem == null ? "" : base.currentItem.root_material_id; + var position = Cura.ExtruderManager.activeExtruderIndex; + // try to pick the currently selected item; it may have been moved + if (base.newRootMaterialIdToSwitchTo == "") + { + base.newRootMaterialIdToSwitchTo = currentItemId; + } + + for (var idx = 0; idx < materialsModel.rowCount(); ++idx) + { + var item = materialsModel.getItem(idx); + if (item.root_material_id == base.newRootMaterialIdToSwitchTo) + { + // Switch to the newly created profile if needed + materialListView.currentIndex = idx; + materialListView.activateDetailsWithIndex(materialListView.currentIndex); + if (base.toActivateNewMaterial) + { + Cura.MachineManager.setMaterial(position, item.container_node); + } + base.newRootMaterialIdToSwitchTo = ""; + base.toActivateNewMaterial = false; + return + } + } + + materialListView.currentIndex = 0; + materialListView.activateDetailsWithIndex(materialListView.currentIndex); + if (base.toActivateNewMaterial) + { + Cura.MachineManager.setMaterial(position, materialsModel.getItem(0).container_node); + } + base.newRootMaterialIdToSwitchTo = ""; + base.toActivateNewMaterial = false; + } + } + + // Main layout Label { id: titleLabel - anchors { top: parent.top @@ -42,45 +112,12 @@ Item right: parent.right margins: 5 * screenScaleFactor } - font.pointSize: 18 text: catalog.i18nc("@title:tab", "Materials") } - property var hasCurrentItem: materialListView.currentItem != null - - property var currentItem: - { // is soon to be overwritten - var current_index = materialListView.currentIndex; - return materialsModel.getItem(current_index); - } - - property var isCurrentItemActivated: - { - const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - return base.currentItem.root_material_id == root_material_id; - } - - Component.onCompleted: - { - // Select the activated material when this page shows up - const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - const active_root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - var itemIndex = -1; - for (var i = 0; i < materialsModel.rowCount(); ++i) - { - var item = materialsModel.getItem(i); - if (item.root_material_id == active_root_material_id) - { - itemIndex = i; - break; - } - } - materialListView.currentIndex = itemIndex; - } - - Row // Button Row + // Button Row + Row { id: buttonRow anchors @@ -173,63 +210,102 @@ Item } } - property string newRootMaterialIdToSwitchTo: "" - property bool toActivateNewMaterial: false - - // This connection makes sure that we will switch to the new - Connections - { - target: materialsModel - onItemsChanged: + Item { + id: contentsItem + anchors { - var currentItemId = base.currentItem == null ? "" : base.currentItem.root_material_id; - var position = Cura.ExtruderManager.activeExtruderIndex; - - // try to pick the currently selected item; it may have been moved - if (base.newRootMaterialIdToSwitchTo == "") - { - base.newRootMaterialIdToSwitchTo = currentItemId; - } - - for (var idx = 0; idx < materialsModel.rowCount(); ++idx) - { - var item = materialsModel.getItem(idx); - if (item.root_material_id == base.newRootMaterialIdToSwitchTo) - { - // Switch to the newly created profile if needed - materialListView.currentIndex = idx; - materialListView.activateDetailsWithIndex(materialListView.currentIndex); - if (base.toActivateNewMaterial) - { - Cura.MachineManager.setMaterial(position, item.container_node); - } - base.newRootMaterialIdToSwitchTo = ""; - base.toActivateNewMaterial = false; - return - } - } - - materialListView.currentIndex = 0; - materialListView.activateDetailsWithIndex(materialListView.currentIndex); - if (base.toActivateNewMaterial) - { - Cura.MachineManager.setMaterial(position, materialsModel.getItem(0).container_node); - } - base.newRootMaterialIdToSwitchTo = ""; - base.toActivateNewMaterial = false; + top: titleLabel.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + margins: 5 * screenScaleFactor + bottomMargin: 0 } + clip: true } + Item + { + anchors + { + top: buttonRow.bottom + topMargin: UM.Theme.getSize("default_margin").height + left: parent.left + right: parent.right + bottom: parent.bottom + } + + SystemPalette { id: palette } + + Label + { + id: captionLabel + anchors + { + top: parent.top + left: parent.left + } + visible: text != "" + text: + { + var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName; + if (Cura.MachineManager.hasVariants) + { + caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + Cura.MachineManager.activeVariantName; + } + return caption; + } + width: materialScrollView.width + elide: Text.ElideRight + } + + ScrollView + { + id: materialScrollView + anchors + { + top: captionLabel.visible ? captionLabel.bottom : parent.top + topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0 + bottom: parent.bottom + left: parent.left + } + + Rectangle + { + parent: viewport + anchors.fill: parent + color: palette.light + } + + width: true ? (parent.width * 0.4) | 0 : parent.width + frameVisible: true + verticalScrollBarPolicy: Qt.ScrollBarAlwaysOn + + MaterialsList {} + } + + // MaterialsDetailsPanel + // { + // anchors + // { + // left: materialScrollView.right + // leftMargin: UM.Theme.getSize("default_margin").width + // top: parent.top + // bottom: parent.bottom + // right: parent.right + // } + // } + } + + // Dialogs MessageDialog { id: confirmRemoveMaterialDialog - icon: StandardIcon.Question; title: catalog.i18nc("@title:window", "Confirm Remove") text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(base.currentItem.name) standardButtons: StandardButton.Yes | StandardButton.No modality: Qt.ApplicationModal - onYes: { base.materialManager.removeMaterial(base.currentItem.container_node); @@ -299,184 +375,4 @@ Item { id: messageDialog } - - - Item { - id: contentsItem - - anchors - { - top: titleLabel.bottom - left: parent.left - right: parent.right - bottom: parent.bottom - margins: 5 * screenScaleFactor - bottomMargin: 0 - } - - clip: true - } - - Item - { - anchors - { - top: buttonRow.bottom - topMargin: UM.Theme.getSize("default_margin").height - left: parent.left - right: parent.right - bottom: parent.bottom - } - - SystemPalette { id: palette } - - Label - { - id: captionLabel - anchors - { - top: parent.top - left: parent.left - } - visible: text != "" - text: - { - var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName; - if (Cura.MachineManager.hasVariants) - { - caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + Cura.MachineManager.activeVariantName; - } - return caption; - } - width: materialScrollView.width - elide: Text.ElideRight - } - - ScrollView - { - id: materialScrollView - anchors - { - top: captionLabel.visible ? captionLabel.bottom : parent.top - topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0 - bottom: parent.bottom - left: parent.left - } - - Rectangle - { - parent: viewport - anchors.fill: parent - color: palette.light - } - - width: true ? (parent.width * 0.4) | 0 : parent.width - frameVisible: true - - MaterialsList {} - } - - - Item - { - id: detailsPanel - - anchors - { - left: materialScrollView.right - leftMargin: UM.Theme.getSize("default_margin").width - top: parent.top - bottom: parent.bottom - right: parent.right - } - - function updateMaterialPropertiesObject( currentItem ) - { -// var currentItem = materialsModel.getItem(materialListView.currentIndex); - - materialProperties.name = currentItem.name ? currentItem.name : "Unknown"; - materialProperties.guid = currentItem.guid; - materialProperties.container_id = currentItem.container_id; - - materialProperties.brand = currentItem.brand ? currentItem.brand : "Unknown"; - materialProperties.material = currentItem.material ? currentItem.material : "Unknown"; - materialProperties.color_name = currentItem.color_name ? currentItem.color_name : "Yellow"; - materialProperties.color_code = currentItem.color_code ? currentItem.color_code : "yellow"; - - materialProperties.description = currentItem.description ? currentItem.description : ""; - materialProperties.adhesion_info = currentItem.adhesion_info ? currentItem.adhesion_info : ""; - - materialProperties.density = currentItem.density ? currentItem.density : 0.0; - materialProperties.diameter = currentItem.diameter ? currentItem.diameter : 0.0; - materialProperties.approximate_diameter = currentItem.approximate_diameter ? currentItem.approximate_diameter : "0"; - } - - Item - { - anchors.fill: parent - - Item // Material title Label - { - id: profileName - - width: parent.width - height: childrenRect.height - - Label { - text: materialProperties.name - font: UM.Theme.getFont("large") - } - } - - MaterialView // Material detailed information view below the title Label - { - id: materialDetailsView - anchors - { - left: parent.left - right: parent.right - top: profileName.bottom - topMargin: UM.Theme.getSize("default_margin").height - bottom: parent.bottom - } - - editingEnabled: base.currentItem != null && !base.currentItem.is_read_only - - properties: materialProperties - containerId: base.currentItem != null ? base.currentItem.container_id : "" - currentMaterialNode: base.currentItem.container_node - - property alias pane: base - } - - QtObject - { - id: materialProperties - - property string guid: "00000000-0000-0000-0000-000000000000" - property string container_id: "Unknown"; - property string name: "Unknown"; - property string profile_type: "Unknown"; - property string brand: "Unknown"; - property string material: "Unknown"; // This needs to be named as "material" to be consistent with - // the material container's metadata entry - - property string color_name: "Yellow"; - property color color_code: "yellow"; - - property real density: 0.0; - property real diameter: 0.0; - property string approximate_diameter: "0"; - - property real spool_cost: 0.0; - property real spool_weight: 0.0; - property real spool_length: 0.0; - property real cost_per_meter: 0.0; - - property string description: ""; - property string adhesion_info: ""; - } - } - } - } } diff --git a/resources/qml/Preferences/Materials/OldMaterialList.qml b/resources/qml/Preferences/Materials/OldMaterialList.qml new file mode 100644 index 0000000000..6c15ddf7cc --- /dev/null +++ b/resources/qml/Preferences/Materials/OldMaterialList.qml @@ -0,0 +1,98 @@ +ListView +{ + id: materialListView + + model: materialsModel + + section.property: "brand" + section.criteria: ViewSection.FullString + section.delegate: Rectangle + { + width: materialScrollView.width + height: childrenRect.height + color: palette.light + + Label + { + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_lining").width + text: section + font.bold: true + color: palette.text + } + } + + delegate: Rectangle + { + width: materialScrollView.width + height: childrenRect.height + color: ListView.isCurrentItem ? palette.highlight : (model.index % 2) ? palette.base : palette.alternateBase + + Row + { + id: materialRow + spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.right: parent.right + + property bool isCurrentItem: parent.ListView.isCurrentItem + + property bool isItemActivated: + { + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + return model.root_material_id == root_material_id; + } + + Rectangle + { + width: Math.floor(parent.height * 0.8) + height: Math.floor(parent.height * 0.8) + color: model.color_code + border.color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; + anchors.verticalCenter: parent.verticalCenter + } + Label + { + width: Math.floor((parent.width * 0.3)) + text: model.material + elide: Text.ElideRight + font.italic: materialRow.isItemActivated + color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; + } + Label + { + text: (model.name != model.material) ? model.name : "" + elide: Text.ElideRight + font.italic: materialRow.isItemActivated + color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; + } + } + + MouseArea + { + anchors.fill: parent + onClicked: + { + parent.ListView.view.currentIndex = model.index; + } + } + } + + function activateDetailsWithIndex(index) + { + var model = materialsModel.getItem(index); + base.currentItem = model; + materialDetailsView.containerId = model.container_id; + materialDetailsView.currentMaterialNode = model.container_node; + + detailsPanel.updateMaterialPropertiesObject(); + } + + onCurrentIndexChanged: + { + forceActiveFocus(); // causes the changed fields to be saved + activateDetailsWithIndex(currentIndex); + } +} From 94ce9205c3fc10f69c7508a189ca3a9641a4b123 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 22 Aug 2018 13:30:59 +0200 Subject: [PATCH 200/243] Remove pytest cache --- .gitignore | 1 + .pytest_cache/README.md | 8 --- .pytest_cache/v/cache/lastfailed | 100 ------------------------------- .pytest_cache/v/cache/nodeids | 3 - 4 files changed, 1 insertion(+), 111 deletions(-) delete mode 100644 .pytest_cache/README.md delete mode 100644 .pytest_cache/v/cache/lastfailed delete mode 100644 .pytest_cache/v/cache/nodeids diff --git a/.gitignore b/.gitignore index 98eaa6f414..5cc60c2f4c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ LC_MESSAGES .cache *.qmlc .mypy_cache +.pytest_cache #MacOS .DS_Store diff --git a/.pytest_cache/README.md b/.pytest_cache/README.md deleted file mode 100644 index bb78ba07ee..0000000000 --- a/.pytest_cache/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# pytest cache directory # - -This directory contains data from the pytest's cache plugin, -which provides the `--lf` and `--ff` options, as well as the `cache` fixture. - -**Do not** commit this to version control. - -See [the docs](https://docs.pytest.org/en/latest/cache.html) for more information. diff --git a/.pytest_cache/v/cache/lastfailed b/.pytest_cache/v/cache/lastfailed deleted file mode 100644 index adb96c8331..0000000000 --- a/.pytest_cache/v/cache/lastfailed +++ /dev/null @@ -1,100 +0,0 @@ -{ - "tests/Settings/TestCuraContainerRegistry.py::test_addContainerBadSettingVersion": true, - "tests/Settings/TestCuraContainerRegistry.py::test_addContainerExtruderStack": true, - "tests/Settings/TestCuraContainerRegistry.py::test_addContainerGlobalStack": true, - "tests/Settings/TestCuraContainerRegistry.py::test_addContainerGoodSettingVersion": true, - "tests/Settings/TestCuraContainerRegistry.py::test_addContainerNoSettingVersion": true, - "tests/Settings/TestExtruderStack.py::test_addContainer": true, - "tests/Settings/TestExtruderStack.py::test_constrainDefinitionValid[container0]": true, - "tests/Settings/TestExtruderStack.py::test_constrainDefinitionValid[container1]": true, - "tests/Settings/TestExtruderStack.py::test_constrainMaterialInvalid[container0]": true, - "tests/Settings/TestExtruderStack.py::test_constrainMaterialInvalid[container1]": true, - "tests/Settings/TestExtruderStack.py::test_constrainMaterialInvalid[container2]": true, - "tests/Settings/TestExtruderStack.py::test_constrainMaterialValid[container0]": true, - "tests/Settings/TestExtruderStack.py::test_constrainMaterialValid[container1]": true, - "tests/Settings/TestExtruderStack.py::test_constrainQualityChangesInvalid[container0]": true, - "tests/Settings/TestExtruderStack.py::test_constrainQualityChangesInvalid[container1]": true, - "tests/Settings/TestExtruderStack.py::test_constrainQualityChangesInvalid[container2]": true, - "tests/Settings/TestExtruderStack.py::test_constrainQualityChangesValid[container0]": true, - "tests/Settings/TestExtruderStack.py::test_constrainQualityChangesValid[container1]": true, - "tests/Settings/TestExtruderStack.py::test_constrainQualityInvalid[container0]": true, - "tests/Settings/TestExtruderStack.py::test_constrainQualityInvalid[container1]": true, - "tests/Settings/TestExtruderStack.py::test_constrainQualityInvalid[container2]": true, - "tests/Settings/TestExtruderStack.py::test_constrainQualityValid[container0]": true, - "tests/Settings/TestExtruderStack.py::test_constrainQualityValid[container1]": true, - "tests/Settings/TestExtruderStack.py::test_constrainUserChangesInvalid[container0]": true, - "tests/Settings/TestExtruderStack.py::test_constrainUserChangesInvalid[container1]": true, - "tests/Settings/TestExtruderStack.py::test_constrainUserChangesInvalid[container2]": true, - "tests/Settings/TestExtruderStack.py::test_constrainUserChangesValid[container0]": true, - "tests/Settings/TestExtruderStack.py::test_constrainUserChangesValid[container1]": true, - "tests/Settings/TestExtruderStack.py::test_constrainVariantInvalid[container0]": true, - "tests/Settings/TestExtruderStack.py::test_constrainVariantInvalid[container1]": true, - "tests/Settings/TestExtruderStack.py::test_constrainVariantValid[container0]": true, - "tests/Settings/TestExtruderStack.py::test_constrainVariantValid[container1]": true, - "tests/Settings/TestExtruderStack.py::test_deserializeMoveInstanceContainer": true, - "tests/Settings/TestExtruderStack.py::test_deserializeRemovesWrongContainerClass": true, - "tests/Settings/TestExtruderStack.py::test_deserializeRemovesWrongInstanceContainer": true, - "tests/Settings/TestExtruderStack.py::test_deserializeWrongDefinitionClass": true, - "tests/Settings/TestExtruderStack.py::test_getPropertyFallThrough": true, - "tests/Settings/TestExtruderStack.py::test_insertContainer": true, - "tests/Settings/TestExtruderStack.py::test_removeContainer": true, - "tests/Settings/TestExtruderStack.py::test_setPropertyUser[foo-value-100]": true, - "tests/Settings/TestExtruderStack.py::test_setPropertyUser[layer_height-default_value-0.1337]": true, - "tests/Settings/TestExtruderStack.py::test_setPropertyUser[layer_height-is_bright_pink-of course]": true, - "tests/Settings/TestExtruderStack.py::test_setPropertyUser[layer_height-value-0.1337]": true, - "tests/Settings/TestExtruderStack.py::test_setPropertyUser[support_enabled-value-True]": true, - "tests/Settings/TestGlobalStack.py::test_addContainer": true, - "tests/Settings/TestGlobalStack.py::test_addExtruder": true, - "tests/Settings/TestGlobalStack.py::test_constrainDefinitionChangesInvalid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainDefinitionChangesInvalid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_constrainDefinitionChangesInvalid[container2]": true, - "tests/Settings/TestGlobalStack.py::test_constrainDefinitionChangesValid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainDefinitionChangesValid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_constrainDefinitionValid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainDefinitionValid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_constrainMaterialInvalid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainMaterialInvalid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_constrainMaterialInvalid[container2]": true, - "tests/Settings/TestGlobalStack.py::test_constrainMaterialValid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainMaterialValid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_constrainQualityChangesInvalid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainQualityChangesInvalid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_constrainQualityChangesInvalid[container2]": true, - "tests/Settings/TestGlobalStack.py::test_constrainQualityChangesValid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainQualityChangesValid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_constrainQualityInvalid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainQualityInvalid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_constrainQualityInvalid[container2]": true, - "tests/Settings/TestGlobalStack.py::test_constrainQualityValid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainQualityValid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_constrainUserChangesInvalid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainUserChangesInvalid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_constrainUserChangesInvalid[container2]": true, - "tests/Settings/TestGlobalStack.py::test_constrainUserChangesValid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainUserChangesValid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_constrainVariantInvalid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainVariantInvalid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_constrainVariantValid[container0]": true, - "tests/Settings/TestGlobalStack.py::test_constrainVariantValid[container1]": true, - "tests/Settings/TestGlobalStack.py::test_deserializeMoveInstanceContainer": true, - "tests/Settings/TestGlobalStack.py::test_deserializeRemovesWrongContainerClass": true, - "tests/Settings/TestGlobalStack.py::test_deserializeRemovesWrongInstanceContainer": true, - "tests/Settings/TestGlobalStack.py::test_deserializeWrongDefinitionClass": true, - "tests/Settings/TestGlobalStack.py::test_getPropertyFallThrough": true, - "tests/Settings/TestGlobalStack.py::test_getPropertyInstancesBeforeResolve": true, - "tests/Settings/TestGlobalStack.py::test_getPropertyNoResolveInDefinition": true, - "tests/Settings/TestGlobalStack.py::test_getPropertyResolveInDefinition": true, - "tests/Settings/TestGlobalStack.py::test_getPropertyResolveInInstance": true, - "tests/Settings/TestGlobalStack.py::test_hasNoUserValue": true, - "tests/Settings/TestGlobalStack.py::test_hasUserValueQualityChanges": true, - "tests/Settings/TestGlobalStack.py::test_hasUserValueUserChanges": true, - "tests/Settings/TestGlobalStack.py::test_insertContainer": true, - "tests/Settings/TestGlobalStack.py::test_removeContainer": true, - "tests/Settings/TestGlobalStack.py::test_setNextStack": true, - "tests/Settings/TestGlobalStack.py::test_setPropertyUser[foo-value-100]": true, - "tests/Settings/TestGlobalStack.py::test_setPropertyUser[layer_height-default_value-0.1337]": true, - "tests/Settings/TestGlobalStack.py::test_setPropertyUser[layer_height-is_bright_pink-of course]": true, - "tests/Settings/TestGlobalStack.py::test_setPropertyUser[layer_height-value-0.1337]": true, - "tests/Settings/TestGlobalStack.py::test_setPropertyUser[support_enabled-value-True]": true, - "tests/TestMachineAction.py::test_addMachineAction": true -} \ No newline at end of file diff --git a/.pytest_cache/v/cache/nodeids b/.pytest_cache/v/cache/nodeids deleted file mode 100644 index d548ce2ff2..0000000000 --- a/.pytest_cache/v/cache/nodeids +++ /dev/null @@ -1,3 +0,0 @@ -[ - "plugins/VersionUpgrade/VersionUpgrade34to40/tests/TestVersionUpgrade34to40.py::test_upgradeVersionNr[Empty config file-[general]\\n version = 5\\n [metadata]\\n setting_version = 4\\n]" -] \ No newline at end of file From 29180740de7100f58853556ce8603c54d2741f58 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 22 Aug 2018 13:36:17 +0200 Subject: [PATCH 201/243] Fix missed names --- resources/qml/Cura.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 60f6e77ea9..046a887a71 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -120,7 +120,7 @@ UM.MainWindow text: catalog.i18nc("@title:menu menubar:file","&Save...") onTriggered: { - var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetype": "application/x-curaproject+xml" }; + var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/x-curaproject+xml" }; if(UM.Preferences.getValue("cura/dialog_on_project_save")) { saveWorkspaceDialog.args = args; @@ -142,7 +142,7 @@ UM.MainWindow onTriggered: { var localDeviceId = "local_file"; - UM.OutputDeviceManager.requestWriteToDevice(localDeviceId, PrintInformation.jobName, { "filter_by_machine": false, "preferred_mimetype": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml"}); + UM.OutputDeviceManager.requestWriteToDevice(localDeviceId, PrintInformation.jobName, { "filter_by_machine": false, "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml"}); } } @@ -151,7 +151,7 @@ UM.MainWindow text: catalog.i18nc("@action:inmenu menubar:file", "Export Selection..."); enabled: UM.Selection.hasSelection; iconName: "document-save-as"; - onTriggered: UM.OutputDeviceManager.requestWriteSelectionToDevice("local_file", PrintInformation.jobName, { "filter_by_machine": false, "preferred_mimetype": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml"}); + onTriggered: UM.OutputDeviceManager.requestWriteSelectionToDevice("local_file", PrintInformation.jobName, { "filter_by_machine": false, "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml"}); } MenuSeparator { } From 6225fff1f852e57bc47282cfd81cc7f11dfc6e2d Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 22 Aug 2018 15:58:58 +0200 Subject: [PATCH 202/243] Re-added material detail view Contributes to CURA-5378 --- cura/Machines/Models/BaseMaterialsModel.py | 2 +- cura/Machines/Models/BrandMaterialsModel.py | 33 +++++++++-------- .../Machines/Models/FavoriteMaterialsModel.py | 1 + cura/Machines/Models/GenericMaterialsModel.py | 1 + .../Preferences/Materials/MaterialSlot.qml | 2 +- .../Preferences/Materials/MaterialView.qml | 2 +- .../Materials/MaterialsDetailsPanel.qml | 35 +++++++++---------- .../Preferences/Materials/MaterialsPage.qml | 26 +++++++------- 8 files changed, 51 insertions(+), 51 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index ebf87e26b3..80ecf72c0a 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -34,7 +34,7 @@ class BaseMaterialsModel(ListModel): self.addRoleName(self.RootMaterialIdRole, "root_material_id") self.addRoleName(self.IdRole, "id") - self.addRoleName(self.GUIDRole, "guid") + self.addRoleName(self.GUIDRole, "GUID") self.addRoleName(self.NameRole, "name") self.addRoleName(self.BrandRole, "brand") self.addRoleName(self.MaterialRole, "material") diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py index 1eb76ca33c..154019d028 100644 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ b/cura/Machines/Models/BrandMaterialsModel.py @@ -127,24 +127,23 @@ class BrandMaterialsModel(ListModel): # Now handle the individual materials item = { - "root_material_id": root_material_id, - # "root_material_id": container_node.metadata["base_file"] <- as written in material management model - "id": metadata["id"], - "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml - "guid": metadata["GUID"], - "name": metadata["name"], - "brand": metadata["brand"], - "description": metadata["description"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "color_code": metadata["color_code"], - "density": metadata.get("properties", {}).get("density", ""), - "diameter": metadata.get("properties", {}).get("diameter", ""), + "root_material_id": root_material_id, + "id": metadata["id"], + "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml + "GUID": metadata["GUID"], + "name": metadata["name"], + "brand": metadata["brand"], + "description": metadata["description"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "color_code": metadata["color_code"], + "density": metadata.get("properties", {}).get("density", ""), + "diameter": metadata.get("properties", {}).get("diameter", ""), "approximate_diameter": metadata["approximate_diameter"], - "adhesion_info": metadata["adhesion_info"], - "is_read_only": self._container_registry.isReadOnly(metadata["id"]), - "container_node": container_node, - "is_favorite": root_material_id in favorites + "adhesion_info": metadata["adhesion_info"], + "is_read_only": self._container_registry.isReadOnly(metadata["id"]), + "container_node": container_node, + "is_favorite": root_material_id in favorites } brand_group_dict[brand][material_type].append(item) diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index d9ca69f4e1..35a5229da1 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -56,6 +56,7 @@ class FavoriteMaterialsModel(BaseMaterialsModel): item = { "root_material_id": root_material_id, "id": metadata["id"], + "GUID": metadata["GUID"], "name": metadata["name"], "brand": metadata["brand"], "material": metadata["material"], diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index 90c8d43026..a8f5bfbd35 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -55,6 +55,7 @@ class GenericMaterialsModel(BaseMaterialsModel): item = { "root_material_id": root_material_id, "id": metadata["id"], + "GUID": metadata["GUID"], "name": metadata["name"], "brand": metadata["brand"], "material": metadata["material"], diff --git a/resources/qml/Preferences/Materials/MaterialSlot.qml b/resources/qml/Preferences/Materials/MaterialSlot.qml index 678a69bd54..ab0dd23750 100644 --- a/resources/qml/Preferences/Materials/MaterialSlot.qml +++ b/resources/qml/Preferences/Materials/MaterialSlot.qml @@ -21,7 +21,7 @@ Rectangle width: parent.width color: base.currentItem == model ? UM.Theme.getColor("favorites_row_selected") : "transparent" - Row + Item { height: parent.height width: parent.width diff --git a/resources/qml/Preferences/Materials/MaterialView.qml b/resources/qml/Preferences/Materials/MaterialView.qml index c3503ae646..1e5362567a 100644 --- a/resources/qml/Preferences/Materials/MaterialView.qml +++ b/resources/qml/Preferences/Materials/MaterialView.qml @@ -38,7 +38,7 @@ TabView if (!base.containerId || !base.editingEnabled) { return "" } - var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.currentMaterialNode, true); + var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.currentItem.container_node, true); if (linkedMaterials.length == 0) { return "" } diff --git a/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml index e18ae15201..fc8c6d728c 100644 --- a/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml +++ b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml @@ -13,25 +13,24 @@ Item { id: detailsPanel + property var currentItem: base.currentItem + + onCurrentItemChanged: { updateMaterialPropertiesObject(currentItem) } + function updateMaterialPropertiesObject( currentItem ) { -// var currentItem = materialsModel.getItem(materialListView.currentIndex); - - materialProperties.name = currentItem.name ? currentItem.name : "Unknown"; - materialProperties.guid = currentItem.guid; - materialProperties.container_id = currentItem.container_id; - - materialProperties.brand = currentItem.brand ? currentItem.brand : "Unknown"; - materialProperties.material = currentItem.material ? currentItem.material : "Unknown"; - materialProperties.color_name = currentItem.color_name ? currentItem.color_name : "Yellow"; - materialProperties.color_code = currentItem.color_code ? currentItem.color_code : "yellow"; - - materialProperties.description = currentItem.description ? currentItem.description : ""; - materialProperties.adhesion_info = currentItem.adhesion_info ? currentItem.adhesion_info : ""; - - materialProperties.density = currentItem.density ? currentItem.density : 0.0; - materialProperties.diameter = currentItem.diameter ? currentItem.diameter : 0.0; - materialProperties.approximate_diameter = currentItem.approximate_diameter ? currentItem.approximate_diameter : "0"; + materialProperties.name = currentItem.name || "Unknown" + materialProperties.guid = currentItem.GUID; + materialProperties.container_id = currentItem.id + materialProperties.brand = currentItem.brand || "Unknown" + materialProperties.material = currentItem.material || "Unknown" + materialProperties.color_name = currentItem.color_name || "Yellow" + materialProperties.color_code = currentItem.color_code || "yellow" + materialProperties.description = currentItem.description || "" + materialProperties.adhesion_info = currentItem.adhesion_info || ""; + materialProperties.density = currentItem.density || 0.0 + materialProperties.diameter = currentItem.diameter || 0.0 + materialProperties.approximate_diameter = currentItem.approximate_diameter || "0" } Item @@ -66,7 +65,7 @@ Item editingEnabled: base.currentItem != null && !base.currentItem.is_read_only properties: materialProperties - containerId: base.currentItem != null ? base.currentItem.container_id : "" + containerId: base.currentItem != null ? base.currentItem.id : "" currentMaterialNode: base.currentItem.container_node diff --git a/resources/qml/Preferences/Materials/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml index 0e615a8d1b..ce7203f34b 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -56,8 +56,8 @@ Item // } // materialListView.currentIndex = itemIndex; // } - - // This connection makes sure that we will switch to the new + + onCurrentItemChanged: { MaterialsDetailsPanel.currentItem = currentItem } Connections { target: materialsModel @@ -284,17 +284,17 @@ Item MaterialsList {} } - // MaterialsDetailsPanel - // { - // anchors - // { - // left: materialScrollView.right - // leftMargin: UM.Theme.getSize("default_margin").width - // top: parent.top - // bottom: parent.bottom - // right: parent.right - // } - // } + MaterialsDetailsPanel + { + anchors + { + left: materialScrollView.right + leftMargin: UM.Theme.getSize("default_margin").width + top: parent.top + bottom: parent.bottom + right: parent.right + } + } } // Dialogs From 49e3c23d1438c7133e739af62b23f5f9297313b1 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 22 Aug 2018 16:53:27 +0200 Subject: [PATCH 203/243] Brackets on new line As per our code style. --- plugins/SimulationView/SimulationView.qml | 240 +++++++++++++++------- 1 file changed, 161 insertions(+), 79 deletions(-) diff --git a/plugins/SimulationView/SimulationView.qml b/plugins/SimulationView/SimulationView.qml index a3a8ced4cf..be767e93ab 100644 --- a/plugins/SimulationView/SimulationView.qml +++ b/plugins/SimulationView/SimulationView.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2017 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.4 @@ -12,30 +12,43 @@ import Cura 1.0 as Cura Item { id: base - width: { - if (UM.SimulationView.compatibilityMode) { + width: + { + if (UM.SimulationView.compatibilityMode) + { return UM.Theme.getSize("layerview_menu_size_compatibility").width; - } else { + } + else + { return UM.Theme.getSize("layerview_menu_size").width; } } height: { - if (viewSettings.collapsed) { - if (UM.SimulationView.compatibilityMode) { + if (viewSettings.collapsed) + { + if (UM.SimulationView.compatibilityMode) + { return UM.Theme.getSize("layerview_menu_size_compatibility_collapsed").height; } return UM.Theme.getSize("layerview_menu_size_collapsed").height; - } else if (UM.SimulationView.compatibilityMode) { + } + else if (UM.SimulationView.compatibilityMode) + { return UM.Theme.getSize("layerview_menu_size_compatibility").height; - } else if (UM.Preferences.getValue("layerview/layer_view_type") == 0) { + } + else if (UM.Preferences.getValue("layerview/layer_view_type") == 0) + { return UM.Theme.getSize("layerview_menu_size_material_color_mode").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height) - } else { + } + else + { return UM.Theme.getSize("layerview_menu_size").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height) } } Behavior on height { NumberAnimation { duration: 100 } } - property var buttonTarget: { + property var buttonTarget: + { if(parent != null) { var force_binding = parent.y; // ensure this gets reevaluated when the panel moves @@ -44,7 +57,8 @@ Item return Qt.point(0,0) } - Rectangle { + Rectangle + { id: layerViewMenu anchors.right: parent.right anchors.top: parent.top @@ -83,7 +97,8 @@ Item } } - ColumnLayout { + ColumnLayout + { id: viewSettings property bool collapsed: false @@ -195,7 +210,8 @@ Item width: width } - Connections { + Connections + { target: UM.Preferences onPreferenceChanged: { @@ -212,18 +228,22 @@ Item } } - Repeater { + Repeater + { model: Cura.ExtrudersModel{} - CheckBox { + CheckBox + { id: extrudersModelCheckBox checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == "" - onClicked: { + onClicked: + { viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0 UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|")); } visible: !UM.SimulationView.compatibilityMode enabled: index + 1 <= 4 - Rectangle { + Rectangle + { anchors.verticalCenter: parent.verticalCenter anchors.right: extrudersModelCheckBox.right width: UM.Theme.getSize("layerview_legend_size").width @@ -253,8 +273,10 @@ Item } } - Repeater { - model: ListModel { + Repeater + { + model: ListModel + { id: typesLegendModel Component.onCompleted: { @@ -285,13 +307,16 @@ Item } } - CheckBox { + CheckBox + { id: legendModelCheckBox checked: model.initialValue - onClicked: { + onClicked: + { UM.Preferences.setValue(model.preference, checked); } - Rectangle { + Rectangle + { anchors.verticalCenter: parent.verticalCenter anchors.right: legendModelCheckBox.right width: UM.Theme.getSize("layerview_legend_size").width @@ -320,18 +345,22 @@ Item } } - CheckBox { + CheckBox + { checked: viewSettings.only_show_top_layers - onClicked: { + onClicked: + { UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0); } text: catalog.i18nc("@label", "Only Show Top Layers") visible: UM.SimulationView.compatibilityMode style: UM.Theme.styles.checkbox } - CheckBox { + CheckBox + { checked: viewSettings.top_layer_count == 5 - onClicked: { + onClicked: + { UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1); } text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top") @@ -339,8 +368,10 @@ Item style: UM.Theme.styles.checkbox } - Repeater { - model: ListModel { + Repeater + { + model: ListModel + { id: typesLegendModelNoCheck Component.onCompleted: { @@ -355,11 +386,13 @@ Item } } - Label { + Label + { text: label visible: viewSettings.show_legend id: typesLegendModelLabel - Rectangle { + Rectangle + { anchors.verticalCenter: parent.verticalCenter anchors.right: typesLegendModelLabel.right width: UM.Theme.getSize("layerview_legend_size").width @@ -378,30 +411,37 @@ Item } // Text for the minimum, maximum and units for the feedrates and layer thickness - Item { + Item + { id: gradientLegend visible: viewSettings.show_gradient width: parent.width height: UM.Theme.getSize("layerview_row").height - anchors { + anchors + { topMargin: UM.Theme.getSize("slider_layerview_margin").height horizontalCenter: parent.horizontalCenter } - Label { + Label + { text: minText() anchors.left: parent.left color: UM.Theme.getColor("setting_control_text") font: UM.Theme.getFont("default") - function minText() { - if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) { + function minText() + { + if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) + { // Feedrate selected - if (UM.Preferences.getValue("layerview/layer_view_type") == 2) { + if (UM.Preferences.getValue("layerview/layer_view_type") == 2) + { return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2) } // Layer thickness selected - if (UM.Preferences.getValue("layerview/layer_view_type") == 3) { + if (UM.Preferences.getValue("layerview/layer_view_type") == 3) + { return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2) } } @@ -409,20 +449,25 @@ Item } } - Label { + Label + { text: unitsText() anchors.horizontalCenter: parent.horizontalCenter color: UM.Theme.getColor("setting_control_text") font: UM.Theme.getFont("default") - function unitsText() { - if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) { + function unitsText() + { + if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) + { // Feedrate selected - if (UM.Preferences.getValue("layerview/layer_view_type") == 2) { + if (UM.Preferences.getValue("layerview/layer_view_type") == 2) + { return "mm/s" } // Layer thickness selected - if (UM.Preferences.getValue("layerview/layer_view_type") == 3) { + if (UM.Preferences.getValue("layerview/layer_view_type") == 3) + { return "mm" } } @@ -430,20 +475,25 @@ Item } } - Label { + Label + { text: maxText() anchors.right: parent.right color: UM.Theme.getColor("setting_control_text") font: UM.Theme.getFont("default") - function maxText() { - if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) { + function maxText() + { + if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) + { // Feedrate selected - if (UM.Preferences.getValue("layerview/layer_view_type") == 2) { + if (UM.Preferences.getValue("layerview/layer_view_type") == 2) + { return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2) } // Layer thickness selected - if (UM.Preferences.getValue("layerview/layer_view_type") == 3) { + if (UM.Preferences.getValue("layerview/layer_view_type") == 3) + { return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2) } } @@ -453,7 +503,8 @@ Item } // Gradient colors for feedrate - Rectangle { // In QML 5.9 can be changed by LinearGradient + Rectangle + { // In QML 5.9 can be changed by LinearGradient // Invert values because then the bar is rotated 90 degrees id: feedrateGradient visible: viewSettings.show_feedrate_gradient @@ -463,20 +514,25 @@ Item border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") transform: Rotation {origin.x: 0; origin.y: 0; angle: 90} - gradient: Gradient { - GradientStop { + gradient: Gradient + { + GradientStop + { position: 0.000 color: Qt.rgba(1, 0.5, 0, 1) } - GradientStop { + GradientStop + { position: 0.625 color: Qt.rgba(0.375, 0.5, 0, 1) } - GradientStop { + GradientStop + { position: 0.75 color: Qt.rgba(0.25, 1, 0, 1) } - GradientStop { + GradientStop + { position: 1.0 color: Qt.rgba(0, 0, 1, 1) } @@ -484,7 +540,8 @@ Item } // Gradient colors for layer thickness (similar to parula colormap) - Rectangle { // In QML 5.9 can be changed by LinearGradient + Rectangle // In QML 5.9 can be changed by LinearGradient + { // Invert values because then the bar is rotated 90 degrees id: thicknessGradient visible: viewSettings.show_thickness_gradient @@ -494,24 +551,30 @@ Item border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") transform: Rotation {origin.x: 0; origin.y: 0; angle: 90} - gradient: Gradient { - GradientStop { + gradient: Gradient + { + GradientStop + { position: 0.000 color: Qt.rgba(1, 1, 0, 1) } - GradientStop { + GradientStop + { position: 0.25 color: Qt.rgba(1, 0.75, 0.25, 1) } - GradientStop { + GradientStop + { position: 0.5 color: Qt.rgba(0, 0.75, 0.5, 1) } - GradientStop { + GradientStop + { position: 0.75 color: Qt.rgba(0, 0.375, 0.75, 1) } - GradientStop { + GradientStop + { position: 1.0 color: Qt.rgba(0, 0, 0.5, 1) } @@ -520,19 +583,22 @@ Item } } - Item { + Item + { id: slidersBox width: parent.width visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity - anchors { + anchors + { top: parent.bottom topMargin: UM.Theme.getSize("slider_layerview_margin").height left: parent.left } - PathSlider { + PathSlider + { id: pathSlider height: UM.Theme.getSize("slider_handle").width @@ -553,25 +619,29 @@ Item rangeColor: UM.Theme.getColor("slider_groove_fill") // update values when layer data changes - Connections { + Connections + { target: UM.SimulationView onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath) onCurrentPathChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath) } // make sure the slider handlers show the correct value after switching views - Component.onCompleted: { + Component.onCompleted: + { pathSlider.setHandleValue(UM.SimulationView.currentPath) } } - LayerSlider { + LayerSlider + { id: layerSlider width: UM.Theme.getSize("slider_handle").width height: UM.Theme.getSize("layerview_menu_size").height - anchors { + anchors + { top: !UM.SimulationView.compatibilityMode ? pathSlider.bottom : parent.top topMargin: !UM.SimulationView.compatibilityMode ? UM.Theme.getSize("default_margin").height : 0 right: parent.right @@ -593,7 +663,8 @@ Item handleLabelWidth: UM.Theme.getSize("slider_layerview_background").width // update values when layer data changes - Connections { + Connections + { target: UM.SimulationView onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer) onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer) @@ -601,45 +672,54 @@ Item } // make sure the slider handlers show the correct value after switching views - Component.onCompleted: { + Component.onCompleted: + { layerSlider.setLowerValue(UM.SimulationView.minimumLayer) layerSlider.setUpperValue(UM.SimulationView.currentLayer) } } // Play simulation button - Button { + Button + { id: playButton iconSource: "./resources/simulation_resume.svg" style: UM.Theme.styles.small_tool_button visible: !UM.SimulationView.compatibilityMode - anchors { + anchors + { verticalCenter: pathSlider.verticalCenter } property var status: 0 // indicates if it's stopped (0) or playing (1) - onClicked: { - switch(status) { - case 0: { + onClicked: + { + switch(status) + { + case 0: + { resumeSimulation() break } - case 1: { + case 1: + { pauseSimulation() break } } } - function pauseSimulation() { + function pauseSimulation() + { UM.SimulationView.setSimulationRunning(false) iconSource = "./resources/simulation_resume.svg" simulationTimer.stop() status = 0 } - function resumeSimulation() { + function resumeSimulation() + { UM.SimulationView.setSimulationRunning(true) iconSource = "./resources/simulation_pause.svg" simulationTimer.start() @@ -652,7 +732,8 @@ Item interval: 100 running: false repeat: true - onTriggered: { + onTriggered: + { var currentPath = UM.SimulationView.currentPath var numPaths = UM.SimulationView.numPaths var currentLayer = UM.SimulationView.currentLayer @@ -697,7 +778,8 @@ Item } } - FontMetrics { + FontMetrics + { id: fontMetrics font: UM.Theme.getFont("default") } From 8da77736006429d5e719402e2bdc52bdb0250181 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 23 Aug 2018 16:04:51 +0200 Subject: [PATCH 204/243] Remove unused code Contributes to CURA-5162, CURA-5378 --- cura/CuraApplication.py | 6 +- .../Models/MaterialManagementModel.py | 104 ------------------ .../Preferences/Materials/OldMaterialList.qml | 98 ----------------- 3 files changed, 2 insertions(+), 206 deletions(-) delete mode 100644 cura/Machines/Models/MaterialManagementModel.py delete mode 100644 resources/qml/Preferences/Materials/OldMaterialList.qml diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 27f558bc41..27c0350eea 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -68,10 +68,9 @@ from cura.Machines.Models.NozzleModel import NozzleModel from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfilesDropDownMenuModel from cura.Machines.Models.CustomQualityProfilesDropDownMenuModel import CustomQualityProfilesDropDownMenuModel from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel -from cura.Machines.Models.MaterialManagementModel import MaterialManagementModel from cura.Machines.Models.FavoriteMaterialsModel import FavoriteMaterialsModel from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel -from cura.Machines.Models.BrandMaterialsModel import BrandMaterialsModel +from cura.Machines.Models.MaterialBrandsModel import MaterialBrandsModel from cura.Machines.Models.QualityManagementModel import QualityManagementModel from cura.Machines.Models.QualitySettingsModel import QualitySettingsModel from cura.Machines.Models.MachineManagementModel import MachineManagementModel @@ -936,8 +935,7 @@ class CuraApplication(QtApplication): qmlRegisterType(FavoriteMaterialsModel, "Cura", 1, 0, "FavoriteMaterialsModel") qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") - qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") - qmlRegisterType(MaterialManagementModel, "Cura", 1, 0, "MaterialManagementModel") + qmlRegisterType(MaterialBrandsModel, "Cura", 1, 0, "MaterialBrandsModel") qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel") qmlRegisterType(MachineManagementModel, "Cura", 1, 0, "MachineManagementModel") diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py deleted file mode 100644 index 46e9cb887a..0000000000 --- a/cura/Machines/Models/MaterialManagementModel.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright (c) 2018 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from PyQt5.QtCore import Qt - -from UM.Logger import Logger -from UM.Qt.ListModel import ListModel - - -# -# This model is for the Material management page. -# -class MaterialManagementModel(ListModel): - RootMaterialIdRole = Qt.UserRole + 1 - DisplayNameRole = Qt.UserRole + 2 - BrandRole = Qt.UserRole + 3 - MaterialTypeRole = Qt.UserRole + 4 - ColorNameRole = Qt.UserRole + 5 - ColorCodeRole = Qt.UserRole + 6 - ContainerNodeRole = Qt.UserRole + 7 - ContainerIdRole = Qt.UserRole + 8 - - DescriptionRole = Qt.UserRole + 9 - AdhesionInfoRole = Qt.UserRole + 10 - ApproximateDiameterRole = Qt.UserRole + 11 - GuidRole = Qt.UserRole + 12 - DensityRole = Qt.UserRole + 13 - DiameterRole = Qt.UserRole + 14 - IsReadOnlyRole = Qt.UserRole + 15 - - def __init__(self, parent = None): - super().__init__(parent) - - self.addRoleName(self.RootMaterialIdRole, "root_material_id") - self.addRoleName(self.DisplayNameRole, "name") - self.addRoleName(self.BrandRole, "brand") - self.addRoleName(self.MaterialTypeRole, "material") - self.addRoleName(self.ColorNameRole, "color_name") - self.addRoleName(self.ColorCodeRole, "color_code") - self.addRoleName(self.ContainerNodeRole, "container_node") - self.addRoleName(self.ContainerIdRole, "container_id") - - self.addRoleName(self.DescriptionRole, "description") - self.addRoleName(self.AdhesionInfoRole, "adhesion_info") - self.addRoleName(self.ApproximateDiameterRole, "approximate_diameter") - self.addRoleName(self.GuidRole, "guid") - self.addRoleName(self.DensityRole, "density") - self.addRoleName(self.DiameterRole, "diameter") - self.addRoleName(self.IsReadOnlyRole, "is_read_only") - - from cura.CuraApplication import CuraApplication - self._container_registry = CuraApplication.getInstance().getContainerRegistry() - self._machine_manager = CuraApplication.getInstance().getMachineManager() - self._extruder_manager = CuraApplication.getInstance().getExtruderManager() - self._material_manager = CuraApplication.getInstance().getMaterialManager() - - self._machine_manager.globalContainerChanged.connect(self._update) - self._extruder_manager.activeExtruderChanged.connect(self._update) - self._material_manager.materialsUpdated.connect(self._update) - - self._update() - - def _update(self): - Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) - - global_stack = self._machine_manager.activeMachine - if global_stack is None: - self.setItems([]) - return - active_extruder_stack = self._machine_manager.activeStack - - available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, - active_extruder_stack) - if available_material_dict is None: - self.setItems([]) - return - - material_list = [] - for root_material_id, container_node in available_material_dict.items(): - keys_to_fetch = ("name", - "brand", - "material", - "color_name", - "color_code", - "description", - "adhesion_info", - "approximate_diameter",) - - item = {"root_material_id": container_node.metadata["base_file"], - "container_node": container_node, - "guid": container_node.metadata["GUID"], - "container_id": container_node.metadata["id"], - "density": container_node.metadata.get("properties", {}).get("density", ""), - "diameter": container_node.metadata.get("properties", {}).get("diameter", ""), - "is_read_only": self._container_registry.isReadOnly(container_node.metadata["id"]), - } - - for key in keys_to_fetch: - item[key] = container_node.metadata.get(key, "") - - material_list.append(item) - - material_list = sorted(material_list, key = lambda k: (k["brand"].upper(), k["name"].upper())) - self.setItems(material_list) diff --git a/resources/qml/Preferences/Materials/OldMaterialList.qml b/resources/qml/Preferences/Materials/OldMaterialList.qml deleted file mode 100644 index 6c15ddf7cc..0000000000 --- a/resources/qml/Preferences/Materials/OldMaterialList.qml +++ /dev/null @@ -1,98 +0,0 @@ -ListView -{ - id: materialListView - - model: materialsModel - - section.property: "brand" - section.criteria: ViewSection.FullString - section.delegate: Rectangle - { - width: materialScrollView.width - height: childrenRect.height - color: palette.light - - Label - { - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_lining").width - text: section - font.bold: true - color: palette.text - } - } - - delegate: Rectangle - { - width: materialScrollView.width - height: childrenRect.height - color: ListView.isCurrentItem ? palette.highlight : (model.index % 2) ? palette.base : palette.alternateBase - - Row - { - id: materialRow - spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.right: parent.right - - property bool isCurrentItem: parent.ListView.isCurrentItem - - property bool isItemActivated: - { - const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - return model.root_material_id == root_material_id; - } - - Rectangle - { - width: Math.floor(parent.height * 0.8) - height: Math.floor(parent.height * 0.8) - color: model.color_code - border.color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; - anchors.verticalCenter: parent.verticalCenter - } - Label - { - width: Math.floor((parent.width * 0.3)) - text: model.material - elide: Text.ElideRight - font.italic: materialRow.isItemActivated - color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; - } - Label - { - text: (model.name != model.material) ? model.name : "" - elide: Text.ElideRight - font.italic: materialRow.isItemActivated - color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; - } - } - - MouseArea - { - anchors.fill: parent - onClicked: - { - parent.ListView.view.currentIndex = model.index; - } - } - } - - function activateDetailsWithIndex(index) - { - var model = materialsModel.getItem(index); - base.currentItem = model; - materialDetailsView.containerId = model.container_id; - materialDetailsView.currentMaterialNode = model.container_node; - - detailsPanel.updateMaterialPropertiesObject(); - } - - onCurrentIndexChanged: - { - forceActiveFocus(); // causes the changed fields to be saved - activateDetailsWithIndex(currentIndex); - } -} From 56a5f59964d25066c713dec6d5b04558b9a2bcab Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 23 Aug 2018 16:39:40 +0200 Subject: [PATCH 205/243] Cleaner code I was hoping to completely nix the generic materials model (since it's basically just a brand "Generic", but then in the QML it has to be have the same in terms of sub-menus or fold-outs and that looked stupid (Generic -> ABS -> ABS)). So we keep that one for now. It is cleaner though. Contributes to CURA-5162, CURA-5378 --- cura/Machines/Models/BaseMaterialsModel.py | 95 ++++++---- cura/Machines/Models/BrandMaterialsModel.py | 174 ------------------ .../Machines/Models/FavoriteMaterialsModel.py | 43 ++--- cura/Machines/Models/GenericMaterialsModel.py | 51 ++--- cura/Machines/Models/MaterialBrandsModel.py | 129 +++++++++++++ resources/qml/Menus/MaterialMenu.qml | 4 +- .../Preferences/Materials/MaterialsList.qml | 4 +- .../Preferences/Materials/MaterialsPage.qml | 2 +- 8 files changed, 222 insertions(+), 280 deletions(-) delete mode 100644 cura/Machines/Models/BrandMaterialsModel.py create mode 100644 cura/Machines/Models/MaterialBrandsModel.py diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 80ecf72c0a..122c38804c 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -2,51 +2,54 @@ # Cura is released under the terms of the LGPLv3 or higher. from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty - -from UM.Application import Application from UM.Qt.ListModel import ListModel -# -# This is the base model class for GenericMaterialsModel and BrandMaterialsModel -# Those 2 models are used by the material drop down menu to show generic materials and branded materials separately. -# The extruder position defined here is being used to bound a menu to the correct extruder. This is used in the top -# bar menu "Settings" -> "Extruder nr" -> "Material" -> this menu -# +## This is the base model class for GenericMaterialsModel and MaterialBrandsModel. +# Those 2 models are used by the material drop down menu to show generic materials and branded materials separately. +# The extruder position defined here is being used to bound a menu to the correct extruder. This is used in the top +# bar menu "Settings" -> "Extruder nr" -> "Material" -> this menu class BaseMaterialsModel(ListModel): - RootMaterialIdRole = Qt.UserRole + 1 - IdRole = Qt.UserRole + 2 - NameRole = Qt.UserRole + 3 - BrandRole = Qt.UserRole + 4 - MaterialRole = Qt.UserRole + 5 - ColorRole = Qt.UserRole + 6 - ContainerNodeRole = Qt.UserRole + 7 - ColorCodeRole = Qt.UserRole + 8 - GUIDRole = Qt.UserRole + 9 - IsFavoriteRole = Qt.UserRole + 10 extruderPositionChanged = pyqtSignal() def __init__(self, parent = None): super().__init__(parent) - self._application = Application.getInstance() - self._machine_manager = self._application.getMachineManager() - self.addRoleName(self.RootMaterialIdRole, "root_material_id") - self.addRoleName(self.IdRole, "id") - self.addRoleName(self.GUIDRole, "GUID") - self.addRoleName(self.NameRole, "name") - self.addRoleName(self.BrandRole, "brand") - self.addRoleName(self.MaterialRole, "material") - self.addRoleName(self.ColorRole, "color_name") - self.addRoleName(self.ColorCodeRole, "color_code") - self.addRoleName(self.ContainerNodeRole, "container_node") - self.addRoleName(self.IsFavoriteRole, "is_favorite") + from cura.CuraApplication import CuraApplication + + self._application = CuraApplication.getInstance() + + # Make these managers available to all material models + self._extruder_manager = self._application.getExtruderManager() + self._machine_manager = self._application.getMachineManager() + self._material_manager = self._application.getMaterialManager() + + # Update the stack and the model data when the machine changes + self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack) + + # Update this model when switching machines + self._machine_manager.activeStackChanged.connect(self._update) + + # Update this model when list of materials changes + self._material_manager.materialsUpdated.connect(self._update) + + self.addRoleName(Qt.UserRole + 1, "root_material_id") + self.addRoleName(Qt.UserRole + 2, "id") + self.addRoleName(Qt.UserRole + 3, "GUID") + self.addRoleName(Qt.UserRole + 4, "name") + self.addRoleName(Qt.UserRole + 5, "brand") + self.addRoleName(Qt.UserRole + 6, "material") + self.addRoleName(Qt.UserRole + 7, "color_name") + self.addRoleName(Qt.UserRole + 8, "color_code") + self.addRoleName(Qt.UserRole + 9, "container_node") + self.addRoleName(Qt.UserRole + 10, "is_favorite") self._extruder_position = 0 self._extruder_stack = None - # Update the stack and the model data when the machine changes - self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack) + + self._available_materials = None + self._favorite_ids = None def _updateExtruderStack(self): global_stack = self._machine_manager.activeMachine @@ -71,8 +74,30 @@ class BaseMaterialsModel(ListModel): def extruderPosition(self) -> int: return self._extruder_position - # - # This is an abstract method that needs to be implemented by - # + ## This is an abstract method that needs to be implemented by the specific + # models themselves. def _update(self): pass + + ## This method is used by all material models in the beginning of the + # _update() method in order to prevent errors. It's the same in all models + # so it's placed here for easy access. + def _canUpdate(self): + global_stack = self._machine_manager.activeMachine + + if global_stack is None: + return False + + extruder_position = str(self._extruder_position) + + if extruder_position not in global_stack.extruders: + return False + + extruder_stack = global_stack.extruders[extruder_position] + + self._available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) + if self._available_materials is None: + return False + + return True + diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py deleted file mode 100644 index 154019d028..0000000000 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright (c) 2018 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty - -from UM.Qt.ListModel import ListModel -from UM.Logger import Logger -from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel - - -# -# This is an intermediate model to group materials with different colours for a same brand and type. -# -class MaterialsModelGroupedByType(ListModel): - NameRole = Qt.UserRole + 1 - ColorsRole = Qt.UserRole + 2 - - def __init__(self, parent = None): - super().__init__(parent) - - self.addRoleName(self.NameRole, "name") - self.addRoleName(self.ColorsRole, "colors") - - -# -# This model is used to show branded materials in the material drop down menu. -# The structure of the menu looks like this: -# Brand -> Material Type -> list of materials -# -# To illustrate, a branded material menu may look like this: -# Ultimaker -> PLA -> Yellow PLA -# -> Black PLA -# -> ... -# -> ABS -> White ABS -# ... -# -class BrandMaterialsModel(ListModel): - NameRole = Qt.UserRole + 1 - MaterialsRole = Qt.UserRole + 2 - - extruderPositionChanged = pyqtSignal() - - def __init__(self, parent = None): - super().__init__(parent) - - self.addRoleName(self.NameRole, "name") - self.addRoleName(self.MaterialsRole, "materials") - - self._extruder_position = 0 - self._extruder_stack = None - - from cura.CuraApplication import CuraApplication - self._container_registry = CuraApplication.getInstance().getContainerRegistry() - self._machine_manager = CuraApplication.getInstance().getMachineManager() - self._extruder_manager = CuraApplication.getInstance().getExtruderManager() - self._material_manager = CuraApplication.getInstance().getMaterialManager() - - self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack) - self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines. - self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes. - # self._material_manager.favoritesUpdated.connect(self._update) # Update when favorites are changed - self._update() - - def _updateExtruderStack(self): - global_stack = self._machine_manager.activeMachine - if global_stack is None: - return - - if self._extruder_stack is not None: - self._extruder_stack.pyqtContainersChanged.disconnect(self._update) - self._extruder_stack = global_stack.extruders.get(str(self._extruder_position)) - if self._extruder_stack is not None: - self._extruder_stack.pyqtContainersChanged.connect(self._update) - # Force update the model when the extruder stack changes - self._update() - - def setExtruderPosition(self, position: int): - if self._extruder_stack is None or self._extruder_position != position: - self._extruder_position = position - self._updateExtruderStack() - self.extruderPositionChanged.emit() - - @pyqtProperty(int, fset=setExtruderPosition, notify=extruderPositionChanged) - def extruderPosition(self) -> int: - return self._extruder_position - - def _update(self): - Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) - global_stack = self._machine_manager.activeMachine - if global_stack is None: - self.setItems([]) - return - extruder_position = str(self._extruder_position) - if extruder_position not in global_stack.extruders: - self.setItems([]) - return - extruder_stack = global_stack.extruders[str(self._extruder_position)] - - available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, - extruder_stack) - if available_material_dict is None: - self.setItems([]) - return - - brand_item_list = [] - brand_group_dict = {} - for root_material_id, container_node in available_material_dict.items(): - metadata = container_node.metadata - - favorites = self._material_manager.getFavorites() - - # Do not include the materials from a to-be-removed package - if bool(metadata.get("removed", False)): - continue - - # Skip generic materials, and add brands we haven't seen yet to the dict - brand = metadata["brand"] - if brand.lower() == "generic": - continue - if brand not in brand_group_dict: - brand_group_dict[brand] = {} - - # Add material types we haven't seen yet to the dict - material_type = metadata["material"] - if material_type not in brand_group_dict[brand]: - brand_group_dict[brand][material_type] = [] - - # Now handle the individual materials - item = { - "root_material_id": root_material_id, - "id": metadata["id"], - "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml - "GUID": metadata["GUID"], - "name": metadata["name"], - "brand": metadata["brand"], - "description": metadata["description"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "color_code": metadata["color_code"], - "density": metadata.get("properties", {}).get("density", ""), - "diameter": metadata.get("properties", {}).get("diameter", ""), - "approximate_diameter": metadata["approximate_diameter"], - "adhesion_info": metadata["adhesion_info"], - "is_read_only": self._container_registry.isReadOnly(metadata["id"]), - "container_node": container_node, - "is_favorite": root_material_id in favorites - } - brand_group_dict[brand][material_type].append(item) - - for brand, material_dict in brand_group_dict.items(): - brand_item = {"name": brand, - "materials": MaterialsModelGroupedByType(self)} - - material_type_item_list = [] - for material_type, material_list in material_dict.items(): - material_type_item = {"name": material_type, - "colors": BaseMaterialsModel(self)} - material_type_item["colors"].clear() - - # Sort materials by name - material_list = sorted(material_list, key = lambda x: x["name"].upper()) - material_type_item["colors"].setItems(material_list) - - material_type_item_list.append(material_type_item) - - # Sort material type by name - material_type_item_list = sorted(material_type_item_list, key = lambda x: x["name"].upper()) - brand_item["materials"].setItems(material_type_item_list) - - brand_item_list.append(brand_item) - - # Sort brand by name - brand_item_list = sorted(brand_item_list, key = lambda x: x["name"].upper()) - self.setItems(brand_item_list) diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index 35a5229da1..34e148e2fd 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -8,51 +8,32 @@ class FavoriteMaterialsModel(BaseMaterialsModel): def __init__(self, parent = None): super().__init__(parent) - - from cura.CuraApplication import CuraApplication - self._preferences = CuraApplication.getInstance().getPreferences() - self._machine_manager = CuraApplication.getInstance().getMachineManager() - self._extruder_manager = CuraApplication.getInstance().getExtruderManager() - self._material_manager = CuraApplication.getInstance().getMaterialManager() - - self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines. - self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes. self._material_manager.favoritesUpdated.connect(self._update) # Update when favorites are changed self._update() def _update(self): - Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) - global_stack = self._machine_manager.activeMachine - if global_stack is None: + # Perform standard check and reset if the check fails + if not self._canUpdate(): self.setItems([]) return - extruder_position = str(self._extruder_position) - if extruder_position not in global_stack.extruders: - self.setItems([]) - return - extruder_stack = global_stack.extruders[extruder_position] - - available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) - if available_material_dict is None: - self.setItems([]) - return - - favorite_ids = self._material_manager.getFavorites() + # Get updated list of favorites + self._favorite_ids = self._material_manager.getFavorites() item_list = [] - for root_material_id, container_node in available_material_dict.items(): - metadata = container_node.metadata - # Only add results for favorite materials - if root_material_id not in favorite_ids: - continue + for root_material_id, container_node in self._available_materials.items(): + metadata = container_node.metadata # Do not include the materials from a to-be-removed package if bool(metadata.get("removed", False)): continue + # Only add results for favorite materials + if root_material_id not in self._favorite_ids: + continue + item = { "root_material_id": root_material_id, "id": metadata["id"], @@ -63,11 +44,11 @@ class FavoriteMaterialsModel(BaseMaterialsModel): "color_name": metadata["color_name"], "color_code": metadata["color_code"], "container_node": container_node, - "is_favorite": True + "is_favorite": True # Don't need to set since we only include favorites anyway } item_list.append(item) - # Sort the item list by material name alphabetically + # Sort the item list alphabetically by name item_list = sorted(item_list, key = lambda d: d["brand"].upper()) self.setItems(item_list) diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index a8f5bfbd35..3432f3e35c 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -4,44 +4,25 @@ from UM.Logger import Logger from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel - class GenericMaterialsModel(BaseMaterialsModel): def __init__(self, parent = None): super().__init__(parent) - - from cura.CuraApplication import CuraApplication - self._machine_manager = CuraApplication.getInstance().getMachineManager() - self._extruder_manager = CuraApplication.getInstance().getExtruderManager() - self._material_manager = CuraApplication.getInstance().getMaterialManager() - - self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines. - self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes. self._update() def _update(self): - Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) - global_stack = self._machine_manager.activeMachine - if global_stack is None: - self.setItems([]) - return - extruder_position = str(self._extruder_position) - if extruder_position not in global_stack.extruders: - self.setItems([]) - return - extruder_stack = global_stack.extruders[extruder_position] - - available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, - extruder_stack) - if available_material_dict is None: + # Perform standard check and reset if the check fails + if not self._canUpdate(): self.setItems([]) return - favorites = self._material_manager.getFavorites() + # Get updated list of favorites + self._favorite_ids = self._material_manager.getFavorites() item_list = [] - for root_material_id, container_node in available_material_dict.items(): + + for root_material_id, container_node in self._available_materials.items(): metadata = container_node.metadata # Only add results for generic materials @@ -54,19 +35,19 @@ class GenericMaterialsModel(BaseMaterialsModel): item = { "root_material_id": root_material_id, - "id": metadata["id"], - "GUID": metadata["GUID"], - "name": metadata["name"], - "brand": metadata["brand"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "color_code": metadata["color_code"], - "container_node": container_node, - "is_favorite": root_material_id in favorites + "id": metadata["id"], + "GUID": metadata["GUID"], + "name": metadata["name"], + "brand": metadata["brand"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "color_code": metadata["color_code"], + "container_node": container_node, + "is_favorite": root_material_id in self._favorite_ids } item_list.append(item) - # Sort the item list by material name alphabetically + # Sort the item list alphabetically by name item_list = sorted(item_list, key = lambda d: d["name"].upper()) self.setItems(item_list) diff --git a/cura/Machines/Models/MaterialBrandsModel.py b/cura/Machines/Models/MaterialBrandsModel.py new file mode 100644 index 0000000000..89d9fc7bfd --- /dev/null +++ b/cura/Machines/Models/MaterialBrandsModel.py @@ -0,0 +1,129 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty +from UM.Qt.ListModel import ListModel +from UM.Logger import Logger +from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel + +class MaterialTypesModel(ListModel): + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(Qt.UserRole + 1, "name") + self.addRoleName(Qt.UserRole + 2, "colors") + +class MaterialBrandsModel(BaseMaterialsModel): + + extruderPositionChanged = pyqtSignal() + + def __init__(self, parent = None): + super().__init__(parent) + + from cura.CuraApplication import CuraApplication + + self.addRoleName(Qt.UserRole + 1, "name") + self.addRoleName(Qt.UserRole + 2, "material_types") + + self._container_registry = CuraApplication.getInstance().getContainerRegistry() + + self._update() + + def _update(self): + + # Perform standard check and reset if the check fails + if not self._canUpdate(): + self.setItems([]) + return + + # Get updated list of favorites + self._favorite_ids = self._material_manager.getFavorites() + + brand_item_list = [] + brand_group_dict = {} + + # Part 1: Generate the entire tree of brands -> material types -> spcific materials + for root_material_id, container_node in self._available_materials.items(): + metadata = container_node.metadata + + # Do not include the materials from a to-be-removed package + if bool(metadata.get("removed", False)): + continue + + # Add brands we haven't seen yet to the dict, skipping generics + brand = metadata["brand"] + if brand.lower() == "generic": + continue + if brand not in brand_group_dict: + brand_group_dict[brand] = {} + + # Add material types we haven't seen yet to the dict + material_type = metadata["material"] + if material_type not in brand_group_dict[brand]: + brand_group_dict[brand][material_type] = [] + + # Now handle the individual materials + item = { + "root_material_id": root_material_id, + "id": metadata["id"], + "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml + "GUID": metadata["GUID"], + "name": metadata["name"], + "brand": metadata["brand"], + "description": metadata["description"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "color_code": metadata["color_code"], + "density": metadata.get("properties", {}).get("density", ""), + "diameter": metadata.get("properties", {}).get("diameter", ""), + "approximate_diameter": metadata["approximate_diameter"], + "adhesion_info": metadata["adhesion_info"], + "is_read_only": self._container_registry.isReadOnly(metadata["id"]), + "container_node": container_node, + "is_favorite": root_material_id in self._favorite_ids + } + brand_group_dict[brand][material_type].append(item) + + # Part 2: Organize the tree into models + # + # Normally, the structure of the menu looks like this: + # Brand -> Material Type -> Specific Material + # + # To illustrate, a branded material menu may look like this: + # Ultimaker ┳ PLA ┳ Yellow PLA + # ┃ ┣ Black PLA + # ┃ â”— ... + # ┃ + # â”— ABS ┳ White ABS + # â”— ... + for brand, material_dict in brand_group_dict.items(): + + material_type_item_list = [] + brand_item = { + "name": brand, + "material_types": MaterialTypesModel(self) + } + + for material_type, material_list in material_dict.items(): + material_type_item = { + "name": material_type, + "colors": BaseMaterialsModel(self) + } + material_type_item["colors"].clear() + + # Sort materials by name + material_list = sorted(material_list, key = lambda x: x["name"].upper()) + material_type_item["colors"].setItems(material_list) + + material_type_item_list.append(material_type_item) + + # Sort material type by name + material_type_item_list = sorted(material_type_item_list, key = lambda x: x["name"].upper()) + brand_item["material_types"].setItems(material_type_item_list) + + brand_item_list.append(brand_item) + + # Sort brand by name + brand_item_list = sorted(brand_item_list, key = lambda x: x["name"].upper()) + self.setItems(brand_item_list) diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index a53bc72a94..186c5d1d2a 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -26,7 +26,7 @@ Menu extruderPosition: menu.extruderIndex } - Cura.BrandMaterialsModel + Cura.MaterialBrandsModel { id: brandModel extruderPosition: menu.extruderIndex @@ -80,7 +80,7 @@ Menu id: brandMenu title: brandName property string brandName: model.name - property var brandMaterials: model.materials + property var brandMaterials: model.material_types Instantiator { diff --git a/resources/qml/Preferences/Materials/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml index a051f55cac..220ce0134d 100644 --- a/resources/qml/Preferences/Materials/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -18,7 +18,7 @@ Item // Children UM.I18nCatalog { id: catalog; name: "cura"; } - Cura.BrandMaterialsModel { id: materialsModel } + Cura.MaterialBrandsModel { id: materialsModel } Cura.FavoriteMaterialsModel { id: favoriteMaterialsModel } Cura.GenericMaterialsModel { id: genericMaterialsModel } Column @@ -186,7 +186,7 @@ Item { id: brand_section property var expanded: true - property var types_model: model.materials + property var types_model: model.material_types height: childrenRect.height width: parent.width Rectangle diff --git a/resources/qml/Preferences/Materials/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml index ce7203f34b..4df6049b3f 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -31,7 +31,7 @@ Item id: catalog name: "cura" } - Cura.BrandMaterialsModel + Cura.MaterialBrandsModel { id: materialsModel } From 6be9b5e27fb8cc2e0d3a9941b3824b40bc94d20a Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 23 Aug 2018 16:58:23 +0200 Subject: [PATCH 206/243] Consolidate models some more Contributes to CURA-5162, CURA-5378 --- cura/Machines/Models/BaseMaterialsModel.py | 42 ++++++++++++++++--- .../Machines/Models/FavoriteMaterialsModel.py | 13 +----- cura/Machines/Models/GenericMaterialsModel.py | 21 +++------- cura/Machines/Models/MaterialBrandsModel.py | 24 +---------- 4 files changed, 44 insertions(+), 56 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 122c38804c..ff006d00ae 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -21,6 +21,7 @@ class BaseMaterialsModel(ListModel): self._application = CuraApplication.getInstance() # Make these managers available to all material models + self._container_registry = self._application.getInstance().getContainerRegistry() self._extruder_manager = self._application.getExtruderManager() self._machine_manager = self._application.getMachineManager() self._material_manager = self._application.getMaterialManager() @@ -39,11 +40,17 @@ class BaseMaterialsModel(ListModel): self.addRoleName(Qt.UserRole + 3, "GUID") self.addRoleName(Qt.UserRole + 4, "name") self.addRoleName(Qt.UserRole + 5, "brand") - self.addRoleName(Qt.UserRole + 6, "material") - self.addRoleName(Qt.UserRole + 7, "color_name") - self.addRoleName(Qt.UserRole + 8, "color_code") - self.addRoleName(Qt.UserRole + 9, "container_node") - self.addRoleName(Qt.UserRole + 10, "is_favorite") + self.addRoleName(Qt.UserRole + 6, "description") + self.addRoleName(Qt.UserRole + 7, "material") + self.addRoleName(Qt.UserRole + 8, "color_name") + self.addRoleName(Qt.UserRole + 9, "color_code") + self.addRoleName(Qt.UserRole + 10, "density") + self.addRoleName(Qt.UserRole + 11, "diameter") + self.addRoleName(Qt.UserRole + 12, "approximate_diameter") + self.addRoleName(Qt.UserRole + 13, "adhesion_info") + self.addRoleName(Qt.UserRole + 14, "is_read_only") + self.addRoleName(Qt.UserRole + 15, "container_node") + self.addRoleName(Qt.UserRole + 16, "is_favorite") self._extruder_position = 0 self._extruder_stack = None @@ -101,3 +108,28 @@ class BaseMaterialsModel(ListModel): return True + ## This is another convenience function which is shared by all material + # models so it's put here to avoid having so much duplicated code. + def _createMaterialItem(self, root_material_id, container_node): + metadata = container_node.metadata + item = { + "root_material_id": root_material_id, + "id": metadata["id"], + "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml + "GUID": metadata["GUID"], + "name": metadata["name"], + "brand": metadata["brand"], + "description": metadata["description"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "color_code": metadata["color_code"], + "density": metadata.get("properties", {}).get("density", ""), + "diameter": metadata.get("properties", {}).get("diameter", ""), + "approximate_diameter": metadata["approximate_diameter"], + "adhesion_info": metadata["adhesion_info"], + "is_read_only": self._container_registry.isReadOnly(metadata["id"]), + "container_node": container_node, + "is_favorite": root_material_id in self._favorite_ids + } + return item + diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index 34e148e2fd..3c5ca226fe 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -34,18 +34,7 @@ class FavoriteMaterialsModel(BaseMaterialsModel): if root_material_id not in self._favorite_ids: continue - item = { - "root_material_id": root_material_id, - "id": metadata["id"], - "GUID": metadata["GUID"], - "name": metadata["name"], - "brand": metadata["brand"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "color_code": metadata["color_code"], - "container_node": container_node, - "is_favorite": True # Don't need to set since we only include favorites anyway - } + item = self._createMaterialItem(root_material_id, container_node) item_list.append(item) # Sort the item list alphabetically by name diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index 3432f3e35c..27e6fdfd7c 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -25,26 +25,15 @@ class GenericMaterialsModel(BaseMaterialsModel): for root_material_id, container_node in self._available_materials.items(): metadata = container_node.metadata - # Only add results for generic materials - if metadata["brand"].lower() != "generic": - continue - # Do not include the materials from a to-be-removed package if bool(metadata.get("removed", False)): continue - item = { - "root_material_id": root_material_id, - "id": metadata["id"], - "GUID": metadata["GUID"], - "name": metadata["name"], - "brand": metadata["brand"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "color_code": metadata["color_code"], - "container_node": container_node, - "is_favorite": root_material_id in self._favorite_ids - } + # Only add results for generic materials + if metadata["brand"].lower() != "generic": + continue + + item = self._createMaterialItem(root_material_id, container_node) item_list.append(item) # Sort the item list alphabetically by name diff --git a/cura/Machines/Models/MaterialBrandsModel.py b/cura/Machines/Models/MaterialBrandsModel.py index 89d9fc7bfd..3f917abb16 100644 --- a/cura/Machines/Models/MaterialBrandsModel.py +++ b/cura/Machines/Models/MaterialBrandsModel.py @@ -21,13 +21,9 @@ class MaterialBrandsModel(BaseMaterialsModel): def __init__(self, parent = None): super().__init__(parent) - from cura.CuraApplication import CuraApplication - self.addRoleName(Qt.UserRole + 1, "name") self.addRoleName(Qt.UserRole + 2, "material_types") - self._container_registry = CuraApplication.getInstance().getContainerRegistry() - self._update() def _update(self): @@ -64,25 +60,7 @@ class MaterialBrandsModel(BaseMaterialsModel): brand_group_dict[brand][material_type] = [] # Now handle the individual materials - item = { - "root_material_id": root_material_id, - "id": metadata["id"], - "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml - "GUID": metadata["GUID"], - "name": metadata["name"], - "brand": metadata["brand"], - "description": metadata["description"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "color_code": metadata["color_code"], - "density": metadata.get("properties", {}).get("density", ""), - "diameter": metadata.get("properties", {}).get("diameter", ""), - "approximate_diameter": metadata["approximate_diameter"], - "adhesion_info": metadata["adhesion_info"], - "is_read_only": self._container_registry.isReadOnly(metadata["id"]), - "container_node": container_node, - "is_favorite": root_material_id in self._favorite_ids - } + item = self._createMaterialItem(root_material_id, container_node) brand_group_dict[brand][material_type].append(item) # Part 2: Organize the tree into models From 8582a1ba1ad6b1287f638c9ac21cc4de8eb8dc22 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 23 Aug 2018 16:59:09 +0200 Subject: [PATCH 207/243] Mock application in unit tests --- tests/conftest.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index f2c709d8d8..77d215815a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,19 +3,21 @@ # The purpose of this class is to create fixtures or methods that can be shared among all tests. +import unittest.mock import pytest + from UM.Qt.QtApplication import QtApplication #QtApplication import is required, even though it isn't used. from cura.CuraApplication import CuraApplication from cura.MachineActionManager import MachineActionManager + + # Create a CuraApplication object that will be shared among all tests. It needs to be initialized. # Since we need to use it more that once, we create the application the first time and use its instance afterwards. @pytest.fixture() def application() -> CuraApplication: - application = CuraApplication.getInstance() - if application is None: - application = CuraApplication() - return application + app = unittest.mock.MagicMock() + return app # Returns a MachineActionManager instance. @pytest.fixture() From 26fced22bb3b1c124ae65dd6f1524ad9f5aa1ca5 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 21 Aug 2018 14:13:27 +0200 Subject: [PATCH 208/243] Add quality profiles for S5 aluminum CURA-5656 --- ...s5_aa0.4_aluminum_ABS_Draft_Print.inst.cfg | 36 ++++++++++ ..._s5_aa0.4_aluminum_ABS_Fast_Print.inst.cfg | 35 ++++++++++ ...5_aa0.4_aluminum_ABS_High_Quality.inst.cfg | 10 +-- ...aa0.4_aluminum_ABS_Normal_Quality.inst.cfg | 34 +++++++++ ...5_aa0.4_aluminum_CPEP_Draft_Print.inst.cfg | 54 +++++++++++++++ ...s5_aa0.4_aluminum_CPEP_Fast_Print.inst.cfg | 52 ++++++++++++++ ..._aa0.4_aluminum_CPEP_High_Quality.inst.cfg | 12 ++-- ...a0.4_aluminum_CPEP_Normal_Quality.inst.cfg | 54 +++++++++++++++ ...s5_aa0.4_aluminum_CPE_Draft_Print.inst.cfg | 35 ++++++++++ ..._s5_aa0.4_aluminum_CPE_Fast_Print.inst.cfg | 33 +++++++++ ...5_aa0.4_aluminum_CPE_High_Quality.inst.cfg | 14 ++-- ...aa0.4_aluminum_CPE_Normal_Quality.inst.cfg | 32 +++++++++ ..._s5_aa0.4_aluminum_PC_Draft_Print.inst.cfg | 69 +++++++++++++++++++ ...m_s5_aa0.4_aluminum_PC_Fast_Print.inst.cfg | 69 +++++++++++++++++++ ...s5_aa0.4_aluminum_PC_High_Quality.inst.cfg | 15 ++-- ..._aa0.4_aluminum_PC_Normal_Quality.inst.cfg | 68 ++++++++++++++++++ ..._s5_aa0.4_aluminum_PP_Draft_Print.inst.cfg | 65 +++++++++++++++++ ...m_s5_aa0.4_aluminum_PP_Fast_Print.inst.cfg | 67 ++++++++++++++++++ ..._aa0.4_aluminum_PP_Normal_Quality.inst.cfg | 68 ++++++++++++++++++ ...s5_aa0.8_aluminum_ABS_Draft_Print.inst.cfg | 9 +-- ...0.8_aluminum_ABS_Superdraft_Print.inst.cfg | 28 ++++++++ ...a0.8_aluminum_ABS_Verydraft_Print.inst.cfg | 28 ++++++++ ...s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg | 11 +-- ....8_aluminum_CPEP_Superdraft_Print.inst.cfg | 44 ++++++++++++ ...0.8_aluminum_CPEP_Verydraft_Print.inst.cfg | 44 ++++++++++++ ...s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg | 12 ++-- ...0.8_aluminum_CPE_Superdraft_Print.inst.cfg | 32 +++++++++ ...a0.8_aluminum_CPE_Verydraft_Print.inst.cfg | 31 +++++++++ ...m_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg | 11 +-- ...a0.8_aluminum_PC_Superdraft_Print.inst.cfg | 36 ++++++++++ ...aa0.8_aluminum_PC_Verydraft_Print.inst.cfg | 38 ++++++++++ ..._s5_aa0.8_aluminum_PP_Draft_Print.inst.cfg | 6 +- ...a0.8_aluminum_PP_Superdraft_Print.inst.cfg | 56 +++++++++++++++ ...aa0.8_aluminum_PP_Verydraft_Print.inst.cfg | 54 +++++++++++++++ 34 files changed, 1217 insertions(+), 45 deletions(-) create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_Draft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_Fast_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_Normal_Quality.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Draft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Fast_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Normal_Quality.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Draft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Fast_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Normal_Quality.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_Draft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_Fast_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_Normal_Quality.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PP_Draft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PP_Fast_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PP_Normal_Quality.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Superdraft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Verydraft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Superdraft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Verydraft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Superdraft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Verydraft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Superdraft_Print.inst.cfg create mode 100644 resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Verydraft_Print.inst.cfg diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_Draft_Print.inst.cfg new file mode 100644 index 0000000000..c8d64f9dcb --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_Draft_Print.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Fast +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = draft +weight = -2 +material = generic_abs +variant = AA 0.4 +buildplate = Aluminum + +[values] +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_print_temperature = =default_material_print_temperature + 20 +material_initial_print_temperature = =material_print_temperature - 15 +material_final_print_temperature = =material_print_temperature - 20 +prime_tower_enable = False +skin_overlap = 20 +speed_print = 60 +speed_layer_0 = 20 +speed_topbottom = =math.ceil(speed_print * 35 / 60) +speed_wall = =math.ceil(speed_print * 45 / 60) +speed_wall_0 = =math.ceil(speed_wall * 35 / 45) +wall_thickness = 1 + +infill_line_width = =round(line_width * 0.4 / 0.35, 2) +speed_infill = =math.ceil(speed_print * 50 / 60) + +material_bed_temperature_layer_0 = 100 +default_material_bed_temperature = 90 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_Fast_Print.inst.cfg new file mode 100644 index 0000000000..c7fa604e89 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_Fast_Print.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Normal +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = fast +weight = -1 +material = generic_abs +variant = AA 0.4 +buildplate = Aluminum + +[values] +cool_min_speed = 7 +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_print_temperature = =default_material_print_temperature + 15 +material_initial_print_temperature = =material_print_temperature - 15 +material_final_print_temperature = =material_print_temperature - 20 +prime_tower_enable = False +speed_print = 60 +speed_layer_0 = 20 +speed_topbottom = =math.ceil(speed_print * 30 / 60) +speed_wall = =math.ceil(speed_print * 40 / 60) +speed_wall_0 = =math.ceil(speed_wall * 30 / 40) + +infill_line_width = =round(line_width * 0.4 / 0.35, 2) +speed_infill = =math.ceil(speed_print * 45 / 60) + +material_bed_temperature_layer_0 = 100 +default_material_bed_temperature = 90 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_High_Quality.inst.cfg index 9a3eef5762..187023d3c0 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_High_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_High_Quality.inst.cfg @@ -14,21 +14,21 @@ buildplate = Aluminum [values] cool_min_speed = 12 -layer_height_0 = 0.17 machine_nozzle_cool_down_speed = 0.8 machine_nozzle_heat_up_speed = 1.5 -material_bed_temperature = 90 -material_bed_temperature_layer_0 = 100 material_print_temperature = =default_material_print_temperature + 5 material_initial_print_temperature = =material_print_temperature - 15 material_final_print_temperature = =material_print_temperature - 20 -prime_blob_enable = False prime_tower_enable = False speed_print = 50 -speed_layer_0 = =math.ceil(speed_print * 20 / 50) +speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 50) speed_wall = =math.ceil(speed_print * 30 / 50) infill_line_width = =round(line_width * 0.4 / 0.35, 2) speed_infill = =math.ceil(speed_print * 40 / 50) +material_bed_temperature_layer_0 = 100 +default_material_bed_temperature = 90 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_Normal_Quality.inst.cfg new file mode 100644 index 0000000000..81cb27f060 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_ABS_Normal_Quality.inst.cfg @@ -0,0 +1,34 @@ +[general] +version = 4 +name = Fine +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = normal +weight = 0 +material = generic_abs +variant = AA 0.4 +buildplate = Aluminum + +[values] +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_print_temperature = =default_material_print_temperature + 10 +material_initial_print_temperature = =material_print_temperature - 15 +material_final_print_temperature = =material_print_temperature - 20 +prime_tower_enable = False +speed_print = 55 +speed_layer_0 = 20 +speed_topbottom = =math.ceil(speed_print * 30 / 55) +speed_wall = =math.ceil(speed_print * 30 / 55) + +infill_line_width = =round(line_width * 0.4 / 0.35, 2) +speed_infill = =math.ceil(speed_print * 40 / 55) + +material_bed_temperature_layer_0 = 100 +default_material_bed_temperature = 90 +prime_blob_enable = False +layer_height_0 = 0.17 + diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Draft_Print.inst.cfg new file mode 100644 index 0000000000..46e3483a6a --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Draft_Print.inst.cfg @@ -0,0 +1,54 @@ +[general] +version = 4 +name = Fast +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = draft +weight = -2 +material = generic_cpe_plus +variant = AA 0.4 +buildplate = Aluminum + +[values] +acceleration_enabled = True +acceleration_print = 4000 +cool_fan_speed_max = 80 +cool_min_speed = 5 +infill_line_width = =round(line_width * 0.35 / 0.35, 2) +infill_overlap = 0 +infill_wipe_dist = 0 +jerk_enabled = True +jerk_print = 25 +machine_min_cool_heat_time_window = 15 +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_print_temperature = =default_material_print_temperature + 10 +material_print_temperature_layer_0 = =material_print_temperature +multiple_mesh_overlap = 0 +prime_tower_enable = True +prime_tower_wipe_enabled = True +retraction_combing = off +retraction_extrusion_window = 1 +retraction_hop = 0.2 +retraction_hop_enabled = False +retraction_hop_only_when_collides = True +skin_overlap = 20 +speed_layer_0 = 20 +speed_print = 50 +speed_topbottom = =math.ceil(speed_print * 40 / 50) + +speed_wall = =math.ceil(speed_print * 50 / 50) +speed_wall_0 = =math.ceil(speed_wall * 40 / 50) +support_bottom_distance = =support_z_distance +support_z_distance = =layer_height +wall_0_inset = 0 +wall_thickness = 1 + +material_bed_temperature_layer_0 = 115 +default_material_bed_temperature = 105 +prime_blob_enable = False +layer_height_0 = 0.17 + diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Fast_Print.inst.cfg new file mode 100644 index 0000000000..5c235b656a --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Fast_Print.inst.cfg @@ -0,0 +1,52 @@ +[general] +version = 4 +name = Normal +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = fast +weight = -1 +material = generic_cpe_plus +variant = AA 0.4 +buildplate = Aluminum + +[values] +acceleration_enabled = True +acceleration_print = 4000 +cool_fan_speed_max = 80 +cool_min_speed = 6 +infill_line_width = =round(line_width * 0.35 / 0.35, 2) +infill_overlap = 0 +infill_wipe_dist = 0 +jerk_enabled = True +jerk_print = 25 +machine_min_cool_heat_time_window = 15 +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_print_temperature = =default_material_print_temperature + 10 +material_print_temperature_layer_0 = =material_print_temperature +multiple_mesh_overlap = 0 +prime_tower_enable = True +prime_tower_wipe_enabled = True +retraction_combing = off +retraction_extrusion_window = 1 +retraction_hop = 0.2 +retraction_hop_enabled = False +retraction_hop_only_when_collides = True +skin_overlap = 20 +speed_layer_0 = 20 +speed_print = 45 +speed_topbottom = =math.ceil(speed_print * 35 / 45) + +speed_wall = =math.ceil(speed_print * 45 / 45) +speed_wall_0 = =math.ceil(speed_wall * 35 / 45) +support_bottom_distance = =support_z_distance +support_z_distance = =layer_height +wall_0_inset = 0 + +material_bed_temperature_layer_0 = 115 +default_material_bed_temperature = 105 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_High_Quality.inst.cfg index 8b0b08f731..326a730fe4 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_High_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_High_Quality.inst.cfg @@ -22,18 +22,14 @@ infill_overlap = 0 infill_wipe_dist = 0 jerk_enabled = True jerk_print = 25 -layer_height_0 = 0.17 machine_min_cool_heat_time_window = 15 machine_nozzle_cool_down_speed = 0.85 machine_nozzle_heat_up_speed = 1.5 -material_bed_temperature = 105 -material_bed_temperature_layer_0 = 115 material_final_print_temperature = =material_print_temperature - 10 material_initial_print_temperature = =material_print_temperature - 5 material_print_temperature = =default_material_print_temperature + 2 material_print_temperature_layer_0 = =material_print_temperature multiple_mesh_overlap = 0 -prime_blob_enable = False prime_tower_enable = True prime_tower_wipe_enabled = True retraction_combing = off @@ -42,7 +38,7 @@ retraction_hop = 0.2 retraction_hop_enabled = False retraction_hop_only_when_collides = True skin_overlap = 20 -speed_layer_0 = =math.ceil(speed_print * 20 / 40) +speed_layer_0 = 20 speed_print = 40 speed_topbottom = =math.ceil(speed_print * 30 / 35) @@ -51,3 +47,9 @@ speed_wall_0 = =math.ceil(speed_wall * 30 / 35) support_bottom_distance = =support_z_distance support_z_distance = =layer_height wall_0_inset = 0 + +material_bed_temperature_layer_0 = 115 +default_material_bed_temperature = 105 +prime_blob_enable = False +layer_height_0 = 0.17 + diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Normal_Quality.inst.cfg new file mode 100644 index 0000000000..d40b2db90e --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Normal_Quality.inst.cfg @@ -0,0 +1,54 @@ +[general] +version = 4 +name = Fine +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = normal +weight = 0 +material = generic_cpe_plus +variant = AA 0.4 +buildplate = Aluminum + +[values] +acceleration_enabled = True +acceleration_print = 4000 +cool_fan_speed_max = 50 +cool_min_speed = 7 +infill_line_width = =round(line_width * 0.35 / 0.35, 2) +infill_overlap = 0 +infill_wipe_dist = 0 +jerk_enabled = True +jerk_print = 25 +machine_min_cool_heat_time_window = 15 +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_print_temperature = =default_material_print_temperature + 5 +material_print_temperature_layer_0 = =material_print_temperature +multiple_mesh_overlap = 0 +prime_tower_enable = True +prime_tower_wipe_enabled = True +retraction_combing = off +retraction_extrusion_window = 1 +retraction_hop = 0.2 +retraction_hop_enabled = False +retraction_hop_only_when_collides = True +skin_overlap = 20 +speed_layer_0 = 20 +speed_print = 40 +speed_topbottom = =math.ceil(speed_print * 30 / 35) + +speed_wall = =math.ceil(speed_print * 35 / 40) +speed_wall_0 = =math.ceil(speed_wall * 30 / 35) +support_bottom_distance = =support_z_distance +support_z_distance = =layer_height +wall_0_inset = 0 + +material_bed_temperature_layer_0 = 115 +default_material_bed_temperature = 105 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Draft_Print.inst.cfg new file mode 100644 index 0000000000..c812066e0c --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Draft_Print.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Fast +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = draft +weight = -2 +material = generic_cpe +variant = AA 0.4 +buildplate = Aluminum + +[values] +material_print_temperature = =default_material_print_temperature + 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_final_print_temperature = =material_print_temperature - 10 +skin_overlap = 20 +speed_print = 60 +speed_layer_0 = 20 +speed_topbottom = =math.ceil(speed_print * 35 / 60) +speed_wall = =math.ceil(speed_print * 45 / 60) +speed_wall_0 = =math.ceil(speed_wall * 35 / 45) +wall_thickness = 1 + + +infill_pattern = zigzag +speed_infill = =math.ceil(speed_print * 50 / 60) +prime_tower_purge_volume = 1 + +material_bed_temperature_layer_0 = 90 +default_material_bed_temperature = 80 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Fast_Print.inst.cfg new file mode 100644 index 0000000000..ef634316da --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Fast_Print.inst.cfg @@ -0,0 +1,33 @@ +[general] +version = 4 +name = Normal +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = fast +weight = -1 +material = generic_cpe +variant = AA 0.4 +buildplate = Aluminum + +[values] +cool_min_speed = 7 +material_print_temperature = =default_material_print_temperature + 5 +material_initial_print_temperature = =material_print_temperature - 5 +material_final_print_temperature = =material_print_temperature - 10 +speed_print = 60 +speed_layer_0 = 20 +speed_topbottom = =math.ceil(speed_print * 30 / 60) +speed_wall = =math.ceil(speed_print * 40 / 60) +speed_wall_0 = =math.ceil(speed_wall * 30 / 40) + +infill_pattern = zigzag +speed_infill = =math.ceil(speed_print * 50 / 60) +prime_tower_purge_volume = 1 + +material_bed_temperature_layer_0 = 90 +default_material_bed_temperature = 80 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_High_Quality.inst.cfg index 6299071194..cda97e6ab3 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_High_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_High_Quality.inst.cfg @@ -14,19 +14,21 @@ buildplate = Aluminum [values] cool_min_speed = 12 -layer_height_0 = 0.17 machine_nozzle_cool_down_speed = 0.85 machine_nozzle_heat_up_speed = 1.5 -material_bed_temperature = 80 -material_bed_temperature_layer_0 = 90 material_print_temperature = =default_material_print_temperature - 5 material_initial_print_temperature = =material_print_temperature - 5 material_final_print_temperature = =material_print_temperature - 10 -prime_blob_enable = False speed_print = 50 -speed_layer_0 = =math.ceil(speed_print * 20 / 50) +speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 50) speed_wall = =math.ceil(speed_print * 30 / 50) infill_pattern = zigzag -speed_infill = =math.ceil(speed_print * 40 / 50) \ No newline at end of file +speed_infill = =math.ceil(speed_print * 40 / 50) +prime_tower_purge_volume = 1 + +material_bed_temperature_layer_0 = 90 +default_material_bed_temperature = 80 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Normal_Quality.inst.cfg new file mode 100644 index 0000000000..5a75f3b6e3 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Normal_Quality.inst.cfg @@ -0,0 +1,32 @@ +[general] +version = 4 +name = Fine +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = normal +weight = 0 +material = generic_cpe +variant = AA 0.4 +buildplate = Aluminum + +[values] +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_initial_print_temperature = =material_print_temperature - 5 +material_final_print_temperature = =material_print_temperature - 10 +speed_print = 55 +speed_layer_0 = 20 +speed_topbottom = =math.ceil(speed_print * 30 / 55) +speed_wall = =math.ceil(speed_print * 30 / 55) + +infill_pattern = zigzag +speed_infill = =math.ceil(speed_print * 45 / 55) +prime_tower_purge_volume = 1 + +material_bed_temperature_layer_0 = 90 +default_material_bed_temperature = 80 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_Draft_Print.inst.cfg new file mode 100644 index 0000000000..f05ecddc25 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_Draft_Print.inst.cfg @@ -0,0 +1,69 @@ +[general] +version = 4 +name = Fast +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = draft +weight = -2 +material = generic_pc +variant = AA 0.4 +buildplate = Aluminum + +[values] +acceleration_enabled = True +acceleration_print = 4000 +adhesion_type = brim +brim_width = 20 +cool_fan_full_at_height = =layer_height_0 + layer_height +cool_fan_speed_max = 90 +cool_min_layer_time_fan_speed_max = 5 +cool_min_speed = 6 +infill_line_width = =round(line_width * 0.4 / 0.35, 2) +infill_overlap = 0 +infill_overlap_mm = 0.05 +infill_pattern = triangles +infill_wipe_dist = 0.1 +jerk_enabled = True +jerk_print = 25 +machine_min_cool_heat_time_window = 15 +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_print_temperature = =default_material_print_temperature + 10 +material_standby_temperature = 100 +multiple_mesh_overlap = 0 +ooze_shield_angle = 40 +prime_tower_enable = True +prime_tower_wipe_enabled = True +raft_airgap = 0.25 +raft_interface_thickness = =max(layer_height * 1.5, 0.225) +retraction_count_max = 80 +retraction_extrusion_window = 1 +retraction_hop = 2 +retraction_hop_only_when_collides = True +retraction_min_travel = 0.8 +retraction_prime_speed = 15 +skin_overlap = 30 +speed_layer_0 = 25 +speed_print = 50 +speed_topbottom = 25 +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 25 / 40) +support_bottom_distance = =support_z_distance +support_interface_density = 87.5 +support_interface_pattern = lines +switch_extruder_prime_speed = 15 +switch_extruder_retraction_amount = 20 +switch_extruder_retraction_speeds = 35 +wall_0_inset = 0 +wall_line_width_x = =round(line_width * 0.4 / 0.35, 2) +wall_thickness = 1.2 + +material_bed_temperature_layer_0 = 125 +default_material_bed_temperature = 115 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_Fast_Print.inst.cfg new file mode 100644 index 0000000000..6103519f1c --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_Fast_Print.inst.cfg @@ -0,0 +1,69 @@ +[general] +version = 4 +name = Normal +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = fast +weight = -1 +material = generic_pc +variant = AA 0.4 +buildplate = Aluminum + +[values] +acceleration_enabled = True +acceleration_print = 4000 +adhesion_type = brim +brim_width = 20 +cool_fan_full_at_height = =layer_height_0 + layer_height +cool_fan_speed_max = 85 +cool_min_layer_time_fan_speed_max = 5 +cool_min_speed = 7 +infill_line_width = =round(line_width * 0.4 / 0.35, 2) +infill_overlap_mm = 0.05 +infill_pattern = triangles +infill_wipe_dist = 0.1 +jerk_enabled = True +jerk_print = 25 +machine_min_cool_heat_time_window = 15 +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_print_temperature = =default_material_print_temperature + 10 +material_standby_temperature = 100 +multiple_mesh_overlap = 0 +ooze_shield_angle = 40 +prime_tower_enable = True +prime_tower_wipe_enabled = True +raft_airgap = 0.25 +raft_interface_thickness = =max(layer_height * 1.5, 0.225) +retraction_count_max = 80 +retraction_extrusion_window = 1 +retraction_hop = 2 +retraction_hop_only_when_collides = True +retraction_min_travel = 0.8 +retraction_prime_speed = 15 +skin_overlap = 30 +speed_layer_0 = 25 +speed_print = 50 +speed_topbottom = 25 + +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 25 / 40) +support_bottom_distance = =support_z_distance +support_interface_density = 87.5 +support_interface_pattern = lines +switch_extruder_prime_speed = 15 +switch_extruder_retraction_amount = 20 +switch_extruder_retraction_speeds = 35 +wall_0_inset = 0 +wall_line_width_x = =round(line_width * 0.4 / 0.35, 2) +wall_thickness = 1.2 + +material_bed_temperature_layer_0 = 125 +default_material_bed_temperature = 115 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_High_Quality.inst.cfg index 2afaf21de1..130afb8c91 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_High_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_High_Quality.inst.cfg @@ -16,7 +16,7 @@ buildplate = Aluminum acceleration_enabled = True acceleration_print = 4000 adhesion_type = brim -brim_width = 10 +brim_width = 20 cool_fan_full_at_height = =layer_height_0 + layer_height cool_fan_speed_max = 50 cool_min_layer_time_fan_speed_max = 5 @@ -28,19 +28,15 @@ infill_pattern = triangles infill_wipe_dist = 0.1 jerk_enabled = True jerk_print = 25 -layer_height_0 = 0.17 machine_min_cool_heat_time_window = 15 machine_nozzle_cool_down_speed = 0.85 machine_nozzle_heat_up_speed = 1.5 -material_bed_temperature = 115 -material_bed_temperature_layer_0 = 125 material_final_print_temperature = =material_print_temperature - 10 material_initial_print_temperature = =material_print_temperature - 5 material_print_temperature = =default_material_print_temperature - 10 material_standby_temperature = 100 multiple_mesh_overlap = 0 ooze_shield_angle = 40 -prime_blob_enable = False prime_tower_enable = True prime_tower_wipe_enabled = True raft_airgap = 0.25 @@ -52,9 +48,9 @@ retraction_hop_only_when_collides = True retraction_min_travel = 0.8 retraction_prime_speed = 15 skin_overlap = 30 -speed_layer_0 = =math.ceil(speed_print * 25 / 50) +speed_layer_0 = 25 speed_print = 50 -speed_topbottom = =math.ceil(speed_print * 25 / 50) +speed_topbottom = 25 speed_wall = =math.ceil(speed_print * 40 / 50) speed_wall_0 = =math.ceil(speed_wall * 25 / 40) @@ -68,4 +64,7 @@ wall_0_inset = 0 wall_line_width_x = =round(line_width * 0.4 / 0.35, 2) wall_thickness = 1.2 - +material_bed_temperature_layer_0 = 125 +default_material_bed_temperature = 115 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_Normal_Quality.inst.cfg new file mode 100644 index 0000000000..9e1bf394d4 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PC_Normal_Quality.inst.cfg @@ -0,0 +1,68 @@ +[general] +version = 4 +name = Fine +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = normal +weight = 0 +material = generic_pc +variant = AA 0.4 +buildplate = Aluminum + +[values] +acceleration_enabled = True +acceleration_print = 4000 +adhesion_type = brim +brim_width = 20 +cool_fan_full_at_height = =layer_height_0 + layer_height +cool_fan_speed_max = 50 +cool_min_layer_time_fan_speed_max = 5 +cool_min_speed = 5 +infill_line_width = =round(line_width * 0.4 / 0.35, 2) +infill_overlap = 0 +infill_pattern = triangles +infill_wipe_dist = 0.1 +jerk_enabled = True +jerk_print = 25 +machine_min_cool_heat_time_window = 15 +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_standby_temperature = 100 +multiple_mesh_overlap = 0 +ooze_shield_angle = 40 +prime_tower_enable = True +prime_tower_wipe_enabled = True +raft_airgap = 0.25 +raft_interface_thickness = =max(layer_height * 1.5, 0.225) +retraction_count_max = 80 +retraction_extrusion_window = 1 +retraction_hop = 2 +retraction_hop_only_when_collides = True +retraction_min_travel = 0.8 +retraction_prime_speed = 15 +skin_overlap = 30 +speed_layer_0 = 25 +speed_print = 50 +speed_topbottom = 25 + +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 25 / 40) +support_bottom_distance = =support_z_distance +support_interface_density = 87.5 +support_interface_pattern = lines +switch_extruder_prime_speed = 15 +switch_extruder_retraction_amount = 20 +switch_extruder_retraction_speeds = 35 +wall_0_inset = 0 +wall_line_width_x = =round(line_width * 0.4 / 0.35, 2) +wall_thickness = 1.2 + +material_bed_temperature_layer_0 = 125 +default_material_bed_temperature = 115 +prime_blob_enable = False +layer_height_0 = 0.17 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PP_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PP_Draft_Print.inst.cfg new file mode 100644 index 0000000000..6124dff257 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PP_Draft_Print.inst.cfg @@ -0,0 +1,65 @@ +[general] +version = 4 +name = Fast +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = draft +weight = -2 +material = generic_pp +variant = AA 0.4 +buildplate = Aluminum + +[values] +acceleration_enabled = True +acceleration_print = 4000 +brim_width = 20 +cool_fan_speed_max = 100 +cool_min_layer_time = 7 +cool_min_layer_time_fan_speed_max = 7 +cool_min_speed = 2.5 +infill_line_width = =round(line_width * 0.38 / 0.38, 2) +infill_overlap = 0 +infill_pattern = tetrahedral +infill_wipe_dist = 0.1 +jerk_enabled = True +jerk_print = 25 +line_width = =machine_nozzle_size * 0.95 +machine_min_cool_heat_time_window = 15 +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_bed_temperature_layer_0 = =material_bed_temperature +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_print_temperature = =default_material_print_temperature - 5 +material_print_temperature_layer_0 = =material_print_temperature + 5 +material_standby_temperature = 100 +multiple_mesh_overlap = 0 +prime_tower_enable = False +prime_tower_size = 16 +prime_tower_wipe_enabled = True +retraction_count_max = 12 +retraction_extra_prime_amount = 0.8 +retraction_extrusion_window = 1 +retraction_hop = 2 +retraction_hop_only_when_collides = True +retraction_min_travel = 0.8 +retraction_prime_speed = 18 +speed_equalize_flow_enabled = True +speed_layer_0 = 15 +speed_print = 25 +speed_topbottom = =math.ceil(speed_print * 25 / 25) +speed_travel_layer_0 = 50 +speed_wall = =math.ceil(speed_print * 25 / 25) +speed_wall_0 = =math.ceil(speed_wall * 25 / 25) +support_angle = 50 +switch_extruder_prime_speed = 15 +switch_extruder_retraction_amount = 20 +switch_extruder_retraction_speeds = 35 +wall_0_inset = 0 +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 + +default_material_bed_temperature = 95 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PP_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PP_Fast_Print.inst.cfg new file mode 100644 index 0000000000..2791e9f5d5 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PP_Fast_Print.inst.cfg @@ -0,0 +1,67 @@ +[general] +version = 4 +name = Normal +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = fast +weight = -1 +material = generic_pp +variant = AA 0.4 +buildplate = Aluminum + +[values] +acceleration_enabled = True +acceleration_print = 4000 +brim_width = 20 +cool_fan_speed_max = 100 +cool_min_layer_time = 7 +cool_min_layer_time_fan_speed_max = 7 +cool_min_speed = 2.5 +infill_line_width = =round(line_width * 0.38 / 0.38, 2) +infill_overlap = 0 +infill_pattern = tetrahedral +infill_wipe_dist = 0.1 +jerk_enabled = True +jerk_print = 25 +line_width = =machine_nozzle_size * 0.95 +machine_min_cool_heat_time_window = 15 +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_bed_temperature_layer_0 = =material_bed_temperature +material_final_print_temperature = =material_print_temperature - 12 +material_initial_print_temperature = =material_print_temperature - 2 +material_print_temperature = =default_material_print_temperature - 13 +material_print_temperature_layer_0 = =material_print_temperature + 3 +material_standby_temperature = 100 +multiple_mesh_overlap = 0 +prime_tower_enable = False +prime_tower_size = 16 +prime_tower_wipe_enabled = True +retraction_count_max = 12 +retraction_extra_prime_amount = 0.8 +retraction_extrusion_window = 1 +retraction_hop = 2 +retraction_hop_only_when_collides = True +retraction_min_travel = 0.8 +retraction_prime_speed = 18 +speed_equalize_flow_enabled = True +speed_layer_0 = 15 +speed_print = 25 +speed_topbottom = =math.ceil(speed_print * 25 / 25) + +speed_travel_layer_0 = 50 +speed_wall = =math.ceil(speed_print * 25 / 25) +speed_wall_0 = =math.ceil(speed_wall * 25 / 25) +support_angle = 50 +switch_extruder_prime_speed = 15 +switch_extruder_retraction_amount = 20 +switch_extruder_retraction_speeds = 35 +top_bottom_thickness = 1.1 +wall_0_inset = 0 +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 + +default_material_bed_temperature = 95 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PP_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PP_Normal_Quality.inst.cfg new file mode 100644 index 0000000000..f78b4048fb --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_PP_Normal_Quality.inst.cfg @@ -0,0 +1,68 @@ +[general] +version = 4 +name = Fine +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = normal +weight = 0 +material = generic_pp +variant = AA 0.4 +buildplate = Aluminum + +[values] +acceleration_enabled = True +acceleration_print = 4000 +brim_width = 20 +cool_fan_speed_max = 100 +cool_min_layer_time = 7 +cool_min_layer_time_fan_speed_max = 7 +cool_min_speed = 2.5 +infill_line_width = =round(line_width * 0.38 / 0.38, 2) +infill_overlap = 0 +infill_pattern = tetrahedral +infill_wipe_dist = 0.1 +jerk_enabled = True +jerk_print = 25 +line_width = =machine_nozzle_size * 0.95 +machine_min_cool_heat_time_window = 15 +machine_nozzle_cool_down_speed = 0.85 +machine_nozzle_heat_up_speed = 1.5 +material_bed_temperature_layer_0 = =material_bed_temperature +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_print_temperature = =default_material_print_temperature - 15 +material_print_temperature_layer_0 = =material_print_temperature + 3 +material_standby_temperature = 100 +multiple_mesh_overlap = 0 +prime_tower_enable = False +prime_tower_size = 16 +prime_tower_wipe_enabled = True +retraction_count_max = 12 +retraction_extra_prime_amount = 0.8 +retraction_extrusion_window = 1 +retraction_hop = 2 +retraction_hop_only_when_collides = True +retraction_min_travel = 0.8 +retraction_prime_speed = 18 +speed_equalize_flow_enabled = True +speed_layer_0 = 15 +speed_print = 25 +speed_topbottom = =math.ceil(speed_print * 25 / 25) + +speed_travel_layer_0 = 50 +speed_wall = =math.ceil(speed_print * 25 / 25) +speed_wall_0 = =math.ceil(speed_wall * 25 / 25) +support_angle = 50 +switch_extruder_prime_speed = 15 +switch_extruder_retraction_amount = 20 +switch_extruder_retraction_speeds = 35 +top_bottom_thickness = 1 +wall_0_inset = 0 +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 + +default_material_bed_temperature = 95 + diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Draft_Print.inst.cfg index 3d984e1dff..37dceff349 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Draft_Print.inst.cfg @@ -13,15 +13,16 @@ variant = AA 0.8 buildplate = Aluminum [values] -layer_height_0 = 0.3 line_width = =machine_nozzle_size * 0.875 -material_bed_temperature = 90 -material_bed_temperature_layer_0 = 100 material_print_temperature = =default_material_print_temperature + 20 material_standby_temperature = 100 -prime_blob_enable = False speed_print = 50 speed_topbottom = =math.ceil(speed_print * 30 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) speed_wall_0 = =math.ceil(speed_wall * 30 / 40) retract_at_layer_change = False + +material_bed_temperature_layer_0 = 100 +default_material_bed_temperature = 90 +prime_blob_enable = False +layer_height_0 = 0.3 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Superdraft_Print.inst.cfg new file mode 100644 index 0000000000..eac339baa8 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Superdraft_Print.inst.cfg @@ -0,0 +1,28 @@ +[general] +version = 4 +name = Sprint +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = superdraft +weight = -4 +material = generic_abs +variant = AA 0.8 +buildplate = Aluminum + +[values] +line_width = =machine_nozzle_size * 0.875 +material_print_temperature = =default_material_print_temperature + 25 +material_standby_temperature = 100 +speed_print = 50 +speed_topbottom = =math.ceil(speed_print * 30 / 50) +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 30 / 40) +retract_at_layer_change = False + +material_bed_temperature_layer_0 = 100 +default_material_bed_temperature = 90 +prime_blob_enable = False +layer_height_0 = 0.3 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Verydraft_Print.inst.cfg new file mode 100644 index 0000000000..590496df0f --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_ABS_Verydraft_Print.inst.cfg @@ -0,0 +1,28 @@ +[general] +version = 4 +name = Extra Fast +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = verydraft +weight = -3 +material = generic_abs +variant = AA 0.8 +buildplate = Aluminum + +[values] +line_width = =machine_nozzle_size * 0.875 +material_print_temperature = =default_material_print_temperature + 22 +material_standby_temperature = 100 +speed_print = 50 +speed_topbottom = =math.ceil(speed_print * 30 / 50) +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 30 / 40) +retract_at_layer_change = False + +material_bed_temperature_layer_0 = 100 +default_material_bed_temperature = 90 +prime_blob_enable = False +layer_height_0 = 0.3 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg index 6fd60c197a..3e74390840 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg @@ -16,22 +16,18 @@ buildplate = Aluminum brim_width = 14 cool_fan_full_at_height = =layer_height_0 + 14 * layer_height infill_before_walls = True -layer_height_0 = 0.3 line_width = =machine_nozzle_size * 0.9375 machine_nozzle_cool_down_speed = 0.9 machine_nozzle_heat_up_speed = 1.4 -material_bed_temperature = 105 -material_bed_temperature_layer_0 = 115 material_print_temperature = =default_material_print_temperature - 10 material_print_temperature_layer_0 = =material_print_temperature material_standby_temperature = 100 -prime_blob_enable = False prime_tower_enable = True retraction_combing = off retraction_hop = 0.1 retraction_hop_enabled = False skin_overlap = 0 -speed_layer_0 = =math.ceil(speed_print * 15 / 50) +speed_layer_0 = 15 speed_print = 50 speed_slowdown_layers = 15 speed_topbottom = =math.ceil(speed_print * 35 / 50) @@ -41,3 +37,8 @@ support_bottom_distance = =support_z_distance support_line_width = =round(line_width * 0.6 / 0.7, 2) support_z_distance = =layer_height top_bottom_thickness = 1.2 + +material_bed_temperature_layer_0 = 115 +default_material_bed_temperature = 105 +prime_blob_enable = False +layer_height_0 = 0.3 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg new file mode 100644 index 0000000000..dc32bee180 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg @@ -0,0 +1,44 @@ +[general] +version = 4 +name = Sprint - Experimental +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = superdraft +weight = -4 +material = generic_cpe_plus +variant = AA 0.8 +buildplate = Aluminum + +[values] +brim_width = 14 +cool_fan_full_at_height = =layer_height_0 + 7 * layer_height +infill_before_walls = True +line_width = =machine_nozzle_size * 0.9375 +machine_nozzle_cool_down_speed = 0.9 +machine_nozzle_heat_up_speed = 1.4 +material_print_temperature = =default_material_print_temperature - 5 +material_print_temperature_layer_0 = =material_print_temperature +material_standby_temperature = 100 +prime_tower_enable = True +retraction_combing = off +retraction_hop = 0.1 +retraction_hop_enabled = False +skin_overlap = 0 +speed_layer_0 = 15 +speed_print = 50 +speed_slowdown_layers = 8 +speed_topbottom = =math.ceil(speed_print * 35 / 50) +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 35 / 40) +support_bottom_distance = =support_z_distance +support_line_width = =round(line_width * 0.6 / 0.7, 2) +support_z_distance = =layer_height +top_bottom_thickness = 1.2 + +material_bed_temperature_layer_0 = 115 +default_material_bed_temperature = 105 +prime_blob_enable = False +layer_height_0 = 0.3 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg new file mode 100644 index 0000000000..e8bc10aff7 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg @@ -0,0 +1,44 @@ +[general] +version = 4 +name = Extra Fast - Experimental +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = verydraft +weight = -3 +material = generic_cpe_plus +variant = AA 0.8 +buildplate = Aluminum + +[values] +brim_width = 14 +cool_fan_full_at_height = =layer_height_0 + 9 * layer_height +infill_before_walls = True +line_width = =machine_nozzle_size * 0.9375 +machine_nozzle_cool_down_speed = 0.9 +machine_nozzle_heat_up_speed = 1.4 +material_print_temperature = =default_material_print_temperature - 7 +material_print_temperature_layer_0 = =material_print_temperature +material_standby_temperature = 100 +prime_tower_enable = True +retraction_combing = off +retraction_hop = 0.1 +retraction_hop_enabled = False +skin_overlap = 0 +speed_layer_0 = 15 +speed_print = 50 +speed_slowdown_layers = 10 +speed_topbottom = =math.ceil(speed_print * 35 / 50) +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 35 / 40) +support_bottom_distance = =support_z_distance +support_line_width = =round(line_width * 0.6 / 0.7, 2) +support_z_distance = =layer_height +top_bottom_thickness = 1.2 + +material_bed_temperature_layer_0 = 115 +default_material_bed_temperature = 105 +prime_blob_enable = False +layer_height_0 = 0.3 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg index 37aa25f9d8..80c0585061 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg @@ -14,16 +14,18 @@ buildplate = Aluminum [values] brim_width = 15 -layer_height_0 = 0.3 line_width = =machine_nozzle_size * 0.875 -material_bed_temperature = 80 -material_bed_temperature_layer_0 = 90 material_print_temperature = =default_material_print_temperature + 15 material_standby_temperature = 100 -prime_blob_enable = False prime_tower_enable = True speed_print = 40 speed_topbottom = =math.ceil(speed_print * 25 / 40) speed_wall = =math.ceil(speed_print * 30 / 40) -jerk_travel = 50 \ No newline at end of file +jerk_travel = 50 +prime_tower_purge_volume = 1 + +material_bed_temperature_layer_0 = 90 +default_material_bed_temperature = 80 +prime_blob_enable = False +layer_height_0 = 0.3 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Superdraft_Print.inst.cfg new file mode 100644 index 0000000000..5dcc454173 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Superdraft_Print.inst.cfg @@ -0,0 +1,32 @@ +[general] +version = 4 +name = Sprint +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = superdraft +weight = -4 +material = generic_cpe +variant = AA 0.8 +buildplate = Aluminum + +[values] +brim_width = 15 +line_width = =machine_nozzle_size * 0.875 +material_print_temperature = =default_material_print_temperature + 20 +material_standby_temperature = 100 +prime_tower_enable = True +speed_print = 45 +speed_topbottom = =math.ceil(speed_print * 30 / 45) +speed_wall = =math.ceil(speed_print * 40 / 45) +speed_wall_0 = =math.ceil(speed_wall * 30 / 40) + +jerk_travel = 50 +prime_tower_purge_volume = 1 + +material_bed_temperature_layer_0 = 90 +default_material_bed_temperature = 80 +prime_blob_enable = False +layer_height_0 = 0.3 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Verydraft_Print.inst.cfg new file mode 100644 index 0000000000..8423e109e8 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Verydraft_Print.inst.cfg @@ -0,0 +1,31 @@ +[general] +version = 4 +name = Extra Fast +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = verydraft +weight = -3 +material = generic_cpe +variant = AA 0.8 +buildplate = Aluminum + +[values] +brim_width = 15 +line_width = =machine_nozzle_size * 0.875 +material_print_temperature = =default_material_print_temperature + 17 +material_standby_temperature = 100 +prime_tower_enable = True +speed_print = 40 +speed_topbottom = =math.ceil(speed_print * 25 / 40) +speed_wall = =math.ceil(speed_print * 30 / 40) + +jerk_travel = 50 +prime_tower_purge_volume = 1 + +material_bed_temperature_layer_0 = 90 +default_material_bed_temperature = 80 +prime_blob_enable = False +layer_height_0 = 0.3 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg index 9ebf2ea151..747e2fe8a5 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg @@ -16,21 +16,22 @@ buildplate = Aluminum brim_width = 10 cool_fan_full_at_height = =layer_height_0 + 14 * layer_height infill_before_walls = True -layer_height_0 = 0.3 line_width = =machine_nozzle_size * 0.875 -material_bed_temperature = 115 -material_bed_temperature_layer_0 = 125 material_print_temperature = =default_material_print_temperature - 5 material_print_temperature_layer_0 = =material_print_temperature material_standby_temperature = 100 -prime_blob_enable = False raft_airgap = 0.5 raft_margin = 15 skin_overlap = 0 -speed_layer_0 = =math.ceil(speed_print * 15 / 50) +speed_layer_0 = 15 speed_print = 50 speed_slowdown_layers = 15 speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) speed_wall_0 = =math.ceil(speed_wall * 30 / 40) support_line_width = =round(line_width * 0.6 / 0.7, 2) + +material_bed_temperature_layer_0 = 125 +default_material_bed_temperature = 115 +prime_blob_enable = False +layer_height_0 = 0.3 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Superdraft_Print.inst.cfg new file mode 100644 index 0000000000..e46914c7b0 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Superdraft_Print.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Sprint - Experimental +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = superdraft +weight = -2 +material = generic_pc +variant = AA 0.8 +buildplate = Aluminum + +[values] +brim_width = 10 +cool_fan_full_at_height = =layer_height_0 + 7 * layer_height +infill_before_walls = True +line_width = =machine_nozzle_size * 0.875 +material_print_temperature_layer_0 = =material_print_temperature +material_standby_temperature = 100 +raft_airgap = 0.5 +raft_margin = 15 +skin_overlap = 0 +speed_layer_0 = 15 +speed_print = 50 +speed_slowdown_layers = 8 +speed_topbottom = =math.ceil(speed_print * 25 / 50) +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 30 / 40) +support_line_width = =round(line_width * 0.6 / 0.7, 2) + +material_bed_temperature_layer_0 = 125 +default_material_bed_temperature = 115 +prime_blob_enable = False +layer_height_0 = 0.3 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Verydraft_Print.inst.cfg new file mode 100644 index 0000000000..a6dbc255eb --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Verydraft_Print.inst.cfg @@ -0,0 +1,38 @@ +[general] +version = 4 +name = Extra Fast - Experimental +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = verydraft +weight = -1 +material = generic_pc +variant = AA 0.8 +buildplate = Aluminum + +[values] +brim_width = 10 +cool_fan_full_at_height = =layer_height_0 + 9 * layer_height +infill_before_walls = True +line_width = =machine_nozzle_size * 0.875 +material_print_temperature = =default_material_print_temperature - 2 +material_print_temperature_layer_0 = =material_print_temperature +material_standby_temperature = 100 +raft_airgap = 0.5 +raft_margin = 15 +skin_overlap = 0 +speed_layer_0 = 15 +speed_print = 50 +speed_slowdown_layers = 10 +speed_topbottom = =math.ceil(speed_print * 25 / 50) +speed_wall = =math.ceil(speed_print * 40 / 50) +speed_wall_0 = =math.ceil(speed_wall * 30 / 40) +support_line_width = =round(line_width * 0.6 / 0.7, 2) + +material_bed_temperature_layer_0 = 125 +default_material_bed_temperature = 115 +prime_blob_enable = False +layer_height_0 = 0.3 + diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Draft_Print.inst.cfg index 94bede16bd..b80af1b75f 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Draft_Print.inst.cfg @@ -23,14 +23,14 @@ infill_pattern = tetrahedral jerk_prime_tower = =math.ceil(jerk_print * 25 / 25) jerk_support = =math.ceil(jerk_print * 25 / 25) jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) -material_bed_temperature_layer_0 = =material_bed_temperature + 5 +material_bed_temperature_layer_0 = =material_bed_temperature material_print_temperature = =default_material_print_temperature - 2 material_print_temperature_layer_0 = =default_material_print_temperature + 2 material_standby_temperature = 100 multiple_mesh_overlap = 0.2 prime_tower_enable = True prime_tower_flow = 100 -prime_tower_min_volume = 10 +prime_tower_wall_thickness = =prime_tower_line_width * 2 retract_at_layer_change = False retraction_count_max = 12 retraction_extra_prime_amount = 0.5 @@ -51,3 +51,5 @@ travel_compensate_overlapping_walls_0_enabled = False wall_0_wipe_dist = =line_width * 2 wall_line_width_x = =round(line_width * 0.8 / 0.8, 2) wall_thickness = 1.6 + +default_material_bed_temperature = 95 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Superdraft_Print.inst.cfg new file mode 100644 index 0000000000..970e0971a9 --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Superdraft_Print.inst.cfg @@ -0,0 +1,56 @@ +[general] +version = 4 +name = Sprint +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = superdraft +weight = -4 +material = generic_pp +variant = AA 0.8 +buildplate = Aluminum + +[values] +brim_width = 25 +cool_min_layer_time_fan_speed_max = 6 +cool_min_speed = 17 +top_skin_expand_distance = =line_width * 2 +infill_before_walls = True +infill_line_width = =round(line_width * 0.7 / 0.8, 2) +infill_pattern = tetrahedral +jerk_prime_tower = =math.ceil(jerk_print * 25 / 25) +jerk_support = =math.ceil(jerk_print * 25 / 25) +jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) +material_bed_temperature_layer_0 = =material_bed_temperature +material_print_temperature = =default_material_print_temperature + 2 +material_print_temperature_layer_0 = =default_material_print_temperature + 2 +material_standby_temperature = 100 +multiple_mesh_overlap = 0.2 +prime_tower_enable = True +prime_tower_flow = 100 +prime_tower_wall_thickness = =prime_tower_line_width * 2 +retract_at_layer_change = False +retraction_count_max = 12 +retraction_extra_prime_amount = 0.5 +retraction_hop = 0.5 +retraction_min_travel = 1.5 +retraction_prime_speed = 15 +skin_line_width = =round(line_width * 0.78 / 0.8, 2) + +speed_wall_x = =math.ceil(speed_wall * 30 / 30) +support_bottom_distance = =support_z_distance +support_line_width = =round(line_width * 0.7 / 0.8, 2) +support_offset = =line_width +switch_extruder_prime_speed = 15 +switch_extruder_retraction_amount = 20 +switch_extruder_retraction_speeds = 45 +top_bottom_thickness = 1.6 +travel_compensate_overlapping_walls_0_enabled = False +wall_0_wipe_dist = =line_width * 2 +wall_line_width_x = =round(line_width * 0.8 / 0.8, 2) +wall_thickness = 1.6 + +default_material_bed_temperature = 95 + diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Verydraft_Print.inst.cfg new file mode 100644 index 0000000000..e51ba3207b --- /dev/null +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PP_Verydraft_Print.inst.cfg @@ -0,0 +1,54 @@ +[general] +version = 4 +name = Extra Fast +definition = ultimaker_s5 + +[metadata] +setting_version = 5 +type = quality +quality_type = verydraft +weight = -3 +material = generic_pp +variant = AA 0.8 +buildplate = Aluminum + +[values] +brim_width = 25 +cool_min_layer_time_fan_speed_max = 6 +cool_min_speed = 17 +top_skin_expand_distance = =line_width * 2 +infill_before_walls = True +infill_line_width = =round(line_width * 0.7 / 0.8, 2) +infill_pattern = tetrahedral +jerk_prime_tower = =math.ceil(jerk_print * 25 / 25) +jerk_support = =math.ceil(jerk_print * 25 / 25) +jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) +material_bed_temperature_layer_0 = =material_bed_temperature +material_print_temperature_layer_0 = =default_material_print_temperature + 2 +material_standby_temperature = 100 +multiple_mesh_overlap = 0.2 +prime_tower_enable = True +prime_tower_flow = 100 +prime_tower_wall_thickness = =prime_tower_line_width * 2 +retract_at_layer_change = False +retraction_count_max = 12 +retraction_extra_prime_amount = 0.5 +retraction_hop = 0.5 +retraction_min_travel = 1.5 +retraction_prime_speed = 15 +skin_line_width = =round(line_width * 0.78 / 0.8, 2) + +speed_wall_x = =math.ceil(speed_wall * 30 / 30) +support_bottom_distance = =support_z_distance +support_line_width = =round(line_width * 0.7 / 0.8, 2) +support_offset = =line_width +switch_extruder_prime_speed = 15 +switch_extruder_retraction_amount = 20 +switch_extruder_retraction_speeds = 45 +top_bottom_thickness = 1.6 +travel_compensate_overlapping_walls_0_enabled = False +wall_0_wipe_dist = =line_width * 2 +wall_line_width_x = =round(line_width * 0.8 / 0.8, 2) +wall_thickness = 1.6 + +default_material_bed_temperature = 95 From 01cf9ee23bf4f669aa7c3a4a473f2f1a0383131f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 23 Aug 2018 13:12:10 +0200 Subject: [PATCH 209/243] Remove "Experimental" text --- .../um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg | 2 +- .../um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg | 2 +- .../um_s5_aa0.8_aluminum_PC_Superdraft_Print.inst.cfg | 2 +- .../um_s5_aa0.8_aluminum_PC_Verydraft_Print.inst.cfg | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg index dc32bee180..4c1b807430 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg @@ -1,6 +1,6 @@ [general] version = 4 -name = Sprint - Experimental +name = Sprint definition = ultimaker_s5 [metadata] diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg index e8bc10aff7..11aefc90cd 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg @@ -1,6 +1,6 @@ [general] version = 4 -name = Extra Fast - Experimental +name = Extra Fast definition = ultimaker_s5 [metadata] diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Superdraft_Print.inst.cfg index e46914c7b0..689652dc06 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Superdraft_Print.inst.cfg @@ -1,6 +1,6 @@ [general] version = 4 -name = Sprint - Experimental +name = Sprint definition = ultimaker_s5 [metadata] diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Verydraft_Print.inst.cfg index a6dbc255eb..0480ee5620 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Verydraft_Print.inst.cfg @@ -1,6 +1,6 @@ [general] version = 4 -name = Extra Fast - Experimental +name = Extra Fast definition = ultimaker_s5 [metadata] From 93645e6bfe1d2b1c330beade5db2906c46184396 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 24 Aug 2018 10:46:23 +0200 Subject: [PATCH 210/243] Reduce component sizes Contributes to CURA-5378 --- .../Materials/MaterialBrandSection.qml | 88 ++++++++++ .../Materials/MaterialTypeSection.qml | 97 +++++++++++ .../Preferences/Materials/MaterialsList.qml | 162 +----------------- 3 files changed, 186 insertions(+), 161 deletions(-) create mode 100644 resources/qml/Preferences/Materials/MaterialBrandSection.qml create mode 100644 resources/qml/Preferences/Materials/MaterialTypeSection.qml diff --git a/resources/qml/Preferences/Materials/MaterialBrandSection.qml b/resources/qml/Preferences/Materials/MaterialBrandSection.qml new file mode 100644 index 0000000000..0acd2aa1d5 --- /dev/null +++ b/resources/qml/Preferences/Materials/MaterialBrandSection.qml @@ -0,0 +1,88 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Rectangle +{ + id: brand_section + property var expanded: true + property var types_model: model.material_types + height: childrenRect.height + width: parent.width + Rectangle + { + id: brand_header_background + color: UM.Theme.getColor("favorites_header_bar") + anchors.fill: brand_header + } + Row + { + id: brand_header + width: parent.width + Label + { + id: brand_name + text: model.name + height: UM.Theme.getSize("favorites_row").height + width: parent.width - UM.Theme.getSize("favorites_button").width + verticalAlignment: Text.AlignVCenter + leftPadding: 4 + } + Button + { + text: "" + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: "black" + source: brand_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + } + } + MouseArea + { + anchors.fill: brand_header + onPressed: + { + brand_section.expanded = !brand_section.expanded + } + } + Column + { + anchors.top: brand_header.bottom + width: parent.width + anchors.left: parent.left + height: brand_section.expanded ? childrenRect.height : 0 + visible: brand_section.expanded + Repeater + { + model: types_model + delegate: MaterialTypeSection {} + } + } +} \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialTypeSection.qml b/resources/qml/Preferences/Materials/MaterialTypeSection.qml new file mode 100644 index 0000000000..ba4621f15e --- /dev/null +++ b/resources/qml/Preferences/Materials/MaterialTypeSection.qml @@ -0,0 +1,97 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Rectangle +{ + id: material_type_section + property var expanded: true + property var colors_model: model.colors + height: childrenRect.height + width: parent.width + Rectangle + { + id: material_type_header_background + color: UM.Theme.getColor("lining") + anchors.bottom: material_type_header.bottom + anchors.left: material_type_header.left + height: UM.Theme.getSize("default_lining").height + width: material_type_header.width + } + Row + { + id: material_type_header + width: parent.width - 8 + anchors + { + left: parent.left + leftMargin: 8 + } + Label + { + text: model.name + height: UM.Theme.getSize("favorites_row").height + width: parent.width - UM.Theme.getSize("favorites_button").width + id: material_type_name + verticalAlignment: Text.AlignVCenter + } + Button + { + text: "" + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: "black" + source: material_type_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + } + } + MouseArea + { + anchors.fill: material_type_header + onPressed: + { + material_type_section.expanded = !material_type_section.expanded + } + } + Column + { + height: material_type_section.expanded ? childrenRect.height : 0 + visible: material_type_section.expanded + width: parent.width + anchors.top: material_type_header.bottom + anchors.left: parent.left + Repeater + { + model: colors_model + delegate: MaterialSlot { + material: model + } + } + } +} \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml index 220ce0134d..c16b37170f 100644 --- a/resources/qml/Preferences/Materials/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -180,168 +180,8 @@ Item Repeater { id: brand_list - model: materialsModel - delegate: Rectangle - { - id: brand_section - property var expanded: true - property var types_model: model.material_types - height: childrenRect.height - width: parent.width - Rectangle - { - id: brand_header_background - color: UM.Theme.getColor("favorites_header_bar") - anchors.fill: brand_header - } - Row - { - id: brand_header - width: parent.width - Label - { - id: brand_name - text: model.name - height: UM.Theme.getSize("favorites_row").height - width: parent.width - UM.Theme.getSize("favorites_button").width - verticalAlignment: Text.AlignVCenter - leftPadding: 4 - } - Button - { - text: "" - implicitWidth: UM.Theme.getSize("favorites_button").width - implicitHeight: UM.Theme.getSize("favorites_button").height - UM.RecolorImage { - anchors - { - verticalCenter: parent.verticalCenter - horizontalCenter: parent.horizontalCenter - } - width: UM.Theme.getSize("standard_arrow").width - height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width - sourceSize.height: height - color: "black" - source: brand_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") - } - style: ButtonStyle - { - background: Rectangle - { - anchors.fill: parent - color: "transparent" - } - } - } - } - MouseArea - { - anchors.fill: brand_header - onPressed: - { - brand_section.expanded = !brand_section.expanded - } - } - Column - { - anchors.top: brand_header.bottom - width: parent.width - anchors.left: parent.left - height: brand_section.expanded ? childrenRect.height : 0 - visible: brand_section.expanded - Repeater - { - model: types_model - delegate: Rectangle - { - id: material_type_section - property var expanded: true - property var colors_model: model.colors - height: childrenRect.height - width: parent.width - Rectangle - { - id: material_type_header_background - color: UM.Theme.getColor("lining") - anchors.bottom: material_type_header.bottom - anchors.left: material_type_header.left - height: UM.Theme.getSize("default_lining").height - width: material_type_header.width - } - Row - { - id: material_type_header - width: parent.width - 8 - anchors - { - left: parent.left - leftMargin: 8 - } - Label - { - text: model.name - height: UM.Theme.getSize("favorites_row").height - width: parent.width - UM.Theme.getSize("favorites_button").width - id: material_type_name - verticalAlignment: Text.AlignVCenter - } - Button - { - text: "" - implicitWidth: UM.Theme.getSize("favorites_button").width - implicitHeight: UM.Theme.getSize("favorites_button").height - UM.RecolorImage { - anchors - { - verticalCenter: parent.verticalCenter - horizontalCenter: parent.horizontalCenter - } - width: UM.Theme.getSize("standard_arrow").width - height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width - sourceSize.height: height - color: "black" - source: material_type_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") - } - style: ButtonStyle - { - background: Rectangle - { - anchors.fill: parent - color: "transparent" - } - } - } - } - MouseArea - { - anchors.fill: material_type_header - onPressed: - { - material_type_section.expanded = !material_type_section.expanded - } - } - Column - { - height: material_type_section.expanded ? childrenRect.height : 0 - visible: material_type_section.expanded - width: parent.width - anchors.top: material_type_header.bottom - anchors.left: parent.left - Repeater - { - model: colors_model - delegate: MaterialSlot { - material: model - } - } - } - } - } - } - } + delegate: MaterialBrandSection {} } } } \ No newline at end of file From 61c635fbaf9545fb460950042622d4045f710ffa Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 23 Aug 2018 16:59:09 +0200 Subject: [PATCH 211/243] Mock application in unit tests --- tests/conftest.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index f2c709d8d8..77d215815a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,19 +3,21 @@ # The purpose of this class is to create fixtures or methods that can be shared among all tests. +import unittest.mock import pytest + from UM.Qt.QtApplication import QtApplication #QtApplication import is required, even though it isn't used. from cura.CuraApplication import CuraApplication from cura.MachineActionManager import MachineActionManager + + # Create a CuraApplication object that will be shared among all tests. It needs to be initialized. # Since we need to use it more that once, we create the application the first time and use its instance afterwards. @pytest.fixture() def application() -> CuraApplication: - application = CuraApplication.getInstance() - if application is None: - application = CuraApplication() - return application + app = unittest.mock.MagicMock() + return app # Returns a MachineActionManager instance. @pytest.fixture() From 13069a2f99f5d530c0f06e564daa99ceb358ad0b Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 24 Aug 2018 11:06:44 +0200 Subject: [PATCH 212/243] Some file renaming Contributes to CURA-5378 --- .../{MaterialBrandSection.qml => MaterialsBrandSection.qml} | 2 +- .../qml/Preferences/Materials/MaterialsDetailsPanel.qml | 2 +- resources/qml/Preferences/Materials/MaterialsList.qml | 6 +++--- .../Materials/{MaterialSlot.qml => MaterialsSlot.qml} | 0 .../{MaterialTypeSection.qml => MaterialsTypeSection.qml} | 2 +- .../Materials/{MaterialView.qml => MaterialsView.qml} | 0 6 files changed, 6 insertions(+), 6 deletions(-) rename resources/qml/Preferences/Materials/{MaterialBrandSection.qml => MaterialsBrandSection.qml} (98%) rename resources/qml/Preferences/Materials/{MaterialSlot.qml => MaterialsSlot.qml} (100%) rename resources/qml/Preferences/Materials/{MaterialTypeSection.qml => MaterialsTypeSection.qml} (98%) rename resources/qml/Preferences/Materials/{MaterialView.qml => MaterialsView.qml} (100%) diff --git a/resources/qml/Preferences/Materials/MaterialBrandSection.qml b/resources/qml/Preferences/Materials/MaterialsBrandSection.qml similarity index 98% rename from resources/qml/Preferences/Materials/MaterialBrandSection.qml rename to resources/qml/Preferences/Materials/MaterialsBrandSection.qml index 0acd2aa1d5..7e1db1353c 100644 --- a/resources/qml/Preferences/Materials/MaterialBrandSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsBrandSection.qml @@ -82,7 +82,7 @@ Rectangle Repeater { model: types_model - delegate: MaterialTypeSection {} + delegate: MaterialsTypeSection {} } } } \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml index fc8c6d728c..ad9f0e3766 100644 --- a/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml +++ b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml @@ -50,7 +50,7 @@ Item } } - MaterialView // Material detailed information view below the title Label + MaterialsView // Material detailed information view below the title Label { id: materialDetailsView anchors diff --git a/resources/qml/Preferences/Materials/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml index c16b37170f..2aea433843 100644 --- a/resources/qml/Preferences/Materials/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -94,7 +94,7 @@ Item Repeater { model: favoriteMaterialsModel - delegate: MaterialSlot { + delegate: MaterialsSlot { material: model } } @@ -171,7 +171,7 @@ Item Repeater { model: genericMaterialsModel - delegate: MaterialSlot { + delegate: MaterialsSlot { material: model } } @@ -181,7 +181,7 @@ Item { id: brand_list model: materialsModel - delegate: MaterialBrandSection {} + delegate: MaterialsBrandSection {} } } } \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialSlot.qml b/resources/qml/Preferences/Materials/MaterialsSlot.qml similarity index 100% rename from resources/qml/Preferences/Materials/MaterialSlot.qml rename to resources/qml/Preferences/Materials/MaterialsSlot.qml diff --git a/resources/qml/Preferences/Materials/MaterialTypeSection.qml b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml similarity index 98% rename from resources/qml/Preferences/Materials/MaterialTypeSection.qml rename to resources/qml/Preferences/Materials/MaterialsTypeSection.qml index ba4621f15e..2395714d15 100644 --- a/resources/qml/Preferences/Materials/MaterialTypeSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml @@ -89,7 +89,7 @@ Rectangle Repeater { model: colors_model - delegate: MaterialSlot { + delegate: MaterialsSlot { material: model } } diff --git a/resources/qml/Preferences/Materials/MaterialView.qml b/resources/qml/Preferences/Materials/MaterialsView.qml similarity index 100% rename from resources/qml/Preferences/Materials/MaterialView.qml rename to resources/qml/Preferences/Materials/MaterialsView.qml From 2304aeaceb2a29b6210a5e3513488ba04a7b01cf Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 24 Aug 2018 12:10:32 +0200 Subject: [PATCH 213/243] Expanded states preserved when updating models Did this so that models can be updated more often fixing bugs where when a material is set as "not favorite" in the favorites section, its updated accordingly in its "normal" section. It's also the ground work for saving material section expansion to preferences. Contributes to CURA-5378 --- cura/Machines/Models/BaseMaterialsModel.py | 3 ++ .../Machines/Models/FavoriteMaterialsModel.py | 1 - .../Materials/MaterialsBrandSection.qml | 16 +++++- .../Preferences/Materials/MaterialsList.qml | 16 +++++- .../Preferences/Materials/MaterialsPage.qml | 50 +++++++++++-------- .../Materials/MaterialsTypeSection.qml | 16 +++++- 6 files changed, 74 insertions(+), 28 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index ff006d00ae..a90d762236 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -35,6 +35,9 @@ class BaseMaterialsModel(ListModel): # Update this model when list of materials changes self._material_manager.materialsUpdated.connect(self._update) + # Update this model when list of favorites changes + self._material_manager.favoritesUpdated.connect(self._update) + self.addRoleName(Qt.UserRole + 1, "root_material_id") self.addRoleName(Qt.UserRole + 2, "id") self.addRoleName(Qt.UserRole + 3, "GUID") diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index 3c5ca226fe..be3f0f605f 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -8,7 +8,6 @@ class FavoriteMaterialsModel(BaseMaterialsModel): def __init__(self, parent = None): super().__init__(parent) - self._material_manager.favoritesUpdated.connect(self._update) # Update when favorites are changed self._update() def _update(self): diff --git a/resources/qml/Preferences/Materials/MaterialsBrandSection.qml b/resources/qml/Preferences/Materials/MaterialsBrandSection.qml index 7e1db1353c..1077cbff6f 100644 --- a/resources/qml/Preferences/Materials/MaterialsBrandSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsBrandSection.qml @@ -13,7 +13,7 @@ import Cura 1.0 as Cura Rectangle { id: brand_section - property var expanded: true + property var expanded: base.collapsed_brands.indexOf(model.name) > -1 property var types_model: model.material_types height: childrenRect.height width: parent.width @@ -69,7 +69,19 @@ Rectangle anchors.fill: brand_header onPressed: { - brand_section.expanded = !brand_section.expanded + const i = base.collapsed_brands.indexOf(model.name) + if (i > -1) + { + // Remove it + base.collapsed_brands.splice(i, 1) + brand_section.expanded = false + } + else + { + // Add it + base.collapsed_brands.push(model.name) + brand_section.expanded = true + } } } Column diff --git a/resources/qml/Preferences/Materials/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml index 2aea433843..4a1a330ed6 100644 --- a/resources/qml/Preferences/Materials/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -102,7 +102,7 @@ Item } Rectangle { - property var expanded: true + property var expanded: base.collapsed_brands.indexOf("Generic") > -1 id: generic_section height: childrenRect.height @@ -158,7 +158,19 @@ Item anchors.fill: generic_header onPressed: { - generic_section.expanded = !generic_section.expanded + const i = base.collapsed_brands.indexOf("Generic") + if (i > -1) + { + // Remove it + base.collapsed_brands.splice(i, 1) + generic_section.expanded = false + } + else + { + // Add it + base.collapsed_brands.push("Generic") + generic_section.expanded = true + } } } Column diff --git a/resources/qml/Preferences/Materials/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml index 4df6049b3f..0b81df5fa1 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -26,36 +26,44 @@ Item property string newRootMaterialIdToSwitchTo: "" property bool toActivateNewMaterial: false + // TODO: Save these to preferences + property var collapsed_brands: [] + property var collapsed_types: [] + UM.I18nCatalog { id: catalog name: "cura" } - Cura.MaterialBrandsModel + Cura.MaterialBrandsModel { id: materialsModel } + + function findModelByRootId( search_root_id ) { - id: materialsModel + for (var i = 0; i < materialsModel.rowCount(); i++) + { + var types_model = materialsModel.getItem(i).material_types; + for (var j = 0; j < types_model.rowCount(); j++) + { + var colors_model = types_model.getItem(j).colors; + for (var k = 0; k < colors_model.rowCount(); k++) + { + var material = colors_model.getItem(k); + if (material.root_material_id == search_root_id) + { + return material + } + } + } + } } - Cura.GenericMaterialsModel + Component.onCompleted: { - id: genericMaterialsModel + // Select the activated material when this page shows up + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + const active_root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + console.log("goign to search for", active_root_material_id) + base.currentItem = findModelByRootId(active_root_material_id) } - // Component.onCompleted: - // { - // // Select the activated material when this page shows up - // const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - // const active_root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - // var itemIndex = -1; - // for (var i = 0; i < materialsModel.rowCount(); ++i) - // { - // var item = materialsModel.getItem(i); - // if (item.root_material_id == active_root_material_id) - // { - // itemIndex = i; - // break; - // } - // } - // materialListView.currentIndex = itemIndex; - // } onCurrentItemChanged: { MaterialsDetailsPanel.currentItem = currentItem } Connections diff --git a/resources/qml/Preferences/Materials/MaterialsTypeSection.qml b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml index 2395714d15..11bf2385e1 100644 --- a/resources/qml/Preferences/Materials/MaterialsTypeSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml @@ -13,7 +13,7 @@ import Cura 1.0 as Cura Rectangle { id: material_type_section - property var expanded: true + property var expanded: base.collapsed_types.indexOf(model.brand + "_" + model.name) > -1 property var colors_model: model.colors height: childrenRect.height width: parent.width @@ -76,7 +76,19 @@ Rectangle anchors.fill: material_type_header onPressed: { - material_type_section.expanded = !material_type_section.expanded + const i = base.collapsed_types.indexOf(model.brand + "_" + model.name) + if (i > -1) + { + // Remove it + base.collapsed_types.splice(i, 1) + material_type_section.expanded = false + } + else + { + // Add it + base.collapsed_types.push(model.brand + "_" + model.name) + material_type_section.expanded = true + } } } Column From ea935024cfae2cc6b376d1caa0a832d589bfb429 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 24 Aug 2018 13:02:06 +0200 Subject: [PATCH 214/243] Add materil xml file to UFP file CURA-5555 --- plugins/UFPWriter/UFPWriter.py | 40 +++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index ceb9d79087..7c8b43a018 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -60,5 +60,43 @@ class UFPWriter(MeshWriter): else: Logger.log("d", "Thumbnail not created, cannot save it") + #Store the material. + application = Application.getInstance() + machine_manager = application.getMachineManager() + global_stack = machine_manager.activeMachine + container_registry = application.getContainerRegistry() + + archive.addContentType(extension="xml.fdm_material", mime_type="application/x-ultimaker-material-profile") + + added_materials = [] + for extruder_stack in global_stack.extruders.values(): + material = extruder_stack.material + material_file_name = material.getMetaData()["base_file"] + ".xml.fdm_material" + material_file_name = "/Cura/" + material_file_name + + #Same material cannot be added + if material_file_name in added_materials: + continue + + material_file = archive.getStream(material_file_name) + material_containers = container_registry.findContainers(id=material.getMetaDataEntry("base_file")) + + if not material_containers: + Logger.log("e", "Cannot find material container with id: %s", material.id) + return False + + material_container = material_containers[0] + try: + serialized_material = material_container.serialize() + except NotImplementedError: + Logger.log("e", "Unable serialize material container with id: %s", material.id) + return False + + material_file.write(serialized_material.encode("UTF-8")) + archive.addRelation(virtual_path=material_file_name,relation_type="http://schemas.ultimaker.org/package/2018/relationships/xml.fdm_material") + + + added_materials.append(material_file_name) + archive.close() - return True + return True \ No newline at end of file From aa03fabc57ceb2bc485ef59470451f25301560eb Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 24 Aug 2018 15:24:00 +0200 Subject: [PATCH 215/243] Remove trailing whitespace --- cura/LayerPolygon.py | 2 +- resources/definitions/ultimaker3.def.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 9766e0c82a..f33934de0c 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -21,7 +21,7 @@ class LayerPolygon: __number_of_types = 11 __jump_map = numpy.logical_or(numpy.logical_or(numpy.arange(__number_of_types) == NoneType, numpy.arange(__number_of_types) == MoveCombingType), numpy.arange(__number_of_types) == MoveRetractionType) - + ## LayerPolygon, used in ProcessSlicedLayersJob # \param extruder # \param line_types array with line_types diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json index 08fe01a76b..b75d12ce44 100644 --- a/resources/definitions/ultimaker3.def.json +++ b/resources/definitions/ultimaker3.def.json @@ -90,7 +90,7 @@ "infill_overlap": { "value": "0" }, "infill_pattern": { "value": "'triangles'" }, "infill_wipe_dist": { "value": "0" }, - "initial_layer_line_width_factor": { "value": "120" }, + "initial_layer_line_width_factor": { "value": "120" }, "jerk_enabled": { "value": "True" }, "jerk_layer_0": { "value": "jerk_topbottom" }, "jerk_prime_tower": { "value": "math.ceil(jerk_print * 15 / 25)" }, From 8daf02063da0f66ff12f49e0d8f8d8ac324c174b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 24 Aug 2018 15:35:01 +0200 Subject: [PATCH 216/243] Fix quality lookup fallback mechanism CURA-5668 The last fallback is the global qualities, either machine-specific or generic, but not using both. Because if a machine defines its own global qualities, it is intended to override the existing ones, so do not fallback again in this case. --- cura/Machines/QualityManager.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index df3bec0827..cb2776429f 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -259,8 +259,12 @@ class QualityManager(QObject): # 2. machine-nozzle-and-material-specific qualities if exist # 3. machine-nozzle-specific qualities if exist # 4. machine-material-specific qualities if exist - # 5. machine-specific qualities if exist - # 6. generic qualities if exist + # 5. machine-specific global qualities if exist, otherwise generic global qualities + # NOTE: We DO NOT fail back to generic global qualities if machine-specific global qualities exist. + # This is because when a machine defines its own global qualities such as Normal, Fine, etc., + # it is intended to maintain those specific qualities ONLY. If we still fail back to the generic + # global qualities, there can be unimplemented quality types e.g. "coarse", and this is not + # correct. # Each points above can be represented as a node in the lookup tree, so here we simply put those nodes into # the list with priorities as the order. Later, we just need to loop over each node in this list and fetch # qualities from there. @@ -289,7 +293,13 @@ class QualityManager(QObject): addNodesToCheck(machine_node, nodes_to_check, node_info_list_0, 0) - nodes_to_check += [machine_node, default_machine_node] + # The last fall back will be the global qualities (either from the machine-specific node or the generic + # node), but we only use one. For details see the overview comments above. + if machine_node.quality_type_map: + nodes_to_check += [machine_node] + else: + nodes_to_check += [default_machine_node] + for node in nodes_to_check: if node and node.quality_type_map: if has_variant_materials: From eac70dc06dd5e062fc54a36482b9ab025a147b65 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 27 Aug 2018 09:41:19 +0200 Subject: [PATCH 217/243] Change default print job name to 'Untitled' This is more common for documents that don't yet have a title in many applications. --- cura/PrintInformation.py | 2 +- resources/qml/JobSpecs.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 21e2040dc1..8527da1b8a 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -300,7 +300,7 @@ class PrintInformation(QObject): def _updateJobName(self): if self._base_name == "": - self._job_name = "unnamed" + self._job_name = "Untitled" self._is_user_specified_job_name = False self.jobNameChanged.emit() return diff --git a/resources/qml/JobSpecs.qml b/resources/qml/JobSpecs.qml index 20ec8ce289..31ca84d66e 100644 --- a/resources/qml/JobSpecs.qml +++ b/resources/qml/JobSpecs.qml @@ -81,7 +81,7 @@ Item { text: PrintInformation.jobName horizontalAlignment: TextInput.AlignRight onEditingFinished: { - var new_name = text == "" ? catalog.i18nc("@text Print job name", "unnamed") : text; + var new_name = text == "" ? catalog.i18nc("@text Print job name", "Untitled") : text; PrintInformation.setJobName(new_name, true); printJobTextfield.focus = false; } From 33f495442a84eecbb0a0aee4970d17258b52dd75 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 27 Aug 2018 10:44:13 +0200 Subject: [PATCH 218/243] Remove unneeded code CURA-5162 --- cura/Machines/Models/BaseMaterialsModel.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index a90d762236..43b42c55ff 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -22,7 +22,6 @@ class BaseMaterialsModel(ListModel): # Make these managers available to all material models self._container_registry = self._application.getInstance().getContainerRegistry() - self._extruder_manager = self._application.getExtruderManager() self._machine_manager = self._application.getMachineManager() self._material_manager = self._application.getMaterialManager() From 336ea150d931e7e91582997648bf02af4a023832 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 27 Aug 2018 10:45:18 +0200 Subject: [PATCH 219/243] Change tabs into spaces As per our code style. --- resources/extruders/builder_premium_large_front.def.json | 6 +++--- resources/extruders/builder_premium_large_rear.def.json | 4 ++-- resources/extruders/builder_premium_medium_front.def.json | 6 +++--- resources/extruders/builder_premium_medium_rear.def.json | 4 ++-- resources/extruders/builder_premium_small_front.def.json | 6 +++--- resources/extruders/builder_premium_small_rear.def.json | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/resources/extruders/builder_premium_large_front.def.json b/resources/extruders/builder_premium_large_front.def.json index 059f7ef8a7..4834bc8fd9 100644 --- a/resources/extruders/builder_premium_large_front.def.json +++ b/resources/extruders/builder_premium_large_front.def.json @@ -16,13 +16,13 @@ "machine_nozzle_offset_x": { "default_value": 0.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 }, "material_diameter": { "default_value": 1.75 }, - - "machine_extruder_start_pos_abs": { "default_value": true }, + + "machine_extruder_start_pos_abs": { "default_value": true }, "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" }, "machine_extruder_end_pos_abs": { "default_value": true }, "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }, - "extruder_prime_pos_abs": { "default_value": true } + "extruder_prime_pos_abs": { "default_value": true } } } diff --git a/resources/extruders/builder_premium_large_rear.def.json b/resources/extruders/builder_premium_large_rear.def.json index 769178a8b4..f257749ea4 100644 --- a/resources/extruders/builder_premium_large_rear.def.json +++ b/resources/extruders/builder_premium_large_rear.def.json @@ -20,9 +20,9 @@ "machine_extruder_start_pos_abs": { "default_value": true }, "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" }, - "machine_extruder_end_pos_abs": { "default_value": true }, + "machine_extruder_end_pos_abs": { "default_value": true }, "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }, - "extruder_prime_pos_abs": { "default_value": true } + "extruder_prime_pos_abs": { "default_value": true } } } diff --git a/resources/extruders/builder_premium_medium_front.def.json b/resources/extruders/builder_premium_medium_front.def.json index bd735fbe25..05dcb3d49f 100644 --- a/resources/extruders/builder_premium_medium_front.def.json +++ b/resources/extruders/builder_premium_medium_front.def.json @@ -16,13 +16,13 @@ "machine_nozzle_offset_x": { "default_value": 0.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 }, "material_diameter": { "default_value": 1.75 }, - - "machine_extruder_start_pos_abs": { "default_value": true }, + + "machine_extruder_start_pos_abs": { "default_value": true }, "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" }, "machine_extruder_end_pos_abs": { "default_value": true }, "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }, - "extruder_prime_pos_abs": { "default_value": true } + "extruder_prime_pos_abs": { "default_value": true } } } diff --git a/resources/extruders/builder_premium_medium_rear.def.json b/resources/extruders/builder_premium_medium_rear.def.json index 59e688ff71..3461e07f09 100644 --- a/resources/extruders/builder_premium_medium_rear.def.json +++ b/resources/extruders/builder_premium_medium_rear.def.json @@ -20,9 +20,9 @@ "machine_extruder_start_pos_abs": { "default_value": true }, "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" }, - "machine_extruder_end_pos_abs": { "default_value": true }, + "machine_extruder_end_pos_abs": { "default_value": true }, "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }, - "extruder_prime_pos_abs": { "default_value": true } + "extruder_prime_pos_abs": { "default_value": true } } } diff --git a/resources/extruders/builder_premium_small_front.def.json b/resources/extruders/builder_premium_small_front.def.json index 17fb914a42..7a1c352c73 100644 --- a/resources/extruders/builder_premium_small_front.def.json +++ b/resources/extruders/builder_premium_small_front.def.json @@ -16,13 +16,13 @@ "machine_nozzle_offset_x": { "default_value": 0.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 }, "material_diameter": { "default_value": 1.75 }, - - "machine_extruder_start_pos_abs": { "default_value": true }, + + "machine_extruder_start_pos_abs": { "default_value": true }, "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" }, "machine_extruder_end_pos_abs": { "default_value": true }, "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }, - "extruder_prime_pos_abs": { "default_value": true } + "extruder_prime_pos_abs": { "default_value": true } } } diff --git a/resources/extruders/builder_premium_small_rear.def.json b/resources/extruders/builder_premium_small_rear.def.json index 70a2dbf1aa..7085236a5c 100644 --- a/resources/extruders/builder_premium_small_rear.def.json +++ b/resources/extruders/builder_premium_small_rear.def.json @@ -20,9 +20,9 @@ "machine_extruder_start_pos_abs": { "default_value": true }, "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" }, - "machine_extruder_end_pos_abs": { "default_value": true }, + "machine_extruder_end_pos_abs": { "default_value": true }, "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }, - "extruder_prime_pos_abs": { "default_value": true } + "extruder_prime_pos_abs": { "default_value": true } } } From 45e335531884902becc2c948e592fa6aa0a12b10 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 27 Aug 2018 10:57:58 +0200 Subject: [PATCH 220/243] Catch failure to parse QML component Don't crash the application then. --- plugins/PostProcessingPlugin/PostProcessingPlugin.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/PostProcessingPlugin.py b/plugins/PostProcessingPlugin/PostProcessingPlugin.py index da971a8e61..b28a028325 100644 --- a/plugins/PostProcessingPlugin/PostProcessingPlugin.py +++ b/plugins/PostProcessingPlugin/PostProcessingPlugin.py @@ -1,5 +1,6 @@ -# Copyright (c) 2015 Jaime van Kessel, Ultimaker B.V. +# Copyright (c) 2018 Jaime van Kessel, Ultimaker B.V. # The PostProcessingPlugin is released under the terms of the AGPLv3 or higher. + from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot from UM.PluginRegistry import PluginRegistry @@ -260,6 +261,9 @@ class PostProcessingPlugin(QObject, Extension): # Create the plugin dialog component path = os.path.join(PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), "PostProcessingPlugin.qml") self._view = Application.getInstance().createQmlComponent(path, {"manager": self}) + if self._view is None: + Logger.log("e", "Not creating PostProcessing button near save button because the QML component failed to be created.") + return Logger.log("d", "Post processing view created.") # Create the save button component @@ -269,6 +273,9 @@ class PostProcessingPlugin(QObject, Extension): def showPopup(self): if self._view is None: self._createView() + if self._view is None: + Logger.log("e", "Not creating PostProcessing window since the QML component failed to be created.") + return self._view.show() ## Property changed: trigger re-slice From 423f1210b013b268086c2edd4acf121bdde64710 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Mon, 27 Aug 2018 11:10:41 +0200 Subject: [PATCH 221/243] Catch erros and open the write stream only if the material cointaner is found CURA-5555 --- plugins/UFPWriter/UFPWriter.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index 7c8b43a018..841d61a000 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -24,6 +24,8 @@ class UFPWriter(MeshWriter): self._snapshot = None Application.getInstance().getOutputDeviceManager().writeStarted.connect(self._createSnapshot) + self._default_data_path ="/Cura/" + def _createSnapshot(self, *args): # must be called from the main thread because of OpenGL Logger.log("d", "Creating thumbnail image...") @@ -66,19 +68,24 @@ class UFPWriter(MeshWriter): global_stack = machine_manager.activeMachine container_registry = application.getContainerRegistry() - archive.addContentType(extension="xml.fdm_material", mime_type="application/x-ultimaker-material-profile") + material_extension = "xml.fdm_material" + material_mime_type = "application/x-ultimaker-material-profile" + + try: + archive.addContentType(extension=material_extension, mime_type=material_mime_type) + except: + Logger.log("w", "The material extension: %s was already added", material_extension) added_materials = [] for extruder_stack in global_stack.extruders.values(): material = extruder_stack.material material_file_name = material.getMetaData()["base_file"] + ".xml.fdm_material" - material_file_name = "/Cura/" + material_file_name + material_file_name = self._default_data_path + material_file_name #Same material cannot be added if material_file_name in added_materials: continue - material_file = archive.getStream(material_file_name) material_containers = container_registry.findContainers(id=material.getMetaDataEntry("base_file")) if not material_containers: @@ -92,10 +99,10 @@ class UFPWriter(MeshWriter): Logger.log("e", "Unable serialize material container with id: %s", material.id) return False + material_file = archive.getStream(material_file_name) material_file.write(serialized_material.encode("UTF-8")) archive.addRelation(virtual_path=material_file_name,relation_type="http://schemas.ultimaker.org/package/2018/relationships/xml.fdm_material") - added_materials.append(material_file_name) archive.close() From 22ccf074f3b8529bbb541d1da20ca39ff7d9d572 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 27 Aug 2018 13:20:18 +0200 Subject: [PATCH 222/243] Only check if printing extruder is enabled for printing meshes CURA-5669 --- plugins/CuraEngineBackend/StartSliceJob.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 0ebcafdbb2..1295390c22 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -220,8 +220,10 @@ class StartSliceJob(Job): stack = global_stack skip_group = False for node in group: + # Only check if the printing extruder is enabled for printing meshes + is_non_printing_mesh = node.callDecoration("evaluateIsNonPrintingMesh") extruder_position = node.callDecoration("getActiveExtruderPosition") - if not extruders_enabled[extruder_position]: + if not is_non_printing_mesh and not extruders_enabled[extruder_position]: skip_group = True has_model_with_disabled_extruders = True associated_disabled_extruders.add(extruder_position) From fe9cada45903c71b64c033fd3603eb6866917a2e Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Mon, 27 Aug 2018 13:59:00 +0200 Subject: [PATCH 223/243] Increase plugin API version to 5 CURA-5627 --- plugins/3MFReader/plugin.json | 2 +- plugins/3MFWriter/plugin.json | 2 +- plugins/ChangeLogPlugin/plugin.json | 2 +- plugins/CuraEngineBackend/plugin.json | 2 +- plugins/CuraProfileReader/plugin.json | 2 +- plugins/CuraProfileWriter/plugin.json | 2 +- plugins/FirmwareUpdateChecker/plugin.json | 2 +- plugins/GCodeGzReader/plugin.json | 2 +- plugins/GCodeGzWriter/plugin.json | 2 +- plugins/GCodeProfileReader/plugin.json | 2 +- plugins/GCodeReader/plugin.json | 2 +- plugins/GCodeWriter/plugin.json | 2 +- plugins/ImageReader/plugin.json | 2 +- plugins/LegacyProfileReader/plugin.json | 2 +- plugins/MachineSettingsAction/plugin.json | 2 +- plugins/ModelChecker/plugin.json | 2 +- plugins/MonitorStage/plugin.json | 2 +- plugins/PerObjectSettingsTool/plugin.json | 2 +- plugins/PostProcessingPlugin/plugin.json | 2 +- plugins/PrepareStage/plugin.json | 2 +- plugins/RemovableDriveOutputDevice/plugin.json | 2 +- plugins/SimulationView/plugin.json | 2 +- plugins/SliceInfoPlugin/plugin.json | 2 +- plugins/SolidView/plugin.json | 2 +- plugins/SupportEraser/plugin.json | 2 +- plugins/Toolbox/plugin.json | 2 +- plugins/UFPWriter/plugin.json | 2 +- plugins/UM3NetworkPrinting/plugin.json | 2 +- plugins/USBPrinting/plugin.json | 2 +- plugins/UltimakerMachineActions/plugin.json | 2 +- plugins/UserAgreement/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade34to40/plugin.json | 2 +- plugins/X3DReader/plugin.json | 2 +- plugins/XRayView/plugin.json | 2 +- plugins/XmlMaterialProfile/plugin.json | 2 +- 43 files changed, 43 insertions(+), 43 deletions(-) diff --git a/plugins/3MFReader/plugin.json b/plugins/3MFReader/plugin.json index 5d15123017..5e41975752 100644 --- a/plugins/3MFReader/plugin.json +++ b/plugins/3MFReader/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for reading 3MF files.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/3MFWriter/plugin.json b/plugins/3MFWriter/plugin.json index 22d18b2cf1..9ec4fb0c20 100644 --- a/plugins/3MFWriter/plugin.json +++ b/plugins/3MFWriter/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for writing 3MF files.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/ChangeLogPlugin/plugin.json b/plugins/ChangeLogPlugin/plugin.json index e9414b9b71..e09a08564a 100644 --- a/plugins/ChangeLogPlugin/plugin.json +++ b/plugins/ChangeLogPlugin/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Shows changes since latest checked version.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/CuraEngineBackend/plugin.json b/plugins/CuraEngineBackend/plugin.json index e5df06f228..111698d8d1 100644 --- a/plugins/CuraEngineBackend/plugin.json +++ b/plugins/CuraEngineBackend/plugin.json @@ -2,7 +2,7 @@ "name": "CuraEngine Backend", "author": "Ultimaker B.V.", "description": "Provides the link to the CuraEngine slicing backend.", - "api": 4, + "api": 5, "version": "1.0.0", "i18n-catalog": "cura" } diff --git a/plugins/CuraProfileReader/plugin.json b/plugins/CuraProfileReader/plugin.json index 004a1ade4d..66a2a6a56b 100644 --- a/plugins/CuraProfileReader/plugin.json +++ b/plugins/CuraProfileReader/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for importing Cura profiles.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/CuraProfileWriter/plugin.json b/plugins/CuraProfileWriter/plugin.json index d9accce770..16c8c34152 100644 --- a/plugins/CuraProfileWriter/plugin.json +++ b/plugins/CuraProfileWriter/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for exporting Cura profiles.", - "api": 4, + "api": 5, "i18n-catalog":"cura" } diff --git a/plugins/FirmwareUpdateChecker/plugin.json b/plugins/FirmwareUpdateChecker/plugin.json index d6a9f9fbd7..cbbd41e420 100644 --- a/plugins/FirmwareUpdateChecker/plugin.json +++ b/plugins/FirmwareUpdateChecker/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Checks for firmware updates.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/GCodeGzReader/plugin.json b/plugins/GCodeGzReader/plugin.json index e9f14724e0..3bd6a4097d 100644 --- a/plugins/GCodeGzReader/plugin.json +++ b/plugins/GCodeGzReader/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Reads g-code from a compressed archive.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/GCodeGzWriter/plugin.json b/plugins/GCodeGzWriter/plugin.json index 9774e9a25c..4c6497317b 100644 --- a/plugins/GCodeGzWriter/plugin.json +++ b/plugins/GCodeGzWriter/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Writes g-code to a compressed archive.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/GCodeProfileReader/plugin.json b/plugins/GCodeProfileReader/plugin.json index f8f7d4c291..9677628c85 100644 --- a/plugins/GCodeProfileReader/plugin.json +++ b/plugins/GCodeProfileReader/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for importing profiles from g-code files.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/GCodeReader/plugin.json b/plugins/GCodeReader/plugin.json index f72a8cc12c..75b4d0cd4f 100644 --- a/plugins/GCodeReader/plugin.json +++ b/plugins/GCodeReader/plugin.json @@ -3,6 +3,6 @@ "author": "Victor Larchenko", "version": "1.0.0", "description": "Allows loading and displaying G-code files.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/GCodeWriter/plugin.json b/plugins/GCodeWriter/plugin.json index 5fcb1a3bd7..3bbbab8b95 100644 --- a/plugins/GCodeWriter/plugin.json +++ b/plugins/GCodeWriter/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Writes g-code to a file.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/ImageReader/plugin.json b/plugins/ImageReader/plugin.json index 2752c6e8f4..08195863e8 100644 --- a/plugins/ImageReader/plugin.json +++ b/plugins/ImageReader/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Enables ability to generate printable geometry from 2D image files.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/LegacyProfileReader/plugin.json b/plugins/LegacyProfileReader/plugin.json index 2dc71511a9..179f5444e0 100644 --- a/plugins/LegacyProfileReader/plugin.json +++ b/plugins/LegacyProfileReader/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for importing profiles from legacy Cura versions.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/MachineSettingsAction/plugin.json b/plugins/MachineSettingsAction/plugin.json index 703a145deb..571658e40a 100644 --- a/plugins/MachineSettingsAction/plugin.json +++ b/plugins/MachineSettingsAction/plugin.json @@ -3,6 +3,6 @@ "author": "fieldOfView", "version": "1.0.0", "description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/ModelChecker/plugin.json b/plugins/ModelChecker/plugin.json index a9190adcaa..3753c0cc88 100644 --- a/plugins/ModelChecker/plugin.json +++ b/plugins/ModelChecker/plugin.json @@ -2,7 +2,7 @@ "name": "Model Checker", "author": "Ultimaker B.V.", "version": "0.1", - "api": 4, + "api": 5, "description": "Checks models and print configuration for possible printing issues and give suggestions.", "i18n-catalog": "cura" } diff --git a/plugins/MonitorStage/plugin.json b/plugins/MonitorStage/plugin.json index cb3f55a80d..88b53840e0 100644 --- a/plugins/MonitorStage/plugin.json +++ b/plugins/MonitorStage/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides a monitor stage in Cura.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } \ No newline at end of file diff --git a/plugins/PerObjectSettingsTool/plugin.json b/plugins/PerObjectSettingsTool/plugin.json index 3254662d33..15fde63387 100644 --- a/plugins/PerObjectSettingsTool/plugin.json +++ b/plugins/PerObjectSettingsTool/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides the Per Model Settings.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/PostProcessingPlugin/plugin.json b/plugins/PostProcessingPlugin/plugin.json index ebfef8145a..fea061e93b 100644 --- a/plugins/PostProcessingPlugin/plugin.json +++ b/plugins/PostProcessingPlugin/plugin.json @@ -2,7 +2,7 @@ "name": "Post Processing", "author": "Ultimaker", "version": "2.2", - "api": 4, + "api": 5, "description": "Extension that allows for user created scripts for post processing", "catalog": "cura" } \ No newline at end of file diff --git a/plugins/PrepareStage/plugin.json b/plugins/PrepareStage/plugin.json index 4fd55e955e..f0464313c7 100644 --- a/plugins/PrepareStage/plugin.json +++ b/plugins/PrepareStage/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides a prepare stage in Cura.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } \ No newline at end of file diff --git a/plugins/RemovableDriveOutputDevice/plugin.json b/plugins/RemovableDriveOutputDevice/plugin.json index df11644256..36bb9ae186 100644 --- a/plugins/RemovableDriveOutputDevice/plugin.json +++ b/plugins/RemovableDriveOutputDevice/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "description": "Provides removable drive hotplugging and writing support.", "version": "1.0.0", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/SimulationView/plugin.json b/plugins/SimulationView/plugin.json index 0e7bec0626..93df98068f 100644 --- a/plugins/SimulationView/plugin.json +++ b/plugins/SimulationView/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides the Simulation view.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/SliceInfoPlugin/plugin.json b/plugins/SliceInfoPlugin/plugin.json index d1c643266b..939e5ff235 100644 --- a/plugins/SliceInfoPlugin/plugin.json +++ b/plugins/SliceInfoPlugin/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Submits anonymous slice info. Can be disabled through preferences.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/SolidView/plugin.json b/plugins/SolidView/plugin.json index 6d6bda96f0..e70ec224dd 100644 --- a/plugins/SolidView/plugin.json +++ b/plugins/SolidView/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides a normal solid mesh view.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } \ No newline at end of file diff --git a/plugins/SupportEraser/plugin.json b/plugins/SupportEraser/plugin.json index 5ccb639913..7af35e0fb5 100644 --- a/plugins/SupportEraser/plugin.json +++ b/plugins/SupportEraser/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Creates an eraser mesh to block the printing of support in certain places", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/Toolbox/plugin.json b/plugins/Toolbox/plugin.json index 12d4042b6b..2557185524 100644 --- a/plugins/Toolbox/plugin.json +++ b/plugins/Toolbox/plugin.json @@ -2,6 +2,6 @@ "name": "Toolbox", "author": "Ultimaker B.V.", "version": "1.0.0", - "api": 4, + "api": 5, "description": "Find, manage and install new Cura packages." } diff --git a/plugins/UFPWriter/plugin.json b/plugins/UFPWriter/plugin.json index 7d10b89ad4..ab590353e0 100644 --- a/plugins/UFPWriter/plugin.json +++ b/plugins/UFPWriter/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for writing Ultimaker Format Packages.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/plugin.json b/plugins/UM3NetworkPrinting/plugin.json index e7b59fadd6..d415338374 100644 --- a/plugins/UM3NetworkPrinting/plugin.json +++ b/plugins/UM3NetworkPrinting/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "description": "Manages network connections to Ultimaker 3 printers.", "version": "1.0.0", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/USBPrinting/plugin.json b/plugins/USBPrinting/plugin.json index 27e07c45b2..3484c8a48a 100644 --- a/plugins/USBPrinting/plugin.json +++ b/plugins/USBPrinting/plugin.json @@ -2,7 +2,7 @@ "name": "USB printing", "author": "Ultimaker B.V.", "version": "1.0.0", - "api": 4, + "api": 5, "description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.", "i18n-catalog": "cura" } diff --git a/plugins/UltimakerMachineActions/plugin.json b/plugins/UltimakerMachineActions/plugin.json index 57b3e6bc8f..b60c7df88e 100644 --- a/plugins/UltimakerMachineActions/plugin.json +++ b/plugins/UltimakerMachineActions/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/UserAgreement/plugin.json b/plugins/UserAgreement/plugin.json index b10abc5640..50a2aa0441 100644 --- a/plugins/UserAgreement/plugin.json +++ b/plugins/UserAgreement/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Ask the user once if he/she agrees with our license.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json b/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json index 79115f931e..463fcdc941 100644 --- a/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 2.1 to Cura 2.2.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json b/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json index d213042ad2..e7a0b1c559 100644 --- a/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 2.2 to Cura 2.4.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json b/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json index 759b6368fd..3029539887 100644 --- a/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 2.5 to Cura 2.6.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json b/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json index 3c3d7fff8c..225da67235 100644 --- a/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 2.6 to Cura 2.7.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json b/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json index 3df84ff7e6..9a139851ec 100644 --- a/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 2.7 to Cura 3.0.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json b/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json index d80b820976..cf42b3f6cd 100644 --- a/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 3.0 to Cura 3.1.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json b/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json index fbce09c807..f9cc968dae 100644 --- a/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 3.2 to Cura 3.3.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json b/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json index 164b79d504..f5ba7235d1 100644 --- a/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 3.3 to Cura 3.4.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade34to40/plugin.json b/plugins/VersionUpgrade/VersionUpgrade34to40/plugin.json index 1059ca3e57..c07ae31c0a 100644 --- a/plugins/VersionUpgrade/VersionUpgrade34to40/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade34to40/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 3.4 to Cura 4.0.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/X3DReader/plugin.json b/plugins/X3DReader/plugin.json index f18c7f033d..9ee09e43df 100644 --- a/plugins/X3DReader/plugin.json +++ b/plugins/X3DReader/plugin.json @@ -3,6 +3,6 @@ "author": "Seva Alekseyev", "version": "0.5.0", "description": "Provides support for reading X3D files.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/XRayView/plugin.json b/plugins/XRayView/plugin.json index 4e89690c13..576dec4656 100644 --- a/plugins/XRayView/plugin.json +++ b/plugins/XRayView/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides the X-Ray view.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/XmlMaterialProfile/plugin.json b/plugins/XmlMaterialProfile/plugin.json index 17056dcb3e..4b2901c375 100644 --- a/plugins/XmlMaterialProfile/plugin.json +++ b/plugins/XmlMaterialProfile/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides capabilities to read and write XML-based material profiles.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } From 8c4117541c1f15d0ac8655e56c0e9a20d54a25fc Mon Sep 17 00:00:00 2001 From: Matteo Spinelli Date: Fri, 17 Aug 2018 12:01:43 +0200 Subject: [PATCH 224/243] Update Peopoly moai definitions and files --- resources/definitions/peopoly_moai.def.json | 115 +++++++++++++++--- resources/images/moai.jpg | Bin 0 -> 431184 bytes resources/meshes/moai.obj | 32 +++++ .../peopoly_moai/peopoly_moai_coarse.inst.cfg | 17 +++ .../peopoly_moai/peopoly_moai_draft.inst.cfg | 18 +++ .../peopoly_moai_extra_high.inst.cfg | 18 +++ .../peopoly_moai/peopoly_moai_high.inst.cfg | 13 +- .../peopoly_moai/peopoly_moai_max.inst.cfg | 17 --- .../peopoly_moai/peopoly_moai_normal.inst.cfg | 14 +-- 9 files changed, 199 insertions(+), 45 deletions(-) create mode 100644 resources/images/moai.jpg create mode 100644 resources/meshes/moai.obj create mode 100644 resources/quality/peopoly_moai/peopoly_moai_coarse.inst.cfg create mode 100644 resources/quality/peopoly_moai/peopoly_moai_draft.inst.cfg create mode 100644 resources/quality/peopoly_moai/peopoly_moai_extra_high.inst.cfg delete mode 100644 resources/quality/peopoly_moai/peopoly_moai_max.inst.cfg diff --git a/resources/definitions/peopoly_moai.def.json b/resources/definitions/peopoly_moai.def.json index 5c03444d49..815469db32 100644 --- a/resources/definitions/peopoly_moai.def.json +++ b/resources/definitions/peopoly_moai.def.json @@ -4,15 +4,13 @@ "inherits": "fdmprinter", "metadata": { "visible": true, - "author": "fieldOfView", + "author": "Peopoly", "manufacturer": "Peopoly", "file_formats": "text/x-gcode", "has_machine_quality": true, "has_materials": false, - "machine_extruder_trains": - { - "0": "peopoly_moai_extruder_0" - } + "platform": "moai.obj", + "platform_texture": "moai.jpg" }, "overrides": { @@ -28,6 +26,9 @@ "machine_depth": { "default_value": 130 }, + "machine_nozzle_size": { + "default_value": 0.067 + }, "machine_head_with_fans_polygon": { "default_value": [ @@ -37,6 +38,10 @@ [ 10, -10 ] ] }, + "material_diameter": { + "enabled": false, + "value": 1.75 + }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, @@ -46,7 +51,6 @@ "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\nG28 X0 Y0\nM84" }, - "line_width": { "minimum_value_warning": "machine_nozzle_size" }, @@ -75,7 +79,8 @@ "value": "0.1" }, "top_bottom_thickness": { - "minimum_value_warning": "0.1" + "minimum_value_warning": "0.1", + "value": "0.4" }, "infill_sparse_thickness": { "maximum_value_warning": "0.5" @@ -102,24 +107,23 @@ "value": "speed_print" }, "speed_travel": { - "value": "300" + "value": 150 }, "speed_travel_layer_0": { - "value": "300" + "value": 150 }, "speed_layer_0": { - "value": "5" + "value": 5 }, "speed_slowdown_layers": { - "value": "2" + "value": 3 }, "infill_overlap": { - "value": "15" + "value": 15 }, "adhesion_type": { - "value": "\"none\"" + "value": "'none'" }, - "acceleration_enabled": { "value": "False" }, @@ -139,6 +143,10 @@ "enabled": false, "value": "False" }, + "cool_fan_speed_min": { + "enabled": false, + "value": 0 + }, "retraction_enable": { "enabled": false, "value": "False" @@ -148,7 +156,8 @@ "value": "'off'" }, "retract_at_layer_change": { - "enabled": false + "enabled": false, + "value": false }, "cool_min_layer_time_fan_speed_max": { "enabled": false @@ -158,6 +167,82 @@ }, "cool_fan_full_layer": { "enabled": false + }, + "snap_distance": { + "value": "0.1" + }, + "meshfix_maximum_resolution": { + "value": "0.005" + }, + "skin_outline_count": { + "value": 0 + }, + "travel_compensate_overlapping_walls_enabled": { + "value": "False" + }, + "travel_compensate_overlapping_walls_0_enabled": { + "value": "False" + }, + "travel_compensate_overlapping_walls_x_enabled": { + "value": "False" + }, + "wall_thickness": { + "value": 0.4 + }, + "infill_sparse_density": { + "value": 70 + }, + "infill_pattern": { + "value": "'lines'" + }, + "cool_min_layer_time": { + "enabled": false, + "value": 0 + }, + "cool_min_speed": { + "enabled": false, + "value": 0 + }, + "cool_lift_head": { + "enabled": false, + "value": "False" + }, + "material_flow": { + "enabled": false + }, + "material_flow_layer_0": { + "enabled": false + }, + "speed_equalize_flow_enabled": { + "enabled": false, + "value": "False" + }, + "draft_shield_enabled": { + "enabled": false, + "value": "False" + }, + "z_seam_corner": { + "value": "'z_seam_corner_none'" + }, + "z_seam_type": { + "value": "'shortest'" + }, + "skin_no_small_gaps_heuristic": { + "value": "False" + }, + "ironing_enabled": { + "enabled": false, + "value": "False" + }, + "skin_overlap": { + "value": 6 + }, + "infill_wipe_dist": { + "value": 0 + }, + "max_feedrate_z_override": { + "value": 0, + "enabled": false } } } diff --git a/resources/images/moai.jpg b/resources/images/moai.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eb7fcf35621850f15cf874032224c00990b4acad GIT binary patch literal 431184 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Ƀ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 literal 0 HcmV?d00001 diff --git a/resources/meshes/moai.obj b/resources/meshes/moai.obj new file mode 100644 index 0000000000..f13f30d6f4 --- /dev/null +++ b/resources/meshes/moai.obj @@ -0,0 +1,32 @@ +# OBJ written from C:\Users\Flo\Desktop\Cura_FILES\moai.obj +mtllib moai.mtl +# Units millimeters + +g Mesh +v 65 -65 0 +v -65 -65 0 +v -65 65 0 +v 65 65 0 +v 65 -65 0 +v -65 -65 0 +v -65 65 0 +v 65 65 0 +v -65 65 18.8383 +v 65 65 18.8383 +vn 0 0 1 +vn 1 0 0 +vn -1 0 0 +vt 0.0975501 1 +vt 1 1 +vt 1 0.0977239 +vt 0.0975501 0.0977239 +vt 0.0186426 0.870052 +vt 0.0736426 0.870052 +vt 0.0186426 0.815052 +vt 0.0214764 0.912057 +vt 0.0764764 0.967057 +vt 0.0214764 0.967057 +usemtl red +f 1/1/1 4/2/1 3/3/1 2/4/1 +f 7/5/2 9/6/2 6/7/2 +f 5/8/3 10/9/3 8/10/3 diff --git a/resources/quality/peopoly_moai/peopoly_moai_coarse.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_coarse.inst.cfg new file mode 100644 index 0000000000..482b8ce51a --- /dev/null +++ b/resources/quality/peopoly_moai/peopoly_moai_coarse.inst.cfg @@ -0,0 +1,17 @@ +[general] +version = 4 +name = Coarse +definition = peopoly_moai + +[metadata] +setting_version = 5 +type = quality +quality_type = coarse +weight = 3 + +[values] +layer_height = 0.08 +speed_print = 90 +speed_travel = 100 +speed_travel_layer_0 = 100 +speed_wall = 90 diff --git a/resources/quality/peopoly_moai/peopoly_moai_draft.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_draft.inst.cfg new file mode 100644 index 0000000000..e7cfa673b2 --- /dev/null +++ b/resources/quality/peopoly_moai/peopoly_moai_draft.inst.cfg @@ -0,0 +1,18 @@ +[general] +version = 4 +name = Draft +definition = peopoly_moai + +[metadata] +setting_version = 5 +type = quality +quality_type = draft +weight = 4 + +[values] +layer_height = 0.1 +speed_print = 85 +speed_travel = 100 +speed_travel_layer_0 = 100 +speed_wall = 85 +speed_slowdown_layers = 2 diff --git a/resources/quality/peopoly_moai/peopoly_moai_extra_high.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_extra_high.inst.cfg new file mode 100644 index 0000000000..da62ee32cd --- /dev/null +++ b/resources/quality/peopoly_moai/peopoly_moai_extra_high.inst.cfg @@ -0,0 +1,18 @@ +[general] +version = 4 +name = Extra High +definition = peopoly_moai + +[metadata] +setting_version = 5 +type = quality +quality_type = extra_high +weight = 0 + +[values] +layer_height = 0.02 +speed_print = 185 +speed_travel = 190 +speed_travel_layer_0 = 100 +speed_wall = 185 +speed_slowdown_layers = 5 diff --git a/resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg index 36b5f21ff8..be35dbaf05 100644 --- a/resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg +++ b/resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg @@ -1,6 +1,6 @@ [general] version = 4 -name = Extra Fine +name = High definition = peopoly_moai [metadata] @@ -10,8 +10,9 @@ quality_type = high weight = 1 [values] -infill_sparse_density = 70 -layer_height = 0.05 -top_bottom_thickness = 0.4 -wall_thickness = 0.4 -speed_print = 150 +layer_height = 0.04 +speed_print = 140 +speed_travel = 145 +speed_travel_layer_0 = 100 +speed_wall = 140 +speed_slowdown_layers = 4 diff --git a/resources/quality/peopoly_moai/peopoly_moai_max.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_max.inst.cfg deleted file mode 100644 index 48ffd07f33..0000000000 --- a/resources/quality/peopoly_moai/peopoly_moai_max.inst.cfg +++ /dev/null @@ -1,17 +0,0 @@ -[general] -version = 4 -name = Maximum Quality -definition = peopoly_moai - -[metadata] -setting_version = 5 -type = quality -quality_type = extra_high -weight = 2 - -[values] -infill_sparse_density = 70 -layer_height = 0.025 -top_bottom_thickness = 0.4 -wall_thickness = 0.4 -speed_print = 200 diff --git a/resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg index f5fe799ac3..2d6ba873db 100644 --- a/resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg +++ b/resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg @@ -1,17 +1,17 @@ [general] version = 4 -name = Fine +name = Normal definition = peopoly_moai [metadata] setting_version = 5 type = quality quality_type = normal -weight = 0 +weight = 2 [values] -infill_sparse_density = 70 -layer_height = 0.1 -top_bottom_thickness = 0.4 -wall_thickness = 0.4 -speed_print = 100 +layer_height = 0.06 +speed_print = 120 +speed_travel = 130 +speed_travel_layer_0 = 100 +speed_wall = 120 From eca2f5f6bad341e407b887dcb7147702c00ae1e9 Mon Sep 17 00:00:00 2001 From: Matteo Spinelli Date: Fri, 17 Aug 2018 12:27:38 +0200 Subject: [PATCH 225/243] change from snap_distance to minimum_polygon_circumference --- resources/definitions/peopoly_moai.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/peopoly_moai.def.json b/resources/definitions/peopoly_moai.def.json index 815469db32..cf919dd1fa 100644 --- a/resources/definitions/peopoly_moai.def.json +++ b/resources/definitions/peopoly_moai.def.json @@ -168,7 +168,7 @@ "cool_fan_full_layer": { "enabled": false }, - "snap_distance": { + "minimum_polygon_circumference": { "value": "0.1" }, "meshfix_maximum_resolution": { From d0c14969604f69053404bcadd3eac667c5f97f84 Mon Sep 17 00:00:00 2001 From: Matteo Spinelli Date: Fri, 17 Aug 2018 17:02:56 +0200 Subject: [PATCH 226/243] fix issues with moai profile --- resources/definitions/peopoly_moai.def.json | 12 ++++-------- resources/extruders/peopoly_moai_extruder_0.def.json | 5 ++++- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/resources/definitions/peopoly_moai.def.json b/resources/definitions/peopoly_moai.def.json index cf919dd1fa..85480b303d 100644 --- a/resources/definitions/peopoly_moai.def.json +++ b/resources/definitions/peopoly_moai.def.json @@ -10,7 +10,10 @@ "has_machine_quality": true, "has_materials": false, "platform": "moai.obj", - "platform_texture": "moai.jpg" + "platform_texture": "moai.jpg", + "machine_extruder_trains": { + "0": "peopoly_moai_extruder_0" + } }, "overrides": { @@ -26,9 +29,6 @@ "machine_depth": { "default_value": 130 }, - "machine_nozzle_size": { - "default_value": 0.067 - }, "machine_head_with_fans_polygon": { "default_value": [ @@ -38,10 +38,6 @@ [ 10, -10 ] ] }, - "material_diameter": { - "enabled": false, - "value": 1.75 - }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, diff --git a/resources/extruders/peopoly_moai_extruder_0.def.json b/resources/extruders/peopoly_moai_extruder_0.def.json index 7940002926..bbffd4ac4d 100644 --- a/resources/extruders/peopoly_moai_extruder_0.def.json +++ b/resources/extruders/peopoly_moai_extruder_0.def.json @@ -11,6 +11,9 @@ "overrides": { "extruder_nr": { "default_value": 0 }, "machine_nozzle_size": { "default_value": 0.067 }, - "material_diameter": { "default_value": 1.75 } + "material_diameter": { + "enabled": false, + "default_value": 1.75 + } } } From 048bdd36a66d49edb128c39f722c186ae31c5b1d Mon Sep 17 00:00:00 2001 From: Matteo Spinelli Date: Sun, 19 Aug 2018 21:11:20 +0200 Subject: [PATCH 227/243] updated moai plate image --- resources/images/moai.jpg | Bin 431184 -> 308997 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/resources/images/moai.jpg b/resources/images/moai.jpg index eb7fcf35621850f15cf874032224c00990b4acad..54c6c7561e2f4031a7a52350fc7a5257371dfa14 100644 GIT binary patch literal 308997 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

rjL6g#g~Em8>-G4Q8_nf{*1Gs%*r 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

=0Hrz4-Obzf!+jyBk+L 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

ys&wKl?eniE{{To_c2sWeQsW)i>*Ub zBuPGnRK?AdWPkCXzTv(&pcE`3Q+9<%1%&))*1DE^1xG;{EDmepTjkWgGJkeTlyDpa z=RD4W-CK~NVk$WXj_v+s|IG#qJbXMdjUcqLof=tHy$44S0YG-lYi^mw1-Gc#F62qe zg*8r&@1uvF1sZQ?dO07dHbC_dgF~73pigy=L>?nWVBf_E$^e080oNQafI6}~g;sYu zpnHIWRK0Sh<`q8MG5M((VGBFIk5176emx0<)u7NkP{2g;NW|t_`(}8X!-qeRkE|nu z=A!u98H{cW2K#dL2m3&(XUgR&jueYFws{`X+~;0Nv>BeZQ#)A~o6;)#*qM=TN=ExM z)lmZE+d`6|?TGKIhTpHX>hpn<5BHN(E9Q1jSnQwolhwrGpzuJFZe2Z~ti)t9~{Ne4v zO(MM~EF>|1G8yyBk*s6j$qYKRTwc)w?fZl(b7-1cXiNUhp5+6g0g0W>j_iYo+}Vsl zHg~N9SM1P@`r(-jM!Q|*L1;k{nkX-Hezrl}@-=y**>4*Kwonc#Guef6OXx0dxF`P5 zr9zUHAzJBjWzPe>F}3=94K)=fzWWnWS0!##(a#Mp*;XESYbqo8_!736lf2tcn{7leAZm=fw>TgGoN@MsKgsxQ<$gxchpl9uu70mfUB0lP=JdO zPUOk(#QtKwB6Fq0nnz1V{|1?Io_KZSxi|0Kj9=-IQKwU`PRE=4Y~#`KeD@W6CZI>! zPlh)r55(Ykukqqx;-|E-+iN>sA18KgooHAW5bu*OJ82KsC23MqV^=r3?>Lcm8Y}r1 zmUT)cQg^ELZHT_1uCV7V3QD-~P;j-&jbPyBGwUM~TE=!5JPBbE<)H{h?3CN%` zy5n6a#MsV=o6@!3XZY--IHhW~btijT*8c1H_1vqReQ!&Z+LMiJC9W5at{Me)>*70? z57c!1cSzR}{(m69*|C*PK*+!$@#b*{P;DC)Di3Pl2HXA~4E zS>l5}>VXoyp~`NA*SCYbeOZyUcZX(ybKyVIbuL?Gxz|+B$X0vEwyr8GzL~M&OuAA% zbI4ESFC~lXJXK4=JxFaU*bR|4qTIQDjAKh6_EhB4*kj&CtIH>~X3q}=4JLoaTAyQu zEWx?Rh|m1d-ATKoL(EA^*I)gCqyj^6vNC_5I?{+=DP*KY&zrn|Y}jqX5v4*i;V9?*jpq~n4@XqGRXM+*-D2wc z^VEzElxHMKnf#mGvD9w9Mupz39Hy+#PKU`BXD)`KrmB3=VQuZ+14gr!amusF`Pq`V zlYO4o4$tyy=&YrD_3p<}Fs>{3ySsjEAQ3Hn*GBF6wP_=~gU`UrEBo8F9{a~|C3MLImA`{{fiwk*w z&lV&qkOhIO4o-x#g2))2HE??N_=DpWYMS~@!>-yxq`9pRly$RnXe`%1YGnnw_+~+! zYiRw};bmH;iFW_Pq9J_Ps63yjYPaSdKYR5^aGOPTe@5%PXPW_0cY}946GH>}A1Fil zuwmP&;*9hNs9ABEodcDq8Q`>^@{-!MvOA|z6glqH zI+3r1DPro!=EdbO&S-5wV@tHY9i6#8=?a&{{u?ehJ5U9xF@tFbFN2|qppE`fFT*W8 zo#J?UT*6KGa#CsO%*cKvwd{;r=$%q$!=-`jL4TEoDFw&Ip*A-<4Ud^&F@EnG@$W{T zvgbdW;rfhfNQ$tqFbm>KI~?$&)4@<(TTe9Vt#%!_os5xr)xP?^bxY~NpsEG?@u}f; z_G69lQA*c|WZ2`wGMr2JC+c$(4&16z+L$w^g%PROI<0f8+*Z=VSYxQIjQ2L$tDD|r z%}9$=k5Sg@xsFh?MdXzGSx7H`Rv`Vw8N|A6wA}E>LhJjg>s-cl3&hbnk+ShSlDyp1 z$Kjpf{r8{|6X-a|LrmTHSDX|CpWXt8jQA*#D}fObT||7-s*0rrzeBw8f@Q=Jv_!AP zCOZE>KRfna*v0qhK+z202sTq6)o-p|Lb~CTw0+rs6E6{)q{mE_tMSs?E<>JM@bB%5 z#K2FyGmL4qAh-=adxQV@b{kgkhk~V5-7#;%slu5+2j5|Mj!Vp z=X>x-*XyBfX_@1{8uUsup{`zf^kMnjnqGNbr4sT2Kgh}A4(@E&o}IfkGA}b35a_3c zSe}fxOb5SX7enL=_r3Rnjld&uC{YLq385eeq5&^(_4rPIYhFKQwLpP69*%ox1D zMFw8CZm)Xe%Nx1t6`$-z$Z-MTlzW*@lJ%Q)BkI8uJQ7Rt)~G;LaG`od`$bh(R0=?d zfENUj5J4E^{Mn|M6ymTzQSO}+Dn7$B5V=tQ(m@7= zgR4#o?=Oi40Hh><5k9=(P>KEE#Y%qu#SRm};9>srTrbhxB;-p!!nd_07ld3dUnf2} z%@0=jPRTy~{oVK7jsQtQKtp&e2D)TmNmNZ&=ayN}#C-iGGgK2`{aeMlRam%)v(}gL z#5D4S-CX#Rt&98Fp*ai;ERE3wb zAGYz!nb)$4H2V0DPf$}z|E6ZA&}QX3%`1$0#({Wu+uWX$06y05^<|egjN7I+rPJUJ zANh+gJ=CBho;`_}-1ySKjn1(a!Lh7+Ek5tR--ax=m6iA)NJ07S(0c+HadSqhbJjfU z8B*o8(zKl@>BT~Jg;U08VI=mVc#iaYEI-r8CbhYN*B>Zb#|cmKdI^G9Hy)hxAfS=I z%@{-;%2B;iCo?>+>54_9-KKCzE(Rv#p=hEm>m7{4i~K_hztm8M#IVc5m&Gn)A+*KH z=4}EP5)#|rSiQ`7kxzFz40ZN`-HqfMW$vsze)v;W?PH;W=Z{r2-$t#p-&D$PE3sUL zZekz`A*Z#yBk-fIMzR7FSm^u*^vGH$hH*M0GB|n>dulkmcbu4k4MR^pDfs?_1#?}l zOHUerxI(Cb_=E3Q0$T4Bzmriqq7eK=`$rh5<}IcXOhGrsbXiFLr0fVe724f_4PoYJ z@Ze(kEk>khId~w~^q|Eeo&Y{2dbi`;eNrY{gwTuE)!2)ItdXNY|JErU%EDCcF{gIoDNqL$0dsMs^X@qeQ$k;B4}t zvZH>Oq{J{xF%{}g?MG{DtktcvF*?W0*VUO8`SyUK;4R zh$PBqG8lDV(^u2=^Lei4#1A5KG^<6GnW-w-I=}S@(UVUZckW<`YV0@3sA>T4fA;jT zAci-PHVNWG+DMm!HuLe?CVcFOLe(%=fTOizmZmWBrH(%B8QX9QU&b6V#3}&)-P6XG zIU&Bc#PL{@a;S#(`^YJ#5X$?#=bXesCmT*wCrMQsi=9MVk{-Atu`ED*MO~!<_5bZ@ zI_{$`JjO5Uuu9@dAnEg~oOIhBWDj34hGG2rpwf1);E3OENrW;k2qLVo;HU8f1S8Ec zh-{tkEwmuBE%vGY!9^%fkBTz)(K#a9*_I5PIy8)U9A+A19!vNs#AginYE1Z^l8hH3 z={52{LErfxXSDLf=!Ful50@3x&t5Mzz{)rff3xBo#t3BC6?6qQ;9&%j9w+$opY`^| zK%O&C8QpO2J{xGh*v;u_!}1yhT@!4f_Mx)Q+J8o4cV}I1At9BTKKX4atDuYo4FLbM z-e9r&@016A&@{@b_YZC8IctHTHuC zYzn~tCORB~j539J+zMDXc2Kp)c`4XwY7(j}Mox|V^a;52lx_5hHS&ed32qa|?mZ;q zSq&vY0RB7C-ci=4*ylNLg+<-DJa>~iHmk&+$Xt3@Gc4XfBhDtvw|HlUCCKTSbg%W- zi0~ZnsA;|*#Hth9{NNqHB^;HHO6@K0Ncve7v@3Ot>$rmZyO}*ATUYw~daQ2s^dt(u zktw#a=TL8@3nhtPzbytIw;ZD9JWK$y&`fvf;vN_0(iziqJ@AjBr-_tH{DGI2r=WdQ z_W_lO54u->{q(afC^~o7k-Wb19t3#@?#aPp4nfC6b)4U=Co^@t!=AOK`S#+f&*f7w zV3^p6fEz(Ne@JAtZ4U`waa zUEaCJm-}A}yeweV_Bd{0(fgwxRgF*k*%B5i9eu2hvBJl%-9ChTp^)Y^&o~|;O}-aZ za0JFR8EVdGbkx3oO0?A)%9$tNWYzR76idvheZ}hphV?4z@LAc^1`9^bcTWdP#;)xf zLkQd#ivuhH&7323*7Th#((`%fUU>_Rii+OP`c)~+@-ms~>dA5RGge!BHWO1vgQlxx zA8=eDJGNkY6$R_@1h5eO!}j#Z@_`ePcs{5;=qxu*(7ZPRa=U!ei6wERUNuaij65Y( zurB|!c5V(mdKqj@36Qh7pF%(*XDoUu;dl3J0iKMpI6C1a!tm>zqn zoYb$@;}#-izn}ZE{dheF2SHvAtui76FiJyaF8h44EYJBjlyb568^8MtHuhUh1MAJs z(0I?TDlN=eIVc+WB6>!*cDk77IT&b}(a9~a)WAhTgoKb@R##Yhiq|}kwb*>(hWE5n z*m2H9N}n6jquZZR?tqcKD=TGr`vp{TG>wiuz7BBo1T+eX;6z9kmHSLn-tkI(M$1@D zc?Uypew)I-{~4BqEkobvd2tH4(8>Ad6{Y;UNZVeOtRMjVx2ZX4poFZSJYV?v*Y&I4 ze9(|Q&q*FrkaDr~LLMo(^rnGI1Csc407I=xmSVXeoM%O9gB}66efp@>x$3iiL$s@zQ1o~o0X#Ia(_quP+E(N+z5`}|(<=g19M>aYNf2QRQM z!7qx+iZLS(_mJK~F~P3t`xwT2Q=!W@<`s!VnxCHzLDWJw9;ZGGQhVv9sdbw3V+{tt zjKK>G92v04-v>8I%iWr^`_A5LH1K&t`7JXz;GzdxsdX@v^6l872;!TR1^6C3mh%o?TQF6?hf+3jTZqmUx}_g`m%^P` zx7!E5D(4vvz>MGp#to2f#O+@d5|4gJ^?!Lm*7;r1ihDQz!*?UI^ucCR$gj&G#QbXSNgt}8 z8122w8k4%o)fv~JHz0IS>CGi`hqH$)U*&==mT>E<$1)~0HeCmKaAZ8i^)&acx7CNf z47@ywJ!?sFYA!T{olBf;%CMXAe%i1pJcMLR9#6v%z&sSKZ<_rSMCDVSD?9R# z@e1-Tl+hJH?w4s!U3q6$uR@9}eo;IptNJeUuGD*|&chXg=9hSH8WX@osTk&mlt}`) z?=h6C;?Ix>q~cwR1*|kD(slWh^r)X2j=uh0T;hq-ZMk!__ib)If*>8?lmuG>nEYPC zIxY7Tr|Q=jPGbAfZ^%H#(;<(i(KJM~fg|_q@Q9W#=CS$#FU$9DKg(`cQQ(6hIURk5 z9s(Fr^4vduQ8zJC;zr$RR$8Je?TnM(3yedBkw^-`Q0ZxilZ9)YkMuHreeUM?&q7Dw ztN55>bjFXsyTF!@C&WZekUhNM%b1SOdX0RVuuRI}L&SBW^`0X}J1B3?w<>j*`PG}n zVag}ffO@-vlUI5KG{WYM?X+;F+RRB;F zqm#1ajrd~do%K};wX0FUd=Ep=B`g7bk@DU64(aLDgG8FCnLrxw_`Al=nN4VUnR0vp zJr)+iZf8$y>?$#!c5~>G!OM?mFwoe-EpH(LfX*Z_PIjw7JZZ_1e_4fsU17bZ#*;n|-x+)m_~3b4OiKl4HD zQBxmz*&OD{af=rSz%t;=sbgbmH-yPA4ieQJ&i}z)O%V#EG!AR4Q#h%9(lgb_ASnb z*Vz{>n8=||ajIA2ETq^&a>zRphM!fvYr_-3%->aMM5R8CXI-2nzQjvbTL0n!h7o&_ zjdjvMl1Os&*zj%W8L-`grVY7G@$*8&Tp{}y05m3mDOEX@RNy)5wMx)}eKO>+j%AkEM1w^w*$|4uXya2q;14piXjL8s=? z0ekVaz)fqWYYQwrs-hIDR$;){VHouDnm8=SCp&28F3&jp0!I62q9GrBy_are{*$7L zpB)A?Z!e@^6UB#*E7B9c^ADu47Ce`hQL~_JbLQJEr2t%l&Vsb$s^I)0OE{s~hz2GR zlxy6ZuvJs8rgZ3vL7@o;^GgGsm-x4_y|X#8kXw!V#x+r0+YmvU5-(vXK*)%}*~6<9 z1T<6$LC0s*?Q9rdF!F7kg}6EI73>er(^d`Nz^a_;K5?CBG=qI4D7#o=VpFe}=UNIL zLM=%B=)w}v*6d5M`h2d_A*U$Ft^}g)+%gypb*O`mhYQS$$?k=oLb^+_U+SSZc%YXP zcQ-Qs0vM~t-!`cj0vOf*syEe7-oUVp2Gimz~ zvz2nDQ8x+n{ooD+S+VuZ4HLlh6sM}AK9)1(?%coo)hpQZ zFXBwp9Pfs>+>OrE_Z?UBl!qYaK#3|E0vJMmzP-~w;c>GZZ~WNy8@Vr0-my!D!>oox z3Yzt|?C@_i1s2Ev}=)yOnvUrp%`aE>4UL} zp_X$b5r*of($cY6K2z@;ZqX=XzBy(qM<+t$WHP)l;ICIO6yEs)l?WwLx9 zg=0fs#9@ptJX061WkbEh`$l=}hRQ~h1>l_wxH??IM%uu${LMdtPc_sHpNu=Y^J%&J zpQO!B=Ik}lKO6Z*h7&MPNj$cX7=dUT>YRqj4CyaUi{XudZjyJNJOPUL1-6?Lf|9Wi zeCe4_Ex6V0tWmy#vW^AN=wrBv91EPG;bj5SPqNveLCB{LY`1PX^#`pMcpHtx&lv-; zXm`dB4`U%oUS9|`_q4%qc#84c@Ry4rw{!eOIa4q_7vojPYzpZ)ikZM796&d)c=E0F zuy?C9eeegcVHgWOEdXetD`7Tv7RQqo=~PfwT9+fIMS_h{5&Z&-ac zo_0xa$E&e7_{FFJm@$k6wwo7=xI4INT;Qa}ozSl%&Q&}@d7YB=F{u{?vRLO*j}_lV ztU#fi80i-w?-~B-&YDV20Q7{GWwep$)C!W7d;}dSKm0nd-AXKMqc4WD7`9wE3ct-FLmsh>$e71%t@ii%ozHj z*#Nd1n+ZOz%DFzCY<^z3=5lyy!qkzu0d6vQK@cK>2n(^u-o!emml<|k49c;dr01ky z$e{gBebrc5v$TnK{Ckf=*9*SKeT^~)L>|Wlyi5V?ul2?Q8T;OXHJ2hojhxNtJ>6v% zV7-xa-%U=viRH@Gv5mZnhLA5FiqoixbnIO&rZ9N?34l@HMYuSze1jXDb3UW)KXiuY z?2iqQ-6tCtIv)S_J@oDDSt&bidc>vDxID#Tvk8`S>1Q)^0O~LE7K53$i+=E6^OSdo zJdXZ3Q5`+vK94g(=kjAR%XX>}Zk9GEwKu2Xa6oE5K91b~W(yXe@!$o#4l}&CuVB&~{30X!ES#}Z)R%Sk$ zwies&l!!S|f)+S^8W><1`J%NWFeYx%D)YX0bm{1mnmshGY7dd*rj<@ZOVtv;G7tHGN zS?f=NX`xg|cV&g^HPLOPvz3o}Xa>lZA*40+A1D}4KnwB4_=QBBch}8&>#yGQ!s5Mx zb(%~9Wa~=vQ0N5U-oy&-=)6){)rr$ag>O#{rMN4-|pSdprq0<-CA;?4WiW|JUz*lmV+I-&=pr4zuJ9GfPjEQNp~X+(h|}o0xDgSBHZ_k&vV!B{tfT? zvgVvM#y+vnKATVNy=tPy5_4Ca%2yG`g3_hC}#@;z8IC)mvs413Zc}gYJAOFa+cclj)x7LsKo_P=zkwH8!HtK^??Pe-!mLhtLr6^=OkTbjfu{D)mbY!TTPe4KlF z-S=4Y+KI;uSMO61ywm@A-?s|`6?6X0AKhBErLTw|A=a*{$V#$3nl<;gFj1Zcka6h_ zNVz?V!$M+ZYg9n^D9G(O&h1-x z`9@2g>z~5BXO%-9aoae!4V0xDa9rCX_gm=&OE_Acd8p&{Z61kdpY(hYViP_&5k4)r zrS*q|o%kC8J$e5Wrt2QM;wKl4xKl*hiMcIMC4+9g_F9V^WmW844d`UDxPR6pTfFMs z`X<8U4-%iGlQ{zC_@l-^#NX2PHt`D9ylYtl$iDLY+}1e4I|wu2(n@f@w|| zlzjV$5HiiFg?Q(=SIn z_(&yAj<{GaRm`4>8F;`Hgf~e@nhY{F`G|uPbUIr5&yyy4nCi4i^SQligVR%&;S(-b zteM=qADhg~xbWx?HojB%W9~iM0&ilATumxTkzDP8fN+xeBWv^TWfR=8bU1Bgy}2_- z5H8!|BVnx8#xRJnz3qzA-RIXXqaOLQR%DLDS$pYZ=SN>c^Jk#*W-+e$3ypwQUVBUZ zX0O{Ez4c0rhMYKB5i`RUo>6t{RwNkz9v~jO;NC&*Ao6loS&SD$X3Rp=B5;T-_CAFD zJu_}3fNW5UD;bSmWP!EHHFc$85+IU0Oc}jo!>h`-H@?Y1SLO)u4g#ONd6xNZLS%~n zD-$&2=cn{RmNgm*-=hO?Sy?7awaTzE(VkEg_n8?J}ukr}(Uy?^IUuoBEg znNIW0Waif_yMSep_m-G0Ac&AXQcZDuE^jvKY}DQf6#fT#<3!*9K?HeAAQiX z-mw;YSEL9dV?wXC&k^?$F%|1(hFMK7Q4s*WTe#f9Vix?E+@QKxaPaSwwpC=s;ps<5 z?x7+=(Prx{!Mq3(JYePmF_yz7(0Jg7Bt_{uT$SzlCa|p6wH5&#Y1;ohX&C~*fqN`@ z9N>sg10xTdQxsDqsuH4IxHRsvC?S>5vDLGW=zlLi#T6MuMgB4#-$x2x5jZs~u>If9 z|JA_%)xiH>YJdg1mK-Gx;Ai09A_Ufv!~N&Ra7BT| z2P`+I0J;&P^jo8&{W441j?<4z=%Vk-z^*kLf{KtN)sA!2sfe*Ck`vb2E#!(a)=aeD zOT7!%L_qtrnPUklQkj^A{CkJ^s;P!5l9gnQNnN2XC|tw)Qu+Lw5-)(^&fH;-*VGDm zk5BKf^h1c{H4{pj?F~@TGJH+lKUj58R>crmCe;C-ren7m-9T@twkFgp#rN!=QMt|V zWX}V?qubI`ar{AC(1^{XVRNl#MOvZ-S-s13%{eSVb9PR?+$Y->w+v1VstyYlU~!F4 zo)2?}dailK?C&hA4D%PYn@cr4A{jq>{bP`GG+wyvp-0=o_rAw#!V+zv>A!o<2$$@8 zv*I2Pa{3>8JDIGjBcURjM^7smgaTFtWwi-55yVzSag>-lQBuK;?DI0 z->%%ygY-8Rd$NcPYJ`KTj!pEIK5HTW+$&u1M0tG)6Ap6Zwsvm}ZX9Ue6FhF49#8F- zs+1=_yy80T59x|PKa$T6)mn{~h)Wtbmu}G5%UDae5sLlLCTif|UQ2$#`Jz`&0^PRY zaavlR0+2kU8vcu8Jem1@s6Mgr5AdD5 zqL>Zqk1cE3bU%E;G}@Ow^S=^0Jgi+SekX4c$C*_2r7Z)U(U#FV|MtdU&oSC>AAK$8 zt#3|MLlehP8~J;Xhi!3YpFiWSak~FVaVEOC*t*HKvNUvixBf}qcWI393;5tI)X~y4 z!>G@buGxXp@YmNQkKM(+zlPWp-xAZX|II$yR(|051BMPq@R;43u!m&@(E4YPjOU^? z*-h~7#$Sv8?e9f9EtPoBmmU4X)R6mOXs~__2qD@v3z{kGB>*8{s0p1k3qShz(rK3I z>k*FUa!(jO-lFY$F5drsaNpfkCanHG1y_+TvHBMs0=0NywT!d2n8L@}=EK}2XO&Oz zg@mYn^s59)eWlM7C|ziilB+%SsNQW`NR#ycN)TJu_~Jp?HTAtm(_E~Jx#}y6Y-^LQ zArp=?WwXu!LR&h1NdLls-vm&$yN>WK*{&(mNtcRZG*28Q7-IXSlC*__W%&ROM%mD- zRS?Xv-3H^NNEx$3dBTd7L{&sc2B<-BXrgS3wN`Y&Xc7ciZF>K~?uR#&8Efr!hri6} zLNgZPQ|=~G=`fV&6>It}v_$7?dHc1V4KK-9rG}07^O>G-uRM5_R1;;J!`&?Ir8A;F z6RPdyI$r^+&AzGI6AH9G&`F}|;%`_^(sH*?g7pV@uA6Ioc6Gj|Px-7G946k~@=mJO zsVy^~*2SZ08+v?N;G#UMQnw{RjZqPkAyAD5``Wt3r2cJ9eeknP-@>pqw`x9%JiSXk zD4OzaNV8~uri&X*G8Kv~z`rF{dEb2_^Xrqwra7;j2I;S2uF_{->)GpY#dDvqfDc3Z zOD>Yo-W>?2ab7_%ce2L2)ot0;?^3WG`lN7rZs;!l@al!cL4l=``ZKFU;`IvoX`t;q?Q8)?kYD4G@IZ z0Y*^pqMuf^5JFRuf_A%|W^sSCU5708zU^ECXKU-iz|_)3+vkrm)f#l_)*i{QW_)(b z-7^K{??miLi!U|zj+gsV*U^>LWm6wAcB*`dgPgrLm3srV+a!n? z3Duy^m9>V}g4wuw8;_n#3)#;=GyM*llmeqVN*4shV}|uB7REKNh8>olSy>8MECxw7 zmlwHmWrjc5h6a1PQMsGjWFAZ9L zb8SfaXixe!7xh-EuM)?8XI!!G2Zmqvx3sKnKK4g}J?by-EuC2+KT2$zYJ2K12o%#< za^*0JH5RPoawKUy@T7;DKWqv*QrCmS%Qy3Ng{^3*E9UR$Br9Gf(u!g3pg|aiy+fwI zy;`n49qm|JQIx&_b(rpaKohqQ-<7*x+X!oCe9>WTLix~Sw_vOajGH4*gGg*fLWP|s?0lj&!9ZmP0cDAL3 zL0tO8A@u3c@bWwfJ>A?J@7!~Gy(GsZgcfw~nN7e%c=^~v>dNDSP0dhJbnmyLj*LB?G z<{->Wc?e!LoK_*iNC5PTkv!{(jDI@MIcN+@ke8FuveqshNAeu11LJO`ki@QNCa~U1 zWkWE79IXqaC$H~w3vpI}smA+sN>XsIYCeH_9FGu167Zhyo_qRjn7D>dEmb!khfwJD zRE3B0S1tW9wM)Mc>hb%;VVPL0EPnjFzn!VPdgu8M^^@CL42iu2W_lR}UQ}s@MvdDX zL~mH|qcK@rZ<@CIIv5ArQj-Ln#C@bGv`3Z#q^Sd@mg^r8h3C<&8}dSatt&jBmqWJh zS|cv$9S$ikW2-u-c0Cjb=WNmg1w-lWn9^J~Dyy!8magfSuAP^z&zG*Hmu%Y3spJou zI^6feGxvojuVPQy*IA6`4h!b~NX{Jr`}(=&J?nS|>-aI?xU+WQz~Rt=;#>T!^|yyP zCgH*hSFva9Yl~s6@$=8eCZ6|QwZ>2G3tzP&fG_O(4;r60)|X4K^j)@+34QK4es~9O zS3$f=^LHSLjSlvYBfC-xF?Jbq*5*9gWs^Dv+}ryKmQC0D-@^CT&s*b{_7xnOu64fM zT3!nO>Fd3`BzI~Z-(wx!URt&Bhu$t+WlrO_P`B=MAeDS+^}1G72k9=y^+WPW()~SU zSH}#!xV-O6((=0c>Bk|j2Pg(~QbtmyUhlr1N_Q%Hb;a0N`@Cbl5dAHcXiBO*ia#@@ z(*rSprovSFpg~I73tn_B)Zmvke*Q|3S2Fcqo&WT$M3s$IkPS?tDQQs(7GN^SOT<7I1l)hQvEM+E*9vcv_0GDi#&m5k zq7C{CzY3T(-Drgw36=VRhBs2zS(6T8%i|Q(B-1jS+OqIR@VTMNCcY7IfT`#d1jHDB zPA7xj+9!R8O_&GC^gsn4FkoLfBveHK+E7#7j?%*pDquCn?|@8U{qb3M$?A{UEf&#%)|u!H(t! z+k?brj)R7M15iFB!kS?Z>NbRC17jQnlZ3nm2AL246opnt&Pz96wL>XBgc^K-^Ts%%{L4rssh<6_jSv6_6O9eN~^i0I0_kYs8LhBBbR z@KT%S(dBQ!faw_F;LZAfs)kOYB)FM45|}Ot969aACMi~NP)+m8>ATZPtYCw3_-)ip zIuHwdh#7k%9*{O#5ahU8mckiLd%9Rr$6?M*;2yCaF{wtMoOS>ToNyHkeVE|t{W@e1 z>XW=$n$Gg!=*u_el%67|^AqONrGn*ZIoDF@mNS`yuv9}tvVE<87)x(?qnXK*j5WmI zd4s3WyX#nU?Sp3>L6g(^j4L(aA#VgvgF+^|?OYRSM)ixV;I1M2oNBUJ{F(^`M(GTr z%#T2*r2IoiEg~bW)9LY|bg;2oF1wXWX`XQ@AzCT{oyOT$w%5wOq9vLg*iYgCWw$r6 zI=B&7lpXhjEnORDXiH%PLoc~5f1KxU?3c|2EFf2TQKG+J$g#Wa>Datb60b_(x_aU( zzXH3qH2HepDGjI$s1Pcs>!_eV(9$brclUMwl(kuKt8eQ! zck+tXca~AwjHk74y6hhG@PFK>6dw`})hzuFPWxN)!jGemG6t8$`Ob<(gGk>srcUn% zYOl_^u}8dbvRBak7Q*$t-XgVhdK30kq*chvK`J~=3oR~Q%h}dsea_z&^(&NO&`Zl6 zqjKiPkT|-?-RJR~g~f{QXY2BDve&z`r(%{qmfxk?dJk00o}#xu)|++}3gL@65)6pE zeO^T{J(*6O&kLzE&toLT5G(2XjAoO9fB;EFili7VHTB=uk{t>vEta&XvYf$fTA*5+ z(eU&He|C1P^sjWxP7Csu+Wh97ALZFd!kOs-4J`fe`Ny!|ioo>usy@ktvLq7?FAWtJ zgCe3y64a3E#uu?hw}S^?-M#h?`f9Yeo+zvDei^rHb8Cc1P2a>4G)To)#JwVnV{XaMe#Tl2) z5DPe1vAcif9z)w>JjW`EtVdQz5W5A~7&x`MUO#bMJ8$M0YOf=}Z!c((Cvf@aGy8!B z37tAuH&1euLGDyTrQdw5top#gL5-YoTc&+i#S~PDuOG*10O%W&95mD!SAeDCHW63+ zC#7Z{8i&uJ4AJ{^VI^(U$=>LsnGy<>`o*t8^{05&2}Bgh|a954@LNqzCx9&@6< z&*v7W5rxxhO;CFZn4C|S$gxTa??SmF z>1USiA+1~|oxnsMxf~_cK&LgHn@HP{|YX5+mRO!#;00jnCT!Z z?P5U9hIn%+HgxgmiymRSGJR5BT2|q~Ji2reec}W}>@cAy!?iWfY9XYQZ-dxYpL83z zPzg)D)TPX!D-X*!t3jT){o6a!#Yd|J)P)>G0*qkA8qVd6V~d}AN#i1rG3%KZ4$_6GOI3pLa=*s930BDcxwv`UF|qbS4Sf^a;hi_o-WT)*dz{Z-o#S_%F5RBp#NU}S zeHK6;KX-J^!XfMq%>DTFqsgWJBLyYP@8gHpckYZI{b6RoeE&_>zsXKL7}Pye?USug z&r=l9MD`XBM0R82{`hJ(^xOpGCJ+<4LhoyIweTybuCMkPU8Fz#=7aCQ>BNrD1)hfw zztF8c4)6QX{)sv;N3asrTY(Dv)}TkFKS1JMcEGk;^#wlI5Oo;wqJ62-<-5V)ZGR#z1r;R;ULOILYm5Ls$A5M zbD7LSf5L$2Q~wXns{%-YEvGi~t9&-va>})z+EZl|DnbA=VdJ@ac_OGK zX%##s7Rl9(AF7*cpN99+4$YJY(npUDEKy)6qTGPf026Ah+28Me^3wQ&sa82v_d%44 zq!EUa{ml=5FcqVyUX-C)Zm~Y;PiS!SWX}eGya58DBql?3(bmllRVTX>He&SR9|cLk zN|*dHB<_!0_$?Fpg`h)FY2j+AJnr!<1zMg$xwgj50@*)%Cpo}+; z@LJ~Zx3`vH<1WAy5eKnrIl>k)s)LTzjn(YVL%DyqVG6$?tz@4%g{7Wr<$N&$+`{-;?DV8LGx;8Nf0bAUTXGsSh01F1NLiP|p(0wc4>C2G#Pq#L4`QmC(ZxB}^Y<>e4d?p3X*WyDh3 zlQ+UupIXyyr0?hlk#gCI6%a!;Y+IP1a%w$$i9ij2V%TqJ@?p?H;z+)_5CIzH+wt_W zN0hSL?Lf`4Wwap<=7a<@tjvDLa%n%xa5J>opYi0N_XyMwEdQ9$Tk&Ipo93CdWK2E( zG(dWQk-p}yrp%m&r!0!!@bGb(#as7vX5xP4G#TMi{vkk)nx5Q&7A4eA#R(p|6&tF5 z`=*u)set4{{@y+LBjD5~=%~&RKx0Y-ZU6be6;hZfm*%loryNcEK30sdTX=vDBthe` zev47|Z9raGT$4(yzrIbo=ck(B+fi!gSKkc(o?Wvvn_mew|VvBu5faFAnN+ z!iua$2~Ce&Veku}UD$c4I0eC$zGj9#WpM;*b}(iV zAYB)aFHQi33*yj)=);Re8{OAG>Tcrb<%LujVD(~L~IaBCJAAYVfxI{K~+|F%)1H82@LbI1&gua1}QuDyhik@6iW zoZOiVMEB6g7@+wVxW3&`Pn2LNG4}29C`}X~FVP3ue>pL%G=#nH^GB7aLSt-2(HMe( zMcFub(2FcUYnk64`u@3Wa`e^sr}e>2VCIjmri=C-{iEm6?5kJgJyUK(O$>1E>xB8d z>IOOCk3m)aXYq=g`l(G5J+Va$v;LM7PuK`as!Crm-7W!fXhXkJoUA|tGgnVOrrQzi zVS2`$onCs4k_C?^dZ$=FC%giE9Pk+L$h`CEd2Dw7T=TBe^x^aPf#>lf&*3-m)t6&c zITL4sp)7W%X`bmtW3Inrn>rx-!sD$u4XvqdJ53!S`{A$lpIKn{!4~`M=hkCg&k+|k z4o5Z)pK|Pf)}IN5+Sr9l&;1F)erynDk9g0-zVSaSARXg&=CP>{Qcww^-?knbw;r3? zrw4eRdsD~${-d!bo7Scm+KZlhp?&AY3j9@nbh^LPRvilU9JLa(XT|&oq+8C4Sqo&z znsfX?XX3`-EtQ1$c>R|i&g?6MHeGwIpFKoeJ;ahl!=~%cYh$fVHj!rva%YUc+j|m$ zo9uj!2#>Gom_DQV-QKNW3NY9++TVfqTo754@Z`a|?{Y7%t$TboPN^LRx4An>s;FEw z5)47&K4Sj&9Eo3DX|>G$nyfGIR#kq{kCBZ}g{qHFF98!~-Me4!3`536jzr>I@Y_XG zn?g8Ht4{#@5f91~B}I|Zr;<{ZPLIR4(A2p`M}D~k?vRo=0D17FlE)MfGfovkumt19 z042)@U=*-#zzOr`DNezJH0b7-axdwNIOx$4WsP241L-ut6M*jMRneVemjOEhFck=8 z+iq{hBQW~70$~yWLqD>DmmzJ(V+t6`jS6}5b>1d)V&bh!>N+|J!gGdT`f3Ks)$?|u~#v}wUM!u&rJbk0{7Ia77cVcQw%SkgXAvfc_yM%q`JAes751j;P*iB10 zz$8hu)SSBXU{Dv>RJGLDHK~$8=c9Y4e!O+*pHBe8%gui0TeNe+ZNZ^#20LcRE7p4P zMsp@h2$DV%Md)ToaVl%bW`y7?${1xbVMy116g>i|kQ^pY1ZpOlOC18tk^}0(7z0NR zPet|GGYbl-=4%<7a?=j zlvzHU7*MZXwabxtdFxYg5Mg-SFjWK<(V8Zx#5~SBSt6_g1-2v+0oYnHYOtRKjt|l6 zF@hpACMD7Z#3X-L6PiF|svZkLUecPY;7{hyx)t!EgI|@Y8?+Wh%LV4*>s<`Sf4Ovh zBS{w3pMwebL}O3D$K_u&7g5hhK4Jwgsp||&X=hhNelRTH)6h340qEO!{aYg_oGq9a z(ghBGZqAnqm!v9TyDP!B1ps-M5zRCVbvbDjjl+x^JG6Q}CH~8W4XG9q_HcTWqePT} zizlVtgUy4&^=lb?fLxM_CK6}u&J7KCbUcnKpBGvTuyZgx0Rid%u96RTI}N_Yi3)B8 zff2^z9a3df#%pW=-!xypH#^Nhu1oTG0MNhco_Fc^$l+ZOhZD;qaF}faMJMbH&Za#9 zkv*Q?TSmQ%7DG0FBTO;Ad0yUAyaYJRK;Ti|OE~vfDahDTlpKZzp_ZaaNYRuPQ>v(> zf+8bcDm>ow7-)m(_OBWw4p6;fgN zZj>8VTEIu5*#JC_5g{Rl!Ubf>2#Ke+2mgcf@(H&67l=t1Ph|i^$B^%c?iQ&D0(is9 zs*AcIo&p{5a7(sXG2!U2Hdha^Ix}BNy*Y9pGt`aQND55I2!r)j7`=7sGet|vgRy7= zs=it#YM)Fi5yCf))ZbBy%_gl12E<7&s8NYN13RRmPK(~3L1A>o^5)?;iph%)!?Slu z3`J>!jpKw7$)Is1o`g6a&+c+r@Z=7J0(C^su2E88!11CxA8det4g$Y?y8c>sT@$iK zi051{{Yz+xMsZmU3h2hgGz-WR8{&4dG1#7W$yT17D< z0P4b5Dk(6&f7c|7*l56L#A7RO!axGbpGEb^YD>vg)*h0cp-s>~U{pd$NenEVuH5k+ z7+i(_m5!=iD92*(X56;j*Z@ua=P+Ge522RpuclRQKK&fM$OhP^7Hn#S{Pqw^u)anT z04UUv`jMJk!OgP+0!(6pA2i;-?JhKKHwNG6j_LqdA@rLQ7l&Cppj4NWL^yTp>A~GT zAyH9vwj_{M!Hkv?2^|0@mOe5?;RBUmdjGC%KG+aUp@~H*5U|x|JpCi7fa$-LzyXE2 zqHtei{tG?rb9*LsbYLX#yq8Egr?TF>A@x)IkaUrj*IeFGlm*6Aj@z37n8C@5hZFCo zNx}AqHRkc9EXJkozaj_VB_Jttaan26T!x@t z=VOS-MVjJVnqRyko$R3k6#$hPw!Ia=_=lwzz_kVln6H-dt7HzgZ-f8`s1qRHtm33J zHNcv8iL_Yz*a}HT&HVNbwj!?9zR&dmZOp~u3H&}p;9hZ@Xy;TI>zb{>geW;12MP() zu?Cr6u&iM|aJh!$0YEc8q%OrGk!U6g4L9n7EiJy^+E~!!tjQiBAansdv+J7+{{;c@ z?>kYFPGdN*m-?iMxtzIcenu7p+Qvqg`hcmX5;=UQ7`WEbXkIry7_3j3iZXA)wnBzJ zH}O%MS|J;^wF*$Zjw+B0N=n2)1S+vF_+N|(HWpxFt}B$FddmmNcMU7Hu9M`2kmwT? zDm_AU`k4uy-!A;d$DBTkqSh#(G4hiLBP@c$5{eRv^CnE-kk}h6%%eTY;6>r~u@T3q zzlhBQ4xDFHi}bw>?v;rF=^XuOzknIF|1tc&V_qV8o0Hm1gJ39a_|InojH|~6;TRd8 zUcXj3SyZ_w8`K8y>uE*1JgU?oz%L#y085$?yZuy=F)U$5+h7HJLq5=@QAAbk&&M>) z@5djNzAmQCgk{Z_Rn*q+Iqi!)>Ra^MYujrMUI3f!&3*AS4AfDrb(PEl)`?$64=0)z zTp53lA4?v03ulT-KC+H>UTeLr+ZD)|_Wq<=NVR}5u;NEhk>||S;2u*#V})W>^PL}M6QhN+xT{5G^oO^jJ^Eht^r%G0 zwVdu}l`;EWt23c)wTVCl+&~49W7_#r@|PqUw`4y2q9d}}FOD}K)6r`ourbJhNH zr~T(<``YzE^Kaq5Vt?#kvH!gN=SD^MAO30u&E4S1-Ea%wm=*nTLjB)?zul=0SZF0X ztoY=}85D?FbkGEKIP43?44&V+I%lc6$|<>uJr80jShD%Mf5zgo(%QbbFq3)UydFqr zorQ>Twp+CZ;2YVK!(9dHs-Ug8aA(^N>HiV?7sAhduaB^7Ar+_ziFfvOZ}rMKhWY$bVNJg5E}xJ38=3jQZ}{|f%Gw=%67 z>)TMx1%d&o=0&66V&2XQW{cE*E$(~BkEAu-mXa9*O!u0Pnkby6-8mY{;PIZQR{oWq zPv(4VZSN{pM$dpn1~cude(h{pha|G9){OrLXAs>;HuC0{XFsOKuCdqUmp>h9!VoN; z4=7DAcCdkc{|qVdi!>81dkCgB&-SAg9MUvlsvNd}9M3Q9g&yhpM9VqljUL!?JY(A4 z!;m_h-0+!{e3Qtl97n59P&q8X?>?0xO%YV#hETKcp{f!#h;Nhn2_K&RBX^g)R~XC# z*~u0`c_4iSQGAjiEwt1aVx3BQuo9kxFDXA(a5Oh$pfyXts3-JSOo>+Khc-G1UJoxz z(mwm4HNh4l*I&cN=~*!p==!72fB%DRqn+3By0pN6ae#kfO(%eUWIcEj1|jKRIog&H zF{$Q-$$q2d+0NO+-|Y#v9(&fV?wrU&^r`Tlz!y5JfQkRBe}Q4V5Qrm}5&@>sU_(T0 zdfX3MOls^anIR_0kix<41EK#DK>Q-d1ZD(FC>bhxkMIR$8|#-$zZ|}0M#E=?wM2v+ zq+iXp^-PX3UC=jpb!TO2c|lxvUFSD=3^*~lJ9{3_^xkhxEL%Cs1h%<+9KFX{Q<40j zE_tM8#>v#Q#W>!{$30}Q$hGc^Hiq%-RL!x*SFXO#H^Z(j{ab%h-Z|Jl77zLGnJF9& z&y`Tk{i$sBg%ft+=ExIwZ&`%3z=vZo68vxd=DJG+N5J`L>FJDz;FqV4a84~JzLFyN zfQ1MGP&Um3s-Bo|_&|?#>gn2fS0#4OBtr{pbtRneD(y#X#@SYO_IkuEm;ori z2$f;6o2TpfVKmvDKMLQomBZY_)KoAz(Bzi}WPwfnj+W`DisCM`L11s0eeB_UpjQo8 zi&v9s=Yg5|#vs=a&YD((R@G#~_SyL8+~NQU7S$U*6HN|bch4A5GStr4nb>z@bjsG| zzPWR7yHfdK)rlJ8?N|zZ5;Ofui+}<|Ho#GoP2SLM`xgRj%;*)?eXF7YA*n#s&+HN_ zr`Pg}d`pm#_lqe>%i;oa+3gAebXEpnd+3Y4M1Y{YNm`WO8!f-neCOkxcKM%+_s&%x zWSlae>b_;MfjCT1*08DDL8~^oKw*qr6pt8X0QZ;kNx_a&`E9SLByM$sd_$93Re5Sy zFB>HP&`FXxiLw$f;(7;(Ay_L8X`6thT~N0Vnv+E#ta3a&z#GUOyWGmr+L)vzwVULj zZE?VSp`%*HNkUg$=a^)m@nF1#!1^xR_WpN2oms3cn3~dzGX3OjWaA^ace*JbB(5R= zMNWN=xxpjx73rW9W7k8k3Teh6QsL)JI&js`P5*%SCQ=ZJgzWZ4m9b<Yv{4co6wX@pv)?D27SgOjMk1eMUcdU%5lhYH z*nP;t=`PZWnwZ*r0DcPiBKg`*@%J=97;SEqa@zq&*zX!hCz`qwsyM8UG@dA#f*NrJ ztVg04g5$n9%(@k>a$P*6XQFr55$Yeej%Rau_DgvzgHCmcBdJh9cfIiCw=^bagK9aC zhR4kY8NaEiW!Y3w#w*M?Zd9%I{)i!XsTkpzL9`NKU-kzj4eC6=s_)=>Q$mFSfIC~T zIK~9a4mkK~DBCoNA#4OH2CufY19RCNVQ3d*7N07d2?dZFddhchz|G&m;AhZFc`X~$ z)ErO!VX2uqr!6MP99`z9Xn43XGy@uM88D@(Hh+}inqQf%Ie!3IgQd07D$ykAB@Oje zOZ8QAXQdSkf2}z`Te7xMn|F5g_T;X~bC-R@9tl}{XRxwxA4Xj45^B(DxJKXb?&%vR zjeeO=V{LCJ*X$ejPJ+{&_fDSWOl-UW#B|cHjaVfd_3UivS=xN&;#u(QT;=cUY{|1= z)A@!k*nQ9rc7Mn=^X`M(PsBCztrKDTlVFyK)fbS%7iy7!I)BZmZG-)ex@Oe9;~Oko zGxlZo@R~W`Ojx+;V|#zhF8{}t*s)z+sIc5s#=i3`v!F{b-b3sM+|UYN2W= z*6>r;bK&ULJ$TQ#-4>D`2+>7>ifjZ5d;|Tw4@h`a(^=Xcf2DBBG@oQtRID}Gt(jaI zTmNRzpS*0%j34r0&?WlIOo^>7M6a3fu2qSU@@?N(i0vT6l1N`%UpA2ny7?x}@O73d z^V=`f0JAY=5TY$Y8-P$)K^L2J+_D>}GQ-CIus~3sA%Tu4|HxS>H~m=4W7SJ9VMpqm znxZaHsk#lt-*5pYyrg^Lt3L4h;L&6~yzJSbTU(}^6;CEze4w`r7-rrYH&5+3Xg)tL zQDG^QE7t_ zg;*W^8ue~hp_ZP`og5_% zMU(W}a&e-O{Zl`JF62oLiK$IueSa(wlTbhf2#)Vr>NUQ1xC z`;2~CHHBmTR)ABY^C0rUTdy6*>G#|+<>r4TQS zIZ!y7^*}Y^SlIEs~nnh8H0rIn6@f*@|5;F2RLFQM9 zxzx9-owEY4igrZ|CpHFJQP(cKDM61bRqHp|`u(|0QL50K;NcI7rSiVg7QooqMRYQ!#=!~`%2#MtKsvs1I7pWmm&YbLH68-LioT25(lw2 z%v3dBDF41=jsUYQex!@SzF=guah|@!&^|RR(=rBw`ZziJDP>Erxo8^T1-nmT=W2?e zmS7;v$qFhh%UGLnf2H#7vk(c-2}#$_tlr7x?YZgXE=gyH=O>q4YpeZu^{ACV1M8LF z`|}(ac6))OrCQJBR)0>r9=BgH_+Vk) zbGadlxlSHu&Vmn!TW#liqlSLmkrN zwoIGk`;OKtf!o+>Ho> zl&mCr3|cFoEbs$cYzP^R0ro6`iRaoSbWn@rV^)njf2zd3TtO)Oi+0ko)W_Z3y+4n4 zE3CFh1?I}hTQPV;x{&Tx6*YTvYmNVj0iyOD8A3?=MZrHx+7P7A7YC+)uk zEMlbIkkXxG0}C!L?0)5cNk~G)<0vPTkjSQDOtJCTz&Ups=8;zNI-%RJY@_(9>@&VB zL7&Ks$AMV)2w{N_uY3xp-VGO50G}y{o+;crQ{ct!vChqMnrF_#V3wxV*b||(>(b^c zci@9HZouc(eOIPWPfVY7&ptgjeR^zTCtSK4&c7@C>55*ivij-571>dH|N7t0T6^~& z;p$p=)+EAN$`1jQI}Jtr20rvpPaejL?<;r%mdm&Bif`eczqLtwHr5}|ujHF<&6x)V zvZT)mcL6lt?jq}@jZRm%PS3B0cRufm8Iti!Qb=cNKmfa@et)0w>Mz-E1jv53^I}uO z{{J&>+~n_6UmjFnR95YVu{a#E*oAY?*=$~sUfbBQlnVS-MB=e4{hkc%P>Yg(X*2zgbHW+8VzX%TaeY?`&!333&xo>oo zenuW0N!(U!q9+pRJ%L+uTORL3WJ)>neVyj3l#ILT0WuG ztsH^%9X5oS!oRclM=Q~nls`A6{8`gMEPP{GRC;qy1^qGnBVk2uPvg_6@HzP*WSY`3 zvRQ!p0YOVD+9az%0rgth32gU6i%>o8aalqYhX6gmQ;Zq-fH(=}xRmdRlJBr{MlP@< z&hQS|M>$X~0Jt~ylsfLgMpwVa97uP)aoIkh+JC*FPTAuHFV-x#=BpQ{Lol~EszjTx z2DDI8i}^>amEix$kiCZi7Xf-aq-Vs82Y~$5gb3){!Xl*6ls+~Rk}?)cI*d%wKaaq(4TwJTN}Mt`!w zNHrqODLW(U7D=0SGt08xtWg8P2%k~GIO8P6Q=M3Kcs@EwpR?MBJ*v&CQrZ6Wy<#LE z2kYj6UJ4gZebQ8gKc>iPFacQM=f2WmtJ{_)r-~+3qGX0_<=YetDG!<5Z>6)^*CrIO{7PqiP97G~5sy^E(q&)di~JRZ*B z+*GLDr|`InvhECRyB$>Ud1L8~bX}dqUDb$PZ4Cerd9N*O1;`Jnm4puiTmE=F7}SvCl*JCu$b4zv@GJ`)Hd;o1fV za9PS;1$TbAvGCQD1NjQlWEz056_kK+drMh998-;M*2gRwtFYL>h&TubV4G-i?%xp% zRBW8CQ(y*qj%?2h@mLrZ1O>U zSD^0A`3g0Qf!4yq%E=xB`Lj@j5G!!Y5>T{=Wp35~ao#bI0%$FL!=X)!K1ol#C*#RK z2?u`O`*>E(_J}!`a^sY0ePf@qe{4xTKBsA^Goa?$44^@|oazj5_dKB(V)cZg3vtdUKDSeUzT&s= zVzfSpE)g_O1_XzZC|D^}`Dc{Rak7D1?W*$D2SHQK`64y@jW5q?cN61{pLa)JQO+a+W_uFnOmOV}vZ zPNNymkHd~4{Fz-5rFJ=kApGFH(N1R%N@dP5ptU4^AGJ|TTAZ-q!&M*>Yg?MpLd(Ji zAYrYdyrlj=+FT`Q_4Of<`B!x#M(S8RN>pro`jnKN z32;|PaO>a9i%RSgq(}a76TbZ`RKm&!F^0Fqs&8$_B812{E>ixEgi-wu4#`m-mPy|? zoB$gK0JG2jL!@`8p3Uk5BOABDf6HCo{}VQtXvB5PpjYvMTnA>`SA-A z4ho`@6h4O=TCjm*i5=jP=0gRvDP9I>8DKM9Y&-?B`lRd-?kJ(#b$FtuE)a}N^$R%e7n{WUeo-liknut~whTyTsT^&4iuc~or14(g%IS!LoP&*Cs)ckvE5YOQVYG5?0<|K+YmJR63{Zs^~fkONt=L^nj)35@zEku_9Wi~NbAJ6+qVxz*6R@c<4qhS7==sAP0~x&g zPfi*%Wst@wHi-sP`adFofx)UvCT8s4vP#Wz3+u*~8{RjV029B3^NInXy<$o->V$lY z;akRlqlYXu%9RuczsS7$+uW*RL6$%a5Gk@|V#nvCVj)Q{z#wC;&?(SMvZj?qIk}@e zA$y?dD3e1}QU{H{m{2cDC`!ks!IX%NKfh|S0G;$AOfUW+kDMgdC8Raegowv$rH5u>7Nle>#x6d?>-a=G1~!&{i0(_WP}&^ zKgcGIB8tEJiCm6|oW*yB3dmRu&r45!QX#Oe^_yCb8#DBkX40ND>~t&*s}BDZJo1u$ zYdhRPD3sp*pgNF#!#cjxI)21Dz8mY#!8>wyEdbMwUud#M4;YHmzhr|sr$2Z;_VxML zA~1C3>(i63zTvY=*QQH01%Lmc%NlWE>To>k@F@*QSOqFj1U_;NWW-uu|8?iOf4EvN z7X_O0^QdhD1|Q(=J>3t_+YfKuf0pC>d%6E0i2nIpKxgaog+Rt+ih6G z_n2P($$B{-2CR?#4eQROo$QJ)l9h6j)Msc6S?aFr3x>AFIDcQV1}wgR-MMbl#ir}q z>*o*SXZ8gFJFcT-*VBe}EI>HfB!_UMLAo0Th7bf~=64y8dsVCe1; zW$5lMX^@ic7LXDtK|u671nB{e5H30vZfw{) z;3JQl+)v;A#vr68u?*>ml17Jz&O7!3fPhs+eiRPYOfW2sCkzK8%`(nqD%9u+HPVbt z3W@Z}___E~z&F8uhYTZ^O_0hHXjd+8f>k!tSh}ngb_m#628bEZqd+Z%QJVHyk!~OL z6m$&$)dcuISYR_yB)KhDc?Nt0D0blFKUX4w=F`YDf(i}~3*J}!mSMoTL=$`Pj#4Yk zIS&J=KS35z~m@TWW;kCUq)e0*N*D7wy` z#lfM;@o{&03NTyi0KJ|y55k-PT*E?FF0a1` z&~6n(9s>*XU|9=U8ODWy;V^KkgT;v4Cp`%(5`MybYoIdJfR+9yj3^O)!P5Pz9|nM6 zLH%?RNAiCwlo>dnhdH+3_<+ZUj;{?riHhZjw?`jy%useb9#lB;L~or+$~{86h%JqT z6SZ>sy$;6=IE$X%>Z0%vS!IOuq|-$Ls%se16WFXXhAtg11J{EMeG{)gAH=XuiPd(6Zq20@Kns!=P}R5yw%;ag&~&m+jW zYyzk!UsGbvY(Lljuzq*pm)ZFdDRZ=(_|Z<+%>$yzR446p*XK3H zWx5Htq4`0_^&OC6FvCR#5XP?j{`8&QJUBoPc+O2w?VVX}(a9Z?z;WQgp`i~>iB%XXQS(zr^olzG zs#4YEX#HBL0Aq$BkoK@Lz!4Ob{djA#Hq=^ z1)xCpfifKi5yIYoZfC$7Z}K%du*->?=lgE*ilK5^SZTIt zIY#stV>x~?tW9}BE2yhfEK?evp;>2o7@0-!44}6o6VhlB`@w*0Lp%$(nsCt?wODZG zK{CNtNC3xS3u7=0H96j^zG4=|r#%xts{_K#S7z9QJuar7j1779<(N#LN$=;p|6(>q zHf9{zR%SBa0x7RnN-RkD9grP~A5ul6u|vY3l55J-WCFa<3Y7R7JJnDl76YrovnXKL zs<7e2xj;xGB>#U3fxg(u_chBW8R$h-$r~p*&vKlnT9~}|Pd65Zj@2ej(r^6gmufr( zb7ws0tineRFV!m1S-ei;#7YWtP{oSJpw)_Yv+Xi5!V?>p-mi?qYz9{9+3Ul&R%|k0 zibbmb#gn;kAFEfXB!6xQ%Q8G|U+v=l<>uzsbEENV?=ACkpx^6^rlF?n@kkXZ^UH1` zg3r3x3{ZgeG@39y`#-NCaTv2q7!w45)1;s>xyeY!Nd{Ikz*vQ&6@y61N!GXBBg%-b zPTx#BNz+r-_uLbzd3hM{iZT=Tk#|dnS%>6@^!KXCP_g39h81IN`fD81>c{lU`%4l? zcizsNgEg@JKvP(A%52GFOt~{_?D{1buR_1Q><2xzA6sw99hyXmAFe@-D^zmq2bY12 zIV~6Z@k7{I>Dgc;0<3!X5t@+GLIC+|iZU=k7Kk7KT>{QT((mOT8i4>w{w{;nET~-- zeIyzO-FS0B|FxcM;P>>Ejlf74!_=~+i~6#@u-c)Ewx1fTL*eixt}yZHZGbQ?%H4lm zBS=Yss;`GMhC69sccl$#4pI89%xwRGiws|$}GZd%)_1AyaIri)!E zmalc(q|Y{bBv*i%rxg!gL&yY_ZK(`Qe8ybFVGO{h8Tl3gD=<|)CbJb1l%a(Zi ze@zjR0$=YPvCymT<*IST?w;)0Rdpdva7zf9-m}J!2qmjiHwAS&UTwJ^V+f%8LLU3mB$TekU!r1z(agk+(E&^wJ?gNkYOkeLdvXT|DwCg%b%WltCh)`i* zd_u?I3msIpDef6^3%|z&teMvV^=+>!pbb`y_``q!P=Y%2{QOOX_0B!MeDC$sh|)Po zJSGCC?m~J$UfCr<`3HGIC{?&Po-7yD$1%}NfAiYi)14T9QsZB!-@Z5DOnAQXC3SLX zq)F$(A@TrmA8brC<=l2ViZpn-${lbow?=h9g#KU*uOGGT>QQHx@+ft`ZhOW>wlF2AIo3s5qsXWaY&Kic0F9l($)@9eCfcZ z?r@K+RY=c^r=PDZ{i@)s@)@6TVL9B4%(_117VCgZ{QGC|_2C@}K&R+8*I)7nq=H|M zYj0iC-B=rvP>!EZG}bx%YRTac!JI$;rxO_buTG$Dk#l`Y^!4)*%W%q^YB13j(-M0o zdn83Eg(zPAd)cA3svv6N{?A5_jt?Zf2_r_{p>|d^vBH}Xt{2=cgS*#SS33qN10J8{ zy9Sc=bc5a`(|mLBE_*I=n?m=3`6Ysb!#|fjO;M}XXo8xMCLf#!ymd4>{)rzYfas|S z%rZ#|4}{DH=$n;$f0UIZ19hLQh}2{+-=}OKi28-&UzqUVjftu44dpw2RgcW}F)I~q zT8S7#-5@riQvtvr`zaYg7jF%M(ZY%`A!(;&ey1htvG+AQ_vFupYv=u2(v~2(m z2nGys_5{o*3(lKRN--^O${nYILKmSEm0ST@{%G!=QryF?r2Z95vG4#B*nomq@dt-W z5TmW>zy(PIH)Vvac(z`LOKfgwkR72SXY+<4Q&Cr>zM-U<0}b%>dA@7M-SpFPDIw2l(|^Bho=hk1vk~o_O)+7d0TwSXyPU>LkEx z1jm!EF!}j@vxwV}!wZ>OfU`L^Wj{w9V4@cVM{SMk__G5; z&U(wdv&#U)fuc+2fiy>}cjiiV!=+6|%LH@FYJ)|LOK!5#{(G^tmM_BDr(d3D_|!fT zZi;f=80R@@Fbx?ac*^pzKwo+)wao@T-xGecbaF~$mGA8B>s{~Y!me86cKEu%zL`dV5V$yOq|IB{W-D znZ#GYNj3X=DF^pO* zHD3poOj%_YU+`E34kTB$x~*O!eX8}IPP6oy&(UQ#Bg4e~zZ;;(^8ry?M+Cq1ThsNL z_b$hrS&h51US77!jt|E4iZjNaALc&_G1T2LPvcklk3M8o5=b?aDm&3XHNHwu8MAU& z%{b*wUb%dk+*>)XQp;wUiJY9w<`Q!R2Y-ro?TW;h6IZbB#lyg8&b5(xGH%=`p3D7^?|g$qI1 zWr~ZY^Na&XuFwHS^Za&zn4e2y`}RrMjrl3%l+Jg*-Rf@8NP89SPT$4ys*jrTC+o2t zel45&xEPlNW9H;r<`}>`$$O@-3|P!?cel8YYp+h@+=8SqxmbE``EPssn`d<_}NLap(I+X?k5K6)|E}O{$ig;Zhfj`t<8ln-V0Mx6Q zwHlcpB`Pg7c5C^|>G{i{!KuhHOwpow$nNy|dWQVg*s$n%Hi2`hI39f#5wO^3#9P!duUEZm7^4!nAC zbj6aDS+DSPuRnU}K?mZ!hz4Ek|K;4)Fho`lyKr$1d1d%Isca1qUY<&yU7*P^%fPpK zU}VlfU%swuFAXe@ku+kh;!@lT`vD?!m=!oo0z}vg13ZgiFJ8gGS-=p3uyKr#8>BXf zIh2c%;XNZDlFrHh#$^T=2x=(360Y?8(G`WcC~@2q7P^55X%^g8x?hF|S(M{SX(P_5 zRXB0Tf?gS|RuoVO+bch7YJ3`Il>y>wMY@S_WnH=#Mv3qu5hRpZKuP}&j}rMao{(p8ocAHjC~#>y^w{Wt9=(9j zJ0I?~5H}rPqe94p9rFSGKnNvN?-PcVjRyfb?JkG&B+|y1k0d%MMW3Rp46s1xfmX8A ziQ%^ZlTuHD`vHwf8YPTv2Uv#DaOm)3fQ|z0u8|q}3k}!%%kI}XW%{nnlCg!<(s{x{ z9R!v78co3t$l`OZr9vFCjZ+#C8AP^*(i5PQqcedlIE)oW2uE_s;7Gln=dX(#VEP*D z$liAW3=B*XIx>;9SI0w0ZKK+-X1AM!^aMy){9(X`fWt;~;yAtZ{-RtKq-Mg|Mu6PO zbbN#np{@Ul*@$0?glpe=PlWrMU)*bAZ<{61lIYk=C>$f=UY<@|(lT~s46glz8L0*e z{lTT-#mfGv)mG`Zv$mXdn67x&$aNVLmkR?qt=cIsEC#S}bgWN(sB#O2Bk*D9={Go^ zWO);p;_Ob_Nwe3RZy0YvygFcVH3u8|+YH1Ow#Yp8L1tqgGL2)YQicrr5HW_&#hD^I zT@8*IRRHud;4jO*mA9G`qaVc2f)t?TYW!N_!VDYn!^x2Z0d zX=Apf69=Esam1>UI|H}ww|Gvi_j1aG@ltq+cwffRAx%9bnP)lqQG%sMlqz>iZ^lUJ z4ts4GTp7%fk0A5d6!c8x;W-C3J3HnX?N(4*c&QIWjTiJ;|Y6_BQS2(pW<6GydMxg>IwFp>rw1F*%=w zgBN+N+#gi&(YDrI>QadN`)~DXvw)4oqXDSnczxzXp}(+X#06`c;A!TVTm8=ZL`$?+ zoutr4ty?PZn|wLFg=?0ZX_vQqH9js4u45siVKpg)cgmGnZKV1E(f6m2OK#{Mlz)@q zWS_>3;mRqBp5hnR@ymwkix#4#tRXPJBD+f+Z;|&5SluzFU}v{g*k{-xvoOZ$Go|>G zufj8Iy3a&`8p8j-s1Rpg7+qwHp@o~3?zX;E!F|_Rydbi{Kvb{^3t@EB7Py$@G7gQs_`UD4I+GpEe7!9n!Z0KvCoAw{56ys*ve zkAWX6tWCrV-UqI3WHcF)WK?_(Z08#l3Z#0*n|`QE-x1K9;&N;=dj%stiEN?kNcmJQ zXLZQ6D8QS9r_%9i@I$@nsY~;*-OdtF+R_NTVF+W50KA*Nk-5HFfOk`rgdvEv$UwbyIaRrrTKv3+X-HE*AgvEt0KH(w*lftP+xQYB~;T&NynLoKtu8t&^n_ZuF z>2FLot29@;y!x@r9{YZXkE{{b$HX%SW9Sp zCCwqacF`qnCR9o-8(-0{vp=}uUu;)#q|PwHVfl>nN)MngmHE5&JwQ`aBJj~uo(xqEmbXUy;$t7 z|1|iF;*HgcC@lJ8dlfyIzm`dZWLR5dX@?ll)kj1_dD%d!#bs0>XE(<)tj1HBN1Xvs zni43w6Jhl7RWz=i#rO`$0HlqKNTKGF3RFw4-o1ZOx^3L21q)4^TR8kWa0QU-EEQiS zXns<0zn7mT%E*qJNYqr$%f>X8f<4*QbYtdN^*9KtdVMUhu!9*J=#UsSeL|J?fVVhl z7K+9-wedUb<4Z z-Wo5ZUiIF;{bYK%(P2!or%Drfo^y!KK<>$clO%dpQ#hrTrc$aBX8`X1@`3B0d`ZY- zPTc075HsRNWx(I}h(PA!FB!+DxX&OUT}>t>V9WE`EZsb44oD&1J2f`G3=X~sXld%^ zNqattolC>~>oG~)m3YU80Mk?hxjAMJtqBRO?l-dfCc`c&bw01m_a#)at4>^g2E1X^ zy0g1hb_z(o6tLCl`r&kGr@N058?EVLymD)nPD&%^P$pZxT(8(49WmAX#IkJCuez?A>&d%TnTkF!_ZfD=Z|@MNCUk9Gg<FQ9A8GA7aE+(iUU~hXp@elak*E{$6@2RpRD?DR0ef&2%|YSVqjkVqgojF0wd6 zk{t*tE3dwA1cPU3DmUl9E#chb`H(T0d}*jPQFLTj{v*%}k9q`0HUFi)NuO5O6GEMG zDtIN)PZg(KW8bPFoI`>9t?rkPq)lUrQvyh4*M6KnOEI?DAH7|*J(Y<}TH12Qx&B1D z@I_(WvM6`Zx$EnGlyXM^c+kV7O?hLW?wP~et^&+QDYLJg9H!6BR^;flZQg!x`0lgcmA|S6sU-a z@gLtw(`GsOLE>K=mA~jo8I|gDbAX=u;wMlo8^Dys%*m9l{O$Lztq|<|Xtw;HNghQQ zg`h+Z70L|E!rrJy%r8EJwN!{>+S##DIk3%MmuAqYYqEY{Oy^k_~ z30P`UPML=gETs8ry$nS53M%J-1 z?Eww{L{E4pJ8;Z(mo9k#zhU2PMi6!-1s#)TNaBo?A|rzhcjha8RRxyB8C~|mc1@)S zPk1`os&i9l_ty!Y5*oD@d}T*nuW4P3c_v*=UA?_Dzlj7hdbWWSLiPkEymV1rTF;P~ zm{;AdfBKSPvP3fPp5&YI4dA`UdpDDx!LRrki|IW)iQnKej6RGoRXOe6`#LCF5op5+ zTwtyy>!!5TW?1@PlncneUev%@D(I+a82_44BfC+fqJW>!L+GS5`7AvUbuZo}O`mP| zp8roTYBXdo>N^s3A|)oX^C)RpJbQGUle9E!$VZkkS}d-$b2hwFH`aD3DUSN$sqNkx zy+$88Tc-{WL5{9Rx=LIx;51|jux%*1>VZfG_FUU>lD2tMOOqeo_MS>w}eouvmSaLvPRM& zV^Z|iu72=nQHv8lj(fWp^U#%{gBiCCSSaMS`at=+X~v~~qxCxNkfi-!E%(gT6Yk$9 zKQ_$QJ=?BuA0nu&q{E^I=q@N_(SE@ug%Ty*>)PyY-_e!6pk{cq!p4ADcu1EY!Fadw zPQZ3%BH`6`iAa2_TXMkCuQ1;PbT&;olVFwLZ^Fk;FLLzNv?~-~AtB{0ITPEh+FhcH z;JF!xw^kpY)Oh}qfcs`FaQRSXkWlK(oyR^2fy59(vgO#W3-sg27tKUD+IRC%j;#)Q zn-!K|r4&I)G~we(3c{vXGE@AllZ@nfT$Q&iv?$Vv$>LJ&kL|{8>Q*w0_GFV#VuQmM zWYO#U?7hhedMqCH{TH;vUs>+Gh71{8a^GKPoaX8WNvn(D7axz3i3g_S8&XA%XQ?)% zdgki?rdo#gv6={X*o;mz@_OJ?hoaci$=DXJYx)?V3Ai6qOM|_clP-w_(Tv`(8giK) zkhQm>8t??S`ox>^yhq_aeL+?861%CVMRpux{Oy-jw`gKwAq~QiV-JhVDA+;0sJzYc z78OHtDcBvIgVV2b!$qjXuhOgEl__taf0!CM^+yMF`9qKxVr^(~TG307SR-QTj2Oy?d|@A=g+>0(Q(j1V2cfxDkM~cL z!6{sgdNV_z8?pe%Wy9MkA}KN=1x}|WwNTWXHM);OKZ*}tdsVdyRcgrU8c*!c+G}?% zI0;va6ev-9MOvOy-l&Hj=tr4)!3Jqi<2W3hEMl!mD2c75VJlUFPE|UU9Yh7LEGeb- z!aoNd}Sr|HUW^5u8-Bm zqem`Nc6y&XLw{}V>Q60@y_B@)ZEP`kRBIs7>yTQJ8~$gnv)>}u|M-Ui!4HiW$L*QC zW-e(BWFxHZSJ5P{U@`gblbc$$l6uy}X--WG!h9^}EunS=ih}#~t98)f)}o8H!~QPE z58y>E$eFNfifxXwYt43V>)r7>{fITqxH`|QJP&ZVwoG0`ai0v4U(zSpZ`TMJ3M>iSU$vMFeG3Xt-hz3pmfpgovm`33c2M)w}7mKAn}hxw^Q72XYE`}pQ-owD!|fQ{%y)WWnFH} z($a(EQag9Z1!^8+$~F)?gIyN~a&#!PxA!4G<+75AlVhf2nF|EfKU7)Q9<^iYH#bBo zZ`#;W1W-c__}86F;W=F%k6E_d$y`HrC=u-yUiutu23MeMz%83^NyR)MheHN)fgfQm zxVf0F>r-_YYg3cCjxQP8azEwAF`+p=rgUC&4~^!PR;@o6Ykb@DbIM|p95oLYb(e?~ zV-qwg&Lt_B13hNCW8u{}aXV5b%{}3+eivLdheArc`3mhxHR@}guN)|s8lnU89?MiH zHx0IPkBv{o=LuH=+8%yjv5c)?Nj7CHc45#0@97A*_yfk9yl7%<=}Gb;;9b46cRzI# zjCP1h6;S%o`4+MW#JP;B>*9B&;|s{gcXH|_%xVG#7WvKKqjwDT-k-fG0rb)-^gT?h@S^7Hg2Lk`@)P>O6Yhe?f9LlME3%UE?iLe z(q~|?+kmS+pnB;S$|FaE$GTZnjf@o^J5#%3s9BrM*VH}z5g;^2{F_9ww?~)r2F(dCj8y8oZ7SOyC!;3^r=J3f|ya&V&~RO`8I)Vs z@6?h=pRcF?-k2HwME579Q08W*_oDYw9WnlzTZf~1{#Ap5kljWGIB$Q{;b2Ul!sJm} z2f4rLZ;G6ibk_-tJCx^<0x)*xP@@j_ja4Vj+Sb83-m2joGuLzs<9cVK(J&c&Fk4g- z5yLY=-c^)F!*9!8A*VZT;OG_Y&*qji?l1b+Ke}t5>XJ^2$L`P&DX*f}j!+Yd7Al2t=mK9)Z2bj_E|3E$ONvqU zuLmTk2%oTyvTZ!#`Kp6Th=pduz9_5Y9BUc6!rNK{geR@5#L#lfhje3$tBgEn5eAvg zap|Ol!o;5!J1tcX;{=M+L|^K?%1%9;6@97VP@>CMT*Og^7_{20HK?s8X|L8l*9(Q- z?t2boUdlGx$^Y!VAvsz9?(FhzOBqk#ZB^}r+>*0mx-uy#VRZ^C@Rr$sQ4(OWm^>IT zNHLXrhG%3yOUlN-5J=(r8NBl*Cb`$DZ$$6#RmXSGTx5P42feHkyCz7oCbo0_Wc_D+ zZHZdtp4n(ys#-{usFw>TWmZysU!UAg7VS8jMpXhPTybK8Q1Z`f^D9M^d5dUQ*%VUVY9BIMK51s-Os8 z7v`Z|>7{yL_tT!Plo8#U@VS|5?hsq5!b;a#b5_NGO$hY)5jrL1Q#iFS!ZaRLBQH8Z z0V13;75c==0oItOb=+!I;E!o>{1~;Q541l(Y@#mQdu0se@$LW!YSGvY2g(&HDMmtD zO2RnT=Qzf>b4}!R>Emj~t3CMsc1&{OMDQ1* z&`&nd*3~DAEPZwPI$yyd3cq<+zr;MsuH)_UtAhOuGAe-gs=ae<~wsajjgdSnf&2S}0Qry=&pZfI6kObS6pzxYIN+~JKfaNz%95f) ztg}#d^>ZD|v*+jQ{1eXcuE+Y+l8$_8q`jujrga$;?LU2&7$Wbl2xX6H>#F$KxHM>*Q z1tf<|;F6CmtPuzprH8=@xvXi7S1N)h$cHs9qrn8V+WsyCYEvaZUzCu1N^!f|eHR#I zD3Ka7KK;8VYA&O$`{KHjg99Y%^i4-qCAuA3ot=`bnOAmyC{Hc|??vBqVixG4n@9uu zYT>4?cac`@OzNwPO7V*0>zAMPm2NAbv{v_lu{}zEQTV4HzWbI`;0EA6|LzzLA=%o0 z)IIpliPYA%H95HyU8bHfOocHl)~Y4LC&%mtbQD{LOXxr;xcJB{drXdnZH4K%o8w`R z-E)Qz44SlruxgwpbP#BCBSo=uBWxzlmspf^&0)>>`EbRWs~7_c7iu2IQ>*Hy)jZD1 zSI*D3G25|Ltgm@fVPBu0{zb_OO7}DTi(-)5c_sB1#hkzAtto5i@^y71Duvx%+g}t~ zfz7~`TrGRyd4_pj|Af$k7O>B*aOADfvP<&lAl*W86_d^7l1SlXFkeQfi9{yO7PFuLxcLl1*V zQ77&=zSQBTqUNrAW(qn4WAC=pqQOykVF9_w#=Nh}a2Gx{M79*$9u^u_kj<$PjqO2` zV%Q}EY^JF*IeIAGVl|2FU8w28q{gX8a0=t z+urSFgk4IwH6x^u*U|eB@F$>0Ig5QRLj7gI!^~M|J>&Jx^bc4xc56gyAg!!;YB}*{ z53}SAKZbE3=u)?L&ux@yFmgb%uHw{u>2cTV7I*4#vQiq^jpXa7YwAaNe6-gmGwkmN zU$Vh=*1L$(w*ye6>q7;kg8fO~6rfvE)(ETETa%|+Z=IY`WaP;4vD#=rxY8$HhP8_@ zKLW)8zp3-zi)2Jn1j2bQ_GiT06#dZ6Xur{*{b@(V&I-l|hb;B1KQ)Naa{bSnPt+CG zzkY|RuMMxJsFVbu9QmmG{*nmmx9<6fW&F4%2sn{G&7)R(3~SHsQtA1%xfAbq6FlPM zsB2UIlGK?3AEz%_nSa~_kBw(PjrB3orl&=PZyy5|vT*ss`=@dcEJ=iJfcGEi zKN_WPxCG{;cS=~Su41iqw#=v@%5zCEG|GZ~0Z}x?@*AhLG`@cu7z#A#eaeV&WdEIUJ9$Ni;t`pxW=DU>fgOR{gY!{b?$9kcQ<#t^0`9Hr$*h|*X5_r z+n)x@Z~lDTscCd_Zf}|Gbc;)0r7J7=`%okS_7vF0Ogv=6j zy)LGmR*Sx_a*B7C=;l{N8B_*s|5<+!YBAo))mt{GA~UEKY_B$T^3&WUzCpz9d|CSE$}Pr z1Klbci3H5Lgr9+aLhZkt*DuSa6G|xRa*gr3s;~8W4CZqysg@T`TPFiPP)e+(PukYO zQfI<%?{LNEIoaC+-8=`^&Ca^{55CNOoi`0^G`hZo*R6gS*JG$-&f@B|!lhk&NSCa+ z=jORlXZ&)I`&|5q`?saueMIJ86do!&hu>zC)M5Y#Vqvo;uZz-aE}%T_*McxoEWTSK z792*|W<#K1U~5RhMOo%&d#V}*vDJmqs&zAcT=Rn|f z9*RV$Rq|#G=G&#*k}=Ceb`iJ!BAx}(k#kn112x8)+cg+gassxBGG}t};Ri)qy&$v@ zaEXy>x%*+?PCfjQ>=mcqCv>x)%7ag*3r$!XD`|UY1v7u;B9R>9Ky~DxNljyONdNCg zv=_86IFDJVc%PR(04& zh%5YB&{afIoh>g6Xpe5vCFgI0|J3+O9^Hihsqy^%T8ul{Kq+|aHBT;B&6p<@81fedVSAd9m_uvH`z>+^j@ZTIRTB6AfJH@8K?;%Y z$D_ud)5z1%09PQQnmo5>5<){ru+XaZH)SG&EE}j+px-et&^apnI+ZJxy+uFLV_eWNwH}^N z)&gZ31psAM6lmNZ-QYg_wnRQon%Swal#v*BIIXHP^S#+EWp2-kA zPL5mtU2y`wuj5o*jPJC629fhl8lD)Gtke>>FNw(2^}VwQYH6w7rC;O9)0)b+SgMwv z9@qT48Bn8Y41?vuA+nGHRcmQtt6`4>M+`iL!BS&iQ~TtZ#aPFr%|1wCG(rk91e;wi z#qqGe$a%U2g~bE}kd;8KQaK~qS1~Xe=UDS^mfF_&UVGLm;A%d9IjX65j5o-FF_ViN!XfKDx4L8AfH^FSF zJ_j<)?~fz?)hpxHNwzHqEZG)4nJF*Yfhr^oVuvm%WA0)0-E3j<^WwRsTrQ>KVu`A# zZW`r?p$EBgBVT|!ad`!WDu?HEfhwivP?omnOI1qZzASB!mNqQ=bFW36yA7iUl|y3h@y7A)i=vN_ z=h11ZeHvkY704?Idqk);me~~%x{_Q2wDo>YNm8L(q16HkWU+{y(9Ooga{@J3_rr6e zdz#xQu-D`tS6j>^mBNm|?ZJ{)ze1hv{G}v^578GJu7LL|VTSg0b55DsHNpCznX1q8 zx#ux-TfjfnS`%PJ9jDJ;!@{2xa8p7}Z$B_XtTfiq1r!Yl6!oG(I7Jw+|Guk~VYBb_ z67>avO{Q!@ zkjwdmS@R@wP@MUQ1MSig0Ot(E2W%qmq)2E|6fT7kz&FxSL$id|LzU&qMeV~Q`Ansf z?m$|30XEk32<2}MBH8XAFk?+Q1c`mfXVtu$uuI$IiV~P(7u6W?6ecneFmq!6iG$ap z&vrN>H8gatvQ_u5*k&AH8T6Tcy_JI7KXuWtIgzZeF=5?KjbV{+tS?A_fh~WZ8RQ~O zKEGvjH5B8SKiJu6JrYkO**k-Y(ifHkeZX}fgqYl&fD=SKMR`2s^mibBm;C2sA|g)X*IYoVA8E;oOy zr%omGxr1@4c{{#TpwjS`b+Y|TzY%PI<~zDG%FSLG?G1^?1=(ySn)2>vEx-sM!s8$a201|ze9BItDiv$WbfX0B zrrF4eudQP+5MHmnksGZ2vYTF$;EGDWa3S}=5vV0K^7A8l{^XUY**V@ead5=f(-dso zJu4@$tMX)D5Uo*I&>9La;EL4?&(;;u{=^F}fEmS_q|YznWKIpjQMu7suIML-52A^| za9MT5BC)A3V2&EYw9Qcqa%2^29w9Jr-?{H305~zhjs$OmgUUd}xYAlU)`!4eD>@t! z3v8KjW}roz_yS6ZeXs0h_&o5u_}Hz?0n)*gQrQ^5jVl2VNTgU2t|?hK0}_g- znt(!dPf9pG0QD#F5NMOv0PySa}$-F7a`;w zHaH&N)^nTl>?~446=6K%02J!s#VP72h>2HmdEtq7q@^JN5xqa1P{@5XD`&bGg+tim zWTi3i@hQ7?psM~JWKYTm<7n1enmo4zC<)PpU-V|YsN7F0%?lw$XQMCpcf%MkQ2B?) z`3d&DdojTpKBwVXUhbK@iM3EsMer4%aQI{epYwbr?xeBGH2H#V|L+C9xG48prBwU<~(^F2A;*ZLYkAS(b?({Bzg#*PZ!R2Mle-qDOCzR ziSVViRA`I{NnkO|Vj=262QV{<$buf4@H01uF1OE1tF2Ux+&p)K;t%#8NB-U!9vGp&*CMIdoi3 zKw8sUKehPv0hxk5W0cOljd`y3y?$)Ht1N3e$^Qj43u+qILov7v?z z4E%mzwuH?MD>teWRp~lKnq27Pc_06i9omoiq~su_jqGdo3sZ@55P*#@wVU2Tg1$}? z=7Y{gYf7^@inI0tSnW9V0Yf+&-kE2el&Xk4E_hiqk|~;TyJv>g2mC_8^D<`(vMqoIcxW@>Bk$SWS%?fI*caFFhu|K#6%`y+_$N zea4X#MKvbpEwAG!^pm1=3XbuJml_kH6oIxq6E84=0ZVfuu$y&gdSg9Igs0K^@dJmT zJ)H@)*+akzd7Z_+{iC+|!<%{W*{!>$B$&+Uv!!*#*by-FXZj>1N}&{?7QbZwqd&b$ zEVPOYMjKLx+9^~V;!KnVifoJx3>4P1Svwsxiqk0lJWI6;Od-Xdli4IQGudfcMa)q9 zN~&~RQc_rp?&u%71Ldqs*=W0Q!}3*^KkgDcT{&GZY26ozH;H%DQk zI%V)vURmG#3TplShxQZ??2jVx>&tp>P~(H_?IOUnvb11;+%Q05J1qu_g-#9w_Ez!V zY%~#wIDNR&S(J3?5SK-q;I~lScxkqwr&~DDBid?DK!LK-1ZV&$TEq)wNl`4+(Fu+C z6i+qX_&wW~`^gD0%ZC6EU4_$JAg!JVpH$zvUFt?S)qH_ctje6dqtjc=E`iU4g3y2P zfRPzb!3ej{65WYjw!cwi7yCtC9?;k>XE>V@DD^u>fkUph5{TYnsiPK%j!AyZ+!3>v z&F^9}PrI{rgxd-kJ`o3}`*v^f-AX>X)($~Zis2W7WK^Tgjc<)%u`4KK#2wDNU9#s6 zo`KUDoFPA@T5>(h799F~SBR}iA;5kWXNK7&C~iMkKpO4qVk$B|XVFJ7PLFLbovfb^ zbX}(iBmRe12v|}SAX?cT!lthjw**&-{nLNtTcUJd*YN^r6*|~snLmTf9CcWYF+aQx zUsggEg<7Wr{C0;n5(AP)G6)S*>Q+1Mg`ReA75qaEt@7EDY0K&Xzvzp~)mYLF0lmOC zl$?zipkUFr&+T30MB_-$Ji0nj##bP4SdO%GP9xhni7X5p9czXBcK%~Quq5RubIusI zpb-Yrb8df83U%FgyQQ7RZ@4lQYg~CPE>$G0T@$x#Q&8TZNP5JBN#=Vn7i(pF)R}rV zr+vix))5(ursisYQGDK>&92+1vcB@#-$Tq3M789bSARw7M$5`*m^VhEuB2kbJT?PP z;5rD@$|5@NI?M>DowpL;{u7MC*>caPiv`IWc{o_@r*}%54jHBQwB({MjN1uZ9RfP($bXDCuxg4xGn^9))ran(WbtwN;hlu7A=FvC0<<>uo(dwp zKA@i~35*hT4O2T<`@6sSTIN{AYfi2Rnmhdv$$wEke95}HoW6LCTA++Jtbwtq_lvh< zjc60VdG3qG*gn`LYXhKnPxQr~rzq^Yhi(P@Md{@&0(oU?`_po)n9&UhLSh{ob(Clb z@j9(lGyvw&4{wNxjbWHr0OU0J3ogUPfP|@Mb^xY=mPtj&r!O*8mOYCq!FW@~Cr{iU z?9+P{Q0L}jE5UlldK%RJ_M77E$F@IZ_aBdFTSMQtEPqq?`6Y6+0QJk34X>gkANFK^ z{N5Ugjh_`mjcXn~i6cH+scyv^g1p0g7e+6PAiz?sn3j@43kfMHoXI_aQD#r&!=q0# z6bgJx!Ha^>4}3kQL6a4EYmLMV!e{ru0dne{5`R%jCW-DIwk2yeygm(n<2}=>!?D#|3=qBt74iud;OvDcIVPxsD(u9yWU5uyhr90SFq|CgO zuD^w<-(y=(isWN56agsDRJ40@Z!x zw318we6fc?akaE%y~8lzxWwRFXCSSjNI~@TK|ZDs|13H_?!?-k&P+!bSId@GJmE2| zkLl{J6X2o~oYq4c<&{=a(v*TmAXZQuSw^f*vr|dWNS!a+XE~1SP&oP&{G&se&`wXMmsa_b)X5`0Gcrh8>%s^JTw1{0jpeR7sNI3*ya<=%ari5YD0 zxRHlUsuMSWe5)H$3e4pC=B$%fH_w>=)1)g#cYsn1?{|xPAP^^6?6<86V!Iydx2#_w zUol$tv$m{Xa&B(6wzqcVG(YpWkwtQjlOeqp4Mx~4V^$dkHD?e1QI2rE>`FZ+!Qx|* z2MURU?x(;hpUTAT>&jImg~s)%dMU584vC}P7mgGQ32y<)5y=F)Znzg!CL2?5HP^hH zD-its7v($h!8&;p5OSU8d$Hl}kl3J_uhXW1Lau*wXw@Xb-Voru{vg^_{riotv$B=3 z>~;qZQ@hr!V&TlM|IaR_`%stt0Cfq|n9|g2zaxzq|3e!LUow;Zi^6z3yYL(SrGYo* zd&`ZnByZsm?)3B}dDBDCvi03xl={9?&x_}OqO<}2^DBwscUorg;Xm4X0`@~t4i24D zJWWKbX8c!*CVUyBijWQ9Exm;}6(1VZ1l*cIdSasb5NwU-phmdonG+d`^gF#v2LNXQ zsK~CtUyda)Z*IXsf2?P|Z!Gn|$M5?0KzkYA1P-%`zRUqGJ^cQHJhR;Q`eZ zlXj&wdF%h<>MR4I`l7Xuba#w&Gc+SZN=OaeAl*51mmt#J-3&u_gOqfLD4l|!G?F5M zqP_?J_udch@SWMS&pvyv^*q0|Hu>Cz(>NsMQ9>GGShtlJtcOod;lpGW;L~spjHQ~K z9Inz8A?R4S^gVy(aN(7wO-a6B_aC&X&6XdU0`JIIx$Q_jzwV?4tqmv_19^ijk?r5}P)2Zf!{2l-!B| za(MEfP|`Hh&q#s#F4xF*VE3ICW){DOKTK0g@)urNE#w})E)-eoOizMz90QFdfL_PJ z8g#dp64kU5HOS~6i+(PMLMKr(PLSoo)q?<=6PwFy0|h#9BVuRBc( z1s$z?{DjG^QE~46OB;(<+BTT@;~>NEC#dfW23D$Tyi-j;L5!mzd8DzuDRm(r?ZA=l z6I|>b`QrJ+kL>+xE(^b-Q+4eGQ0pS(oqfHD-bMA;x~m+JFhU_!)56F`03J&0GrZsr z7w}<1Uj$=wGpIL`?X?@n;!k?*JJQu18G6&BSTPJY_6DBEY0oU2%-4U;`m>d1}yQS z{WcAdjuT$tvoVdXft0%+3HwA7-iw|>PMv|2Si8Rr>NC%sg*Th#P9@IY{gzSrH1Zrhi56|8(~3MblMxZ{&9=ig@a&!dBXf7bX>69dK^-rN-fk3>?_WapClZVugndwc@rsnod%F*4z zy41tk?wK}*Br1(RS*@&W4~Kkov>s=}8{{>19IvC*XOYvDPr(r45-k^!=^=mcFgWK& zHwr3T)VFtlwlTN>by)yRQM>3RtOHG%Yt2NSHlLumG?d6Z&@S7^&aIEWTXV|mVIo+{ z|NrmJALnzlRtSe6)YV<_HQInTKc0s&35T8tYGW3_`{jW0$sEFQ)`3@l1~IG^A)6iV zmLM(@#Wjz=2q^JFu`;M(rDOl30}EsS{9)z=U;{UTBE|KoT?CpnU*vw*T(Nl6#>XSx zlvBC>u<;4A;3x3DkvZaPz&~U3sfe=V(DGk=!tG-KQZE`3_-wM~*B@1-pf-2s*f)pX zTR@j4Jwy4R%HDJadANw`iU(cgE`6-@nMW9r*GFZu;CLY-R>;X`YYUzfQ&3kgP&=sK znbB7Ij2C$20(Ja)oSv1ES*SzS+mo=*q9LE5U)1grgq$nt9iXc2muWvJ&X!JHuH(i( zJg!%DnaLHjZfJIiqg18BB<+$3J8#6P%!?4PE>LrVj$uCbv5ae`aE&8hYtf7%tN)md zM};XXLNc-<7R99}8?Og$FpO`mp!oAr;G03OK}Xx@0ut6}N7h)Tty6^iHrkfPFpRjojH?uv~7TxF45^i z=q^s-*toZHfWYVT6Otqfnab~}m4#3BKbslO03eIzgR3hO0Z3)zhVH2Ia&((VAdbOFKaH)2l8swh(}HH zs4_h66m$~WPjqxN+(x`}1)Yi4YHK$c^;a7@#YZP(-_(uTvpNyWCOwx+ck9I`j>pGl z98<6UU*tuvGDC^w%L#3M0D<2ay6$aAS}223X~l=&Td5@9@w`tO$Nmd_MT_Uw%`KlO zf+n;J#vXT2Ya_JMSg1kcaDy<>U{jc6by}VJgLIj=l2T|_3Ah@7&~BP+DVqQdQfDcc z1yp9}wwC42j8*)G9P~n*7VF{{;~%L)?&7}M-QA+%83wHY8+ zjV#bcEW65~D~(YnQTMHxgE>@q99ul6U+8}kM7P036L9RX^QpWRF$IWp1#Ei?N%o8Y z#|J1TlRb4zIa!LGF-EG94bF>bOQrJR+Y_`N1`pT23_xp|M)`gh>L_N2@)Wb|$1A?A z8=*?9dnwD%k$n?{2jxh0Li8Hhg2>>5wn{m2x=J@nb}^fP(LCrAfzVPMb{;MQ1_!6k z2Owk*ddE?u0WCq0%>lZrd=jXyb7>dicpRw}PNKIP6~skcTK4d${{_q|BVcnjnz;_F zR|~0DwyUcfvx;TrtY&>_D@;A*jWsNdYA5mHz=g!FzD4|&MBE{VfP!-*+z+&J+W*6U zQ0@r`ve2W)9mZ^SI;WrScW;CzFa*=`hy1{w`dUhrzu43kV0rjqfNzKP8bPb5>$|cM;Q42fWzTD z?;9@VwRyN$WP?Ss-s1_%fklv05rd_431Z` zYcHa6z^Hkh%Nrd%Bd2aV*4vRw)1PY8wr<0m$Z4@2vXZXzvmf8=-}eDl4dR`R2vQkT zi#^No;8&bAnPpL9j~k0$_?co_PxPtuh^z02RL)jrLN`)m!^w$dCFYKxRY6D4d>Qg; zT@9%K65;ZTAeL1y`IQzjJ_U#_68yp^>q_}}i3PzlwVS5jt$*FSpGhCQ0fMsdKL>xD zf2G{=pFIT$RQuDcALJH|hx~xxj=1Fr`z%WE{>#fG2q;ip>1M~`A&JISBC4Y{Fbmqw z6%9ci8?yFx#_UKN1g`T)$4gNxw3)$wzuyp$&s8Yap!wb*3L*%5u=9{()IJL8Nd`K@ zw-<6iPTwwa{-^4f#W7lFj`WI6jkqcQQOMkbB%{#G0f6WNqN%*y8`Z$o>RV}Id6r6% z_z{fV8rk@6(>1N9y@?)8EL;V3$Cn%R^MXO7o#{fLGsv=&4Xg>zJa;S(CJN5zO}}X@ zv{wNYG5W;MJwy7^F6Ccq0j_dH)R9n?(}TUUok_bqFEQ64?kzUwS0B?od+8U6^Lx9|A_~NF!gA zj5Z)yfBP@;&WdxTTQG!RQ0ZL4@>`x-bh=5UdapS%nz{`ve+tC{B$+0E1xnF)RvQKK z#mi3MYixLu@Yf;WOX0ErNk_+KSPEy|7~!*R45|P#!pz`&-0<4Y0`+S4>l3*dJTg^v z=G+jzqnl!dq3M2>RSf_7K7!^_P_uFxQD^Xy%3O(EF-%VJrl2Byf~Cm zuDaCJ#-Mg6xcd>cgnISGN^}deV*AolmV;5D3&N#!E=)wM8;K6`)e;>Qjqo-FF7dw@ zq;%%#jD7nFdO*Gcfq7H#yz@Up;4n=>GJrA(2CZ{!H=J*We6*n(M}o%Z>Qr?{%*Dsz zs3FLmBv!_#ok3hoKEfCg4L=NA@&_8%9UFQMO%{i7Tz&o zmELk^bc|>9#QSIoz+0dXIijk!`vRnx)1X!op&Y*Y-E~9c(7ZV4CE6Xm5|irV@MNK(x;^`sE|OS(>H)r zpb})Y0bQ8$vDaU!BwYZ`RV{GE12CyO-moQH07!li?$-y}%pWNjA0qPQKKDF`=|;;@ z@0rITEZyT`m6aWc0)-hI&~Z|=wN?ilN!{nM@}3Rf9n=C|a<7mV1^f^Xg0Z35#zO9- z+VIlt2Ojz1F*$3r<349ky-pxKXXpSP)CzYcBrYB_@s?+pGlAS0K-I<))wD(t)*jHg z6#_BNtGL+l1Z{5$g07(YMMojx@Un2a?J9YZnT4pE0uQv*T0tOM9q90luAb+tV5S%U zhrIw-R*dtpr@^9_Mktq{5JUoH6sTGoY(v@Lsu(eW0URFU<2XS{1aDrcFUmX{%r1?= zkgb|CK>4?pfcVDjx#91J8%x|w*5O;ZN14#eSlgcQcx5X5C zwUsFp3E}_v=Hu5P-Fin|ehn*XMhX63ApBPt|6?0O)v&c;I<=1&>37nQ{-^NA+XlBO z=K;+0JJ5Ek?FNZ85)+g_8*SM3DI5IU@HG$aGT<1f=1glf$ThOagApq6S>UG2%bffN z#~`_RXQ9fx5pG5&u3IOjniWSlWqsJ3)?KL?O0HEQ8x{2Zc(y{ZfTljNVYDq4U6w~V zuG#BVRwCDs_0EHDFp!&=c{+T|B#dS&{WDl0lqmN1FKOi!fS3Ms^|CT>@z76VAj6@x zE5wy$!mUli7olA}J8lehx@c0lPg}xK^bKrs>a$lGkI?pueAq|DrU=lPWQJxRjBPrc za`sH_R-<|6p`K$NE%wFy{mK$^v=6#71oS%>A*65lRL&78FL54XOyhhEbJ zHNFMRKDNWViS%)&i^s)!f+i8@T*j?Pa_HlxQ6_S&c#`2x2ykLPsC8NNI6)BvK;FH5!FMIy=C8B zPFMNi@bp)X$M;N0*LARs&fYr_Op`fx1L zFWVhda$6E&GddhwJ1A;EmD&DCUkY|09eP zql*x|?RchubMB^kU+NENFy_j+JeUM#lZZMh)L*~yBM{?|L2a-VV&&ouRNU3OZRg39 z^hEy`J!Kydlet*W7(Ow@XwiGfO#ExY!^R7h0(36v$%K*0>tcvLW6&5GXzoB`>FBDu zC4fkHy-6&QtyCuGTq1oThfj7NK z;%hVJYBOpOF>E@V`VR*cZgb(Yn$HLHUbM>`EOuD!6CSi1EkR?pfG+f{KtcKobQQ4ZI0$rkPNC3#Xo`?JxNWT ztb%p@NI8SM*m}i+o&TZ`O6spnD>S)_8qwu7j2cnI@l3hl2^gkN08W8j#mA%Fz~4^d z?L0QxFo2m5YKO4M$|ob~M&sn311>T3$+VjFICiGmtONh#R+Rrt^?MRMS@IJlp@kT8 z5j>eEk+lD4wF{uKW+JW}lz&Ob1;}9!x&g;{azgIJD@PKw`2>pgQ_wh2yk@h9uGC^& z)B(DsvmQO=T}WtRDr-2@ioktT8Z_G`qXOu+$jU;#Lnh%!Jphpe!VX;j{23?sAU5*E z#DeMp(lc$$-ONOx(x1iD|Ekubvv=ZkN7$E|Ok8qzk-cpq+H#es#0<-VXxAW;kJlkA z|LokzBOj zCz%}{A)CLvGWKwM0zP`}7+;FQCX?4SV-S%qLoT`^^HZ|w?{U?6-Q;(lUxo$`*KMKA zo}9C&aKl6@RE6MjARAIB#0f|%tvwHcU}(!e8o)Uk6uOwo_~;NaGPp`rwp?{e1}gO2 z8z8Z?7quZ5tYz?mdSX*cfTAO>yVw*x1 zq@qBX9A`P4wE2XJptTFVjbDnO<0YB2MBo0Z-&B@(?@~7vi`!gQ=AS)SkCd}&uB~NPj@Hl4&20AgqM1BA2#QM>uU8+IJ;ZW)6 zeut&IlSb#*pI>$Lx+;Xs27cGpx$Ie3N;{yN4~+#???&$C15W?Jo^+6r08|&e)9}^B zW<#DNn8H9a)n63qV^2<*!-?b7YfMzS(z^GC5CWeIQ=RUj>sQz%_6?$XO5+f3IV!`n z@IV&I6l1oBvcEeZY?9-bAtEzfJk%prAdrm&lUHkbNU5HVO3ao5wS<+k;`^a>UuzFu zSsw;TjQ^r{6RN4#H74hT2Nb?H|Ppqq#w=ONum)w>spJnt~i&GqlCbQl7>Ag7Jnz<^$tlol&{tP}X@KZDvIh zw!@Y3U|KWd5WfFi`!S&eB4| zvJU|o1%rox6cd7!H};lhVGz4yHqVn^LisQrIXB2;>&7*iIR|Afy)V-#k;9=^rB^yU&J;|}>AmN{3Uc7!w&s6ujP8EFKO<}PskAFj*y>)l1J zw`O)g$NWsI_5bj?Cz8yN+%`(bCu(aE&;omc)F)Hc+r#>^mi~nf;f|G-Z=u#B`Wg5# z@#>%qGG=^*_^%7h{e-RsKyBea4cB}lii=z|SqPU~`?+4(n-Bkx-3M{l=V-RI(GJU4 z?+~HUide&3X2CJ3w!EoFn2}>xh4~V`J%Ot;uN}6Uye)1B(62FW;N>naoP4)v{Snsb z&eHM|C^5+F#^Yul6tB{j8OtgHg6QLagm93aa0L;zAsXPe#tOfwDkn4lFpmdxE5-sU zpUN5T-&FrH17O~xAI>w{bSq9p_G#N#zkVOjs*FGPH8vs@c3(_PiUMs1S)1PRzh@hb zP9Ay%rHhXhCYgQeZ-&P8iW_s$f^ambG^W=N(r(PAlda9YTx|`D(atIGTE9T^O|)y_ zAH0$o1!OG8+X2S<09<^%e^?3eq7c9r(C9Y}G+f-*;#gLtGB|%ecl4dCymlp@=WRUl zN0j(YY;^`MS?K>H`XJny!S!Z@$7tNUsvc4<8 zEHLQFOlJ)c)qYC?{Pw_^>HrhQZDKH(D@fh`ThIfI0~Fo_*!rlZtl=yi6lLD$Q02jB zDHT2ak-qM1ZI16&VWVr)T&}RR)8{jXKGG*Qr?R+)ERq!|a#&sT*}f5jOy>+(3;6Vo zED>2P`D2L`Sm>7SxTloAh_oe^6`hyNLipV#u~`BG+}lSxS}e zkClV2SBt@e57Qh?fY_nu@=de?87H(fA9*6PgFk8=lyg-tfgfF`u#cIwQtqj~x)k@TwTJsywaWT$0`Wf1JwqD2Htp9x7359HL-2W?si zp`c0zCyf307e%9zt>A{?*LNyis_qpEmNk%>dW% zF|jG#7kb#1dcy$&?kC-^@9swNJfV>a1l%o@dcoQ2litF zU~@d!8ZK1zHuw+n58<+s9BVVM%SvHlwnu3sI|^Qa27SM3?xZ-L{`q`9P22lY=EB3l z_Qf6Dng>uwQhL{??|U-nqoDhM@(2ufBQ9->txDIOtM6_In>M42G$r47tfY_KZ;5yK z75>30);kqs@^PIg{xh;JK3%V@4KSi{qeA_Mhb#Nyi5+y~aWY>X7<561d?N11gEuh! zIfht9v3wrT5NpbH%`vE#+!T8q-NrN8PP%)O5?|kMmfXf|zlxdm`5qK}ryfd8Kp*q_ z6C3o_g=u@SjRW9*B1y0h0JvGEX8B4ZkyB&AEW}Ht@-u%z+oi<{e3amm^8_ zF?QLgP4`Lu_bG1*s!>PBvihvAP420_O!JuxBQ66C1+2 zr2x0e2h=2LTr&b2qY7b${xDo*N0Y4Dmp4}{lx6$pk}p4OF40kiGRsw0ks2LPImDB2 z!AR16*Z2oA*zV9bp2r3z7}pEDM9bu0rxsKS-*WD%2&49OTwHvu|NL09`RZ@#g3$1U z%0jYBadx@7hyNSTW36XHO}@B16a<<^={`pSn@> zWlGSSI%$V7Z=oX>P7&a(Banpc!V zX>{`ynq;g@km+R6bfW&Zol^g2F`j%JaC0H(Rp1o169V`u3PSp98 zEtg^Cl8)wFSdF&ip_*SJch_-FK_$+8Mo{8qO@D~}C+Nn{C+w%uN6CqoO}Q1b4Ut@f zFX~G1>t0Rc*pRmI+b;D^cdgM$MsOWIZJR4(4LS-gfS_PR1l>W?_+Fr3*z6YD0~$WYIojCeu2V5WrGA_-GXc3xS3j+CmJtnIER;AF;xWOqo>R$i z+I;!dm#qD!n&E>`?9emJB^RvxA@scXt&imAVkDLeMnonFdkK8=g!N`m+cd!ffxSU> z*j8Wj)gZlV9K7?VKbCjWWaq>^gJOR%zqChfx}o?zEM--YL_3_tecCG7X!5Q(b@CJ9 zC(~6w{$6vNmA}IJg!aBvG}vl%p|Qp${0mq-*LvS-j0Mc(DcuNv*W-l(vHwAU%6KS5 z@@$=S{I=4Ubf1U|PDN>|2(jThp0G4U(MOH7J~NJXwVzUC{-zv&XzI`pF@T=j6~((< zh~sOGpMV2UYQ04YWX1YcB0>53BIPS@{$=PZ$g**s;9AHSmp^3^TuzRD&YL>vv(`9U z5Rkn#XkO_Z^3)ymQ27mPzO(td_BC!kx_FGpU+U_oyCKGYJ6VH3sM}cE~MqPUyN7wY3%zPwg@Q~SGvjPXI@9t+N%1UMVO9kymR|f^qUh2&+ zMr{@Czj7_$T*h`8mX(XXI!nDpX$GOp(xF1a%+sDuS6ufOaStB-Md6SwXlKCe_MnlC z0#be;BdrQ-aCIcnVsGybc74c)6Ld!xs7c}4NMwRzrn93Z(0yxmh%}l5cs-ns*7zmu zxLmFH(8|Ax^7dy^DZ4;0`u7sp&g_+IxNfVm z>QWRku=aec>pRP(RmqF5Asbi)s^zQS3(@cM@x@9$N)svRG52W(Zzu)s{{)jp*B+uC z-(lMA{RUEoRkT)reXHYFfe5u-bM}H)#mcrTRwXaOIfL<}E|F$l~>wfVW z`|t695j^ViL$@jJAx8tMI<5C>aY6Hy(E0FA?6EC&8)|fG1+oZrdZO@ww6M+N9+bBp zsNHO3r!L=YzRgSGbxw9LF&lL$g}nMgC_9$FhgZF+zy8`N@Ko!^H@jVNKF{tJA0>VS zT63hlylQN&{A8}ORRT$sJjxVDg<-E#7yI^OeHZkW^u`0T5=*q#{zeh9ZB*p?$Ch-1 zKJcc-yUiC;8YS#T_;I^AGflShKJqa>8&a_mh)3ShUQ99=bSo&np`ND;Xf=-|hHpsV zyb$!37c_?6t`Wvm%qdy@dQ740%Npf<&m7+VGWVAl$|rpE82Sy*jO{O7U#MHw`Z16r;jsUPGc(Ih-M0I5rr zk@a}tBq3B=X6CRLUeu|{cZLM5A4r!IWQ1zlf3vK|?~4ye4SU@)plIzQuaRhPun^UUJL+$+w`|^h2f6G15&rJIUfb8+o4_GqyVMrH zciG}5)nh}-wp70w!&XW|Hc)f9&3dqqvl~kW4fr#}z1{wthp*{ehMx(WpnjGlNfPnu z;&tcw@sx5^*v5dO3Fu#5Yy-9BL-6l5ed~_W6~XhHPCIhikO{cQ?syg4_^PKG6@el$ z@N)VJ%i^{53Zq^6C37pmxmDY2mo-`$zT_m^D=XS~2Kk&=eb=7;s78@BY8-UZ*^wLk zdz027%6I&y_}NF{smZ@4O|XCI`bE%VxZcM7E6M%l2soD87$CWXtKt8fNf?yJP>^P} z%2$Z(Dd4c$P}7aE$X>va^d@YSZ+{q~MYV(tpOa0cbEvK#TzHQgCYxCgY|0s)ADXT` z=i{hX@9{x+6lR+Vlb}xfmZcxLqgnE?^HprX!nDymX_(>kmvVJ^ugL7LoQf*9$ohLg zl4daUE0n#gi6d!+?eU3-!}PZ^nWYTB-HoY;n02AQI3D5 z+j3zOy>2%sg9MKvM)d#tn4k7qcbtaMB`r`5p%)vmXB)Ng+u83=iyBpBm}x5zfV3}I z$<*lsj*4IKK&SCBeVE5KYxmr?t|7bMKBzUVAoXskB8u#ju%iAeZBZiPv!Z7+s` zCvw9QMg2lSbj>b%)u;76#reRVl_J?-WwudOwCHuhwCbsenOM8ZBxnLX;nA`c^-lIUHQfcDfm{Z&Uy&dm8`^PIeB%|Ffr=X1nd)w;5 zDtNYRxO_e%V0*HI`moIneRNlLvwbeslLOze$jh28n20+9Tc1GNFPr|oWs&C%A2SYk z&Q~5zDLv$LSuvo`wzKF>`s5bZ*a%ewH}VJTdO(!tham^bKHE8S4$(O;o}Qm?@Jc<2%Bx@A9`-f6!d8lIE~Ck3z+f8oOUBUt%R*V>GC3iCrAZmq6%+6*048lGRa7 zKZJi!8riPj`M8{uotl<$blbKdobs#{5%QRR4be&5&nrEY$s?@K^5kMi2im^&c4`wJ zW{2m^DYyw>?C%$Oo0bE57yxTCVs(qqar(*E45f&u#GT+PLzB6SamD05pCpz-YEvWj z)g!2-$%4dV4J8FqWgIxAb6UlXP2SU|)ET?kpPonwGEdO!M4@iotLTaBI8pipw+3X2 z+J170%HA%o#0CjXVQoR%(}9=ZQ4~IHWidHy5!0>DG zM;xL$3OZhgeWf4ct+ld+Z;Cf4LI7M_{?i;8e^KPT<6~!?;qpxa+`F!<;rr?^DOS00 z|M<&BEP*dDp;JPSFUrhwEXuMl{}g#;6A#7)d?Yo86mbr^-8+1xNZ*>AbO%56Y)U`) zNbwSr8T9jeLP*-R!I?0{k4de}>fu1bbf;OM67{uLCXEe!j~M@B7Wx@)mX2ojp9HMe z73ID5YEGiZzeEN%CeJL;Z8YS`D7lIYu2pQ6TU{o9nNx1hfqx0O7(2{5R5}_v#^;GT zi%6unx4F50Z!$2E{<2UU(FubWzDtX?%T-I18IBWelcFcBy3h!D?8hf2Acl;53lq)I zwP#L{+PWv7tDe9_r%@Sg4|>X`VtErTQA24?*{+jN!oW;G)v19Bugnml)J*f1ZsJ6hK5=f;`RK~TG=Ra$Lr3iu z@4~vT09^<(N|N+w4rv^~QJ4=1p-Pfce*c)fc0I3}Reo1Zr0MF+$T+Eb(^R{)c;mPoBOoF6aM@6vQ6_!mZf?(adW#*i z%XBIhmNJMs)vLM7q^ij*!U+|$M4j9Q=)BiccQ+H*%-591l_Di{)P|SEs|3tkx?+i6 z+BI+`!Vw}Y|Flp(Mem%T-FBefoO6fT9^y%WD!3+AF>fwor2w8qF3T;W@;%GGZ@ z-cp)CzIS|l7FY5#U2xiZLv8wr-4cPy$pqPG>TZJ9UliiZnhcj|HZD9NwgcE7L_?!$ zZ?N|uKQ}_|Lo&fD2xf@G@RIcyYF-n~MF$@FYiiIO)d5si zQ|eddFAZJzD6J;JculA*H#JgJHov~2DoPlxByo(<5VJodw4lC-{QOv4WI_s!c1sCP zSuW?<*{$<-YFhm@htHlEMhCU=9uBTD9|>Mb+8ejz`2zBVqoiyfdFL=zJ8qR%Q3vZU zIImX-DxmA|%Gn78XU-D8IJ&Mok=A=SqFL?-jLmRgbq8`4D%!r*{#rYPB_;ysQ|h|j zj`7;Oat9yrr3T))7aRzksE^#Tt(<86#LJ|_8t<6lI^3nYmwH#pG+JRT;(=hzPJ)KY ztxVjQF^JPcPPTV9%teMWf>R#bY4v8h9#v6W72e9LBa23OCtJ6d%X?i2)Ygu91#fA! zI(OTTCShxAUq^OVKx{(qax}B0x97MG*^v~Lze!v#T+dI;8{7V((D>UtFMrFz`#6*( z&*cM;Qw7hCeAUFdX&g_`kkj^jJijD1pSIW>X%;LbH^9brcsu69>H_Kp17pC^;~Zw) z5eL)@!;370WoE}0bC0TtAr5L|G3L<0$W~qtYUdhxgAh3u0SZ@ruJ;&u;~-d5`E~6~ zB{^3Ir|zjdi|rp3cTHpm{bCq_5X&6a}d~@^8a1YcnPtr_Fh?=j#!+W1Nk!&Eu5ApxfUG zx55%O%P($!<@#v1i{QfiWGWm)`NsKd6HK!`Z8->$1xUQs_mwa|uV{D0KGq90W8uBF zv?Js&mmiycNP02M<6T=~J`B{#Mn}W-$*$nH^U|NNl6zxn`Zt4TQxnL2hdJ96`F0lr zj=Aq;oMM;p6$yA4)r0%B>R#aOx+qdU6`^QR1)c5TC&_5WtHSFFUxQq&MAekVrLbFe zJa{Oe_u3z_5;BgYGHrMY4CE?#!+-i>8;Lc3KxHif@l$T4vKmE$@u+_+pOFX}q}|O6 z2NaIxmauF%ZX_|34IQ~5ZB}+=x^}oT%>OyJt&S6v|sLHa+ z9_e8^ieE;|4Dhlzg%bVbLPXmNbZh}<#I%kr9X3f2iq9_fR?;km>52R>%ml}N8hR?)MAlk&Pjm78M#1}~Xdd-M3SmCMQ5P2Y zxeJ#*G}d{_?lUV0o;KWf;@o;Q~wJ3;hz6do{t z)vR1IIhcY-ro1*j^~_`)*v}P9ZOP)x;AH-&FQje7!k$kpD-<9`Ta+1x%Mq_9bda*G z5}jf*nwlJl#kBWRvFZ^Qm&6i&QTwlq3AFj<6Rr8zw#<8FG#Xee=8&{R*V^@ zRs{2GK9+`m6Tz?to7k4s!}lY9639+iX@r^8YH_I6LIEv3%`h$8EF61MYD}}O8JZ?P zMSdZlMH}G2*JreV{d_K9*V*my>w(GcY>%poDAHSA+7_GPMIPCYYKBRC_w}&kIFaqZ zf$;^W;tuVPUOVgywItW|dpBC@&5RUArX|k_Smc~ohsd2&OVg(qmD!ZRtZX(D)InEj z={VGIh@a0%;8k@}7HgcSdV3#(Mt|Y0@`TegxWGrIGq(bDBhHbA^xm6FeGSzluY0pX zd~6D51_OnBBinxCH2yCN3HsM{({fEtU7ft{vPWbUygI4JoeO46KnS2yrcO<&ygG;M zaFKfy5AO%K0`=xXrmi?)UMOvvn7RmF{cwttz_Ph2J{o%Rp8edEej{vR7zT8IQ6h(aFbFZ-V2IT)!>Ri|h3CJ&MDdtclAnJZ#bMZi zC1`UVnIXL<{pN-Ute0nN_2#tcyy9yjmw4SPjEW`7 zV3zr|t@?yj#+OgU|Ds^Ff-aM$Z8Yhn9UEB}=$}j$WD92qF93gBya z;!i@U%U4vWv>l*U`j+dXDk;rt+dyk0(>U&ECrGY0Ox{toAn^(7Ft|{(z=7lEN*y4U z|3yi#fxF^Jwl;iBOR=>&%7)=zdq7z`Rb(ALNaojwP{XdZxjg2?0#Uy(8oyPE3FOh8H$ zdav~}yb?o=z1&MLy)|=X=_dt_G82zntQVthjIUu5RJb5Li_68FwrdfLj9ucuuJeG- zx0!J$^XC#m*;RL)XkhJj;fL=%^->G?Q8}>6mtZ}fMZE83c{V6(2DoO`A;37OZIub! zlA!(i676|f;wZ$zqWVEE<|Oe@M0X52ZJsv`md4?2c{I4GA!?KfSe4S1pZz!tn5ZwG zzMR0%Uwrq3^M(-fqfw+=7EdJ9bxbkwxv(iKf9Z$zPPQS%#MKLKc6{Jii!EbR`d-n&9Leqrso7^X)Ge zidH+QYovBVn>%gWG6>Tdk@&;6Y;=O`BpPWIgGYX8J`FhPCr{Fx%yE^>Zl90EOZ4x) z!81S|^;w%Xh^k4@u-;jY=g!!@HS(=^0sbck(z)bj$)iAMn51me99c=!_A`zTxRf|OM4T;9e=7FM2mxcnWPe` z#9abyHZk>6bB2ys76Si_zft>{6#6&|ArN*fwv4+*Va?KUoXVn6?5n|rrvo3 zElQNr(YE_p+!_^k*DA+)Rfy3V9!Oyg<4?UlfBEHDXp84`@QR)Er3=Zi)-{O*hfIZ@ z&yMX8ue?UqWASUvQ3k0LHa4<~K^OYv5_uVodgVB;4Lc0|otxqef+m?EA~|Q(5=4Cg zMgxX#48ytGpP?#UTnfg?aBB=U*=kF6i^p6PtTlDxS83sY7>~x(%7GyisK1!(K?+bv zqt+?_mATl)m1XN%Tzr+}A*!O}0?WTS_J%*La@(R2G@HPqOT7$TzK*YmFnpGk*K?B3 z&Ef6j+Zvx)nb>?UnQd~!)a5ewMf;mc-beg<>G_C5=&_ZY#)sFsGen@fhG$o^-%@|? z9Zz6?}xZv-qizFt)hLkA{Ui7|xh4o5s_Nbu)820*v1bV%$kG>ay-0HrTv0pOro> zxR#Yn(f$(ng->82(FdL)jHSE7VKxVSEjKP{HxGmhHsu$=SKj#+Lj_3MxDc5m&Je-^ zdzIHTtLupNsKx4ldu1Y|DgMry-k0ev9=HSiad565f5p|Lxw2+9RJeF@&Whli?Pe?V z!{cV>ubYEgw_r9x0VBn2yQ}vO=hDN!@z+Wer!=B!GQZwFOO*{p7d;v0w!kDg8#qv< zntX4(J<&!iWlH;$xxn5&4;h`2hYZG^UN~EAG!eUglI)sySol+Fg5nl>inH2&=b{UK zEx$wHX@-qV_xm&EiAh;l6)e%})5m#Qu6i+isIQU}9t1Lrp z4#J;Y_!IpG*{zb&z-GF^`8V$B1Z5=n^fWd)`NLyksV-$+UtK@Hd!CjkJc?O06y5CC zoHXpAF9b_^a$x+_ZM!OLJ*rmv!(M_!3h#ZK8+OQ0jGFDj9q-$)&Bvb2cJ~aup?KH4 zghMTAok4i>iXdgd3q^STQ@FG`-DvUw7t~sflWZ;WxjDp~R81d(URMSkB`K^Rb#we; zKT$Q?ml~UJxg*G-tXK=Q6RS3Ed(YPJ__OWVw-!%!a_y<9Xj|hnCrTdHmViRm^G8`b4zP`*qH}JQC*MflaEBC-5X2cfBlm``puA=D3xcBoCdG>I z#0Hx~m6sgkGlDc|dxZ$^l0WoGho1x_5BClOq%8O5^bYOs&{l?!X)SNC$V$*Z-bk#n zc?!?uu%3Z4rQY$4?oUncF3gdqm0fjiC=D1v8rm~ygEXgQOg`%&e}>&T`bY<>GOz{) zdwe+NF%nSc7=^c+8CkSG?qrn$`p6e>@YuO)Z^SDh5sL_L%YZZ zdZ~M<-MX+)B25>ejc_M3dmx=O1~9TnD> z4Z@a9C*8yf`Hl+nnHR#0&9NaJd6S{CDdajk>;+__h01TntE|V1pr_(~vQF{?M1%QF zmFU7&VXa`@8hV8|K?yqBfv+L`$n-QC4cC?&Q*$8=4aRi!vv4 zfHWn^gP<$xUbs`#&ZRYl`tw0>p5|( ztm(?3@uP(W^_R@$*Ly@)(>KEMrhs@}T3TUze~_%j)Rn*_tIUw9&1kxtl6jQQPW1Yx zcp9CkKM*RijkqF6S$XW93`^Uy{JI_J($nXK&u*gcVv96N0an7p%eW;qGhCVV#98&~ zH)HHTzG^kMb=HLiVU15_1z0^b6(Mk$9%ovd!N9>ux{&6S%WP?!+g0Wz5T3pL!FpRI zUGRL!SX?0bPD*RGpHzK=;v0)(XCk*P$4KO-LOiV&rSuz#53>qaIv+{1hNwKAgyRfn z+>ong!*^PKve1hRUS0ujhti0&jW|5lj$_EATI@;+<~6Uafi;B}#2?JWSrZ-^Gy@j? ztXM7V2Hk${0Y8*jy(o8Bt38|^A!6K)`+qEbWn2^7`!}~YNY{`7qXfq29wnu8H%KGR zXa^!7anlVlMvRmW31PGd5;D4#RBD8ZI$+{RpZ)%y=k?y~Z0B6(I^VkZR%n@%3ioM4 zU%7atiEcvBiNwLz{(}T|l>m+#kE58G;-ww&{a+pflk9&sz&J`YEU)3OGRo&R`!_%PR_9=10vp9e54!`4oKkaFGL!PdBEHu1~`9+y6 zMI0B=udv8&DyB9Z|C9&}tTXJ=+yk=K((KxS;APIkog+CK`Vmhh_k}0aPBiB3qh94w zWI`9c)m5B?XLzb#3Eu;ln^(V(2|;FTXy;QYN|k)=<~4y^$%&I;bojYI7v6rLkzH zp~C3+mM4n7kZa&>!&5#&&M9xO;Zz!bR5=6eYo*XY#w7rEaetj%Gk}jgOIc{ZD8oJ7 z2AhRDr;G0$xeTd$!+*TEz7aSLOV^_*?K0NqL-GuF6n`4c(Ob-qz{O<+UnN807sWad^4oAtXN>WwJAQ{+DEAmE~V8 zd&jWTDw^w-*~Jf3j0!LX*Y*reT|Wz>AdDq^3R&lGP9EY= zeA@Rr|19C~-LOV{!cMw)b0uj*o`uo<9Vv2oIl!6~{vuY7Sc8+wO-6e9NPRo&^er`D zhI02CAc&lG7@i-)?^5Hcl|h%)$8x79&$XvhL)_f~9;DdrS+>F@nO%^9bF2vAM;v4& zU*x4Mp2hkAc??%j`+`(&!Q~U4gR3>_t>b9b8DDRwMq~3OsJ13j#Vd1jF3S{Lcknw~ zTAMfBv;wBq=0czIo!>8vz^OMyoy9X%Ir}hE9$c5}Hw?OYqzh~Jbw%cxFRX$6 z4S)w8d4fjY_29{TRxULSOznUV;s&0Wk-Bts3qOA_BA@R?Q4X!(VxD5Be-qg5x>CgS zWp#nB|9~1;(Q`fS7PBHfGGmCGj|ZogH2Z&^8(g78M?o3Ze0&G#N~@mPEDuVF)aGvM zr*?bSCf`-4SXehY0OhkHxQJ=&(;*a zQd_Nl>SYPO(*rObt%=w!a41Oe=kY0Y?MPUGUxQb2c3c6zkuEO}G>^>*>gUGhf}eQ! zTNRkwo^)qRze=V0IOw`u1A&*Tl>h6Lc#sakEghG)ig?w%3Dea^FVNQoTQtex@>_XIK~L z-rr^VQ9qa*ULTgx835Iq?24`@!o)kMrNR z9Q|@e4u<*2=Zd-;lEKVdciHjq(dh5j67y?(H(#jmzx5EobpjLAin%h=hyYKebDw~$ zd2d*b#DP-)mvCMM_O@Vt0-h`0X!e=buZCaLSTUJ?GPRt}CY#m_U*h|u>km~mD9pOQ!7Nu&5czDBpx(_mZQIUK5pe!KI2B&(#zQ)Hs-lH{6gr z$jL@~R6pZZ-zeV{itDx&)cvN>1+ZPm5UvvT1 z1h=whVctUj1x|p>Ytgn$PQN(m3#!dfQF}^kXxzLPAFrN;ITm4)DcUm?+gCTlKJzeh z;sTRav2N;!~91*5s8_9^sj`5Zjtl^M@;#TqAc?=NlK< z($Yeu9B9$D^)}XGipjs_9YZqM)gb~{@pNIjFB~}QZIfbjo$u9pE_=xwY;G5>)~F!v zg=rO005%ZS{C54rG5;cY0!qnJ?Nu4a8^*uPa2VG{2IyqRSsaa={E62vPlmN}s^F)* zF*Vg;m}y2Myz9O9r?YI2YAs=TrheDS76&?b4Giylqx|PJZ|IP#TI$?AXH>Ldlk*0K zS*~V2?jA*;1T#lgv?IqWrhqln3~LCIfM8;$5~sp z$hSOKtf3jIntopEao-mTlK<~f@%ArCh`6Rj7?8>9-||>vrUG6k(s!?}n9d=uDtVEO zYQ)c%pQT&!hDdmgevP@gGsA+(`87w|{pZD!pPl=5loilIqpM%C$~BrR=G$JG?W9*Z zn~zK8hcTApv@|#SvY1QS7IL97W4)WqDc-eG-3dDN>Rg&s$(H>92M;qvSz!y=Wg*y; z`N5pw+pcmXtkY23ig`~KDf>^u@XPl~*2>RmEH8vV7?!ktkNM5%x=bi-ld`}HyAZs+ z=dDbGqLTkHw=m1|`t9&Sd9l{K6k($~^(ofaA=aHilzduVG){!=w~JT9XAledKZEMK zw(Oz+L|c$(o<>mQT{gqOfZD$#{lOP^j2c~Z3FYj?C&h0$a${pCYve+%jif)(etiGz z@Mi03#iqyUiF--rPxYSsde=fxIt$LB3{D+Du!ixc+gPpDBFo7Gt$?PBZ6i}ag85lWO4d-$wND$Es!DAdRwvbj%0Im`5@O?I%@cr0nO5U| z(+1k)2CKJK*ki3~8^#+qrOert-G)<23*0V&T7_ZiG2MF_V}36*YbIvKktLaa4WxDR zzf)q=#?aOzP&vkKSLj}TW zL*S6|OC#l2ac{F13S}9;Z)XZ)jz?tPzg(gD%w_SEBcV8$h@1|(|0ThMsD_HH>#kr& zgpr6TqY361uj8-ZFX5&!s~7C<51YPkiRobxY%NI>b0$9~cnqC4a?PAK+Pc&MkJZYj z4fG|9M7&(!@86kq zt*d?*Q8YivGEsk2w>3O&zBP^{y1n&XT0ze!0+`%YbPsdw1)Y@jG=$4@(yL~Dz3cV`x|hx5FbrGx)`VYvTNs2mVsdruYH{4Ptxwm7=wi_ z-z(Rir_wS=9%QF7Lyk}l#G&#X=r0LHxeZ;A)u|$P)5jmHgL@m?Hs&F>RbOwD-Z6r; zmrHynw=AvDR!FacOo~qFa@sZW&ACuRd4bB zO+n8|BCBYMJ#%3Pf|->&8^k5er13e2XCONc0l+<#RX?w955u(Pe8>7HsD|Ny?c_Zg zV-Etbc@|sL69w)Em<-#886PXGua3q4iCFznbPNEwKSE3_ZnxvwcWY{8`0F*p90{W|q+sw_Z=pnhF4Sdi2b$#YyyG4?XeEvSA) z6^h9UT0L<1S_yagOJZAVaGCw`e1_&{e*`Zq5FMSI;Q_IWRw{&I%FKwbDYlVLSL=s8 zvz+wOd||hS#vE4QkNQGF8Fq6`bS zpbBwo`hl!a*tIDh(&?IcrYgIETg=u?A?V*bl|D#R&Za}}Inc8;d{XgD$YnHDEEbS% zI((zzSy)tsjeOr3B*qbe!-tegC{NTXdzl6-Y4}z7jb#e85dh0i+DrHXNDX&3S?Cs} z4>j+$uob9Qs=UI_!!>tmOKVGYu8+N2m&ZS?bs!wt)mkZ1hH7AI&cfQI=>fq+685*+ z-dpM$M43)k4r?oS$}%$FX7G5o8J*DWF{^K-E-(4=QcQPo;V;RZ=S$3?Y6eGR={~5j z^rrZK&AqlE;PmdyYt*=szNUkIt83-|6u4q$l_Lh(L{I~2lcZO!ubKG1Vf2*GGIhLM z`U8f-p2>-yi^N$+4UiW5Vxhs2W0!BN5SKeZUR%n}{{ye`oOd_{8B>4ZnPTv%ms>fE zT5~@{84l}l^G!d?cmZ|URpF_2#0h_4Z3N2Dfy_QY&HbEaX{_^8&45KqqNO2{5Xi!c zC_SJGVaKJJ^lC@fAykdb`rTlwg~Xi_b-w?|C|OFD`qQ()jzY<0tgj%Qb=qRm{fyi7Y(h<5t=isGs_qcuk)K=u*Iwhh-RAlZL^kq*OUG zm`463xo7hWM_k~)@XPb-P)$_jT6P*v=zK_!(Tz#h*+${L1hPKUVH%G$2M4 zRLL^r2p;|N{>V{B-Kx>`Q>V_I?l5;JjY)kZXAe3za(z%I+7uDI>{kLH| zc#UPc&{SAsb_SD>gpsoIj_|#I(3GH`0VQU3doAirH1Ug*&zAkyF@q!ORG@QLXLeBK zNLJhbVBT+D!`*UsF)2LIWE6-Y_D?E!2Njj>eqi|YN*abl=204@N+4&o$AW$^8=iN- zgp4RpnOu$kjpJIcP3|V%yH`HRMtVMLc1)+5#uJpTs9cys>Ze+=v`0omOK+ZmsEvmm z)&2zB@)<)oT${*HshR1IDoe`t%Q;V!br;sno)IFoM;wv~zDaZX7Z4tM-4f*NnW`vY z#EzqZ>*?{s*Zs4(No8q^eo<8wB3=myRX{;*6?v7K{__pF_>n9f?U0Dgum>q>?FjJSG4PL`$O zOT(03H92Eg6&mtWrKs%nT6mtlfBi++K`ft!&(5k?+7Pzjp^``CZEy6-y=y2?*p|Pm z;=Y-GAK5RnHYusMoTk_w@>HoF0zEFAxAEDjp+0g6K2`ibUI_mpn6G1l^O#HWR3k`L zrvP6c^JFPCnf5{PgCEnjhXXp9^Vk1u1eM^E)ph>F_w{AIy(NEMD~@oz*OlWT^k&WY zR;~9eXDB2_{$7O=-BZzlWS{Kt%0nM>PI7UIuR@P9EszEVCgkIFjK+q#Muv1nnJKBv z7l7;0Yy!ob51iOq9yGvbcejFP-Ej}Vg!9W@tE{Y{IhIyKo!RI@?Pb0 z0XpI!ZwYXn9S0Pt#TRa-JEaN}M~3Al$JzZ4 za(<-_{7dp*$t6FNcEJR+SMo=sj85?Jj8uT8%wBdDVo_?B5fVS995`eL2U}J&YcM+h zCDDhdKCvlkf8DmnFN%lG^a!uzhGyEyrNAqm-;IL%?^MKUe$Hjsqg6b54d>?|w8ylu zcfhShhY68%#T`38%4Uf&3?rb*9ixUThPdeFZ!Dhc-t5_#x$h)oHoBf&73X@crL`^EM^T}M zy*EI+JV2U#KkCN5%$DgNc-J{2MDeT|G72W z9Ey|*d>Pb;4C@6&UjD4S!OCkjZ_E9Tq zbiR_W_s;3UvUW#^zs87}zf;;GD1Elzn%+xqPzUozEd*#dvOUFjJe|ie_crp~M29a56j7F2&!eEP!U4&QVm0%u3GvGL6*r?0pXS~{ z;4K!LQ1r&CF$kag1O9MOPjDS4RA)vOIf-@y#uD(^@SwJ*tRm*91*V2{8LaL2RPKVi zlc>7QV7uOcb{j37Yh*{Y*h$TyL!4ybFW0Puw~YLvI|~#Zdu=>LQg+6|k%1V&YK8QZ z-&}2b4O}t>uDOWC8Lsxnx0r15iEs(|yIf((O>YCJGm4HoGIIvV=~fZ}GuEiclpXBL zbb-kvztxckslnd+0Xhjgn4fy`CI+ewtCFsn~T->m#jNZ zSb29x1Upc}qg~HD!`w?k#5W1hJ_OS}G2**{8vB^eP$-j2IU1uz3o~Yk8x@!?t{*)O zTtx&cU9i|Z^rtxQpd=5(zYGYwx4ubo*UfliE^`#Ji|TNMg}QO z7V273b$S8Ch#w8H1*<k{lM!GU$L)s$tX=N* zb9$5i?FY6VjKQwlhrm*yA%{ID^I>W^gEjf zF-%I1oDi~|3OO{6_R`B~O6*{Rn~_B!{(Z5FxK!hOWAE@?uA&&oCJOjP#(`bSgT9Rq zGeG(!O!6D1)`ck#vRND|CaW<=%TWp#a(U-jp*lcb@LLJ&9en#g)=5B>&I0^)Td!C>tc_ktsG3^}9-U6kG!M!RKy_qh6%y@ocp81CD!-TG zeywvn|Ks8Hy+$JWlp1@gU=b2o9a7HMFeD53mYlKom*maTh(*#`&MyR$;jVwP;=>by zS?dv6uV4fSq2b%klr~?;m$hQYKSLUCZG!xr7sxdO$D5^nh?^qY{kfPtT)`*$Wr+Cp&+nL;eIj!Pa`JE>q@L-ejs}VBr+m&*kgpq_VIQIyWIqwv zPEb6_^j=1!aVv9so4{XP@oc^QNCRGUn2+b&?m3B07SD$!T@4p>o<@`B|hL@Tz=7wuYfRxpHg+ zWgEmnVj>jgeEYJd>eoUK_6xmVV}!vzSD$utinSgMHZVuC7Re(9au!hkmT;mN0tbJ; z%;G+FfQu7+O(n+L)Z?*yT#1$6#_CEbK3)4-j)vQG*!7D!@7(!8394%Iliqkv%KNlb zIb2BAbNmK%^6rFL7>hK|`7SdJT9Z^9m@2B?U>>C}MH93lrOg4v&hZ{fXINRk! zYmb@rSx0N6DZX}s?8u#Aid82Co3K+sE)E==MQ&R>JBljUZPDqStS80pefIV_i=6hFmP+6@4QNr3?eCUtTZQ z)XDD%?ov}kj{#FYPJw`6t420mc&cwz5cavG-+_vhPgM3O0(*YJc}VJR*Qn*saj9BO zfY@rG4oF4fi>h|gjgOQYvN9Xl7wF?tn z>VnlAY5cdNKi)5-$h}ozXj_Io)=?H&&dn_b6o^JdwMz5P{j~4B2kB7{A^@vefrwSb z5J%G-Cz$?Z)Y6tqdx007m=4S&{Jd3R6!1L~;6=6GZ z7D@caRVcO*6Qe7YJjU#3Ib|>Ycl6vD`5E7@A?Q6k zqe#*7n4ZKmf!n)nUHpTH-(Hh~QIfX?M27a$3*G|Z$|b)W46)7X!(_L!+_gteMYOYL zAO^I$=1SVbWH1za<}-O587eHS&@)Y9QUDeZW{-TN&7N8V^ve$QFTvDvV{dB8T^%C{ ze8p%zYO{&)PQzPLi)frvMO+qp!>e1fyQEp=)=>zkh+<#IVvTi?H=&mhVwsUYmA@C0l zR2Y*3aq>h-(Gsj%<|CtFZr&}7w=DzPgSg=ZzT?PUoVYHR1w6$z#&c@i6IA>)d_zwR zZpX;R@4E_Cm7pTS_6t%GlzNE^R4D|R-2b|M8V)4ZPtLUYq!VlH)w$rVPLSm^e!5=L z5e(re)!<)nkgknZV&=ExSD9$JM}5aa*RF>NDW-D_v%IiLHN3x|Bd!09p+*w|^KP-S zT^6|j!k?)c?!2Nt{t{MA&6p&6wsTyur$)(Mu+XB_n}f$Rl?>^na8A?)U|1$`pHOXk zT-{#Exc&(wZ1oJ?^{-XZhW6H_Xv*huHd!0^fd0~Gyo(U9oSe}GZ)V1(zOnF=ru{TP zbatph2egw3!| z^i3^J3?jP9*zaybbn%Fg4aj2hQrxr9YYHYtE?@6xEXY;hL>;(+*CGk>?*Guco=;` zouavtirJTK;_h z28JLu+}d-!&b64Z8GV#$xLEj z40XAiq@D=vOR#PS{zvUNAti`N>#%Vt2plWRrUR-(f`l5tX3+YG?WUf00$dob8NZa0 z@29|bL|?^tmfZ=45+fY(U%ak?c(V~M^a^IU~nV-TGb4=`m6pW?~=g{BBXbocFRLl!&)om)WkQO zyO%`pxnEV3G9>I8)lGaan}I(X^ioZ%fB!m)y8qs(zqoc@yGoNZ`a^;THPMgJe&U8N z!h5nTpmK_L!Opq}{=_ZZjIzvaQDz$q^dmecKE?Y;_g3et~ z1-H{Tl)+BIM|l+Ak^0V%&6U3-FMmf_k6pzRv8-zMpK7;Rw2$UXfSHKU104sN3oj|n zwb<_W^~t3C;u+R-{Qj)_fNbr5g-pFS3f+S1K2#{t1NUmbnrd zUk{`?nAODampf?IwOSRW3+ zemHFU)Gt6RYqJDBc0@#LJvrpJ)+RFtSrp)@gLoKxlB&C!hZZyxvOU!+m)LfYcYGiDu4UK8J(}~IoW&vlDInL4rKH% zy<YtLkd4Gu4Clfle%UW)lO)t{c*~$QMbYrg*+G98yLw`&9@#u$-h<+<^ygYXKaQ zrcl1e15hQyrc90Fg)W6OuH%AWO_|uUTGVvdHCa{4$tJz+WdAeiOHoWh!PVXBDtcl} z3V?-I5&CkIV#_I2hwRrMPB|L1_ZnrR>vV;GZebp&an3{pbRQMT>NRF$XiKdMp2ny3 z#0Dn(C2>@7q$8@|QvI{!VdXOZW+m~3zwa_!)4p7a1g5t~55mjV{&*?p_(+PDNZoq} z-X$BqHlnnck{qF^G!;|dfxLPw&T*aZpf|Hp73W%3Lj`LH+kc48A-anXsYfQ|lFkKi z@5Y;!5?SR9UtG)nj2aAXJ60NvOV92X4tZ;Mh zCAr@jP0M0%?Wl~1ZxoIiXA^CE0)^)QWN_S%p*VEBqXlTu+&QPBG(O_Qk0{;M(z}q( zTo^ERq>Mni2BC)+UDC>>wo_gQU$HI43MiMn{@*E8+v{8S+P2aQy^zM#Z%;{`yMhyR zz(TEe9?4SO>KRz8R_IlsC^HBw9%U1;%^DSdNgik`f!s^PKX3qj^iS;;oyk_MXzZ$M zPeomw6xCpd3j-j2^4H0JTX_1Ro#VX16<%#)Jfz1ExU>6`q+LBKlRmlo>ipGICX0&#= z3)-#-?*ARor`_{AVk0ubs5zQ}X;jDy(ih%_a5-aU=PI)%O|M*0yGqSYI_h3%le4Lj z!XZI0vnm0t<|fxP*$d6$s0<#RW{qhx*r(KQNc&EAzfBcb@nk??tk&)3!loDZO{g94 zd1$S&Y`&l}O1BA<#>>G){@~=ioGuspwj8vr-~I2?aeP8~|JV1+3Lpu@O1-Z&$h|0# zani3|EXY4BV*7CKJZ(4C_z^{LnUvy*6!51dF$>u=&#^ZM zzH25F)7Fp^nxyyZToS()GL7E<*WmGXfoD(y6mB=ZrPdtLcR9FM%(*e#uORnBru30& z{S@2q{xwadV4~koh6)K)WVI-o_oJJ}-m%dqVOI?pFu6`ZTHQ=Oco*q_a->dtzrgUQ z*RLpRZd88?h(#i8PTPRKV+AEVV7%1$lHA~(*)%ns$h0huu;KgvJf%yyNvj_`%h4qn-}xv6&SCf9f&}Ir%^`~#W@rPF=!K8VD_5g_Luj;U%r`d5~p zUsy}m!)85EsY(jIm4j4wZ@hzJHr#^sj7)JnRiv*&(<5PO`7SPJ~7TkM^dwp*0ke37Ng?Lv7RM| z2Mqo!;X|tT&I8F|496oP_ana1qWv;n$d7{L`mGB& z>$u2>n5+}VUtSdZi7Ace+;2YxDg885qI<1?D&=?rx<4?MV+oOVfu3=#RtI1JY_5ptOOpS+^%aE?9|xsoN1c{=~zx2W-WQITD;1v;%KgiDTjt zrQ5ZRGt6*_LL-JeRdluBSwP-u?SfYMotrr?TP;_~vjkyp+m|peRK&HG6peYQX~Xbf z`-Fa_f#!u0$PHJ8UkuUW(3=$^$R}=QiN%^X@CBQl+8bNW>dc!4j{Kx-V+nl}22rrkbMLxg za2Vi=yR+*ywEN>_xu*gTbyYbr1dn zL3SKtgjges|NUguVTBWZm4S(qIX=2cH{3o+rGU&Rh@&EP+f!L+d-%k&yb~-1=F)u> zhvcO<&Sltv z#NP;W!aLEBzc2x~1Ct z{bbGCta}fK>K^dLPp1=1vL2|aTQ0cwKrcc055JlSlYflC`@b|2<)coT&L2GXHMmSM zoX#y+n4Sq7U#_W_A5mbc@n?pw=lE3k09#p%KMconO@B_Tf6S_XO8>+tS~5kUP5?V9 z<*)f@gG@+4s}(^%pikr#Fn2z_Zv!39{SIQ`kWx3eP2}eNpboFkGmuy2DuflsAL7+G z2z$H0ClS|9gMknK&P8!hPK? zNBm@rTn%g6s>g#KqJhWX3IaeLZKC&5)_=$ZIAG7UIZ+xOw0ftX-(_zHeXigks=D*K zKJ>=z>T3EMK{w^1wPSp(o$o~d{z_S`dZnB4U3rh7;JIPXL! ze%!lm(*IN+MI#4?RmmAC_>euLu-Ap`QS^1@Ha*<>kf=@>Wc`tFI0OSJSR~$I#VNWc z{~>jOEb+_{@vCRBl%|odJQe+nQw6$ftnTJ^9(Xk-bxp<{#D0(9Vu+ZbU1Ebw<&k^7 z0Uwi`NG1yh8#9%!O^7J8a&%xC>AJGrGW8lX>N`0q2ISML}q?hj6M28 zIVp#qgZxrv=MFnjjx4>Ka*ll!0UxjNxVO+}1oA9_Rq6J8n(sO&?=ZotKjy}ZrcnpM zzL%d}){eJ5;Wm^V{m!o8ZC=7N@b%>lyGL5Yv8d6y7p_C%hnB09FL+r4+49rH-#j7c zHWKi(#=yMBUyD-6=FwQ_;OJt!WwCB?0J{&*{@PU?Zcx*n*xYZ)zuZ!i6V+pBOr);RL=A3i7>g0Mlj~WUL5khjL$?6_0qXW>+zD`G^1bj-ITvy z1(_DB)w0})_)BuW?Rj{6Lvfe2sF}coFVI^qAHJ5V0qkKY;)4w{oM>s=N`+$L%!a*- z9b(Xe?z!u7vt9?rV)=M+0Uhr4*#>GWBDjrWVHHd`8i{M$Ox@eIL?}9>7~rVG?|n!O z7ECj@^5qv6O6}|XpI^J3iChFzb4cOLwBvKeO==uu`3Wr_MQvUWP`lW^wypKY2g&TY zje$i0mSJ|T8j={vJ(Dc4`o$hq&*ZAn@sn&s3m2OwhXS;T!w9f&ZJ&N_qFy@PIGqkO3Tp#OSKT<&*=1K zE&2oZ6<>CnU0%1>Yrcr=TBfDZPazAiZ^5+-RjhuI3DvfLN#-}R`BDL_u=hBC(x%>N_E}&x<=mlPhyM@ zSm^(71?9@7c>CPD7zVbGr4Zdjbc|`Kz)=JK0ZQmXgVY-z+6THBIO3luz;zu^HypB% zyu(lL9*#kjMxs)K$4`pfn~5!qL&-Oqcb=@)SdnG53nS7I+0w(bNcsU$VkQBcH z{tSb8cliEr;{jidqq za0z?WJNA+;dIIhh3}xWkh3WO%@oN@RKR$`JpB(9Kh1WJ^V>67Q>bB2WNcpwGfURum zyCIcD8sKK?SXb_|y?P^)#FQ1@GLtAS&h%$Rj^*S1Mnt`7dm2L<$ayEO%|VQzY97(N zAg+6pJ}KL79BR6N^NREfEfQ=lcvsnqNj-mJDEl^6bK#(Eoz)f zyh+TV@Frym$E6bbhk$sx!0KCCiAz52qjJp;$T?!sPQ2v4MXS4O$;VfC9oq=@w!J{a zP)PlT)O0eFt_T175VYu-cf`{lvM-rnqu>H9fOU2XnaRy@or!Pw7lu9OizE%$>~(G5 zyHUH+vFTj@HQY}H8FR0eHFMYbMa3)2+vg{zyL1wG#3}}DKwjjoeUlsCamnnZLN1cQ zbVj#>!jJlA$f#JP5THjDl9Sca;BUhI4(8J$*>^0Qq)zEs$9bW?8k(=h0B2302*^djhjNhn4o+UCT>q6cNTFlHTDp zhBfU=%-WS!{CV@W3|svwad7|XVmU|K2p{Q5k^iEDx|1!+8Zq}ClTEuMTc)bl5Anyz6?qf2HbpaaxkHBFRJLx?~|C;pf02> z$>!yHMbsn4tpEEd6p|<1<(5CT|6xLBGDI2U1vaD2vh;WW6?RMl4-cdE$NAp8N`x~{ ze>T@HX zMV`AqZ2~^!S78~y)+SFz=(VoPy_4mqe9|O=oVij3C*PB>mfR6)%wN_y@}Y^@%e^%I zOR}5mj*Z0M#BGd-9*8Lca?wAC5bg)6QK#jL7rGKdr9f6X!9ce0bz$nH`}SBfyi(zI zvX!7ogHE*?nE`+C1jX0-mVzz>S%w}sGs`pG7^a9t=hw2V`N4qAeVE3uW87=_~ zV(>tnj2G{7<@(Q(l6K_mC=_6`&?-vdW5-&%RK3k-kK#^-;2y<>$W_8;HmzD^Mcd|J zf?(-j#Xw@NC);_UY=q52uPR(S?SKR0(&^d5j=fbon|$dNo08^K&dbsKHPUlm`UTmc ziO%)knl$|7P zxqsa%s#X8G6_WG5^a2?kc$|8%mA6xp;uC+)J^I1>u|?}`Yt9i`!?dJ5=gtLE_*h-A zXrC)(a=RTn4El)nwukGf^CMH2j|wJnK;?$?C4;fNaGNS+RRQ`AYNi}Jhx~|w@#e+~ zQ3KjmN@^4??$Fp(?@8*gsetlB+~J-ZfJk4!;C3yfM4I}mP|tlC!$X;W9lTPCoE{C* z+jIl3_c$iHG8E1d^A}*PLz;<;6v+3_|G<;sK*m$V+IauJT>%;XoivWwSSq9G4 zgF~0=9aBlkfD6~<9rXUo0Z?RyqfqS*aLGYPGYWI`aqBw$|8FzTW5G^tKr>o&78Mg` z1lD^hl=j#JVJucQK``qIX6}Hw=xsYCF;8v})#w426rR9zP1muD`95aM9Ql=#05 zxmp?7R34$kCVAMd>BY7zNcdJZlha))Q$3I z4*Tt@MAAEP9uSie@~Uelx}}2yk0NofW6C$lQ#j@lWRS9(glbq6$ZhP|^&OY#ba@BX zK(f_g8PA6CHX2no)}+sC&?vT$wbAS0$$mCDyl(hihZ1F!n=@L1Vx+^?2~h5Imvxm# zxgaFciA$er_9Y5GC`6`jfrwt21x9@B5E62&6N);3S~y)luFT?pySTd!%5hyf%EK+U z4lb<3FuQa~nQpSSO^g`%sI|tRFaKO|rHU{ybu)CSiYTF`^^NOq-`$QOMb?=-M9QN> z{e=*Zsfx)w&R6P%i)r5XTffNR4OQR~F{Jk~9h}I` z<;rOJ(3t(`xpJ|!$1%mWafMQD$$Z<6W&@Bq{A5ssCD{`R7j))LGlB>fGq;5hfHC|W zpR2I%iy)+`IIubgmhw?%{L)w>IRiFvs1{ZXs;x$T$tjhht+)nx2?eP|175ImDaC%j zzi${;8sh$Ge8ONJiY{Z1a9dM7n04;$ zm_dg5ayKR1l9_`~@S~92@+B0Su7oZ{xhK{3GB3W`Sv@)4p?uU-@}#8GOCraCp_o72 z6}6qvQhlv2+@W4aN0_D<?`xj?L`!!a6%UmK4vAX5qZZcdroL^HoKezo7^&8_2iP)K@hsyyhgYlYXWtx` zul_z&*e1|(g!vk7CAY@bjm3-;SQ>@`~RLT2|R^T=?dfl=kT&q19e`d(ArM z3TVutxu5xiwSvF2MYBQnc$!K;>u6Ee201$^g;^Ux=SeN$!cm|Kj9xc>V9eY8-O0Ih zR8~1aAC4rluPRdZF(lRN2lncf1MsUD6a1?dk@t}~e@TYa2m-`sEm7iDe$7Oj9vwYR zJ(m1D6=bSBF+F$Jft4WoQ&T}hLcD57K|pF~CP+-HNN!3c3H)S5&9%(7Q#*`@S(}Q# zDni!e`1OzS3-q@7J+Qtd-(EVGHPu$;g-xdA3b_mT%MEA#1THQ-Re>>*Fh~Be{GUo# zN_!Ob*L>p0?A4R}0iC8Ld42`Y7TUigtFs(~ZrD#5tvVJv&3;AWth)rwtCKQg8*Sf6 z*;>*XLrQ<@zzUodcv23#w_80Gq|d?G3-QTN!tQzA9*E%nGxmXh98G}^ySTUylh#UgU=@{Z%Hj{ofa(IG_b ze+4M2_TP7!FcUNe2c-d=dU*{$xxg1|_yv9_l`pR31xJ4Ueg9w zzn{Z z?K1^#S&Zcorj<-5BJ*mFJ-LIm+_^{`zspz@hfx(5qC7~njxgWmuVpzl^2(B0!zHzW z-hS$L9m^5nU+@ALQeDBP?(;y$BhCgL=^JZo?s*0JMQv8dFZvN_I}IT!Rq9==kV?oa z!`SShQB|Y^V)yd-PUi<>?-zr!vpwP+>j6DKH}#<{X+C$MLe|h(ZPSF@di1D>&N95A zhF$055vsVA@Z{9Ujx%E2-_n&wsere8$#|!v?Q*_YBe;~tbFny|%r5DE63U3`>1_3E zyAsq1tn28uBC<1)t|s@Q>i*-Zfa6EwvaZ_DQ^kL8tbU9mJ(RC|9GF8e@iNaARIh)L;RJmWu1-L-?<-`LhB*9OG^O!lD)wJK!Wn)lNb@D8tDg+5-32TUNc zB$d|Agc@hHr&8!Gs`QFZapgUnNbNfpV5l~01R?TGSyDD85V)FDxt;DIHzyun%AP6M zALP5&F6lpkoLkJD-}B%5&p)(}x_>X8?e}sdmTfA#S$U;d6RX4aJ8BK49zgayx!hLt ztQVbLvk-|07n0?@2hnC(p|0VILPp$r{b!P9i;ST#qm(mg6liA&oa;VrS=EV<0rpu2 zZG6Rw%x0$v?z)INttcC#MOqD9pOtuD2k5qf^L7nq;8cCp2=n{S;Ru5ka+W#i3tW%KBXF_ zSa%qv#vZ?}wBHza0_n(7c?#YzUo9Mw|8CY|Dpb0t#`&${9&48sd_J|bEAtsPh%$*{ zR_M%^{;A7eiIV?nha_@k!Nk}hwHLYgetQPprMb5q7jyk}s0>MuEUVyDI+@lG(X;3r z>CEYU6A0_C1X(p&&XI4hBd8v}B3Nw4tG1&eB@7vw3SuefsHvGuZSwq*5KHK+&p0wR ziR5orTw_RDiw59!7L;asJ|Zlq*>NV3oIZWYSxC33WuD2Zr>()UEl|nxmkOlW%tLn| zT?-*q{D4nUjgfPp67!g%AKcGZ`i@5iU<1Mrj&uKz-c{(0XH$Zx2_kD)!4)HB>psQFY`xD3OgLA@ss>VsASPYT`#d4|m6Bqd9&ZjRPiRfavp75z z69Xzv6D0#DSZepsV-n*7&Z70K`~obBq3))?2Fx!Rb=b1qMdoqR-~Zcs5<_oScLg*h z5Ko&AlfI3Z<)3}1gDeFvHkevlN$Kf^ev26tf#oQ_K1s}%e##;nrOY!cTEUCY{4_!T ztlH&jeJJg}j!LOX;8M{ZSpBj45v3s|-_4*>J`C>4=Q_Lc=X(xApeJLHms(b=zHH|c zWtG}DbF9K!4vI4ER%5&Q!Q^MlUQ)q)I-X?ZT?31L{>wXlvqc?YWbAGP;?2fJ@HYz9 zIYRIarg#35;aK}f@w%-+igkuTtAY|7PS$&`=OQ(ZxsHW_?E&LdG9_L-z*Ji>n9WI* z6jeAxp2sQ|$L6tH>i_|MA^J{2u*v`a`6Rp`+23NJ6FMn#w z)wG*%XZJ79DRObwNy_I>xg9*O86mo6gNEr=7>^cg1-3UctZik#pY-#)$7vt$1L*Vb z9M~6O*Y%8gr6$U*)@pmAv-qRbs8jBM$~}X&PJa8lO#*-1vge&1LhzDsX1AIBsRZ|T zX3GSit}=EQH50K;WUrMxn+3UeZ#o^^<$dN_DPQTzq+kRUkP}dp)jrT!bqe=iA=?02 zI?R=`|KHNd!DySMjH-vO`}q?T2(qtN^V7o9Ebo(5*N3M$G^TJ}&?(V#HyK?DjF3ed z;03ri-nK4W{d+?u8VgPnmPTn4?f#lQ=j*_)kK@(8@@Y*ugqY!pWNTxJB2y0zFSW~! z-_5QxYBHWa8bQaf8qH4@@2X1vd&5~~4M@8fIa&^R%PS--hn|I8ELtEp{>3013B% zvRcmdsoS{cNiK=x{{Syxp*#DWwbF6#t9(jjk^3J0ez6b_4r}ZmpQ4&u+Wqg1vk-%$ zl9Ze80yav=TTJh0Y3um4pU5ouT0665xM^Eb#iUg(rlsGtD>y_4wbjq!ORv?UKeTvO zg-sWSLmqHkM~)>KDsLHMT=`b0BVay=(tiB1g?ux$5L1X18s%m0D+LIFy2g6<}t{WPG}Y=ncc5BB&huQNTrU07?&py!+I#$FV+=#WhWl|enm@JJu=^@5ZIHWz z2`}!Sh;k2E$k~RMVHv_7c~X-CP%V=l-N}}q`=`N{C$j@eX5p&^W;5?{@?r9giREV_ zWM;OLHS@`EIe+=|4WZw(X&m%CU#Q}2ScQXtQ;6DZRFPVE0X*Kk#jr_>(zR`R)H0%T zOnIHjWvG04e`|KBgaF!KQ54B5K`=`cNecI zTjO6Nd9s>9T|Y)<4fA#AmC+g)|AB=pKaT`PYyy^wtMw0Vl0aobG=xt=d5in<3Q1-B z7?mO1S79$Pk5!QhiU{kl@$=(#gH;(B|Mfl%r^p}HzYAQr(2Iq2Q$wU7?Rx+GBhe;Q z5w~TkFN1YXwTY{dANpgcJuj#u_rZ1QpQ<<=MsQ4pI~hJywqFd;bs)SpQQcL&mqy=& zy=IRDH#Y6%hA5t~G|Hls8kx&YCAA72UT5xdc7CXp7A!sp(rxk3!iPCk(7F7zLd#V8 zm6Xj@qqT)dD?N6uaZ~&{$9$0?_|l;<=FM&K3vdgFBQ#emRcm@12n1(0o6#*Rx%|!q|qak6*0Ux^?kzYoidG-F1fGryZXpCjpp|5QuNAqvKB_m(1EbUPCej#XhzN5 z3=d?-kfu1DgPfh*vP*C@wCEY5?Xu!3`C-v}N-d1lc|mG{*ya3r^BSa&^`2>a8uJPk zUTYSU;6%A(;iA2;>Bk%xOahRV-5+-82vZK@{_k`bgbQ~oJ=QYx>1wE_e8G|NU;KdN zx3**~*;{&2>gJ!XEi2H{9{&H5Rj1z0}*}?aeH@6HH6KV9VJQ-QW|0qbqK7qAQ zCp+sMn~t7{?WVO@7PEhuwC=sr8H`uNFO*gKB2=_;ogxIEo(QIKfW$(S&G=KgwyBa< ze}W#~3$zTIp*rPkA`%qgazUq;jRwGF=P*EGJuBtCa5r|M{(yq(uZ}!-Hc_0XXrix{ zj92-!>3XykOp4kTDcXo(xMW3rH&k@cFffjH^H!BT<5w$fp2qEo;A;K*3Fr}@2NIPnC^72P<~grd&nHRIJE|Q=MSx3PnNEo>G*Gb ziB>1c*Va|_P;YYd!gJ&HH??#gO&wSsDVEbwuYs*1CAZvQbH*}L0@`z9#v&!~(hH@- z-QxEN^-JJ6`+ZdO3<&m$9XK#jqdXl9C=DIO>Oi0TKjeeg=6JuqV!C@Gvab9gvf${ril^94jj2C{-mkpSpFaL_{8KW436OX5?PS(iC=w zw$7)vwjV4UAjK67kRy*c>*u z(6jG0CU)COyw+SO1D*c8Q7SX)ZTYIdBQmZMZsmFqCCZdOTDwpD9|CG* z^XEWJ^}PseeJMX0DqVfDtOkCi{5}QJt}jHDaiFk6@s(m8M`bA_QCx?6h4xmG(IGr} zKrT4_Rgu{fYz4J+>mCSG0>a<}jgQ@mE&ZLSS|21dYbH|dEcEsm2R-15ptGQQ6{Jp@PVHc7U?$cBf$a?W9DR2r0#*ohMlfwGn38nKp9c4g>~7c z`tj3k6X1URuGV*j=bgYd*9L67fV95M?DY!!klR7J3E0$D+&~xN&S*_6v;XLEcz;9} z2%;cpv~nKJN%QpWy2?DPmgHsfts1Hr;3Nb>MGLmpn|;>OFjh})DbCAl8!F_Nf)rVw zt||-H3ESB#AMVXoaPt*)?w_3kD~^tj+gC434wGa~-I=cwno6Kt&$2#=In#?MGHD8U zyeuWTKBNa%eHG>=3E-5@a3*;#wj&hjb4M$VlR8%l;N#Y4^5&i7ga$QrB^qK72 zgG`n;lG(A;#`^_s|LB5L9+mELocbpH@g*;ovTC`06EN{k$k~+*V2rsG{zFZlZRK_r zuQH~~I?ZFlt=}GOTaWYKY$ zp$P=#LWX}{vm}_GVnxc(qqZJvse|UBxxcU&S=Nxjsmkyb=BEMoqNSfKw1B_CPz)Pu5atpNtj1dlg;^L*hsev^ISen)ME?9;k*un$Rxo9n zm)AKs>Er$D5S0SF{!LEA{XTSseg1WrlRETc5^=@hVa#SwMzrsHDnH}=?~Rcw4k*q; z#E4t8p)tNZA2KQmY`(Ni#j#0+6LMp}dB}gO8eQ-)T~u8B?P~Qa8SsCLltLSB(bY+^ z4M39o(!b1kk*B?1D3aJSHrHDnH6^9vjs*)T!vYKo!uDr2IEE_O>vIKgNVfyB6{s@@ zleF|zX`cp3GG59c+PezUHMy9)3E2i53dx#+Kge~<2R+>ghOxmdx=n9}-WW<`f_fK? zEPfL5o}MX-CB~-sveWIV3TaGn0$Fn%EaR9pjAUpMu>KDA(jX6^y@Rwr6XRp3Hi(?~ zxNwyDPxQpBVGoWYB?$LWNp2mXH3X>rsdyXt>;|cLb0^6sFbr)ISu{n0`Y?w zKM;INX4|M+=TuanP+d7%7d=eM#tC!nk~V<#hrZ_~iiDcf)`*^1i~M_|l|sAqn^vRt z^#(1E%)w%K?$s+f^wleY;W<+}lqjS3jE;PH@8;7h#(KcS0h*@UDVy`MFBaesx!;~q zz3t!Hp%(1XF<#UKmXshk@$_>D&-vi7h<#OYjL|cox|&DM!2SutMwT^%j+B zp~OF6ptD7IWe6Y5t(D8D9Xhir17^D(a258Adnq5w#;nF!Uib8 z8)QjI7jhJRBFmr(p^*=;;(2tT*e}aKsSbCY?g4cuMMPd!QFt?^9Gk1CEJ11uk&c8l zdjGor1^CYQ{msBN<8Ku#hB#RY)Skr*Lnf2;3USL=NSCZGLxiNylBhJfmXU-0N-8^| zHSyc2w}(B+)sG#oWGdWoXj78Nbr^6p1I-NyhCP?^u1GYn%TfSL6n6Svb&c}P#>Kf} zC--`WQNFtC*d0FkbPI;Lkg8l&>x$u=r2NSmXTG*xXBpFI9(=dDrx%OX3IHAzY*+$N z(=Q#E>o%vFAz$|Ju`?JxW#DRm>93ozAt?TkXa1pLPH3Nu1~9Qso8x6k3D5*7Wn1N#2^CzLD5PeL8Mspbur+B?bZB#Fg`ljS!uTz=$_6oE zJMClz#lsT$u>fxN^%O!Uzbk7!nj#;0ysCRRy-cMG3-+~q;yzC`&SY5MX7rsAeNELC z3-5uUz%*QUDVA3ulHY_Tlvpc+g|t3 zvo?BtvY#6W-N-e3lH5d@mnC+`vTC(k-J*BY=V{cUk5~Dnd>D(jPzqb^aw3@)Um;oX zCf&iYmi-h!27zTO8NBL+$cMjSRCqyO7GPXJ|1V$YlatMBR;Gs3;VuiEOQ1wZTDA;K{}Og zk9MR&f5I0vF;~oR-YWrCl$%&%_k?;OKN+-cr zz)HK6%(X@686K8ejYscwJpa9Mvzj<8ZdwAUzGV3133FigqL8X+3WSzrx1||Ns=wih zB07Fhk2>^nRC?x>a>**lQ)d(HA9LF%BFU;B18!~-l6FLc^=cHflOj6tpp(=dZAZXC zb-{o1u?s97jQk{NEw9D78->2v^Q)BV&b0EM#{JE!_-IUU&2prknT zey|oRr%^2aF$Id)6r9b!D(9|4J8bt;%nIrZ8)(++uOOzwY#P$8$zvwtt~0oS<%oyE zfrgy?Z0XHI{S$H7J@T8QG2;k>pAZAAN!DT$?w1ILujKS`=o>hK#VE#ywRZMLYP0Fl z@7zsG@wRP&Tc2w6&h$1aC1&nSda}ZKss~oMz%KRu@B;t!N3YWJ;FnS1y@MuTECW}8 z6sE9B%M=E((x>%bPjtDy_vMd~zV{3e^3pExvM=y{9bQwuO~c3k8>0;rk^2rm4w1DjGBoXaOR*b1MVruleSiZ8qzD%XqV~{le;R6#tPaZD* z0{6C>VDBU-!t3SI8~5zYO1Ly*ly*d=`?z{09eLWcTI?HUY>N=^BA||`XT4zmI8mUQ ztve1;9pc=_Jwox)uG~xMXG8K1FP)Kc#*sAHMeme4=uI$QeW>L)B)ex#gZns6^28ym z7N}?bbiax`M>m$Ug zgkTu+_q#7y-RggL;`5TSEsEQNm+r1Mo?pNs7J&tktM+K5wD3I=oMz`X0So5x-U@ zpS+Cs|DeUpV#yK8NXEndSeV*l(I#+;FXKO7cv|T1=Ki)QUXP(7cEi8>A_!D(kzCUfP7#Z~MU<7=CJ3tXk{|6id= z@jLyH`6Y|27s3t=+UXv%sfxtY$a)bRSYO{Nq-??Nsk$0$2$$x|skP~88K)U_4QU^z zlx-Rk*M)7gDmy(Z_QTvS?1U_v4>UORvfP#Lm(B>4Z;A!huSO_;Q-E7?@iX_z&bu0n zx6>#Pv&HxunT^;wlR>rQ@=3eoOj$~#SD{5+HW`F0C4}IjRw!B+f9AW>p)ZJmf5<6c z+{XR{uu4GN*!>c=ND=19o*13 zXwi=a!k0UmLUWXpUf+}J`RH#)d=^^m_IQU|Oj-QJ(=+?}46J9DCwG{^w?R#>B0r&B z29q-XBdOiz9mkVz1)sL&Qr-hPXYtKgr~TiXQ=EB|;>%w=t5-5A%RF8H`-!=>5e4}*lC!>?xB#_t>HwzfT^ zm+RE3#4at?09n4bFsQT2*Q<=YuuE#m!y)FGOeDYSDr?=y7{vfgm>tS`l2b!8$gcof zZ@<@Yu)+l;n?0FP|3rBxEKzL@o4dt=ZOumTD}3E_oj6c(cr>1xyzq;#P;``jqw@mT z5aCw79zDU%=}*cpgXMqxeUcc4{VXK%b8JwJhY-uQ4kI>C7T{kbJS_2gb1RuyWBUEA zXE_CS#C|zd!x82hqi4V@>$Te(#=xpEVBK$6B)i>qzw|d@`U~A=1@%18GMZlou-jGd zfr26kWvfN#RB03a7<+3d`0vAp2BjGlC~Fv&YPn*PWD#I8NymXUSf%^}GFe|d+%d2> zZpD`PilM+G$t(HPF)4tDfC$t2eM{K( ze@SLtUQR$j*O=rNnCS3pq;%50NjNo6TyZJ2P_b z%zG>o2CCIOmUG}GRq`|W5wL6x@##$@7fpJb-hLuyW0j>SQSTx5Gp?sXR>*{am1jA~ zjrGL<5uOY*i{|fBA)^ienBz3uVdp<%PdyOd6{^J(;d)t0jDD79p7`5*GdA@d_6kZ+?kG*6o$gaiZy%zi7FSts{j-aa0fYJk= z{UJg31h!SZHikTL_FGVWd12p2RwxHZJ@M;s@1d>hMp>Jd<#3w~br?vRx!ll{W}_D( z`0WZ+0EFM4@&zZ=0K?9XnI^Im38NCWPN+>%rO`4`|GR#h)Kf^o`HRV8E0ZUCwJI6Q z^va|MzuaP~V~}?vN65gK1WTNccxolm2kNKru?8O%rz7~ zG<cXQO$^^(I$Qz<;H>Wi%RopgsOdx(^){gD{^Pc^ zVwt4X!gZ>pqG$&>&#h8rm2!)Win8AXqT5}6yYxYt?0Sh#2hg{Z-S?yomoq?oe|KjU z$KK(fD4&!=Zz~M%2I(h`m#glvtE&OrEeu!$c+P!QHeZe3+3Yt^e@wPor}vEMJQmu@ zKKe#4!OxYOy&TJna54mENqpAFdls!}DwHbT)ap|nBCXxe!!JzsDVvR7GMbV1981OU z=hHQKLZ-9serT8?Oc-SLkcM>2H6~o#Yt&1Hc>+!T{sTP@UTo_4ssW0*)gVAyg@OnV zzdH{R?HgzZ)fdfHzJAKbqY%SpiqD*Ur%%8}Pj_N`4lP@8)xe;Qhi0jx7y)ZG=i}NQ zb-)9SioC9b(3Fc<`Dr^$l%Tzp*q0>RQ9DG~e^Mr3{~R~W*pX7jW<;CME|n|esG7B5 zG-?&VYjXBkVSC@*9sewAXX1GLXseN!H+UP^h5viwFmiliQQoubCi@}SZFGxXWkQIe zU+T?bl-KC^mXW6Z?YymPV^K=7Hk*JMa10eDRGkr|QG0C`QwW#Y-%{x59D`VtRQx<8 z*vrUHw+$sQoimS0-i1WVUenh8Zy|6oI(C<(h(oU^cJ7FBWmi5lb?hXj`BLa02%DQJ zo9*HHsQXVs2(0i}{etODEk1{YD94_i={YGBL&~h8LX=7yKP6Nxk6E&(_NZ zNyhPaD4es4?HebSXZgjP8CdSi`X{`A2O1H{{A(I zHGfF!Lh(5fo|i&9HSWx_=sm+zay4$M=#m)!Wd{ttPj6$}{3jFFV4&B zdiL)P};AId}Cw zQ35=1!#j|*QhtT%-M@d894_;{=7vEhp9qL#MPM}cGL7DF=@uyk%zqC6$kGNMk98L@ z5!#0L48xy($T1=3^ z+bRrlO+hv%e?H@BVbEHOwwKHhexQ4|tgTtt zA&P<$IrLuhoSoS22(OBVzF!O(_#&uDvhnyidbvJGEazfAO!F0D!6@$eUoRAU+GKgzrXr6jxaCwLtZ!|r*suqvVdHY zGe%1%dej!+i-1YVzLdhE)Q8Y`rs zVicFV7x!b{?D;4$maJ?vq4D`S&um)W7e2Wc4tG&cnj>cwC_x}uD| zk#j5PphPp{SwoL+f>3?YiH^{~nfbOFNB=Vve7|My)`$F~;cq1&YF!iQx^g|&vAt+6 zac}$vNxn~Zuf5@WX`lSks7&yGO=o~?@?As(P@7+JAzEd#C#5E*R>E$mAb6%u*cIQkGt0@*;H=uVkr?!jMCD)2at}XXLs!irS!Zp-u~=K*_e!d9X=x zV6eQY4phVc`MAgCUB*XN&y}jY>9X08-*0^rc`N%|*Hqp0YdSd1uAP(K=87u%k<(ja zdh*+B#x~tm!vEfQzaOP}gg~0J$ec@jToYw5z<<_$-$CQEnR2^Bhe)^*);#g6_RO>t zc~|28sG+}IfiKHB-6wi~o@`knr*p}P&6}CW2u-V#C8GOKWUqBP57T9Z;d`HHVYOQv$; zjMmIFR4rKDBWPYe2*mYXp#I6>uF3i)mwMr$Gh)-ER1j1Ikf{cs-uzEAmw5RfjEYVwD% z)Sq=KAGHEDVzghqBp2pPxpP<8$5SI?dXsL@k|Alb(xyaby_w*Utry^2 z<_MrsFJ8zy(x9;$uq44F-(#6=@+VIXmg;5Y5d*NVrh60zcp=&$$gTg7F@lZ>eXVh%c>hsvvnGK{N5QCt9C!))A*yw4;6Vc5jy zrnq$)SScj?(#xxOB+EHG+3G1k(7qgU4bqC(J#;L=nK)&JHGkI=vu1y8q>I^Me3ri1 zkzEzM5ggJ}^{WcXn#refXqO3-(i>>jpNcbJmL}A~gp7Z)2GS4;MEPU~(q0Ku+%n?v z>Ar*`x$2AgNd8x&<;3WD7ebSNkTcMG$Q?TgCa?96RF46j3_xPDu0f1WcuykvMiwegwRkXUeTZG&BUwap>V|HihM+N;a#p^hndHgG{+@I8fp4!w04trahyltS$3aNg7 zosmFSWc1s12^fNzz7Z9qmUs_L5EFdwEL>b_Eg%MYxV&;1ZtAIUeD~AsPrTV+bCuzK z8z<%tea8ZpaA8=1N; zea6!r?Bfq{%c{h#PMUbff*1)c97K<5A5z{7%%9z&dJG@$}FIU|KFnI853w zdRrYW@&fjeL8?yR7$aDy1h>jkwiP~ksK9uuY(yGd`_Td}U{mDvTxY(r}3D?^2;(i45 zZ+uSmsxX~cI_n6EgdMOFj#=Q{VgNs@-0ixqEofeyzwLmGmwR1*A~U%^FKO%oPX zmFPCHcxxam=+K!{`snqCw)9Ib~P!G*X&T^>CBD=!QFGsB9Fiq-#%xE2J!@2Cx}Eo~}18)b=dN z6MkjURJ1dQGR6myGvRASby6$+Kw^_P#&+bQ4j|uEU956gU!}ws;>}`mOzxTrMyfIx zayt_Id-vvoM+JL}eLbf!w87{pr?(09yd>jx$PszG7f(<(ll;tMg zrT3~<=Q(yzC2UcP#r0%G;TG9ZpmEtuktlW!K8v1K?%%siSo*K&UhQ`2ArGnhiJjob z0L>Wk8R4BFI0ZrXT1lIPKD(FbeCZQ8|IaTB+W#4Gna$WD+gj+oS1IDFRP5!grHMIx zpgVKWHOPTh1D~oX$S$EaicY7cCr$~a)z9HR87Qlh4DX4Y9i91G1b_R#49b^&j6Oa- z&L5ZF$=tK)<^N0E*K8nDKCju7xR@rUYkimI7>-YL!gnK_#C>B$*Th~?hA$N2%I&Gc zt5>kVX?>3yf3om7G6r3LA?lYXHTNMQX01#YvNB^)0Bfl79{USjQ&2PgR{v~7LQ~A~ zP$<6SiMDF@Mu=FUTo2XV{WOlyiVu}?T7GCF)7R`PqJrnSn?*1z)p#qrf3#Dn^wi%I zvo8F?g_TyjcBSHNb!m3`9s734eE{&eC8kbXAr+lmYw1KIo-VD4vRe0yp~>cx1Iy@u zH1M@DiTvF~D>LBj5$!Pl$T`bIn068OD=zMR;^tF+S@;I>yT0{&0w$GWJS%2}w{^Cm zA;mxP5hg83&xs?zenPYD1z7ijpE=1I>naw*VdA$y!{ViCC^9}{yc+a&$?`x=jhdd~ zZM3`bW)mJiM}ELW3o;anozsWTV++7i#jF_q0cI7Qx`tzD;$NhrNb?UaPHj_=~STT7f!pr!7jYO6x5H+F)`D*W^O@x>ZM$cj&NG zkauokQOwe?qEqx_nlSA^?&;YqR)DW6v3;1~*XDvd&SlDH*JHIuWzYyGv|cIR)Nn2T z?6Gy22Z3y`6Wv^#*(+%Q;mbg?mEz2D2$?`thK+;tTt8b2*Eh*GR7`v1%&DQ`atKWG zQC$juW_q)t>|*!5HC~Ia3o{;!_IlQO=l(>Ct{0_Gf$douOR+gVy6tPCrMz0SRvs93 z(h;TuGp~)4b3F}9Q#p2zf7m9hPxmU^2vm}%mO0E}yYAU|vTg*dRU1m0FR($-O9eOnAVJ&-g%ul9UBeG>MIgK5K6T7V-M*sN`1E6%asc;RN{^w@HHm$9kx$EDG`c|| zuiB~xk2lJY9;cCagpRI}J%p>~!LYyO?kd0@jZrHfu6e60iy0+LB|2$pSsg@**T_(h zI%Sd%%9FY{br`Zg>wgzN9XnjMk}2X~3J%c_;JfvEGF1ysc)M?xikzeFOxaXeHwiHtV zl2I}e`@Jl}JAWa+O|fCK_cG=^Jz_tpaHH;9&YrBS^P<4TxZ4QqmNG)eCqs?v^`qr4-5Ito<+ZE*e~Uzi zNNKE0`7N_z3lOsD;$UN^ckA%19V7A=Q%lL>0o1Z3m;4?e2JVQWqc+9SRSDDXbP0jy zPhXkKJ7D0o?xg(auP2s=zD zq(@*~@?XoN*nW2_LUCuc0jL;_LBCjDkVl_}W^!m{+z6S57M zVm&uva_}87kOaK#0_%8_`coD7nMbH1*6>^YsZYciE%J3KL zwa3vWQYQJRDUjQ$HfV-eu_@3%eOX5aANke)o@4SqCrZ(duQ7d{@Wh&kYiE#Ul#7C~ zYYftx#*hE5MrBdnbtFBrnc>Ko(lWYt8N!lLY+#~QuoQ7-TmOEsy{7U}=55|bP8|E`ZVc|xlZaAm{)4^V?)RP0#0G?)8u#OQrH{ImNM?o(OzQ~I~o{EK%YqTLQe z1dQPf25k-zbT?AkZ3#=Y9uM;6XQjo9VelFUIBZ#G4~x4UZpL}37|qS|{NS#P<$?u< z!swBN;Y1F#c=ty!0p4&2ZOvGD-Tf#=R?zYqZ;|WZ1|ax}XQzAHigL55ErEBN-$+cR zAFbL<2p;x#)uf_KG9Dp|@frSK31m?;a}wmTD!I4{J-pym=lMAwgkhwLCM-m-&fB&i$55Ej)mBBQ%8kE)6uSpZ`>b1GXuKU zgQfu=MuDW4xU4CeVOv50%7(rhJ=sHDGd!2P?@&RK^u6^h@|DL7Q_3e6_;GU8cKmK^ z44YRaFYT?MN>6%oQ`%i!{xcErsutPYX1zYZSp>C`P`sv-F){P3IVUddcYaH&Zx++Z zPU*XIYcMr=95KW%-jX45Dbov^18F=WJZiOq)eWEX7{>>`fT!FopD-K0wVn5-24*U& z?h$xbK&q6<%zPri{%#)eJT-g!P5(FUB7yAbOhx7373t%;skcnlX2GvTLYS&oqr-Dv zuKA1x3|~l0)Lj&1M;^6}mXirXjjLJwpOS#?X>m3oQDAy~g7cs`a&_ttpFwGnaO3C- zJP7?5>w6N)>y&8<7(VYN{7>_4PmA+7({GQ>CcB!PxNI_*!zow0?4La?=cCu-xarf; zO0xP=@jU_M+HdkrXx)9!ZYLL3+GibLTcsde{!_S8+uyj2rIh!`hf|0eWb_C1Az5h%&xSt{D;mr)X~xQsHT*~j`k%z@n56`#x# zz|RenMAu|%6!>#(K+p5$DvPZ>-St+yM7ByQ^H>Xdt{GxUpGRY5MDp^c%(x&9m7Mshr; zA3X@oP-VBDR`Z&IiF!kQ^4)G?_+b=m<6hAj_Kf|KiYiqVHSLe>SB9;#4;c$E_K zQ3SvB-ivQOt#bYG&2cML)Bw50HaS-IsID&sgDW| zOXTN!1EFP9BE=E1VfcMn?)3R5>0GcE~|EC%#D5&*7nDxE-SGy)_i*l_q#MRC-0LYQ;)#zSfTTZL1k9Ri!<4mNt!CNK`R@+%&s(PKs-xGtYE84P0 z=}ws+UWgd&oEZj<;A7{hN>>n};=8YD9^f;)OiqptqDK1IGns3yZwq^0XZjmM31yZ( zVKQR^;8p3FV$9Kyvx*;IG^tA&j^sHzNdLCN^M_wq-R!BR(2 zq7zk*Dd||2+@n$NnFNcMvuctgu%n~GC0;5lhTL%B(D8sz{wt~UX3uvta|Gm7D2_W% z`W>FVk>Nr(bwdG%(-6tMz^ZY>E7%~}OybQABiBA7U%BBI1o50jx1@9dX^$uv0}bb^LQf`D2q*X2yj*!|%#qI>H7qISbOZ*; zXS^i?V9Vxjq~WK{O1FJ_E2i>1Ux-w89JidIZrc^}7++>c=6v?^y>MHyw$!_}cvJjC zD@HCZF$^Jm%%8T?p5OSC|7XqDvbb$2T~tgH{}6+*f%drywnD_2-}RyusA(OKQrdf| z>b$D*%ga<02Vt-1M-}95dMYHHu@vTr_I#yW_IW~OI!LV^T%xul`_w4u_=(coQe0+K zY01loZ4^}5bipR;!xp%p@4kf1+YdEW%z~Y$>Xa^ubM%o?sDkd3Gf}nS=|imFpLra{ zD9z-8BUvq%>7^GsQ9enmCHur+r6$rYsoWe(4^{WsLs>5LwAJ7+W4Kmjtrf|K;Jr(T zO{_6tDOa6f^NRn&*F%FKw8^T+O0U9Kyw~7-VxE{BpF(XGBY#4Vx#946{0l9o`AMoi z;OFRlIEP7O;9s?2=b-UTx78Qu^gD9$wgE^^gsDf9|B@T6nUD;X@L@!!Z@q)Tvgs&G z%5vUX7-?*YwaiE|rW+XQ(z>dZxN6Q`eqE2hZ-Yu(>$?Dgx27`3JA{|TJ$E6Z{&~N( zeNXI_JiEwkM^rj)E`0_LbpI0ZY!U9>WMdzO`wjrooHezdab$)2Es&lHE5R|&WJIlE z$q7L=2bW$0#{g1>Q*qmxSqebPubVI^NAI!KsOL4j=?-wE38AZiakUx`3R0VUoyo6m z3=aYrgcBr=+HtE(u?Eau1!-s{Sl_>Ci@YEo0d1{LoVytpdpHSr=V4I_%Pfx*ihr!f ztN58A6f;cJVnCUTJ`G?Og5ae9_>6xwX` ztf|6wPl#;69;GO+l{+i?(kQ*mPlAbQ8^A4ISOJ{a#`K)orPseYo3qm^#MyQo> z;%${+rE^y95`SM=OmXA?1yB~R=@%U;f$9^ujnaFB(s~iNqa-BgME52(257-;FXVq% zbD)OMiG=$MH86)%Lu*?L)4wMX3MgFt3HUPLXEM`R zjV~(@wF?oY{tzoU3S}ATz@`o!KF~e0XFZ{7#Aal8#>C4o`0?sWWx(-|9|y-2oA-jN zN?>(74M4TR7{$2bOt~I9k^O_od7EPjv^NR$eU^tNnraE9gnrN7 zZ1{`#@r0`_ab;YpJ<~Z8T2Y~D6*SMp9Wy)&Q0Q8PifqYlaW}xRV&M4{m!WAhMMLVooWcA)`o@8k1zxGafhMPHs_;8Q^=eG2?>L zs207ExS{eoY~{f4H!|7*!_>H0)(9 zq76DRvPm}VS(PYdd=pL1j+?`7TQmK^=7hdK&zFYE@qXFAP(CXRF|28NJ}e5UIkX)NlG4q6{IbIXFy-ZsLx_CQq6+zqnQ0 z8|@0cNwzO0B`R%UZ}2DCn#43Gl%XZzC`lS#V__E+Y-N24vq)7|CXzT7_HyLc zvT|UIc;AR&jgJ||Jut_QWRa>j$dfoedLFUlc*o3?aRy&BIENf2LgVM z62|n|RR;Mt4u|c1Nv#@v52o|RI_Z~OqEe|GIIqdV8Y`hMkwhkiO)+XFdlYKT5{CI= zihK&94!?dn?51^$S?Fkd3lS*vQK4^Wr0_N|xNnXSpDNPl!u$(X`R%|K;F70}H3GQN zVy}U-leeM0vJ&9mp??N_c;AXswqvh7GYow4Q36ik4)`81>p4uZB?+n=9I+xW-KIQv z&4IaOq|+vr!O5#;y_`ps$*I{LreY@a)}~{TY10be;la1buc9zJh=ue=sU>Ed(OjSU zAdyDiF_Uu1{{TK%ryhsajn5~;f>#(}h@6=@>6g%nLC^SKtQTXKJ}b$V;J>pb5;2J* zj+Al1%4VZRxhp*jQKTfuzpz8w{{UxtF_4Ztk@ymsg~;^GgK8j4tFHJ<4WtRf#w9-agIX@Af2}>5*{{WHY zT5c!$AF)62*S?2#M-;Mh%&}@rm_<>-$R`BjK6HPl5^5k2Z zGspcIMNy0h;|^H2*sWEVN|DCwYg#Q1n6SJpTniDUQ{!CuScs0xwemB6semXMQ#PUf z7b8VSl;{hi{=JE|-}ilpFvQ=dw-VucO^x5TAYM(S!y%~~kxcXehXHVAGxPuS1$hQrmEnAIn%z zv7|Dkrg~(M1RMKOEmoQoFJNOBe;nW7z zBMVoJw$e>7(!8-50BSd zEwP_Ni2p0B`{)RQuG3(^*J{OZFyB;xTxHc_0a86$aJ)F(-NkV5hD>#fn z#KNU}Cl9k`#!${6$~5HCK4?wyjMDKvHVrAUG4euGNtY6k`tXzxcwO@aC!T-&hpXwZ zzcnKKNw#G9jTL0tRR$%iF~P@?f+euFa}_kiq$6z7qEqaQ%Te$(Y?@U?{TUJwl?9lV zknUVbT9G&DGmIuJQKLSVEO=U{1&CU_BAz_qX;4`NNpjs1_AEl+lCzN{+Y(7#Bqu(q zN1KbA023IEcwwn1E(2`H)5y||T-iBZUJ04wszwKOAp;SDYb&?eJN2n>=YzYm)W(@hhG(M0Q3 zxlGG2lSKSD-6#?(+$Nu#poaqUH71)%2D?bxl9Z(vaEZYxHtiqKH*M<{JZZ3{HSAO* z-XoIJ8x_NeK{fW`0&J$WN@^NyG{r}z(Bx^$z}EB{OtjoF<(U9ueYREUvraU)mlzBR zchteQ&@fc7NP{9RSyN27RN#%b2yT)|FNAhy$~DI8{0~I$empNGMzNAz!7-fV+u*~Y zAuIjK!{E{~Ht5Rm;!iX^In!v~I3>#c3y#e{f>&cDD-l{ol$R3VVTvg%p9c*gISlHP zmjXI9dNbqm`r+#H{{W1Sc7y5r9;VrxW>J^Xg)mau_%N+5&KP$kl2VDx>6R;Ik^9S6 zBIJa){mg8eR!vEshm>U;Du_%=AlS;SaA1_x$kfS$CUR*H zToRo&*&Mt+S1_z-@Fk+_zbU>LIA~dvn+=nZN@>iBWI8uBA*431B-Kr=Ou=JZCAG1( z+jiR$j4-ZM2DX)TrJzpL51#=ncx(3G;D1t8Iq~uPGL13k2Ma-^*qGX&iB;ln7c|K+o!{~&~5@j@wXkB(KMi_0WzmiB+-a#hfe#

URor-XbJ0>Y^AX^R&ImyP)N79mgu8Eq>~a++}k zuUFO_q?paN%6LGGG-=3+9I-?Mr=khJ8s@-IpEB1A1%v+2u{S@_`5z~rI!U_PTABT) zW?bNtWz*U}^8SSgG80t8rkZ5SVV(qRS;IRFa|aTOMD`n>;n3aNN|mIK;9f{@uzG}h z{%3`3I^i7>T|y|sOK>Hd6O83Hg}hrA47u>_+2c^#Z|)kKPNPpqu}zPdT(1fS1e3^A zks?c>_Q#H-6q^f4k zs4;5)07h1ud=+q+m;I7`w83W7f9WWFnV`m?S8AE)OvFTv=*>3NqSN}oY~Y*=p4wGBaHTP4q8`y~B^Jha&+*Ct|&m>N=4 zCw3!kDn!$m^l@_^LU1K7m=iIP;ubjau?ts?Zl#M6uBapCCJYsc5eENl}PuPQ|B&HZG;C;Eveo6SipNj2s33zIc!Yd`V;BCe7p(tru;{m`jBxrF?i|N92TrrwviA z(McXn@@5g1E;EEPd$Wc~VL*b81+7=lmkzGNQ zMp)n3J&n_$9Ahl_Ake^G-5n%&!P%z*GNQ=KX5T;lOV#DNLv$+O+l(U&>Sd6G;6{8? zB~?RL$r92x(Uxgcke-Upir&!Enoos7#BQ#M_RP?*jG-xM#Ih2iOAkrXXSK1b*i~hk z+=@|tFj$4Fd?ddq%AXH7(uKsNt;VMk3AT{VQAfokDCF2*f=v|J)lL*VDp;9Z$tpOd zT+>JiC5aI4#2ZjW$W9nq;cKb6|&H%o2pBA@(I7 z0!48r(3|rD4J=elUQ4gfWav~QS#>_%4rr&oTm`px5c!E*}<(};MT63*Z3Z~Cv)dG zqfB@|z&IT3BTX4IEu)?qgWV@lj!95UB5?a35xGi?--C$MzoW*S# z$twPZVnf6vV~iyhLa>byf~brwfojA>#JV>7=zf%#cG4P?ro@=hA+RQuv*CV4h+ZKo ze5y!y`5F==?YF`usYF&S1H6otqfR3)$o&cC7O7g`N;uaxTV^LFUys{=fvCoY+n+hd zqg)Rdt5e8uIZTyr3{=5cuiQ(cOOv?fG0FAGq_kz5L~taem|ugA8zFqzTcR@gCYJ`^ z2-ta~PYKDD8z4RTzU3P)1gaElwphEBw(`E3hrC8ddN+hTXv zZKG{Q5j}=Tnv}dUwjX|kg|^#CC8CzYb%Ki0ip@BaYD7TEs)VY8Xc=WN5cMbbh#SS5Y+;O8W@ zM%psPsKDI`X-yO)-b*o9Z9E={L7zra5?GNR!#6)GEKcQUoX$jmf{)lcN2*!*-Ct?#Kdrw7hZ$+VpKE!4Egp`-Uj5jD=i9>^4 zG-1HxLYiut_Ar+w&1B^^=XN`@r|==R+faybJ?y?g3xVq#@=48D`KU2av`$7nV=Kqu zc`_tCgkg}GI1U#k-J512h(n4vGf3xc5Y`w^!Iw^8%jDWO!09H0%#)l#T;WRWl6CIM zT^b;h;L8&#d>G_Yk%TRrtk>&LSNu7kCY@Z966Lo40OLUf5J3bGK@aK;h?H^0{0Vqs zP7IZUCE-a_f=a@;0!hy~p&qs(3sXp9p8`%0k^)|Mf)cU@NVIeVB;-#XL}^(7rC~5& zNm&skP)T&WP{~FlV36cMmw+V4h+EfxL279TQs7Ia{z##WF@i>agmA(i+VW8-;f?f& zzq|Po^ZLF>Kdbp8&+PdUv-iL3sv#dQ`yu}T)BePa{p0)CO3&QSp|j$okkvjsP?v(G z{{Vve>#e)sC~w~tQ+}2GP5%I6X3zU}Hf+DQXZHU9+pFikOZ0~ zLgkV-=}p=*Y|Mz+q&IB9-!n5dXzr5@=$Ko!WqPC^Qh_z8q#;X>`0l#vuDa{4xn~xo QB%6p!+y4Oh82l3MwESL^_C3 z5m6D5-kV78HIk6zn*>EY=RN1V_ulXR|MNe;n}@yE%&eJNvu4fAn#r0OYAdx*bjzMl zFLwwsGlOIx2wDTdVe27A0Kvc?1QUdq=`aMj!h}}gqp+>taToxOA_U%$1o#htDbZnG z0N;%Af|$O?O$FaZXzlU|2$Ej+%PZ;D!dstwM-*H)fEelNI zXIWq}zm|mo_9G3L62ofR!s9E+LB`+o_^r z@p5u<^3q zPb#tSUVD_QFDb=m`N~yUCE!$@0etgytLeTOWT5JX$Ini0*?q&>ZO`k(AT|Dan=h!@ zyfYOI*#0>~>6=Ms^KZRr{5qdpP}wxFVCx=yF7`>`+vdSVbt5~Ekf_@!MO7_B1a63d z0Z_|CrwPu&tV$|9ZI6vw5bDb+3ICb`>7OJ}+aY#FdY;@60vfX%kA%J09@?$OIya3Z-~HECPAhr^cH>PZ|i)P8Pj zQguhPd%NLw?Dp*6Jf+=0Ov!)oQo~imwTK;0f_Jl*PE=nyA|~rdH}}7mu{l-H@8C3k7FyCYU8RNU680>+OCVmh1O^ zF>KwTkrC~o;0Y2H^4~3il#?u)IaW~=&i56og~Z2*DXX6 zrYNWNKE3~h(v*9bd)vM$pcy97F_zPk;xTCZ)()vog&J&fOKTt9in{L9?md4m*v7+h z@ZjS9(Xr*JI_0Jhlw@!B=%}*~E>^XUrRVfGJkB`WUTxYH=xIIooROl=fT9aLt-2a@7t()!bER0)@AXYQCi+gQ- zeu_~ngM>uJF5S0yQzAdk0e|gX39c@S@@VE0i)-Rav^D%8%Ty-Ww>LE6V2Uy z2JN3a%&RthJQ1|`-t^3kH)0P&3w$WDh)fcT`|~b zB1c_@ZhP20u4J@#Mj+xW#?r-(=&X-#VNbZ2i1Qj51;sRW5j1+Wg)cD;O6~6&TW40 zydrk$Ae7%NnCH|7Oe=YjcI8g`G5v2vEFnC8n$|&tH|&K)um% z#8vwA)t=tr|IT1X#Qhgvk(2txWHI$oTzYpATxrY^i$$YS!Vk0UjtVa_xGx-Yl4604 zQVEmjdR#&<@9Mzc>mgMeaS=C*&G=BEw6#%=R0uW`^7ZHm<9E{{_|y8D$+1pvPOQ_t z7gIaDfa@%j9o4Y49c^c8D}omi2G`E#!k%n-m8++>mJ>6lF<1;=9It7NJJlF z3fp3F4>!Aas^e+<+uY_8gZZkjMIJGFN7WsKk8oWan52on_Uuj9h?@EAPxx(;HzFV0 zb9gzZ8C^-bQ*!4I9n1Y-rbw0?FF{!z%ny(Qrbcgcc1 zquR65{u|?Ag+1QoAKr+BYwDOHIPN;?wsi2>p`wpPZPbQ8nJ5d1*le^tZJwkgy6D8V zPp=(t^vjzN=oqw&we!F0@HR76p;v{8eJ!n$qfEhjHd(Rt~SJ60OcFJ*VR-wbuK z@)l|L^}bU0D_(5#OEQcKY2X4bRE5|ejv~))!Y8)&mBj>4ys9BDT!D~=;db{bT%-2| ze5pxNTM$(Q-H#=^5E?I6iV4q3>nKtjJm`}A`XKIR0j1(Bair3_RPbV`^fL!2?(9*7L?xMab4eD^#pII1w5y^z5y@2rEDU*%;~M- zq_Qq%m^6SiwE)Q3Jek9h)>&1$BUD%_$QzJvPqx>%)VP9@Ixv ztmb&&i9nO9dgC@7@CigX!eE$W98ww*j#tM_KD-Y{CLC@Rl_A8Q(9_0VxcTiWv)J9v z0lhlOnOrJVr#$IUV(Z{Im0h$!F}EN~f$4-z3RX>Q+K5)i@^3YbCSb2leG=S#P4tt| z!htI>_b>%rm1F0l<>RLshUb@v2auXA_J_RGR8+2tq}~-wjN3|u410>ji5~34B;v{L zcMO^Yb9|H8;tb_7dE^aGW-zwItG|jK`{Ux`3e8uV_e8*Y_S@%J0gLys#WO zhA;7+k5bF@P-_?|e*Pe5@y@w1PFv@M(^fUXUz;4ST=^K-zUG=%!6*BYCF{XX`HX`v zu}AJSHlc25*0ehk)iqyKUX}BQPO-#2x8q$pS+RBF?y)K=w5Mq_Sn1<-fkUUegDVcY z-3i30X7JRPk%g#GO$b49{waL_6ZjOau_S1lKzQV}9GevBE}Sh~gg8zNnWsXXs=2ah z#rXxb-iO=U*-W5Q(C4$JnF)4v^LUf|(%|sN!E=SSk%tZ~md%TO(w@yAGeM+&Gti;p zOwSm#;G^QqxzC69&Tx+c?aFJUXL-vN)q`@Waote3$>t=8G3xqoL>Qu8dAT>%Vm=&~ zI`yu^uX#d{b3J2c9l*IRt?99L1Ewk76 ziP4Ba?G)G4;jX5((VgcsP7Ud`AGf&fQSdZ~?KsbfUCyBTEYs-XvTxf!;zV;1+Rl7Y zsn6rt;a0B2k8uA|Zl(B&7*Fpw6Bmeqbu(MmQKE;lcgeSc{SUeFn^J~~W>e13gi#8< zP6j+n7x}!wfdtfEm5ky~-u`!l4UF$Hoj9g*v2^yhty*x2t@(3YV}XXKj@syCKz}O( zvMDmIgV;mZmUlj4mvVQ=K6R^C&_tr~) zUsPp&RM??0A_sZlE@JTIg%-19+?c*hJbwtHtDkLkIopLG0YU|Tt2h%+mSkjdmAxCDoY)}3oyM_M~Q-W#a?Yaw;$DUvC zHq+mhGyMn=waxzFTFamvO;b*>EbOdyYL6d`wePKhS{3>Wx|*m^YpX6772283F>?2o zPGNZ#d)BMTP4zA*fo0pNP@$hi2rllxElO0&*k91i$`Zb?g>>5mQ(%t)e+f?CHj}W z!y+oAx3V&A^#IrsUi`%U|Cl#hamNO%Ha1sbp&3tz1>$l4^w71JQ6du zwd?Mlk66{){H<()YfegEu_`E+kE$35DLFVj?OB$J3N2dx{N#hoyG&=#EmdR*b`H*- zMDi{85mc!9a_^Jsv8v1iUJ`F3#F?&`PbHI+=A0Ap3yv?$rxx&=y(W)8ckWZo%g7OY zu%N=PQMoNuqhDUHr<+mT+oFF%U^IRp_A zeL4yE^M;d~4?2!nlNdWcLz$W{z2@U|_UzEL!d*gY>dvzWC00~STospb%F^hol%E!( zHjY`E$W`^?B=#P2?_F4nd6&n(CD!hSN4f)w^B8BFqjdMjxCs0sFfycKEo|ank+Gi;5j{(rbLs^<{O^w$rS{IMBRXA$l1gn2a~X^d zLcSLKn|2^F@A9NaJ>fos57sS0Bwr0Xt6(%l>$7EUTVMsxk)T~gOsl5Ux1#+ZU`-l!OK^X_VM&(?ogKkwWB^~N2P=u2TKVko|i zSV)DK>)%siFbg6}{Bpuwi3h4K>ZrA&Q-wtJ!u6OxiJ$6w)D)z9R&2P9;<=Yx&RKZE zX#1munX#0VfuliJ{DcHa300L`Squs$S{&m;U(yzgw4S#-E7H8e;iHO>D5n&3E+5RBd8euBoxMo0 zNo*(|&u^RBRC9$gT-S-Yx$lVrvfbd|8W-^sFu~wWJ58eiKhy(nU8x(-do^v}_Esq~ zL7sT^&WqZfkfkb8Q|FNuq(U*AN6DCJHvDFxc~E23*s&A?U+NkEfFt(C5S{qmMw;=Tpy9 zV)h4Zvfl#RVl7$3jM)}>-$R<(^rJ(Md6|@QO@#F+!hC8@|I#y&`k1ymJ@(r3_d0{; zCORN(!iE#IuVY5|s8Bqj9JR0ozg^1Vazlj6$>asnnN$6Rhi2?QE8Sw9aI)aI=%8d8 zrS`O^Q3K9TDBs2sNW8Go{7CAdrQY{KIFor(qseWQ*BBz`y7&$YW+lp%KfMoj-({xtvOH5r9 zzn->ES>n;)8%^)I$nZz09g`2J(7K+)TpPTYMD@h8()dN4$w1LM@l&X5FWXWFl4O>q z^TTeTyvD_k=&quW$w_l@nE%pU={1Hdp)U!Z+(s7^RDnqIxFC_E!8r+#C^xbXH=<+5Wz{2Oc(1&!HZF5{$LlpDorJ+#$%~o$ z-{yC|9L#56J9CO@omK6VV%>t#;Axm(FR?j`jcdFIi8C7uzYtQWM#8CwOo`toxQXp* z-YC1s&tM{ye`n9=uCJweSBOVm_Rcw%vPzACZUI?)O2k&XhL{JC;8U z$(ScxQV)8|HJ!3tM;?}cuaPp|_vj1$(-zhQoLIYE!i_7GTM3~KZ8mMbQ_r5<&aEq$ zSkDfrY<*i>Q`9>7C3Uy3vrb*#0`d5*QQ?Xa?vZn(uikG#1!q3?gA)x1n=iLmxnN&5 z*Vn^>Pq}$UV-m@dk<<501dTin#h%-F^-JyH@UR$Ic6@>s#r@q>}+y|SvOj9wh>*^d~> zJh}C2>Zs_BfvS(!Vw!~1PzD1c<>p1Ji;H~hKIk;t2+%dS7dQBBX|B6X+)Iw8cn_B$ zgNQb{hl^4X$tS|5_VP7<+4b&iUf|*5X%Y82s1SM^^3oY=;|HVgYWW$r)~ae@$&NGq zaaKG1FB@0gd_%;=eQ>Fq#oZu?CU6l&eqX&HFW8o;D_u%3vz-8QlIB*gb1@HfYRHYp zxn@si3M4$?^Hr@aR7ZC$ch`39KYu4)xoF0#in~%ia`#3q8>7Jmq7hkIH)aS7@0UHu z`yI8CG3Kwci|jv~h&WR6#Qf}w!FXHy(FlFmLd;SY6?*sBs3bEed*lwONjNf|gG+1y zU-kxXM~SCGqj|Gi=W|9Xh%w6-DWW=>clsr_o$9!MxPDI3@DBQNd*ja0ZLc4Gbycq~ z*39B!dLS}?1`&AR3*W1jfob%ScUxUr&U2xukkO?9--IOH?RUzSTBwji&&>>rQHS33 za!NbzQK4&gkrn3#RVP#VHQ*Z61ybmcAXlC8g%@C%gC{1kJkC*m*pci`F_HiasD?$v zXs}}Urmy5mC3)S`_0y`?8#svJ_+vKiwtEVnWr#XDMstK8Im#uu>%nW2ej&`Fc4y{^ zhBD)fZ}>XzCEB7Lo7zQ(yC+SBz(Ob$vScN&sAv| z%(=f0*SWmcZypxmxOMlO!xn#HC=(`z*y&tWNy?$N{OFv4wtY1z<(5d`2Kewe39#UX zwN~P@XRXQ#id|Pnd?l_MI4TW=MTeAJNh`x2v-T4Db+J4{A`y~eUV84<$LYNA^vczv zNfzvmHmucS}n;>9+7Se9MViQ~NgUA`F-$MtA}Res%3U zWhv$oUea3M(6Ub($C9K}y~V=a=B1ApJ`q&u;~KKF=wRHzYR0TZm8-4H-LFc;2A|EQ zx$~6oynnH^_w&%M+*euBNN4Yiw3_5-Tpc!Dg?kL>(i>}u4`Z62<|&CZKDb!DvB6As z2U3r;=j5jl`L6ND4>HO8$zgXx@yk!5}`po6t#T-Bt zH+%HOIT3nL&9;NAS^biMcgB1d3sY>$8j6~hKi~}$l3sk=c_|&MHdxwR{8TZyrU;9z z8)=_PG!0SiCV|#4A~{hp*g1u-`O;BQ{pHb3o^35+HDV6+hyBT|Pd-*`%;9r$v#u7d zpMHDEC-_xL`rrYxY?SkKj4j-*a=xt~Cos5B7&;|6Qs_8;ICiu8eEQ_$cHgq*C$X1i z?0pGM(VgnZ_77E=&AAK2JBwkFvDNqpWIab{WApUEMccRKNk@g7&y}PQvyEZ0HBH{# zUFHXqTP|ia)!PocakWe7#vFNaaLUR=j=)i-P8o%_q945`l$f;00?RRgPaxgEreV*~<65r)FklobXlFsk` z)qW1u8k{?IWxH1(E2GzZ7YRRF`3-Kg;FZoY?%0Pz>ljVJ8o5=C64NK09gVva z<;3~EZCYK**>u#_FTIN{CL|G;jtY*K7#v)seJ;TT$zJbuP! zA4AZ%$j;-3A1RzEzMLL-|K*pP_(>!w7e`wvH<7yeqW??WUK6Q%GS?FVpIb>?&m>si zOiH@GH?J$As#0YIsFbZ#GLiU@^ev@xiub)#GNG(e_S4M1>wBHUpIdg*ywZO{T+}w| z#Fh^~f2mcLQ-Cz|P0W}!(|Y6?MYegR(SAPa1eA2tX$ zX+JGP`vZflTrn6QI)({42!%ppeQ5zSnD#aB381;T=y9#QLTMQKUO}`twBVIAQ32*I zz9{QG_SV2l0J4J&Az4TrQiGHr1xOsSf>2NZP^F4$8 z0T_(C6)FhpXW@Dj3B1{%{U9m^{JDQmCnDfS|H2^)zaTFRIuL~O(=ZMEg3vz-4VdB@utNeRi)p0N;Nmt&jBf_|6D=@gT_3NZ$ZZ z!$>2^(oJ044TE*vh3Ta^>5owW`k(ytef}9wKfuk}1|4K5Y3W0gh1Eyj$4&gN{4E20 zg6RJHLw$BxuA;9EMj?YR0lQs-Txcbr6S?1Gf8Y-(qQNv|@THLr?L)b*B=Zm1S_2D& zzslAM>9gX$KLEMQftCXOS%(b3_}O`)K;;67_CkC7U>_$fz!K1;j|mFG`1)Yb9^a#| z{|KRx@QXjk4}VK956@o%*nR{6+E(#tZHsYYg@*6;2n;{I^mey}9>)1SQ}98YfL7#< zgYHMO$q1!m3aq+C>8Z}q-K_LCc){qgfV~FoS^K>O1A(REF3^3AA$fOq5aI*gz`_DN zuCzxm8e~U<+-Q&=4T_*a7idr{4Prk55)+`MxS0ki(I8zKWJ-hVXpkEX@}of! zH0S~iiiKcwnnY=7(Cu1Qs1~F-8Fj#Gh5Ixo#LT<$5Ab|JU*`fk%kMoJJ^1GfB>dx9 zjq}5U{{01E)&FM)2cfY(w0@h$Vis2n7VQ@J5B&==ND+k5#1x`6%2mk+?tf@Gkp5~5 zqmcsoqtymPce4cgcp*`Nwm$o4T>$L2e3cTvp|m@!{!POi;GW?wTs7ZSe!@{h=&RdG6^)cHrw~3qh0gE`!{4( zPfS3Vo{yKu4^DBd6yErUHz+yW4dw2FrFZu6?2k3sA8WEd)?|OI z$^KZA{jnzdV@>wQn(U7?*&l1NKh|V_tjYdZll`$K`(sV^$C~VqHQ66)vOm^jf2_&= zSd;y+Ci`Pe_S;^#Kh|V_tjYdZll`$K`(sV^{|#$0`fsP3z)znL!#eAU$Bj zfPq|rO_n$?x$*>X5cm(IL%=8m7(xAe3~|T+{E5>oz7!!9TEZ*8#;#a7z#;nYuP}(( z$5Y@L6y&ERFOLqCbD^C=B8SBI%7?o6$t%h!$U{33p?)q%Z&Z-DD+>JHuOl&4hL;fc za?_EpQ#DgC^D{tsdKrfWpsd2ot&w5gNKH2hgs%9`P_0m3KVMXki+HH74?0jQR7ZlI zxE6qE-trRSbd(@(9SQn5A>#IC`^60~0Vr`*IaOJtf|8=Rx~80>s;auW(hmArDDn!5 z@`}o`ikey~Dq0E(;@=+$kXwM8yO!l{!|!e?0F&%OB@uiU_zK8d|fC!v$2i63R_hS;ZA4tEQx)Dyylg1f*C|U0FjNsi>*o;_{>P ze?>hw<4Hy3hur=*ssGMgq^Aqo0|h#2d5M2n9ye5g*DodVa|r;3!$GKkKu}c}G|dBLkJxToshu-Bo23G+kYR z@B;?AD7vW1Dyq3^D7d<-x+}P;{W}J#s{B97!2eht1tk&gGJ6pK$oFHqu7tmvA;Hm`2P_HelEeG&|o?j0v6b)U)b%z+}wG;rG=r%zCH9+Lw4hRUT6#h z*j?lcHZ9U7>-G)@#o?d8?jlyOxe4qeazO_AnOPZHgVjI?OytFBGkO~Q{Q)bFi_P>+ z8Bl|)@qTgf9|3>!%Z>C42m%X@`vJbP8(2&O@EHL6garA~{Ars)cwN0|FavEz6K?<@ z5WrwV7{u$b0@L<@@Vc(RyJ)bRFB20L04o5PJ;2%$Y=30h2~K!s_xJ^N{RIvJ z8+-sRWPtHIM&I%xz7@Gm9IPQ~h#R9qd{99_virfhs7rtwShe)^b3q>i`_AZPrp1ER z|I=y--FxNrZv%h9`*$F%ZdbzR4$$iiw&CMXzn?LG`e7b}t&d=RsOT&N zZEXMPC-o34K%ar2!rEWTvwS)-QDI0CO2s01C`H#BG6;fxWGuy3uZ4w3QEW zFZ6HgVZWsC-;DN43N&yy$=t*|z`V%9 z!m@!ynnj((n8ktRC`&lYWtImlIV>+(>R9?&7T|EW0DL=K2W|m(fd|3Q!SBK|;dppG zd;tD!4ci*AHA-s?*Bo4fUUOi{chE%#dKwK{99*B)Jaa_yb9*=sA;cCMXcV`GzG(_}lq=EZh`?GD>hws&lOY)kCx z*=5)b*blQ~*`wK0*k7`@vCnaEaBSh&#c_}$h$EUKjiZ92o8ucN52qZb38xz;j`JR8 zA!j}3Bo`~!W-dK0C$2EASgt&-TCVYRtn0R{Gg#-cE^^(ybtUUs)-7=Ja4T|KaQkv! z=1%8+&po^zzJAO4J?q`ppIM){zG8hp4|S4dk3DRfcjnNYhh zgRqRSrEs`#qVPxI1rbpZBN0E5yCM}L zWk|JeX5Fl@*>m&l%~hKTTco$xZHd}av}IU&qqK>1m~@78=T?rbh^_uxA8&2k#-8krW&RCT9vG(t`?w{tu~@ArG7;HzIuxWuf~3j%Np-AnKkt_ahlIH zm$cNhg0!A#O=-(&duyj_5AT%TiQ1X8vtLI-$3^FnPOq-G?h)OGy1j@^2p7a-#Ft%? zyWDm?*)^oMP4B2)rrxB!f_{L0fj+@N%OJww+_31{FTLM?f7t<+1N#r$J1}UeXnEYS%8JLz*(%*?(OTa+#=661 zs}0uXwJn$JVcRrYg57Sr>vp~N^7aw-)eeFVUJk_v;RkIGJ~_B>XwRWrhXxL-9zJ)t z*-_dt)bYKOpp%bNxigoui*w!)<|B4T(vK{=ShzfPS#ULRz3)1WG(g@)j=Ak}yXiK9 z(m`EE4Y}*MUw0q&(DAt8G2)5vjP)G%GVqG?nmKBGG~p=0+rm4=o9bidljFO__lR!^ zdOg}3{RSh73B}a;ZTCCp*Xyt4f6IS5z%<}VAS}=^usDbpC{rJ?Td`-ceZjiH_kzEL z*oNeVa)+WrKOU1gcH!7im|<9QI8!(>{Ppoo$4?&bi_nXB6bXxTjeL!h#GSznoG?0( zdUEYa?~^sB6i!_~HGkUfbm> zMYoF|E-74!y|jE8dHKT?#VdENP@~4RI~?I`{Rk>-{&(ZWP`W zzj^WI{4M8O?_*VB6K=1)jlJD_XWyOTyHa~)?-UUvTG{QCtw z1s4lpg~tk~i#&^ZiyeyVO7@n#F4ZnAD3dEodA{lSy>h@Bc~f1pO>=9@;g;T3x7Oh{pSGFy z;C52SiB9Iui(TuwV!MUAANOqQ$>~+=E$`di_wkF>myUj9|Jc{Suge2x1~~>}hs1`` zhLwh&j~I@89z8TVFy=Q#8b3F|J#l|>>tz1auBngH_R|A10W;Lu%X0#ADf24xuNU?& zbT9fYk_Z>S34BXk(pah@+7X9HA_1lj;i&l=yjZ$1b1?tX$l&axKPR zzZq7%8Gd^he}BHm1gK!ZW?=X|@b9>&w2M2Kd6{_`Vc@2VpBHx|f{QzVS_`o-fXgRV zANU#;W+qm~wcr91aB&C3!U*zT4Fo}qaE3K7R%k8TI*0+r2(Ip6q>;qH!ioj-F>y1m zXW0bjk$~1H^6Du`^06M!-{2yp%x~#`a--|D%?6Khr?;pCtQB}wrz+iNrFLrO`s3Z! zfqM+qjgVVyZ0!V}y{`W<>vlTm#u-#%UPVLyHVyYVtc<3XvB_Sbta*5P9Ssf%Jr;KM zT-5ms7jNE*y?y6yTvGCrl+?8J{DQ)w;*!!gm2a!wz5meI)ZEhA*8X*1aAljSYtq#W#2Q-+33(>x zNri5C_=Dpu55*Ak$wu*$;F62fK^)O~(s?mT{ounf%z_!ElT;zYS!|LVp|uDOF17BN zsKxKcPHZ1(DJUX70Y~^n5KrfLIh&Vf;hWS+fm4kl;d_bL313PYz5^WMIo591kmJ3Q z&H~)2{>6jvL%4Lz;!sbj*5a-CvGxwK6|P8^tk;sClj79eGkT9)LKx*N|4-RvXFSmy zbt=IlraryIO_uBQ_bA}r2TW0p;+I1gK2o6o{75ebG1rD5A4Z?)L5VPE5%Ac_@~N)y zobUy$ADk2cE`rloH@T(sM{s)IQlW9zJ()K#gvn+ytJv(U?m!G?s}CB{5c6%y;VuCQ z%~FP(my9ilMRi-g6TIm&_D0x071Zi`L3RE|CH>os72vusURC;(UkaQf-&L^yKGpHg zF1o>Dv!b`jO1P@3{Z;sfTt1V-h&owtYT@jH52cT@gbJ-lR2Yz`ZptT`d=32MMo#$R zDzkF17jbjSxaw_)VS_2}8Lpxf2})CB9Yr)%eWgmf&GuuPb^hO$jNkd?gXg)RBYRq^ zhx`G}l|#--BCHL3s}3%lFiz+lgLEiR_-(8Op$Shu=ydt^Q`~<1U$n7NEULd*nL;As z&XT8+O`6rH&@n1>+@d`Cwo$Vrg+#`LlfoRu>|=y+FDUU7@wY4E&$rY(GlaXe_mis! zBX5h%Msbx0b(BV!)e>!}5bM~s$O*)(br)jrCSry#T4oAb5@Ot<#PY<#oweyZOM4wa zTUx$}OTk+u%P@O2D@{<+VwTTDOrB0o&A527g`tMtx)w#pp^?2OopNtu7WN@pZ%j6h z98K?M%tZBoHuc`9=Y+`i%WLZ&xXP`xs?wkmXnssc8JCWjs4YLC<*<&guUV;vl1hb& zc7{J?Y)DRpr`T7owCZF1-NRar8+o&|))O7?k++YFf|DTeH$*k1VwyvB-!Glv>b&hd zXNG@OC#`ux)54Dm#mQ4Rvj*@zxbp-i&RjKitO$N*qy-5VEF!Ge3?HOIQ(`SK!11cl zoeE*75Fes{vP-yQdQ=%)8AK#K9UkpTt)-BbBYF}u!dgY9$i%J1*t2&_7Q_~Z zx<}$KKN1+@{*D_A1tIxw+q16pf(7u~h6nmHchuC<7_Ymyt?s@(W9GhhHnO4oHP@GTLkP)r#Y zkj7>BfrL5A8)q_Rf!rAs;XBZ11ddwIn(Wby$$DN2?o{fV>`&}KYmRQmy;vqkv;vej zSb?cp($u0l!KH4Ze0w7}?Gg!O8W%E5>`Bd`RCHAt750l5;%b+@y8%dXgm9a#6tcSs z;Y!9sB&g6G=|!0V`6ZcaWELv4cHZWb*z9hxxdVuoUEJr~DJh^k-?ASowA)HWQztOsS9q%ott8Bs!mJ6Xkr_lOCLLtUv_3YQa{a+MXAfvbC@?#%9n82d|N z3r6IUq3&g(vw&9Vz4OTBL;UZl(4{N<3t;HGwb=Di%tD$7N(>t&xl0q03vqQwz{(t3 zi5`obUR)NXsuMBPVj$kD^|GgLk}Rw@&=?HrfbuQ8b@&UX$Po-^f?DdQGdX~;f;xyQ zkG}G7R2vsVs#-SDomvd?g^NBdYM7}NYe@(nZkBthUOw;5Z!a`ANfxMV2JDKU05Mj% zlxap2<4B!W|KSgE7wkNE$V;8V3E#L)(YVnb{t|hl*krocQz}#ybNCzK+IfODwzmHg zC38g&O9O4K7IY)9do7u638N9D zWdA&?n8PNB(HIi0wtSwb92Q@EorZ>vm`b@7_dKjWkZb|Q@d)j-^00+kI^VGqW@9bc z^t5Q>yH(i2Si&f11hnBDq+6sb2I6azaqT+92i{iRUqZ3e&;J(`mJ2{(iTo#p#rrQ6 z76eUUNg!3|7MuMSG$cn4Q!4Z^c`RXB*-wm=V*ykLvDw3Apfk&%LZUi>>YX{nP@&r8 zMGGoqC-g|Y&1hHjiVm@=HCX+sjZG!|R3-S!~&{{aFZNW%Z*|) z-FfPhl~hQE0`B9|VFj185v5*yHGdZPPs+$&dJMl?2ISmrIYEUA+`$pDT{~aAK0E=E zo5zpbpy+CyB~z$Sibn_)Qe7G6eMP}IPi`syw(wm6S|y&Q5jFmUD*4+W&w2k6$%bU~ zE$kuwn0kvt*bgn~FA4iikIHcW2GmR?J7y~6ZT5-^m3isBK0Zfy$OIwpl()| z0%n5-xZoA06#0s*57gQh5kIvu>F|!F6U(Y&5pD6UWrVMsRqfgpK5m;UhZYBqJ^Qwt zEmOKq;8A*V{LOU&4sKT}n|GtG30%8%eh$4@kx=BlwMaJ4J1+d#O(o+v2YWFEgNTRG z;-@&)j7e&GOkN{g9nv|~5O>VtCMJZVl&H9ae_g239vQJWna>)S_>OqKdv)yuN}N?h zem17RdC(agB7%jjeM})gRkc>9v22lr;m#c4ys_@n1>&K-bR8ZMT>Vk$3XR?cui< z{h}q6wb61kJNdTdIZNxSjj9YM=68w_dRkh&Q){%|;CgT|<@3)JKL@ru=Cn9&&kN8w z+g?`2le=gub38)M$lv{I><;W^L(2li)^Ew72ij+AC3eR;r-{}CJKn$!vdy;_+6xZ$ zRq$QeYJZkF?v~^UCh`L=O|EO2_|ACOsGBAHnA?G!*&7U_yVtQt=We>L50lw?J~=v+ z^U~tmrMc;zJoR9>%eeg2aK<1EN8RB&HTa^LTes@nl$n}M;5)D0-E+te8ruu>CUn+GlCg$C|GyAfMkG>aF|Lr zMQ%#-mR~Gar<@>#fy;4TDB7GA`}!iRS#pOIW5ye}gks25%)Uo*VE`s?GTkBy1?+zk~1HCg3KOy7n zmw#PV_>g&$n0J=l(t_|Dyzn>``moo1P~`Do_vU`-b57igHKN5)q#pg;WzrTAX8!7I zIGM0))l+ICCYqZ-sOZV4|JvWIMsTTr7rJnsRAg%Tz#udI$)hJ}S())NNB3$SOHWUC z_ZL=~Z=AWC66dwC&4zb_s|9qJR4V!Ii$dz)oasv^XKu5#l9Xj{O*%f<6J0fwn(lpcC@r1a>Xne=z}52>jAV@ay`D{T zXWusXGie{s90$L>rRm-e+c0OB=QP|s+clA#T^%rM!o$2j!_orME?zh$;?fb}-4$-5 zjblVzrUB}qLK`(C`KNHUt(x=L@*@>yiuF0;6 zl(j+z7e!=WF7*!8R%c2M>h2#z8+S!l*2G%cJD#7sSu2*);>95mX%yHKIV(!sgdlJ*cOZ&W;kU+g6r#K zf0*+xG1Ym&A8)5(eMO)v=5hL|H{{cgeL>%PXXrIY!p`|6=WAtav-jfEuN9`%Oq~~+ zcsUy?Q)nZquZcKh>{s!<$o+lS&ZAHxv;*JdoGoCF2zc%VLYmo zbaBU3pO7_z3GKs0nhQM7-Hwkk?;JVsISdg;c)88-K=_Pa@EW#-s6fNp$RkcBYQr{S zO?OV{ro_18$2Lu#;M4XX-#>_JUY_56X_7QK?wXYkW(~J9B$vat)eu<80EiSMGpB z7NZN~^K}R8vpm|exrn=-B_Ou8feW3)I_e&^ld3$YKFX?nZ4*jCV`R(h9X;ndtTZoo z+8<05fK{s5aqswSyl1IyQ_)k@#92z4pRf8xsiIqBBm0zJ}-TZ z>qew}BN004ZXVWp-7^(a9(|dH4MgX%qYI*e9QBP<^dL+rCR28akXv{EFx(#K!-fje z!*j=v01cL36=PMI5*T%6xj)Ys^NZy-;R z@nxJbzQtH>DmcU)L#XN^>K4w9Do1mXFbn1F>cjgH0UM^ z7PTq)7UNbQoM&wiBSOoPkF$YZcU>It=K_Ug_)<}cdTP5|E+|Gfc|6F4i!)a&8C*Ao zoUDj3RP-MMO4GIQZY>3K5f{W%4n>qucQew_6%#&ke5cl%o+-TOqL#v?^JA7fh|b(chLgrfQN&?4VfcZLVK5Gt(@Ck_$hqzGH`Ws@{KX#asg3d(**RD z-gz(ycteGr5?)++IK~)>>!3n!b0&LR5Lg^XJ$!IzUC z2=3N;-94_Qe5rBaEa2>0atD}J2JH<;P!L%_iIN?`i7lX`I`8J<-pkNu1oyJTN$;tU zg*Fzv_{sK{k^pOt>%=Vx8&zdSE{55c`w^yeZ*qceyJr>=K621+>;j>$VWdSYd}N@X z_U`^op{=Hj0Ob)sZ&beET(yLy*8R`*_~RFT=s0Qa7&sg zj`+O%kWulj{%jmr_f7de!6^5qsqMuyjXvmy0zdwXe$NZi2FnkzmblMRUAMo8Va)fC z)5(d;I{TfU$Bku{|NYhDro7{3V7jsWG-xbOfHKpSAK#}7*1xWka7h-^*jjLDAr%@K z=)%=(#}V_(1rVVB$xA)-OTk6Uo0M>B&I7q7v$ZJGP93B3PfmYzuc%arj=sCi3-03^ zCZ(j-^nTwf*axevvgguccX6dhTlHTT*p@Qo7SR!D+-X?x!q~hapwrBv!5CM^>oMO! z=G!%YEnp+UB(hg5VtWjz8fEz+r`}HGS@f8k<0ZsoMv4kC^<|cXoW4$FlcqRDjQwmR&(5DQVop*93N7 zHNR%P8<}=$8;^QP(XB#s*g#vb&S&^JEc zxvxC;IT#1-UGvE8lys1tl&r5mWX^jpyu(3>>Dp-e)xD-XJC(f8IdB*Cf2)|a%GR}? zZ*HDMKg*u|68JRY1(MZjhecdlNBnhFifTTA=|JSgbd&!>-J8cl+4ud!TD4M1g_wjC zp;TlnlVm9&yFx-JvhV9rNlKUyikPzRTQZiIgp_^XhMDZkFq3u6>iJIRa$V*qLf^Wo0(THIGe-Y3X9*}5Z75{IKOtwqkeuL@mIhixrJ zJvLCXuUj_Sb}Ky1b18)6T{1j5f4H2C!@8H=a*{ALICt_mUzM$BZRNw{v)58X8;(92 zeYw-xbIUTMtzPtb?hJCeR~wS&qL@inlKsxJHQyB6tm=E6qo)+uQj75w$7NRVwbm+0NI+S!ydLXqY zb8`A?Q0E9j1kJB*_8@$1ItBOoljI!tE0-sA<8xCP7Xv~hRTOV`>UL}N9@J|o*13_X z86l*V|MuvMHogn-C+n*|HeK$UU+hSpVw=;;`e?h!Y*&cf_6kC^Qmy~@@1~+3;#}Rm zCbzvx^oTLN=T0qn|H z7dN*!lrE}q{lYd?`F#&~dqJ>D=cB9=(XC!M@00@mg6i%KHa<`1^>($Yc-#it5aH?` zqcaw_^@D}a9*4Ev9CzW2pY8AAcq@%*R;kMRan4#+$8>Up`-NV3^60y4uR~ogdEefD zhEJr3XhO)ccVz$gyN>5n6d=Wub<1h7jE5_&NcG}MmZc-fQbZ;|r?#X8GrdLiChT3<>dZ$Axs zMyVZ2(lS(iKD^qS^rG0XODtU5tK?cZQS$ZRoKqsU$pHC|6O7g8<^p~ViATz+I3RdQcJ zTowNOLiCvugE{MCynBCmqHQ1GutNrX?beg2O{2M*SAHP(ddXBCQ<~<9O|`nU>si4C zAs2((_xDEli@UuC$$KLyWsHXN8kpBM3OqUqC?Ud)d&*mqKXo_BlZ8oc4~{l$dOD_n zJRikbC+t|;nf+LLhuCN7k`S=qvt&MrnfDi0pI6U&ln5xgC@pl=&!hxk=WPhM$0Pf? z+bo+&PhVJDeL2%--SU<6_GNzEwj(n+-6jI@K8?Jg#r8&bVHRsgsPvzi}ZtRtTSC*lKj5RgSuMC8l z>`M-eH<`5EEZIFWDG5la2I zo<$+QTQ`3MTxrTtxt9@}_xZrwHFPNxh(x;sOkQ?slm(WfX79zU}BZwzRMWW z!nYcUC{-*xSGb(IJ4Cq0K5Cotcu6YI|MBY(^3xT<+m|i?69F(B zhVtSW@2uxnht^<=Ks|+{XJY766y(Pm9#1Z3vxv=3{0kNKIcF3dOL?vL+{~kUJWWXz zjE$2PM)F+>5y_86=pPQ-dU828FLVKO>^ALD4U-u1N!;g>|MUCiJ8x~X5E4pw!hXc| z!Y<{vf$?jFZe)uDgvV#*wxr7El9}n(UE|&vuy4P)_sX3gx^H^~*|l+FBpj1shq+&( z7+Qfw+##MW)4eZK*4EHquKWCJ?_HaNE9K^~AI?^eKTi`mZjc$0@p|Cf(l^bc>jQEY zu@u;YvyL|!9S%C&6tUWJMptk7TF;3$!o|C4l-1yKjpA;`A~c5&7it=uxnJ!Uu}x|U zbxFy%I&FVwi*VeXXG;5WPI6$3!9Azj-|&Y-q&H75(zvp-=Ay-(&CodAdLaS(o0lsq zzAWrg$gPu%6I~$O&5XJh8>O4K$NLiv+?9;aAb(qKYd~{Y?U7D1rrfPFYD&T!ocncq zEHHu7fyIMF-oEcd*+Y72x%Watb{G+v8*HcIPTG6=u0 zK+aK^IVQR!aHeojcWqVQ9N&%2eCKcM>%m;h{?g|Z5oMu;Y&LY9tE`-txbo5Gn{JMQFt=FR?5A3z<_q+Hx!8$9>}vv}N@3C-0=`IwW) z427$RsVA_-?!Ln`2EfM0btv!I=^m^1b%41M+CO|69_Cn?SpYyaa@ijm9jSoG?uZH! z(43-e(DW`O^CJA4V=D7%-v-;V7GgX#%{ovCgRCewo*QjWPKzZ{YQSIXb9}1X(B9D3>7pX4wB8%Z6NEIwP zrvO*L96^jXv_hkU;7X|UlXA_3Z?JvWMo`ia+;On@Pq*PKN96| z6`*L>J$Wz#z<*-Bu-df;d@xw<0Fzl8z60Kru0w0AibOgRA|E1N;un8_J7PP`d-umM ztstvpJ#dH$X=)p6J7#j1ThLJsWJ#$tPC%RQnDAM*0NsFbD@oqV?g1J|R+o z-x*|{D1*H2k5<#Ac!pHdQg`@xMgaRB(}-)-92@WB0>;!1D&TJU>*V67&L?K#fE)Y& zoDF~u>$}1hy?|am^c4^`H{%gW#IP@-3%$;%j+LdyN?@k)pvBd>dgMB!L+&SYu68sB zoFr^W* zc@2Icbh2*?b6tRw#_6>@GbB(1BliJT2jY4TK)~js2eAVNXT|y}unRM7k}L{}8B1R1 zd~1Fn8Qf7BNpOLh{VW*$b&SC8i7jN~{eGX&lgUxQ;YHUC*XPZoP*9Z(`lyPSsCkun4B%%2&BU)WlTmdU#NV5b1N z7dkxIztQ!-!_@wai2V1c8uAavh5Y~GxFG()aS5RQ5#RWG>xEd|>k@zkM;{Fc)M%AC za2$k)CTk={Eszbg5#!ai&Lc0FhKzQm9~U!!Q2QT|4Z~3Q3 zWrd=*;Fp?osQYLobd?2uxx;I@YsjCg%0WvG1tqKhdC`uP*;5 zlxe2s0y7Fx+m8TW5Wx6&pb?zU2hoqNmAi~!YRF%&CsqiiuaVLUogS~4MYFdk1!Mb% zO{h0ZsuxPm?mMUS<6XMGh|WFBlgBP=c`A56nAf_0OksWNpR zy86si?lpbuPqdfl4{OGA`so1p>`AUt%*aRbAfIp_%3H_F8BsrJ^TN9NP4U)<5Ugm_ zGX@Xeq0{!(u{Ez_xIPzk8!t^!Mk{ML$-+Eu@Ir59s|kwRrOLd_#q%QcBg51pW4!KU zPYP}~J|rA%vOSG^KhLS84vmrqC0hPMetdb=CbaokJoc%>eVrJAvlTo)C*H9~#;CJ( zJe?KAA13A(F{Z0494iI+(PtN42v-@7@4El;;q5*zHdJ~=SI$(prAtgsv6?!r-G-!< zJ5Z(W-g!jMH5GstTv6`$V$5cFCj`dCMok#Q6*gYQGxlQ1d zwN*jHW##urY(z|SU&S6vsAGD;)=1i5@2NxOBFJOb)h#gZLaLt^Vp)5dnRm6%4f4ul ziqwFMQ2~o$V2SYFc#17F=tsZ3!B(HB0BYk(@fuXy00J68xJ1eZwD^r zSu9cE>=)SG$5RbFJPYu zB(iZUR4oAtqWJ~D=Mlge6vp2Ir@s*!&Bs@ ziOFN-@sZ918IC7U^>3){5PG!LMJT;&sd;Pm`8~QFPmT1Hjkdpk#IyD2V`)x<)n(1m z0x1V;x4_z-^2v8!^tg-7j|eE=nZwV|L*iuRp;Ryz~>a7=CtI>|0DbdYExx z{(BJ#nWI*(mwY-Psyz|*W!Pjir=AN1^Ckt6WD~P|xsoOqonU2Mv(I`3x9qzP9elD& zU6A;4P0{SBRm`Hp1c&~6`2$G7)7@Idvu`e!MJxtHP5r01wEiD>- zz~E}Oy25nR&t;jO&Xb#`j@>%Mj8EXAOI?Ghs4cyJTRpbc);^qU?0@%0RYcZ(3E@%o z3@ebSNO)wrZhHL{{G^veMs9jxdPYG?*5iW6vK{ubV%cd|v*)sNgt+v3^jmqvzRjqJ zpE~w?bf9_Z>X9q>*T{Or!iV54odCtJ$QTMCek84v zV|Z+8g0iDP_z+QNli@?{dm43NKUQwmaCApI z)v)ptD$2%+*X`-PLTZ(T&)!uaSUSgPMvr~Awt+iCt6MJWaj<6m4dFX?4=NGd-#1O~J>KwjvIk9mb zn46pnSoxY0mN^gqHokb2!jZvf^K$T)df+7Mx#erkrx<7Q{IJ9+8s*n+VsW zrhuky)4OzdgN;KG=yjh2#PL@G!D^K0@DXa2L(HutdF~#BQ9Tn8^zImDVRJ7X5{1!@ zzlAY{6COn-O#scpwzDe(H=np zDWLGNAHast1ql3zkB6_)8L06^0$9sS3c=0ne;G0WLcfKUHK0ZicGC{m|Mgx`v>lO8 zWH#88QZPMC1OVq2Ui>iAZjix31B-$b3IKWjQ+ODFIIGpz=2U_c_uMOxiQB(YqX z6wEXMd?4Y$OL!QN`pI=8R7JEuH7)goSjx_yw?US@eOl-d`0A zUcae>eF?@?0J<@-W*E-PT(pBr@$^_7>hC}wG4T{Jl>$Ag6k;Dv>~TD7l89?m+xN53 zLnZoPQ$D1 z_k0fc4N#;}nq%uAqy_R>Wm3$(^A@z|8Y}>Bt`i$<*YH1PHrRlm9i5J*_aZ^crC5dv zRfGHL5@ChryMrHQn(zUOTD@w^?Z`WnRURg0(PEaxk?Og@zl>DMJ{)I-w78fU0NvlS zEEzoXiB|0=6N=Qu0(Jla^a8?v&SboW7l8CdXQ+#Sv4Ow^h-)1Iw5Sc_xTeAL@Kqi* zhc|VK&6C!dXm&a}9jpVrH83|@Ku?6Tg1~+ZQbXf79jY%DB!@6__2$QPJ~*X%jQ1hP zc;q@VNb$6VWH~D)%1B1>yMV(oaeEDJ4C5$=t)mJt9Ir&pbgDd-770j<2k9^96iBch z0DI%9LO5#S7`<|%`~O#X|IdWg|2f|O_tuQ64W&FH^ePb>q- z?51H)?n#?FhOZtP2JhbY`KK~0m~N+QX136qFIr8*kz*Tx`!=Jyvy{1 zm@wYom{UuXdZU0nKL6}LURn<@l#F}>YlH{2Ypk*aGhsDY2pJDg-_-xbY z2VMsZS{Z-qyZf#;ZP`NQZmo0_;?3>=uMrQ_QGb-;aStO(bH$L{@T-Pdzf`};%&M!x zU1oK`O)ZYM;urOL5xAlAah2-2Bur^tLSAB`T#yvm<^d)r?40{9q>fxFY}0xYduVj= zLubY)#@&+0tP}kdgdN(_DsQGT_aj^vt$8t?ZBuCVM`h}XWZ|Du-G+k_QBIANerfd5 z@`8~bkEy$-sradFH+8J6!%Cvo5f(nnWdDO??QbyhNISzMroaL6$`U7+55yL!mVxu( zMT`7s$GnMJyNx-FSv=9P!A300#M#oodD3nNc3Lvnr37wQC6R$iQh#&WnQ9EG3&{Ms z8Yc+Ep%`+_QxNbsTnEyb_ozf9A*$c&G+lVVw8nHV~^BT_LR0 zI*f$G>{*<(XCcCC@yHv5Q>WYx#u{+<{Os*C)^ERhQ&X3>Sw~+}fB(~zS|(5 zKF0=VUa~$(cf(_Cjy*o3%(FG1wq4DryVU`1hAqA-bf@WaNA9VdA_e8Gn|FL8+~lAW zkSkile9M+SuUOn4{m^N*1ZVqOLDJ{UZw4cBH+#^L- zd((69F>h@8pl;8{7Ctzm7x9YU6P9{6*HwH)U*g!Tb~3hN@cqo-#?4DU%HOH9mWWJeq&@Z+Hg$BDSbxu>80J6^3SIDF>1!jqgxf+~t+STQ z%SL|nF`FCw%zpb~N^+UwI$u9#rV7?!s$`#HOM*{u1kEGT@{<*TZJ0eehG6=rsd_z`kdje9!@NQaI z?)=erMbSGC&!zc)haOZsb5|E~#OBImD+nI_ctPp3MaBeuprCl^P5`x?bjNojuy!rf zdP+3VodK_PxtbfOik`XFS|2PV8YZ43eQKHD2u)&e5_k+pWw2*|AA>lJeQn*(_f`Fs zmVx*7dZ8V$o=ZV?1@CX2eiaYW+$bMeB3_ciWST%b5`X<10(t1e@?>qU?;>$XxsHn4FZ(;?lt<0T?Yfrp zT1c=IAWoAI+wIqDX&;v_d`fhjK6U-G)Zi|eQz)AAyJBhy`LHG38z<*?UBu3M@(iu8 zK(ye^scdO%N@PSa&q&FKCJ)A>xpb$d3J>~K?fE;U`Fos5IN4XufEc=WYBvqq9fDfapgj|4;2nSxIK`AJ9xM^~P>1_8czDS1)n*duT4nNgG8$vN7W zcklhP!RH%n1A&M}94xZP3XcS3j0nt_;y?gZJ~;m*<_($=Z~V=IesPV&{OMB|xNpsy znN-jVFggHkxm}(;Qg@-*z6U@@*Vdt8q>LBoZ=v}x7ij$@d4r8Pf1Lb+`6~)sAH%$- z46;#*)>0V!$|87i!ak@`$LQ4t8wjuHxD?HuLXY+;dL5=iiFiOF7QoJ5^`^Q#(U=|s zMBrD@Vr`#_BWy_vY|Vd!tN^O-Dlo>j$QV@~{0#rRE{=VJJ=8L| zDD!|q@6N=qe2gw2%R9G&7}&YcyuGVH_5f$%+zZ76H7tRC+6C%S1xKwfKxv{C$-H`l z5z18Xn?`>^tt_K0Ru-Y&XO))#Ah#V+-@ixz=YeGflQlsO7Df_abdTrRF`U=?t5=FI zde+m(I+sO#E=-&jY8bF|`=f4lz>EP%1zg>*@k74_o-yiDy{J+q@4QrR3 znMxxu8*EP(yqWXJ3TrHeynUQ;5it7IHyAG|iZK~MnPK%SMaaiJW0L-}tdg4g7({RT z#Lmc-)-r^|7nSy^FNm88(Elr{;v&_cvb+cHy)|X89;2y9~ikX=>MTgf4{8$XjzbLYLM>q zy;--5Ed}_vS6w}$!VP^vBWAH*RZ}z56xz=}Kd`xt{R8e+3C>%B+142ExqDVbcjslp zSi%kJQv;C;AA-2IMY8MZl+xH0m(|N@C+Zg7#Cp>b%Z(a-ctvVt?%}aLkm;ehJ?4D$ z&#?3NdBf6Hm!ohOsvJbByw%igEydQ_Itqv75=QdT;!Dm61)m*<^1@?AT|W9gH{{K^ zcFQ)BJ`I8se7_E#ATb+oM+ zFQF3AxwdojYiel;t&9Bw1)m#FCwlpwKvYG2{&G;=y5ND2k=U)sl>35$3x4yre-18} zHS$YHhI}qpJ@VA+5v}2(a3eChIgFW-^|_ap(YQdyTU(RIUpkgPsH$|bc7J?fz62BZ zWh{Odd!2K@s)TNae2KxC!~4}jV*Wvbx90Q)detBavD^lYH}_!40QUbQxDSNJNN<3| z({m8fkK0c3W=@(RX9|CV_kUM+Fb^Hhj{LCA?+27g14-9wt^^nj3YxX2c(R~<4AP_> zlq~_!S3|X+c5}1)I@0q5)fb6X^;&vT1pDD2XF=rs9lN%pHtXk%Jg-D|nBvs^uex+C zO%%ye56-g>e2ZWnz&B6#tJTb+N$v~1y{}Mt2?8et-ue(Ewb{Nc7hd*Ws%?Q! z_(N=6TaK=ns+`@UYWB+SDq$ukO>K)t&xt2ztle$8KRe&WEq>l3bNJF-o*SrALD&yO z`(%eT$<-#WC2~3&s7%&( zOnjYc-z>Gi-m#djcguHODeR3N?>S56!ck;al5e*sqrKT%R^#4$4X@u^OzHmR8=BBZ z!iB)WDT}$nV?@4i+Zc`Ht+#80@fkZPDRD83OcY01=&Um(k&hjqlv|u&_qj=a`W9$I z!kUGYj1jl0B*ditFk%Y0*}*CPbh_V_^NJEn;yfA`uBO6Kt ze*t#=l0amj-<1tE!AKI5uZk8r-lz9LOKG~H)9YzRMr`kKv$jpCSX$*Sm#-v6!=vki zrJErBgApt2gGiiRyn@4Sj{70*yZL-I#^28^a?NnpKdvd+)R9Z-|BlfA_<;FiDAV)9 z$JpAm3g zFJ2&{<1`=9*w2qdXQ8#5M|{@4PP=$A?>;R+efv-+tlw4YuB;%P=C0pUdt7r*R`iv* zxxBqH5qQ@D^htDJhW_4qiERG+!Jm8fDeLXrlg52V@s&X@=1K7Jhe z;1H>rZqN~YL)pk^EAUAQ(sDPaMV1mMBR{(>1Fqp#rTXxKWipGINC`e&&+%!Vs#Ke{ z69-fToMN^deD(hRx1NtNt*YWC_cMg;vQ|xc zw_Rkj_dCN*Ap|@{ENl2#Gt)^(W|cq4C4TO2!YrY{%47f$ER^rkvX<;!hMl1Yu+`k0 z_ax#}8$D!!u`ryNc=-93Y429gy+JC6A9DwDT@~3bkhq&yH~h&5t+dAL;X{+wS&6Q9 zP7sYJX-;cHZ?r^e1veULNji`S0&!j*QrT8PTbJO$jY7)LFvg|2S8?mN(5kc4RXORG}{r+`QAo~0_iNC1*Pl?S1YY-7=VEs$^c@Z)|4h1vN4T>CRf&Zgmsu@y zkWAVC4HN`|!cz(R=`=Dcmhz|uO&+}+ZuOhg-w2k|<(Vdd^8_vy2(@IX`5?A45wy_x zD!}gxJ{ju&RlWF?*gqSZ+PoOdR50tGW-wwQT4oBF*FBRS3w{d;e-tl3L7fJ(+z-e> zb53vKR_f#tQaSi@`yQ zyPpbuW3b8wt@9+dL73WOEJF_astg3VIZP2LLfTT<{`cKLEcJR*S;S z?+d7=92|`-LbX$;aa3t!bKZ41GA3SaA6?N3NRKtlnl-ouw-~%099v5m%NJ+_`xKy4 zQGG%yzk2fGa z#o&)`5zSg)(wORCY=APWJq?c1Cjj+v0tZ2x0-Pbo)o~nE29&Ibb^Ltb8DvZS&Qb;S zU(Fa-aB?#l&TC2wlbvbicbsRLi|b4b(toDwXk-zZuFpVInSddLhF;12fElL_!M0EGpWi+>~Ri{dMP3H!bOeTML#R4)F9f;|5XVgH{gAq2)N2e1GCkmUcuq!KufY^HAlx zHBw9{<|xTAGXVcSW8~NBiSN#)tE#B`$ElPYD%%e-AhNC?PN2s8Fk|NFl?uwFcww z42pDCSnQg!2-_j9_7W!Qwo5G_Ykr5=M;PRT#MO)sFg0Fa3skDkxN9??tQRL-MGtHj z7x{*G?Elp0@jzG3*5y;iVbZmj`(sK%yiHs;xZoe+#<0hVMInG!egBb!*A8SyOl>I=dH2ZNI8CLQzg61{x+^pLQx z#ozrCLyzuuj|%F%{JpumWmv!~bD+2pHKakWoGBa;>(U6UsjdpxSvb)hDR}ImJ^NHc z{L@{i+i|F7j>lJJ5snkJ&fEg*4mU3DxaKP@x2x&dM@|1N_QoXx_!!sBXp+z5=C-de z8DBoeqyf}kmx8RWZYt<5xg{WVp)P#tS=6aU`Y^YW1{&xz^H?>aj+n<+ zb#E#!=~-XEJWA(-JZzF&as|Il&he(Qs~GY=pT4DPaGyK$NpzYt%E=%3!JUI1*Jr9A za9ZQ$Fd@R9$$ijU|Dox5p(><69F5%ccDXIek)|U)$oJx&W~;bQhnm8zd*OOFZ$xL^ z6@IAh!<{9RdyT+}vN*6tvUJ=tWnHG!e)vUeXP>bl7m#9c-t^?a< z&6Dp6m0?!Z4{2Zg?TB%mt?~XlBl~zh$)`wpO{JI4S-vSvAGQ10*^-m9Q-ZgHOS!KS zoL&DE3nU~0_eKXSDMt<^w(~P4&+gTcY-`<)r8RBUNj+yZms5Y|C+sQ}>1*0<_DL@D zmGhdI;q>!QaNvCE*9fiogngtK7exAh_?}B-NAoqFy1!SXw`%>u4@sf4vZHy357Ts`KTR<)q6uZ<2wR$^_1zRaD^J$(E8xW#+ekqTA`O5Y38Rgoo zuI$ru@Ol;&-cS5N-gt_$ZtVJtz$X{sSy}d#`{dCf%&5sj6=_bJ;*#RW z-(H7#l2o;9>^qUQ_GuPf=5-)N&b$Af(=NZ9`P(P_x@>Rp!aY1r^BOh$|(-(1Udh}8P* zL)PCcu^=R9{$*UBcmF~0&lUP_kIQY{`;^*Gkq(d<^cgsgE6<!9zO=yA8G1Mg&G?$2%eh(yFJaOlE^oGe1TR#IF&GV*Nu2- z+p{>;BRAN=fcVkAAbaB(4zYbc3Lp6JdqH7? zZBdW}GMNLaBre9UNbYk{dPgu5?$^K~J>$)PC66s zi1CGC6s;nW>W`8sq?|B?T2BI=9h~=c2r-cai1+z!CLFGc{y0Rd!b znKK7;nKhd0rRQ;^g*!D4i?t|yN;JD=&K5X+*MFyKKv}JXMrq2Ugm=& zSuvwkz*hnt>$2J*azCr20D1>#P*@U|7Vh&=4h!~;V>5uK@PG3N+63>YjZns2%diVNUy z|Hxz%7UNe_pwEEz2r?J6phuW5aPesv<@heJQv9Mlh()CdT&hVW=pKZCrWfd%7ohy`Dmh0ez=gxx_9Vu3+RJxK?TFj(~laH!TqS?)*yU_8Sfcap4}q?qUxGDb4| z_-Nm`6*4itanbV}7mM*&F!Jt!O*{uooNA;Ye@&cXSN|L30p*1uz!F;l12% zREQJgG#xlWXo)&bSVx1G9tZ3eg8(D8@B$H5;5kJsS7pG%j?*NO0jTphi`1IIMa+}H z>FfIe8jmX|TH)Up&5>qgatt%si@;1qP>T<1Y+){g&s<+~yq)@tDOrpH;G#I7a+K7V zz6IDLKgl(*>U9O8jB#8e%O9cEF_2W;8r;`!oHU~NXZoF`?B9e&5G!QnGjdJtIz|$+ z(f7YYfBwfB=Pth*=l`)kf(QEjsy1uPBJyvuqW6BFvc+Fcp-CpFN66AkVwg{q)=>LqzhORF zltQ67yU8(up7DR@sQim4*PqWQbAFCl7IA^rN{3;zvY27fcEpkewDO$Enp4SIITfl3 zDd}LPGm1|Yorm>E{N-z~cv!C%B!fxHU1U!+wSS;co*0@^r%CD?>bK!*`9*c07fI5AH? z;CsGG>i+R0pU6)8Y&m}7gR9fvxYG&^z+Ed+(=9(MCs(?>u-XVfKbe zoNxl;w;lsn@c-yBH2vx^7+L(@V=(`{$6!HG8wQCeylY<`=D*OQ7CcZY|MXD$-I-L_ z`U?dB)UQng9Vu$H+`F~SMIM-H6cnQ_^mqT{w{cN5fl3RozninkIR&mFrAZ4VmWvXU z%;gbfA2KhHtkZKRfsO+sVSr#0I|lzUpOx2E%dKo{drU0ru&q_lLyoIt7qNSA zvxm{#ZaTNR0utsEg8E5&X`jw6hlQUWRIPWU7{u%uP}nAIIU|0I{blTBE@SI&(x}XC zoVi<22Ub+_*1)w>$IP`A>MA6aDfuAI`H@g?yVLFMr`Uz5!D4gC#1Le|Yv1P?*5cWe zucmc{DIEEH6mZMXB7Q{_&eQeCB)%$H@0Q3aj*Z! z3W+|(A>7lHJ_UNR_80=UIS5zGMbc_HOEg<{Ec#+!;@oMFhN*WD z$bf5nXV#x=KEU}U3x@QKFB@nmbNuP}lYS=U9c7lyctKQj%8!sKIp0UGDjJ+O!VC_n z9KA%Hxsi@+eRewN?uzGH{}N##umSC2`Uq|Nz5eYKj4z&f_+bvKAal$$pt5 zo0Cu3$rvX#Txv}VdXNT&?UZ2gelmP~SEYnMmfJ*V?o)ujR1{+zaKiWzwT8R~$#P|c zK8<}9yMGuwnh-z9O{bnyr|bxbge{v;HJKUC7-p$Iu#0MCo1hivDgYG_tLUr|r46>* zSj^r;H%1(0t+Q91{$yrkWU;Cojn;I2bJE`X#J9q<^qhhQ-na&vQ_?2o=S=c4E)aym z^!KVtT$j!$?|qt*w`H?pTR?t`mjbrP)SYAKh>BZUh`qgDo^EWGMo!7gdm76}2$GDN z>4?mcuz$aM;27m3AsXh>c9ogxUt2j)U+G9f5#Fu*B)*VmQ;0pmrS{J1nNk}v7%F3; z7OKAnXFbIiCac>zKS0`e$wT+9B@2e8B9D9p)9r6@ zTd#yApWhn7jz=isN1SAxUA;w@i$ zVsVVioEff|OP60H-pR9J)1@MP_1~dRB zr#1-`p#Z=STn8i|{IlKGK*!;+&oo~Toz=BvpIB|qq{yxx(OZL}5E9UG> z_1Az|Fh)`X47dRZABj;nLQT%p1BO9hHV$0z5JVS(NxsED%B9%E)IgEY$&Ai@>PSTl(0AvE~AS(OV4YY^5L=PLMm3pJ-$4uRY@ zZLsap`6+wF98) z?;6c%oY5G=5QlOtwqX5@1--BMi1T0!ssElQ?D4DA}dx4^K zku1xx=mz}ar%Ry;FKC=kGeWD!Q}4ke@k>$!B7;x4F>f!0Ty(B8Pr;-EkgQtq#hD>fjIM44S>e8d*hy2Y3P#Oebj8>aH>17~uS(F&@;_ zMjVyJF9PNNf(rkhUu>`eg3VLI3@$;V)C*ae+C&kwP z=@-R2|BW9N>o9GdDK?^v9f1o$f@_ig?Wwe2tNlNmN?Z9ytPOd4Mv9pHV_;-UFBrh( zFLd&(ysYJ&Id|Xt{q?#as(qipgEvVHDlz3WqmY34Pv$9zb(81NRb#pSQ@ zrz>c_h~JU=&G*Au?v&$?iT8(cbmCP|j*692NH5@EuMuL7Q6rkYk}RLQr#l!$-`Ciq zcjUNng5CSh1M)Yzk^(3-`t&F~blShpj|^6)WYxmq*sn(q?X*wJZk%68y}TeWGIa5A zE!*QrE`n#op5@YBX{iL?opUger8w;OqgBq$*gFeP3~{gS+aQLn4ZAfy%v3{b|F?`ys+i#=BSg86I3PCvx|c9 zkUP5^317bUM!am`tl_b>){8lxYC?=p?QeI=+#Y?yg_BmVw3>={b`3qYWK$btG+AN3 zKMJGGq#MbR&W47a&DkwO+>SWp0eA9v5eYg}pJ|USP8ay7FU@5ll0q3(-5)VOr{~%k z>*XYO=MkV-#3Je4fI;RS@I>K909k$R4D^q789*RdwG5kosAbss|Cd?@>Q^n}*5B1K z9I@-$>i~kUxd+X?Rr)E5tz>}d{sye+{?pyWZm>gXbu;gSO#v2^3qA}@7F&HS-dMnn ztJM4C_Z6A|JJB<;Q(U1LXE&}9xHE>n%cfJ?5AT26vH~KClRuiAu7C2p7%^L3+~u3) zwI*$FPx^?0=UuxivCEGwlg3Y%&gM&san85Y;FkF7$!AH}78}9Hhyyaai<+u91ljlP z-OURN9c$&R!WWx{tc^Rj2aIn~xxeYA?l)Ym7dT=qq$mmF;tGy#>F1`Z=lu3(&$3? z9p9>;gBFRf0Ws}OgmaYc#Igdl$*SbLBSTT2t8;IiFWDDxF{U@EcxIbPr$N*Qj@BWc zi07qiQ!StCE$bHEDsu1%6sTP5xN)iI`LwH}UXyaPF*zHIDfZ*k~cqBV|)Uikh|$6Kh08SAEX&{vEurtoUhWT!fXJP>N*p`^0y zD&mF2z?*AY`D|*I(qmkVCcCK{r}sGS5my%>HC!4`eAHehZ%h)fF^%WeRF#HlS?uC0 z%e=9{cC}}m>^OTPojUg&cx!3kWhUst@smzW^F5Mo0%H0G|Mph2|CGPoH?; z=w%O|pNrjwcxajWpv+R(b~K>q^3PKUtmh%&hjs<_BN(^&!}5<4;OSfp`L)b>VXh_i zJRnoQ!Q>o8mXorEY$A_G`K@$NB7nl@XZ>1mVQo4!1{!``uJrHK42mJnYI z%9~GcaiGRhTm;p*jf2h8uEfa_guO-j>D^AxD!Q45ignC;m~}Wh14yJbM`@4QO%mDT zZ`FcV21PNsFn%v44oM=lPW=30v|2Wwe5AC#Vxd^bwyeR>EOk}qri!8QW;}|2Gx8nz zHTYdPSuL(LGmYL<BkE_&CiU3p^ei>`ALMty+q7SEef$+4jW;ZA;$QQ&8il-JnX zc!LZ}0loGQisZOSeD=_3-(+rLnful!P|YOqa?rIogMdlKQ+y!tIu&OzR53Rwwx;(n zuO6z&FFJ*G7N& zCU^W2p+X7ku8NUc66kFyBf{n!$E9!dUvH`uRaw3o+rx+@*r6tOF6lU~;lEyI*EhJE zoiZPZ%!qfgaVcrZzWH*ne000k(E}%B-eoJvz1vprps=ZE93QFsX`te( z`QpJut#8k{XG7vO4t#C={(QUYsNn;HT+fFv-$-T5B+4aY${;*(@9=ZIOY%m6$F#Tv zHoe#))|U{qs28bPC`-QzI{(YWeREqLg4!!;v2aak9{$%}M%iz@jQxM@Wvu?&UIvJx zF1ozHN&T9g#PR#=q;TLJ82CpCf&l=^tfIy(eb8_i)$K8Kg8wl|2|vpq4!=dw%vx9f zasKV!vRE&i8$U8&D)p<+m=MB(Jj|*AFM{4R>DM@=-)G?BEq)uPq(utkQE6mNRRTD^ zQSGcJ7>ybTDgms%b!b06RL#}bGo)KoIK{_{IDg z#Im5`nd6~)w2C8;^NQGTMvAcC?*XItLg{z07T51Q!fIR0MypsZ3qm@hDZd<-`@|sMY;c3 z(?9`3gmZPxvBwq0>lsd4WKjf=!2+#E-|6%%1>g%YL1WtBE&NB|y2pF?7@(&ZENh~Y z0GO+!{g(kdeHLULhT;ZWiXth8iD)kTpSX#|f0D%d|H6vE8UEWa)9?2fGiGlEZ5kOJ zCf`RqtpwZ%%V~pcm=C!E5*Yl1b3yYKONB&exdXN8oT5p*LJ)=jQFQ)O(f_9pgd>52 zPD%3Nq!~HE7~ReDB5nAkLQUoy#Q1oY1;~4Pc|*&3cxIuLQ73WVG66O6TLon9pAvAa+hX||o|!MDrZa%}%eY%lV(AFe6Q+O+TFYLa?t6nl z=&VfHrYL^5h{&;fhfjL1!TUnU;P$x``=cV0?^2F&`?mf+#JzW16WiK097V;B1;heG z1f@t3MNnEqrHl05rFWzX5k^HtQHX$mfDi%K1i*-qu|xk@tS=4#)1Nil$FQf|yZA?bC7++T*CXRfeG zannCc>u%W1)-gqKVstmW8NLUue^wdEA=S~Cs%Bdz&vW)gvnE<8#bamD)?>U} zSMpe?VmH}Pyl79xGlj-FNygdE%50OuZolQ06S9zhtl*XV;=31`CEJw3jKYpT(VGc0 zjZBVHeU)k8LuMfvt(e)uIrFFWyoUFL38P<>pEY#z3Uso)^l<~<#zTgnn*KJ2Y$%_) z3d%B0m8Yk)PWy<6oVYO&NFGqZ_74$!?tO2w7P$~?7G)onhWJka!@kh7Qm#}M#E5qb}Ku&Ql`M@HwJLsoD zjo?FAO7K@tpv7X)zJB?qyWaQr?t1AJs=*?mEQr~DH~w*@>^l~DXV7@~z-ab|Zk-Oh z!b4nlbbcTXHn&U3@*cVOOw+KtSc@}Km)C&ph0&<1w-KKkIzy;Vfs6=rbbNB|xP@Vr z{uW(f!Kyon1=s73(m^w^Tg2bc(e(QFp)M^L=WcuE)E@FDZ_Ce=yqH zBYW+BMv_MK@FDYD&Wf&}ASb6myctG(JXo}4FIu|%J_9{)Fi2P!JE#GA6<(G>J_?qR z>UeU%zKoY%Du+P2&hcqb2=e>a{ME456xzJ0X|AP_-|L}whWt_bU!@Grd=+%zjrG;g zG%y>Ft97zaGrI565OJ?gsB-npKqX6@zlup}=%?5lav3I@ypC!g-IL<2Pm^?Sb!UI7jQWA-ELiMzN^c9h zSbKva9>b_9mX>Sq&l1wLEx*V!W_2No#dLp!=j&4;0^F9A2CaxB6rp!0I_7Xo;t2Id z8h}L1hWmxTu6Xs_wy0>|r^NfxEBw5VWP>IgtY1jvBvJu}DKWpUZQXwX+x38pZAOBA z^=8|tQwWZNb2S|l$D5Q(0sAdL%VhsMt*)Vy2D%k}yq_wcS=S(R25)WDI9M_#(Czj- zC=H}I`M?o6T04(DtSjeYGYM8EBhsOw!OF%RYJ3 zjOE(b8L6Un9-oOdYDTPQ87Cs?!L#Exwiz**Ib4supjQ#el{a6oDJ&i!HtXIpT^#9^ z`EJs;B0Ai+c0#rP`@1n2d~r&4VpUvXRrn2;X`;}#?3dXYQTBIU$E8U~?yoyGV!~~F zx=`xq9r>lbgd4;4M}?bJk1lMo4xLspmsNdvNBO?J@U*J^vAcUzk46H9Fgc8Y8odP- zZ*C>#RRMn_nn>KRTpC!bl;{Te?Ss0uvaB8#?Q&iZ9g-nVzs|Yi%w4onyo;sr`)9)w zYR;2*C;2|PM_#n6q{EtJ-%7d9JMl|yQQ|T&-jKJ&>yXR4oC%|mDZJzAhnZC#Yc{Di z-}TQaQ)N#(t~9>2ICNp(r!%)^40jg0)J4?=kUx?-U%N%@rq5jM8Z6aqQPgiTyWRXT z-9WDNVDmI!@+rIjVh3*=Yhqm5iDQeG>61^5xQg132B9$a1t&5fG?iAK1_+giD)U%~d&Hzzd zQbl;viT#L_ID6odgNJFo?xqj<85{U)J(}gWh+GLWjvlOkdTFR(q$Q@n?)1FT{sF_9 zTe(FTbygmMArnoN?bl~_jKZ^W_s|kpyUNNTqUF05IgJ^`qYEK}tu9*xeZDk8*sJp> ziYOX51Ii9sK&h^_5%tv$d-N8Q#@SmcLjS)HeF~DSxM>h zaqxO`BtW1xXZqyq_loB5@a*lZsUNy*bY+6Vb5!5QC78$2i;!A@o1354unBuJ%EgBo zJ6{zShgq{oWjHn-r0Ww;RHEWi$6>S5iE3w4yHZ2#IfO&^9F>L3^w~1ekvtA!9Xq{H z0_?)W1euw^VxX%=3;H|etiqw6Z8ZSNuod;QuVxh#SgaUCCNHjN#ozO1LH}F>qJbI^ zII|}cp#~MzvQ=FAG^hbF0mmThV8YGdS|%~>y&CdQs#`o+Zh<_)WX9D5+N1(TYn$PS>5dE#wyqHBAX2B*3s=@wjr75b*#DEY01bBck%Tp{JMR$VAnT<3> zps5}jH>WWhY#z*>!~p7tf&kX^At)Y{kH{lc3gwIPN}x@oZh;{`>@~fL=aW}L`+y?G z5F~a>>&Ytom3Imj?3b!xr5m!9|B?zCa$ay z#Fv1W3&gNDEv}&!c;-9qLSls}0OhqF3wQ~N055?J=TG=q1}F<1%M1DxJoIX&cRzr{ zt}v(cF1Shq{rwLGlV4FB+uuiVLlPi;^IM^3dW1|`n!Q>afvX*&dDsXW3LQ7MOW5jC zyd-jQu5c`q9#b@Kyp>8vZ*=E+(VFy))%{J>7x=WKz);?F#-c!O)|Ay-){@#Gp+`vp zL}SMbuAWEMC>#jx69+d%-n}C7Nvx59 z?)EC@r8y9g9&i#Dw7kVe=3Y}zu~iJ$vu0Z8o&x>e1xxbRrX-<2fijwnQ{W~0n&EzH zxi;>Xj#KJw$K{2?gPl79+5osHZ^7V*7@o*o@-UvZZ{kb>*O&D>JCrs_8jaCi=$M%~ z3)i`nCLT|*$#{m~W#re8)OjMUwdQk$w1%`V2C?Xzp||2D4Zx9f0gWXerZrso_BF=6 z9C0|?L?2mRpLi+q;8DFupKd++NBCmWx<8V(t5gqSw5?99cY1@E<5E2AU9PVMu51ih=LUbaB%gWIt@Xc3uu?HSYX0Wc>Oy?{1ELK25X-#Ft7Hga^2Ow3c|uaK`bQ zQpwxk#3v}1{a<3-;3dzuno(A{<%42(7J8gdpF!%{R%xS-v(VGG48smOa_a#BhE1EL zQe31aznWGKkeAs5&sl4uq?eF0HgocUbI*^f4Ur!xT)ey~qz4e^iDiW7!>cFPNc$B0 zCbkZWe_SHgx-jt=Uta>r&2e)EjK0{z`(vAjrpMj1;5{%38EvPl_j{Bqu#q z;_KE#a7rAqq4o?Q^0k!1AMq;2z6!5CWT6(7mT94F@TI%XNb@v6K1ANwAp}@~f*Y2G zhE1=ylhU1%Z{%#uRrunhVlq%jPLh^z@9^Zp1?*aR`Jt%IQ&@99Mn780&SrIgFWC8@ zjWC?%`a+UfLdH@)0{+R4=kou+%S^fgysGh7wtk4v@MrxTBvU_U1Cv8jYW5rezy8ED zhM8+kEr1P39uWjQc0@E@y$k#aw;K>MV*%yEe`x69`>mnt|B;5y|8~KV32FRKB035| zn}8tAzfB{Me=-&Pl9K+HT9_RF*R?R^{=F6^ZSoJEivJeah&xDA`ICxH(*I=@9r%UE z@37FBlCuxf+rKULi-a19q0UC+f9#VwBlPtBcpT=q`m&z@GUq6;BQW?#p@~ zd!vQ+DH-k_YCoPk;nTUVjBRdjij14D2GV&IL!>gBoxPp> zSz}7<3&e=ff`>bs_|Ke3JzFp0$^J+`>d-bl(|LLlDvl`Our_Y;EY88>D>=IL<8buV z>2WNPWX1!di#Klpa6E@HtJU^i7dA4IHkH}=cH#nRW^WNRT9Q7|9jw^PVC$5a%kXm89k&}K()=nJwS{K7-Nq91+^nO(X!rGO3%p{2}+7`(3Vi`e0$ z6v1KpkS|>FveM;9!A?nV75CN*26@0BXos>7AgTnJ(e|3=au9f3xTau?NO|h+vPMIH}kmh>_>{X|}yH9nN zD0isJoqYECUa9h2sZ$e2_Lo~h!ZnWce0clvBx8_)?PVNc4C7_RPb4IlCV`q%a@{ld zNOZW=Jz?nnRKR8fu3jUXv^3VMo*6SXuK{YJ@(4U2)m}}q6fONQ9i@=c<0pRDMU^9L zx3Jk2j+n8g9;eOZ9ybjrD6ja~(yFZ6uEYP|Hh<+hD$hh`Em$~A6Nj9&Amt#Ss&GpN(|v$Y0g+7%2bJCdm)fKSNE zx1#u>i>=zWhnSp;gK4%)b^-$DhgT!0!R*(SON%7f?R@ozLa&kR{4-qamBs$jxk0cd|= z$FS|kg>Z54itl*?12~;~^P}a?%7(g$SjTu#(m#BlAhmitXBARk3=_; zwrWOvs1?pvyhwm|se4k#;3n~!kCVieFCLH8Z>AYsf|s`x!7E>+(X@JWIZo&{<&yKE z#j=Q_D5of+PspdC>57*ysr5Qtgd$(bXT!l<*AA<1-|plzJ!4~eS%0}uI8Bf)oXPXP zQ-iMR9?NRd2hG}61c1=?OThvR$;~O>JQs`PnPYRN=U0#3hn$SJ>-e1P{ zA;%sQ9fJ!9TgUdd1NQFR$$7mG(zLVF1ii8aH(#-P9vH1QrY3&{jjH9DcBA7Itshe?hoaL!xD$n*0t1)OSQYdv)AQ!^UR+hVrl3+4+&TPkNs} zaMrJVJUcV49GHSjC3_Hy>TU>w;#(UI%v5_E=^3aU9$&COx=Y{S-B-aE`XQI58d9;R zmXv92v~*9o`ty~Q_WEK5`%5>oZ;sGGAdhqK$LOlfT!T;`oxq4+wnFZ{`#El^bd`<3 zpjQCTA7wXO_d6rU-X$zO8y!aPfWG^Ay2Eu#aNY181&eET3Kojl8F%ux&A6oAf1Q{u zBs43OeGCwF3r$|)`qIAhR!(}BaPzx6+cp`~u5+hbPpg7R+)0sZD_>W7iyD8pQrt0v zr+2nW9({ag>sQ4_xtr_xtgx`Hp>^Dwdrd1yQLI&NiiIW#1oGUV$1SgdJ~=HoD5Uw|8e{@S^248eb zx2{d0?_Pq$(-QkLXY>vA-*{bq(AA^GU*N7QE5ZLsx;*|!#9TSWPO_w0bzC@8Y|i9? z{`MSQwX|F5w-A1NEJ;R5pC_(YlSFvNW>pdm4OHvY_&EKy9nL-~qP9Ie`z^->ZrO7H zv*+oyJI*X6>IlA|Ou+6M(sT7d%V6~sE3dyB5LN5XYl!HbAvhaiMA7P=M3S;A31Trhz@;NYH}rE(L>WlOnR&r+Qy;DYMGlNo3?9o)astUkW=fPGd;q z3H$GQ0s3lYdL6z8WtxsJN>*$6c?K70zT6?H_Tb}q`U@pFq|&Kl!+U)K4>yb!c<1g> zPKr@Yh0^MGhRt_(#0$*ZF3oxjDtxyjxli+2jJ(zsQcJs|w@SS6_%5U1ivcjyUCpw>9x}IQ0yVP*cG&Q_w>j%>K{0Lb(j`G8MPTbkG<~Rck@}h z*E=Ea%nC~ub>Ym6#@)AQI0;X=u1aov$n#>=QSV*)-oLH!O?Vh^r=fKZF#ztLs){YILAm;nT!_DLQ7`ZSuiTgg60~#&lK{7fSHJ*W_cOn-k)3aUa`v7tuSJ$ud zVizu62Q;OP(qW)Fx*LLiAwl>%BgCJvMZaA%}TPceY&ZvzmKtN2^L z5ozp%R%;uew~DB#{+y?{@$5gv{Yd(-6%*q5Til<=Y-0nIt+q_9n+FU~2xW@l>}QJM zFm+2)Kt~xBpgch%-hP0P1vDB=AsO&e@eRO10VPq!!3^Uh47f)y%)?k+t`+0n6pR@j z63DYXHF?sqTyo)|&?+o)Tv`3H|Muc;7yHN*1wWVM?!sLJBR;L718ps`DT|jrR2^H2 zD#Xe2Jwg_0bM2GC1Wt{7)*a_?61S6_WR-!YaWu*5kb?C9Di!FK~sXt7fHS_7+tszgE~YX6sT!Z)qE zj`v*Z)~f1YZ%S7Rwc6s15wbe(aQgeQ<2!`9h4}GloDu{ z;%t#(@;V^SguAwYKT-`Kl65`j^e${>)h3*gJ#bA;PL0Th^ZVDl$oUNd>wvy(`YN%O zFqe{55Ls>O(VD`0Kq+t`#3B2GVP=e3gUQ3J9+t5216#Q^`WDL3ght9l({J8=U-d3V zJc_Rp>MTqbdiPajZdQM_dKB*`pD+@CV|55!IfT@9j6fQ^>0V43)YMj&t0wRpW-Gop z@TvnTCsno{7v{ElPyR&f@CqA;sF*|YD_JuM?T%Y=7^#fZsNqxk38S*H8_klBZJjJ| zE)d};2=q;QaQ}*?76;TBrFfL8EggGsWk|eQfRgMD$+vqp!PH9!-dCw!RDlk8j+7K_ zOcC^Mx0~zX@Q>c!S*&6qj~tIapRRVzH%@4;UASt$oVPMTSM5l_X4RriUJ%c>UPEQU zuRz!S97qCVOjmk`&VQ@AE#{tV7pb%}^5yB`!tCP0Or~%_=FvO5WR55Qxw@VoHXQ$l znk>eg_Is0`IJ3!bKh!{X9VpQGa2+r})&h|tKz&GO=HlDvpCEm@qa<2=<(c5``w-e(vwF75LurlRvo54 z*$F*rI+*#Q;C;KA(T3<_xm5&zvz(3MUW%*iQ%x_+$Ac%w_N!qb(Z{y?M#QNh7rN%n!J$Dt{9cj9)*Gq}H=CT#5L(VqYwM;W|Kp;6eGLM}ficnnY4nQDl(%xUfQAAyK5^ zNEP@xz}c9tQ~u#maLgxxb=hdm&=+|$16>1BWa&{q5YM%t-r5?tMF3!e+BuPM@Di4x zN5=QPaSgTfnz!Qywvh|IMFx(aRY-bKY^~Qao+~34>Jzy7+KJzWI2@5f%Cb z7B2H6uR735V6+-)sUs9HgLsC(8H;3kI);(~7G@P?y^&@Q$`Tzv5a%6#Ao7yYjD*@b zfD-Q1qAy#6GI~%#-Xc`_1ZV@e{?((T!R>?l&^^n<#>=4HC~^nzCGNkI&lLJS68~_MKirD z)GhZpzE&TN=B@_MBIJhSx~&Srg_2tea$34FjYf{paE_E679~Rs4E*MCcadyFym|N_ zi=hoKySX+9Uv{JZ(a6+ce{I)a8&D@;oq`6*1r@#@h;yl6r39lHaaVyCm?DOv)22}C z8F*Yi7iiBALN5F?d6fTZ{Dc=Yst4aD;)x?9PX-r;J{Ag>u8>zvWVGNL6@ajT{2VM= zYzSQ8!%2UMq}*j%)Bo<)fALX3d?&=p_=cM1sex-oCxKR8;}67VK@`yn*dF_sm%#Ww z!T@wEwH?l)kcnZSAknNsxBqX)LlV$m86F0P18W|rwa!`q6$Dh`mc3C+;cV-DeYgR; z85DJl0E~964@iIq)7HO%@;ET)hyH2s7w4g1^cxv1J3HAOc@iw{q&W*indmT)ScBO4 zO^4J!rsivvHZ@6#=5zX1E34MjV-(s}KAM-YLgZ$Kmb4PjPch%HR z!ZsA?gl`kO{VUc-YW<={k7e<^ez^02-{nk#M&>yiQ|)eF9cUnl)J~lTzFE66+Ydxm zO(gE`mw2PqN)!MKN2J5v?V#Q$L!q4s9{7Qfe~G0|gN?Exjf3>40kBR34Y&heEYJ+Q zV1RK-2Z6=&65wusuK9c8N5*%<;0ry4*8c7AzCYQ@e={7Ix;^}pGnQ2?W z51Am{aMOdRDUgd=DJg(Tq(`tzgWw2Fd5rvl&_h#JP=7PU|J`tCf(xoaF*f(%dR2zR z*QGGj78Jt`oce7PNBU|sG?mT@=w3$|46O+=RRt6r{@;y#3Z0P68^0{usUe%4GV=Dn@&r$VD##bU@4-{ z*NeBH)Unr}J|Ag4$tPHGj{l|*5suGQj~{LK*=ML&d3dABs&*ifn$c_Zj~m|)YA_GMZ=`;z_jQ+CAR9y>y!qqtl# zD*uvezcE4{<8P7Q@XWuFqB$bxjMo-XGri}aE%$Q zfFq&8O+o>h7lkbO58K))zT!}3H;g^Yzs&Pb8&VR^^rq0$e=XK&Tew(Z0P1)HeKuh> zMSu(=h0%|jQQ7(V)0M!$uvB_TawRQc4|MZ7Bp)j=nW=^^Y1LAHCyMCV*bGD`wBGU=9%J_243(L?X z{bpo;GlS|z16J;=^pf9P%*XTu5)PPr&`Hvg@zYk(&;Q9GRVS<(4Vgksl3>ztL`QJ* z$XRgn&%b+^qu><#I~P+orG@4>QO-tfk!H9}yUlRjvuZTY_u&`<=K$Kte^dd>d;iX5 zbE|=#K7B^1e$I)5dhy-isk!%VmDX2Qpr55-V)F=CTOJnmL36qRLjR^|7WV2b9)hVE zP1DvrxbfujzERbV=64Bav&CMqCmFNzC+3}-tW}n%mGmv3FMy-8u*DGsTJCyt#~GfJ zNXiey&x1a#pD|832ww6s(=&jGR>qi5DRJOcq<{+q3K#w0b7@sWW|d(KCX|MG9=}?k z)suJ$6(Evh1CiXewXV)O*t$OqRw}s(&9;LLYDNu(bx{OnBnRLe)$q3z+1t$E3>K(O4F8m75l%Jq8+N~C!LsMK<%dEyn2mzWQQoay%rOga56w3Ge1f22$ zcltFY&TLg&-@QCR+uX0QkS5fQ1i`A06+?%F@0|yDV)&;EIo*r&sqBw}Wq#dOm9fw* zkM0{%@glpY-!i{CF?6u`aoK+U(t*QqX^pxO+WOmrn(Q7fr}$Rwf%pdJtAj_RHKxmm z)SIdf*7T6=3!X(}PM))QUAf*To?565D;ZqcPJbZ3{{WSH z7+UIU0@I!=4jcg56I3>ul}7j#i|Mt73@tjnD?u(rYpt{8YA#9xpLVK%X>E+H*1{n) zoHd7Bj6{usgLL|nxJRYjPE+X9IB;@7(vwg25gbGXH@^>KSJ+5(PgmI};8O=d>pRl7 z*3?Yw{qO~<0Y9v`a<5j2vJFt%*J{yMzTx_CbXJPzY)T!x_RCr5cy1orYzrS_qg0}% z#R|(C^TFp&sRDy-aO>F724OczxbD{jE1z0K3U{V;|GF{gB)?2yMUhD{jQirdfD;0* zp4YMgjT{j3wiw3G-GqeOY?%F%#X-l(XVtr zPa-j*{q_eBx5*Lp;nA@=!kNl&d~MT3*V73>{Ec?PZ`qfGd83`Vmyg}!EJR$N+w9kR zq%^iW&cAae@&q`kG&!~za2$JmYlEKN7r*kh&fYN%)#F`UR~pkE-P67JI6QH~lpe90 zvc~8Rg>8VLX-}~Qvm^iJd`9pO1O$#T;0aBC#y<=2xd;OH#|6}?NIY^q2}_x6@PHT>47z1k96q^e$ps%4`${ELRJn(zYLQZ&UgrXwS`z_U?m$G zG>kdK>_$t-@I9 zVhc8dfuh*79l^650hyS|>DgVMS1NFe$jR9=z5@EN)Ej@$NEBzbutI1j5fUi1JSe(7 zG|dw^PbRe=fG^QUltb>#VyP1`z($FS;Am_Vs5;USk77RI&!|$Syt+cpj0)(lFZmhK z7iTD8 zvSiUao_thF%1$?aQLt}9_@qE;;>)%ulb4*~iR_&R1-sDZ(Mo3AZ{_OT`p^{%FO>z^ z>IOF!vYYM}(aH}x7ZLu1lY4W-XmT1fDZsP={RL|e>6~YKE2YnVQ`gJd-x!J^fY-|gyx z;8J&R3)9r|n8 z6YuoCTuqD??BTkwIBn7rUoKZ4Osl@(d3evOH($iPQnzGpsMoq=yWC&~ON~KOAzCmF zy({wCs2oTtF!yV89#tj&VH@t3rAtR$S!tjzWq~GFDr%iUs(VJkP{==5Xbo z^4|uQYx=blJTlghxF)EN?9WyI7Q#UU<}y7xo^K+V2kaploDG?6UBN!UX;=h5tpOkN z4EWQ)7vmvDa_%a$pEg*m=QVkiG`@oNY-(t1od!3DUF^k~(1960T z$N8?20BDWU1-_rqz)7f=><+M~^U$UK^Z0gh$6(h_^=onaN zs7Q)jOX4Vfkr{B`WW#~D%DQ8Vh4(#2uG}3LQy$@eC>`QzJMy&b=+5iAgb;^+AU=S0 z3HleG0`e}(tqHViWuW-LbnMMzP1h^8_~+Q0%E}a3@O_?4d<5CN6mDL*ZeSp9w`5?T zb=JV(GUlw3=9OYC9l1`aj5z04#}l3$eNW=P>SUS=H> z7+KA15X!_nxWanz+Po#ob%vHQOG5@?eRuBu0k6e057NL+d6|v>^*k|+E|p9Zx*|6Z!2}I zMxR5*tdCIMw*jO6q} zk=ovgPu~RvsTaf?G{uyd1HhB${P*j${tT?;G{IN8g?pjzNrzkO z=(k*~!@DSVd-X|2aj5;>e83-$x?GtX;RK$qMz3hb8c;{0eK*p5zthV3qr+Hs9 zUPyhMm6a)T&vkVL54lzv#mM(hoIAhtj1S{ofs=t>pEu@j{$vGmMS27mLc)^U$8nQ0 z-e`__&y?Oj2Ifks{2VAl%ma}~Fqtwr12dTRJ6@njp%?1Ng+4no<7DG@V>b-7vjFxt zg8J}i29^2K(ZCUS6-8s4w?K`@{eDZwTz_y&T|9QNnM}cqP;mI9WK=2hmT>}wwLRAv z-M@{@M@=^X@8WYTYN@yyu0`X?ZS4#iJ)S-y3xk1BM<(>y6|+9nhwF%J0@EZ6P1y%9 zZc@njqzoDbK8>3MN#h;!MvTK@^hw}VGfNi-=djeyjGqtL9`d(`EP!&wORbh&kV}aK zxNL>IY+DRXspF^vz)V@m)Bbqrn!o$uUe9HlVmVHDYy6TKyv2wi3AJc3-&~Jo#hl85 zm3yl>4H={t-vKpj#tLXos)7C&WR{agtrn&|3g}WxSXyp;KWbQOnR2+)1~y2Ra~8T=f6sezSYW*LfdBM%G=bo?D` z-yyu!C|`H%$rjc!GjOoZ7QTw$Qk#}<^Cug)H*Go(H}~Ige&n=goZ_)1(%n$hcIQ$~ zFguLm`TT7n#kNBGyRrG{=XZFc!{%h1f;i_>Mwdv7DJQy$@#c9avt`vroH1t~V4mopW$MYJI0>AE`@10O^(#f2sup_@Gu&r^v>Z0k9 zf^(J8kru;IoDZdp*m`#3<<3i5{Tm)TGb8bfz*qoI;ja`MCJVZU* z`M-OlJ3SBK)XiAk!*(GlN4EOV%^m$IoXC4UQ8-&fP{Mpl%!)038;a01ieI}9%p>Uy z`eDt-9|#|?kvfrU6k~fzGSC?fbpu{k03ee|=Ehy0GH&>H--x>M_X2aGcoEd3x+5?R z_T@OrbO&ZE8&pK>CHaO<}4{%(x> za{C`^=szI20jsJq9e6Vd->RY6BksUUIIBkT9>-CQtZ87s=S1{fln?uX$gnC0BH3Wy zzDWoY=c%{2BL7dqeSYK-_Zv)}t{Z+0Gvr_enXeE&1n7#c>mkkAn9u^>SLc@fV0NgX ztrpd=IRbQ>uTqfcd+=A_-n3m}cAay>3%Et4A!za~cE!!_+D?$v2?D{))!=&WYqVb-i1VU5s)%(8P3QJq%cr$I5UkC@p_38R=W=OcG@>h)#fv=pdWeoe)qZ zP0+%Tfp6A(iE-VDk-SKu$IU~NX)8w;_kuPge-P%JjiJlyy{E|gCFy`C!b5rFx>p@u z#3Sg!8Q&0nros-Os9PT;ciauW=2?IX^sVJ#lDYYF1)ai-abHuI?_6WTtF+c`1BQo& zcYaLv3wbiY6sn z821=V5qj=0xA*EU$wEu+B2j;S^GQSA`F`vZBRb7z`YBHga{0XrVSkC zn>=;T2SARsV3i1OnY}nJP8CB^U*o@7MpiRv(~+w@1e=-eCHHQ}b!HqD1g3lf$K`hj zhg!h-Pm^}1OMr*+3^+8s$`-F<%ADIFAJPbq;w5!IZs0BZz<`xQruIEbhA3Mz9o7(q@<}v-ZLU~F1STeLe1GWHgKSSU`*QNkmllP(eNx|_SrL= z8?nwcxW{Qemdmjx?hi^GWMR;iPHU}mcqz#2(~i8sn1>gn70x!ic^)GXvA@K-QaSyM z-Px!1Asm*R0%H!0-909kpY~k`I;qG7T;PsAnf2)%N$5Vy8TTTYDfFtLxs8;;m&n*4r(zy$w2@@28x~{`mHDdZ=rPeClw3JkF_18vV3or)^t=@XcFXCYb13 zYF}9|TI!FJoTefMq!jdu;^3L3G=9-nDxCgnwn`kLe6dQ1IO`45{ci0KmS+ol$Zv_w zblGdC_*M3e>>?xyXjeT8bzLI>7&div({S)RgA?-kqE=loVdJ;@__{+Ei2{|fqyo9w z_?z>=-&kTcmmXStdpKY-M{LF2NTs8P6)eURSEGFL};&G-B36NmaA zhc~S!rrlvdp>#{Pr(J-0ZRVQ$0*2=rrAn&0T69jri!Qh~z8rY@ig7V#!>iVVq8=Ix z{`U@8HQVhFW@Ho67;hEC-OW=Ib6gC&-3NO`7CNt3R_`-;&~?y=G2QLcTmt3IS(N*X z4C`aOAFJ28)f6mAt{KzsrxdlMC`=CLRf)vkd~}26Hu=itSwh~!dUn+6LZtl1&mk83 zM~Hn#s%`Xhk38b!-=jVuRO~xNl8C)5c#Stl(R%n%`aRF@lwtOxNPcUA9EpJHPW7Z$5b1Bo?~$0?!LQW+RCpipWHRJ8o*rG z{dQMvEhDm~=N|nyl~=5_t;^h481Yu9vXW^FoX?sf{xdS#84 zhR{owUA3_8#;j{jq8@|cU&n-+)g^OUHS49<;f0ru1?i0?fN3%mZkR^(f$ff-{=nP2 zA4E=d4C3heDGcDXr>vpNHPV?<2!sVd8Qnpz`UC;@030)*!?R4Gf>ype1$b_Cz-tR4 z2LGhDXQFtpPzMiX&9w`)z{e<{2K_IH0RLO35;Sl88?VyHiktgSCvw=|=oM?oqrv~I zgqy8P!cdbeFo2pP4gzT#HZt#d2v+sSE~x?P*Zc%DNDqK~mIH8y&Y@-pmk-g-O?&>~ z4cVmJ5VB6p&UVVm%1Vn43V%4RYJF#`c9Te#2JiOF>>Xz$5F30NsvEdsREsXZN`A0C zb)VXaTZq$Y=MZ)&1?;-*!tXc62k;u`?`!?|1+hg<0I@UXc8@iMyu>|JZJAc>=9{8` zxiRr#u}iDQTUn>nS$N|cH?Qs}_V}YZxrW{g@7#UQq+1PlG{c>3URmhY{A+qq8~5gp zBfD?j%gi%y>E^3BxVQH@O_L%yD&2SuFW;81I^>@&`qXzl!yMV`V^F@yI@Rc@VZ^sn z83tDUz+o7+$k3Cc4M8NXS8|h9l>NJ038!@U3o`2t>_0U2di%MJ3o)Kq3X{O?94IrU zixv;?)(dl1+@@c3nG12#GWpg7ccOh7pS(0Ld1LmDsMRBQ{P~k}2`~GO-~9g0=oU8% zSaNI*BdTwR1tG-Xlm036(WHH~A}OsS=NUy7>`gLl_nHm9utqDecVA-J^wjK5@yU(n zj$)iid7|Pkq$oxFnKyDWtsy?0FAy|w)pRn)uy|5qt9Y8VVa#RB1?X;}NXF#LJ>G1F zY8}Ydc<*b%f*^An_~pb{U5SzwWA#I)l17EZjQsV&8UF<4TK@WTOn%g`U6J z$CWIh-gCqFyAE%(!p5TTax-0!0Uqfp56Cbj$+wrDVLwFQVs#di-7s;zBu`27vS`GH z`>!S}4zkAyY#?~)^q8m~)FZ{-BMrP&vW1Q)i8#HFy{{6mcU*Do;J#cz#iOBptO}GP z2Nqh)iS|Y0)lO53p}J#D?BNDa*RX|I?85J2{dk|o9*tQdog(fJVg@`_6jFJI4;dGS z=dL|H_F1C}t>rd1ld?@9?Y*Y)$#P|#Yui6p)RbfP8D4RF7qQnE^I}zMLd%0%myCoj zt!jz*y@<_xg0bp$5#nnVd(D%4C8djj4<4gb(WYzO^m_yx-^nqxEv@&MtJZ-@%~PqF zeBx9;y=o%NzIP#%)k06DSf;DAy!%w^zMUny-=s!1oAVJRz3hcUW}x?Wx3wx;+-SKz zI~$Sy!>PBrP9B!4q^UjDo9YemE~hA?300=A+Ru>Dmffww9WIHJmlf`%VLqT-DreY$ zU%Z`nCLsHvxBP~I?q$2e6qhTXd$Up`Y+p9)j8Q(4WX{Rc`ihn{@}Ma+@ZzXqUL!JL zUkn{{@lgROh$3X|P%=4EG*0LJR%M`2%6kygA9UX041G#rxBrCw0Y2W^#bl%Bc|3_% zTk6{GeNy4oHarw?RszeDYdpOngA;Z2{3-$ulTyC9ExcJ(JMcAB^4`pGRHy2JibdUz z-+^twle8#qjOm)%@_4T|gK7A@YhyIG56-Gtjb+yHn>NH;mP9J#on%Y==)vWF!ja`^ z!(`E+t-5Jp0^zwC1*y4r6n*0o^J7z__11(NhPean1ImYMlIdDI8=abtJ+)W3XS@;R zXe?AQUwyv=ePXEU{qfR|{5kc)lHPo~d82Mwhg|lZnip67xd0vow6Ia56Mi6QCi7&* zu+p4a6LPVz0R{;hLPl14KXN@V4!d-f0Oyt)h?6{tss9|p{K8qse$!%_YsDzRuEwP+vu*8JFq+jJM&fa}v#grnMF{vAJQD3_k;gHH&9xCZ&dK z0jw`m7=-bwUH13B&)@!VbNwgx?EiiccAbc+SzaUF26b^pFqvEUY6UW6M%~w6;a31Q zuLJ_Hkx(=y80>H_5KT=|hLO&40^#2kndN38@=1=gC#h*ZKCEr8JyqWnOtx#xz_f;WzS zrlMgDf83Hz(38L&u;F|)?3%F_l;J}PZIMF5AV4)i5vDRz#-ZvX7-}}CZxK3U=K-%b9S%<87BA?@bu^A84C2{fU(RLH=rcz`O)`ctqz7l{|0^U0!1^-nTG{XaWKVhM-E*AeBMCLNa68| zwXEL#)E@|AW;2htSRtU?>thf`fId{NDEM;}8pLK^V7`L54_)d#v5o|quk{~&rRdG{jG}L2 zJ=}tf1l1>nzuHPUs6La*Ec!m1Wv!pncaAbKa7`%AN2cF? zLUtQeFx|vc3yB=|!VP&2!bF#x z*=*OGY~hoxu8t|$#l`u7!ou0Jvvz0n4fMOOXf*Lhwtk*dyQan;LzdiYD7iIMm03oR zyG7ky@t!~W%DhOf$+Kv+v&>#aP)CUQn35I=)s3!as5p+5*9EuZW7R547JJ-73e&Q- zN!ix9MNY;EZSS`AAJmxXe5I~s{I%iGa%NPWaKp_7(gA$4PO!*Ptsp{~%(o3+JENY+ zeTbZ-?*8@^6#!KWoTiObz>9B1%jfo-JyCUXM1u8{X=qr?+Bhm>>sj}!y3%h)ih76m za-`%f`})yAp`PDn7D|H%FERAjRlezVXA^`Q-j?pi^}LFGC^uM#xlvi^IaF|p2~hjapUnBkvTq_F)bl-RGV5; zXX(kqX&s6OncSb~n5ugH{HWgj43G^t3tUmL@Yn)l(4Ac)10=bCE&-#nzXDJ@_RqM5 zSlG&q!gDf~DHgV#8MJnwLu`ZuRtH=pYAG)@A@OXkZI`n2NhQrEso4=}nJ=>+I^5Uy z(!cZgoZR=isFh7f7twqVkx8>hj)KH@p_kys71mAG%P|4{Wg&J$#|O%3PNaFq&6el& zPe&1--{&%TdS7q&0XSaa} z4trGifoliOzkT-LRXTg1#_a>EVnhy^@yL!?I|mizoso|XVxNwf7zb~ayCY9)4$Hfv ze_!vSyi6_m0i%&o(<3Pwm$gKiPx~@I()hVAv7~O-f=Pl1>sjpr60$W*U~F_jYdF%B z3x|{JZFxOPDppavkZ0AcsCE2Asx~4w)r&ZrL3lY8n6s$CozfaxViRRA#EG~p zrCwSNh?w=@)s2?mulcyYmPK&-3zEn{;Wv;_#MHgOSoY5Z`8^m0$t$|+ND)&cZ9f{X zVM{y&?8-Vrp8P6mr2${110sSyg&HLQiN{d*$+7u;xt$IYP_D2g?#KVR=JCG`i2iMs z-Kf1FGV-^hHigLsLB{_12>uTt5jYnAYDn}!jqkp6oRMnU!^3L)QL%iHk``A<^VSGN zv|1t0YWC;%d-kcNvhc^e+d%Az;!)ZAX~&s8h>b5}Zh@rxBDXfa75}VKp}%E(9iQ)A zqT^>N1HEZ9>O6Bvfsy~}3DqSdVXNmim#@Kj^7B$ra;Y(gFU33$ZPf8zsUjsMZmGS# z`alu6k?Q)IyCF;IxQkT|${$}H8-LXOyASsKg<{Vxv5Jm&_C?AY!&3>f58&Rb65aJk zR_Buq!wJ3CetkH<+P`y2=8mBIC5hd$pK$T0CB!IhYqdISW@cX7a^zx@j^Y4~|G+cR z^C-7!oX1D}WU;TH-+-I&HN8z(gb*u)?4}TXUpY_X%54V zgXMt!-~g$k@qVnK-bIN!@>}`$Ufi~cr`D+QQG9v69=_nb?X&rm&p!~Ji5ln!{D&=t z(ym4Gu}tP}U6xZ)WPJs4d1JL-^wM1X@}-wVVQ>62jkh9*bIejVE+@z~`{b!1e8pZN z;`JeyvLjtR-^wnk^9UzSTj{o$&vslSrk#zdV{b(|!Q>_p9UlP&743I&h7Rdmm(1Co zz1XvU?Me@;eeDEtq=w;9QbMsJZ(va=Yt1?v_eFz0UJxDa+9|m3ZtUJs-D1@Yy{Eb? zE<@GQAv5?udgSbAQrMZQ@)M>3Sxt^-sE2c3UoCd@o_L*;QXZ}2@=obB}NjJ zn2NG*S;i7mi7Aro%V4rEgR#wwS$nRpPUk-7KKK2+?&tU1zkj?WX8V4=pU?Ha-peK8 zn7Y2#Z&zEE|KaYopzyf)CTG1Gb5^~4yGehG4JCeyf&FI7a9=OhM!FW2o{{U8a58@A zg3+NT=pO4mw(q`18kL?(Q~m5fiZAzS>7+o=tvh=}EJOH?tJfMdCcusS+JDW}(|Z(# zf_fs9_ANM9&0XNLWX7`04EH&z7Wyu=?zr(DMY}EoV2N%i&OpOlTJxCTE#&fi&I2;h z55+iNoPzVhS^e_wD*b=Tx2+at58?XLaWnf^CbO8fhD(s^Mzw`VD$_Q2j(Lux5g8Px zS+n;Tm4a@^mA7o&g(l)=$UIGbCiU1~qK*G(%lv>ZnZPX4f54Yh?o|YKycALJynrg0 zJ{3Q>>nOZ@U(o^#r?AsowiU;Xc&iOv6yqFj7}pJX7>=1Vb7KAUw|)Jm4@q6Q_h9K=kfu$6 z(Vq#uNa=is6GQ^oaEAm}`XitFa^fCDz9sQY0m+D6)Pz8=E3W;~*rs7e>*@+*xf{&Zc)frz5prS7cls_s!v*F`kIA^i9cHnAE z;U6+lK&jv_l8=t1iW(6(LBv`>5{>XbcR^1G>=&fey&!_vE(oD>M#V{YjM)moJP1I7|O4>6pR&QSamaDzlCMx%YYt<6+roh)>edhl5+cIj<{x)A)n8%oe#rd+h zMF&@UYfJrl%5eX}llk?ba>bVA^}f44*ygDFtqOnpEobJ@)4f~5mj^4a)m~~`S7&sx za?`c=_%&~rraqe|=;)ZHi;RztyN_E>O@5C2cvN|Jirgf61Y%g!#%p)ESnBNiN6bvMK&*}r z`rgP)+&~mzvb@P1<+VlaUGl6C+`XFg+Lv{cKxvLc6v7txs#`uctA0`dchZM%z@zlQ zYAr*<*jX48rWnMY$wY^y>j9&@^SGuxnh+$t1D~9Ks*#b`P}fv0ZMgH4l5wN)=TJFg z9i=t>cMrKOeI2=&IeOAydFYNqY1(pr9KU`@-Iy^Y%FX z@aj90liI?!HBJ03G1BAwirN)UKV&j(s!eYsdtmP9%r^>y=8@uYGoj%0n`@>pMWh(N zs4kZU8QKcIg>3e3Gb=t^9?9R6b;g^;ZC}ez96bCwe>vBRnUbEUqIo6ELs>@2GI!yY z{EO||RxEo6yHM`;U+pC7Q@64jfXGj#2Gf(6sJzh4XHYCq-IX&uc^G;&w63iThM^=R1ksQVPAUHQy;UvghhX9}3F3mh zgG=quNRwf7sdup!q~HPRY+K(tr3S-%(Lc_EAez-**be?|ptC>@mk*zf&3|E}@4v0? z{}a07&q;KD>a~&o(Z54f5KY_s^msLyl|c7YqrVH42(u!dl7I|W$FLI#lXWe}O5x2U z;c{`c>ro8Xz~%g>-l}uwcqVmVW7k9Jpyru4M`D^xte3CLX^(TM8}3J5_N{((K4i!I zjSG)!w;F|Z>_K1Jw^ys50`&Y^4AuLU1 zfsFg${{1cf_cWtF8YP&Bn=7t+wM*lWkbl<;%z}yJkq||D@*Dg&&lZz?_ZT!Rnu^PU zE@Fac15SdAf8*WkGM3lK^*+8a*4H6%U-~b209u`ks8g_R8M;;b_>EXT#k1gZbv$ z?9W1!Xyjrrp(I`xs5EbNw+U`u^{~IoCf%p}Oh?^qcA`;)D6eA=d*gAa1+O|5XGP7B2gOqO582*F9a&=o zha#}S?_4*XYAG*_R>mku7%V)%cIdCO7!&Pp=`2|nowP0AMzYPn%EKxJx|Z<|Jku?% z-CCni7Z4j8_40`cabs}7T9>Y&OO-=CQX$TIX!^*4Ef4oZtbDfA6Dz*wm7!W(krX|2 z48P|~wA4h*xwy&H-lLReIE}RC@wc5+$=qJIB;{3dLh_U7%q1yKDgFLV+fwcP6}An8 z<$YQ{Q8iz7TjBY$i?#Y}a?`V}`McSfk9D34d#g~TvweQVsk=x<)N|V6y{z%4NtQ=& z8){>G%rBda&E70k$}-y9m6S$}JJ@t-#DC&-Bk0p=of=AFqpk(me{49cb7vyq7Fbpum2Tbe z?vdhbT*JJ9$u!H4UFSDU%RSi18x#bYUcN-Lkhw9^(O}OFA!ajF*4`^!s2wVs6WDH! zl0F@o6p21{y2$aQlbZa3J)UIatqL@;ji?fG!F{hS10B>iuhNc6E?fHRo@x&vrwISV z4QU<;>brv0tTE>13x=6xQ`6~Xqh6iFuS~S7cQt?xS$ba zv%9r_^TS#Fp2PQ{aMC@rfWYkHUECL+JSFF3eNbF)rJ)e-i`usnDGG1Xw&iaBB~gqa zp}}RUwVu^ItW8Vvq<6ZN`p|u3LoA25xLr`O$3Ez`!FCg`revm#j5VpqP{%T|mKn(H z-$|5fxBqhTZ5-0yhzX`JZ9 zN9EHh(p8CeIO?+Tx?F5OKdGqy>m3>HS(#p^BB%M%A1xk9&(2C7SlloEOl@=T8d|W1 zgx9K~>_=hbD<4nxX9tX)7jY1cdhyU9;bYH~cQt_9qe?5+?YHysv1JHTce}fc`_ewS zD4rni5vePVR~R|+n($~tc-e8HRhCDas(M(g@6C+y3_1S`cPeAT%~}(0zwJ}X-hemy zx@4+caPAdO&>RFkAV0Anu_--X`fl7y-0bj(8Bf2J5~ zHbd6}FSXPDyU=rTG4Xxym)IEY7Ov>5T3HolcA4RKp%b98Y|f#tyC7&2Gzeshv_1Jy z!@WXxkLVR}9RBYEM1FQ7MiPQSGW2<(lf+m7WgzQGB5VI88(vyA_BF1llJ;B%c$bDO z3Vb<(Yd=;hiMPvqCG+!-{{UgdTKwh~{244gDdY@}in9qCo-EH?0or%4ML`?OXo7Z? z)m?w1x2|Q@2#U!$EF+@I58+0*VaZ+HxWc`VY5;;kavfmWwMEYQyApZ8Anken6XJGH6ww~ z>6&NVCs3f#g4z|n$3bhJibK%MvkG8C=%f!|Y=m(;Z?xhT@Y}u%DJ1|=-%X4l&hY2A zQDF&xa%&MdDV`MGh^y)(;%Wd!h@Kk9)>>Vt_e4Ucj`nmnE034I%wa=24*@Z^`GDCb zJ!nffh)`wdJ^D5@UWrG00aXE&V-HbQYi51!K%u@S5F)(F;#u{xc#&)v2eel2eVk<( z@I-jgb9`KH9R)|jRXmZwzLQGgJ=}#GNGD8AHyZjt!M+{nrscnj&oHxDdG>SSGcFxT z2$Qko07wCe-1s*nnac#gpVsx{8aLowf?VJFh=aHvix3@sfnXS+0ghl&lCx$Iff^M2 zfPCOnBLZ{*7y|$YE0_gFg+qNIK7|*cpUR`Bm(&NNMZcz>kc;88WDP?)JCVEsXaCCxB{v>CV-b7N~UzM6B<Gdk%aGT;PpUL$0%2SS|ov+Cw&j7W*4hYM_?AS#$;wm+1hu+zBWXR_)Rm zUlh<_f`kqiwRqRr7DOz^M+VmV4r(5DXLU@2gzVj1syUXwAD+8U`Y^7Ri}D*95xHhf zAKj{!lu|N3`_)AW!<>RkDy@AfcG-;s{rFK|{<7CoT0O-U{tHP>csrTXZD07GO@j2r z%@a>_m91mx2Y{D5uZrFuztxwD+5j1-2Im7$N7 zq3gM+(ROZ?MqEh2GUdP@37 zA$n2+I1K{9eD^G;{&ZmFL#5b~jUv(eHJk3=IaiGt5Rwev^2?J)_i@XOsIlDlZaxF%0cnr6 zbllNethUj3*6yTt@5chGwAn{@zlxN!v4WWeE$wKx9YyX3Bz|O z{Q+sZX1(+M8L-&P26=#=Gqnm)zQazQLtDoUqhl%d=eIr&wYHR!y71fQ-i4t-78Lrr+F9W`vb!)?9V{)do4|=q1Sh3|++0oRefj7z~WhhC|Q?_oi zBxefVN|hX0S`;a6H<2;V9#XMYP8?8r^oTb~v@DY;Or_@7rx< zUcG*zuqX0;kACarrbbkCMs$I1&#O+Zo{L+ma%zm{x83^-_w{W#eoO7`4y_wbIjEMd zRpU%~mrgg|0hI|k@2q5#4eL4g1Xyf#km;A`_}(DTY%hL9qGdDHG4NS^8sj&)mxlYq zcbww8=7Uhsxo023n!a@Pm9tA#CP-u_-E0<#aMU;x(#tx3 zZ;TP=;7qIlHu_-}Uu?X~O8L9cN;EWtVzT}VlY{>)j`{a2#a~rhKQT*L*S|3b{PY5R z7y5rQ1LP;OL)%U=aUTu&QQ^KZV#L>&*V)T5&fVNyVsW^#MpJp`yYSTX(KiNvl$N6a;Ij+YHam@B<@C;Z}`n3MWC+`JU z&2X!Y);ve=#se<2x$NageQJy_Tzp4C@3!{rqlkms7CJ4{Jb3f+VeS|H zH#uh2y8ykY4(V~Grs0+~=5L#RIkN7$#;vlY5eKiF^W;AY8hZBZc}3mH-khjYk4CYp z#TtxGoG{kW(={+$IdnHZIy&yOtnPY+O;?1!232lLdNN=V-`%d~WpV-bxs!$lXyulz z@FXC@25rm=#G6D{;JZq zQX(ndr%}$BwnqVz5mVfwAHBq(xYAsP}bCs)QLd@%kn+wCw z%FnwB^KvSmuJ(Jm`26KGZV|tmg?1(S2iQM;<;YwXv(zWDvf|NKL-9)+Gc+#V+S9CG znO(h$G_A8!VeWBlvfQ`4ePVN#F?lP1qrmVlCw8ZXg)!SdS z7yPQLz2NLMrN!@t$ULoa)@=Wj&8w38sS1vhLFz$vNgY&|*9LMWdK={@GFq0tlT>=3 zt*Na~%6q5R((3$l?}CAF6H=?$FK*AhtbUh@rt5;@cN~1>tS^u5;X8Cl~&Ju91Oa=9sI{96&wjfDNbuccCwXZ8$OIeni z^VWWExY(}~*J4qt7k3|6v4tpWoTJ_^awfkYh>CuSnqz+0sqEFw--T93iWxta+c78~ zwn)uyoIAFQGU}IGB3fV>n3++~wy^wJQdofeNattFs-83I4>R-)71U1&t#B!QTpYB@ z=j`6S|-; zB=6u;Pq<3iNnpB+4`&5=MyixcU6+1+cJ+>|jbAb})Jj&skkH<)x8##{1?~n6-(SLS zp57K6YClHTu*DhDE+hrChQ>-p5d5ccf9F0qHgt*b?fVm@0l zAasxzX)}#d9{0O+#HpR`w&%&@=*k7C$g2&(jM=QoteoAsJ${5kjN`tyUYcJpU>^SE z$@7PIc1RT8TAXAViFu{{iPS=&;ELAs3y$yFsTx|Ub0r}DG!Ot$#i$z05w-&r9~hv< zP!+Kl$f$2V^>KTU`Y!ad@sIuiDdbZD)9&omqn|5R?IsCi42=qihO2${uM1E3axO8Q zLb)RBn3&ie5ZH76dGgYO?=Z%)@0ksK_p-I76e*-Pi8Y=wO|>J%>+TXgGoP$qTDzuV zNyfQ*Lc7i0rinbqwgUfve!O?=3ni*-(ur8G@?n_YMcE~u?pNk_zK_c#Tf{`Fm`mh; z{brnD?&W{1j8fgdSAbhCsn%~ghWBDF zs5{MXIJ#s1dY2=_B`fx9;Oo6v#;u-u;=-c{@3!13=63OD12kSm9(ujMZn4K9%=~(M znJcbTwe2>xl+`8b!F+UCUBvxrrj-7Ru=lNrepfE{n-YucE?O8Q%3dA$B=|{oRnL)K z9xZZUVk-aL#FS0^-%!xu{;HsZe*Q7s`@sGMAiG9Yv1V znn9^yY^eH`%Y7mFVlM^YgwunL{!h56Ol{^T7`rW%c_T;^RLvy!??Q&2--R5NW~?>u z7C)L35B>!=4sltQ>jQh~SdD#*4=_$NyigTA3SiNoJX3g>-ns2~IO#opmdzsblRZh? zZ08_+>EA_ko5n~#M07b4pau&8pm-`2Fvlba=SW~?dC}V}fwGxI_=`RuQH(sLZEXcy zo+c$>Un!tJ469?30UXvQ0B7J%K`b&6JWe=pX29rxU1?7UjAP}1$7Jty_y&AELtRS| zJ5w2R8(_&Fc#(kM#e5q9X^5CxW(_8s{w!Xjb)v{Y-~fqk&;t3?q)zZ^F)w%u9vXTG z$-8(Li0DSukW#8-FkvwVQRwtp^Xq2|eY<}+VLD!lE}S{ zv?UOB{L`s~waokh7UB6500glNSMU+67&ZPoR>UA!5u_voX#lKikC+VNX=5mn7>XyL zADGnyuR)VIhxx$ZH?F1u2Bq3L#O@BFF&dCxsskNZ+y|KTR49U_f z;OoL8v~+Sb3+Bc~k+|d%5ls}u2cAt8K<;;;O{`$NYvFa!=)t7`Z6FiDkl|G7Q$@i# zZvwY4gSGV%;C-JzFk}N@$O}B~8t-C69yd!!DxGmai6E>bQwES^NOig)17vHEQ9Y-s zgJ^^RxT+AByZ7DzQ2PZabJV%O=VB#@|4@G5e!DL%l z62SjD{euvTLN{d1N~J7|AoUTy3+<&MsybW}JiAt}EjeX?nw$yGcNYuM_5drRdm$Hl z{`4%%EqsiJH;Sdf+s6YV3UB{yd&_qrH{b~U=6wrHCk@;zB?#9CxnD3oy+*;WdHR(~ z#KHw8XPNo3=M{SF^ww=pto*oGwfO3cd=Y(BmG82*%o> zsm6~e?tRj^(ROls`+d(jty^@rS?%?2)9JYfd-p6tTb#UJ+tPK?=W`j}Z)%3NkV@UK zyNxqquO*p2`B1&!*{9>L>kC}6E5}kDt-cE#x}$-&StfKm)!2PR7VYa-(7yk$rT>#i z>)&n|hes}n;JrHl7bZ#iykzJ6`!P>T2VcJ_HuR+^sc>7aMk=jr4{1E3ap~&Y+pQin z+r40vgZq3Xy1Z*6KhC$F`Xes9bjC;YSX&xyaTPY8vYC$?SzDS?kku&9u@#8b#{wI? z8JdeV+t9rssZ=x~PaCk#cG8lzbB3VbIRaRE7qFUmVh6Z!jpDRbR+Kq^9}%7;nMxhAV}cLoY@$ zf^gtG_2#a+)MFo7q0hL!4S%B8-eUcSqYtia#idsC|AwDDsFlz$ncWpve(~DyogF6k zFtHoAlBdthXUYbReMs)rWAnx-6mt3mrm*bw|)wRFyu34UWdnIt|P{RWxTqbI}IwI)c|A@BJx9z!R=v*_Z{}efv1Lr`JrX#;xE;-g+(iP~uhDsjP#Uy8VoSGN1N<^RyR&sdnM*ALL%Y zP`95wk-MsIVPMmy!+yR2YvVdYOG+gCeE(>*CkN86DWu*!Ahbs4?7Ti<4ELx@zu&7N zO016X%9=-=Yu{MUUn>>2d);Wh(}{+)1n$=K?nJNm$vgaI8amIsJMX-?|5L+yg)ihS zcc101TmD4IV<9F+SL0o2>!s$3fY0g);>4V5=6$mAhxDzIHCk`J2$%c1Jig!=tu*vH zZ6`jTDbf*I5z^jz*Tri4>O;|~`YoT#@285j9b*{hC0GQ^}T_e@||vF z`yb__Z+M(WZ9cI&;H!hC2kvP=n)hJv#j=5#{`@o4s`>(hr6Ma;GQAI7wLjp$Y3tOm z<0$bN^(SKc!*G3SGw(z3gdW8cWUU)FtGoGDWxJ+| z*O|`5XuE|WZ=NwruRl@llAJg+$gW_gVt(Fm-5*J90R=1>T1smmKHeFjY{ zrdon~R=SmsEww1N&I>P&voK6*kug5Texec)sE`{Tw&8KW>Vq3@EEzDqK@C88UMTIr zC97Kw6AS8Dht?Zxn-?j|UvqQK-H3CWo~@|}4#Jg6(KWGO)=yFW#!nS)&mBD$RSDd>=(OxVb?T!;sg5}{`h$6SmOn1O?WozGP=@rw4i|y&+cu zJ*?f`qD(5axo7mnwad0A8wM&r9rS&Vw50*p##?xGxAEahVL!>pV1n$9jHODT14kSu3B%WWjETv zu$un>8^V*eIWNy!`0Be*vOkVy#tKu$xlkRU>3HT@p`a634%9^a@73@>Dan4sJ^WSD zD)V2n^?PHv8Cf!gPzL*u5sM^J4x@sGPhmZ@`1Lo2MlWv#ULf`|u02!=i1kIhzZJuP z`fAyKRKwX!4(i#D5-F?jnI}!$Zcb&xb*ONhKop zdcgZl$2lCn?{gLSDr_yf0TfsfjGGxS&>%V|lI^!yAMCA|ii6u)L5-#pz z03`u_6A&%8db!6xABB+~V!#2|XF(hRtASdK6aYkciFVTEAbTpdjl~zRgM8 z`-1tPoC<`BIarf^b*NHHHeC;1`)-C?$ufb4=0kxx;^l|c;PI7vP4(EgAL?It`9W-s zVG8O*?(NK((}CeINhMe3tR@%0s*d0TVjBpej6ko=0kt>qD9G#+geD=w@RT*(bqvzH zAG8U%ldM<36Gnb>5Wa1098nfvTTK%v?w~2-nSz?m8|wxX3y)jKo`Hd@bxV;08TDlq zXz0{*KxuWCP6Li5i@gP^R22-*Q*E!!ZET!`F`K!2__BS78AL0bN14Tf8RmzVe zLP>DKZVrr)nG%JGv4aG*_$=TJjq9mO0;iHli?UBN%~!7%CB1j)xaFC!pi_Y*az2@Q zf`f}Cf6#`mwNcR83ptngoecGUf-cr%&q=hsx=#)C@H59-&hQIdsyLC&ANE^xpL^n{ zV*fGEQB3RE(ut8&QK0p+z;w2p^M=|Vlxw`U$+9=dK**xB<;^Pb)qRmucFZrD8VY*f zmOd%Y@~@?b_nhk-W#+tJ^F)XFu^ktIXEPdY3RQQ8x}EM~XX=WV6ot2mKC-;XAof{w z<5Wg!P5{nj=h%$J!-j}P zYaIPkqXm{IgwIG8h#|^HSXBr?TIWey3u_-Kb$P{etOnG&Oc_@FhfKA(slZzF`k5)j zW`+#1sV@`&*%1UR21H=A4xjPY^w0uTS8p@a<5;*i!yi^0zeD&eU9g)S|E43&!*5GV zTB1*OL)yH^-NKNSl%c-}VofxwWT@7mVZ}k{eVframCt#!7B#pBJDyNfRWG&d!-oV? z*7^slZ);aFm{vQl&D=Wl6lE{So}YGAV71>EZRvh*w{xayfUdP9Eoru3-I_aKZOG!1 z-vqIqv>YBhAGq%mfYIKwR7OnJ3(;}Mfknm4kl27TPtDyXt&AIJJ9=*uYKKBbN8V%V zsq~_rX4Z0_wq#Ca2i#=!vy;uTYyk8hq;PnW_iIEjMJJJwk9sG*zXdFIdVid#Na_mQ zo>4ds7QjtVzWP5r;{X3sL;nZ$Z1q1Z5m3tV5Ld*%Z>P{YPsVuTKDUp$^EAA`Q<;qm zSW^96Xi6s!8V7LeOG|rKQ*1bXTvguWJBUPVc~;v-)(O4?Npj2EyUP@P6#^{QPAe8< zM}2-((Vpg2k2wuENI2=P5BeMSqgIQ>C(kc?r{ou#n7U_I))1TDJb?|V*pL7nT z%iY=AFHthF*7{8~EdSGM(0EUJ5o>@Pbs@}Pg~#x(vg?l*pllDF)q75p2%f$Cfs4vD zZavg)<6T57=+${9Q5bmn_H~`hPw`p>%UPk)m$v`Q^L(i2yU=f18KFVEU%I4v*6o+C zV#s@qj=ftw8Sa=(xh}!ARPO7YkxWUnugSbVC7eUfqg0!5L%APm zgkk-PFs;-3W~49MO-pbKrw_y3{<-AMEz6Ae0d8A-<)R}U*XhYUeUd8^6hg2EUHyIM(V;u?T_BJ+%xXIlzH;Sb<4_U zUT?=8j%?&#Vf##Xq48KX4K>b`v^1u_rYN!9X1|tVf4%zxcS@|isOgr{WlZ&3NwX`? z`W8y;Zd6?`J-TXKH>>&5qG>ltBWLw%33!h?cLjl0lFaH@AKO+v(xN?`CMwZn9g7|> z+)i~XQ#0o0*=O_w|FxTXxucK3HnaOK1ZVkVLrZl_HhN}yCwd@`%r_5CwdtU?9Qb=D z@^49A$PZq>69l5z&M3Z!W>eWJrgsOaO|=#Gu8DaP_twIl6A~iG$NM*^GHaQH2}ad2 z{1}zL`@7JRKTB`Ie}Y=B8tej@@UPz;13#Op|1Cc z>&HkWI|mA%43N!3<4vJAU4B|HO)l|vkTjDL$n!u_Oi$29`l|Gh!Opb0L`_@gU~r?7 z;N(}i1;IfqDjnR?&ca3%5X^$&MXJ2f4=NzYfjWLI{6`KH-1m>1H?qGAU6lD!^oJjL zKlqV5Ndjm2IX`kBZSMoTSuBl?-4zPiFeLOScGSBVt-wG8IJ+5l@aRcQ@UZt88Qbp2!KfV-iy8rnD3bAvT?oh_&NdPFr1 zVv43N4rzNP*Ro06UZkTM3?uWV1r$CJ`k9)<8c`z~kgPy*RVR7rOprTBbNH=b8E7;` zJO|CCe8gq&0U~`-WB5T@E&PoZ^jd>)J!PZ&pkkc!DZ_p~eG|mC$ix{x@v?pqSoA+L zpp1WHKnbw-0&T#qjp5SSk|cOYgUVKB0RBk<{rQ^`d6T{#=294qxrN(ADCI zqGf`k4gyEwtZ70fj{cN3Ymcz zsG0Dlxl|Me)J$MvzCt@wJFq|61z#mye(cS4 zQCHpjO?{RozuY?f82@=T{RL_4RPdJ~RaQ!|q!x4hs>KVrd~NdT{M*^6F*rQs5AEY) zID)>i9BRgc;H9>v%O>5^qdeI9%55obJC61drO%`q3d*iTqwBjSAb2yna4{A?v=%R9Epu-yrR5r6Dq8(E zC)d7LsmuA08JOD(Ti5pS#k5i}#ytV91pvzr(Ft@mp_%E8cw<41!h@nYX95XdKz3G; zoX|7o@`Cn*TR#3(_;OfsOLw3XT=`XnVc3| z`YExAd7tt!UBB$(n!mkS&j8fnHoeE5q&G1qIWH+!2ev-R0=ky3HCLh9ok zxR=8aaXPA5UN-gF)FH26Dj*d1W+Q4EvJFsux2fKCqRdc22U(RI zr?f|tC1pepg&WQ55*89^O5V@#Z&w};!&Q`$gU75?2nCeSsR|a&hj@uHYk6;-!n0xJ zkCoKq^6QJfT-;Z4F?w*%i(1d+&^uUbw{6gx*v+aQFFRgL|K~orykGFHg+fi-Ji zq&-RL&`}tOtNWO#+<%{(^<>M1xNS;o3w>Zp>ig1C8m^Sxc6zdT2A?#4n4YQN^c??) zHg?_hapvCHU8vB?d%^Y32op0qc}^cs*_G+cm>hgSX6-30Z8=%qZ{?WArRbNv>q_3xtKzp%YOYpnEaTzrVY zg8W@b2k+y4gCD1=$TVc4CVa3_gb9gQ!Sik?Fzmbb)bMk$Nj%L<*Lt~rKj`ZFV`Y#3 z5FG#Mv5}-Oz<@#2oS)Gz)Ls7zeK`@NIR{O-EP&T~(?6g%k>vec4Gz4e=-vUUupoUO z#SGWB~1d@6_?n5w?I*yXi6LV*^u*$+Vj;MPID1tp$il)?oz_-)}f!;VT5Mis?gZvPv zP;%gxzD7}ZpGHln z*n)X#a}9~vmJ;s*@QXpnOv#Kr)Dbj#mlcxzf^UH19R;(Abtgq&JbHO&u?-6PQ{ngQ zzk!31Rd)jnpL5JzFeJn%_}oUK{E#ZkWGtK1Ti%AAy*NhVH|Tt1EpQ`D85aTYeT^gI zjWk<$QEuot?iznYua|>DoSJ1=U0iKRIDRMR9+?J3Y9Ol^dT?{f-au$~LNE-p=PU)= z-JzR_&zKc~W?LxVy%w2YJUyZuj;5lX4FZ4L+<6H19D?CFe6$v#d`6mB7#dQfU1o?Q z`tT2Pvgg}FH<1}h_`zl0g>J>k3&yu&Kk*)dp{Wf$06S55(&6e!(cBkRU6q=O_^LQt zEfyqYszJ~wh^V2Kin6w{bBFTSUKDujhAtjQIRt1*=xRXKhj8p`-W0!wP@b)`jGGXN zs>QF1IwNdmNiF*_CxD*wcq;0ArA)E}NS0o{h#n8!IT4J##r~%{3pedbdS5CX(#zAF ztFiDsY~h!|R6br|?_nRkt*ocn^e+%h%w>n$1Q%DhaL);_c< z=rNZwQ}REet7OA$f8czgTuxt#yYc$GSsu40%eCjXsly$K^USJorRu-&YIK9U3VZ4O zpNd(bkK|HZRox!C$(ApT;?A=WeW*;*u+E*Um!6h7dp1?y&S0v! zf!{Gm7@69QYUo-W6e4@{OGzkNY$tm2X(QehS|JDmh9VX1iab~5O~|>|WNxwN)s7AY z;?9o0)}kiU5m3`vtakmC3$!vk*J2Pu; zw`e_xGNcxt0ZJJfs-`Hj+7j=aeREP`m;k{AMtMk<{bU6vtrShW3NdqDLbJn?fUvaC$p0_agzRp3{`9tQ*rGl=vt~;yu`SuWQgXkD79)(+z ziSAR;%BqJpos|lp-&c9u-PRfOjukB$#Xpa`zf?W<7I=R>&0Eb*Sa{4}k9=CmFFNb5 zjaZA6rN&DT8K$Rg1sj4k=H2gM>BU$m>oCMbKfPS4H?Tx_Y(zHTC6U`0YOb4AgjOS^Ptbs!47V? z-E)n$(GSI@Gbs;bWrtBT8>)@{>M*^JKFqpoa<_}GkxB8{8>Y?old}#AlSyoXl{^qY z&Y8F_KP)Pbg6BOLgrfk|CDNJ;uyBErj6TD#$&?P<*h)7dECgHd>KLOT{6-TFvXa}S zQ`M2^e%nw!Y~^H(ja=7T*bx2_8WCbO?_ZS<|6=w1=b;hp#6O2d$p4;2_s7y6{1*@Y zb7lNn9o@VCfsW2v)00&eFAZM^(jI6U4l_p`!Z`%Sz7tOa)lqX53X1un5(2G*{uW0E z+Z6R5b;8P&a1-m zv_3D^+_R0AURF(C?98WkSCPiCF5H0x6ws zU8Ij27oi6q!1*2yTE@;jTHnHI|D5!lM28@{Wa#t^%q4x}XPEcAZCx8L4D#I>c&IUU zauCmy4L*xA*jcPed?$U_J*AgVf`Y@{!bgk@B?^`wz`_v|C~osX90hdIBs?#JI1k|s zFQdEQlft?VBcvfn*2t*d@!tNrv4TK&Py)1Bkl&0kvJA&|I6(hM_J<8C{SOJ9{FEv0 z0c?g(k_7wWq~t%S?fAgQQG(XY6a(R>+5+5T7e^TnWFfS^o=?riNI-D+d$)fNXz1#7{51xF}>HUB;|t#~{X z-nPsI`b{7fJ5KuMmZ$~SERxEjxKCt35)Q1sv*dc%7H-~owA zMzJH<4jKFgNJ8fl33|SKC;s#a+?SIqdBOU;azK;b@zbFZ=>B7nQ-95;(k6&BJU)%$ zu{v<%T3xSJQZg|kp$zPKZTr2mRAGdWS3W>PhTBmu`jUX}LIP7mvcOq&R@kbVn={zj zbq2i30JGAjX7&@g^q2e_dghYu6yCx%Z20Q(mlEiY4ung#jR8SH$ta?XzZQx1U@?V6I$eC6YUu6my$ z>FKvZ3{|vO@?z8TMzpSqkGIka`3IlVKK63>dWFti7axuJ8iz02t~l_?2sts&qNrty zTnRC|^xo%MJ?ENlkVTJSIB88)Tyj|v=}$-fKYCH#w#n>SgFMb|VY=np0L)F^+Ajbv7K zvB{2Y_kE;Fs?82Cl)l_vq#SpOHjogJqLSZ~f2*&lsj)G#x$)R^USb4VW160^!4aJA z%nS$728#+8^w&C5e*XdJ4eO{@YB*oe((~TCdy9o{`nX8Z?PK2_;`#i%u;i-(;_I4m zPv=}1onj-hc3ph2Q5afF`mli26;{%g>0Ek#mu$Q0D(w$Yk{@m66L$PQuf$<)UP+nN z6y~QhoYq&{s`$U2mFw`AtlS$6SqfJ9Utaw`bbG&ZhSga~coQWRWVjW7(F*W|XuiXljL=q`@^Sj8O+{L-<^A<7> zVZXbIXkZbIKN->Z`+>$khro>&{3Y2ct4sAy$yVAVDvFimi80H7%-hc5xkM{)3^&h* z%?8j9#98eWP&$kEgtkDWDvPu$Y-0wPz{f~E1R5y+vmvbtibx3_7CY)W)C_=pkUuyn zpmx&g@}$o~f5JUTe5mW6bW51btDsvV{nRbZkI1Ph@#8gPCK$&DI~dKb@-on!hyFBF zBg8>yf>29f1MCM{sqCKYT$$0mk0yqcI&&db!+L(^*#O>lk1%9ZEiUYmhf2~^f>5X@C>*ko0Ukdxt&pf(_~=1n4~O3LP!$Re zQbe*9;By0bJQ!61tdtQFA{;y?`8PzG{-fTupx>v0eqTW1CttE*l!@AYL8=f_uFrR& z`92$`Bze)byauEQv4UC=O%e6X9tj|_kq_gC7-|aMi!v@_E*iHQQ7kp^&`CVKl5kC# z1KW=S^+bP}F-~>Y^9b-sN7sy8c*!>E5X;@ZR=Kb$;=rbA(}H9t@x_8v8FH5!*Kcb~ zr0?J_QMVPjpSIh4c}NQj=DhzJMEa~>nb=j;I^&fb?7g2obBZ6Pc8AlJ+nsUbH1F(i zn^C?$^K)L!h=@*Ie`<=kfh1@3w_stJiRzC2?X^Ky7#C~DZfTYHv5X=NMimvsRTBM# zc(>maqDI)p2?|IFMm_FN%3i~uZ5aczO1FSJg>Cir5k6Lw>AC;+rU=T(^}7%eGgHpf z+*XDj&m0su8h}?{(}WxJSPOf$5hrRED^Sp+W(ki@k||W>j-w$W`ZP)xKM;OK zOZ1h;{VM$=vRnGYLkF;%r249F^tE9b_rI`sVqnayxD{RBAIPqT|U7yI2(p9;f zdsv7UT8Tm3A78>sxy^5n*CV5I-zCjrthxpLv8YLm2TNWjrp?Y|YL8V-oL-9fJwl%G zosrL!j@4@8pB*3>i;sw~7`F*Phh0V|l^DZ6?(xyRxCR=TcL=_z1`8nzl_<=^+8%l~7iCZ_qH-CWH|rK^I9i#e@<&wxk9$oOT>+ z62axZ!3|zVv7tSjZO!f!5N)QWf#3Kpw_VYZg586;RF_FYKNos$5hfDfJNhv!W|wSY!3 zmr+U0bb&Rl7d6VD|6g8N*4!(D0w~$0g!xnksu)+HVY3Qz=UZ@msoL>43+E$GOkhZ0BwPW_Zn!pR{!LaE z1L~I;_t_S%bdX>PT(!dlPR4hkgNzgCFCo2meN-#M@I~PR50sjuD{g+s*h=Q-IVnI= z>GM|sK1A8~zhp@k3E~H-B`qp(tS9a}HN@6fo@{C|zGJ_7{+dtFAv%OEvFy6Qn%`B^ za86=V>z2Ab#cvD`4HxH~5PBw1doU$a>MRjlHbu|;CK8eb5MiULJK6QqqmEdN)U9g6 zr{&*;7G*yFLN?zlbs*osd^L@!^uFhi_e`8`&W7taTfw>h5|NA9RwR#Iso`=97q3W$ z85y=mb}uky`m7Ejj)^LAD{?JeN_Y*H8R=b08Vl#&sy~s^oLQ{DzrtyrZ~_2xk?S2c z)9)E%zJ3RRZ!;<;$nD4#2#SC)zzgzygm7-*=&r??P~U znU9;pyGb2buFI2aufh32A4uwxR5k>lZNNqFG6!jaBl=f;Lgh zQ2+WSykFvA7~Fim1k>SUgR4k>A_bd7^s;pKI4YyAta5pEK*x?kg-^*_Qqw&m7oWGg z8Fl5YRFD(ue9^(3Jq_5M9@A}VpVm4qRN1~rd}*kWQF(2x^vW#OWv&4~uub!AtY=4J zX{+1DBH|+bLoO4?a-T))P&h)p+=F@A5l4WgPF1b4Pm%o;jmMn-`v&G=S(cf$jew=@5-QDnv zqXN`)KZ`fn3BAYo9koD!azjYpoSD7#g90zySCBdJo*0i$!u8%s6?nl~wFspD{1fdz z{)EL_5!}IntNq2DBbkN!^iqqCnz_^o)0s8UjHE1Fx!`gc{IYry3 zfN^~1LN1*{JkWPR}1Som!}3_NWp0Pvb7WjuqUbQKuX+C1n13 zB92`v%6A-I+X@?mRKMSOhJZZ^!#bs4DtWNJ6jX7+kdAy1%n?7Vm0$)hGC zul*A}UPfIp92+G&a7mXIeJZB7ON8!^Zq|J`|Hu)VPKv>5@dP198^z-{-aO{F1izay zRds#ZZ5vcnqt)cIu)}dj-I{iNIr9_y#C|cgxOQMuUec+GaSvJ|e=YT9erOomc5-^h z4En>1_ssal|HIvz$2D=T@55MoN;gfdwNw$(ij}HWv@R$DqqT}lm0B09fDw0!f~bfR zVd_>~i91y)Q4w(g;|_u_Dk>@>vIuB^$i4&;AS9DzX8c_f)M`(A+VefP`mYe(8;*Yxg6>xp+w$HqN*?}^tJ z0bkFZBZzFDFQoS;I;LIIgq5Dx_gitPWTeo3;-s!yCbjF5xqX_)rjU}UtOI<>5Nxn; zy*=&8n_6xNP2O~s>#a=tb9Bk`9#uBO>3LXD6^aokMUhhx1FN@GtPV}?eLUH;x@MD~ zMp;eruCTz3n=5=2O6GFX4KeADD!6??(@)0DIMX%ON!@03Yq)bDR5+xPXFdasIRJvZ zHh!;JUA1nU8$*ZVOQ9TZrJxEwK*P8r6M%VN&n(`g*&bwlBKscPHE0;6LPmp53=wvV z*J#MtD4Hpq6U}ta;C2vNPyU-WfaR_haBKMAq{uT4ObQ85xJapJau*s0V-uJ+LRLW7}Pa=)&p}0@*~FY4*7c&62TOx-}3JdK^^@ zT(O|rnCxvOQSux2XBIbe5|fKJ*AP;4rR4l1@*Hr*fI{NcP^R>GC_^-8MgNUZCWArZ zb(?&Q4>v$!96>%38m(oog?22LNWP5h$ZI!<+Qw%V)5u!?RPF)nQ}p{}O$B#dOdCru z$U2)@#71L3wSW7WMNA?)1)_7wv}r^Jw|XEl4vFa>YK1ZwQlvz)L>EFc@7r+^3auOW zGd7f3Xn2~zg%J%_6q%r4uHvzXfBjhVxbMjdEX2Qx>DmIP|8Yz=cUzq0-S87CK}ERV zq4WVU!$yzod+W1n*M9MyIKyVh7H8YZ(`H_}Vj&D(N*klC<~A__@BdinJ)~gbvLj`) z0_$7E+e7zE)2ZviQfhBg)}nA(#=@wlF;gd}I#2Qyxn3Y&Js@&yeprAnsAg=j0PY>N z@tZ$7M>LltZNVq#hI+4zyzWfa=7B*^)y_`k?qb!Wk$cogxf`ZJW4Y8Yme0Na@Fd~n z#*?P^@I5w@Ro2`PE(4}~y_nne#|OO4sI-N0FCXm8pBM`~|9Q6N0&3{bBfe`)k2a$s zF`87*f6UUTQo{nQ ztH@||LcLk|LCFUn)|JryzY}DqnUyG&)yf&6C+!E+i#os%wqPJ{RJ*3FU94t z!v&(P$)|c(O_&~E>I2=~h~rO<&N)^mlTEz@F0_)hS6a7npg?PGgx&M5NmGYg2s zBlQSRL^WUw(Ja-4cnV8y{47l+>Lb|>1%otmFc#RR(vGd|2W`38(PJlo53UrU>bwyS&scGe`46L)hCba*W1Zl0I+48;KAz{fu@0k?ZskD_Tsrjn=adqB=ALI7^O#%mQ673jRzF+E)72YV4^;?nbNl4o$@Z1KgZ;5BD*M2x$$&G2B|t zpTn_expiky2gBd;fna!hPCO4wb41HYYeMBl?)iBgd)9PGq=!Sdh9$uLD#`4nIMgy6 z>UmO}l}_e|^RrC8R#A(wYVbpw(rnggOEXxqOr*0a2`7Zl?L*En*V^5Fty130UsDM1 zz`x|PM9p+~S{J#ImC!=-bDcFso#uMLF2m8+k67#4o|}h*6)iKpqe_>ORSNS(O{QHU z{kAsqgok3ng5$XJ_@egk3ZfSmJv42q!?W@xEWSgt1)05=)D#fP8vYvM`Hjx5(2gV~ zwOw?gvH9(eWZEKRm-8^sKB*?#051Z|mUGovbDFcmGg15_?H(ay4LA_xM6sGyk{=9# z|D+LALDr-bohIm-Q`Mx*S>gAjy0l^VXgbn#uK8l9TfJ|dx2yfCgN1_=`sQ5hF2jda zrQgb{;Eo^kn4DHW<4UaW?6Z!Udk{G-M&x<~_yn0{I$P;(K=8I5t|jMc_n6TbRE-@N zlbE?-9>?V1Si92_O<2S5&fIK*Khyz&J`W|2I8lSvCe5=m`jYs2NdaL5)bqAg!b2F= z>6x?095T}6GACgFM)WjyCp3ti=CDP};XYqplOIvnR%kICBxWI#--aEun{weU@k^r8293VttSm5TCiX;7%R|X5M&h*t1!B~ z%8ti1+&)-pB&}MM?bn{^iGPbXP9QSaiL}oh(Eq}0Aivu% zx=IHT(!rqwp~@C>DdY`;Kb3(UPW(7c+cmA91zFKZ7#hue%)?dbhfZ@aH2l_!+5F`Y z!8SvXOW8!1?TNXZWro;@CYN=8Z8V%9@pu`4-B=KwAQ_<;4OW6fMIJkC#D+gQ#!6B)aDmS&+>q~zx^7N;>Nd2OHI z`iiFVy&1BxO^sB3nW@4cB%L`cN`FUwDPeL}Wm6*k!v)w8HzuzNlr;^dE;pLH~Yf}e>K{AmuSE{pN1alqL|nJ=xm8% z>{?@~i(NsH|K*sXqz-q-Y&damyxZiK~5!^UKaR zlIPXjlaOuGnTLt7-b2Rp)y^oKcJk+$HhYNu`5(?7c+T_Ym|OZJdcJPr{2l2DmD)Eu zZDyz^t(8=%jcUn5m#a~|3XhLjFxV<6=G|`O_D-|9&uMM%cz?+`=Otc<3`CCKlX^wb zVKMIkdw&>q3$hVY2AB$0{MaP#M=VijFPyQgw#BEqFNhEtx}8GIL?YnxlnZD^dXCJ> z%cL(>;|%ThmNrIlmxHb`*Y67r>j!QCrD%vqTfx5<9iWMJFQTgJw5F03A+TWmvvt_x zqqNr;ioZBeYS81xGFxOqDI{}jyvd3wai-RG448rl_cTGn9@M%f2_p~eX?=`#8WVo6 zP%5@nEJgj>0OMa>S7oYL@e`h6lGKzB`kBznJ@aY~j)j929K|e{7O&JIF_}nG*thT~ z4_%yH4ZoHXRl62(T7tDKY~NBbl&tP>i>%3&ajD3)P?1#E;nuB!$ufo8uX_t=m&oV0 z7Gy3_FwIFa#=t)ZCFTw<#kC}Vt-B<8v>;xPh3SS{ z;+e^bW>axEBq+@EYxNcDA(5tH^Fx!5FFb(L5^ll&>|4ZkRg?KPi7e~DEaKMH<FGdUF|UVo|L{Dxxu5NxS-5tQwl1Q`?=CCoR;pQQw2bpmXFWiW@a4p|tNX8; z{h;A~+@k6e%ME>o4OB+lyuLa1=<$QThamp75^Dlhhx|PZ+id_7ppU!Wp z?~;jc+}iTvv^_eDfmH=grdukNN$ogj^!=2Ef$|}#7gwFT_0IBb-Iu6mx7@ric>BzX zJ5z1mijyu({f7O4y3wyX%Ff6C%Flymq|IA-!q@fbts{X+ch>jc)=7J4Gtn$tCQF`S zxw5$59EW3LtR3G)BO$(9{Jb+yVDk!-noaW>BL^zpb2t^6x#Ao9n>nNW{JKt=(CK#7 z4l*FpZ5+K1#S5ID)6&-Pq!eTPFg=xd=4f2$;jLt{#EgLlZKosInO~Aa6ELGMN3D1i zpbzE^)qXenl&hy3I|HGl(`|7E7cVrXXo0%9sEzT20*j{$K@M|KVwlfoO`XqJUKKF4 zZd{Op+e}mSNoEY#K^HPj8lp+3iMIPxaK94u>1~gL2x~h0f+CZRjz+$B4R%t>Lni?5 zhmnt9nLUU)K^S*hK+`RJDTlm1hpfeBL4r9s^_BZjXwS42Iax28&Cm zg`IemZ5&-nol-QZtIQRgSAJ+AuCcrx@KmT$!k<1No<=va9vQk)fR)*ko>^S?TI(&k z!klCivswH9#>A42Yq4L?hpF9}(TAcy=A9mVzCU8GeT(2HqCF+Xi>zC;ip)DvO&X`E z2wk}2ti$4T*Q7~*i{Q}4@bO-RBXd6%%$7lCg(jK%YWlvg#VZ8{REAComlcl1GUICN zY)0qKOB)_>d`ygtIO%85_=tKp&2p;jIJQ_7k#_%X%-CJslZr3DX$V?zT$^cJ^C+&F zTw_i9gxZ#Q^=4)a5*QQw$-9LUiR3-YJ%y=*W?dpOhWhEp_}v`u=i0kwoS^&nX)Bcz zdAgl_=~~;g{chf3`p<;0(3|{9_shRvnDX4?+A8MFTjWQEQRi%q_|CmG#Xmkic4QB` zw;rEbAMMdg_lB>X6?aVB-X!Te`fhOi&l@)vw)oEbp73#*7hDRHQHv2e(}wO(63-0J zo__z^Yvjcl#2lqxHa?8TsY$4dFD6WJk)s~~h@WgUG{@rTI!c0!* zoB5VQF@1IANvGRT1XPL@*|B$_oPrjMRP-O3r}?O5XemznvUO~jKY1(Mha-y9{Ll#b zl(sXi;VNN-kBOS1&qu0YS3jQwJ)_ZJaD<&ct5Hoi1pU&tu)VsZ4?lJZVwhjfhVG9| zpV=<+AnEa_h5zkP#5S}#aspqe2lpR+oxI+8xP!5scOFl z0W%yYq;|rACYfb!{yswcOFrdWeJ|skgKcc&<_;Tv5ORzBl(<2tM__OX$k&-- zX(1OpNGu&n8G3o0+PY6l3tK}481qoWtOhl9qnF!E&pJ?e z(3q~>h*nX)0Z6s|D2T44J18Y+tU{8(%dIqlX@VvsT2Y3M=T9&bPff|7?+HO1%#r}R z1QXTJRLcKdh_m7oqT*H-4DDl&XBNpJ4uMi9^nMeDV^lL;Tb~#6p`uyTr0Y~WI>0=1 zx-(Qk`3VV`Cu9bIr?`ha05g^onE**#AzIv_iP;4ztEQx~oW{gm^?i#JERE%H<)^DD z8rilfbB-7v2ffS$<90=qMwK28=^!Tr6Hvj_Z@?XuVeJnKDhX!wcmz?!x)Iz(_lBwW zL@m>aI%~%6Xf&d&-JjwsZ{gmm-6mZgFy$ipj%dXOjGA~mDQJ_K)9H=HpMSmE;!XSgyOsX#19xSkckD{uu497CU7s@VS8#(p zxiIB>F10)M6!*RCGqSFoaNyIU`D;%d3ynFN(cqIm{f`e|8?Wy-hT-oyX0MVgpG&07 zCA%*U%Rb$#wU}Aia$sw@n{Ip1BI^^_9xhaoINb2Wr@!ty^2kw##?uI8N>*8`d@hDH z>b`!`vX?Cj4i41S1^S6hL*uF*)-~7_c=BD-b+eW!VXolXI+LL5x*iI|fW=JntVO6o zzVdXDEKa98St|*vr?#~y{|i#}f6IXZYx*yFuw{SOgKZXSTOLqRtrUcGHs` zAFUJ*vcJ?c&9$A!t}{0R?k^mB{@oSd-C39Q;dIZbG9y{79CNMxr;~@te(kBTda6ar$VQsA zeeo`ctTt>@Nuh>(DZBw;UIO?o*6-CMvK6izaNH;{!n;s4yPTy^c*&A7H4<(;ZWe@GRY1t5T36BwQVyJkuK59S@|m_;X=u4q1TA9^=yMq=Nt z@80_G>8763+8bRD^#VV?zrh80garOa+5xZlD7utOX^CXwZgE;J!;NT~V6ws5yf4&5 zm>*j=G0mOKj(I@Vqz52+K=R>jn8-~9UjhjpUpDF65X=r9Kt32DG3KG>`A@fJ+2AS% zgZnmC*;XHwol~?vL`XjjGq?Go_xzMfnlU=paBGM10PhSjtyS!$s$3mtU@|oGVOj>6 zH`PJ3hR(#F}chOEa| z#r6yHmmVDac=w#9#+@f_Pn$G#*S&?kPsQ%u`CWEzQTLC|_uRPd=1(GNAa#X#birTT zeTMb)-206K7QQ{cTNhFJ;JBN2Mmmo>@igRCK&mvg`=)H?J&7$fpQ|Q@es;BUR$2Vk zkB1%EH8OPZ;rcbxPQ1w=awdhHAypmplxX}RiKN{fu6ou47(7tW_*UB7T=+Rpeu`TZ z3^lxdIF~KjrM6`qudu&!JPq1E4vpidKC?Iw#r-fIbts`&w0UKv=!xtJk^bl(rn_m$ znZLWsb6@m_?#t8hroym0i7?Ib7qIg2s?LzMbD)gh!1{OrtHuF~_AX>{aWqd)%-N$8 z)PIb)_xBx+vaotMAWK$)VP1+GcWp~h6LBQ!JQ(}<EM;l4cXhxHV| zjW}v$Y}jW7gP<0oNS>9tjBsC7Hvw{U2->_-d3DJXdQfc@6CtT1H_BNwHSHf=*dAQv zT^MCWW|T4~bM?w^TYIfcWU_W_00!8f;4X`MRe!l8Qly!bY*#}VrqKe!(PtJ<>r12R zxEl(kc>P;WH;dLLM_|5HIFu1<%WY#QBM@kU@3D>wvvDJ3CZIzp9V3<+BT(UBAstk_ zGAJM-W(ZHy6+t&eu~{}ns$tRY9&Fhue<7hxLUVVq?V+&&cM%bT%Um4dyy0gAQPCqA zsgeza;C8^QcZ0g1bW&KdDa1Lk?2(JkiXo$LY&$mI<%BJUD5FU_6q1UbXwUruzq%p* z=O;wvA()xLd7P8eSTyixDc8bQF=9+9Eu$&EH{Xs|oBT?`OC6aYDUT9U^dRm{1LjIeiv5u&2b+lpvMu_N6B@`JsMS$>WA_J*w6~b3kI2| zE#E?SbV>36EKMn<5N940wnQcbA8#xz`tovtysPsgr=^=0pQ>Lxck8&^>#_EY zJy_P^RNt#p2JM(Te%XW##UIIpeOAuQ#_KapBd`~TPvs(XL%Fj{$d*U}Qz_DD1sFJ9 z6Rz5pZL*K#)+uGJLb*tD-Cw{|yBkN8A~9VeHDBtk(FSO*)?7$mbQKuG8nV_FdD7Q5 zmryFQCEHwm46CF$e52louOEy7AJxOQSkqi~9(Q>>m}(Wkmwat=o~Ul0P4YntNrmAr zh^qcV!yT%oK3yKL%)P^Yn!5`Vb~vQbiMV{|QD+~2%iuYiw@ujo;Qo?Rr@B?{xz=8R z18~0G)ZmUp*)}fhOj?m?YeSczeXDyuZ09$yXSBttHLZwI7Wh?;?-o8uE&t$cyMKJ| z|8|n=!|1@O0gHqC1{kss%RD>~rY<$yY43K=`udyGIwh9Ohr3)*C~8Px5d2DqQ-tQ$ zR5-8xu!J%D5}9g58Fkm`)%4S*%ElV5s!*goeMWLiv9m&%m(oDWHlCo*J#aowR>dyG zYV6_G*H@_O)Q`*Vrew33XDFqI7x8$G;ceH{QE6^Q{SO(bfNl*QT*Od?<^WOK|FWxU zHn(Tg-KfI0tG&tdw_4r~4cR7^Xq)oja?|&bwG}vd!>2N=h4m)cuvqE4WM|Od|VUJ%vl_F@>YmWWj@( zc+X7~Q{`@aF9E9jh4lI|cEZaaP_p}@O~TnHN=JiTiYTZHtyV7jav59p{EoeTk$xl>ZTp)`wnbN{{Zo2MbYrSqYZt zHD;OGM_Zp-PPBBfXFRZL5}dKUdLsza>?5)tg_lUwAFf_L7CvLSQf4eH?A)ApHKXu! zu!IX)K>OThE~5dr?FCMg*RIpsoQK;XR=g5a$okbq$c~SgvHnP%-_VaMkDuJ;zPsyU zoB5L#_w=3+7Ww_#NJJZ36+_2cc?Iv>x%TEsAjT`**ECqAMun!&5-mSd_x|Zg<8&+f zzWdXdX|b4EpMzZ&J?ZRe4n-bWB~`rh>nZ7Q37H9g2ir3nn| z^nUD5Z_fYVr_V=eEGPNZ6wYBcRc%X~q}wp3ioMZmeR*G>p68Nso9`}D2ljCK_4Mg` z)Av>m__QWgaenskQNTw+`%Jc3#ybI(bTT5dn-EBr@#7|67xQy4#c|Pm0f~M@T2&Q3 z`_BdK|JPDD&lEUw*`I=te}Djbi)CWP>!9JOrv^kKLjSuc{H?+bSGg6RYgCvZLGvq_ z5prLVV#S;`NtsrR+N|Ae+U0cj!5`fBWjFh8;8=_uxEhOQx91*3g@bb5VtQxAO8`(` zZ$+E9Lx&VhJ|6{TKDsF0=v0F~%6}DBy-36haOUo3p}cSmFuEYc;kIk(uiH%1O>X*- z!_=A~g+ILhy-V5Op6NBE1^zWoFVsh&-O|Gn8Ud4#0HpZ3+*qpt0EZJdPWn_S<@oqN zFB69U;0&Z1z9Cz4D0;R?FVY!Llys}3+AVff-j#AauFkN>I*h>{p?LR1`+ z8_v119syUT#$N;U7gjd`LVUo{(s;}se9V+OtP}UMnPGuM9@9?ud zil#yu+GcE^D&0ONGt6dc;T#04hE%Glu^3}vqKXZ$k$1n6bG~lRENpD%56wZPPEHz* zV}5vUKdLk#!w7fgm*I96%LLF4Yr$iIdw~VE$r8CkFb>fOngLBlF+Fxb6F=IgrcOOi z!b==>#>3x+SOMSg4j|E_Zi1BIud}^sx*t{NG$ z4K;-N{{?kbNIKSl@~Qi zUF_7(6}~ECy;O$;wP1_-RRl1NM*!`aV)rJ;Z@ekY47xHj+I#FdK2SruBUIzPWkE)I*o0}hPksiiUaIRNPo1JPGQ0->N zIBJciBAf2l3#|Caoxsa=AC}2&%D)uiu9CGxVex@; z*in6iXR&$`FCD#yi(aMVq8*Iqtj4u(kcUsXxi;h}M)qzi6ol1{e2%wwLj&nPdoOn; zpwt*TOq-!dUb9+@{#BURSL!n7fe-^zWIL%tJ(@Xh^4WhbIQ_roZ~mg_^@?AJM*o`< z*sYk?Tzkz_DoZ>pvnai3l{;sRSu5vVt0evihpZ*772Jq|g=`U3B`OBQcZ8@{d=pu` zrC{>kfQ0!pyenV1ex=}4H1QBsH9M013M#GNQIw*!K?Up}mO__$LQL^zg+%fTje*y` z*DEj4<~Po{a|;6u3+&mqLm!8IrfYo#7C7@ifdw31g9Q@*6c*^n!vgdR-}PdqL`*A& zgJ58hc?!}w7=L?cN7S)y%(hbF511APyRj8QR8Uv*ge8_j4RdU2Cs`EP>{BGtC1!<^ z_3sLoJ0?n1ld_G|Aw{h0oz_USOe=x(Jkd>z0SaWG9g)c2(+Z-e_+{Rso zPt{Q|`qkPkFrYX2F%~{no%o^&FNE6xK0W}F$Nk&$;(T3dI6J5z4_s!pKM(lQ5)$j} z{1CaDCJdP~YGHWE+l{Ed3|rli_cDkYw)=piSgnUQw(ai+Na7we?{dUDhUak;b^(w0 z3}!1VBEe~(1AeMm*U9GXrA#tvKn-pcyj~sSv>E^Hz!!u3V+gp9q?Mt5`5rZ_nhns| zs&g7I4b1mo*syTkuMFo`;j$4K&{Ym|U%FY!Kt>t9)IrrY=-DxOXqLq4#Gd^g~QNZ3hGaYiQ0`v+<{M?0$ z$w32r+uMCsR`4+|-h11jO%6rEH{qvkpU11tD0nXnXB`4o5bE1Tk&Q;vy_F`f|Yv={??)P%;#|*62?D%o$eAf$U z$ue5%{r-ls_7FWxG?j4>`w6m)oFZ=_%3b6!tHFy^BaZGy&vA0xaH5gZ0c$E+6tg%i z6m#ThhV6&b9r?cX8<+venye}XMU!{qd5$I=06v+?a0FdZQP1f zM9D9?6@Gz80e`^b=4oxk$QUNa96%XjDo*8-?j=8x>i3Ohj(;zdH-oA{ha3=sN1h>? zvaXS;RF?|H0P^l~HTNUMtk&LFET`(81`wLZ1ncF$Q8Ax=!-=LsQ(u4ie=^$qAN+Y@ zbBL@+T^LZZjhoJ9b0M9%gx2w)cMi?3`FjtYvrCTvVvwvIW&>uWIbHd5@?)D#+GiHq()^^xqZkl?d~)9kZXaOMzz zL#zO(<{2zsXU?dj`)Gd|j||@X3ve0;cɃ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 From ae4d6f05f8378541fceb7bad8933471df5b40933 Mon Sep 17 00:00:00 2001 From: Matteo Spinelli Date: Mon, 20 Aug 2018 12:12:31 +0200 Subject: [PATCH 228/243] teaking the moai profile --- resources/definitions/peopoly_moai.def.json | 49 +++++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/resources/definitions/peopoly_moai.def.json b/resources/definitions/peopoly_moai.def.json index 85480b303d..6ab1157c62 100644 --- a/resources/definitions/peopoly_moai.def.json +++ b/resources/definitions/peopoly_moai.def.json @@ -76,7 +76,13 @@ }, "top_bottom_thickness": { "minimum_value_warning": "0.1", - "value": "0.4" + "value": "0.1" + }, + "top_thickness": { + "minimum_value_warning": "resolveOrValue('layer_height')" + }, + "bottom_thickness": { + "minimum_value_warning": "resolveOrValue('layer_height')" }, "infill_sparse_thickness": { "maximum_value_warning": "0.5" @@ -115,7 +121,7 @@ "value": 3 }, "infill_overlap": { - "value": 15 + "value": 12 }, "adhesion_type": { "value": "'none'" @@ -182,8 +188,11 @@ "travel_compensate_overlapping_walls_x_enabled": { "value": "False" }, + "wall_0_wipe_dist": { + "value": "machine_nozzle_size / 3" + }, "wall_thickness": { - "value": 0.4 + "value": 0.5 }, "infill_sparse_density": { "value": 70 @@ -191,6 +200,9 @@ "infill_pattern": { "value": "'lines'" }, + "infill_angles": { + "valie": "[10,55,100,145,190,235,280,325]" + }, "cool_min_layer_time": { "enabled": false, "value": 0 @@ -231,14 +243,43 @@ "value": "False" }, "skin_overlap": { - "value": 6 + "value": 3 }, "infill_wipe_dist": { "value": 0 }, + "expand_skins_expand_distance": { + "value": "( wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x ) / 2" + }, "max_feedrate_z_override": { "value": 0, "enabled": false + }, + "flow_rate_max_extrusion_offset": { + "enabled": false + }, + "flow_rate_extrusion_offset_factor": { + "enabled": false + }, + "adaptive_layer_height_enabled": { + "value": "False", + "enabled": false + }, + "bridge_settings_enabled": { + "value": "False", + "enabled": false + }, + "acceleration_enabled": { + "value": "False", + "enabled": false + }, + "relative_extrusion": { + "value": "False", + "enabled": false + }, + "coasting_enable": { + "value": "False", + "enabled": false } } } From 39cbfca17f423cd9064960caffca12005f6948fe Mon Sep 17 00:00:00 2001 From: Matteo Spinelli Date: Mon, 20 Aug 2018 15:09:31 +0200 Subject: [PATCH 229/243] typo in moai profile --- resources/definitions/peopoly_moai.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/peopoly_moai.def.json b/resources/definitions/peopoly_moai.def.json index 6ab1157c62..e6d8b90571 100644 --- a/resources/definitions/peopoly_moai.def.json +++ b/resources/definitions/peopoly_moai.def.json @@ -201,7 +201,7 @@ "value": "'lines'" }, "infill_angles": { - "valie": "[10,55,100,145,190,235,280,325]" + "value": "[10,55,100,145,190,235,280,325]" }, "cool_min_layer_time": { "enabled": false, From 65992f4281afe5b4f798ce34aeae1bf4f9defcb8 Mon Sep 17 00:00:00 2001 From: Matteo Spinelli Date: Wed, 22 Aug 2018 16:26:34 +0200 Subject: [PATCH 230/243] Add KDE .directory file in gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5cc60c2f4c..0a66b6eb33 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ LC_MESSAGES *.lprof *~ *.qm +.directory .idea cura.desktop From 203e77fee102a8e63cec1f34991a4587ebd2c6d8 Mon Sep 17 00:00:00 2001 From: Matteo Spinelli Date: Fri, 24 Aug 2018 23:08:18 +0200 Subject: [PATCH 231/243] moai definition tweaks --- resources/definitions/peopoly_moai.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/peopoly_moai.def.json b/resources/definitions/peopoly_moai.def.json index e6d8b90571..ac9cee131b 100644 --- a/resources/definitions/peopoly_moai.def.json +++ b/resources/definitions/peopoly_moai.def.json @@ -121,7 +121,7 @@ "value": 3 }, "infill_overlap": { - "value": 12 + "value": 15 }, "adhesion_type": { "value": "'none'" @@ -243,7 +243,7 @@ "value": "False" }, "skin_overlap": { - "value": 3 + "value": 5 }, "infill_wipe_dist": { "value": 0 From 255a2afe3bcde210a6e3723f3285c5a3a0ec3386 Mon Sep 17 00:00:00 2001 From: Matteo Spinelli Date: Sat, 25 Aug 2018 13:31:48 +0200 Subject: [PATCH 232/243] more moai tweaks --- resources/quality/peopoly_moai/peopoly_moai_coarse.inst.cfg | 2 +- resources/quality/peopoly_moai/peopoly_moai_draft.inst.cfg | 2 +- resources/quality/peopoly_moai/peopoly_moai_extra_high.inst.cfg | 2 +- resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg | 2 +- resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/resources/quality/peopoly_moai/peopoly_moai_coarse.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_coarse.inst.cfg index 482b8ce51a..ac4f9ee81d 100644 --- a/resources/quality/peopoly_moai/peopoly_moai_coarse.inst.cfg +++ b/resources/quality/peopoly_moai/peopoly_moai_coarse.inst.cfg @@ -12,6 +12,6 @@ weight = 3 [values] layer_height = 0.08 speed_print = 90 -speed_travel = 100 +speed_travel = 120 speed_travel_layer_0 = 100 speed_wall = 90 diff --git a/resources/quality/peopoly_moai/peopoly_moai_draft.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_draft.inst.cfg index e7cfa673b2..2d21b1f7e0 100644 --- a/resources/quality/peopoly_moai/peopoly_moai_draft.inst.cfg +++ b/resources/quality/peopoly_moai/peopoly_moai_draft.inst.cfg @@ -12,7 +12,7 @@ weight = 4 [values] layer_height = 0.1 speed_print = 85 -speed_travel = 100 +speed_travel = 120 speed_travel_layer_0 = 100 speed_wall = 85 speed_slowdown_layers = 2 diff --git a/resources/quality/peopoly_moai/peopoly_moai_extra_high.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_extra_high.inst.cfg index da62ee32cd..796c2cff3c 100644 --- a/resources/quality/peopoly_moai/peopoly_moai_extra_high.inst.cfg +++ b/resources/quality/peopoly_moai/peopoly_moai_extra_high.inst.cfg @@ -12,7 +12,7 @@ weight = 0 [values] layer_height = 0.02 speed_print = 185 -speed_travel = 190 +speed_travel = 185 speed_travel_layer_0 = 100 speed_wall = 185 speed_slowdown_layers = 5 diff --git a/resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg index be35dbaf05..b36163d9f1 100644 --- a/resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg +++ b/resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg @@ -12,7 +12,7 @@ weight = 1 [values] layer_height = 0.04 speed_print = 140 -speed_travel = 145 +speed_travel = 140 speed_travel_layer_0 = 100 speed_wall = 140 speed_slowdown_layers = 4 diff --git a/resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg index 2d6ba873db..cf67591ab2 100644 --- a/resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg +++ b/resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg @@ -12,6 +12,6 @@ weight = 2 [values] layer_height = 0.06 speed_print = 120 -speed_travel = 130 +speed_travel = 120 speed_travel_layer_0 = 100 speed_wall = 120 From dd0ddaedac6404edb9808a50e11e071bda839e6d Mon Sep 17 00:00:00 2001 From: Matteo Spinelli Date: Tue, 28 Aug 2018 07:48:24 +0200 Subject: [PATCH 233/243] reduce stress on the galvo by printing infill in straight lines --- resources/definitions/peopoly_moai.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/peopoly_moai.def.json b/resources/definitions/peopoly_moai.def.json index ac9cee131b..a578cc4240 100644 --- a/resources/definitions/peopoly_moai.def.json +++ b/resources/definitions/peopoly_moai.def.json @@ -201,7 +201,7 @@ "value": "'lines'" }, "infill_angles": { - "value": "[10,55,100,145,190,235,280,325]" + "value": "[0,90]" }, "cool_min_layer_time": { "enabled": false, From 3e3f1cb03d27eabdaa682bea1cbb38e59dd14de9 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Tue, 28 Aug 2018 09:31:05 +0200 Subject: [PATCH 234/243] Remove double shortcut buttons CURA-5642 --- resources/qml/Actions.qml | 18 +++++++++--------- resources/qml/Cura.qml | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index 21e6eebf58..d5572298f7 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -110,35 +110,35 @@ Item Action { id: view3DCameraAction; - text: catalog.i18nc("@action:inmenu menubar:view","&3D View"); + text: catalog.i18nc("@action:inmenu menubar:view","3D View"); onTriggered: UM.Controller.rotateView("3d", 0); } Action { id: viewFrontCameraAction; - text: catalog.i18nc("@action:inmenu menubar:view","&Front View"); + text: catalog.i18nc("@action:inmenu menubar:view","Front View"); onTriggered: UM.Controller.rotateView("home", 0); } Action { id: viewTopCameraAction; - text: catalog.i18nc("@action:inmenu menubar:view","&Top View"); + text: catalog.i18nc("@action:inmenu menubar:view","Top View"); onTriggered: UM.Controller.rotateView("y", 90); } Action { id: viewLeftSideCameraAction; - text: catalog.i18nc("@action:inmenu menubar:view","&Left Side View"); + text: catalog.i18nc("@action:inmenu menubar:view","Left Side View"); onTriggered: UM.Controller.rotateView("x", 90); } Action { id: viewRightSideCameraAction; - text: catalog.i18nc("@action:inmenu menubar:view","&Right Side View"); + text: catalog.i18nc("@action:inmenu menubar:view","Right Side View"); onTriggered: UM.Controller.rotateView("x", -90); } @@ -229,7 +229,7 @@ Item Action { id: deleteSelectionAction; - text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete &Selected Model", "Delete &Selected Models", UM.Selection.selectionCount); + text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete Selected Model", "Delete Selected Models", UM.Selection.selectionCount); enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection; iconName: "edit-delete"; shortcut: StandardKey.Delete; @@ -239,7 +239,7 @@ Item Action //Also add backspace as the same function as delete because on Macintosh keyboards the button called "delete" is actually a backspace, and the user expects it to function as a delete. { id: backspaceSelectionAction - text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete &Selected Model", "Delete &Selected Models", UM.Selection.selectionCount) + text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete Selected Model", "Delete Selected Models", UM.Selection.selectionCount) enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection iconName: "edit-delete" shortcut: StandardKey.Backspace @@ -328,7 +328,7 @@ Item Action { id: selectAllAction; - text: catalog.i18nc("@action:inmenu menubar:edit","&Select All Models"); + text: catalog.i18nc("@action:inmenu menubar:edit","Select All Models"); enabled: UM.Controller.toolsEnabled; iconName: "edit-select-all"; shortcut: "Ctrl+A"; @@ -386,7 +386,7 @@ Item Action { id: resetAllAction; - text: catalog.i18nc("@action:inmenu menubar:edit","Reset All Model &Transformations"); + text: catalog.i18nc("@action:inmenu menubar:edit","Reset All Model Transformations"); onTriggered: CuraApplication.resetAll(); } diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index cd8a122bd2..33e456c758 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -117,7 +117,7 @@ UM.MainWindow MenuItem { id: saveWorkspaceMenu - text: catalog.i18nc("@title:menu menubar:file","&Save...") + text: catalog.i18nc("@title:menu menubar:file","Save...") onTriggered: { var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/x-curaproject+xml" }; From 40c4e9c5dfe5361a8f7c38ec3ef2462b0ec2aacb Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 28 Aug 2018 09:56:00 +0200 Subject: [PATCH 235/243] Fix KeyError color_code in BaseMaterialsModel --- cura/Machines/Models/BaseMaterialsModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 43b42c55ff..1b20e1188c 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -124,7 +124,7 @@ class BaseMaterialsModel(ListModel): "description": metadata["description"], "material": metadata["material"], "color_name": metadata["color_name"], - "color_code": metadata["color_code"], + "color_code": metadata.get("color_code", ""), "density": metadata.get("properties", {}).get("density", ""), "diameter": metadata.get("properties", {}).get("diameter", ""), "approximate_diameter": metadata["approximate_diameter"], From 694cc91ae9d174f8b420f63188754e3db232457d Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 28 Aug 2018 11:21:47 +0200 Subject: [PATCH 236/243] Add a "Favorites" heading to materials menu Contributes to CURA-5162 Also fixed some non i18n strings --- resources/qml/Menus/MaterialMenu.qml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index 186c5d1d2a..f9e343d2dd 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -10,7 +10,7 @@ import Cura 1.0 as Cura Menu { id: menu - title: "Material" + title: catalog.i18nc("@label:category menu label", "Material") property int extruderIndex: 0 @@ -32,6 +32,12 @@ Menu extruderPosition: menu.extruderIndex } + MenuItem + { + text: catalog.i18nc("@label:category menu label", "Favorites") + enabled: false + visible: favoriteMaterialsModel.items.length > 0 + } Instantiator { model: favoriteMaterialsModel @@ -52,7 +58,7 @@ Menu Menu { id: genericMenu - title: "Generic" + title: catalog.i18nc("@label:category menu label", "Generic") Instantiator { From dda356fbc4fb122b36fd71e096434c414319c9f4 Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 29 Aug 2018 11:50:43 +0200 Subject: [PATCH 237/243] Remove the 40 char maximum on printer address textfield --- plugins/UM3NetworkPrinting/DiscoverUM3Action.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml index 127b3c35bd..b5b80a3010 100644 --- a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml +++ b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml @@ -364,7 +364,6 @@ Cura.MachineAction { id: addressField width: parent.width - maximumLength: 40 validator: RegExpValidator { regExp: /[a-zA-Z0-9\.\-\_]*/ From 1d8f19f1d1c501f5d7525ca695967a7813f30c16 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 29 Aug 2018 11:55:37 +0200 Subject: [PATCH 238/243] Don't give error value for infill layer thickness if no infill It won't crash the engine because the entire infill filling routine is skipped. --- 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 3eb7cb1c32..610ee1473e 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1819,9 +1819,9 @@ "unit": "mm", "type": "float", "default_value": 0.1, - "minimum_value": "resolveOrValue('layer_height')", + "minimum_value": "resolveOrValue('layer_height') if infill_line_distance > 0 else -999999", "maximum_value_warning": "0.75 * machine_nozzle_size", - "maximum_value": "resolveOrValue('layer_height') * (1.45 if spaghetti_infill_enabled else 8)", + "maximum_value": "resolveOrValue('layer_height') * (1.45 if spaghetti_infill_enabled else 8) if infill_line_distance > 0 else 999999", "value": "resolveOrValue('layer_height')", "enabled": "infill_sparse_density > 0 and not spaghetti_infill_enabled", "limit_to_extruder": "infill_extruder_nr", From c48a5474f0f0e51945d9783839e0d5d0eee338df Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 29 Aug 2018 13:42:26 +0200 Subject: [PATCH 239/243] remove .curaproject from the extensions and just use .3mf CURA-5650 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 4 +--- plugins/3MFReader/__init__.py | 6 +----- plugins/3MFWriter/__init__.py | 6 +----- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 16ab22473b..685f3091e2 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -89,7 +89,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): MimeType( name="application/x-curaproject+xml", comment="Cura Project File", - suffixes=["curaproject.3mf"] + suffixes=["3mf"] ) ) @@ -726,8 +726,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader): nodes = [] base_file_name = os.path.basename(file_name) - if base_file_name.endswith(".curaproject.3mf"): - base_file_name = base_file_name[:base_file_name.rfind(".curaproject.3mf")] self.setWorkspaceName(base_file_name) return nodes diff --git a/plugins/3MFReader/__init__.py b/plugins/3MFReader/__init__.py index 3a4fde4ab8..ce94bbe69c 100644 --- a/plugins/3MFReader/__init__.py +++ b/plugins/3MFReader/__init__.py @@ -18,11 +18,7 @@ catalog = i18nCatalog("cura") def getMetaData() -> Dict: - # Workaround for osx not supporting double file extensions correctly. - if Platform.isOSX(): - workspace_extension = "3mf" - else: - workspace_extension = "curaproject.3mf" + workspace_extension = "3mf" metaData = {} if "3MFReader.ThreeMFReader" in sys.modules: diff --git a/plugins/3MFWriter/__init__.py b/plugins/3MFWriter/__init__.py index e779628f7e..29e2beae60 100644 --- a/plugins/3MFWriter/__init__.py +++ b/plugins/3MFWriter/__init__.py @@ -15,11 +15,7 @@ from UM.Platform import Platform i18n_catalog = i18nCatalog("uranium") def getMetaData(): - # Workarround for osx not supporting double file extensions correctly. - if Platform.isOSX(): - workspace_extension = "3mf" - else: - workspace_extension = "curaproject.3mf" + workspace_extension = "3mf" metaData = {} From baef0350cdf931a8365272b86e42233740c99541 Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 29 Aug 2018 14:41:38 +0200 Subject: [PATCH 240/243] Cleaned up MIME types --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 8 -------- plugins/3MFWriter/__init__.py | 2 +- resources/qml/Cura.qml | 2 +- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 685f3091e2..6d55e0643d 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -85,14 +85,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader): def __init__(self) -> None: super().__init__() - MimeTypeDatabase.addMimeType( - MimeType( - name="application/x-curaproject+xml", - comment="Cura Project File", - suffixes=["3mf"] - ) - ) - self._supported_extensions = [".3mf"] self._dialog = WorkspaceDialog() self._3mf_mesh_reader = None diff --git a/plugins/3MFWriter/__init__.py b/plugins/3MFWriter/__init__.py index 29e2beae60..4b8a03888d 100644 --- a/plugins/3MFWriter/__init__.py +++ b/plugins/3MFWriter/__init__.py @@ -32,7 +32,7 @@ def getMetaData(): "output": [{ "extension": workspace_extension, "description": i18n_catalog.i18nc("@item:inlistbox", "Cura Project 3MF file"), - "mime_type": "application/x-curaproject+xml", + "mime_type": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml", "mode": ThreeMFWorkspaceWriter.ThreeMFWorkspaceWriter.OutputMode.BinaryMode }] } diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 33e456c758..616523fc45 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -120,7 +120,7 @@ UM.MainWindow text: catalog.i18nc("@title:menu menubar:file","Save...") onTriggered: { - var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/x-curaproject+xml" }; + var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml" }; if(UM.Preferences.getValue("cura/dialog_on_project_save")) { saveWorkspaceDialog.args = args; From 939484bc9181f2b08a0c0f093c3ed7f4539a5364 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 29 Aug 2018 17:25:34 +0200 Subject: [PATCH 241/243] Fix adding materials in UFP CURA-5555 - Store materials in virtual path "/Materials" - Correct material relationship type - Add origin for material relationship - Use MaterialManager instead of ContainerRegistry to get materials - Other minor changes --- plugins/UFPWriter/UFPWriter.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index 841d61a000..49a6a36d68 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -24,8 +24,6 @@ class UFPWriter(MeshWriter): self._snapshot = None Application.getInstance().getOutputDeviceManager().writeStarted.connect(self._createSnapshot) - self._default_data_path ="/Cura/" - def _createSnapshot(self, *args): # must be called from the main thread because of OpenGL Logger.log("d", "Creating thumbnail image...") @@ -62,17 +60,17 @@ class UFPWriter(MeshWriter): else: Logger.log("d", "Thumbnail not created, cannot save it") - #Store the material. + # Store the material. application = Application.getInstance() machine_manager = application.getMachineManager() + material_manager = application.getMaterialManager() global_stack = machine_manager.activeMachine - container_registry = application.getContainerRegistry() material_extension = "xml.fdm_material" material_mime_type = "application/x-ultimaker-material-profile" try: - archive.addContentType(extension=material_extension, mime_type=material_mime_type) + archive.addContentType(extension = material_extension, mime_type = material_mime_type) except: Logger.log("w", "The material extension: %s was already added", material_extension) @@ -80,30 +78,32 @@ class UFPWriter(MeshWriter): for extruder_stack in global_stack.extruders.values(): material = extruder_stack.material material_file_name = material.getMetaData()["base_file"] + ".xml.fdm_material" - material_file_name = self._default_data_path + material_file_name + material_file_name = "/Materials/" + material_file_name #Same material cannot be added if material_file_name in added_materials: continue - material_containers = container_registry.findContainers(id=material.getMetaDataEntry("base_file")) - - if not material_containers: - Logger.log("e", "Cannot find material container with id: %s", material.id) + material_root_id = material.getMetaDataEntry("base_file") + material_group = material_manager.getMaterialGroup(material_root_id) + if material_group is None: + Logger.log("e", "Cannot find material container with root id [%s]", material_root_id) return False - material_container = material_containers[0] + material_container = material_group.root_material_node try: serialized_material = material_container.serialize() except NotImplementedError: - Logger.log("e", "Unable serialize material container with id: %s", material.id) + Logger.log("e", "Unable serialize material container with root id: %s", material_root_id) return False material_file = archive.getStream(material_file_name) material_file.write(serialized_material.encode("UTF-8")) - archive.addRelation(virtual_path=material_file_name,relation_type="http://schemas.ultimaker.org/package/2018/relationships/xml.fdm_material") + archive.addRelation(virtual_path = material_file_name, + relation_type = "http://schemas.ultimaker.org/package/2018/relationships/material", + origin = "/3D/model.gcode") added_materials.append(material_file_name) archive.close() - return True \ No newline at end of file + return True From 8f5aa82bdb98e8df2cb6c89f061545f3f0396afc Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 29 Aug 2018 17:33:18 +0200 Subject: [PATCH 242/243] Fix adding materials in UFP CURA-5555 Need to use getContainer() for a MaterialNode. --- plugins/UFPWriter/UFPWriter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index 49a6a36d68..d838aaef36 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -90,7 +90,7 @@ class UFPWriter(MeshWriter): Logger.log("e", "Cannot find material container with root id [%s]", material_root_id) return False - material_container = material_group.root_material_node + material_container = material_group.root_material_node.getContainer() try: serialized_material = material_container.serialize() except NotImplementedError: From 570d0715eda45a1ec4caf05f143171cdd208cb9c Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 29 Aug 2018 17:33:51 +0200 Subject: [PATCH 243/243] Add call_on_qt_thread to UFPWriter.write() CURA-5555 --- plugins/UFPWriter/UFPWriter.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index d838aaef36..a85ee489cb 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -13,6 +13,7 @@ from UM.PluginRegistry import PluginRegistry #To get the g-code writer. from PyQt5.QtCore import QBuffer from cura.Snapshot import Snapshot +from cura.Utils.Threading import call_on_qt_thread from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -29,6 +30,11 @@ class UFPWriter(MeshWriter): Logger.log("d", "Creating thumbnail image...") self._snapshot = Snapshot.snapshot(width = 300, height = 300) + # This needs to be called on the main thread (Qt thread) because the serialization of material containers can + # trigger loading other containers. Because those loaded containers are QtObjects, they must be created on the + # Qt thread. The File read/write operations right now are executed on separated threads because they are scheduled + # by the Job class. + @call_on_qt_thread def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode): archive = VirtualFile() archive.openStream(stream, "application/x-ufp", OpenMode.WriteOnly)