Browse Source

Merge branch 'master' of github.com:Ultimaker/Cura

Jaime van Kessel 3 years ago
parent
commit
66f57d4d58

+ 6 - 0
README.md

@@ -26,10 +26,16 @@ Dependencies
 * [PySerial](https://github.com/pyserial/pyserial) Only required for USB printing support.
 * [python-zeroconf](https://github.com/jstasiak/python-zeroconf) Only required to detect mDNS-enabled printers.
 
+For a list of required Python packages, with their recommended version, see `requirements.txt`.
+
+This list is not exhaustive at the moment, please check the links in the next section for more details.
+
 Build scripts
 -------------
 Please check out [cura-build](https://github.com/Ultimaker/cura-build) for detailed building instructions.
 
+If you want to build the entire environment from scratch before building Cura as well, [cura-build-environment](https://github.com/Ultimaker/cura-build) might be a starting point before cura-build. (Again, see cura-build for more details.)
+
 Running from Source
 -------------
 Please check our [Wiki page](https://github.com/Ultimaker/Cura/wiki/Running-Cura-from-Source) for details about running Cura from source.

+ 9 - 6
cura/Backups/Backup.py

@@ -14,6 +14,7 @@ from UM.Logger import Logger
 from UM.Message import Message
 from UM.Platform import Platform
 from UM.Resources import Resources
+from UM.Version import Version
 
 if TYPE_CHECKING:
     from cura.CuraApplication import CuraApplication
@@ -28,6 +29,8 @@ class Backup:
     IGNORED_FILES = [r"cura\.log", r"plugins\.json", r"cache", r"__pycache__", r"\.qmlc", r"\.pyc"]
     """These files should be ignored when making a backup."""
 
+    IGNORED_FOLDERS = [r"plugins"]
+
     SECRETS_SETTINGS = ["general/ultimaker_auth_data"]
     """Secret preferences that need to obfuscated when making a backup of Cura"""
 
@@ -74,8 +77,9 @@ class Backup:
         machine_count = max(len([s for s in files if "machine_instances/" in s]) - 1, 0)  # If people delete their profiles but not their preferences, it can still make a backup, and report -1 profiles. Server crashes on this.
         material_count = max(len([s for s in files if "materials/" in s]) - 1, 0)
         profile_count = max(len([s for s in files if "quality_changes/" in s]) - 1, 0)
-        plugin_count = len([s for s in files if "plugin.json" in s])
-
+        # We don't store plugins anymore, since if you can make backups, you have an account (and the plugins are
+        # on the marketplace anyway)
+        plugin_count = 0
         # Store the archive and metadata so the BackupManager can fetch them when needed.
         self.zip_file = buffer.getvalue()
         self.meta_data = {
@@ -94,8 +98,7 @@ class Backup:
         :param root_path: The root directory to archive recursively.
         :return: The archive as bytes.
         """
-
-        ignore_string = re.compile("|".join(self.IGNORED_FILES))
+        ignore_string = re.compile("|".join(self.IGNORED_FILES + self.IGNORED_FOLDERS))
         try:
             archive = ZipFile(buffer, "w", ZIP_DEFLATED)
             for root, folders, files in os.walk(root_path):
@@ -132,8 +135,8 @@ class Backup:
                                    "Tried to restore a Cura backup without having proper data or meta data."))
             return False
 
-        current_version = self._application.getVersion()
-        version_to_restore = self.meta_data.get("cura_release", "master")
+        current_version = Version(self._application.getVersion())
+        version_to_restore = Version(self.meta_data.get("cura_release", "master"))
 
         if current_version < version_to_restore:
             # Cannot restore version newer than current because settings might have changed.

+ 13 - 0
cura/Backups/BackupsManager.py

@@ -4,6 +4,7 @@
 from typing import Dict, Optional, Tuple, TYPE_CHECKING
 
 from UM.Logger import Logger
+from UM.Version import Version
 from cura.Backups.Backup import Backup
 
 if TYPE_CHECKING:
@@ -52,6 +53,18 @@ class BackupsManager:
 
         backup = Backup(self._application, zip_file = zip_file, meta_data = meta_data)
         restored = backup.restore()
+
+        package_manager = self._application.getPackageManager()
+
+        # If the backup was made with Cura 4.10 (or higher), we no longer store plugins.
+        # Since the restored backup doesn't have those plugins anymore, we should remove it from the list
+        # of installed plugins.
+        if Version(meta_data.get("cura_release")) >= Version("4.10.0"):
+            for package_id in package_manager.getAllInstalledPackageIDs():
+                package_data = package_manager.getInstalledPackageInfo(package_id)
+                if package_data.get("package_type") == "plugin" and not package_data.get("is_bundled"):
+                    package_manager.removePackage(package_id)
+
         if restored:
             # At this point, Cura will need to restart for the changes to take effect.
             # We don't want to store the data at this point as that would override the just-restored backup.

+ 2 - 2
cura/Machines/Models/MachineModelUtils.py

@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Ultimaker B.V.
+# Copyright (c) 2021 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
 from typing import TYPE_CHECKING
@@ -34,4 +34,4 @@ def fetchLayerHeight(quality_group: "QualityGroup") -> float:
     if isinstance(layer_height, SettingFunction):
         layer_height = layer_height(global_stack)
 
-    return float(layer_height)
+    return round(float(layer_height), 3)

+ 3 - 1
cura/Machines/Models/MaterialManagementModel.py

@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Ultimaker B.V.
+# Copyright (c) 2021 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
 import copy  # To duplicate materials.
@@ -79,6 +79,7 @@ class MaterialManagementModel(QObject):
 
         :param material_node: The material to remove.
         """
+        Logger.info(f"Removing material {material_node.container_id}")
 
         container_registry = CuraContainerRegistry.getInstance()
         materials_this_base_file = container_registry.findContainersMetadata(base_file = material_node.base_file)
@@ -194,6 +195,7 @@ class MaterialManagementModel(QObject):
 
         :return: The root material ID of the duplicate material.
         """
+        Logger.info(f"Duplicating material {material_node.base_file} to {new_base_id}")
         return self.duplicateMaterialByBaseFile(material_node.base_file, new_base_id, new_metadata)
 
     @pyqtSlot(result = str)

+ 2 - 1
cura/Settings/ContainerManager.py

@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Ultimaker B.V.
+# Copyright (c) 2021 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
 import os
@@ -241,6 +241,7 @@ class ContainerManager(QObject):
             file_url = file_url_or_string.toLocalFile()
         else:
             file_url = file_url_or_string
+        Logger.info(f"Importing material from {file_url}")
 
         if not file_url or not os.path.exists(file_url):
             return {"status": "error", "message": "Invalid path"}

+ 7 - 2
plugins/3MFReader/ThreeMFWorkspaceReader.py

@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Ultimaker B.V.
+# Copyright (c) 2021 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
 from configparser import ConfigParser
@@ -412,7 +412,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
         quality_container_id = parser["containers"][str(_ContainerIndexes.Quality)]
         quality_type = "empty_quality"
         if quality_container_id not in ("empty", "empty_quality"):
-            quality_type = instance_container_info_dict[quality_container_id].parser["metadata"]["quality_type"]
+            if quality_container_id in instance_container_info_dict:
+                quality_type = instance_container_info_dict[quality_container_id].parser["metadata"]["quality_type"]
+            else:  # If a version upgrade changed the quality profile in the stack, we'll need to look for it in the built-in profiles instead of the workspace.
+                quality_matches = ContainerRegistry.getInstance().findContainersMetadata(id = quality_container_id)
+                if quality_matches:  # If there's no profile with this ID, leave it empty_quality.
+                    quality_type = quality_matches[0]["quality_type"]
 
         # Get machine info
         serialized = archive.open(global_stack_file).read().decode("utf-8")

+ 15 - 0
plugins/VersionUpgrade/VersionUpgrade49to410/VersionUpgrade49to410.py

@@ -94,6 +94,16 @@ class VersionUpgrade49to410(VersionUpgrade):
         }
     }
 
+    _deltacomb_quality_type_conversion = {
+        "a" : "D005",
+        "b" : "D010",
+        "c" : "D015",
+        "d" : "D020",
+        "e" : "D030",
+        "f" : "D045",
+        "g" : "D060"
+    }
+
     def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
         """Upgrades instance containers to have the new version number.
 
@@ -123,6 +133,11 @@ class VersionUpgrade49to410(VersionUpgrade):
                     parser["metadata"]["quality_type"] = self._two_trees_bluer_quality_type_conversion.get(parser.get("metadata", "quality_type", fallback = "fast"), "standard")
                     break
 
+                if os.path.basename(filename).startswith("deltacomb_"):
+                    parser["general"]["definition"] = "deltacomb_base"
+                    parser["metadata"]["quality_type"] = self._deltacomb_quality_type_conversion.get(parser.get("metadata", "quality_type", fallback = "c"), "D015")
+                    break
+
         result = io.StringIO()
         parser.write(result)
         return [filename], [result.getvalue()]

+ 20 - 12
resources/definitions/deltacomb_base.def.json

@@ -13,7 +13,7 @@
         "has_variants":                    true,
         "variants_name":                   "Head",
         
-        "preferred_quality_type":          "d",
+        "preferred_quality_type":          "D020",
         "preferred_material":              "generic_pla",
         
         "machine_extruder_trains": {
@@ -29,7 +29,7 @@
         "machine_heated_bed":              { "default_value": true },
         "machine_center_is_zero":          { "default_value": true },
         "machine_gcode_flavor":            { "default_value": "RepRap (Marlin/Sprinter)" },
-        "machine_start_gcode":             { "default_value": ";---------------------------------------\n;Deltacomb start script\n;---------------------------------------\nG21 ;metric values\nG90 ;absolute positioning\nM107 ;start with the fan off\nG28 ;Home all axes (max endstops)\nG92 E0 ;zero the extruded length\nG1 Z15.0 F9000 ;move to the platform down 15mm\nG1 F9000\n\n;Put printing message on LCD screen\nM117 Printing...\n;---------------------------------------"},
+        "machine_start_gcode":             { "default_value": ";---------------------------------------\n;Deltacomb start script\n;---------------------------------------\nG21 ;metric values\nG90 ;absolute positioning\nM107 ;start with the fan off\nG28 ;Home all axes (max endstops)\nM420 S1; Bed Level Enable\nG92 E0 ;zero the extruded length\nG1 Z15.0 F9000 ;move to the platform down 15mm\nG1 F9000\n\n;Put printing message on LCD screen\nM117 In stampa...\nM140 S{print_bed_temperature} ;set the target bed temperature\n;---------------------------------------"},
         "machine_end_gcode":               { "default_value": ";---------------------------------------\n;Deltacomb end script\n;---------------------------------------\nG91 ;relative positioning\nG1 F15000 X8.0 E-4.5 ;Wipe filament+material retraction\nG1 F15000 E4.0 Z1 ;Retraction compensation\nG28 ;Home all axes (max endstops)\nM84 ;steppers off\n" },
         "machine_shape":                   { "default_value": "elliptic" },
 
@@ -60,25 +60,32 @@
         "jerk_infill":                     { "value": "10" },
         "jerk_travel":                     { "value": "10" },
 
-        "retraction_hop_enabled":          { "default_value": true },
-        "retraction_hop":                  { "default_value": 0.5 },
-        "retraction_amount" :              { "default_value": 3.5 },
-        "retraction_speed" :               { "default_value": 70 },
-        "retraction_combing" :             { "default_value": "noskin" },
-        "travel_avoid_distance":           { "value": "1" },
+        "retraction_hop_enabled":            { "default_value": true },
+        "retraction_hop":                    { "default_value": 1.0 },
+        "retraction_amount" :                { "default_value": 3.5 },
+        "retraction_speed" :                 { "default_value": 40 },
+        "retraction_combing" :               { "default_value": "noskin" },
+        "travel_avoid_distance":             { "value": "1" },
+        "travel_avoid_supports":             { "value": "True" },
+        "retraction_hop_only_when_collides": { "value": "1" },
+
+        "switch_extruder_retraction_amount": { "value": 10},
+        "switch_extruder_retraction_speeds": { "default_value": 70 },
 
         "top_bottom_thickness":            { "default_value": 0.8 },
         "roofing_layer_count":             { "value": "1" },
         "roofing_line_width":              { "value": "line_width * 0.75" },
+        "z_seam_corner":                   { "value": "'z_seam_corner_weighted'" },
 
         "infill_sparse_density":           { "default_value": 30 },
         "infill_pattern":                  { "value": "'cubic'" },
         "infill_before_walls":             { "default_value": false },
 
-        "support_z_distance":              { "value": "layer_height * 2" },
+        "support_z_distance":              { "value": "layer_height" },
         "support_bottom_distance":         { "value": "layer_height" },
-        "support_use_towers" :             { "default_value": false },
-        "support_bottom_enable" :          { "value": "0" },
+        "support_use_towers":              { "default_value": false },
+        "support_bottom_enable":           { "value": false },
+        "support_wall_count":              { "value": "1" },
 
         "skirt_brim_speed":                { "value": "speed_layer_0" },
         "skirt_line_count":                { "default_value": 3 },
@@ -86,7 +93,8 @@
         "brim_width":                      { "value": "3" },
 
         "prime_tower_size":                { "value": "math.sqrt(extruders_enabled_count * prime_tower_min_volume / layer_height / math.pi) * 2"},
-        "prime_tower_position_x":          { "value": "prime_tower_size - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' or (prime_tower_brim_enable and adhesion_type != 'raft') 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)" },
+        "prime_tower_brim_enable":         { "value": false },
+        "prime_tower_position_x":          { "value": "prime_tower_size / 2" },
         "prime_tower_position_y":          { "value": "machine_depth / 2 - prime_tower_size - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' or (prime_tower_brim_enable and adhesion_type != 'raft') 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" }
     }
 }

+ 15 - 1
resources/definitions/deltacomb_dc20.def.json

@@ -19,6 +19,20 @@
         "machine_extruder_count":  { "default_value": 2, "maximum_value": "2" },
         "machine_width":           { "default_value": 190 },
         "machine_depth":           { "default_value": 190 },
-        "machine_height":          { "default_value": 250 }
+        "machine_height":          { "default_value": 250 },
+        "machine_disallowed_areas":{ "default_value": [
+           [[ 53, 78], [ 63, 78], [  73, 70], [ 62, 70]],
+           [[ 62, 70], [ 73, 70], [  81, 61], [ 70, 61]],
+           [[ 70, 61], [ 81, 61], [  88, 51], [ 76, 51]],
+           [[ 76, 51], [ 88, 51], [  93, 40], [ 81, 40]],
+           [[ 81, 40], [ 93, 40], [  97, 29], [ 85, 29]],
+           [[ 85, 29], [ 97, 29], [ 101, 17], [ 88, 17]],
+           [[-37, 78], [-47, 78], [-57, 70], [-46, 70]],
+           [[-46, 70], [-57, 70], [-69, 61], [-54, 61]],
+           [[-54, 61], [-69, 61], [-72, 51], [-60, 51]],
+           [[-60, 51], [-72, 51], [-77, 40], [-65, 40]],
+           [[-65, 40], [-77, 40], [-81, 29], [-69, 29]],
+           [[-69, 29], [-81, 29], [-85, 17], [-72, 17]]
+         ]}
     }
 }

Some files were not shown because too many files changed in this diff