Browse Source

Allow specifying the extruder stack to use for each replacement pattern

The replacement pattern is (optionally) extended with an extruder_nr: {setting_key,extruder_nr}. The extruder_nr can either be a number (-1 for the global stack, 0 or higher for an extruder), or a setting keyword such as support_extruder_nr etc.

Contributes to #1296
fieldOfView 7 years ago
parent
commit
7a0b49ca2f
1 changed files with 45 additions and 10 deletions
  1. 45 10
      plugins/CuraEngineBackend/StartSliceJob.py

+ 45 - 10
plugins/CuraEngineBackend/StartSliceJob.py

@@ -36,9 +36,32 @@ class StartJobResult(IntEnum):
 ##  Formatter class that handles token expansion in start/end gcod
 class GcodeStartEndFormatter(Formatter):
     def get_value(self, key, args, kwargs):  # [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
+
         if isinstance(key, str):
             try:
-                return kwargs[key]
+                extruder_nr = kwargs["default_extruder_nr"]
+            except ValueError:
+                extruder_nr = -1
+
+            key_fragments = [fragment.strip() for fragment in key.split(',')]
+            if len(key_fragments) == 2:
+                try:
+                    extruder_nr = int(key_fragments[1])
+                except ValueError:
+                    try:
+                        extruder_nr = int(kwargs["-1"][key_fragments[1]]) # get extruder_nr values from the global stack
+                    except (KeyError, ValueError):
+                        # either the key does not exist, or the value is not an int
+                        Logger.log("w", "Unable to determine stack nr '%s' for key '%s' in start/end gcode, using global stack", key_fragments[1], key_fragments[0])
+            elif len(key_fragments) != 1:
+                Logger.log("w", "Incorrectly formatted placeholder '%s' in start/end gcode", key)
+                return "{" + str(key) + "}"
+
+            key = key_fragments[0]
+            try:
+                return kwargs[str(extruder_nr)][key]
             except KeyError:
                 Logger.log("w", "Unable to replace '%s' placeholder in start/end gcode", key)
                 return "{" + key + "}"
@@ -56,6 +79,8 @@ class StartSliceJob(Job):
         self._slice_message = slice_message
         self._is_cancelled = False
 
+        self._all_extruders_settings = None # cache for all setting values from all stacks (global & extruder) for the current machine
+
     def getSliceMessage(self):
         return self._slice_message
 
@@ -237,12 +262,21 @@ class StartSliceJob(Job):
 
     ##  Replace setting tokens in a piece of g-code.
     #   \param value A piece of g-code to replace tokens in.
-    #   \param settings A dictionary of tokens to replace and their respective
-    #   replacement strings.
-    def _expandGcodeTokens(self, value: str, settings: dict):
+    #   \param default_extruder_nr Stack nr to use when no stack nr is specified, defaults to the global stack
+    def _expandGcodeTokens(self, value: str, default_extruder_nr: int = -1):
+        if not self._all_extruders_settings:
+            global_stack = Application.getInstance().getGlobalContainerStack()
+            self._all_extruders_settings = {}
+            # keys must be strings for the string formatter
+            self._all_extruders_settings["-1"] = self._buildReplacementTokens(global_stack)
+            for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()):
+                extruder_nr = extruder_stack.getProperty("extruder_nr", "value")
+                self._all_extruders_settings[str(extruder_nr)] = self._buildReplacementTokens(extruder_stack)
         try:
             # any setting can be used as a token
             fmt = GcodeStartEndFormatter()
+            settings = self._all_extruders_settings.copy()
+            settings["default_extruder_nr"] = default_extruder_nr
             return str(fmt.format(value, **settings))
         except:
             Logger.logException("w", "Unable to do token replacement on start/end gcode")
@@ -259,8 +293,9 @@ class StartSliceJob(Job):
         settings["material_guid"] = stack.material.getMetaDataEntry("GUID", "")
 
         # Replace the setting tokens in start and end g-code.
-        settings["machine_extruder_start_code"] = self._expandGcodeTokens(settings["machine_extruder_start_code"], settings)
-        settings["machine_extruder_end_code"] = self._expandGcodeTokens(settings["machine_extruder_end_code"], settings)
+        extruder_nr = stack.getProperty("extruder_nr", "value")
+        settings["machine_extruder_start_code"] = self._expandGcodeTokens(settings["machine_extruder_start_code"], extruder_nr)
+        settings["machine_extruder_end_code"] = self._expandGcodeTokens(settings["machine_extruder_end_code"], extruder_nr)
 
         for key, value in settings.items():
             # Do not send settings that are not settable_per_extruder.
@@ -286,12 +321,12 @@ class StartSliceJob(Job):
         settings["material_print_temp_prepend"] = all(("{" + setting + "}" not in start_gcode for setting in print_temperature_settings))
 
         # Find the correct temperatures from the first used extruder
-        extruder_stack = Application.getInstance().getExtruderManager().getUsedExtruderStacks()[0]
-        extruder_0_settings = self._buildReplacementTokens(extruder_stack)
+        initial_extruder_stack = Application.getInstance().getExtruderManager().getUsedExtruderStacks()[0]
+        initial_extruder_nr = initial_extruder_stack.getProperty("extruder_nr", "value")
 
         # Replace the setting tokens in start and end g-code.
-        settings["machine_start_gcode"] = self._expandGcodeTokens(settings["machine_start_gcode"], extruder_0_settings)
-        settings["machine_end_gcode"] = self._expandGcodeTokens(settings["machine_end_gcode"], extruder_0_settings)
+        settings["machine_start_gcode"] = self._expandGcodeTokens(settings["machine_start_gcode"], initial_extruder_nr)
+        settings["machine_end_gcode"] = self._expandGcodeTokens(settings["machine_end_gcode"], initial_extruder_nr)
 
         # Add all sub-messages for each individual setting.
         for key, value in settings.items():