From be008c6ff08aa8ca7a9ab03185f5861c27cdc4e5 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Tue, 3 Oct 2023 12:16:51 -0400 Subject: [PATCH] Update MultiExtColorMix.py Update Update MultiExtColorMix.py Update --- .../scripts/MultiExtColorMix.py | 502 ++++++++++-------- 1 file changed, 291 insertions(+), 211 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/MultiExtColorMix.py b/plugins/PostProcessingPlugin/scripts/MultiExtColorMix.py index 735c7df09f7..41d2543f917 100644 --- a/plugins/PostProcessingPlugin/scripts/MultiExtColorMix.py +++ b/plugins/PostProcessingPlugin/scripts/MultiExtColorMix.py @@ -1,16 +1,13 @@ -# Written by GregValiant (Greg Foresi) June of 2023 with thanks to @AHoeben and @Ghostkeeper +# Written by GregValiant (Greg Foresi) June of 2023 # Released under the terms of the AGPLv3 or higher. # -# Revised: Sept 1, 2023 -# Bug fix. -# Allow 4-in-1-out hot ends although only 3 can be used. -# -# This post processor is for machines with a 2-in-1-out or 3-in-1-out hot ends that have shared heaters and nozzles. +# This post processor is for machines with a 2-in-1-out, 3-in-1-out, or 4-in-1-out hot ends that have shared heaters and nozzles. # If 'Extruders Share Heater' and 'Extruders Share Nozzle' are not enabled in Cura - the post will exit. -# This script REQUIRES that M163 and M164 are enabled in the firmware. +# This script REQUIRES that M163 and M164 are enabled in the firmware. (RepRap uses M567 and is not compatible.) # Prime Towers are not allowed. +# 'One-at-a-Time' is not supported # 'Printer Settings / Shared Nozzle Initial Retraction Amount' and 'Dual Extrusion / Nozzle Switch Retraction Distance' will be set to "0". You will be informed of your defaults so you can reset them manually after slicing is complete. -# Options are: Constant Mix or Gradient Mix. A Range of Layers, or Entire File. 'Resume Extruder' and 'Purge'. +# Options are: Constant Mix, Gradient Mix, Range of Layers, the Entire File, the 'Resume Extruder' and whether to 'Purge' at mix change. # Additional instances of the Post Processor can be run on different layers and with different mix ratios. # All tool changes that Cura might insert will be removed from the gcode. # All M109 and M104's will be removed starting at LAYER:0. @@ -23,10 +20,10 @@ # Ex: If you are using three extruders and the first starts with 35, and 2nd with 10 then E3 must start with 55. # The same thing applies to the End numbers when you use a gradient mix. # If the Percentage Sums do not add up then the post will exit with a message. -# The virtual extruder is always Extruder_count+1 (either T2 or T3 in the gcode) +# The virtual extruder is always Extruder_count+1. (If the printer has 3 extruders then the virtual mixing extruder will be Extruder 4 (T3)). # This Post can also be used to simply set an extruder mix for an entire print. # May be used with either Absolute or Relative extrusion. -# 'One-at-a-Time' printing is a work in process. It is typically not allowed for multi-extruder printers. +# 'One-at-a-Time' printing is not supported as it isn't allowed for multi-extruder printers in Cura. from ..Script import Script from UM.Application import Application @@ -38,10 +35,17 @@ class MultiExtColorMix(Script): # Adjust Cura settings and enable the third extruder if there is one-- def initialize(self) -> None: super().initialize() + firmware_flavor = str(Application.getInstance().getGlobalContainerStack().getProperty("machine_gcode_flavor", "value")) + if firmware_flavor != "RepRap (Marlin/Sprinter)": + Message(title = "Multi-Extruder Color Mixer:", text = "This post processor is only compatible with Marlin firmware. The post processor will not run.").show() + self._instance.setProperty("enable_3rd_extruder", "value", False) + self._instance.setProperty("enable_4th_extruder", "value", False) ext_list = Application.getInstance().getGlobalContainerStack().extruderList extruder_count = Application.getInstance().getGlobalContainerStack().getProperty("machine_extruder_count", "value") enable_3rd_extruder = extruder_count > 2 + enable_4th_extruder = extruder_count > 3 self._instance.setProperty("enable_3rd_extruder", "value", enable_3rd_extruder) + self._instance.setProperty("enable_4th_extruder", "value", enable_4th_extruder) self._instance.setProperty("resume_ext_nr", "maximum_value_warning", int(extruder_count)) # Disable the Prime Tower as it interferes with the tool changes by this script if bool(Application.getInstance().getGlobalContainerStack().getProperty("prime_tower_enable", "value")): @@ -67,28 +71,32 @@ def initialize(self) -> None: ext1_default_str = "" ext2_default_str = "" ext3_default_str = "" - if extruder_count == 2: - ext1_default_str += "Ext 1 Nozzle Switch Retraction Distance = " + str(switch_retraction_list[0]) + "\n" - ext1_default_str += "Ext 1 Shared Extruder Initial Retraction Amount = " + str(shared_retraction_list[0]) + "\n" - ext2_default_str += "Ext 2 Nozzle Switch Retraction Distance = " + str(switch_retraction_list[1]) + "\n" - ext2_default_str += "Ext 2 Shared Extruder Initial Retraction Amount = " + str(shared_retraction_list[1]) + "\n" + ext4_default_str = "" + if extruder_count >= 2: + ext1_default_str += "Ext 1 Nozzle Switch Retraction Distance.............. " + str(switch_retraction_list[0]) + "\n" + ext1_default_str += "...Ext 1 Shared Extruder Initial Retraction Amt... " + str(shared_retraction_list[0]) + "\n" + ext2_default_str += "Ext 2 Nozzle Switch Retraction Distance.............. " + str(switch_retraction_list[1]) + "\n" + ext2_default_str += "...Ext 2 Shared Extruder Initial Retraction Amt... " + str(shared_retraction_list[1]) + "\n" if extruder_count >= 3: - ext3_default_str += "Ext 3 Nozzle Switch Retraction Distance = " + str(switch_retraction_list[2]) + "\n" - ext3_default_str += "Ext 3 Shared Extruder Initial Retraction Amount = " + str(shared_retraction_list[2]) + "\n" + ext3_default_str += "Ext 3 Nozzle Switch Retraction Distance.............. " + str(switch_retraction_list[2]) + "\n" + ext3_default_str += "...Ext 3 Shared Extruder Initial Retraction Amt... " + str(shared_retraction_list[2]) + "\n" + if extruder_count == 4: + ext4_default_str += "Ext 4 Nozzle Switch Retraction Distance.............. " + str(switch_retraction_list[3]) + "\n" + ext4_default_str += "...Ext 4 Shared Extruder Initial Retraction Amt... " + str(shared_retraction_list[3]) + "\n" if multi_present == 1: - Message(text = "Multi-Extruder Color Mixer:" + "\n" + "You must have a Blending Hot End and 'Extruders Share Heater' and 'Extruders Share Nozzle' must be enabled in the 'Printer Settings' in Cura." + "\n" + "The 'Printer Settings / Shared Nozzle Initial Retraction Amount' will be set to '0.0' for all extruders." + "\n" + "The 'Dual Extrusion / Nozzle Switch Retraction Distance' will be set to '0.0' for all extruders." + "\n" + "Prime Tower is not allowed and will be turned off." + "\n\n" + "Note Your Default Settings:" + "\n" + ext1_default_str + ext2_default_str + ext3_default_str).show() + Message(title = "Multi-Extruder Color Mixer:", text = "You must have a Blending Hot End and 'Extruders Share Heater' and 'Extruders Share Nozzle' must be enabled in the 'Printer Settings' in Cura." + "\n" + "The 'Printer Settings / Shared Nozzle Initial Retraction Amount' will be set to '0.0' for all extruders." + "\n" + "The 'Dual Extrusion / Nozzle Switch Retraction Distance' will be set to '0.0' for all extruders." + "\n" + "Prime Tower is not allowed and will be turned off." + "\n\n" + "Note Your Default Settings:" + "\n" + ext1_default_str + ext2_default_str + ext3_default_str + ext4_default_str).show() except: - all + pass def getSettingDataString(self): return """{ - "name":"Multi-Extruder Color Mixer", - "key":"MultiExtColorMix", + "name": "Multi-Extruder Color Mixer", + "key": "MultiExtColorMix", "metadata": {}, "version": 2, "settings": - { + { "mix_style": { "label": "Mix Style", @@ -123,7 +131,7 @@ def getSettingDataString(self): "maximum_value": "4", "enabled": "end_layer != -1" }, - "T0_include": + "t0_include": { "label": "Ext-1 in the Mix", "description": "Check For dual extruders. For 3-in-1-out hot end Check if you want this extruder in the Mix.", @@ -131,31 +139,29 @@ def getSettingDataString(self): "default_value": true, "enabled": true }, - "T0_mix_start": + "t0_mix_start": { "label": " Ext-1 Start mix %", "description": "First extruder percentage 0-100", "type": "int", "unit": "%", "default_value": 100, - "minimum_value": "0", - "minimum_value_warning": "0", - "maximum_value_warning": "100", - "enabled": "T0_include" + "minimum_value": 0, + "maximum_value": 100, + "enabled": "t0_include" }, - "T0_mix_end": + "t0_mix_end": { "label": " Ext-1 End mix %", "description": "First extruder percentage 0-100 to finish blend", "type": "int", "unit": "%", "default_value": 0, - "minimum_value": "0", - "minimum_value_warning": "0", - "maximum_value_warning": "100", - "enabled": "T0_include and mix_style == 'gradient'" + "minimum_value": 0, + "maximum_value": 100, + "enabled": "t0_include and mix_style == 'gradient'" }, - "T1_include": + "t1_include": { "label": "Ext-2 in the Mix", "description": "Check For dual extruders. For 3-in-1-out hot end Check if you want this extruder included in the Mix.", @@ -163,7 +169,7 @@ def getSettingDataString(self): "default_value": true, "enabled": true }, - "T1_mix_start": + "t1_mix_start": { "label": " Ext-2 Start mix %", "description": "Second extruder percentage 0-100", @@ -171,11 +177,10 @@ def getSettingDataString(self): "unit": "%", "default_value": 0, "minimum_value": "0", - "minimum_value_warning": "0", - "maximum_value_warning": "100", - "enabled": "T1_include" + "maximum_value": "100", + "enabled": "t1_include" }, - "T1_mix_end": + "t1_mix_end": { "label": " Ext-2 End mix %", "description": "Second extruder percentage 0-100 to finish blend", @@ -183,9 +188,8 @@ def getSettingDataString(self): "unit": "%", "default_value": 100, "minimum_value": "0", - "minimum_value_warning": "0", - "maximum_value_warning": "100", - "enabled": "T1_include and mix_style == 'gradient'" + "maximum_value": "100", + "enabled": "t1_include and mix_style == 'gradient'" }, "enable_3rd_extruder": { @@ -195,7 +199,7 @@ def getSettingDataString(self): "default_value": false, "enabled": false }, - "T2_include": + "t2_include": { "label": "Ext-3 in the Mix", "description": "For 3-in-1-out hot end Check if you want this extruder included in the Mix.", @@ -203,7 +207,7 @@ def getSettingDataString(self): "default_value": false, "enabled": "enable_3rd_extruder" }, - "T2_mix_start": + "t2_mix_start": { "label": " Ext-3 Start mix %", "description": "Third extruder percentage 0-100", @@ -211,11 +215,10 @@ def getSettingDataString(self): "unit": "%", "default_value": 0, "minimum_value": "0", - "minimum_value_warning": "0", - "maximum_value_warning": "100", - "enabled": "T2_include" + "maximum_value": "100", + "enabled": "t2_include" }, - "T2_mix_end": + "t2_mix_end": { "label": " Ext-3 End mix %", "description": "Third extruder percentage 0-100 to finish blend", @@ -223,9 +226,46 @@ def getSettingDataString(self): "unit": "%", "default_value": 0, "minimum_value": "0", - "minimum_value_warning": "0", - "maximum_value_warning": "100", - "enabled": "T2_include and mix_style == 'gradient'" + "maximum_value": "100", + "enabled": "t2_include and mix_style == 'gradient'" + }, + "enable_4th_extruder": + { + "label": "Enable 4th Extruder:", + "description": "Hidden from the user. Sets 'T3_enable' visibility to true if there are 4 extruders.", + "type": "bool", + "default_value": false, + "enabled": false + }, + "t3_include": + { + "label": "Ext-4 in the Mix", + "description": "For 4-in-1-out hot end Check if you want this extruder included in the Mix.", + "type": "bool", + "default_value": false, + "enabled": "enable_4th_extruder" + }, + "t3_mix_start": + { + "label": " Ext-4 Start mix %", + "description": "Fourth extruder percentage 0-100", + "type": "int", + "unit": "%", + "default_value": 0, + "minimum_value": "0", + "maximum_value": "100", + "enabled": "t3_include and enable_4th_extruder" + }, + "t3_mix_end": + { + "label": " Ext-4 End mix %", + "description": "Fourth extruder percentage 0-100 to finish blend", + "type": "int", + "unit": "%", + "default_value": 0, + "minimum_value": "0", + "maximum_value": "100", + "enabled": "t3_include and mix_style == 'gradient'" }, "park_head": { @@ -261,61 +301,79 @@ def getSettingDataString(self): "minimum_value": "1", "maximum_value": "50", "enabled": "park_head" + }, + "park_head_init_only": + { + "label": " Initial Purge only", + "description": "When enabled only the first use of the mixing extruder will Park and Purge. Any other changes will be done on-the-fly.", + "type": "bool", + "default_value": false, + "enabled": "park_head" } } }""" def execute(self, data): - MyCura = Application.getInstance().getGlobalContainerStack() - extruder_count = MyCura.getProperty("machine_extruder_count", "value") + mycura = Application.getInstance().getGlobalContainerStack() + extruder_count = mycura.getProperty("machine_extruder_count", "value") init_extruder = Application.getInstance().getExtruderManager().getInitialExtruderNr() - if extruder_count >1: - T0_include = self.getSettingValueByKey("T0_include") - T1_include = self.getSettingValueByKey("T1_include") - T2_include = False - if extruder_count >= 3: - T2_include = self.getSettingValueByKey("T2_include") + firmware_flavor = str(mycura.getProperty("machine_gcode_flavor", "value")) + if firmware_flavor != "RepRap (Marlin/Sprinter)": + Message(title = "Multi-Extruder Color Mixer:", text = "This post processor is only compatible with Marlin firmware. The post processor will exit.").show() + data[0] += "; [Multi-Extruder Color Mix] Did not run because it is only compatible with Marlin firmware\n" + return data + if extruder_count > 1: + t0_include = self.getSettingValueByKey("t0_include") + t1_include = self.getSettingValueByKey("t1_include") + t2_include = False + t3_include = False + if extruder_count >= 2: + t2_include = self.getSettingValueByKey("t2_include") + t3_include = False + if extruder_count > 3: + t3_include = self.getSettingValueByKey("t3_include") park_head = bool(self.getSettingValueByKey("park_head")) park_x = str(self.getSettingValueByKey("park_x")) park_y = str(self.getSettingValueByKey("park_y")) purge_amt = str(self.getSettingValueByKey("purge_amt")) + park_head_init_only = bool(self.getSettingValueByKey("park_head_init_only")) park_string = "" # If the Prime Tower is enabled after the script is loaded then inform the user and exit----- - if bool(MyCura.getProperty("prime_tower_enable", "value")): + if bool(mycura.getProperty("prime_tower_enable", "value")): data[0] += "; [Multi-Extruder Color Mixer] Did not run because - Prime Tower is enabled.\n" - Message(text = "[Multi-Extruder Color Mixer]: DID NOT RUN because Prime Tower is enabled.").show() - return data - + Message(title = "[Multi-Extruder Color Mixer]:", text = "DID NOT RUN because Prime Tower is enabled.").show() + return data + # If Extruder Count > 3 then inform the user that the maximum useable number is 3 extruders - if extruder_count > 3: - Message(text = "[Multi-Extruder Color Mixer]: the number of extruders is > 3 but only extruders #1, #2, and #3 can be used when mixing.").show() + if extruder_count > 4: + Message(title = "[Multi-Extruder Color Mixer]:", text = "The number of extruders is > 4 but only extruders #1, #2, #3, and #4 can be used when mixing.").show() # If it is a single extruder printer exit with a message----------- if extruder_count == 1: data[0] += "; [Multi-Extruder Color Mixer] did not run because the printer has one extruder\n" - Message(text = "Multi-Extruder Color Mixer: {}".format("The post processor exited because the printer has a single extruder.")).show() + Message(title = "Multi-Extruder Color Mixer:", text = "The post processor exited because the printer has a single extruder.").show() return data # If the printer is not equipped with Shared Heater and Shared Nozzle then exit with a message------------------ - shared_heater = bool(MyCura.getProperty("machine_extruders_share_heater", "value")) + shared_heater = bool(mycura.getProperty("machine_extruders_share_heater", "value")) try: - shared_nozzle = bool(MyCura.getProperty("machine_extruders_share_nozzle", "value")) + shared_nozzle = bool(mycura.getProperty("machine_extruders_share_nozzle", "value")) except: shared_nozzle = shared_heater if not shared_heater and not shared_nozzle: - Message(text = "Multi-Extruder Color Mixer: {}".format("This post is for machines with 'Shared Heaters' and 'Shared Nozzles'. Separate hot ends won't work. Those settings are not enabled in Cura. The Post Process will exit.")).show() + Message(title = "Multi-Extruder Color Mixer:", text = "This post is for machines with 'Shared Heaters' and 'Shared Nozzles'. Separate hot ends won't work. Those settings are not enabled in Cura. The Post Process will exit.").show() data[0] += "; [Multi-Extruder Color Mixer] did not run because - 'Shared Heaters' and/or 'Shared Nozzles' are not enabled in Cura.\n" return data - + # Set variables--------------------------------------------------------------------- start_layer = self.getSettingValueByKey("start_layer") - 1 end_layer = self.getSettingValueByKey("end_layer") resume_ext_nr = self.getSettingValueByKey("resume_ext_nr")-1 if resume_ext_nr > extruder_count + 1: resume_ext_nr = extruder_count + 1 - M164_ext_nr = extruder_count + m164_ext_nr = extruder_count mix_style = self.getSettingValueByKey("mix_style") - + # Figure out the actual End Layer------------------------------------------------------------- if end_layer == -1: end_layer = len(data)-2 @@ -324,45 +382,40 @@ def execute(self, data): layer_span = end_layer - start_layer - 1 # Calculate the 'Gradient' Indexing Factor for extruders included in the mixing------------ - if T0_include: - T0_mix_start = int(self.getSettingValueByKey("T0_mix_start")) - T0_mix_end = int(self.getSettingValueByKey("T0_mix_end")) - T0_ext_incr = (T0_mix_start - T0_mix_end) / (layer_span - 1) + if t0_include: + t0_mix_start = int(self.getSettingValueByKey("t0_mix_start")); t0_mix_end = int(self.getSettingValueByKey("t0_mix_end")); t0_ext_incr = (t0_mix_start - t0_mix_end) / (layer_span - 1) + else: + t0_mix_start = 0; t0_mix_end = 0; t0_ext_incr = 0 + if t1_include: + t1_mix_start = int(self.getSettingValueByKey("t1_mix_start")); t1_mix_end = int(self.getSettingValueByKey("t1_mix_end")); t1_ext_incr = (t1_mix_start - t1_mix_end) / (layer_span - 1) else: - T0_mix_start = 0 - T0_mix_end = 0 - T0_ext_incr = 0 - if T1_include: - T1_mix_start = int(self.getSettingValueByKey("T1_mix_start")) - T1_mix_end = int(self.getSettingValueByKey("T1_mix_end")) - T1_ext_incr = (T1_mix_start - T1_mix_end) / (layer_span - 1) + t1_mix_start = 0; t1_mix_end = 0; t1_ext_incr = 0 + if t2_include: + t2_mix_start = int(self.getSettingValueByKey("t2_mix_start")); t2_mix_end = int(self.getSettingValueByKey("t2_mix_end")); t2_ext_incr = (t2_mix_start - t2_mix_end) / (layer_span - 1) else: - T1_mix_start = 0 - T1_mix_end = 0 - T1_ext_incr = 0 - if T2_include: - T2_mix_start = int(self.getSettingValueByKey("T2_mix_start")) - T2_mix_end = int(self.getSettingValueByKey("T2_mix_end")) - T2_ext_incr = (T2_mix_start - T2_mix_end) / (layer_span - 1) + t2_mix_start = 0; t2_mix_end = 0; t2_ext_incr = 0 + if t3_include: + t3_mix_start = int(self.getSettingValueByKey("t3_mix_start")); t3_mix_end = int(self.getSettingValueByKey("t3_mix_end")); t3_ext_incr = (t3_mix_start - t3_mix_end) / (layer_span - 1) else: - T2_mix_start = 0 - T2_mix_end = 0 - T2_ext_incr = 0 + t3_mix_start = 0; t3_mix_end = 0; t3_ext_incr = 0 # Check that the Start Percentages and the End Percentages add up to 100. If not then Exit with a message---- total_start_percent = 0 total_end_percent = 0 - if T0_include: - total_start_percent += T0_mix_start - total_end_percent += T0_mix_end - if T1_include: - total_start_percent += T1_mix_start - total_end_percent += T1_mix_end - if T2_include: - total_start_percent += T2_mix_start - total_end_percent += T2_mix_end + if t0_include: + total_start_percent += t0_mix_start + total_end_percent += t0_mix_end + if t1_include: + total_start_percent += t1_mix_start + total_end_percent += t1_mix_end + if t2_include: + total_start_percent += t2_mix_start + total_end_percent += t2_mix_end + if t3_include: + total_start_percent += t3_mix_start + total_end_percent += t3_mix_end - # Remove the existing tool changes and temperature lines from the data. This is supposed to leave one G92 E0 at each previous tool change------------------ + # Remove the existing tool changes and temperature lines from the data. This leaves one G92 E0 at each previous tool change------------------ for num in range(start_layer+2,len(data)-1,1): data[num] = re.sub("G92 E0\nT(\d*)\n", "", data[num]) data[num] = re.sub("M109 S(\d.*)\n", "",data[num]) @@ -373,33 +426,39 @@ def execute(self, data): if mix_style == "constant": total_end_percent = 100 if total_start_percent != 100 or total_end_percent != 100: - textstring = "The post processor exited due to a 'Total Percentage' error. Start Total Percent = " + str(total_start_percent) + " EndTotalPercent = " + str(total_end_percent) + " Both sums must equal 100" - Message(text = "[Multi-Extruder Color Mixer]: {}".format(textstring)).show() - data[0] += "; [Multi-Extruder Color Mixer] Did not run because Start Total Percent = " + str(total_start_percent) + " EndTotalPercent = " + str(total_end_percent) + " Both sums must equal 100%\n" + textstring = "The post processor exited due to a 'Total Percentage' error. Start Total Percent = " + str(total_start_percent) + " EndTotalPercent = " + str(total_end_percent) + " Each sum must equal 100" + Message(title = "[Multi-Extruder Color Mixer]:", text = textstring).show() + data[0] += "; [Multi-Extruder Color Mixer] Did not run because Start Total Percent = " + str(total_start_percent) + " EndTotalPercent = " + str(total_end_percent) + " Each sum must equal 100%\n" return data # Put together the Reset String----------------------------------------------------------- - M163_reset = "" + m163_reset = "" if extruder_count == 2: - M163_reset = "M163 P0.50 S0" + "\nM163 P0.50 S1\n" - if extruder_count >= 3: - M163_reset = "M163 P0.33 S0" + "\nM163 P0.34 S1\n" + "M163 P0.33 S2\n" - M163_reset += "M164 S" + str(M164_ext_nr) + "\n" + m163_reset = "M163 P0.50 S0\nM163 P0.50 S1\n" + if extruder_count == 3: + m163_reset = "M163 P0.33 S0\nM163 P0.34 S1\nM163 P0.33 S2\n" + if extruder_count == 4: + m163_reset = "M163 P0.25 S0\nM163 P0.25 S1\nM163 P0.25 S2\nM163 P0.25 S3\n" + m163_reset += f"M164 S{m164_ext_nr}\n" # Put together the Initial Mix String----------------------------------- - if T0_include: - M163_T0 = "\nM163 P" + str(T0_mix_start/100) + " S0" + if t0_include: + m163_t0 = f"\nM163 P{t0_mix_start/100} S0" + else: + m163_t0 = "" + if t1_include: + m163_t1 = f"\nM163 P{t1_mix_start/100} S1" else: - M163_T0 = "" - if T1_include: - M163_T1 = "\nM163 P" + str(T1_mix_start/100) + " S1" + m163_t1 = "" + if t2_include: + m163_t2 = f"\nM163 P{t2_mix_start/100} S2" else: - M163_T1 = "" - if T2_include: - M163_T2 = "\nM163 P" + str(T2_mix_start/100) + " S2" + m163_t2 = "" + if t3_include: + m163_t3 = f"\nM163 P{t3_mix_start/100} S3" else: - M163_T2 = "" - M164str = M163_T0 + M163_T1 + M163_T2 + "\nM164 S" + str(M164_ext_nr) + "\nT" + str(M164_ext_nr) + m163_t3 = "" + m164str = m163_t0 + m163_t1 + m163_t2 + m163_t3 + "\nM164 S" + str(m164_ext_nr) + "\nT" + str(m164_ext_nr) # If purge is selected-------------------------------------------------------- initial_purge = "" @@ -407,11 +466,11 @@ def execute(self, data): final_string = "" if park_head: initial_purge = self.park_script(0, data, park_x, park_y, purge_amt)[1] - if park_head and M164_ext_nr != resume_ext_nr: + if park_head and m164_ext_nr != resume_ext_nr and not park_head_init_only: start_purge = self.park_script(start_layer, data, park_x, park_y, purge_amt)[1] if park_head and self.getSettingValueByKey("end_layer") != -1: final_string = self.park_script(end_layer, data, park_x, park_y, purge_amt)[0] - + # Check to see if a reset is already present (do to multiple instances of this post processor running) and if so then move on------------------------------- reset_present = False start_up_sect = data[1] @@ -422,12 +481,13 @@ def execute(self, data): reset_present = True break if not reset_present: - init_str = M163_T0 + M163_T1 + M163_T2 + "\nM164 S" + str(M164_ext_nr) + "\nT" + str(init_extruder) + init_str = m163_t0 + m163_t1 + m163_t2 + m163_t3 + "\nM164 S" + str(m164_ext_nr) + "\nT" + str(init_extruder) if start_layer > 0: init_str += initial_purge lines = data[1].split("\n") lines.insert(len(lines)-2, init_str[1:]) data[1] = "\n".join(lines) + # Constant if mix_style == "constant": self.processConstant(data, start_layer, @@ -436,8 +496,11 @@ def execute(self, data): park_x, park_y, purge_amt, - M164str, - resume_ext_nr) + m164str, + resume_ext_nr, + park_head_init_only) + + # Gradient elif mix_style == "gradient": self.processGradient(data, start_layer, @@ -446,23 +509,28 @@ def execute(self, data): park_x, park_y, purge_amt, - M164str, + m164str, resume_ext_nr, - T0_include, - T0_mix_start, - T0_ext_incr, - T1_include, - T1_mix_start, - T1_ext_incr, - T2_include, - T2_mix_start, - T2_ext_incr, - M163_T0, - M163_T1, - M163_T2, - M164_ext_nr) + t0_include, + t0_mix_start, + t0_ext_incr, + t1_include, + t1_mix_start, + t1_ext_incr, + t2_include, + t2_mix_start, + t2_ext_incr, + t3_include, + t3_mix_start, + t3_ext_incr, + m163_t0, + m163_t1, + m163_t2, + m163_t3, + m164_ext_nr, + park_head_init_only) if not reset_present: - data[len(data)-1] = M163_reset + "T" + str(resume_ext_nr) + "\n" + data[len(data)-1] + data[len(data)-1] = m163_reset + "T" + str(resume_ext_nr) + "\n" + data[len(data)-1] return data def processConstant(self, @@ -473,8 +541,9 @@ def processConstant(self, park_x: str, park_y: str, purge_amt: str, - M164str: str, - resume_ext_nr: int) -> str: + m164str: str, + resume_ext_nr: int, + park_head_init_only: bool) -> str: pre_ret = False post_prime = False for index, layer in enumerate(data): @@ -508,8 +577,9 @@ def processConstant(self, add_str = self.park_script(start_layer, data, park_x, park_y, purge_amt)[3] elif not park_head: add_str = "" - - data[index] = layer.replace(";LAYER:" + str(start_layer) + "\n", ";LAYER:" + str(start_layer) + M164str + add_str + "\n") + #if park_head_init_only: + # add_str = "" + data[index] = layer.replace(";LAYER:" + str(start_layer) + "\n", ";LAYER:" + str(start_layer) + m164str + add_str + "\n") if ";LAYER:" + str(end_layer) in layer: lines = layer.split("\n") # The last retraction and prime------------------------------------------ @@ -529,8 +599,8 @@ def processConstant(self, pre_ret = True break # Add final line depending on retraction and prime------------------------------- - if park_head: - if not pre_ret and not post_prime: + if park_head and not park_head_init_only: + if not pre_ret: final_string = self.park_script(end_layer, data, park_x, park_y, purge_amt)[0] elif not pre_ret and post_prime: final_string = self.park_script(end_layer, data, park_x, park_y, purge_amt)[1] @@ -540,6 +610,8 @@ def processConstant(self, final_string = self.park_script(end_layer, data, park_x, park_y, purge_amt)[3] elif not park_head: final_string = "" + #if park_head_init_only: + # final_string = "" data[index] = data[index].replace(";LAYER:" + str(end_layer), ";LAYER:" + str(end_layer) + "\n" + "T" + str(resume_ext_nr) + final_string) break return @@ -552,21 +624,26 @@ def processGradient(self, park_x: str, park_y: str, purge_amt: str, - M164str: str, + m164str: str, resume_ext_nr: int, - T0_include: bool, - T0_mix_start: int, - T0_ext_incr: int, - T1_include: bool, - T1_mix_start: int, - T1_ext_incr: int, - T2_include:bool, - T2_mix_start: int, - T2_ext_incr: int, - M163_T0: str, - M163_T1: str, - M163_T2: str, - M164_ext_nr: int) -> str: + t0_include: bool, + t0_mix_start: int, + t0_ext_incr: int, + t1_include: bool, + t1_mix_start: int, + t1_ext_incr: int, + t2_include:bool, + t2_mix_start: int, + t2_ext_incr: int, + t3_include:bool, + t3_mix_start: int, + t3_ext_incr: int, + m163_t0: str, + m163_t1: str, + m163_t2: str, + m163_t3: str, + m164_ext_nr: int, + park_head_init_only: bool) -> str: pre_ret = False post_prime = False for index, layer in enumerate(data): @@ -600,36 +677,44 @@ def processGradient(self, add_str = self.park_script(start_layer, data, park_x, park_y, purge_amt)[3] elif not park_head: add_str = "" - - data[index] = data[index].replace(";LAYER:" + str(start_layer) + "\n", ";LAYER:" + str(start_layer) + M164str + add_str + "\n") + + # Gradient percentages and fix rounding errors------------------------------ + data[index] = data[index].replace(";LAYER:" + str(start_layer) + "\n", ";LAYER:" + str(start_layer) + m164str + add_str + "\n") for L in range(index + 1, len(data)-2): - if T0_include: - T0_mix_start -= T0_ext_incr - if T0_mix_start > 100: T0_mix_start = 100 - if T0_mix_start < 0: T0_mix_start = 0 - M163_T0 = "\nM163 P" + str(round(T0_mix_start/100, 2)) + " S0" + if t0_include: + t0_mix_start -= t0_ext_incr + if t0_mix_start > 100: t0_mix_start = 100 + if t0_mix_start < 0: t0_mix_start = 0 + m163_t0 = f"\nM163 P{round(t0_mix_start/100, 2)} S0" + else: + m163_t0 = "" + if t1_include: + t1_mix_start -= t1_ext_incr + if t1_mix_start > 100: t1_mix_start = 100 + if t1_mix_start < 0: t1_mix_start = 0 + m163_t1 = f"\nM163 P{round(t1_mix_start/100, 2)} S1" else: - M163_T0 = "" - if T1_include: - T1_mix_start -= T1_ext_incr - if T1_mix_start > 100: T1_mix_start = 100 - if T1_mix_start < 0: T1_mix_start = 0 - M163_T1 = "\nM163 P" + str(round(T1_mix_start/100, 2)) + " S1" + m163_t1 = "" + if t2_include: + t2_mix_start -= t2_ext_incr + if t2_mix_start > 100: t2_mix_start = 100 + if t2_mix_start < 0: t2_mix_start = 0 + m163_t2 = f"\nM163 P{round(t2_mix_start/100, 2)} S2" else: - M163_T1 = "" - if T2_include: - T2_mix_start -= T2_ext_incr - if T2_mix_start > 100: T2_mix_start = 100 - if T2_mix_start < 0: T2_mix_start = 0 - M163_T2 = "\nM163 P" + str(round(T2_mix_start/100, 2)) + " S2" + m163_t2 = "" + if t3_include: + t3_mix_start -= t3_ext_incr + if t3_mix_start > 100: t3_mix_start = 100 + if t3_mix_start < 0: t3_mix_start = 0 + m163_t3 = f"\nM163 P{round(t3_mix_start/100, 2)} S3" else: - M163_T2 = "" - M164str = M163_T0 + M163_T1 + M163_T2 + "\nM164 S" + str(M164_ext_nr) + "\nT" + str(M164_ext_nr) + "\n" + m163_t3 = "" + m164str = m163_t0 + m163_t1 + m163_t2 + m163_t3 + "\nM164 S" + str(m164_ext_nr) + "\nT" + str(m164_ext_nr) + "\n" try: lines = data[L].split("\n") layer_num = int(lines[0].split(":")[1]) if layer_num < end_layer: - data[L] = data[L].replace(";LAYER:" + str(layer_num) + "\n", ";LAYER:" + str(layer_num) + M164str) + data[L] = data[L].replace(";LAYER:" + str(layer_num) + "\n", ";LAYER:" + str(layer_num) + m164str) elif layer_num == end_layer: lines = layer.split("\n") # determine retraction and prime------------------------------------ @@ -649,7 +734,7 @@ def processGradient(self, pre_ret = True break # Add the final line depending on retraction and prime - if park_head: + if park_head and not park_head_init_only: if not pre_ret and not post_prime: final_string = self.park_script(end_layer, data, park_x, park_y, purge_amt)[0] elif not pre_ret and post_prime: @@ -660,19 +745,21 @@ def processGradient(self, final_string = self.park_script(end_layer, data, park_x, park_y, purge_amt)[3] elif not park_head: final_string = "" - M164str = "\nT" + str(resume_ext_nr) - data[L] = data[L].replace(";LAYER:" + str(end_layer), ";LAYER:" + str(end_layer) + M164str + final_string) + if park_head_init_only: + final_string = "" + m164str = "\nT" + str(resume_ext_nr) + data[L] = data[L].replace(";LAYER:" + str(end_layer), ";LAYER:" + str(end_layer) + m164str + final_string) break except: - all + pass if layer_num == end_layer: break return @staticmethod def park_script(purge_layer: str, data: str, park_x: str, park_y: str, retract_amt: str) -> str: # Put together the park/purge lines to be inserted---------------------------- - MyCura = Application.getInstance().getGlobalContainerStack() - extruder = MyCura.extruderList + mycura = Application.getInstance().getGlobalContainerStack() + extruder = mycura.extruderList if int(purge_layer) < 50: zup = " Z12\n" zdn = " Z-12\n" @@ -699,38 +786,31 @@ def park_script(purge_layer: str, data: str, park_x: str, park_y: str, retract_a yloc = " Y" + str(ytemp) if xloc != "" and yloc != "": break - park_ret_prime = "\n; Multi Mix Purge\nG91\nM83\n" - park_ret = "\n; Multi Mix Purge\nG91\nM83\n" - park_prime = "\n; Multi Mix Purge\nG91\nM83\n" - park_none = "\n; Multi Mix Purge\nG91\nM83\n" - firmware_retract = bool(MyCura.getProperty("machine_firmware_retract", "value")) + park_ret_prime = "\n;TYPE:CUSTOM Multi Mix Purge\nG91\nM83\n" + park_ret = "\n;TYPE:CUSTOM Multi Mix Purge\nG91\nM83\n" + park_prime = "\n;TYPE:CUSTOM Multi Mix Purge\nG91\nM83\n" + park_none = "\n;TYPE:CUSTOM Multi Mix Purge\nG91\nM83\n" + firmware_retract = bool(mycura.getProperty("machine_firmware_retract", "value")) speed_travel = str(int(extruder[0].getProperty("speed_travel", "value")) * 60) speed_print = str(int(extruder[0].getProperty("speed_print", "value")) * 60) speed_z_hop = str(int(extruder[0].getProperty("speed_z_hop", "value")) * 60) retract_distance = str(extruder[0].getProperty("retraction_amount", "value")) speed_retract = " F" + str(int(extruder[0].getProperty("retraction_retract_speed", "value")) *60) - relative_ext = bool(MyCura.getProperty("relative_extrusion", "value")) - if relative_ext: - relative_str = "M83\n" - else: - relative_str = "M82\n" - if firmware_retract: - E_retract = "G10\n" - E_prime = "G11\n" - else: - E_retract = "G1" + speed_retract + " E-" + retract_distance + "\n" - E_prime = "G1" + speed_retract + " E" + retract_distance + "\n" + relative_ext = bool(mycura.getProperty("relative_extrusion", "value")) + relative_str = "M83\n" if relative_ext else "M82\n" + e_retract = "G10\n" if firmware_retract else f"G1{speed_retract} E-{retract_distance}\n" + e_prime = "G11\n" if firmware_retract else f"G1{speed_retract} E{retract_distance}\n" hop_str = "G1 F" + speed_z_hop + zup - park_at_str = "G0 F" + speed_travel + " X" + park_x + " Y" + park_y + "\n" - purge_str = "G1" + " F200" + " E" + retract_amt + "\n" + park_at_str = f"G0 F{speed_travel} X{park_x} Y{park_y}\n" + purge_str = f"G1 F200 E{retract_amt}\n" goto_str = "G0 F" + speed_travel + str(xloc) + str(yloc) + "\n" z_str = "G91\nG1 F" + speed_z_hop + zdn # Used when yes retraction and yes prime - park_ret_prime += E_retract + hop_str + "G90\n" + park_at_str + purge_str + E_retract + goto_str + z_str + E_prime + relative_str + "G90\nG1 F" + speed_print + "\n; End of Purge" + park_ret_prime += e_retract + hop_str + "G90\n" + park_at_str + purge_str + e_retract + goto_str + z_str + e_prime + relative_str + "G90\nG1 F" + speed_print + "\n; End of Purge" # Used when yes retraction and no prime - park_ret += E_retract + hop_str + "G90\n" + park_at_str + purge_str + E_retract + goto_str + z_str + relative_str + "G90\nG1 F" + speed_print + "\n; End of Purge" + park_ret += e_retract + hop_str + "G90\n" + park_at_str + purge_str + e_retract + goto_str + z_str + relative_str + "G90\nG1 F" + speed_print + "\n; End of Purge" # Used when no retraction and yes prime - park_prime += hop_str + "G90\n" + park_at_str + purge_str + E_retract + goto_str + z_str + E_prime + relative_str + "G90\nG1 F" + speed_print + "\n; End of Purge" + park_prime += hop_str + "G90\n" + park_at_str + purge_str + e_retract + goto_str + z_str + e_prime + relative_str + "G90\nG1 F" + speed_print + "\n; End of Purge" # Used when no retraction and no prime - park_none += hop_str + "G90\n" + park_at_str + purge_str + E_retract + goto_str + z_str + relative_str + "G90\nG1 F" + speed_print + "\n; End of Purge" + park_none += hop_str + "G90\n" + park_at_str + purge_str + e_retract + goto_str + z_str + relative_str + "G90\nG1 F" + speed_print + "\n; End of Purge" return park_ret_prime, park_ret, park_prime, park_none \ No newline at end of file