From bcc12030a2f2d6cbca6c34e166d4b25cb089d611 Mon Sep 17 00:00:00 2001 From: novamxd Date: Fri, 3 Jan 2020 19:01:33 -0600 Subject: [PATCH] Revamped ChangeAtZ Adjusted coding style to use spaces instead of tabs --- .../PostProcessingPlugin/scripts/ChangeAtZ.py | 1473 ++++++++--------- 1 file changed, 736 insertions(+), 737 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py b/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py index 52e8096a7f..f37676a28c 100644 --- a/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py +++ b/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py @@ -52,935 +52,934 @@ import re # this was broken up into a separate class so the main ChangeZ script could be debugged outside of Cura class ChangeAtZ(Script): + version = "5.2.0" - version = "5.2.0" + def getSettingDataString(self): + return """{ + "name": "ChangeAtZ """ + self.version + """(Experimental)", + "key": "ChangeAtZ", + "metadata": {}, + "version": 2, + "settings": { + "a_trigger": { + "label": "Trigger", + "description": "Trigger at height or at layer no.", + "type": "enum", + "options": { + "height": "Height", + "layer_no": "Layer No." + }, + "default_value": "height" + }, + "b_targetZ": { + "label": "Change Height", + "description": "Z height to change at", + "unit": "mm", + "type": "float", + "default_value": 5.0, + "minimum_value": "0", + "minimum_value_warning": "0.1", + "maximum_value_warning": "230", + "enabled": "a_trigger == 'height'" + }, + "b_targetL": { + "label": "Change Layer", + "description": "Layer no. to change at", + "unit": "", + "type": "int", + "default_value": 1, + "minimum_value": "-100", + "minimum_value_warning": "-1", + "enabled": "a_trigger == 'layer_no'" + }, + "c_behavior": { + "label": "Behavior", + "description": "Select behavior: Change value and keep it for the rest, Change value for single layer only", + "type": "enum", + "options": { + "keep_value": "Keep value", + "single_layer": "Single Layer" + }, + "default_value": "keep_value" + }, + "e1_Change_speed": { + "label": "Change Speed", + "description": "Select if total speed (print and travel) has to be changed", + "type": "bool", + "default_value": false + }, + "e2_speed": { + "label": "Speed", + "description": "New total speed (print and travel)", + "unit": "%", + "type": "int", + "default_value": 100, + "minimum_value": "1", + "minimum_value_warning": "10", + "maximum_value_warning": "200", + "enabled": "e1_Change_speed" + }, + "f1_Change_printspeed": { + "label": "Change Print Speed", + "description": "Select if print speed has to be changed", + "type": "bool", + "default_value": false + }, + "f2_printspeed": { + "label": "Print Speed", + "description": "New print speed", + "unit": "%", + "type": "int", + "default_value": 100, + "minimum_value": "1", + "minimum_value_warning": "10", + "maximum_value_warning": "200", + "enabled": "f1_Change_printspeed" + }, + "g1_Change_flowrate": { + "label": "Change Flow Rate", + "description": "Select if flow rate has to be changed", + "type": "bool", + "default_value": false + }, + "g2_flowrate": { + "label": "Flow Rate", + "description": "New Flow rate", + "unit": "%", + "type": "int", + "default_value": 100, + "minimum_value": "1", + "minimum_value_warning": "10", + "maximum_value_warning": "200", + "enabled": "g1_Change_flowrate" + }, + "g3_Change_flowrateOne": { + "label": "Change Flow Rate 1", + "description": "Select if first extruder flow rate has to be changed", + "type": "bool", + "default_value": false + }, + "g4_flowrateOne": { + "label": "Flow Rate One", + "description": "New Flow rate Extruder 1", + "unit": "%", + "type": "int", + "default_value": 100, + "minimum_value": "1", + "minimum_value_warning": "10", + "maximum_value_warning": "200", + "enabled": "g3_Change_flowrateOne" + }, + "g5_Change_flowrateTwo": { + "label": "Change Flow Rate 2", + "description": "Select if second extruder flow rate has to be changed", + "type": "bool", + "default_value": false + }, + "g6_flowrateTwo": { + "label": "Flow Rate two", + "description": "New Flow rate Extruder 2", + "unit": "%", + "type": "int", + "default_value": 100, + "minimum_value": "1", + "minimum_value_warning": "10", + "maximum_value_warning": "200", + "enabled": "g5_Change_flowrateTwo" + }, + "h1_Change_bedTemp": { + "label": "Change Bed Temp", + "description": "Select if Bed Temperature has to be changed", + "type": "bool", + "default_value": false + }, + "h2_bedTemp": { + "label": "Bed Temp", + "description": "New Bed Temperature", + "unit": "C", + "type": "float", + "default_value": 60, + "minimum_value": "0", + "minimum_value_warning": "30", + "maximum_value_warning": "120", + "enabled": "h1_Change_bedTemp" + }, + "i1_Change_extruderOne": { + "label": "Change Extruder 1 Temp", + "description": "Select if First Extruder Temperature has to be changed", + "type": "bool", + "default_value": false + }, + "i2_extruderOne": { + "label": "Extruder 1 Temp", + "description": "New First Extruder Temperature", + "unit": "C", + "type": "float", + "default_value": 190, + "minimum_value": "0", + "minimum_value_warning": "160", + "maximum_value_warning": "250", + "enabled": "i1_Change_extruderOne" + }, + "i3_Change_extruderTwo": { + "label": "Change Extruder 2 Temp", + "description": "Select if Second Extruder Temperature has to be changed", + "type": "bool", + "default_value": false + }, + "i4_extruderTwo": { + "label": "Extruder 2 Temp", + "description": "New Second Extruder Temperature", + "unit": "C", + "type": "float", + "default_value": 190, + "minimum_value": "0", + "minimum_value_warning": "160", + "maximum_value_warning": "250", + "enabled": "i3_Change_extruderTwo" + }, + "j1_Change_fanSpeed": { + "label": "Change Fan Speed", + "description": "Select if Fan Speed has to be changed", + "type": "bool", + "default_value": false + }, + "j2_fanSpeed": { + "label": "Fan Speed", + "description": "New Fan Speed (0-100)", + "unit": "%", + "type": "int", + "default_value": 100, + "minimum_value": "0", + "minimum_value_warning": "0", + "maximum_value_warning": "100", + "enabled": "j1_Change_fanSpeed" + }, + "caz_change_retractfeedrate": { + "label": "Change Retract Feed Rate", + "description": "Changes the retraction feed rate during print (M207)", + "type": "bool", + "default_value": false + }, + "caz_retractfeedrate": { + "label": "Retract Feed Rate", + "description": "New Retract Feed Rate (units/s)", + "unit": "units/s", + "type": "float", + "default_value": 40, + "minimum_value": "0", + "minimum_value_warning": "0", + "maximum_value_warning": "100", + "enabled": "caz_change_retractfeedrate" + }, + "caz_change_retractlength": { + "label": "Change Retract Length", + "description": "Changes the retraction length during print (M207)", + "type": "bool", + "default_value": false + }, + "caz_retractlength": { + "label": "Retract Length", + "description": "New Retract Length (units)", + "unit": "units", + "type": "float", + "default_value": 6, + "minimum_value": "0", + "minimum_value_warning": "0", + "maximum_value_warning": "20", + "enabled": "caz_change_retractlength" + } + } + }""" - def getSettingDataString(self): - return """{ - "name": "ChangeAtZ """ + self.version + """(Experimental)", - "key": "ChangeAtZ", - "metadata": {}, - "version": 2, - "settings": { - "a_trigger": { - "label": "Trigger", - "description": "Trigger at height or at layer no.", - "type": "enum", - "options": { - "height": "Height", - "layer_no": "Layer No." - }, - "default_value": "height" - }, - "b_targetZ": { - "label": "Change Height", - "description": "Z height to change at", - "unit": "mm", - "type": "float", - "default_value": 5.0, - "minimum_value": "0", - "minimum_value_warning": "0.1", - "maximum_value_warning": "230", - "enabled": "a_trigger == 'height'" - }, - "b_targetL": { - "label": "Change Layer", - "description": "Layer no. to change at", - "unit": "", - "type": "int", - "default_value": 1, - "minimum_value": "-100", - "minimum_value_warning": "-1", - "enabled": "a_trigger == 'layer_no'" - }, - "c_behavior": { - "label": "Behavior", - "description": "Select behavior: Change value and keep it for the rest, Change value for single layer only", - "type": "enum", - "options": { - "keep_value": "Keep value", - "single_layer": "Single Layer" - }, - "default_value": "keep_value" - }, - "e1_Change_speed": { - "label": "Change Speed", - "description": "Select if total speed (print and travel) has to be changed", - "type": "bool", - "default_value": false - }, - "e2_speed": { - "label": "Speed", - "description": "New total speed (print and travel)", - "unit": "%", - "type": "int", - "default_value": 100, - "minimum_value": "1", - "minimum_value_warning": "10", - "maximum_value_warning": "200", - "enabled": "e1_Change_speed" - }, - "f1_Change_printspeed": { - "label": "Change Print Speed", - "description": "Select if print speed has to be changed", - "type": "bool", - "default_value": false - }, - "f2_printspeed": { - "label": "Print Speed", - "description": "New print speed", - "unit": "%", - "type": "int", - "default_value": 100, - "minimum_value": "1", - "minimum_value_warning": "10", - "maximum_value_warning": "200", - "enabled": "f1_Change_printspeed" - }, - "g1_Change_flowrate": { - "label": "Change Flow Rate", - "description": "Select if flow rate has to be changed", - "type": "bool", - "default_value": false - }, - "g2_flowrate": { - "label": "Flow Rate", - "description": "New Flow rate", - "unit": "%", - "type": "int", - "default_value": 100, - "minimum_value": "1", - "minimum_value_warning": "10", - "maximum_value_warning": "200", - "enabled": "g1_Change_flowrate" - }, - "g3_Change_flowrateOne": { - "label": "Change Flow Rate 1", - "description": "Select if first extruder flow rate has to be changed", - "type": "bool", - "default_value": false - }, - "g4_flowrateOne": { - "label": "Flow Rate One", - "description": "New Flow rate Extruder 1", - "unit": "%", - "type": "int", - "default_value": 100, - "minimum_value": "1", - "minimum_value_warning": "10", - "maximum_value_warning": "200", - "enabled": "g3_Change_flowrateOne" - }, - "g5_Change_flowrateTwo": { - "label": "Change Flow Rate 2", - "description": "Select if second extruder flow rate has to be changed", - "type": "bool", - "default_value": false - }, - "g6_flowrateTwo": { - "label": "Flow Rate two", - "description": "New Flow rate Extruder 2", - "unit": "%", - "type": "int", - "default_value": 100, - "minimum_value": "1", - "minimum_value_warning": "10", - "maximum_value_warning": "200", - "enabled": "g5_Change_flowrateTwo" - }, - "h1_Change_bedTemp": { - "label": "Change Bed Temp", - "description": "Select if Bed Temperature has to be changed", - "type": "bool", - "default_value": false - }, - "h2_bedTemp": { - "label": "Bed Temp", - "description": "New Bed Temperature", - "unit": "C", - "type": "float", - "default_value": 60, - "minimum_value": "0", - "minimum_value_warning": "30", - "maximum_value_warning": "120", - "enabled": "h1_Change_bedTemp" - }, - "i1_Change_extruderOne": { - "label": "Change Extruder 1 Temp", - "description": "Select if First Extruder Temperature has to be changed", - "type": "bool", - "default_value": false - }, - "i2_extruderOne": { - "label": "Extruder 1 Temp", - "description": "New First Extruder Temperature", - "unit": "C", - "type": "float", - "default_value": 190, - "minimum_value": "0", - "minimum_value_warning": "160", - "maximum_value_warning": "250", - "enabled": "i1_Change_extruderOne" - }, - "i3_Change_extruderTwo": { - "label": "Change Extruder 2 Temp", - "description": "Select if Second Extruder Temperature has to be changed", - "type": "bool", - "default_value": false - }, - "i4_extruderTwo": { - "label": "Extruder 2 Temp", - "description": "New Second Extruder Temperature", - "unit": "C", - "type": "float", - "default_value": 190, - "minimum_value": "0", - "minimum_value_warning": "160", - "maximum_value_warning": "250", - "enabled": "i3_Change_extruderTwo" - }, - "j1_Change_fanSpeed": { - "label": "Change Fan Speed", - "description": "Select if Fan Speed has to be changed", - "type": "bool", - "default_value": false - }, - "j2_fanSpeed": { - "label": "Fan Speed", - "description": "New Fan Speed (0-100)", - "unit": "%", - "type": "int", - "default_value": 100, - "minimum_value": "0", - "minimum_value_warning": "0", - "maximum_value_warning": "100", - "enabled": "j1_Change_fanSpeed" - }, - "caz_change_retractfeedrate": { - "label": "Change Retract Feed Rate", - "description": "Changes the retraction feed rate during print (M207)", - "type": "bool", - "default_value": false - }, - "caz_retractfeedrate": { - "label": "Retract Feed Rate", - "description": "New Retract Feed Rate (units/s)", - "unit": "units/s", - "type": "float", - "default_value": 40, - "minimum_value": "0", - "minimum_value_warning": "0", - "maximum_value_warning": "100", - "enabled": "caz_change_retractfeedrate" - }, - "caz_change_retractlength": { - "label": "Change Retract Length", - "description": "Changes the retraction length during print (M207)", - "type": "bool", - "default_value": false - }, - "caz_retractlength": { - "label": "Retract Length", - "description": "New Retract Length (units)", - "unit": "units", - "type": "float", - "default_value": 6, - "minimum_value": "0", - "minimum_value_warning": "0", - "maximum_value_warning": "20", - "enabled": "caz_change_retractlength" - } - } - }""" + def __init__(self): + super().__init__() - def __init__(self): - super().__init__() + def execute(self, data): - def execute(self, data): + caz_instance = ChangeAtZProcessor() - caz_instance = ChangeAtZProcessor() + caz_instance.TargetValues = {} - caz_instance.TargetValues = {} + # copy over our settings to our change z class + self.setIntSettingIfEnabled(caz_instance, "e1_Change_speed", "speed", "e2_speed") + self.setIntSettingIfEnabled(caz_instance, "f1_Change_printspeed", "printspeed", "f2_printspeed") + self.setIntSettingIfEnabled(caz_instance, "g1_Change_flowrate", "flowrate", "g2_flowrate") + self.setIntSettingIfEnabled(caz_instance, "g3_Change_flowrateOne", "flowrateOne", "g4_flowrateOne") + self.setIntSettingIfEnabled(caz_instance, "g5_Change_flowrateTwo", "flowrateTwo", "g6_flowrateTwo") + self.setFloatSettingIfEnabled(caz_instance, "h1_Change_bedTemp", "bedTemp", "h2_bedTemp") + self.setFloatSettingIfEnabled(caz_instance, "i1_Change_extruderOne", "extruderOne", "i2_extruderOne") + self.setFloatSettingIfEnabled(caz_instance, "i3_Change_extruderTwo", "extruderTwo", "i4_extruderTwo") + self.setIntSettingIfEnabled(caz_instance, "j1_Change_fanSpeed", "fanSpeed", "j2_fanSpeed") + self.setFloatSettingIfEnabled(caz_instance, "caz_change_retractfeedrate", "retractfeedrate", "caz_retractfeedrate") + self.setFloatSettingIfEnabled(caz_instance, "caz_change_retractlength", "retractlength", "caz_retractlength") - # copy over our settings to our change z class - self.setIntSettingIfEnabled(caz_instance, "e1_Change_speed", "speed", "e2_speed") - self.setIntSettingIfEnabled(caz_instance, "f1_Change_printspeed", "printspeed", "f2_printspeed") - self.setIntSettingIfEnabled(caz_instance, "g1_Change_flowrate", "flowrate", "g2_flowrate") - self.setIntSettingIfEnabled(caz_instance, "g3_Change_flowrateOne", "flowrateOne", "g4_flowrateOne") - self.setIntSettingIfEnabled(caz_instance, "g5_Change_flowrateTwo", "flowrateTwo", "g6_flowrateTwo") - self.setFloatSettingIfEnabled(caz_instance, "h1_Change_bedTemp", "bedTemp", "h2_bedTemp") - self.setFloatSettingIfEnabled(caz_instance, "i1_Change_extruderOne", "extruderOne", "i2_extruderOne") - self.setFloatSettingIfEnabled(caz_instance, "i3_Change_extruderTwo", "extruderTwo", "i4_extruderTwo") - self.setIntSettingIfEnabled(caz_instance, "j1_Change_fanSpeed", "fanSpeed", "j2_fanSpeed") - self.setFloatSettingIfEnabled(caz_instance, "caz_change_retractfeedrate", "retractfeedrate", "caz_retractfeedrate") - self.setFloatSettingIfEnabled(caz_instance, "caz_change_retractlength", "retractlength", "caz_retractlength") + # see if we're applying to a single layer or to all layers hence forth + caz_instance.IsApplyToSingleLayer = self.getSettingValueByKey("c_behavior") == "single_layer" - # see if we're applying to a single layer or to all layers hence forth - caz_instance.IsApplyToSingleLayer = self.getSettingValueByKey("c_behavior") == "single_layer" + # used for easy reference of layer or height targeting + caz_instance.IsTargetByLayer = self.getSettingValueByKey("a_trigger") == "layer_no" - # used for easy reference of layer or height targeting - caz_instance.IsTargetByLayer = self.getSettingValueByKey("a_trigger") == "layer_no" + # change our target based on what we're targeting + caz_instance.TargetLayer = self.getIntSettingByKey("b_targetL", None) + caz_instance.TargetZ = self.getFloatSettingByKey("b_targetZ", None) - # change our target based on what we're targeting - caz_instance.TargetLayer = self.getIntSettingByKey("b_targetL", None) - caz_instance.TargetZ = self.getFloatSettingByKey("b_targetZ", None) + # run our script + return caz_instance.execute(data) - # run our script - return caz_instance.execute(data) + # Sets the given TargetValue in the ChangeAtZ instance if the trigger is specified + def setIntSettingIfEnabled(self, caz_instance, trigger, target, setting): - # Sets the given TargetValue in the ChangeAtZ instance if the trigger is specified - def setIntSettingIfEnabled(self, caz_instance, trigger, target, setting): + # stop here if our trigger isn't enabled + if not self.getSettingValueByKey(trigger): + return - # stop here if our trigger isn't enabled - if not self.getSettingValueByKey(trigger): - return + # get our value from the settings + value = self.getIntSettingByKey(setting, None) - # get our value from the settings - value = self.getIntSettingByKey(setting, None) + # skip if there's no value or we can't interpret it + if value is None: + return - # skip if there's no value or we can't interpret it - if value is None: - return + # set our value in the target settings + caz_instance.TargetValues[target] = value - # set our value in the target settings - caz_instance.TargetValues[target] = value + # Sets the given TargetValue in the ChangeAtZ instance if the trigger is specified + def setFloatSettingIfEnabled(self, caz_instance, trigger, target, setting): - # Sets the given TargetValue in the ChangeAtZ instance if the trigger is specified - def setFloatSettingIfEnabled(self, caz_instance, trigger, target, setting): + # stop here if our trigger isn't enabled + if not self.getSettingValueByKey(trigger): + return - # stop here if our trigger isn't enabled - if not self.getSettingValueByKey(trigger): - return + # get our value from the settings + value = self.getFloatSettingByKey(setting, None) - # get our value from the settings - value = self.getFloatSettingByKey(setting, None) + # skip if there's no value or we can't interpret it + if value is None: + return - # skip if there's no value or we can't interpret it - if value is None: - return + # set our value in the target settings + caz_instance.TargetValues[target] = value - # set our value in the target settings - caz_instance.TargetValues[target] = value + # Returns the given settings value as an integer or the default if it cannot parse it + def getIntSettingByKey(self, key, default): - # Returns the given settings value as an integer or the default if it cannot parse it - def getIntSettingByKey(self, key, default): + # change our target based on what we're targeting + try: + return int(self.getSettingValueByKey(key)) + except: + return default - # change our target based on what we're targeting - try: - return int(self.getSettingValueByKey(key)) - except: - return default + # Returns the given settings value as an integer or the default if it cannot parse it + def getFloatSettingByKey(self, key, default): - # Returns the given settings value as an integer or the default if it cannot parse it - def getFloatSettingByKey(self, key, default): + # change our target based on what we're targeting + try: + return float(self.getSettingValueByKey(key)) + except: + return default - # change our target based on what we're targeting - try: - return float(self.getSettingValueByKey(key)) - except: - return default # The primary ChangeAtZ class that does all the gcode editing. This was broken out into an # independent class so it could be debugged using a standard IDE class ChangeAtZProcessor: + TargetValues = {} + IsApplyToSingleLayer = False + LastE = None + CurrentZ = None + CurrentLayer = None + IsTargetByLayer = True + TargetLayer = None + TargetZ = None + LayerHeight = None + RetractLength = 0 - TargetValues = {} - IsApplyToSingleLayer = False - LastE = None - CurrentZ = None - CurrentLayer = None - IsTargetByLayer = True - TargetLayer = None - TargetZ = None - LayerHeight = None - RetractLength = 0 + # boots up the class with defaults + def __init__(self): + self.reset() - # boots up the class with defaults - def __init__(self): - self.reset() + # Modifies the given GCODE and injects the commands at the various targets + def execute(self, data): - # Modifies the given GCODE and injects the commands at the various targets - def execute(self, data): + # indicates if we should inject our defaults or not + inject_defaults = True - # indicates if we should inject our defaults or not - inject_defaults = True + # our layer cursor + index = 0 - # our layer cursor - index = 0 + for active_layer in data: - for active_layer in data: + # will hold our updated gcode + modified_gcode = "" - # will hold our updated gcode - modified_gcode = "" + # mark all the defaults for deletion + active_layer = self.markDefaultsForDeletion(active_layer) - # mark all the defaults for deletion - active_layer = self.markDefaultsForDeletion(active_layer) + # break apart the layer into commands + lines = active_layer.split("\n") - # break apart the layer into commands - lines = active_layer.split("\n") + # evaluate each command individually + for line in lines: - # evaluate each command individually - for line in lines: + # skip empty lines + if line.strip() == "": + continue - # skip empty lines - if line.strip() == "": - continue + # update our layer number if applicable + self.processLayerNumber(line) - # update our layer number if applicable - self.processLayerNumber(line) + # update our layer height if applicable + self.processLayerHeight(line) - # update our layer height if applicable - self.processLayerHeight(line) + # skip this line if we're not there yet + if not self.isTargetLayerOrHeight(): - # skip this line if we're not there yet - if not self.isTargetLayerOrHeight(): + # read any settings we might need + self.processSetting(line) - # read any settings we might need - self.processSetting(line) + # if we haven't hit our target yet, leave the defaults as is (unmark them for deletion) + if "[CAZD:DELETE:" in line: + line = line.replace("[CAZD:DELETE:", "[CAZD:") - # if we haven't hit our target yet, leave the defaults as is (unmark them for deletion) - if "[CAZD:DELETE:" in line: - line = line.replace("[CAZD:DELETE:", "[CAZD:") + # set our line + modified_gcode += line + "\n" - # set our line - modified_gcode += line + "\n" + # skip to the next line + continue - # skip to the next line - continue + # inject our defaults before linear motion commands + if inject_defaults and ("G1" in line or "G0" in line): - # inject our defaults before linear motion commands - if inject_defaults and ("G1" in line or "G0" in line): + # inject the defaults + modified_gcode += self.getTargetDefaults() + "\n" - # inject the defaults - modified_gcode += self.getTargetDefaults() + "\n" + # mark that we've injected the defaults + inject_defaults = False - # mark that we've injected the defaults - inject_defaults = False + # append to our modified layer + modified_gcode += self.processLinearMove(line) + "\n" - # append to our modified layer - modified_gcode += self.processLinearMove(line) + "\n" + # inject our defaults after the layer indicator + if inject_defaults and ";LAYER:" in line: - # inject our defaults after the layer indicator - if inject_defaults and ";LAYER:" in line: + # inject the defaults + modified_gcode += self.getTargetDefaults() + "\n" - # inject the defaults - modified_gcode += self.getTargetDefaults() + "\n" + # mark that we've injected the defaults + inject_defaults = False - # mark that we've injected the defaults - inject_defaults = False + # remove any marked defaults + modified_gcode = self.removeMarkedTargetDefaults(modified_gcode) - # remove any marked defaults - modified_gcode = self.removeMarkedTargetDefaults(modified_gcode) + # append our modified line + data[index] = modified_gcode - # append our modified line - data[index] = modified_gcode + index += 1 + return data - index += 1 - return data + # Converts the command parameter to a float or returns the default + @staticmethod + def getFloatValue(line, key, default=None): - # Converts the command parameter to a float or returns the default - @staticmethod - def getFloatValue(line, key, default=None): + # get the value from the command + value = ChangeAtZProcessor.getValue(line, key, default) - # get the value from the command - value = ChangeAtZProcessor.getValue(line, key, default) + # stop here if it's the default + if value == default: + return value - # stop here if it's the default - if value == default: - return value + try: + return float(value) + except: + return default - try: - return float(value) - except: - return default + # Converts the command parameter to a int or returns the default + @staticmethod + def getIntValue(line, key, default=None): - # Converts the command parameter to a int or returns the default - @staticmethod - def getIntValue(line, key, default=None): + # get the value from the command + value = ChangeAtZProcessor.getValue(line, key, default) - # get the value from the command - value = ChangeAtZProcessor.getValue(line, key, default) + # stop here if it's the default + if value == default: + return value - # stop here if it's the default - if value == default: - return value + try: + return int(value) + except: + return default - try: - return int(value) - except: - return default + # Handy function for reading a linear move command + def getLinearMoveParams(self, line): - # Handy function for reading a linear move command - def getLinearMoveParams(self, line): + # get our motion parameters + feed_rate = self.getFloatValue(line, "F", None) + x_coord = self.getFloatValue(line, "X", None) + y_coord = self.getFloatValue(line, "Y", None) + z_coord = self.getFloatValue(line, "Z", None) + extrude_length = self.getFloatValue(line, "E", None) - # get our motion parameters - feed_rate = self.getFloatValue(line, "F", None) - x_coord = self.getFloatValue(line, "X", None) - y_coord = self.getFloatValue(line, "Y", None) - z_coord = self.getFloatValue(line, "Z", None) - extrude_length = self.getFloatValue(line, "E", None) + return extrude_length, feed_rate, x_coord, y_coord, z_coord - return extrude_length, feed_rate, x_coord, y_coord, z_coord + # Returns the unmodified GCODE line from previous ChangeZ edits + @staticmethod + def getOriginalLine(line): - # Returns the unmodified GCODE line from previous ChangeZ edits - @staticmethod - def getOriginalLine(line): + # get the change at z original (cazo) details + original_line = re.search(r"\[CAZO:(.*?):CAZO\]", line) - # get the change at z original (cazo) details - original_line = re.search(r"\[CAZO:(.*?):CAZO\]", line) + # if we didn't get a hit, this is the original line + if original_line is None: + return line - # if we didn't get a hit, this is the original line - if original_line is None: - return line + return original_line.group(1) - return original_line.group(1) + # Builds the layer defaults based on the settings and returns the relevant GCODE lines + def getTargetDefaults(self): - # Builds the layer defaults based on the settings and returns the relevant GCODE lines - def getTargetDefaults(self): + # will hold all the default settings for the target layer + defaults = [] - # will hold all the default settings for the target layer - defaults = [] + # used to trim other defaults + defaults.append(";[CAZD:") - # used to trim other defaults - defaults.append(";[CAZD:") + # looking for wait for bed temp + if "bedTemp" in self.TargetValues: + defaults.append("M190 S" + str(self.TargetValues["bedTemp"])) - # looking for wait for bed temp - if "bedTemp" in self.TargetValues: - defaults.append("M190 S" + str(self.TargetValues["bedTemp"])) + # set our extruder one temp (if specified) + if "extruderOne" in self.TargetValues: + defaults.append("M109 S" + str(self.TargetValues["extruderOne"]) + " T0") - # set our extruder one temp (if specified) - if "extruderOne" in self.TargetValues: - defaults.append("M109 S" + str(self.TargetValues["extruderOne"]) + " T0") + # set our extruder two temp (if specified) + if "extruderTwo" in self.TargetValues: + defaults.append("M109 S" + str(self.TargetValues["extruderTwo"]) + " T1") - # set our extruder two temp (if specified) - if "extruderTwo" in self.TargetValues: - defaults.append("M109 S" + str(self.TargetValues["extruderTwo"]) + " T1") + # set our fan speed + if "fanSpeed" in self.TargetValues: - # set our fan speed - if "fanSpeed" in self.TargetValues: + # convert our fan speed percentage to PWM + fan_speed = int((float(self.TargetValues["fanSpeed"]) / 100.0) * 255) - # convert our fan speed percentage to PWM - fan_speed = int((float(self.TargetValues["fanSpeed"]) / 100.0) * 255) + # add our fan speed to the defaults + defaults.append("M106 S" + str(fan_speed)) - # add our fan speed to the defaults - defaults.append("M106 S" + str(fan_speed)) + # set global flow rate + if "flowrate" in self.TargetValues: + defaults.append("M221 S" + str(self.TargetValues["flowrate"])) - # set global flow rate - if "flowrate" in self.TargetValues: - defaults.append("M221 S" + str(self.TargetValues["flowrate"])) + # set extruder 0 flow rate + if "flowrateOne" in self.TargetValues: + defaults.append("M221 S" + str(self.TargetValues["flowrateOne"]) + " T0") - # set extruder 0 flow rate - if "flowrateOne" in self.TargetValues: - defaults.append("M221 S" + str(self.TargetValues["flowrateOne"]) + " T0") + # set second extruder flow rate + if "flowrateTwo" in self.TargetValues: + defaults.append("M221 S" + str(self.TargetValues["flowrateTwo"]) + " T1") - # set second extruder flow rate - if "flowrateTwo" in self.TargetValues: - defaults.append("M221 S" + str(self.TargetValues["flowrateTwo"]) + " T1") + # set feedrate percentage + if "speed" in self.TargetValues: + defaults.append("M220 S" + str(self.TargetValues["speed"]) + " T1") - # set feedrate percentage - if "speed" in self.TargetValues: - defaults.append("M220 S" + str(self.TargetValues["speed"]) + " T1") + # set print rate percentage + if "printspeed" in self.TargetValues: + defaults.append(";PRINTSPEED " + str(self.TargetValues["printspeed"]) + "") - # set print rate percentage - if "printspeed" in self.TargetValues: - defaults.append(";PRINTSPEED " + str(self.TargetValues["printspeed"]) + "") + # set retract rate + if "retractfeedrate" in self.TargetValues: + defaults.append(";RETRACTFEEDRATE " + str(self.TargetValues["retractfeedrate"]) + "") - # set retract rate - if "retractfeedrate" in self.TargetValues: - defaults.append(";RETRACTFEEDRATE " + str(self.TargetValues["retractfeedrate"]) + "") + # set retract length + if "retractlength" in self.TargetValues: + defaults.append(";RETRACTLENGTH " + str(self.TargetValues["retractlength"]) + "") - # set retract length - if "retractlength" in self.TargetValues: - defaults.append(";RETRACTLENGTH " + str(self.TargetValues["retractlength"]) + "") + # used to trim other defaults + defaults.append(";:CAZD]") - # used to trim other defaults - defaults.append(";:CAZD]") + # if there are no defaults, stop here + if len(defaults) == 2: + return "" - # if there are no defaults, stop here - if len(defaults) == 2: - return "" + # return our default block for this layer + return "\n".join(defaults) - # return our default block for this layer - return "\n".join(defaults) + # Allows retrieving values from the given GCODE line + @staticmethod + def getValue(line, key, default=None): - # Allows retrieving values from the given GCODE line - @staticmethod - def getValue(line, key, default=None): + if key not in line or (";" in line and line.find(key) > line.find(";") and ";ChangeAtZ" not in key and ";LAYER:" not in key): + return default - if not key in line or (";" in line and line.find(key) > line.find(";") and not ";ChangeAtZ" in key and not ";LAYER:" in key): - return default + sub_part = line[line.find(key) + len(key):] # allows for string lengths larger than 1 + if ";ChangeAtZ" in key: + m = re.search("^[0-4]", sub_part) + elif ";LAYER:" in key: + m = re.search("^[+-]?[0-9]*", sub_part) + else: + # the minus at the beginning allows for negative values, e.g. for delta printers + m = re.search(r"^[-]?[0-9]*\.?[0-9]*", sub_part) + if m is None: + return default + try: + return float(m.group(0)) + except: + return default - sub_part = line[line.find(key) + len(key):] # allows for string lengths larger than 1 - if ";ChangeAtZ" in key: - m = re.search("^[0-4]", sub_part) - elif ";LAYER:" in key: - m = re.search("^[+-]?[0-9]*", sub_part) - else: - # the minus at the beginning allows for negative values, e.g. for delta printers - m = re.search(r"^[-]?[0-9]*\.?[0-9]*", sub_part) - if m is None: - return default - try: - return float(m.group(0)) - except: - return default + # Determines if the current line is at or below the target required to start modifying + def isTargetLayerOrHeight(self): - # Determines if the current line is at or below the target required to start modifying - def isTargetLayerOrHeight(self): + # target selected by layer no. + if self.IsTargetByLayer: - # target selected by layer no. - if self.IsTargetByLayer: + # if we don't have a current layer, we're not there yet + if self.CurrentLayer is None: + return False - # if we don't have a current layer, we're not there yet - if self.CurrentLayer is None: - return False + # if we're applying to a single layer, stop if our layer is not identical + if self.IsApplyToSingleLayer: + return self.CurrentLayer == self.TargetLayer + else: + return self.CurrentLayer >= self.TargetLayer - # if we're applying to a single layer, stop if our layer is not identical - if self.IsApplyToSingleLayer: - return self.CurrentLayer == self.TargetLayer - else: - return self.CurrentLayer >= self.TargetLayer + else: - else: + # if we don't have a current Z, we're not there yet + if self.CurrentZ is None: + return False - # if we don't have a current Z, we're not there yet - if self.CurrentZ is None: - return False + # if we're applying to a single layer, stop if our Z is not identical + if self.IsApplyToSingleLayer: + return self.CurrentZ == self.TargetZ + else: + return self.CurrentZ >= self.TargetZ - # if we're applying to a single layer, stop if our Z is not identical - if self.IsApplyToSingleLayer: - return self.CurrentZ == self.TargetZ - else: - return self.CurrentZ >= self.TargetZ + # Marks any current ChangeZ layer defaults in the layer for deletion + @staticmethod + def markDefaultsForDeletion(layer): + return re.sub(r";\[CAZD:", ";[CAZD:DELETE:", layer) - # Marks any current ChangeZ layer defaults in the layer for deletion - @staticmethod - def markDefaultsForDeletion(layer): - return re.sub(r";\[CAZD:", ";[CAZD:DELETE:", layer) + # Grabs the current height + def processLayerHeight(self, line): - # Grabs the current height - def processLayerHeight(self, line): + # stop here if we haven't entered a layer yet + if self.CurrentLayer is None: + return - # stop here if we haven't entered a layer yet - if self.CurrentLayer is None: - return + # expose the main command + line_no_comments = self.stripComments(line) - # expose the main command - line_no_comments = self.stripComments(line) + # stop here if this isn't a linear move command + if not ("G1" in line_no_comments or "G0" in line_no_comments): + return - # stop here if this isn't a linear move command - if not ("G1" in line_no_comments or "G0" in line_no_comments): - return + # stop here if we don't have a Z value defined, we can't get the height from this command + if "Z" not in line_no_comments: + return - # stop here if we don't have a Z value defined, we can't get the height from this command - if "Z" not in line_no_comments: - return + # get our value from the command + current_z = self.getFloatValue(line_no_comments, "Z", None) - # get our value from the command - current_z = self.getFloatValue(line_no_comments, "Z", None) + # stop if there's no change + if current_z == self.CurrentZ: + return - # stop if there's no change - if current_z == self.CurrentZ: - return + # set our current Z value + self.CurrentZ = current_z - # set our current Z value - self.CurrentZ = current_z + # if we don't have a layer height yet, set it based on the current Z value + if self.LayerHeight is None: + self.LayerHeight = self.CurrentZ - # if we don't have a layer height yet, set it based on the current Z value - if self.LayerHeight is None: - self.LayerHeight = self.CurrentZ + # Grabs the current layer number + def processLayerNumber(self, line): - # Grabs the current layer number - def processLayerNumber(self, line): + # if this isn't a layer comment, stop here, nothing to update + if ";LAYER:" not in line: + return - # if this isn't a layer comment, stop here, nothing to update - if ";LAYER:" not in line: - return + # get our current layer number + current_layer = self.getIntValue(line, ";LAYER:", None) - # get our current layer number - current_layer = self.getIntValue(line, ";LAYER:", None) + # this should never happen, but if our layer number hasn't changed, stop here + if current_layer == self.CurrentLayer: + return - # this should never happen, but if our layer number hasn't changed, stop here - if current_layer == self.CurrentLayer: - return + # update our current layer + self.CurrentLayer = current_layer - # update our current layer - self.CurrentLayer = current_layer + # Handles any linear moves in the current line + def processLinearMove(self, line): - # Handles any linear moves in the current line - def processLinearMove(self, line): + # if it's not a linear motion command we're not interested + if not ("G1" in line or "G0" in line): + return line - # if it's not a linear motion command we're not interested - if not ("G1" in line or "G0" in line): - return line + # always get our original line, otherwise the effect will be cumulative + line = self.getOriginalLine(line) - # always get our original line, otherwise the effect will be cumulative - line = self.getOriginalLine(line) + # get the details from our linear move command + extrude_length, feed_rate, x_coord, y_coord, z_coord = self.getLinearMoveParams(line) - # get the details from our linear move command - extrude_length, feed_rate, x_coord, y_coord, z_coord = self.getLinearMoveParams(line) + # set our new line to our old line + new_line = line - # set our new line to our old line - new_line = line + # handle retract length + new_line = self.processRetractLength(extrude_length, feed_rate, new_line, x_coord, y_coord, z_coord) - # handle retract length - new_line = self.processRetractLength(extrude_length, feed_rate, new_line, x_coord, y_coord, z_coord) + # handle retract feed rate + new_line = self.processRetractFeedRate(extrude_length, feed_rate, new_line, x_coord, y_coord, z_coord) - # handle retract feed rate - new_line = self.processRetractFeedRate(extrude_length, feed_rate, new_line, x_coord, y_coord, z_coord) + # handle print speed adjustments + new_line = self.processPrintSpeed(feed_rate, new_line) - # handle print speed adjustments - new_line = self.processPrintSpeed(feed_rate, new_line) + # set our current extrude position + self.LastE = extrude_length if extrude_length is not None else self.LastE - # set our current extrude position - self.LastE = extrude_length if extrude_length is not None else self.LastE + # if no changes have been made, stop here + if new_line == line: + return line - # if no changes have been made, stop here - if new_line == line: - return line + # return our updated command + return self.setOriginalLine(new_line, line) - # return our updated command - return self.setOriginalLine(new_line, line) + # Handles any changes to print speed for the given linear motion command + def processPrintSpeed(self, feed_rate, new_line): - # Handles any changes to print speed for the given linear motion command - def processPrintSpeed(self, feed_rate, new_line): + # if we're not setting print speed or we don't have a feed rate, stop here + if "printspeed" not in self.TargetValues or feed_rate is None: + return new_line - # if we're not setting print speed or we don't have a feed rate, stop here - if "printspeed" not in self.TargetValues or feed_rate is None: - return new_line + # get our requested print speed + print_speed = int(self.TargetValues["printspeed"]) - # get our requested print speed - print_speed = int(self.TargetValues["printspeed"]) + # if they requested no change to print speed (ie: 100%), stop here + if print_speed == 100: + return new_line - # if they requested no change to print speed (ie: 100%), stop here - if print_speed == 100: - return new_line + # get our feed rate from the command + feed_rate = float(self.getValue(new_line, "F")) * (float(print_speed) / 100.0) - # get our feed rate from the command - feed_rate = float(self.getValue(new_line, "F")) * (float(print_speed) / 100.0) + # change our feed rate + return self.replaceParameter(new_line, "F", feed_rate) - # change our feed rate - return self.replaceParameter(new_line, "F", feed_rate) + # Handles any changes to retraction length for the given linear motion command + def processRetractLength(self, extrude_length, feed_rate, new_line, x_coord, y_coord, z_coord): - # Handles any changes to retraction length for the given linear motion command - def processRetractLength(self, extrude_length, feed_rate, new_line, x_coord, y_coord, z_coord): + # if we don't have a retract length in the file we can't add one + if self.RetractLength == 0: + return new_line - # if we don't have a retract length in the file we can't add one - if self.RetractLength == 0: - return new_line + # if we're not changing retraction length, stop here + if "retractlength" not in self.TargetValues: + return new_line - # if we're not changing retraction length, stop here - if "retractlength" not in self.TargetValues: - return new_line + # retractions are only F (feed rate) and E (extrude), at least in cura + if x_coord is not None or y_coord is not None or z_coord is not None: + return new_line - # retractions are only F (feed rate) and E (extrude), at least in cura - if x_coord is not None or y_coord is not None or z_coord is not None: - return new_line + # since retractions require both F and E, and we don't have either, we can't process + if feed_rate is None or extrude_length is None: + return new_line - # since retractions require both F and E, and we don't have either, we can't process - if feed_rate is None or extrude_length is None: - return new_line + # stop here if we don't know our last extrude value + if self.LastE is None: + return new_line - # stop here if we don't know our last extrude value - if self.LastE is None: - return new_line + # if there's no change in extrude we have nothing to change + if self.LastE == extrude_length: + return new_line - # if there's no change in extrude we have nothing to change - if self.LastE == extrude_length: - return new_line + # if our last extrude was lower than our current, we're restoring, so skip + if self.LastE < extrude_length: + return new_line - # if our last extrude was lower than our current, we're restoring, so skip - if self.LastE < extrude_length: - return new_line + # get our desired retract length + retract_length = float(self.TargetValues["retractlength"]) - # get our desired retract length - retract_length = float(self.TargetValues["retractlength"]) + # subtract the difference between the default and the desired + extrude_length -= (retract_length - self.RetractLength) - # subtract the difference between the default and the desired - extrude_length -= (retract_length - self.RetractLength) + # replace our extrude amount + return self.replaceParameter(new_line, "E", extrude_length) - # replace our extrude amount - return self.replaceParameter(new_line, "E", extrude_length) + # Used for picking out the retract length set by Cura + def processRetractLengthSetting(self, line): - # Used for picking out the retract length set by Cura - def processRetractLengthSetting(self, line): + # if it's not a linear move, we don't care + if "G0" not in line and "G1" not in line: + return - # if it's not a linear move, we don't care - if "G0" not in line and "G1" not in line: - return + # get the details from our linear move command + extrude_length, feed_rate, x_coord, y_coord, z_coord = self.getLinearMoveParams(line) - # get the details from our linear move command - extrude_length, feed_rate, x_coord, y_coord, z_coord = self.getLinearMoveParams(line) + # the command we're looking for only has extrude and feed rate + if x_coord is not None or y_coord is not None or z_coord is not None: + return - # the command we're looking for only has extrude and feed rate - if x_coord is not None or y_coord is not None or z_coord is not None: - return + # if either extrude or feed is missing we're likely looking at the wrong command + if extrude_length is None or feed_rate is None: + return - # if either extrude or feed is missing we're likely looking at the wrong command - if extrude_length is None or feed_rate is None: - return + # cura stores the retract length as a negative E just before it starts printing + extrude_length = extrude_length * -1 - # cura stores the retract length as a negative E just before it starts printing - extrude_length = extrude_length * -1 + # if it's a negative extrude after being inverted, it's not our retract length + if extrude_length < 0: + return - # if it's a negative extrude after being inverted, it's not our retract length - if extrude_length < 0: - return + # what ever the last negative retract length is it wins + self.RetractLength = extrude_length - # what ever the last negative retract length is it wins - self.RetractLength = extrude_length + # Handles any changes to retraction feed rate for the given linear motion command + def processRetractFeedRate(self, extrude_length, feed_rate, new_line, x_coord, y_coord, z_coord): - # Handles any changes to retraction feed rate for the given linear motion command - def processRetractFeedRate(self, extrude_length, feed_rate, new_line, x_coord, y_coord, z_coord): + # if we're not changing retraction length, stop here + if "retractfeedrate" not in self.TargetValues: + return new_line - # if we're not changing retraction length, stop here - if "retractfeedrate" not in self.TargetValues: - return new_line + # retractions are only F (feed rate) and E (extrude), at least in cura + if x_coord is not None or y_coord is not None or z_coord is not None: + return new_line - # retractions are only F (feed rate) and E (extrude), at least in cura - if x_coord is not None or y_coord is not None or z_coord is not None: - return new_line + # since retractions require both F and E, and we don't have either, we can't process + if feed_rate is None or extrude_length is None: + return new_line - # since retractions require both F and E, and we don't have either, we can't process - if feed_rate is None or extrude_length is None: - return new_line + # get our desired retract feed rate + retract_feed_rate = float(self.TargetValues["retractfeedrate"]) - # get our desired retract feed rate - retract_feed_rate = float(self.TargetValues["retractfeedrate"]) + # convert to units/min + retract_feed_rate *= 60 - # convert to units/min - retract_feed_rate *= 60 + # replace our feed rate + return self.replaceParameter(new_line, "F", retract_feed_rate) - # replace our feed rate - return self.replaceParameter(new_line, "F", retract_feed_rate) + # Used for finding settings in the print file before we process anything else + def processSetting(self, line): - # Used for finding settings in the print file before we process anything else - def processSetting(self, line): + # if we're in layers already we're out of settings + if self.CurrentLayer is not None: + return - # if we're in layers already we're out of settings - if self.CurrentLayer is not None: - return + # check our retract length + self.processRetractLengthSetting(line) - # check our retract length - self.processRetractLengthSetting(line) + # Removes all the ChangeZ layer defaults from the given layer + @staticmethod + def removeMarkedTargetDefaults(layer): + return re.sub(r";\[CAZD:DELETE:[\s\S]+?:CAZD\](\n|$)", "", layer) - # Removes all the ChangeZ layer defaults from the given layer - @staticmethod - def removeMarkedTargetDefaults(layer): - return re.sub(r";\[CAZD:DELETE:[\s\S]+?:CAZD\](\n|$)", "", layer) + # Easy function for replacing any GCODE parameter variable in a given GCODE command + @staticmethod + def replaceParameter(line, key, value): + return re.sub(r"(^|\s)" + key + r"[\d\.]+(\s|$)", r"\1" + key + str(value) + r"\2", line) - # Easy function for replacing any GCODE parameter variable in a given GCODE command - @staticmethod - def replaceParameter(line, key, value): - return re.sub(r"(^|\s)" + key + r"[\d\.]+(\s|$)", r"\1" + key + str(value) + r"\2", line) + # Resets the class contents to defaults + def reset(self): - # Resets the class contents to defaults - def reset(self): + self.TargetValues = {} + self.IsApplyToSingleLayer = False + self.LastE = None + self.CurrentZ = None + self.CurrentLayer = None + self.IsTargetByLayer = True + self.TargetLayer = None + self.TargetZ = None + self.LayerHeight = None + self.RetractLength = 0 - self.TargetValues = {} - self.IsApplyToSingleLayer = False - self.LastE = None - self.CurrentZ = None - self.CurrentLayer = None - self.IsTargetByLayer = True - self.TargetLayer = None - self.TargetZ = None - self.LayerHeight = None - self.RetractLength = 0 + # Sets the original GCODE line in a given GCODE command + @staticmethod + def setOriginalLine(line, original): + return line + ";[CAZO:" + original + ":CAZO]" - # Sets the original GCODE line in a given GCODE command - @staticmethod - def setOriginalLine(line, original): - return line + ";[CAZO:" + original + ":CAZO]" - - # Removes the gcode comments from a given gcode command - @staticmethod - def stripComments(line): - return re.sub(r";.*?$", "", line).strip() + # Removes the gcode comments from a given gcode command + @staticmethod + def stripComments(line): + return re.sub(r";.*?$", "", line).strip() def debug(): - # get our input file - file = r"PATH_TO_SOME_GCODE.gcode" + # get our input file + file = r"PATH_TO_SOME_GCODE.gcode" - # read the whole thing - f = open(file, "r") - gcode = f.read() - f.close() + # read the whole thing + f = open(file, "r") + gcode = f.read() + f.close() - # boot up change - caz_instance = ChangeAtZProcessor() - caz_instance.IsTargetByLayer = False - caz_instance.TargetZ = 5 - caz_instance.TargetValues["printspeed"] = 100 - caz_instance.TargetValues["retractfeedrate"] = 60 + # boot up change + caz_instance = ChangeAtZProcessor() + caz_instance.IsTargetByLayer = False + caz_instance.TargetZ = 5 + caz_instance.TargetValues["printspeed"] = 100 + caz_instance.TargetValues["retractfeedrate"] = 60 - # process gcode - gcode = debug_iteration(gcode, caz_instance) + # process gcode + gcode = debug_iteration(gcode, caz_instance) - # write our file - debug_write(gcode, file + ".1.modified") + # write our file + debug_write(gcode, file + ".1.modified") - caz_instance.reset() - caz_instance.IsTargetByLayer = False - caz_instance.TargetZ = 10.5 - caz_instance.TargetValues["bedTemp"] = 75.111 - caz_instance.TargetValues["printspeed"] = 150 - caz_instance.TargetValues["retractfeedrate"] = 40.555 - caz_instance.TargetValues["retractlength"] = 10.3333 + caz_instance.reset() + caz_instance.IsTargetByLayer = False + caz_instance.TargetZ = 10.5 + caz_instance.TargetValues["bedTemp"] = 75.111 + caz_instance.TargetValues["printspeed"] = 150 + caz_instance.TargetValues["retractfeedrate"] = 40.555 + caz_instance.TargetValues["retractlength"] = 10.3333 - # and again - gcode = debug_iteration(gcode, caz_instance) + # and again + gcode = debug_iteration(gcode, caz_instance) - # write our file - debug_write(gcode, file + ".2.modified") + # write our file + debug_write(gcode, file + ".2.modified") - caz_instance.reset() - caz_instance.IsTargetByLayer = False - caz_instance.TargetZ = 15 - caz_instance.TargetValues["bedTemp"] = 80 - caz_instance.TargetValues["printspeed"] = 100 - caz_instance.TargetValues["retractfeedrate"] = 10 - caz_instance.TargetValues["retractlength"] = 0 - caz_instance.TargetValues["extruderOne"] = 100 - caz_instance.TargetValues["extruderTwo"] = 200 + caz_instance.reset() + caz_instance.IsTargetByLayer = False + caz_instance.TargetZ = 15 + caz_instance.TargetValues["bedTemp"] = 80 + caz_instance.TargetValues["printspeed"] = 100 + caz_instance.TargetValues["retractfeedrate"] = 10 + caz_instance.TargetValues["retractlength"] = 0 + caz_instance.TargetValues["extruderOne"] = 100 + caz_instance.TargetValues["extruderTwo"] = 200 - # and again - gcode = debug_iteration(gcode, caz_instance) + # and again + gcode = debug_iteration(gcode, caz_instance) - # write our file - debug_write(gcode, file + ".3.modified") + # write our file + debug_write(gcode, file + ".3.modified") def debug_write(gcode, file): - # write our file - f = open(file, "w") - f.write(gcode) - f.close() + # write our file + f = open(file, "w") + f.write(gcode) + f.close() def debug_iteration(gcode, caz_instance): - index = 0 + index = 0 - # break apart the GCODE like cura - layers = re.split(r"^;LAYER:\d+\n", gcode) + # break apart the GCODE like cura + layers = re.split(r"^;LAYER:\d+\n", gcode) - # add the layer numbers back - for layer in layers: + # add the layer numbers back + for layer in layers: - # if this is the first layer, skip it, basically - if index == 0: - # leave our first layer as is - layers[index] = layer + # if this is the first layer, skip it, basically + if index == 0: + # leave our first layer as is + layers[index] = layer - # move the cursor - index += 1 + # move the cursor + index += 1 - # skip to the next layer - continue + # skip to the next layer + continue - layers[index] = ";LAYER:" + str(index - 1) + ";\n" + layer + layers[index] = ";LAYER:" + str(index - 1) + ";\n" + layer - return "".join(caz_instance.execute(layers)) + return "".join(caz_instance.execute(layers)) # debug()