Browse Source

Merge branch 'master' into PP-1-Improved_print_profiles

# Conflicts:
#	resources/definitions/ultimaker_s3.def.json
#	resources/definitions/ultimaker_s5.def.json
p.kuiper 3 years ago
parent
commit
f9f59d0da1

+ 1 - 1
cura/CuraApplication.py

@@ -129,7 +129,7 @@ class CuraApplication(QtApplication):
     # SettingVersion represents the set of settings available in the machine/extruder definitions.
     # You need to make sure that this version number needs to be increased if there is any non-backwards-compatible
     # changes of the settings.
-    SettingVersion = 17
+    SettingVersion = 19
 
     Created = False
 

+ 3 - 1
cura/Settings/ContainerManager.py

@@ -23,6 +23,8 @@ from UM.Settings.InstanceContainer import InstanceContainer
 
 import cura.CuraApplication
 from cura.Machines.ContainerTree import ContainerTree
+from cura.Settings.ExtruderStack import ExtruderStack
+from cura.Settings.GlobalStack import GlobalStack
 
 if TYPE_CHECKING:
     from cura.CuraApplication import CuraApplication
@@ -408,7 +410,7 @@ class ContainerManager(QObject):
         container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
         for plugin_id, container_type in container_registry.getContainerTypes():
             # Ignore default container types since those are not plugins
-            if container_type in (InstanceContainer, ContainerStack, DefinitionContainer):
+            if container_type in (InstanceContainer, ContainerStack, DefinitionContainer, GlobalStack, ExtruderStack):
                 continue
 
             serialize_type = ""

+ 2 - 0
plugins/CuraEngineBackend/CuraEngineBackend.py

@@ -428,6 +428,7 @@ class CuraEngineBackend(QObject, Backend):
                                                             "Unable to slice with the current settings. The following settings have errors: {0}").format(", ".join(error_labels)),
                                               title = catalog.i18nc("@info:title", "Unable to slice"),
                                               message_type = Message.MessageType.WARNING)
+                Logger.warning(f"Unable to slice with the current settings. The following settings have errors: {', '.join(error_labels)}")
                 self._error_message.show()
                 self.setState(BackendState.Error)
                 self.backendError.emit(job)
@@ -454,6 +455,7 @@ class CuraEngineBackend(QObject, Backend):
                                                         "Unable to slice due to some per-model settings. The following settings have errors on one or more models: {error_labels}").format(error_labels = ", ".join(errors.values())),
                                           title = catalog.i18nc("@info:title", "Unable to slice"),
                                           message_type = Message.MessageType.WARNING)
+            Logger.warning(f"Unable to slice due to per-object settings. The following settings have errors on one or more models: {', '.join(errors.values())}")
             self._error_message.show()
             self.setState(BackendState.Error)
             self.backendError.emit(job)

+ 14 - 5
plugins/CuraEngineBackend/StartSliceJob.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 numpy
@@ -353,10 +353,19 @@ class StartSliceJob(Job):
             result[key] = stack.getProperty(key, "value")
             Job.yieldThread()
 
-        result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
+        # Material identification in addition to non-human-readable GUID
+        result["material_id"] = stack.material.getMetaDataEntry("base_file", "")
+        result["material_type"] = stack.material.getMetaDataEntry("material", "")
+        result["material_name"] = stack.material.getMetaDataEntry("name", "")
+        result["material_brand"] = stack.material.getMetaDataEntry("brand", "")
+
+        # Renamed settings.
+        result["print_bed_temperature"] = result["material_bed_temperature"]
         result["print_temperature"] = result["material_print_temperature"]
         result["travel_speed"] = result["speed_travel"]
-        result["time"] = time.strftime("%H:%M:%S") #Some extra settings.
+
+        #Some extra settings.
+        result["time"] = time.strftime("%H:%M:%S")
         result["date"] = time.strftime("%d-%m-%Y")
         result["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][int(time.strftime("%w"))]
         result["initial_extruder_nr"] = CuraApplication.getInstance().getExtruderManager().getInitialExtruderNr()
@@ -455,9 +464,9 @@ class StartSliceJob(Job):
         bed_temperature_settings = ["material_bed_temperature", "material_bed_temperature_layer_0"]
         pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(bed_temperature_settings) # match {setting} as well as {setting, extruder_nr}
         settings["material_bed_temp_prepend"] = re.search(pattern, start_gcode) == None
-        print_temperature_settings = ["material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature"]
+        print_temperature_settings = ["material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature", "print_temperature"]
         pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(print_temperature_settings) # match {setting} as well as {setting, extruder_nr}
-        settings["material_print_temp_prepend"] = re.search(pattern, start_gcode) == None
+        settings["material_print_temp_prepend"] = re.search(pattern, start_gcode) is None
 
         # Replace the setting tokens in start and end g-code.
         # Use values from the first used extruder by default so we get the expected temperatures

+ 47 - 1
plugins/PostProcessingPlugin/scripts/FilamentChange.py

@@ -7,6 +7,8 @@
 from typing import List
 from ..Script import Script
 
+from UM.Application import Application #To get the current printer's settings.
+
 class FilamentChange(Script):
 
     _layer_keyword = ";LAYER:"
@@ -81,10 +83,51 @@ class FilamentChange(Script):
                     "type": "float",
                     "default_value": 0,
                     "minimum_value": 0
+                },
+                "retract_method":
+                {
+                    "label": "Retract method",
+                    "description": "The gcode variant to use for retract.",
+                    "type": "enum",
+                    "options": {"U": "Marlin (M600 U)", "L": "Reprap (M600 L)"},
+                    "default_value": "U",
+                    "value": "\\\"L\\\" if machine_gcode_flavor==\\\"RepRap (RepRap)\\\" else \\\"U\\\"",
+                    "enabled": "not firmware_config"
+                },                    
+                "machine_gcode_flavor":
+                {
+                    "label": "G-code flavor",
+                    "description": "The type of g-code to be generated. This setting is controlled by the script and will not be visible.",
+                    "type": "enum",
+                    "options":
+                    {
+                        "RepRap (Marlin/Sprinter)": "Marlin",
+                        "RepRap (Volumetric)": "Marlin (Volumetric)",
+                        "RepRap (RepRap)": "RepRap",
+                        "UltiGCode": "Ultimaker 2",
+                        "Griffin": "Griffin",
+                        "Makerbot": "Makerbot",
+                        "BFB": "Bits from Bytes",
+                        "MACH3": "Mach3",
+                        "Repetier": "Repetier"
+                    },
+                    "default_value": "RepRap (Marlin/Sprinter)",
+                    "enabled": "false"
                 }
             }
         }"""
 
+    ##  Copy machine name and gcode flavor from global stack so we can use their value in the script stack
+    def initialize(self) -> None:
+        super().initialize()
+
+        global_container_stack = Application.getInstance().getGlobalContainerStack()
+        if global_container_stack is None or self._instance is None:
+            return
+
+        for key in ["machine_gcode_flavor"]:
+            self._instance.setProperty(key, "value", global_container_stack.getProperty(key, "value"))
+
     def execute(self, data: List[str]):
         """Inserts the filament change g-code at specific layer numbers.
 
@@ -106,7 +149,10 @@ class FilamentChange(Script):
                 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)
+                # Reprap uses 'L': https://reprap.org/wiki/G-code#M600:_Filament_change_pause
+                # Marlin uses 'U' https://marlinfw.org/docs/gcode/M600.html
+                retract_method = self.getSettingValueByKey("retract_method")
+                color_change = color_change + (" %s%.2f" % (retract_method, later_retract))
 
             if x_pos is not None:
                 color_change = color_change + (" X%.2f" % x_pos)

+ 5 - 5
plugins/Toolbox/src/Toolbox.py

@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Ultimaker B.V.
+# Copyright (c) 2021 Ultimaker B.V.
 # Toolbox is released under the terms of the LGPLv3 or higher.
 
 import json
@@ -542,7 +542,7 @@ class Toolbox(QObject, Extension):
     # Make API Calls
     # --------------------------------------------------------------------------
     def _makeRequestByType(self, request_type: str) -> None:
-        Logger.log("d", "Requesting [%s] metadata from server.", request_type)
+        Logger.debug(f"Requesting {request_type} metadata from server.")
         url = self._request_urls[request_type]
 
         callback = lambda r, rt = request_type: self._onDataRequestFinished(rt, r)
@@ -554,7 +554,7 @@ class Toolbox(QObject, Extension):
 
     @pyqtSlot(str)
     def startDownload(self, url: str) -> None:
-        Logger.log("i", "Attempting to download & install package from %s.", url)
+        Logger.info(f"Attempting to download & install package from {url}.")
 
         callback = lambda r: self._onDownloadFinished(r)
         error_callback = lambda r, e: self._onDownloadFailed(r, e)
@@ -572,7 +572,7 @@ class Toolbox(QObject, Extension):
 
     @pyqtSlot()
     def cancelDownload(self) -> None:
-        Logger.log("i", "User cancelled the download of a package. request %s", self._download_request_data)
+        Logger.info(f"User cancelled the download of a package. request {self._download_request_data}")
         if self._download_request_data is not None:
             self._application.getHttpRequestManager().abortRequest(self._download_request_data)
             self._download_request_data = None
@@ -585,7 +585,7 @@ class Toolbox(QObject, Extension):
     # Handlers for Network Events
     # --------------------------------------------------------------------------
     def _onDataRequestError(self, request_type: str, reply: "QNetworkReply", error: "QNetworkReply.NetworkError") -> None:
-        Logger.log("e", "Request [%s] failed due to error [%s]: %s", request_type, error, reply.errorString())
+        Logger.error(f"Request {request_type} failed due to error {error}: {reply.errorString()}")
         self.setViewPage("errored")
 
     def _onDataRequestFinished(self, request_type: str, reply: "QNetworkReply") -> None:

+ 114 - 0
plugins/VersionUpgrade/VersionUpgrade411to412/VersionUpgrade411to412.py

@@ -0,0 +1,114 @@
+# Copyright (c) 2021 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import configparser
+import io
+import os.path
+from typing import List, Tuple
+
+from UM.VersionUpgrade import VersionUpgrade
+
+
+class VersionUpgrade411to412(VersionUpgrade):
+    """
+    Upgrades configurations from the state they were in at version 4.11 to the
+    state they should be in at version 4.12.
+    """
+
+    _flsun_profile_mapping = {
+        "extra_coarse": "flsun_sr_normal",
+        "coarse": "flsun_sr_normal",
+        "extra_fast": "flsun_sr_normal",
+        "draft": "flsun_sr_normal",
+        "fast": "flsun_sr_normal",
+        "normal": "flsun_sr_normal",
+        "high": "flsun_sr_fine"
+    }
+
+    _flsun_quality_type_mapping = {
+        "extra coarse": "normal",
+        "coarse"      : "normal",
+        "verydraft"   : "normal",
+        "draft"       : "normal",
+        "fast"        : "normal",
+        "normal"      : "normal",
+        "high"        : "fine"
+    }
+
+    def upgradePreferences(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+        """
+        Upgrades preferences to have the new version number.
+        :param serialized: The original contents of the preferences file.
+        :param filename: The file name of the preferences file.
+        :return: A list of new file names, and a list of the new contents for
+        those files.
+        """
+        parser = configparser.ConfigParser(interpolation = None)
+        parser.read_string(serialized)
+
+        # Update version number.
+        parser["metadata"]["setting_version"] = "19"
+
+        result = io.StringIO()
+        parser.write(result)
+        return [filename], [result.getvalue()]
+
+
+    def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+        """
+        Upgrades instance containers to have the new version number.
+        :param serialized: The original contents of the instance container.
+        :param filename: The file name of the instance container.
+        :return: A list of file names, and a list of the new contents for those
+        files.
+        """
+        parser = configparser.ConfigParser(interpolation = None, comment_prefixes = ())
+        parser.read_string(serialized)
+
+        # Update setting version number.
+        if "metadata" not in parser:
+            parser["metadata"] = {}
+        parser["metadata"]["setting_version"] = "19"
+
+        # Update user-made quality profiles of flsun_sr printers to use the flsun_sr-specific qualities instead of the
+        # global ones as their base
+        file_base_name = os.path.basename(filename)  # Remove any path-related characters from the filename
+        if file_base_name.startswith("flsun_sr_") and parser["metadata"].get("type") == "quality_changes":
+            if "general" in parser and parser["general"].get("definition") == "fdmprinter":
+                old_quality_type = parser["metadata"].get("quality_type", "normal")
+                parser["general"]["definition"] = "flsun_sr"
+                parser["metadata"]["quality_type"] = self._flsun_quality_type_mapping.get(old_quality_type, "normal")
+
+        result = io.StringIO()
+        parser.write(result)
+        return [filename], [result.getvalue()]
+
+    def upgradeStack(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+        """
+        Upgrades container stacks to have the new version number.
+        Upgrades container stacks for FLSun Racer to change their profiles.
+        :param serialized: The original contents of the container stack.
+        :param filename: The file name of the container stack.
+        :return: A list of file names, and a list of the new contents for those
+        files.
+        """
+        parser = configparser.ConfigParser(interpolation = None)
+        parser.read_string(serialized)
+
+        # Update setting version number.
+        if "metadata" not in parser:
+            parser["metadata"] = {}
+        parser["metadata"]["setting_version"] = "19"
+
+        # Change renamed profiles.
+        if "containers" in parser:
+            definition_id = parser["containers"].get("7")
+            if definition_id == "flsun_sr":
+                if parser["metadata"].get("type", "machine") == "machine":  # Only global stacks.
+                    old_quality = parser["containers"].get("3")
+                    new_quality = self._flsun_profile_mapping.get(old_quality, "flsun_sr_normal")
+                    parser["containers"]["3"] = new_quality
+
+        result = io.StringIO()
+        parser.write(result)
+        return [filename], [result.getvalue()]

+ 56 - 0
plugins/VersionUpgrade/VersionUpgrade411to412/__init__.py

@@ -0,0 +1,56 @@
+# Copyright (c) 2021 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Any, Dict, TYPE_CHECKING
+
+from . import VersionUpgrade411to412
+
+if TYPE_CHECKING:
+    from UM.Application import Application
+
+upgrade = VersionUpgrade411to412.VersionUpgrade411to412()
+
+
+def getMetaData() -> Dict[str, Any]:
+    return {
+        "version_upgrade": {
+            # From                            To                                Upgrade function
+            ("machine_stack",      5000017):  ("machine_stack",      5000019,   upgrade.upgradeStack),
+            ("extruder_train",     5000017):  ("extruder_train",     5000019,   upgrade.upgradeStack),
+            ("definition_changes", 4000017):  ("definition_changes", 4000019,   upgrade.upgradeInstanceContainer),
+            ("quality_changes",    4000017):  ("quality_changes",    4000019,   upgrade.upgradeInstanceContainer),
+            ("quality",            4000017):  ("quality",            4000019,   upgrade.upgradeInstanceContainer),
+            ("user",               4000017):  ("user",               4000019,   upgrade.upgradeInstanceContainer),
+            ("preferences",        7000017):  ("preferences",        7000019,   upgrade.upgradePreferences),
+        },
+        "sources": {
+            "machine_stack": {
+                "get_version": upgrade.getCfgVersion,
+                "location": {"./machine_instances"}
+            },
+            "extruder_train": {
+                "get_version": upgrade.getCfgVersion,
+                "location": {"./extruders"}
+            },
+            "definition_changes": {
+                "get_version": upgrade.getCfgVersion,
+                "location": {"./definition_changes"}
+            },
+            "quality_changes": {
+                "get_version": upgrade.getCfgVersion,
+                "location": {"./quality_changes"}
+            },
+            "quality": {
+                "get_version": upgrade.getCfgVersion,
+                "location": {"./quality"}
+            },
+            "user": {
+                "get_version": upgrade.getCfgVersion,
+                "location": {"./user"}
+            }
+        }
+    }
+
+
+def register(app: "Application") -> Dict[str, Any]:
+    return {"version_upgrade": upgrade}

+ 8 - 0
plugins/VersionUpgrade/VersionUpgrade411to412/plugin.json

@@ -0,0 +1,8 @@
+{
+    "name": "Version Upgrade 4.11 to 4.12",
+    "author": "Ultimaker B.V.",
+    "version": "1.0.0",
+    "description": "Upgrades configurations from Cura 4.11 to Cura 4.12.",
+    "api": 7,
+    "i18n-catalog": "cura"
+}

+ 20 - 18
requirements.txt

@@ -1,36 +1,38 @@
-cffi==1.14.1
-colorlog
-cryptography==3.4.6
-importlib-metadata==3.7.2
-mypy==0.740
-numpy==1.20.2
-PyQt5==5.15.2
-PyQt5-sip==12.8.1
-scipy==1.6.1
-shapely[vectorized]==1.7.1
-twisted==21.2.0
-typing
 appdirs==1.4.3
 certifi==2019.11.28
+cffi==1.14.1
 chardet==3.0.4
+colorlog
+comtypes==1.1.7
+cryptography==3.4.8
 decorator==4.4.0
 idna==2.8
+importlib-metadata==3.7.2
+keyring==23.0.1
+lxml==4.6.3
+mypy==0.740
 netifaces==0.10.9
-networkx==2.3
+networkx==2.6.2
+numpy==1.20.2
 numpy-stl==2.10.1
 packaging==18.0
 pycollada==0.6
-pycparser==2.19
+pycparser==2.20
 pyparsing==2.4.2
+PyQt5==5.15.2
+PyQt5-sip==12.8.1
 pyserial==3.4
 pytest
 python-dateutil==2.8.0
 python-utils==2.3.0
+pywin32==301
 requests==2.22.0
+scipy==1.6.2
 sentry-sdk==0.13.5
+shapely[vectorized]==1.7.1
 six==1.12.0
 trimesh==3.2.33
-zeroconf==0.24.1
-comtypes==1.1.7
-pywin32==300
-keyring==23.0.1
+twisted==21.2.0
+typing
+urllib3==1.25.9
+zeroconf==0.31.0

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