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
This commit is contained in:
fieldOfView 2017-12-31 10:53:53 +01:00
parent 80ba5fc97d
commit 7a0b49ca2f

View file

@ -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():