From da0fe19c962c5e9b22c1b53949ca1d05b3addae5 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sun, 31 Mar 2024 07:55:36 -0400 Subject: [PATCH 001/299] Update DisplayInfoOnLCD.py Bug fix for "remaining_time". Affected M118 and M73_time Update DisplayInfoOnLCD.py Add options for Time-to-pause to include Filament Change. Update DisplayInfoOnLCD.py Make M117 optional. Combine M73 R and M73 P lines into a single line. Add A and P parameters for M118 lines. Update DisplayInfoOnLCD A TouchUp. Update DisplayInfoOnLCD.py TouchUp Update DisplayInfoOnLCD.py TuneUp --- .../scripts/DisplayInfoOnLCD.py | 265 +++++++++++++----- .../scripts/DisplayInfoOnLCD.zip | Bin 0 -> 7911 bytes 2 files changed, 195 insertions(+), 70 deletions(-) create mode 100644 plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.zip diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 63c1c8c788..870a64834d 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -7,7 +7,8 @@ # Cura Post-Process plugin # Combines 'Display Filename and Layer on the LCD' with 'Display Progress' # Combined and with additions by: GregValiant (Greg Foresi) -# Date: September 8, 2023 +# Date: September 8, 2023 +# Date: March 31, 2024 - Bug fix for problem with adding M118 lines if 'Remaining Time' was not checked. # NOTE: This combined post processor will make 'Display Filename and Layer on the LCD' and 'Display Progress' obsolete # Description: Display Filename and Layer options: # Status messages sent to the printer... @@ -34,9 +35,19 @@ import time import datetime import math from UM.Message import Message +import re class DisplayInfoOnLCD(Script): + def initialize(self) -> None: + super().initialize() + try: + if Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") == "all_at_once": + enable_countdown = True + self._instance.setProperty("enable_countdown", "value", enable_countdown) + except: + pass + def getSettingDataString(self): return """{ "name": "Display Info on LCD", @@ -77,7 +88,7 @@ class DisplayInfoOnLCD(Script): "label": "Initial layer number:", "description": "Choose which number you prefer for the initial layer, 0 or 1", "type": "int", - "default_value": 0, + "default_value": 1, "minimum_value": 0, "maximum_value": 1, "enabled": "display_option == 'filename_layer'" @@ -114,17 +125,40 @@ class DisplayInfoOnLCD(Script): "default_value": true, "enabled": "display_option == 'display_progress'" }, + "add_m117_line": + { + "label": "Add M117 Line", + "description": "M117 sends a message to the LCD screen. Some screen firmware will not accept or display messages.", + "type": "bool", + "default_value": true + }, "add_m118_line": { "label": "Add M118 Line", "description": "Adds M118 in addition to the M117. It will bounce the message back through the USB port to a computer print server (if a printer server like Octoprint or Pronterface is in use).", "type": "bool", - "default_value": false + "default_value": true + }, + "add_m118_a1": + { + "label": " Add A1 to M118 Line", + "description": "Adds A1 parameter. A1 adds a double foreslash '//' to the response. Octoprint may require this.", + "type": "bool", + "default_value": false, + "enabled": "add_m118_line" + }, + "add_m118_p0": + { + "label": " Add P0 to M118 Line", + "description": "Adds P0 parameter. P0 has the printer send the response out through all it's ports. Octoprint may require this.", + "type": "bool", + "default_value": false, + "enabled": "add_m118_line" }, "add_m73_line": { "label": "Add M73 Line(s)", - "description": "Adds M73 in addition to the M117. For some firmware this will set the printers time and or percentage.", + "description": "Adds M73 in addition to the M117. For some firmware this will set the printers time and or percentage. M75 is added to the beginning of the file and M77 is added to the end of the file. M73 will be added if one or both of the following options is chosen.", "type": "bool", "default_value": false, "enabled": "display_option == 'display_progress'" @@ -132,7 +166,7 @@ class DisplayInfoOnLCD(Script): "add_m73_percent": { "label": " Add M73 Percentage", - "description": "Adds M73 with the P parameter. For some firmware this will set the printers 'percentage' of layers completed and it will count upward.", + "description": "Adds M73 with the P parameter to the start of each layer. For some firmware this will set the printers 'percentage' of layers completed and it will count upward.", "type": "bool", "default_value": false, "enabled": "add_m73_line and display_option == 'display_progress'" @@ -140,10 +174,10 @@ class DisplayInfoOnLCD(Script): "add_m73_time": { "label": " Add M73 Time", - "description": "Adds M73 with the R parameter. For some firmware this will set the printers 'print time' and it will count downward.", + "description": "Adds M73 with the R parameter to the start of each layer. For some firmware this will set the printers 'print time' and it will count downward.", "type": "bool", "default_value": false, - "enabled": "add_m73_line and display_option == 'display_progress'" + "enabled": "add_m73_line and display_option == 'display_progress' and display_remaining_time" }, "speed_factor": { @@ -154,13 +188,29 @@ class DisplayInfoOnLCD(Script): "default_value": 100, "enabled": "enable_end_message or display_option == 'display_progress'" }, + "enable_countdown": + { + "label": "Enable Countdown to Pauses", + "description": "If print sequence is 'one_at_a_time' this is false. This setting is always hidden.", + "type": "bool", + "value": false, + "enabled": false + }, "countdown_to_pause": { "label": "Countdown to Pauses", - "description": "Instead of the remaining print time the LCD will show the estimated time to pause (TP).", + "description": "This must run AFTER any script that adds a pause. Instead of the remaining print time the LCD will show the estimated time to the next layer that has a pause (TP).", "type": "bool", "default_value": false, - "enabled": "display_option == 'display_progress'" + "enabled": "display_option == 'display_progress' and enable_countdown and display_remaining_time" + }, + "pause_cmd": + { + "label": " What pause command(s) are used?", + "description": "This might be M0, or M25 or M600 if Filament Change is used. If you have mixed commands then delimit them with a comma ',' (Ex: M0,M600). Spaces are not allowed.", + "type": "str", + "default_value": "M0", + "enabled": "countdown_to_pause and enable_countdown and display_remaining_time" }, "enable_end_message": { @@ -173,40 +223,57 @@ class DisplayInfoOnLCD(Script): "print_start_time": { "label": "Print Start Time (Ex 16:45)", - "description": "Use 'Military' time. 16:45 would be 4:45PM. 09:30 would be 9:30AM. If you leave this blank it will be assumed that the print will start Now. If you enter a guesstimate of your printer start time and that time is before 'Now' the guesstimate will consider that the print will start tomorrow at the entered time. ", + "description": "Use 'Military' time. 16:45 would be 4:45PM. 09:30 would be 9:30AM. If you leave this blank it will be assumed that the print will start Now. If you enter a guesstimate of your printer start time and that time is before 'Now' then the guesstimate will consider that the print will start tomorrow at the entered time. ", "type": "str", "default_value": "", "unit": "hrs ", "enabled": "enable_end_message" } - } }""" def execute(self, data): display_option = self.getSettingValueByKey("display_option") + add_m117_line = self.getSettingValueByKey("add_m117_line") add_m118_line = self.getSettingValueByKey("add_m118_line") + add_m118_a1 = self.getSettingValueByKey("add_m118_a1") + add_m118_p0 = self.getSettingValueByKey("add_m118_p0") + m118_text = "M118 " + m118_str = "M118 " + if add_m118_line: + if add_m118_a1 and not add_m118_p0: + m118_str = "M118 A1 " + if add_m118_p0 and not add_m118_a1: + m118_str = "M118 P0 " + if add_m118_p0 and add_m118_a1: + m118_str = "M118 A1 P0 " add_m73_line = self.getSettingValueByKey("add_m73_line") add_m73_time = self.getSettingValueByKey("add_m73_time") add_m73_percent = self.getSettingValueByKey("add_m73_percent") + m73_str = "" # This is Display Filename and Layer on LCD--------------------------------------------------------- if display_option == "filename_layer": max_layer = 0 lcd_text = "M117 " + octo_text = "M118 " if self.getSettingValueByKey("file_name") != "": file_name = self.getSettingValueByKey("file_name") else: file_name = Application.getInstance().getPrintInformation().jobName if self.getSettingValueByKey("addPrefixPrinting"): lcd_text += "Printing " + octo_text += "Printing " if not self.getSettingValueByKey("scroll"): lcd_text += "Layer " + octo_text += "Layer " else: lcd_text += file_name + " - Layer " + octo_text += file_name + " - Layer " i = self.getSettingValueByKey("startNum") for layer in data: display_text = lcd_text + str(i) + m118_text = octo_text + str(i) layer_index = data.index(layer) lines = layer.split("\n") for line in lines: @@ -217,18 +284,29 @@ class DisplayInfoOnLCD(Script): max_layer = str(int(max_layer) - 1) if line.startswith(";LAYER:"): if self.getSettingValueByKey("maxlayer"): - display_text = display_text + " of " + max_layer + display_text += " of " + max_layer + m118_text += " of " + max_layer if not self.getSettingValueByKey("scroll"): - display_text = display_text + " " + file_name + display_text += " " + file_name + m118_text += " " + file_name else: if not self.getSettingValueByKey("scroll"): - display_text = display_text + " " + file_name + "!" + display_text += " " + file_name + "!" + m118_text += " " + file_name + "!" else: - display_text = display_text + "!" + display_text += "!" + m118_text += "!" line_index = lines.index(line) - lines.insert(line_index + 1, display_text) + if add_m117_line: + lines.insert(line_index + 1, display_text) if add_m118_line: - lines.insert(line_index + 2, str(display_text.replace("M117", "M118", 1))) + if add_m118_a1 and not add_m118_p0: + m118_str = m118_text.replace("M118 ","M118 A1 ") + if add_m118_p0 and not add_m118_a1: + m118_str = m118_text.replace("M118 ","M118 P0 ") + if add_m118_p0 and add_m118_a1: + m118_str = m118_text.replace("M118 ","M118 A1 P0 ") + lines.insert(line_index + 2, m118_str) i += 1 final_lines = "\n".join(lines) data[layer_index] = final_lines @@ -239,7 +317,13 @@ class DisplayInfoOnLCD(Script): # Display Progress (from 'Show Progress' and 'Display Progress on LCD')--------------------------------------- elif display_option == "display_progress": - # get settings + print_sequence = Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") + ## Add the Initial Layer Height just below Layer Height in data[0] + init_layer_hgt_line = ";Initial Layer Height: " + str(Application.getInstance().getGlobalContainerStack().getProperty("layer_height_0", "value")) + nozzle_size_line = ";Nozzle Size T0: " + str(Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("machine_nozzle_size", "value")) + match = re.search(";Layer height: (\d\.\d*)", data[0])[0] + data[0] = re.sub(match, match + "\n" + init_layer_hgt_line + "\n" + nozzle_size_line, data[0]) + ## Get settings display_total_layers = self.getSettingValueByKey("display_total_layers") display_remaining_time = self.getSettingValueByKey("display_remaining_time") speed_factor = self.getSettingValueByKey("speed_factor") / 100 @@ -249,12 +333,16 @@ class DisplayInfoOnLCD(Script): m73_time = True if add_m73_line and add_m73_percent: m73_percent = True - # initialize global variables + if add_m73_line: + data[1] = "M75\n" + data[1] + data[len(data)-1] += "M77\n" + ## Initialize some variables first_layer_index = 0 - time_total = 0 + time_total = int(data[0].split(";TIME:")[1].split("\n")[0]) number_of_layers = 0 time_elapsed = 0 - # if at least one of the settings is disabled, there is enough room on the display to display "layer" + + ## If at least one of the settings is disabled, there is enough room on the display to display "layer" first_section = data[0] lines = first_section.split("\n") for line in lines: @@ -268,28 +356,40 @@ class DisplayInfoOnLCD(Script): orig_hhh = cura_time/3600 orig_hr = round(orig_hhh // 1) orig_mmm = math.floor((orig_hhh % 1) * 60) - orig_sec = round((((orig_hhh % 1) * 60) % 1) * 60) - if add_m118_line: lines.insert(tindex + 3,"M118 Adjusted Print Time " + str(hr) + "hr " + str(mmm) + "min") - lines.insert(tindex + 3,"M117 ET " + str(hr) + "hr " + str(mmm) + "min") - # add M73 line at beginning + if add_m118_line: lines.insert(tindex + 5, m118_str + "Adjusted Print Time " + str(hr) + "hr " + str(mmm) + "min") + if add_m117_line: lines.insert(tindex + 5,"M117 ET " + str(hr) + "hr " + str(mmm) + "min") + ## Add M73 line at beginning mins = int(60 * hr + mmm) - if m73_time: - lines.insert(tindex + 3, "M73 R{}".format(mins)) - if m73_percent: - lines.insert(tindex + 3, "M73 P0") - # If Countdonw to pause is enabled then count the pauses + if add_m73_line and (add_m73_time or add_m73_percent): + if m73_time: + m73_str += " R{}".format(mins) + if m73_percent: + m73_str += " P0" + lines.insert(tindex + 4, "M73" + m73_str) + # If Countdown to pause is enabled then count the pauses pause_str = "" if bool(self.getSettingValueByKey("countdown_to_pause")): pause_count = 0 - for num in range(2,len(data) - 1, 1): - if "PauseAtHeight.py" in data[num]: - pause_count += 1 - pause_str = f" with {pause_count} pause(s)" - # This line goes in to convert seconds to hours and minutes - lines.insert(tindex + 3, f";Cura Time Estimate: {cura_time}sec = {orig_hr}hr {orig_mmm}min {orig_sec}sec {pause_str}") + pause_setting = self.getSettingValueByKey("pause_cmd").upper() + pause_cmd = [] + if "," in pause_setting: + pause_cmd = pause_setting.split(",") + else: + pause_cmd.append(pause_setting) + for q in range(0, len(pause_cmd)): + pause_cmd[q] = "\n" + pause_cmd[q] + for num in range(2,len(data) - 2, 1): + for q in range(0,len(pause_cmd)): + if pause_cmd[q] in data[num]: + pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) + pause_str = f" with {pause_count} pause(s)" + ## This line goes in to convert seconds to hours and minutes + lines.insert(tindex + 5, f";Cura Time Estimate: {orig_hr}hr {orig_mmm}min {pause_str}") data[0] = "\n".join(lines) - data[len(data)-1] += "M117 Orig Cura Est " + str(orig_hr) + "hr " + str(orig_mmm) + "min\n" - if add_m118_line: data[len(data)-1] += "M118 Est w/FudgeFactor " + str(speed_factor * 100) + "% was " + str(hr) + "hr " + str(mmm) + "min\n" + if add_m117_line: + data[len(data)-1] += "M117 Orig Cura Est " + str(orig_hr) + "hr " + str(orig_mmm) + "min\n" + if add_m118_line: + data[len(data)-1] += m118_str + " Est w/FudgeFactor " + str(speed_factor * 100) + "% was " + str(hr) + "hr " + str(mmm) + "min\n" if not display_total_layers or not display_remaining_time: base_display_text = "layer " else: @@ -308,6 +408,11 @@ class DisplayInfoOnLCD(Script): for line in data_section.split("\n"): if line.startswith(";LAYER_COUNT:"): number_of_layers = int(line.split(":")[1]) + if print_sequence == "one_at_a_time": + number_of_layers = 1 + for lay in range(2,len(data)-1,1): + if ";LAYER:" in data[lay]: + number_of_layers += 1 elif line.startswith(";TIME:"): time_total = int(line.split(":")[1]) # for all layers... @@ -352,15 +457,26 @@ class DisplayInfoOnLCD(Script): # insert the text AFTER the first line of the layer (in case other scripts use ";LAYER:") for l_index, line in enumerate(lines): if line.startswith(";LAYER:"): - lines[l_index] += "\nM117 " + display_text - # add M73 line - mins = int(60 * h + m) - if m73_time: - lines[l_index] += "\nM73 R{}".format(mins) - if m73_percent: - lines[l_index] += "\nM73 P" + str(round(int(current_layer) / int(number_of_layers) * 100)) + if add_m117_line: + lines[l_index] += "\nM117 " + display_text if add_m118_line: - lines[l_index] += "\nM118 " + display_text + a1_str = "" + p0_str = "" + if add_m118_a1: + a1_str = "A1 " + if add_m118_p0: + p0_str = "P0 " + lines[l_index] += "\nM118 " + a1_str + p0_str + display_text + # add M73 line + if display_remaining_time: + mins = int(60 * h + m) + if add_m73_line and (add_m73_time or add_m73_percent): + m73_str = "" + if m73_time and display_remaining_time: + m73_str += " R{}".format(mins) + if m73_percent: + m73_str += " P" + str(round(int(current_layer) / int(number_of_layers) * 100)) + lines[l_index] += "\nM73" + m73_str break # overwrite the layer with the modified layer data[layer_index] = "\n".join(lines) @@ -381,34 +497,29 @@ class DisplayInfoOnLCD(Script): if line.startswith(";TIME_ELAPSED:"): this_time = (float(line.split(":")[1]))*speed_factor time_list.append(str(this_time)) - if "PauseAtHeight.py" in layer: - for qnum in range(num - 1, pause_index, -1): - time_list[qnum] = str(float(this_time) - float(time_list[qnum])) + "P" - pause_index = num-1 + for p_cmd in pause_cmd: + if p_cmd in layer: + for qnum in range(num - 1, pause_index, -1): + time_list[qnum] = str(float(this_time) - float(time_list[qnum])) + "P" + pause_index = num-1 + break # Make the adjustments to the M117 (and M118) lines that are prior to a pause for num in range (2, len(data) - 1,1): layer = data[num] lines = layer.split("\n") for line in lines: - if line.startswith("M117") and "|" in line and "P" in time_list[num]: - M117_line = line.split("|")[0] + "| TP " - alt_time = time_list[num][:-1] - hhh = int(float(alt_time) / 3600) - if hhh > 0: - hhr = str(hhh) + "h" - else: - hhr = "" - mmm = ((float(alt_time) / 3600) - (int(float(alt_time) / 3600))) * 60 - sss = int((mmm - int(mmm)) * 60) - mmm = str(round(mmm)) + "m" - time_to_go = str(hhr) + str(mmm) - if hhr == "": time_to_go = time_to_go + str(sss) + "s" - M117_line = M117_line + time_to_go - layer = layer.replace(line, M117_line) - if line.startswith("M118") and "|" in line and "P" in time_list[num]: - M118_line = line.split("|")[0] + "| TP " + time_to_go - layer = layer.replace(line, M118_line) + try: + if line.startswith("M117") and "|" in line and "P" in time_list[num]: + time_to_go = self.get_time_to_go(time_list[num]) + M117_line = line.split("|")[0] + "| TP " + time_to_go + layer = layer.replace(line, M117_line) + if line.startswith("M118") and "|" in line and "P" in time_list[num]: + time_to_go = self.get_time_to_go(time_list[num]) + M118_line = line.split("|")[0] + "| TP " + time_to_go + layer = layer.replace(line, M118_line) + except: + continue data[num] = layer setting_data = "" if bool(self.getSettingValueByKey("enable_end_message")): @@ -476,8 +587,22 @@ class DisplayInfoOnLCD(Script): if print_start_time != "": print_start_str = "Print Start Time................." + str(print_start_time) + "hrs" else: - print_start_str = "Print Start Time.................Now." + print_start_str = "Print Start Time.................Now" estimate_str = "Cura Time Estimate.........." + str(print_time) adjusted_str = "Adjusted Time Estimate..." + str(time_change) finish_str = week_day + " " + str(mo_str) + " " + str(new_time.strftime("%d")) + ", " + str(new_time.strftime("%Y")) + " at " + str(show_hr) + str(new_time.strftime("%M")) + str(show_ampm) - return finish_str, estimate_str, adjusted_str, print_start_str \ No newline at end of file + return finish_str, estimate_str, adjusted_str, print_start_str + + def get_time_to_go(self, time_str: str): + alt_time = time_str[:-1] + hhh = int(float(alt_time) / 3600) + if hhh > 0: + hhr = str(hhh) + "h" + else: + hhr = "" + mmm = ((float(alt_time) / 3600) - (int(float(alt_time) / 3600))) * 60 + sss = int((mmm - int(mmm)) * 60) + mmm = str(round(mmm)) + "m" + time_to_go = str(hhr) + str(mmm) + if hhr == "": time_to_go = time_to_go + str(sss) + "s" + return time_to_go \ No newline at end of file diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.zip b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.zip new file mode 100644 index 0000000000000000000000000000000000000000..fd9e5d90ae894ed7d61fce36a2fb771d58f0c026 GIT binary patch literal 7911 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 literal 0 HcmV?d00001 From 9fe36482f7978e87288d0994711412dc1be0473a Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sun, 7 Apr 2024 09:03:46 -0400 Subject: [PATCH 002/299] Delete DisplayInfoOnLCD.zip Should not have been included. --- .../scripts/DisplayInfoOnLCD.zip | Bin 7911 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.zip diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.zip b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.zip deleted file mode 100644 index fd9e5d90ae894ed7d61fce36a2fb771d58f0c026..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7911 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 From df9862b86610a0726f659d3cff7418837e177ac5 Mon Sep 17 00:00:00 2001 From: GeekyKayaker Date: Mon, 22 Jul 2024 17:04:17 +0100 Subject: [PATCH 003/299] Add some options to CreateThumbnail to allow for some customisation over the format of the begin block for the image --- .../scripts/CreateThumbnail.py | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/CreateThumbnail.py b/plugins/PostProcessingPlugin/scripts/CreateThumbnail.py index 7d6094ade3..8f0c74ceee 100644 --- a/plugins/PostProcessingPlugin/scripts/CreateThumbnail.py +++ b/plugins/PostProcessingPlugin/scripts/CreateThumbnail.py @@ -35,16 +35,21 @@ class CreateThumbnail(Script): def _convertSnapshotToGcode(self, encoded_snapshot, width, height, chunk_size=78): gcode = [] + use_thumbnail = self.getSettingValueByKey("use_thumbnail") + use_star = self.getSettingValueByKey("use_star") + encoded_snapshot_length = len(encoded_snapshot) + image_type = "thumbnail" if use_thumbnail else "png" + resolution_symbol = '*' if use_star else 'x' gcode.append(";") - gcode.append("; thumbnail begin {}x{} {}".format( - width, height, encoded_snapshot_length)) + gcode.append("; {} begin {}{}{} {}".format( + image_type, width, resolution_symbol, height, encoded_snapshot_length)) chunks = ["; {}".format(encoded_snapshot[i:i+chunk_size]) for i in range(0, len(encoded_snapshot), chunk_size)] gcode.extend(chunks) - gcode.append("; thumbnail end") + gcode.append("; {} end".format(image_type)) gcode.append(";") gcode.append("") @@ -79,6 +84,20 @@ class CreateThumbnail(Script): "minimum_value": "0", "minimum_value_warning": "12", "maximum_value_warning": "600" + }, + "use_thumbnail": + { + "label": "Thumbnail Begin/End", + "description": "Use Thumbnail Begin/End rather than PNG", + "type": "bool", + "default_value": true + }, + "use_star": + { + "label": "xxx*yyy", + "description": "Use '*' instead of 'x' for size of image", + "type": "bool", + "default_value": false } } }""" From f22b86a3cac17b7d22a60f4b0d139c9bac7fe8ce Mon Sep 17 00:00:00 2001 From: whoseyoung Date: Sat, 12 Oct 2024 18:28:31 +0800 Subject: [PATCH 004/299] Add geeetech M1 profile Printing settings for the M1 machine provided by Geeetech officially. --- resources/definitions/geeetech_M1.def.json | 57 +++++++++++++++++++ .../geeetech_M1_0.2.inst.cfg | 13 +++++ .../geeetech_M1_0.3.inst.cfg | 13 +++++ .../geeetech_M1_0.4.inst.cfg | 13 +++++ .../geeetech_M1_0.5.inst.cfg | 13 +++++ .../geeetech_M1_0.6.inst.cfg | 13 +++++ .../geeetech_M1_0.8.inst.cfg | 13 +++++ .../geeetech_M1_1.0.inst.cfg | 13 +++++ 8 files changed, 148 insertions(+) create mode 100644 resources/definitions/geeetech_M1.def.json create mode 100644 resources/variants/geeetech_variants/geeetech_M1_0.2.inst.cfg create mode 100644 resources/variants/geeetech_variants/geeetech_M1_0.3.inst.cfg create mode 100644 resources/variants/geeetech_variants/geeetech_M1_0.4.inst.cfg create mode 100644 resources/variants/geeetech_variants/geeetech_M1_0.5.inst.cfg create mode 100644 resources/variants/geeetech_variants/geeetech_M1_0.6.inst.cfg create mode 100644 resources/variants/geeetech_variants/geeetech_M1_0.8.inst.cfg create mode 100644 resources/variants/geeetech_variants/geeetech_M1_1.0.inst.cfg diff --git a/resources/definitions/geeetech_M1.def.json b/resources/definitions/geeetech_M1.def.json new file mode 100644 index 0000000000..02a59eb1c0 --- /dev/null +++ b/resources/definitions/geeetech_M1.def.json @@ -0,0 +1,57 @@ +{ + "version": 2, + "name": "Geeetech M1", + "inherits": "Geeetech_Base_Single_Extruder", + "metadata": + { + "visible": true, + "machine_extruder_trains": { "0": "Geeetech_Single_Extruder" } + }, + "overrides": + { + "gantry_height": { "value": 35 }, + "machine_depth": { "default_value": 105 }, + "machine_end_gcode": { "default_value": "G91 ;Switch to relative positioning\nG1 E-2.5 F2700 ;Retract filament\nG1 E-1.5 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Move away\nG1 Z10 ;lift print head\nG90 ;Switch to absolute positioning\nG28 X Y ;homing XY\nM106 S0 ;off Fan\nM104 S0 ;Cooldown hotend\nM140 S0 ;Cooldown bed\nM84 X Y E ;Disable steppers" }, + "machine_head_with_fans_polygon": + { + "default_value": [ + [-31, 31], + [34, 31], + [34, -40], + [-31, -40] + ] + }, + "machine_height": { "default_value": 95 }, + "machine_name": { "default_value": "Geeetech M1" }, + "machine_start_gcode": { "default_value": "\nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 ;Off Main Fan\nM300 S2500 P1000 ;Play a short tune\nG1 Z0.28 ;Move Z Axis up little to prevent scratching of Heat Bed\nG92 E0 ;Reset Extruder\nG1 Y3 F2400 ;Move to start position\nG1 X75 E40 F500 ;Draw a filament line\nG92 E0 ;Reset Extruder\n;G1 E-0.2 F3000 ;Retract a little\nG1 Z2.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X70 Y3 Z0.27 F3000 ;Quickly wipe away from the filament line\nG92 E0 ;Reset Extruder" }, + "machine_width": { "default_value": 105 }, + "retraction_amount": { "value": 1 }, + "material_print_temperature": + { + "maximum_value": "250", + "value": "200 if speed_infill <=100 else 210 if speed_infill <= 150 else 220 if speed_infill <= 200 else 230" + }, + "speed_print": + { + "maximum_value_warning": "200", + "value": 120 + }, + "speed_wall": + { + "maximum_value_warning": "200", + "value": 80 + }, + "speed_wall_0": + { "maximum_value_warning": "200", + "value": 50 + }, + "speed_wall_x": + { "maximum_value_warning": "200", + "value": 80 + }, + "speed_topbottom": + { "maximum_value_warning": "200", + "value": 60 + } + } +} \ No newline at end of file diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.2.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.2.inst.cfg new file mode 100644 index 0000000000..055fbeb747 --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1_0.2.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1 +name = 0.2mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 23 +type = variant + +[values] +machine_nozzle_size = 0.2 + diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.3.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.3.inst.cfg new file mode 100644 index 0000000000..a442fb90d9 --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1_0.3.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1 +name = 0.3mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 23 +type = variant + +[values] +machine_nozzle_size = 0.3 + diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.4.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.4.inst.cfg new file mode 100644 index 0000000000..d33b7647a9 --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1_0.4.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1 +name = 0.4mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 23 +type = variant + +[values] +machine_nozzle_size = 0.4 + diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.5.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.5.inst.cfg new file mode 100644 index 0000000000..49cb4702b2 --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1_0.5.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1 +name = 0.5mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 23 +type = variant + +[values] +machine_nozzle_size = 0.5 + diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.6.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.6.inst.cfg new file mode 100644 index 0000000000..b2afb9c63e --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1_0.6.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1 +name = 0.6mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 23 +type = variant + +[values] +machine_nozzle_size = 0.6 + diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.8.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.8.inst.cfg new file mode 100644 index 0000000000..15a4c2c58d --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1_0.8.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1 +name = 0.8mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 23 +type = variant + +[values] +machine_nozzle_size = 0.8 + diff --git a/resources/variants/geeetech_variants/geeetech_M1_1.0.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_1.0.inst.cfg new file mode 100644 index 0000000000..4749c6c464 --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1_1.0.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1 +name = 1.0mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 23 +type = variant + +[values] +machine_nozzle_size = 1.0 + From b66cc9d990e56a4356aec7deee518b7dc282d207 Mon Sep 17 00:00:00 2001 From: whoseyoung Date: Sat, 12 Oct 2024 10:30:18 +0000 Subject: [PATCH 005/299] Applied printer-linter format --- resources/definitions/geeetech_M1.def.json | 45 ++++++++++++---------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/resources/definitions/geeetech_M1.def.json b/resources/definitions/geeetech_M1.def.json index 02a59eb1c0..f0ee942386 100644 --- a/resources/definitions/geeetech_M1.def.json +++ b/resources/definitions/geeetech_M1.def.json @@ -25,33 +25,36 @@ "machine_name": { "default_value": "Geeetech M1" }, "machine_start_gcode": { "default_value": "\nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 ;Off Main Fan\nM300 S2500 P1000 ;Play a short tune\nG1 Z0.28 ;Move Z Axis up little to prevent scratching of Heat Bed\nG92 E0 ;Reset Extruder\nG1 Y3 F2400 ;Move to start position\nG1 X75 E40 F500 ;Draw a filament line\nG92 E0 ;Reset Extruder\n;G1 E-0.2 F3000 ;Retract a little\nG1 Z2.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X70 Y3 Z0.27 F3000 ;Quickly wipe away from the filament line\nG92 E0 ;Reset Extruder" }, "machine_width": { "default_value": 105 }, - "retraction_amount": { "value": 1 }, - "material_print_temperature": + "material_print_temperature": { "maximum_value": "250", "value": "200 if speed_infill <=100 else 210 if speed_infill <= 150 else 220 if speed_infill <= 200 else 230" - }, - "speed_print": + }, + "retraction_amount": { "value": 1 }, + "speed_print": { "maximum_value_warning": "200", "value": 120 }, - "speed_wall": - { - "maximum_value_warning": "200", - "value": 80 - }, - "speed_wall_0": - { "maximum_value_warning": "200", - "value": 50 - }, - "speed_wall_x": - { "maximum_value_warning": "200", - "value": 80 - }, - "speed_topbottom": - { "maximum_value_warning": "200", - "value": 60 - } + "speed_topbottom": + { + "maximum_value_warning": "200", + "value": 60 + }, + "speed_wall": + { + "maximum_value_warning": "200", + "value": 80 + }, + "speed_wall_0": + { + "maximum_value_warning": "200", + "value": 50 + }, + "speed_wall_x": + { + "maximum_value_warning": "200", + "value": 80 + } } } \ No newline at end of file From 72f1ac1a0341f216fbb0fde9e39547f80e826c19 Mon Sep 17 00:00:00 2001 From: whoseyoung Date: Thu, 24 Oct 2024 14:36:45 +0800 Subject: [PATCH 006/299] All issue items processed. --- resources/definitions/geeetech_M1.def.json | 6 +++--- .../variants/geeetech_variants/geeetech_M1_0.2.inst.cfg | 2 +- .../variants/geeetech_variants/geeetech_M1_0.3.inst.cfg | 2 +- .../variants/geeetech_variants/geeetech_M1_0.4.inst.cfg | 2 +- .../variants/geeetech_variants/geeetech_M1_0.5.inst.cfg | 2 +- .../variants/geeetech_variants/geeetech_M1_0.6.inst.cfg | 2 +- .../variants/geeetech_variants/geeetech_M1_0.8.inst.cfg | 2 +- .../variants/geeetech_variants/geeetech_M1_1.0.inst.cfg | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/resources/definitions/geeetech_M1.def.json b/resources/definitions/geeetech_M1.def.json index f0ee942386..4afb9f4d60 100644 --- a/resources/definitions/geeetech_M1.def.json +++ b/resources/definitions/geeetech_M1.def.json @@ -23,12 +23,12 @@ }, "machine_height": { "default_value": 95 }, "machine_name": { "default_value": "Geeetech M1" }, - "machine_start_gcode": { "default_value": "\nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 ;Off Main Fan\nM300 S2500 P1000 ;Play a short tune\nG1 Z0.28 ;Move Z Axis up little to prevent scratching of Heat Bed\nG92 E0 ;Reset Extruder\nG1 Y3 F2400 ;Move to start position\nG1 X75 E40 F500 ;Draw a filament line\nG92 E0 ;Reset Extruder\n;G1 E-0.2 F3000 ;Retract a little\nG1 Z2.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X70 Y3 Z0.27 F3000 ;Quickly wipe away from the filament line\nG92 E0 ;Reset Extruder" }, + "machine_start_gcode": { "default_value": ";Geeetech M1 official wiki URL for M1:https://www.geeetech.com/wiki/index.php/Geeetech_M1_3D_printer \nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 ;Off Main Fan\nM300 S2500 P1000 ;Play a short tune\nG1 Z0.28 ;Move Z Axis up little to prevent scratching of Heat Bed\nG92 E0 ;Reset Extruder\nG1 Y3 F2400 ;Move to start position\nG1 X75 E40 F500 ;Draw a filament line\nG92 E0 ;Reset Extruder\n;G1 E-0.2 F3000 ;Retract a little\nG1 Z2.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X70 Y3 Z0.27 F3000 ;Quickly wipe away from the filament line\nG92 E0 ;Reset Extruder" }, "machine_width": { "default_value": 105 }, "material_print_temperature": { - "maximum_value": "250", - "value": "200 if speed_infill <=100 else 210 if speed_infill <= 150 else 220 if speed_infill <= 200 else 230" + "maximum_value": "230", + "value": "205 if speed_infill <=100 else 215 if speed_infill <= 150 else 220 if speed_infill <= 200 else 230" }, "retraction_amount": { "value": 1 }, "speed_print": diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.2.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.2.inst.cfg index 055fbeb747..2ab1f4dd00 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_0.2.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_0.2.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 24 type = variant [values] diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.3.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.3.inst.cfg index a442fb90d9..f2cd78d138 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_0.3.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_0.3.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 24 type = variant [values] diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.4.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.4.inst.cfg index d33b7647a9..aee452940d 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_0.4.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_0.4.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 24 type = variant [values] diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.5.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.5.inst.cfg index 49cb4702b2..dbd7e2a69c 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_0.5.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_0.5.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 24 type = variant [values] diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.6.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.6.inst.cfg index b2afb9c63e..9c542b5fb2 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_0.6.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_0.6.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 24 type = variant [values] diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.8.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.8.inst.cfg index 15a4c2c58d..628e670353 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_0.8.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_0.8.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 24 type = variant [values] diff --git a/resources/variants/geeetech_variants/geeetech_M1_1.0.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_1.0.inst.cfg index 4749c6c464..7a7618760a 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_1.0.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_1.0.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 24 type = variant [values] From 7be35b6bc14a61b2376d3c0e8f8336463f3b62d7 Mon Sep 17 00:00:00 2001 From: whoseyoung Date: Thu, 24 Oct 2024 06:37:41 +0000 Subject: [PATCH 007/299] Applied printer-linter format --- resources/definitions/geeetech_M1.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/geeetech_M1.def.json b/resources/definitions/geeetech_M1.def.json index 4afb9f4d60..fe4b248305 100644 --- a/resources/definitions/geeetech_M1.def.json +++ b/resources/definitions/geeetech_M1.def.json @@ -23,7 +23,7 @@ }, "machine_height": { "default_value": 95 }, "machine_name": { "default_value": "Geeetech M1" }, - "machine_start_gcode": { "default_value": ";Geeetech M1 official wiki URL for M1:https://www.geeetech.com/wiki/index.php/Geeetech_M1_3D_printer \nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 ;Off Main Fan\nM300 S2500 P1000 ;Play a short tune\nG1 Z0.28 ;Move Z Axis up little to prevent scratching of Heat Bed\nG92 E0 ;Reset Extruder\nG1 Y3 F2400 ;Move to start position\nG1 X75 E40 F500 ;Draw a filament line\nG92 E0 ;Reset Extruder\n;G1 E-0.2 F3000 ;Retract a little\nG1 Z2.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X70 Y3 Z0.27 F3000 ;Quickly wipe away from the filament line\nG92 E0 ;Reset Extruder" }, + "machine_start_gcode": { "default_value": ";Geeetech M1 official wiki URL for M1\uff1ahttps://www.geeetech.com/wiki/index.php/Geeetech_M1_3D_printer \nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 ;Off Main Fan\nM300 S2500 P1000 ;Play a short tune\nG1 Z0.28 ;Move Z Axis up little to prevent scratching of Heat Bed\nG92 E0 ;Reset Extruder\nG1 Y3 F2400 ;Move to start position\nG1 X75 E40 F500 ;Draw a filament line\nG92 E0 ;Reset Extruder\n;G1 E-0.2 F3000 ;Retract a little\nG1 Z2.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X70 Y3 Z0.27 F3000 ;Quickly wipe away from the filament line\nG92 E0 ;Reset Extruder" }, "machine_width": { "default_value": 105 }, "material_print_temperature": { From a4d9d309638c154ace93267261d43a0f0b5b8e8f Mon Sep 17 00:00:00 2001 From: whoseyoung Date: Fri, 15 Nov 2024 14:39:26 +0800 Subject: [PATCH 008/299] Updated geeetech_M1.def.json --- resources/definitions/geeetech_M1.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/geeetech_M1.def.json b/resources/definitions/geeetech_M1.def.json index fe4b248305..2ab9447205 100644 --- a/resources/definitions/geeetech_M1.def.json +++ b/resources/definitions/geeetech_M1.def.json @@ -23,7 +23,7 @@ }, "machine_height": { "default_value": 95 }, "machine_name": { "default_value": "Geeetech M1" }, - "machine_start_gcode": { "default_value": ";Geeetech M1 official wiki URL for M1\uff1ahttps://www.geeetech.com/wiki/index.php/Geeetech_M1_3D_printer \nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 ;Off Main Fan\nM300 S2500 P1000 ;Play a short tune\nG1 Z0.28 ;Move Z Axis up little to prevent scratching of Heat Bed\nG92 E0 ;Reset Extruder\nG1 Y3 F2400 ;Move to start position\nG1 X75 E40 F500 ;Draw a filament line\nG92 E0 ;Reset Extruder\n;G1 E-0.2 F3000 ;Retract a little\nG1 Z2.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X70 Y3 Z0.27 F3000 ;Quickly wipe away from the filament line\nG92 E0 ;Reset Extruder" }, + "machine_start_gcode": { "default_value": ";Geeetech M1 official wiki URL:https://www.geeetech.com/wiki/index.php/Geeetech_M1_3D_printer \nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM140 S{material_bed_temperature_layer_0} ; Set Bed Temperature\n;M190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 ;Off Fan\nM300 S2500 P1000 ;Play a short tune\nG1 Z0.28 ;Move Z Axis up little to prevent scratching of Heat Bed\nG92 E0 ;Reset Extruder\nG1 Y3 F2400 ;Move to start position\nG1 X75 E40 F500 ;Draw a filament line\nG92 E0 ;Reset Extruder\n;G1 E-0.2 F3000 ;Retract a little\nG1 Z2.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X70 Y3 Z0.27 F3000 ;Quickly wipe away from the filament line\nG92 E0 ;Reset Extruder" }, "machine_width": { "default_value": 105 }, "material_print_temperature": { From 5a8087d47da74c8ff0611ed4c674170c2023d548 Mon Sep 17 00:00:00 2001 From: JoGrob <59739587+JoGrob@users.noreply.github.com> Date: Sun, 17 Nov 2024 17:15:16 +0100 Subject: [PATCH 009/299] Update sovol_sv01.def.json bowden -> titan --- resources/definitions/sovol_sv01.def.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/definitions/sovol_sv01.def.json b/resources/definitions/sovol_sv01.def.json index 9d77c1c3f6..dd64702f7f 100644 --- a/resources/definitions/sovol_sv01.def.json +++ b/resources/definitions/sovol_sv01.def.json @@ -1,11 +1,11 @@ { "version": 2, "name": "Sovol SV01", - "inherits": "sovol_base_bowden", + "inherits": "sovol_base_titan", "metadata": { "visible": true, - "quality_definition": "sovol_base_bowden" + "quality_definition": "sovol_base_titan" }, "overrides": { @@ -26,4 +26,4 @@ "machine_start_gcode": { "default_value": "M201 X500.00 Y500.00 Z100.00 E5000.00 ;Setup machine max acceleration\nM203 X500.00 Y500.00 Z10.00 E50.00 ;Setup machine max feedrate\nM204 P500.00 R1000.00 T500.00 ;Setup Print/Retract/Travel acceleration\nM205 X8.00 Y8.00 Z0.40 E5.00 ;Setup Jerk\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\n\nG28 ;Home\n\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\n" }, "machine_width": { "default_value": 280 } } -} \ No newline at end of file +} From eec792db0ac697345cf45828e34591785268d9a2 Mon Sep 17 00:00:00 2001 From: Asterchades Date: Thu, 28 Nov 2024 16:08:37 +1000 Subject: [PATCH 010/299] Update fdmprinter.def.json Set global Top and Bottom Layer values to match previous Ultimaker defaults. --- resources/definitions/fdmprinter.def.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index c930a624d0..a4adfd1d83 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1595,7 +1595,7 @@ "maximum_value": "999999", "type": "int", "minimum_value_warning": "2", - "value": "0 if infill_sparse_density == 100 else math.ceil(round(top_thickness / resolveOrValue('layer_height'), 4))", + "value": "math.ceil(round(top_thickness / resolveOrValue('layer_height'), 4))" "limit_to_extruder": "top_bottom_extruder_nr", "settable_per_mesh": true } @@ -1625,7 +1625,7 @@ "default_value": 6, "maximum_value": "999999", "type": "int", - "value": "999999 if infill_sparse_density == 100 and not magic_spiralize else math.ceil(round(bottom_thickness / resolveOrValue('layer_height'), 4))", + "value": "math.ceil(round(bottom_thickness / resolveOrValue('layer_height'), 4))" "limit_to_extruder": "top_bottom_extruder_nr", "settable_per_mesh": true }, @@ -9193,4 +9193,4 @@ } } } -} \ No newline at end of file +} From e0cda11b811c4a704289661852549a9f847db636 Mon Sep 17 00:00:00 2001 From: Asterchades Date: Thu, 28 Nov 2024 16:09:20 +1000 Subject: [PATCH 011/299] Update ultimaker.def.json Removed Top and Bottom Layers values. With global defaults updated it is no longer required to re-set them. --- resources/definitions/ultimaker.def.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/resources/definitions/ultimaker.def.json b/resources/definitions/ultimaker.def.json index 65ceaf6f0f..b1a1cf87b1 100644 --- a/resources/definitions/ultimaker.def.json +++ b/resources/definitions/ultimaker.def.json @@ -16,7 +16,6 @@ { "acceleration_layer_0": { "value": "acceleration_topbottom" }, "acceleration_travel_enabled": { "value": false }, - "bottom_layers": { "value": "math.ceil(round(bottom_thickness / resolveOrValue('layer_height'), 4))" }, "bridge_enable_more_layers": { "value": false }, "bridge_fan_speed": { "value": "cool_fan_speed_max" }, "bridge_fan_speed_2": { "value": "cool_fan_speed_min" }, @@ -131,7 +130,6 @@ "support_wall_count": { "value": "1 if support_structure == 'tree' else 0" }, "support_xy_distance_overhang": { "value": "0.2" }, "support_z_distance": { "value": "0" }, - "top_layers": { "value": "math.ceil(round(top_thickness / resolveOrValue('layer_height'), 4))" }, "wall_0_material_flow_layer_0": { "value": "1.10 * material_flow_layer_0" }, "wall_thickness": { "value": "wall_line_width_0 + wall_line_width_x" }, "wall_x_material_flow_layer_0": { "value": "0.95 * material_flow_layer_0" }, @@ -141,4 +139,4 @@ "z_seam_relative": { "value": "True" }, "zig_zaggify_support": { "value": true } } -} \ No newline at end of file +} From cabd4261c2bd5ecc63971175d50c6656be570a03 Mon Sep 17 00:00:00 2001 From: Asterchades Date: Thu, 28 Nov 2024 16:10:58 +1000 Subject: [PATCH 012/299] Update fdmprinter.def.json Restore missing commas. Going to need those. --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index a4adfd1d83..64e3c7d963 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1595,7 +1595,7 @@ "maximum_value": "999999", "type": "int", "minimum_value_warning": "2", - "value": "math.ceil(round(top_thickness / resolveOrValue('layer_height'), 4))" + "value": "math.ceil(round(top_thickness / resolveOrValue('layer_height'), 4))", "limit_to_extruder": "top_bottom_extruder_nr", "settable_per_mesh": true } @@ -1625,7 +1625,7 @@ "default_value": 6, "maximum_value": "999999", "type": "int", - "value": "math.ceil(round(bottom_thickness / resolveOrValue('layer_height'), 4))" + "value": "math.ceil(round(bottom_thickness / resolveOrValue('layer_height'), 4))", "limit_to_extruder": "top_bottom_extruder_nr", "settable_per_mesh": true }, From e7a1bf89ec94397c5952377de4e47272991a96e0 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Mon, 30 Dec 2024 16:35:02 -0500 Subject: [PATCH 013/299] Update DisplayInfoOnLCD.py Revised the M118 lines and insertion point in the gcode. Revised M117 same. Added nozzle size and filament type to data[0] --- .../scripts/DisplayInfoOnLCD.py | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 870a64834d..ed226c08f3 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -47,7 +47,7 @@ class DisplayInfoOnLCD(Script): self._instance.setProperty("enable_countdown", "value", enable_countdown) except: pass - + def getSettingDataString(self): return """{ "name": "Display Info on LCD", @@ -238,15 +238,6 @@ class DisplayInfoOnLCD(Script): add_m118_line = self.getSettingValueByKey("add_m118_line") add_m118_a1 = self.getSettingValueByKey("add_m118_a1") add_m118_p0 = self.getSettingValueByKey("add_m118_p0") - m118_text = "M118 " - m118_str = "M118 " - if add_m118_line: - if add_m118_a1 and not add_m118_p0: - m118_str = "M118 A1 " - if add_m118_p0 and not add_m118_a1: - m118_str = "M118 P0 " - if add_m118_p0 and add_m118_a1: - m118_str = "M118 A1 P0 " add_m73_line = self.getSettingValueByKey("add_m73_line") add_m73_time = self.getSettingValueByKey("add_m73_time") add_m73_percent = self.getSettingValueByKey("add_m73_percent") @@ -318,12 +309,22 @@ class DisplayInfoOnLCD(Script): # Display Progress (from 'Show Progress' and 'Display Progress on LCD')--------------------------------------- elif display_option == "display_progress": print_sequence = Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") - ## Add the Initial Layer Height just below Layer Height in data[0] + # Add the Initial Layer Height just below Layer Height in data[0] + extruder_count = Application.getInstance().getGlobalContainerStack().getProperty("machine_extruder_count", "value") init_layer_hgt_line = ";Initial Layer Height: " + str(Application.getInstance().getGlobalContainerStack().getProperty("layer_height_0", "value")) - nozzle_size_line = ";Nozzle Size T0: " + str(Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("machine_nozzle_size", "value")) - match = re.search(";Layer height: (\d\.\d*)", data[0])[0] - data[0] = re.sub(match, match + "\n" + init_layer_hgt_line + "\n" + nozzle_size_line, data[0]) - ## Get settings + nozzle_size_line = ";Nozzle Size T0: " + str(Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("machine_nozzle_size", "value")) + filament_type = "\n;Filament type for T0: " + str(Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("material_type", "value")) + if extruder_count > 1: + nozzle_size_line += "\n;Nozzle Size T1: " + str(Application.getInstance().getGlobalContainerStack().extruderList[1].getProperty("machine_nozzle_size", "value")) + filament_type += "\n;Filament type for T1: " + str(Application.getInstance().getGlobalContainerStack().extruderList[1].getProperty("material_type", "value")) + lines = data[0].split("\n") + for index, line in enumerate(lines): + if line.startswith(";Layer height:"): + lines[index] += "\n" + init_layer_hgt_line + "\n" + nozzle_size_line + if line.startswith(";Filament used"): + lines[index] += filament_type + data[0] = "\n".join(lines) + # Get settings display_total_layers = self.getSettingValueByKey("display_total_layers") display_remaining_time = self.getSettingValueByKey("display_remaining_time") speed_factor = self.getSettingValueByKey("speed_factor") / 100 @@ -336,13 +337,13 @@ class DisplayInfoOnLCD(Script): if add_m73_line: data[1] = "M75\n" + data[1] data[len(data)-1] += "M77\n" - ## Initialize some variables + # Initialize some variables first_layer_index = 0 time_total = int(data[0].split(";TIME:")[1].split("\n")[0]) number_of_layers = 0 time_elapsed = 0 - ## If at least one of the settings is disabled, there is enough room on the display to display "layer" + # If at least one of the settings is disabled, there is enough room on the display to display "layer" first_section = data[0] lines = first_section.split("\n") for line in lines: @@ -356,10 +357,10 @@ class DisplayInfoOnLCD(Script): orig_hhh = cura_time/3600 orig_hr = round(orig_hhh // 1) orig_mmm = math.floor((orig_hhh % 1) * 60) - if add_m118_line: lines.insert(tindex + 5, m118_str + "Adjusted Print Time " + str(hr) + "hr " + str(mmm) + "min") - if add_m117_line: lines.insert(tindex + 5,"M117 ET " + str(hr) + "hr " + str(mmm) + "min") - ## Add M73 line at beginning - mins = int(60 * hr + mmm) + if add_m118_line: lines.insert(tindex + 6,"M118 Adjusted Print Time " + str(hr) + "hr " + str(mmm) + "min") + if add_m117_line: lines.insert(tindex + 6,"M117 ET " + str(hr) + "hr " + str(mmm) + "min") + # Add M73 line at beginning + mins = int(60 * hr + mmm) if add_m73_line and (add_m73_time or add_m73_percent): if m73_time: m73_str += " R{}".format(mins) @@ -383,13 +384,13 @@ class DisplayInfoOnLCD(Script): if pause_cmd[q] in data[num]: pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) pause_str = f" with {pause_count} pause(s)" - ## This line goes in to convert seconds to hours and minutes - lines.insert(tindex + 5, f";Cura Time Estimate: {orig_hr}hr {orig_mmm}min {pause_str}") + # This line goes in to convert seconds to hours and minutes + lines.insert(tindex + 1, f";Cura Time Estimate: {orig_hr}hr {orig_mmm}min {pause_str}") data[0] = "\n".join(lines) if add_m117_line: data[len(data)-1] += "M117 Orig Cura Est " + str(orig_hr) + "hr " + str(orig_mmm) + "min\n" if add_m118_line: - data[len(data)-1] += m118_str + " Est w/FudgeFactor " + str(speed_factor * 100) + "% was " + str(hr) + "hr " + str(mmm) + "min\n" + data[len(data)-1] += "M118 Est w/FudgeFactor " + str(speed_factor * 100) + "% was " + str(hr) + "hr " + str(mmm) + "min\n" if not display_total_layers or not display_remaining_time: base_display_text = "layer " else: @@ -463,7 +464,7 @@ class DisplayInfoOnLCD(Script): a1_str = "" p0_str = "" if add_m118_a1: - a1_str = "A1 " + a1_str = "A1 " if add_m118_p0: p0_str = "P0 " lines[l_index] += "\nM118 " + a1_str + p0_str + display_text @@ -592,8 +593,8 @@ class DisplayInfoOnLCD(Script): adjusted_str = "Adjusted Time Estimate..." + str(time_change) finish_str = week_day + " " + str(mo_str) + " " + str(new_time.strftime("%d")) + ", " + str(new_time.strftime("%Y")) + " at " + str(show_hr) + str(new_time.strftime("%M")) + str(show_ampm) return finish_str, estimate_str, adjusted_str, print_start_str - - def get_time_to_go(self, time_str: str): + + def get_time_to_go(self, time_str: str): alt_time = time_str[:-1] hhh = int(float(alt_time) / 3600) if hhh > 0: From e91a636152499f95da04ba75badee132dbdd7cfd Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Wed, 1 Jan 2025 11:54:47 -0500 Subject: [PATCH 014/299] Update AddCoolingProfile.py Add control for a Build Volume fan. Update AddCoolingProfile.py Oops. Left in a debugging line. --- .../scripts/AddCoolingProfile.py | 286 +++++++++++++----- 1 file changed, 209 insertions(+), 77 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py index 44709afd24..ad00fbd923 100644 --- a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py +++ b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py @@ -1,16 +1,18 @@ # Designed in January 2023 by GregValiant (Greg Foresi) -## My design intent was to make this as full featured and "industrial strength" as I could. People printing exotic materials on large custom printers may want to turn the fans off for certain layers, and then back on again later in the print. This script allows that. +# My design intent was to make this as full featured and "industrial strength" as I could. People printing exotic materials on large custom printers may want to turn the fans off for certain layers, and then back on again later in the print. This script allows that. # Functions: -## Remove all fan speed lines from the file (optional). This should be enabled for the first instance of the script. It is disabled by default in any following instances. -## "By Layer" allows the user to adjust the fan speed up, or down, or off, within the print. "By Feature" allows different fan speeds for different features (;TYPE:WALL-OUTER, etc.). -## If 'By Feature' then a Start Layer and/or an End Layer can be defined. -## Fan speeds are scaled PWM (0 - 255) or RepRap (0.0 - 1.0) depending on {machine_scale_fan_speed_zero_to_one}. -## A minimum fan speed of 12% is enforced. It is the slowest speed that my cooling fan will turn on so that's what I used. 'M106 S14' (as Cura might insert) was pretty useless. -## If multiple extruders have separate fan circuits the speeds are set at tool changes and conform to the layer or feature setting. There is support for up to 4 layer cooling fan circuits. -## My thanks to @5axes(@CUQ), @fieldOfView(@AHoeben), @Ghostkeeper, and @Torgeir. A special thanks to @RBurema for his patience in reviewing my 'non-pythonic' script. -## 9/14/23 (Greg Foresi) Added support for One-at-a-Time print sequence. -## 12/15/23 (Greg Foresi) Split off 'Single Fan By Layer', 'Multi-fan By Layer', 'Single Fan By Feature', and 'Multi-fan By Feature' from the main 'execute' script. -## 1/5/24 (Greg Foresi) Revised the regex replacements. +# Remove all fan speed lines from the file (optional). This should be enabled for the first instance of the script. It is disabled by default in any following instances. +# "By Layer" allows the user to adjust the fan speed up, or down, or off, within the print. "By Feature" allows different fan speeds for different features (;TYPE:WALL-OUTER, etc.). +# If 'By Feature' then a Start Layer and/or an End Layer can be defined. +# Fan speeds are scaled PWM (0 - 255) or RepRap (0.0 - 1.0) depending on {machine_scale_fan_speed_zero_to_one}. +# A minimum fan speed of 12% is enforced. It is the slowest speed that my cooling fan will turn on so that's what I used. 'M106 S14' (as Cura might insert) was pretty useless. +# If multiple extruders have separate fan circuits the speeds are set at tool changes and conform to the layer or feature setting. There is support for up to 4 layer cooling fan circuits. +# My thanks to @5axes(@CUQ), @fieldOfView(@AHoeben), @Ghostkeeper, and @Torgeir. A special thanks to @RBurema for his patience in reviewing my 'non-pythonic' script. +# 09/14/23 (GV) Added support for One-at-a-Time print sequence. +# 12/15/23 (GV) Split off 'Single Fan By Layer', 'Multi-fan By Layer', 'Single Fan By Feature', and 'Multi-fan By Feature' from the main 'execute' script. +# 01/05/24 (GV) Revised the regex replacements. +# 12/11/24 (GV) Added 'off_fan_speed' for the idle nozzle layer cooling fan. It does not have to go to 0%. +# 01/01/25 (GV) Added 'Build Volume' fan control from ..Script import Script from UM.Application import Application @@ -273,37 +275,120 @@ class AddCoolingProfile(Script): "maximum_value": 100, "unit": "% ", "enabled": "fan_enable_raft" + }, + "enable_off_fan_speed": + { + "label": "Enable 'Off speed' of the idle fan", + "description": "For machines with independent layer cooling fans. Leaving a fan running while the other nozzle is printing can help with oozing. You can pick the speed % for the idle nozzle layer cooling fan to hold at.", + "type": "bool", + "default_value": false, + "enabled": "enable_off_fan_speed_enable" + }, + "off_fan_speed": + { + "label": " 'Off' speed of idle nozzle fan", + "description": "This is the speed that the 'idle nozzle' layer cooling fan will maintain rather than being turned off completely.", + "type": "int", + "default_value": 35, + "minimum_value": 0, + "maximum_value": 100, + "unit": "% ", + "enabled": "enable_off_fan_speed_enable and enable_off_fan_speed" + }, + "enable_off_fan_speed_enable": + { + "label": "Hidden setting", + "description": "For dual extruder printers, this enables 'enable_off_fan_speed'.", + "type": "bool", + "default_value": false, + "enabled": false + }, + "bv_fan_speed_control_enable": + { + "label": "Enable 'Chamber Fan' control", + "description": "Available if the 'Build Volume Fan Number' > 0 in 'Printer Settings'. Provides: On layer, off layer, and PWM speed control of the Chamber fan.", + "type": "bool", + "default_value": false, + "enabled": "enable_bv_fan" + }, + "bv_fan_speed": + { + "label": " Chamber fan speed %", + "description": "The speed of the Chamber Fan. This will be converted to PWM Duty Cycle (0-255).", + "type": "int", + "unit": "% ", + "default_value": 50, + "maximum_value": 100, + "minimum_value": 0, + "enabled": "enable_bv_fan and bv_fan_speed_control_enable" + }, + "bv_fan_start_layer": + { + "label": " Start Layer", + "description": "The layer number for Chamber Fan start. Use the Cura preview layer number. If you are using a raft the chanber fan will start when the raft finishes.", + "type": "int", + "default_value": 1, + "minimum_value": 1, + "enabled": "enable_bv_fan and bv_fan_speed_control_enable" + }, + "bv_fan_end_layer": + { + "label": " End Layer", + "description": "The layer number for Chamber Fan to turn off. Use the Cura preview layer number or '-1' to indicate the end of the print.", + "type": "int", + "default_value": -1, + "minimum_value": -1, + "enabled": "enable_bv_fan and bv_fan_speed_control_enable" + }, + "enable_bv_fan": + { + "label": "Hidden setting", + "description": "For printers with heated chambers and chamber fans, this enables 'bv_fan_speed_control_enable'.", + "type": "bool", + "default_value": false, + "enabled": false } } }""" def initialize(self) -> None: super().initialize() - scripts = Application.getInstance().getGlobalContainerStack().getMetaDataEntry("post_processing_scripts") + curaApp = Application.getInstance().getGlobalContainerStack() + extruder = curaApp.extruderList + scripts = curaApp.getMetaDataEntry("post_processing_scripts") if scripts != None: script_count = scripts.count("AddCoolingProfile") if script_count > 0: - ## Set 'Remove M106 lines' to "false" if there is already an instance of this script running. + # Set 'Remove M106 lines' to "false" if there is already an instance of this script running. self._instance.setProperty("delete_existing_m106", "value", False) + if curaApp.getProperty("machine_extruder_count", "value") > 1: + if extruder[0].getProperty("machine_extruder_cooling_fan_number", "value") != extruder[1].getProperty("machine_extruder_cooling_fan_number", "value"): + self._instance.setProperty("enable_off_fan_speed_enable", "value", True) + self.has_bv_fan = False + self.bv_fan_nr = -1 + if int(curaApp.getProperty("build_volume_fan_nr", "value")) > 0: + self.has_bv_fan = True + self.bv_fan_nr = int(curaApp.getProperty("build_volume_fan_nr", "value")) + self._instance.setProperty("enable_bv_fan", "value", True) def execute(self, data): #Initialize variables that are buried in if statements. - mycura = Application.getInstance().getGlobalContainerStack() + curaApp = Application.getInstance().getGlobalContainerStack() t0_fan = " P0"; t1_fan = " P0"; t2_fan = " P0"; t3_fan = " P0"; is_multi_extr_print = True #Get some information from Cura----------------------------------- - extruder = mycura.extruderList + extruder = curaApp.extruderList #This will be true when fan scale is 0-255pwm and false when it's RepRap 0-1 (Cura 5.x) fan_mode = True - ##For 4.x versions that don't have the 0-1 option + #For 4.x versions that don't have the 0-1 option try: fan_mode = not bool(extruder[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) except: pass bed_adhesion = (extruder[0].getProperty("adhesion_type", "value")) - extruder_count = mycura.getProperty("machine_extruder_count", "value") - print_sequence = str(mycura.getProperty("print_sequence", "value")) + extruder_count = curaApp.getProperty("machine_extruder_count", "value") + print_sequence = str(curaApp.getProperty("print_sequence", "value")) #Assign the fan numbers to the tools------------------------------ if extruder_count == 1: @@ -333,7 +418,7 @@ class AddCoolingProfile(Script): #Assign the variable values if "By Layer"------------------------- by_layer_or_feature = self.getSettingValueByKey("fan_layer_or_feature") if by_layer_or_feature == "by_layer": - ## By layer doesn't do any feature search so there is no need to look for combing moves + # By layer doesn't do any feature search so there is no need to look for combing moves feature_fan_combing = False fan_list[0] = self.getSettingValueByKey("layer_fan_1") fan_list[2] = self.getSettingValueByKey("layer_fan_2") @@ -343,25 +428,25 @@ class AddCoolingProfile(Script): fan_list[10] = self.getSettingValueByKey("layer_fan_6") fan_list[12] = self.getSettingValueByKey("layer_fan_7") fan_list[14] = self.getSettingValueByKey("layer_fan_8") - ## If there is no '/' delimiter then ignore the line else put the settings in a list + # If there is no '/' delimiter then ignore the line else put the settings in a list for num in range(0,15,2): if "/" in fan_list[num]: fan_list[num + 1] = self._layer_checker(fan_list[num], "p", fan_mode) fan_list[num] = self._layer_checker(fan_list[num], "l", fan_mode) - ## Assign the variable values if "By Feature" + # Assign the variable values if "By Feature" elif by_layer_or_feature == "by_feature": the_start_layer = self.getSettingValueByKey("feature_fan_start_layer") - 1 the_end_layer = self.getSettingValueByKey("feature_fan_end_layer") try: if int(the_end_layer) != -1: - ## Catch a possible input error. + # Catch a possible input error. if the_end_layer < the_start_layer: the_end_layer = the_start_layer except: - the_end_layer = -1 ## If there is an input error default to the entire gcode file. + the_end_layer = -1 # If there is an input error then default to the entire gcode file. - ## Get the speed for each feature + # Get the speed for each feature feature_name_list = [] feature_speed_list = [] feature_speed_list.append(self._feature_checker(self.getSettingValueByKey("feature_fan_skirt"), fan_mode)); feature_name_list.append(";TYPE:SKIRT") @@ -376,19 +461,28 @@ class AddCoolingProfile(Script): feature_speed_list.append(self._feature_checker(self.getSettingValueByKey("feature_fan_feature_final"), fan_mode)); feature_name_list.append("FINAL_FAN") feature_fan_combing = self.getSettingValueByKey("feature_fan_combing") if the_end_layer > -1 and by_layer_or_feature == "by_feature": - ## Required so the final speed input can be determined + # Required so the final speed input can be determined the_end_is_enabled = True else: - ## There is no ending layer so do the whole file + # There is no ending layer so do the whole file the_end_is_enabled = False if the_end_layer == -1 or the_end_is_enabled == False: the_end_layer = len(data) + 2 - ## Find the Layer0Index and the RaftIndex + # For multi-extruder printers with separate fans the 'idle' nozzle fan can be left on for ooze control + off_fan_speed = 0 + if Application.getInstance().getGlobalContainerStack().getProperty("machine_extruder_count", "value") > 1: + if self.getSettingValueByKey("enable_off_fan_speed"): + if fan_mode: + off_fan_speed = round(int(self.getSettingValueByKey("off_fan_speed")) * 2.55) + else: + off_fan_speed = round(int(self.getSettingValueByKey("off_fan_speed")) * .01, 2) + + # Find the Layer0Index and the RaftIndex raft_start_index = 0 number_of_raft_layers = 0 layer_0_index = 0 - ## Catch the number of raft layers. + # Catch the number of raft layers. for l_num in range(1,10,1): layer = data[l_num] if ";LAYER:-" in layer: @@ -399,13 +493,13 @@ class AddCoolingProfile(Script): layer_0_index = l_num break - ## Is this a single extruder print on a multi-extruder printer? - get the correct fan number for the extruder being used. + # Is this a single extruder print on a multi-extruder printer? - get the correct fan number for the extruder being used. if is_multi_fan: T0_used = False T1_used = False T2_used = False T3_used = False - ## Bypass the file header and ending gcode. + # Bypass the file header and ending gcode. for num in range(1,len(data)-1,1): lines = data[num] if "T0" in lines: @@ -418,7 +512,7 @@ class AddCoolingProfile(Script): T3_used = True is_multi_extr_print = True if sum([T0_used, T1_used, T2_used, T3_used]) > 1 else False - ## On a multi-extruder printer and single extruder print find out which extruder starts the file. + # On a multi-extruder printer and single extruder print find out which extruder starts the file. init_fan = t0_fan if not is_multi_extr_print: startup = data[1] @@ -431,7 +525,7 @@ class AddCoolingProfile(Script): elif line == "T3": t0_fan = t3_fan elif is_multi_extr_print: - ## On a multi-extruder printer and multi extruder print find out which extruder starts the file. + # On a multi-extruder printer and multi extruder print find out which extruder starts the file. startup = data[1] lines = startup.split("\n") for line in lines: @@ -445,7 +539,7 @@ class AddCoolingProfile(Script): init_fan = t3_fan else: init_fan = "" - ## Assign the variable values if "Raft Enabled" + # Assign the variable values if "Raft Enabled" raft_enabled = self.getSettingValueByKey("fan_enable_raft") if raft_enabled and bed_adhesion == "raft": fan_sp_raft = self._feature_checker(self.getSettingValueByKey("fan_raft_percent"), fan_mode) @@ -453,15 +547,15 @@ class AddCoolingProfile(Script): fan_sp_raft = "M106 S0" # Start to alter the data----------------------------------------- - ## Strip the existing M106 lines from the file up to the end of the last layer. If a user wants to use more than one instance of this plugin then they won't want to erase the M106 lines that the preceding plugins inserted so 'delete_existing_m106' is an option. + # Strip the existing M106 lines from the file up to the end of the last layer. If a user wants to use more than one instance of this plugin then they won't want to erase the M106 lines that the preceding plugins inserted so 'delete_existing_m106' is an option. delete_existing_m106 = self.getSettingValueByKey("delete_existing_m106") if delete_existing_m106: - ## Start deleting from the beginning + # Start deleting from the beginning start_from = int(raft_start_index) else: if by_layer_or_feature == "by_layer": altered_start_layer = str(len(data)) - ## The fan list layers don't need to be in ascending order. Get the lowest. + # The fan list layers don't need to be in ascending order. Get the lowest. for num in range(0,15,2): try: if int(fan_list[num]) < int(altered_start_layer): @@ -471,12 +565,12 @@ class AddCoolingProfile(Script): elif by_layer_or_feature == "by_feature": altered_start_layer = int(the_start_layer) - 1 start_from = int(layer_0_index) + int(altered_start_layer) - ## Strip the M106 and M107 lines from the file + # Strip the M106 and M107 lines from the file for l_index in range(int(start_from), len(data) - 1, 1): data[l_index] = re.sub(re.compile("M106(.*)\n"), "", data[l_index]) data[l_index] = re.sub(re.compile("M107(.*)\n"), "", data[l_index]) - ## Deal with a raft and with One-At-A-Time print sequence + # Deal with a raft and with One-At-A-Time print sequence if raft_enabled and bed_adhesion == "raft": if print_sequence == "one_at_a_time": for r_index in range(2,len(data)-2,1): @@ -486,9 +580,9 @@ class AddCoolingProfile(Script): lines.insert(1, "M106 S0" + str(t0_fan)) if raft_enabled and bed_adhesion == "raft": if ";LAYER:-" in data[r_index]: - ## Turn the raft fan on + # Turn the raft fan on lines.insert(1, fan_sp_raft + str(t0_fan)) - ## Shut the raft fan off at layer 0 + # Shut the raft fan off at layer 0 if ";LAYER:0" in data[r_index]: lines.insert(1,"M106 S0" + str(t0_fan)) data[r_index] = "\n".join(lines) @@ -496,13 +590,13 @@ class AddCoolingProfile(Script): layer = data[raft_start_index] lines = layer.split("\n") if ";LAYER:-" in layer: - ## Turn the raft fan on + # Turn the raft fan on lines.insert(1, fan_sp_raft + str(init_fan)) layer = "\n".join(lines) data[raft_start_index] = layer layer = data[layer_0_index] lines = layer.split("\n") - ## Shut the raft fan off + # Shut the raft fan off lines.insert(1, "M106 S0" + str(init_fan)) data[layer_0_index] = "\n".join(lines) else: @@ -513,31 +607,34 @@ class AddCoolingProfile(Script): lines.insert(1, "M106 S0" + str(t0_fan)) data[r_index] = "\n".join(lines) - ## Turn off all fans at the end of data[1]. If more than one instance of this script is running then this will result in multiple M106 lines. + # Turn off all fans at the end of data[1]. If more than one instance of this script is running then this will result in multiple M106 lines. temp_startup = data[1].split("\n") temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t0_fan)) - ## If there are multiple cooling fans shut them all off + # If there are multiple cooling fans shut them all off if is_multi_fan: if extruder_count > 1 and t1_fan != t0_fan: temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t1_fan)) if extruder_count > 2 and t2_fan != t1_fan and t2_fan != t0_fan: temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t2_fan)) if extruder_count > 3 and t3_fan != t2_fan and t3_fan != t1_fan and t3_fan != t0_fan: temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t3_fan)) data[1] = "\n".join(temp_startup) - ## If 'feature_fan_combing' is True then add additional 'MESH:NONMESH' lines for travel moves over 5 lines long - ## For compatibility with 5.3.0 change any MESH:NOMESH to MESH:NONMESH. + # If 'feature_fan_combing' is True then add additional 'MESH:NONMESH' lines for travel moves over 5 lines long + # For compatibility with 5.3.0 change any MESH:NOMESH to MESH:NONMESH. if feature_fan_combing: for layer_num in range(2,len(data)): layer = data[layer_num] data[layer_num] = re.sub(";MESH:NOMESH", ";MESH:NONMESH", layer) data = self._add_travel_comment(data, layer_0_index) - + # If there is a build volume fan + if self.has_bv_fan: + if self.getSettingValueByKey("bv_fan_speed_control_enable"): + data = self._control_bv_fan(data) # Single Fan "By Layer"-------------------------------------------- if by_layer_or_feature == "by_layer" and not is_multi_fan: return self._single_fan_by_layer(data, layer_0_index, fan_list, t0_fan) # Multi-Fan "By Layer"--------------------------------------------- if by_layer_or_feature == "by_layer" and is_multi_fan: - return self._multi_fan_by_layer(data, layer_0_index, fan_list, t0_fan, t1_fan, t2_fan, t3_fan) + return self._multi_fan_by_layer(data, layer_0_index, fan_list, t0_fan, t1_fan, t2_fan, t3_fan, fan_mode, off_fan_speed) #Single Fan "By Feature"------------------------------------------ if by_layer_or_feature == "by_feature" and (not is_multi_fan or not is_multi_extr_print): @@ -545,7 +642,7 @@ class AddCoolingProfile(Script): #Multi Fan "By Feature"------------------------------------------- if by_layer_or_feature == "by_feature" and is_multi_fan: - return self._multi_fan_by_feature(data, layer_0_index, the_start_layer, the_end_layer, the_end_is_enabled, fan_list, t0_fan, t1_fan, t2_fan, t3_fan, feature_speed_list, feature_name_list, feature_fan_combing) + return self._multi_fan_by_feature(data, layer_0_index, the_start_layer, the_end_layer, the_end_is_enabled, fan_list, t0_fan, t1_fan, t2_fan, t3_fan, feature_speed_list, feature_name_list, feature_fan_combing, fan_mode, off_fan_speed) # The Single Fan "By Layer"---------------------------------------- def _single_fan_by_layer(self, data: str, layer_0_index: int, fan_list: str, t0_fan: str)->str: @@ -557,7 +654,7 @@ class AddCoolingProfile(Script): for fan_line in fan_lines: if ";LAYER:" in fan_line: layer_number = str(fan_line.split(":")[1]) - ## If there is a match for the current layer number make the insertion + # If there is a match for the current layer number make the insertion for num in range(0,15,2): if layer_number == str(fan_list[num]): layer = layer.replace(fan_lines[0],fan_lines[0] + "\n" + fan_list[num + 1] + str(t0_fan)) @@ -565,7 +662,7 @@ class AddCoolingProfile(Script): return single_fan_data # Multi-Fan "By Layer"----------------------------------------- - def _multi_fan_by_layer(self, data: str, layer_0_index: int, fan_list: str, t0_fan: str, t1_fan: str, t2_fan: str, t3_fan: str)->str: + def _multi_fan_by_layer(self, data: str, layer_0_index: int, fan_list: str, t0_fan: str, t1_fan: str, t2_fan: str, t3_fan: str, fan_mode: bool, off_fan_speed: str)->str: multi_fan_data = data layer_number = "0" current_fan_speed = "0" @@ -573,15 +670,15 @@ class AddCoolingProfile(Script): this_fan = str(t0_fan) start_index = str(len(multi_fan_data)) for num in range(0,15,2): - ## The fan_list may not be in ascending order. Get the lowest layer number + # The fan_list may not be in ascending order. Get the lowest layer number try: if int(fan_list[num]) < int(start_index): start_index = str(fan_list[num]) except: pass - ## Move the start point if delete_existing_m106 is false + # Move the start point if delete_existing_m106 is false start_index = int(start_index) + int(layer_0_index) - ## Track the tool number + # Track the tool number for num in range(1,int(start_index),1): layer = multi_fan_data[num] lines = layer.split("\n") @@ -603,13 +700,13 @@ class AddCoolingProfile(Script): layer = multi_fan_data[l_index] fan_lines = layer.split("\n") for fan_line in fan_lines: - ## Prepare to shut down the previous fan and start the next one. + # Prepare to shut down the previous fan and start the next one. if fan_line.startswith("T"): if fan_line == "T0": this_fan = str(t0_fan) if fan_line == "T1": this_fan = str(t1_fan) if fan_line == "T2": this_fan = str(t2_fan) if fan_line == "T3": this_fan = str(t3_fan) - modified_data += "M106 S0" + prev_fan + "\n" + modified_data += f"M106 S{off_fan_speed}" + prev_fan + "\n" modified_data += fan_line + "\n" modified_data += "M106 S" + str(current_fan_speed) + this_fan + "\n" prev_fan = this_fan @@ -620,11 +717,14 @@ class AddCoolingProfile(Script): if layer_number == str(fan_list[num]): modified_data += fan_list[num + 1] + this_fan + "\n" current_fan_speed = str(fan_list[num + 1].split("S")[1]) - current_fan_speed = str(current_fan_speed.split(" ")[0]) ## Just in case + current_fan_speed = str(current_fan_speed.split(" ")[0]) # Just in case else: modified_data += fan_line + "\n" if modified_data.endswith("\n"): modified_data = modified_data[0:-1] multi_fan_data[l_index] = modified_data + # Insure the fans get shut off if 'off_fan_speed' was enabled + if Application.getInstance().getGlobalContainerStack().getProperty("machine_extruder_count", "value") > 1 and self.getSettingValueByKey("enable_off_fan_speed"): + multi_fan_data[-1] += "M106 S0 P1\nM106 S0 P0\n" return multi_fan_data # Single fan by feature----------------------------------------------- @@ -632,7 +732,7 @@ class AddCoolingProfile(Script): single_fan_data = data layer_number = "0" index = 1 - ## Start with layer:0 + # Start with layer:0 for l_index in range(layer_0_index,len(single_fan_data)-1,1): modified_data = "" layer = single_fan_data[l_index] @@ -652,7 +752,7 @@ class AddCoolingProfile(Script): if feature_fan_combing == True: modified_data += "M106 S0" + t0_fan + "\n" modified_data += line + "\n" - ## If an End Layer is defined and is less than the last layer then insert the Final Speed + # If an End Layer is defined and is less than the last layer then insert the Final Speed if line == ";LAYER:" + str(the_end_layer) and the_end_is_enabled == True: modified_data += feature_speed_list[len(feature_speed_list) - 1] + t0_fan + "\n" if modified_data.endswith("\n"): modified_data = modified_data[0: - 1] @@ -660,7 +760,7 @@ class AddCoolingProfile(Script): return single_fan_data # Multi-fan by feature------------------------------------------------ - def _multi_fan_by_feature(self, data: str, layer_0_index: int, the_start_layer: str, the_end_layer: str, the_end_is_enabled: str, fan_list: str, t0_fan: str, t1_fan: str, t2_fan: str, t3_fan: str, feature_speed_list: str, feature_name_list: str, feature_fan_combing: bool)->str: + def _multi_fan_by_feature(self, data: str, layer_0_index: int, the_start_layer: str, the_end_layer: str, the_end_is_enabled: str, fan_list: str, t0_fan: str, t1_fan: str, t2_fan: str, t3_fan: str, feature_speed_list: str, feature_name_list: str, feature_fan_combing: bool, fan_mode: bool, off_fan_speed: str)->str: multi_fan_data = data layer_number = "0" start_index = 1 @@ -673,7 +773,7 @@ class AddCoolingProfile(Script): if ";LAYER:" + str(the_start_layer) + "\n" in layer: start_index = int(my_index) - 1 break - ## Track the previous tool changes + # Track the previous tool changes for num in range(1,start_index,1): layer = multi_fan_data[num] lines = layer.split("\n") @@ -690,7 +790,7 @@ class AddCoolingProfile(Script): elif line == "T3": prev_fan = this_fan this_fan = t3_fan - ## Get the current tool. + # Get the current tool. for l_index in range(start_index,start_index + 1,1): layer = multi_fan_data[l_index] lines = layer.split("\n") @@ -702,7 +802,7 @@ class AddCoolingProfile(Script): if line == "T3": this_fan = t3_fan prev_fan = this_fan - ## Start to make insertions------------------------------------- + # Start to make insertions------------------------------------- for l_index in range(start_index+1,len(multi_fan_data)-1,1): layer = multi_fan_data[l_index] lines = layer.split("\n") @@ -712,10 +812,10 @@ class AddCoolingProfile(Script): if line == "T1": this_fan = t1_fan if line == "T2": this_fan = t2_fan if line == "T3": this_fan = t3_fan - ## Turn off the prev fan - modified_data += "M106 S0" + prev_fan + "\n" + # Turn off the prev fan + modified_data += f"M106 S{off_fan_speed}" + prev_fan + "\n" modified_data += line + "\n" - ## Turn on the current fan + # Turn on the current fan modified_data += "M106 S" + str(current_fan_speed) + this_fan + "\n" prev_fan = this_fan if ";LAYER:" in line: @@ -729,27 +829,29 @@ class AddCoolingProfile(Script): name_index = -1 if name_index != -1: modified_data += line + "\n" + feature_speed_list[name_index] + this_fan + "\n" - #modified_data += feature_speed_list[name_index] + this_fan + "\n" current_fan_speed = str(feature_speed_list[name_index].split("S")[1]) elif ";MESH:NONMESH" in line: if feature_fan_combing == True: modified_data += line + "\n" - modified_data += "M106 S0" + this_fan + "\n" + modified_data += f"M106 S{off_fan_speed}" + this_fan + "\n" current_fan_speed = "0" else: modified_data += line + "\n" - ## If an end layer is defined - Insert the final speed and set the other variables to Final Speed to finish the file - ## There cannot be a break here because if there are multiple fan numbers they still need to be shut off and turned on. + # If an end layer is defined - Insert the final speed and set the other variables to Final Speed to finish the file + # There cannot be a 'break' here because if there are multiple fan numbers they still need to be shut off and turned on. elif line == ";LAYER:" + str(the_end_layer): modified_data += feature_speed_list[len(feature_speed_list) - 1] + this_fan + "\n" for set_speed in range(0, len(feature_speed_list) - 2): feature_speed_list[set_speed] = feature_speed_list[len(feature_speed_list) - 1] else: - ## Layer and Tool get inserted into modified_data above. All other lines go into modified_data here + # Layer and Tool get inserted into modified_data above. All other lines go into modified_data here if not line.startswith("T") and not line.startswith(";LAYER:"): modified_data += line + "\n" if modified_data.endswith("\n"): modified_data = modified_data[0: - 1] multi_fan_data[l_index] = modified_data modified_data = "" + # Insure the fans get shut off if 'off_fan_speed' was enabled + if Application.getInstance().getGlobalContainerStack().getProperty("machine_extruder_count", "value") > 1 and self.getSettingValueByKey("enable_off_fan_speed"): + multi_fan_data[-1] += "M106 S0 P1\nM106 S0 P0\n" return multi_fan_data #Try to catch layer input errors, set the minimum speed to 12%, and put the strings together @@ -768,7 +870,7 @@ class AddCoolingProfile(Script): if int(fan_string_p) > 100: fan_string_p = "100" except ValueError: fan_string_p = "0" - ## Set the minimum fan speed to 12% + # Set the minimum fan speed to 12% if int(fan_string_p) < 12 and int(fan_string_p) != 0: fan_string_p = "12" fan_layer_line = str(fan_string_l) @@ -784,7 +886,7 @@ class AddCoolingProfile(Script): #Try to catch feature input errors, set the minimum speed to 12%, and put the strings together when 'By Feature' def _feature_checker(self, fan_feat_string: int, fan_mode: bool) -> str: if fan_feat_string < 0: fan_feat_string = 0 - ## Set the minimum fan speed to 12% + # Set the minimum fan speed to 12% if fan_feat_string > 0 and fan_feat_string < 12: fan_feat_string = 12 if fan_feat_string > 100: fan_feat_string = 100 if fan_mode: @@ -798,7 +900,7 @@ class AddCoolingProfile(Script): for lay_num in range(int(lay_0_index), len(comment_data)-1,1): layer = comment_data[lay_num] lines = layer.split("\n") - ## Copy the data to new_data and make the insertions there + # Copy the data to new_data and make the insertions there new_data = lines g0_count = 0 g0_index = -1 @@ -818,12 +920,12 @@ class AddCoolingProfile(Script): if g0_index == -1: g0_index = lines.index(line) elif not line.startswith("G0 ") and not is_travel: - ## Add additional 'NONMESH' lines to shut the fan off during long combing moves-------- + # Add additional 'NONMESH' lines to shut the fan off during long combing moves-------- if g0_count > 5: if not is_travel: new_data.insert(g0_index + insert_index, ";MESH:NONMESH") insert_index += 1 - ## Add the feature_type at the end of the combing move to turn the fan back on + # Add the feature_type at the end of the combing move to turn the fan back on new_data.insert(g0_index + g0_count + 1, feature_type) insert_index += 1 g0_count = 0 @@ -834,4 +936,34 @@ class AddCoolingProfile(Script): g0_index = -1 is_travel = False comment_data[lay_num] = "\n".join(new_data) - return comment_data \ No newline at end of file + return comment_data + + def _control_bv_fan(self, bv_data: str) -> str: + # Control the chamber fan + bv_start_layer = self.getSettingValueByKey("bv_fan_start_layer") - 1 + bv_end_layer = self.getSettingValueByKey("bv_fan_end_layer") + if bv_end_layer != -1: + bv_end_layer -= 1 + # Get the PWM speed or if RepRap then the 0-1 speed + if Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("machine_scale_fan_speed_zero_to_one", "value"): + bv_fan_speed = round(self.getSettingValueByKey("bv_fan_speed") * .01, 1) + else: + bv_fan_speed = int(self.getSettingValueByKey("bv_fan_speed") * 2.55) + # Turn the chamber fan on + for index, layer in enumerate(bv_data): + if ";LAYER:" + str(bv_start_layer) + "\n" in layer: + bv_data[index] = re.sub(f";LAYER:{bv_start_layer}", f";LAYER:{bv_start_layer}\nM106 S{bv_fan_speed} P{self.bv_fan_nr}",layer) + break + # Turn the chamber fan off + if bv_end_layer == -1: + bv_data[len(bv_data)-2] += f"M106 S0 P{self.bv_fan_nr}\n" + else: + for index, layer in enumerate(bv_data): + if ";LAYER:" + str(bv_end_layer) + "\n" in layer: + lines = layer.split("\n") + for fdex, line in enumerate(lines): + if ";TIME_ELAPSED:" in line: + lines[fdex] = f"M106 S0 P{self.bv_fan_nr}\n" + line + bv_data[index] = "\n".join(lines) + break + return bv_data \ No newline at end of file From 248b5915db6d4e7de6a81e27936ba48b5906dd15 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Fri, 3 Jan 2025 07:14:45 -0500 Subject: [PATCH 015/299] Update AddCoolingProfile.py Made changes per request. --- .../scripts/AddCoolingProfile.py | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py index ad00fbd923..370b0aff96 100644 --- a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py +++ b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py @@ -314,7 +314,7 @@ class AddCoolingProfile(Script): "bv_fan_speed": { "label": " Chamber fan speed %", - "description": "The speed of the Chamber Fan. This will be converted to PWM Duty Cycle (0-255).", + "description": "The speed of the Chamber Fan. This will be converted to PWM Duty Cycle (0-255) or (RepRap 0-1 if that is enabled in Cura).", "type": "int", "unit": "% ", "default_value": 50, @@ -355,29 +355,32 @@ class AddCoolingProfile(Script): super().initialize() curaApp = Application.getInstance().getGlobalContainerStack() extruder = curaApp.extruderList + extruder_count = curaApp.getProperty("machine_extruder_count", "value") scripts = curaApp.getMetaDataEntry("post_processing_scripts") if scripts != None: script_count = scripts.count("AddCoolingProfile") if script_count > 0: # Set 'Remove M106 lines' to "false" if there is already an instance of this script running. self._instance.setProperty("delete_existing_m106", "value", False) - if curaApp.getProperty("machine_extruder_count", "value") > 1: + if extruder_count > 1: if extruder[0].getProperty("machine_extruder_cooling_fan_number", "value") != extruder[1].getProperty("machine_extruder_cooling_fan_number", "value"): self._instance.setProperty("enable_off_fan_speed_enable", "value", True) - self.has_bv_fan = False - self.bv_fan_nr = -1 - if int(curaApp.getProperty("build_volume_fan_nr", "value")) > 0: - self.has_bv_fan = True - self.bv_fan_nr = int(curaApp.getProperty("build_volume_fan_nr", "value")) + self.has_bv_fan = bool(curaApp.getProperty("build_volume_fan_nr", "value")) + self.bv_fan_nr = int(curaApp.getProperty("build_volume_fan_nr", "value")) + if self.has_bv_fan: self._instance.setProperty("enable_bv_fan", "value", True) def execute(self, data): + # Exit if the gcode has been previously post-processed. + if ";POSTPROCESSED" in data[0]: + return data #Initialize variables that are buried in if statements. - curaApp = Application.getInstance().getGlobalContainerStack() + self.curaApp = Application.getInstance().getGlobalContainerStack() t0_fan = " P0"; t1_fan = " P0"; t2_fan = " P0"; t3_fan = " P0"; is_multi_extr_print = True #Get some information from Cura----------------------------------- - extruder = curaApp.extruderList + extruder = self.curaApp.extruderList + extruder_count = self.curaApp.getProperty("machine_extruder_count", "value") #This will be true when fan scale is 0-255pwm and false when it's RepRap 0-1 (Cura 5.x) fan_mode = True @@ -387,8 +390,7 @@ class AddCoolingProfile(Script): except: pass bed_adhesion = (extruder[0].getProperty("adhesion_type", "value")) - extruder_count = curaApp.getProperty("machine_extruder_count", "value") - print_sequence = str(curaApp.getProperty("print_sequence", "value")) + print_sequence = str(self.curaApp.getProperty("print_sequence", "value")) #Assign the fan numbers to the tools------------------------------ if extruder_count == 1: @@ -471,7 +473,7 @@ class AddCoolingProfile(Script): # For multi-extruder printers with separate fans the 'idle' nozzle fan can be left on for ooze control off_fan_speed = 0 - if Application.getInstance().getGlobalContainerStack().getProperty("machine_extruder_count", "value") > 1: + if extruder_count > 1: if self.getSettingValueByKey("enable_off_fan_speed"): if fan_mode: off_fan_speed = round(int(self.getSettingValueByKey("off_fan_speed")) * 2.55) @@ -624,10 +626,12 @@ class AddCoolingProfile(Script): layer = data[layer_num] data[layer_num] = re.sub(";MESH:NOMESH", ";MESH:NONMESH", layer) data = self._add_travel_comment(data, layer_0_index) + # If there is a build volume fan if self.has_bv_fan: if self.getSettingValueByKey("bv_fan_speed_control_enable"): data = self._control_bv_fan(data) + # Single Fan "By Layer"-------------------------------------------- if by_layer_or_feature == "by_layer" and not is_multi_fan: return self._single_fan_by_layer(data, layer_0_index, fan_list, t0_fan) @@ -723,7 +727,7 @@ class AddCoolingProfile(Script): if modified_data.endswith("\n"): modified_data = modified_data[0:-1] multi_fan_data[l_index] = modified_data # Insure the fans get shut off if 'off_fan_speed' was enabled - if Application.getInstance().getGlobalContainerStack().getProperty("machine_extruder_count", "value") > 1 and self.getSettingValueByKey("enable_off_fan_speed"): + if self.curaApp.getProperty("machine_extruder_count", "value") > 1 and self.getSettingValueByKey("enable_off_fan_speed"): multi_fan_data[-1] += "M106 S0 P1\nM106 S0 P0\n" return multi_fan_data @@ -850,7 +854,7 @@ class AddCoolingProfile(Script): multi_fan_data[l_index] = modified_data modified_data = "" # Insure the fans get shut off if 'off_fan_speed' was enabled - if Application.getInstance().getGlobalContainerStack().getProperty("machine_extruder_count", "value") > 1 and self.getSettingValueByKey("enable_off_fan_speed"): + if self.curaApp.getProperty("machine_extruder_count", "value") > 1 and self.getSettingValueByKey("enable_off_fan_speed"): multi_fan_data[-1] += "M106 S0 P1\nM106 S0 P0\n" return multi_fan_data @@ -945,7 +949,7 @@ class AddCoolingProfile(Script): if bv_end_layer != -1: bv_end_layer -= 1 # Get the PWM speed or if RepRap then the 0-1 speed - if Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("machine_scale_fan_speed_zero_to_one", "value"): + if self.curaApp.extruderList[0].getProperty("machine_scale_fan_speed_zero_to_one", "value"): bv_fan_speed = round(self.getSettingValueByKey("bv_fan_speed") * .01, 1) else: bv_fan_speed = int(self.getSettingValueByKey("bv_fan_speed") * 2.55) From da0b99cb8273b5e50a6bd3c994af73800f7d3f72 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Wed, 8 Jan 2025 07:46:42 -0500 Subject: [PATCH 016/299] Update DisplayInfoOnLCD.py Added "global_stack" variable. --- .../scripts/DisplayInfoOnLCD.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index ed226c08f3..c4f7ecf55c 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -308,15 +308,16 @@ class DisplayInfoOnLCD(Script): # Display Progress (from 'Show Progress' and 'Display Progress on LCD')--------------------------------------- elif display_option == "display_progress": - print_sequence = Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") + global_stack = Application.getInstance().getGlobalContainerStack() + print_sequence = global_stack.getProperty("print_sequence", "value") # Add the Initial Layer Height just below Layer Height in data[0] - extruder_count = Application.getInstance().getGlobalContainerStack().getProperty("machine_extruder_count", "value") - init_layer_hgt_line = ";Initial Layer Height: " + str(Application.getInstance().getGlobalContainerStack().getProperty("layer_height_0", "value")) - nozzle_size_line = ";Nozzle Size T0: " + str(Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("machine_nozzle_size", "value")) - filament_type = "\n;Filament type for T0: " + str(Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("material_type", "value")) + extruder_count = global_stack.getProperty("machine_extruder_count", "value") + init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) + nozzle_size_line = ";Nozzle Size T0: " + str(global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")) + filament_type = "\n;Filament type for T0: " + str(global_stack.extruderList[0].getProperty("material_type", "value")) if extruder_count > 1: - nozzle_size_line += "\n;Nozzle Size T1: " + str(Application.getInstance().getGlobalContainerStack().extruderList[1].getProperty("machine_nozzle_size", "value")) - filament_type += "\n;Filament type for T1: " + str(Application.getInstance().getGlobalContainerStack().extruderList[1].getProperty("material_type", "value")) + nozzle_size_line += "\n;Nozzle Size T1: " + str(global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")) + filament_type += "\n;Filament type for T1: " + str(global_stack.extruderList[1].getProperty("material_type", "value")) lines = data[0].split("\n") for index, line in enumerate(lines): if line.startswith(";Layer height:"): From 984c19decc764ca51a3ea68a78df3808517bbc92 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Wed, 8 Jan 2025 23:01:19 -0500 Subject: [PATCH 017/299] Update DisplayInfoOnLCD.py Bug fix. --- .../scripts/DisplayInfoOnLCD.py | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index c4f7ecf55c..fc3b22a7a6 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -238,12 +238,14 @@ class DisplayInfoOnLCD(Script): add_m118_line = self.getSettingValueByKey("add_m118_line") add_m118_a1 = self.getSettingValueByKey("add_m118_a1") add_m118_p0 = self.getSettingValueByKey("add_m118_p0") + m118_str = "M118 " + m118_text = "M118 " add_m73_line = self.getSettingValueByKey("add_m73_line") add_m73_time = self.getSettingValueByKey("add_m73_time") add_m73_percent = self.getSettingValueByKey("add_m73_percent") m73_str = "" - # This is Display Filename and Layer on LCD--------------------------------------------------------- + # This is from the original Display Filename and Layer on LCD if display_option == "filename_layer": max_layer = 0 lcd_text = "M117 " @@ -256,7 +258,7 @@ class DisplayInfoOnLCD(Script): lcd_text += "Printing " octo_text += "Printing " if not self.getSettingValueByKey("scroll"): - lcd_text += "Layer " + lcd_text += "Lay " octo_text += "Layer " else: lcd_text += file_name + " - Layer " @@ -275,15 +277,15 @@ class DisplayInfoOnLCD(Script): max_layer = str(int(max_layer) - 1) if line.startswith(";LAYER:"): if self.getSettingValueByKey("maxlayer"): - display_text += " of " + max_layer - m118_text += " of " + max_layer + display_text += "/" + max_layer + m118_text += "/" + max_layer if not self.getSettingValueByKey("scroll"): - display_text += " " + file_name - m118_text += " " + file_name + display_text += "|" + file_name + m118_text += " | " + file_name else: if not self.getSettingValueByKey("scroll"): - display_text += " " + file_name + "!" - m118_text += " " + file_name + "!" + display_text += "|" + file_name + "!" + m118_text += " | " + file_name + "!" else: display_text += "!" m118_text += "!" @@ -291,6 +293,8 @@ class DisplayInfoOnLCD(Script): if add_m117_line: lines.insert(line_index + 1, display_text) if add_m118_line: + if not (add_m118_p0 and add_m118_a1): + m118_str = m118_text if add_m118_a1 and not add_m118_p0: m118_str = m118_text.replace("M118 ","M118 A1 ") if add_m118_p0 and not add_m118_a1: @@ -306,7 +310,7 @@ class DisplayInfoOnLCD(Script): Message(title = "Display Info on LCD - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() return data - # Display Progress (from 'Show Progress' and 'Display Progress on LCD')--------------------------------------- + # This is from 'Show Progress on LCD' elif display_option == "display_progress": global_stack = Application.getInstance().getGlobalContainerStack() print_sequence = global_stack.getProperty("print_sequence", "value") From 043afdb6ed7fbaa672c383ca2337c19564254177 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Fri, 10 Jan 2025 09:01:44 -0500 Subject: [PATCH 018/299] Update DisplayInfoOnLCD.py Update. Remove vestigial line of code at line 530. --- .../scripts/DisplayInfoOnLCD.py | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index fc3b22a7a6..38649ed6ce 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -377,18 +377,21 @@ class DisplayInfoOnLCD(Script): if bool(self.getSettingValueByKey("countdown_to_pause")): pause_count = 0 pause_setting = self.getSettingValueByKey("pause_cmd").upper() - pause_cmd = [] - if "," in pause_setting: - pause_cmd = pause_setting.split(",") + if pause_setting != "": + pause_cmd = [] + if "," in pause_setting: + pause_cmd = pause_setting.split(",") + else: + pause_cmd.append(pause_setting) + for q in range(0, len(pause_cmd)): + pause_cmd[q] = "\n" + pause_cmd[q] + for num in range(2,len(data) - 2, 1): + for q in range(0,len(pause_cmd)): + if pause_cmd[q] in data[num]: + pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) + pause_str = f"with {pause_count} pause(s)" else: - pause_cmd.append(pause_setting) - for q in range(0, len(pause_cmd)): - pause_cmd[q] = "\n" + pause_cmd[q] - for num in range(2,len(data) - 2, 1): - for q in range(0,len(pause_cmd)): - if pause_cmd[q] in data[num]: - pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) - pause_str = f" with {pause_count} pause(s)" + pause_str = "" # This line goes in to convert seconds to hours and minutes lines.insert(tindex + 1, f";Cura Time Estimate: {orig_hr}hr {orig_mmm}min {pause_str}") data[0] = "\n".join(lines) @@ -527,7 +530,6 @@ class DisplayInfoOnLCD(Script): except: continue data[num] = layer - setting_data = "" if bool(self.getSettingValueByKey("enable_end_message")): message_str = self.message_to_user(speed_factor) Message(title = "[Display Info on LCD] - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() From a8849f7081ca8c84a85469f225ed3c0cf464fb79 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:26:43 -0500 Subject: [PATCH 019/299] Update DisplayInfoOnLCD.py Added a condition so the pause_cmd setting box is hidden unless the 'display_option' == "display_progress". --- plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 38649ed6ce..399578fef5 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -210,7 +210,7 @@ class DisplayInfoOnLCD(Script): "description": "This might be M0, or M25 or M600 if Filament Change is used. If you have mixed commands then delimit them with a comma ',' (Ex: M0,M600). Spaces are not allowed.", "type": "str", "default_value": "M0", - "enabled": "countdown_to_pause and enable_countdown and display_remaining_time" + "enabled": "display_option == 'display_progress' and countdown_to_pause and enable_countdown and display_remaining_time" }, "enable_end_message": { From 02847714302bd026de3ddd7a50e8c47b1bb90ec5 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 11 Jan 2025 10:12:42 -0500 Subject: [PATCH 020/299] Update DisplayInfoOnLCD.py Split functions from Execute. Added function "Add Settings" so it also works with the "filename_layer" option. --- .../scripts/DisplayInfoOnLCD.py | 688 +++++++++--------- 1 file changed, 358 insertions(+), 330 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 399578fef5..2177f91f3b 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -1,32 +1,35 @@ -# Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 -# Modified: Joshua Pope-Lewis on November 16, 2018 -# Display Progress on LCD by Mathias Lyngklip Kjeldgaard, Alexander Gee, Kimmo Toivanen, Inigo Martinez on July 31, 2019 -# Show Progress was adapted from Display Progress by Louis Wooters on January 6, 2020. His changes are included here. -#--------------------------------------------------------------- -# DisplayNameOrProgressOnLCD.py -# Cura Post-Process plugin -# Combines 'Display Filename and Layer on the LCD' with 'Display Progress' -# Combined and with additions by: GregValiant (Greg Foresi) -# Date: September 8, 2023 -# Date: March 31, 2024 - Bug fix for problem with adding M118 lines if 'Remaining Time' was not checked. -# NOTE: This combined post processor will make 'Display Filename and Layer on the LCD' and 'Display Progress' obsolete -# Description: Display Filename and Layer options: -# Status messages sent to the printer... -# - Scrolling (SCROLL_LONG_FILENAMES) if enabled in Marlin and you aren't printing a small item select this option. -# - Name: By default it will use the name generated by Cura (EG: TT_Test_Cube) - You may enter a custom name here -# - Start Num: Choose which number you prefer for the initial layer, 0 or 1 -# - Max Layer: Enabling this will show how many layers are in the entire print (EG: Layer 1 of 265!) -# - Add prefix 'Printing': Enabling this will add the prefix 'Printing' -# - Example Line on LCD: Printing Layer 0 of 395 3DBenchy -# Display Progress options: -# - Display Total Layer Count -# - Disply Time Remaining for the print -# - Time Fudge Factor % - Divide the Actual Print Time by the Cura Estimate. Enter as a percentage and the displayed time will be adjusted. This allows you to bring the displayed time closer to reality (Ex: Entering 87.5 would indicate an adjustment to 87.5% of the Cura estimate). -# - Example line on LCD: 1/479 | ET 2h13m -# - Time to Pauses changes the M117/M118 lines to countdown to the next pause as 1/479 | TP 2h36m -# - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. -# - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) -# - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It takes into account the Time Fudge Factor. The user may enter a print start time. This is also available for Display Filename. +""" +Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 + Modified: Joshua Pope-Lewis on November 16, 2018 + Display Progress on LCD by Mathias Lyngklip Kjeldgaard, Alexander Gee, Kimmo Toivanen, Inigo Martinez on July 31, 2019 + Show Progress was adapted from Display Progress by Louis Wooters on January 6, 2020. His changes are included here. +--------------------------------------------------------------- + DisplayNameOrProgressOnLCD.py + Cura Post-Process plugin + Combines 'Display Filename and Layer on the LCD' with 'Display Progress' + Combined and with additions by: GregValiant (Greg Foresi) + Date: September 8, 2023 + Date: March 31, 2024 - Bug fix for problem with adding M118 lines if 'Remaining Time' was not checked. + NOTE: This combined post processor will make 'Display Filename and Layer on the LCD' and 'Display Progress' obsolete + Description: Display Filename and Layer options: + Status messages sent to the printer... + - Scrolling (SCROLL_LONG_FILENAMES) if enabled in Marlin and you aren't printing a small item select this option. + - Name: By default it will use the name generated by Cura (EG: TT_Test_Cube) - You may enter a custom name here + - Start Num: Choose which number you prefer for the initial layer, 0 or 1 + - Max Layer: Enabling this will show how many layers are in the entire print (EG: Layer 1 of 265!) + - Add prefix 'Printing': Enabling this will add the prefix 'Printing' + - Example Line on LCD: Printing Layer 0 of 395 3DBenchy + Display Progress options: + - Display Total Layer Count + - Disply Time Remaining for the print + - Time Fudge Factor % - Divide the Actual Print Time by the Cura Estimate. Enter as a percentage and the displayed time will be adjusted. + This allows you to bring the displayed time closer to reality (Ex: Entering 87.5 would indicate an adjustment to 87.5% of the Cura estimate). + - Example line on LCD: 1/479 | ET 2h13m + - Time to Pauses changes the M117/M118 lines to countdown to the next pause as 1/479 | TP 2h36m + - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. + - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) + - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It uses the Time Fudge Factor. The user may enter a print start time. +""" from ..Script import Script from UM.Application import Application @@ -47,7 +50,7 @@ class DisplayInfoOnLCD(Script): self._instance.setProperty("enable_countdown", "value", enable_countdown) except: pass - + def getSettingDataString(self): return """{ "name": "Display Info on LCD", @@ -234,308 +237,301 @@ class DisplayInfoOnLCD(Script): def execute(self, data): display_option = self.getSettingValueByKey("display_option") - add_m117_line = self.getSettingValueByKey("add_m117_line") - add_m118_line = self.getSettingValueByKey("add_m118_line") - add_m118_a1 = self.getSettingValueByKey("add_m118_a1") - add_m118_p0 = self.getSettingValueByKey("add_m118_p0") - m118_str = "M118 " - m118_text = "M118 " - add_m73_line = self.getSettingValueByKey("add_m73_line") - add_m73_time = self.getSettingValueByKey("add_m73_time") - add_m73_percent = self.getSettingValueByKey("add_m73_percent") - m73_str = "" - - # This is from the original Display Filename and Layer on LCD + self.add_m117_line = self.getSettingValueByKey("add_m117_line") + self.add_m118_line = self.getSettingValueByKey("add_m118_line") + self.add_m118_a1 = self.getSettingValueByKey("add_m118_a1") + self.add_m118_p0 = self.getSettingValueByKey("add_m118_p0") + self.m118_str = "M118 " + self.m118_text = "M118 " + self.add_m73_line = self.getSettingValueByKey("add_m73_line") + self.add_m73_time = self.getSettingValueByKey("add_m73_time") + self.add_m73_percent = self.getSettingValueByKey("add_m73_percent") + self.m73_str = "" if display_option == "filename_layer": - max_layer = 0 - lcd_text = "M117 " - octo_text = "M118 " - if self.getSettingValueByKey("file_name") != "": - file_name = self.getSettingValueByKey("file_name") - else: - file_name = Application.getInstance().getPrintInformation().jobName - if self.getSettingValueByKey("addPrefixPrinting"): - lcd_text += "Printing " - octo_text += "Printing " - if not self.getSettingValueByKey("scroll"): - lcd_text += "Lay " - octo_text += "Layer " - else: - lcd_text += file_name + " - Layer " - octo_text += file_name + " - Layer " - i = self.getSettingValueByKey("startNum") - for layer in data: - display_text = lcd_text + str(i) - m118_text = octo_text + str(i) - layer_index = data.index(layer) - lines = layer.split("\n") - for line in lines: - if line.startswith(";LAYER_COUNT:"): - max_layer = line - max_layer = max_layer.split(":")[1] - if self.getSettingValueByKey("startNum") == 0: - max_layer = str(int(max_layer) - 1) - if line.startswith(";LAYER:"): - if self.getSettingValueByKey("maxlayer"): - display_text += "/" + max_layer - m118_text += "/" + max_layer - if not self.getSettingValueByKey("scroll"): - display_text += "|" + file_name - m118_text += " | " + file_name - else: - if not self.getSettingValueByKey("scroll"): - display_text += "|" + file_name + "!" - m118_text += " | " + file_name + "!" - else: - display_text += "!" - m118_text += "!" - line_index = lines.index(line) - if add_m117_line: - lines.insert(line_index + 1, display_text) - if add_m118_line: - if not (add_m118_p0 and add_m118_a1): - m118_str = m118_text - if add_m118_a1 and not add_m118_p0: - m118_str = m118_text.replace("M118 ","M118 A1 ") - if add_m118_p0 and not add_m118_a1: - m118_str = m118_text.replace("M118 ","M118 P0 ") - if add_m118_p0 and add_m118_a1: - m118_str = m118_text.replace("M118 ","M118 A1 P0 ") - lines.insert(line_index + 2, m118_str) - i += 1 - final_lines = "\n".join(lines) - data[layer_index] = final_lines - if bool(self.getSettingValueByKey("enable_end_message")): - message_str = self.message_to_user(self.getSettingValueByKey("speed_factor") / 100) - Message(title = "Display Info on LCD - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() - return data - - # This is from 'Show Progress on LCD' - elif display_option == "display_progress": - global_stack = Application.getInstance().getGlobalContainerStack() - print_sequence = global_stack.getProperty("print_sequence", "value") - # Add the Initial Layer Height just below Layer Height in data[0] - extruder_count = global_stack.getProperty("machine_extruder_count", "value") - init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) - nozzle_size_line = ";Nozzle Size T0: " + str(global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")) - filament_type = "\n;Filament type for T0: " + str(global_stack.extruderList[0].getProperty("material_type", "value")) - if extruder_count > 1: - nozzle_size_line += "\n;Nozzle Size T1: " + str(global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")) - filament_type += "\n;Filament type for T1: " + str(global_stack.extruderList[1].getProperty("material_type", "value")) - lines = data[0].split("\n") - for index, line in enumerate(lines): - if line.startswith(";Layer height:"): - lines[index] += "\n" + init_layer_hgt_line + "\n" + nozzle_size_line - if line.startswith(";Filament used"): - lines[index] += filament_type - data[0] = "\n".join(lines) - # Get settings - display_total_layers = self.getSettingValueByKey("display_total_layers") - display_remaining_time = self.getSettingValueByKey("display_remaining_time") - speed_factor = self.getSettingValueByKey("speed_factor") / 100 - m73_time = False - m73_percent = False - if add_m73_line and add_m73_time: - m73_time = True - if add_m73_line and add_m73_percent: - m73_percent = True - if add_m73_line: - data[1] = "M75\n" + data[1] - data[len(data)-1] += "M77\n" - # Initialize some variables - first_layer_index = 0 - time_total = int(data[0].split(";TIME:")[1].split("\n")[0]) - number_of_layers = 0 - time_elapsed = 0 - - # If at least one of the settings is disabled, there is enough room on the display to display "layer" - first_section = data[0] - lines = first_section.split("\n") + data = self._display_filename_layer(data) + else: + data = self._display_progress(data) + return data + # This is from the original 'Display Filename and Layer on LCD' + def _display_filename_layer(self, data: str) -> str: + data[0] = self._add_stats(data) + max_layer = 0 + lcd_text = "M117 " + octo_text = "M118 " + if self.getSettingValueByKey("file_name") != "": + file_name = self.getSettingValueByKey("file_name") + else: + file_name = Application.getInstance().getPrintInformation().jobName + if self.getSettingValueByKey("addPrefixPrinting"): + lcd_text += "Printing " + octo_text += "Printing " + if not self.getSettingValueByKey("scroll"): + lcd_text += "Lay " + octo_text += "Layer " + else: + lcd_text += file_name + " - Layer " + octo_text += file_name + " - Layer " + i = self.getSettingValueByKey("startNum") + for layer in data: + display_text = lcd_text + str(i) + self.m118_text = octo_text + str(i) + layer_index = data.index(layer) + lines = layer.split("\n") for line in lines: - if line.startswith(";TIME:"): - tindex = lines.index(line) - cura_time = int(line.split(":")[1]) - print_time = cura_time * speed_factor - hhh = print_time/3600 - hr = round(hhh // 1) - mmm = round((hhh % 1) * 60) - orig_hhh = cura_time/3600 - orig_hr = round(orig_hhh // 1) - orig_mmm = math.floor((orig_hhh % 1) * 60) - if add_m118_line: lines.insert(tindex + 6,"M118 Adjusted Print Time " + str(hr) + "hr " + str(mmm) + "min") - if add_m117_line: lines.insert(tindex + 6,"M117 ET " + str(hr) + "hr " + str(mmm) + "min") - # Add M73 line at beginning - mins = int(60 * hr + mmm) - if add_m73_line and (add_m73_time or add_m73_percent): - if m73_time: - m73_str += " R{}".format(mins) - if m73_percent: - m73_str += " P0" - lines.insert(tindex + 4, "M73" + m73_str) - # If Countdown to pause is enabled then count the pauses - pause_str = "" - if bool(self.getSettingValueByKey("countdown_to_pause")): - pause_count = 0 - pause_setting = self.getSettingValueByKey("pause_cmd").upper() - if pause_setting != "": - pause_cmd = [] - if "," in pause_setting: - pause_cmd = pause_setting.split(",") - else: - pause_cmd.append(pause_setting) - for q in range(0, len(pause_cmd)): - pause_cmd[q] = "\n" + pause_cmd[q] - for num in range(2,len(data) - 2, 1): - for q in range(0,len(pause_cmd)): - if pause_cmd[q] in data[num]: - pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) - pause_str = f"with {pause_count} pause(s)" - else: - pause_str = "" - # This line goes in to convert seconds to hours and minutes - lines.insert(tindex + 1, f";Cura Time Estimate: {orig_hr}hr {orig_mmm}min {pause_str}") - data[0] = "\n".join(lines) - if add_m117_line: - data[len(data)-1] += "M117 Orig Cura Est " + str(orig_hr) + "hr " + str(orig_mmm) + "min\n" - if add_m118_line: - data[len(data)-1] += "M118 Est w/FudgeFactor " + str(speed_factor * 100) + "% was " + str(hr) + "hr " + str(mmm) + "min\n" - if not display_total_layers or not display_remaining_time: - base_display_text = "layer " - else: - base_display_text = "" - layer = data[len(data)-1] - data[len(data)-1] = layer.replace(";End of Gcode" + "\n", "") - data[len(data)-1] += ";End of Gcode" + "\n" - # Search for the number of layers and the total time from the start code - for index in range(len(data)): - data_section = data[index] - # We have everything we need, save the index of the first layer and exit the loop - if ";LAYER:" in data_section: - first_layer_index = index - break - else: - for line in data_section.split("\n"): - if line.startswith(";LAYER_COUNT:"): - number_of_layers = int(line.split(":")[1]) - if print_sequence == "one_at_a_time": - number_of_layers = 1 - for lay in range(2,len(data)-1,1): - if ";LAYER:" in data[lay]: - number_of_layers += 1 - elif line.startswith(";TIME:"): - time_total = int(line.split(":")[1]) - # for all layers... - current_layer = 0 - for layer_counter in range(len(data)-2): - current_layer += 1 - layer_index = first_layer_index + layer_counter - display_text = base_display_text - display_text += str(current_layer) - # create a list where each element is a single line of code within the layer - lines = data[layer_index].split("\n") - if not ";LAYER:" in data[layer_index]: - current_layer -= 1 - continue - # add the total number of layers if this option is checked - if display_total_layers: - display_text += "/" + str(number_of_layers) - # if display_remaining_time is checked, it is calculated in this loop - if display_remaining_time: - time_remaining_display = " | ET " # initialize the time display - m = (time_total - time_elapsed) // 60 # estimated time in minutes - m *= speed_factor # correct for printing time - m = int(m) - h, m = divmod(m, 60) # convert to hours and minutes - # add the time remaining to the display_text - if h > 0: # if it's more than 1 hour left, display format = xhxxm - time_remaining_display += str(h) + "h" - if m < 10: # add trailing zero if necessary - time_remaining_display += "0" - time_remaining_display += str(m) + "m" + if line.startswith(";LAYER_COUNT:"): + max_layer = line + max_layer = max_layer.split(":")[1] + if self.getSettingValueByKey("startNum") == 0: + max_layer = str(int(max_layer) - 1) + if line.startswith(";LAYER:"): + if self.getSettingValueByKey("maxlayer"): + display_text += "/" + max_layer + self.m118_text += "/" + max_layer + if not self.getSettingValueByKey("scroll"): + display_text += "|" + file_name + self.m118_text += " | " + file_name else: - time_remaining_display += str(m) + "m" - display_text += time_remaining_display - # find time_elapsed at the end of the layer (used to calculate the remaining time of the next layer) - if not current_layer == number_of_layers: - for line_index in range(len(lines) - 1, -1, -1): - line = lines[line_index] - if line.startswith(";TIME_ELAPSED:"): - # update time_elapsed for the NEXT layer and exit the loop - time_elapsed = int(float(line.split(":")[1])) - break - # insert the text AFTER the first line of the layer (in case other scripts use ";LAYER:") - for l_index, line in enumerate(lines): - if line.startswith(";LAYER:"): - if add_m117_line: - lines[l_index] += "\nM117 " + display_text - if add_m118_line: - a1_str = "" - p0_str = "" - if add_m118_a1: - a1_str = "A1 " - if add_m118_p0: - p0_str = "P0 " - lines[l_index] += "\nM118 " + a1_str + p0_str + display_text - # add M73 line - if display_remaining_time: - mins = int(60 * h + m) - if add_m73_line and (add_m73_time or add_m73_percent): - m73_str = "" - if m73_time and display_remaining_time: - m73_str += " R{}".format(mins) - if m73_percent: - m73_str += " P" + str(round(int(current_layer) / int(number_of_layers) * 100)) - lines[l_index] += "\nM73" + m73_str - break - # overwrite the layer with the modified layer - data[layer_index] = "\n".join(lines) - - # If enabled then change the ET to TP for 'Time To Pause' - if bool(self.getSettingValueByKey("countdown_to_pause")): - time_list = [] - time_list.append("0") - time_list.append("0") - this_time = 0 - pause_index = 1 - - # Get the layer times - for num in range(2,len(data) - 1): - layer = data[num] - lines = layer.split("\n") - for line in lines: - if line.startswith(";TIME_ELAPSED:"): - this_time = (float(line.split(":")[1]))*speed_factor - time_list.append(str(this_time)) - for p_cmd in pause_cmd: - if p_cmd in layer: - for qnum in range(num - 1, pause_index, -1): - time_list[qnum] = str(float(this_time) - float(time_list[qnum])) + "P" - pause_index = num-1 - break - - # Make the adjustments to the M117 (and M118) lines that are prior to a pause - for num in range (2, len(data) - 1,1): - layer = data[num] - lines = layer.split("\n") - for line in lines: - try: - if line.startswith("M117") and "|" in line and "P" in time_list[num]: - time_to_go = self.get_time_to_go(time_list[num]) - M117_line = line.split("|")[0] + "| TP " + time_to_go - layer = layer.replace(line, M117_line) - if line.startswith("M118") and "|" in line and "P" in time_list[num]: - time_to_go = self.get_time_to_go(time_list[num]) - M118_line = line.split("|")[0] + "| TP " + time_to_go - layer = layer.replace(line, M118_line) - except: - continue - data[num] = layer - if bool(self.getSettingValueByKey("enable_end_message")): - message_str = self.message_to_user(speed_factor) - Message(title = "[Display Info on LCD] - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() + if not self.getSettingValueByKey("scroll"): + display_text += "|" + file_name + "!" + self.m118_text += " | " + file_name + "!" + else: + display_text += "!" + self.m118_text += "!" + line_index = lines.index(line) + if self.add_m117_line: + lines.insert(line_index + 1, display_text) + if self.add_m118_line: + if not (self.add_m118_p0 and self.add_m118_a1): + self.m118_str = self.m118_text + if self.add_m118_a1 and not self.add_m118_p0: + self.m118_str = self.m118_text.replace("M118 ","M118 A1 ") + if self.add_m118_p0 and not self.add_m118_a1: + self.m118_str = self.m118_text.replace("M118 ","M118 P0 ") + if self.add_m118_p0 and self.add_m118_a1: + self.m118_str = self.m118_text.replace("M118 ","M118 A1 P0 ") + lines.insert(line_index + 2, self.m118_str) + i += 1 + final_lines = "\n".join(lines) + data[layer_index] = final_lines + if bool(self.getSettingValueByKey("enable_end_message")): + message_str = self._message_to_user(self.getSettingValueByKey("speed_factor") / 100) + Message(title = "Display Info on LCD - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() return data - def message_to_user(self, speed_factor: float): + # This is from 'Show Progress on LCD' + def _display_progress(self, data: str) -> str: + # Add some print settings to the start of the gcode + data[0] = self._add_stats(data) + # Get settings + print_sequence = Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") + display_total_layers = self.getSettingValueByKey("display_total_layers") + display_remaining_time = self.getSettingValueByKey("display_remaining_time") + speed_factor = self.getSettingValueByKey("speed_factor") / 100 + m73_time = False + m73_percent = False + if self.add_m73_line and self.add_m73_time: + m73_time = True + if self.add_m73_line and self.add_m73_percent: + m73_percent = True + if self.add_m73_line: + data[1] = "M75\n" + data[1] + data[len(data)-1] += "M77\n" + # Initialize some variables + first_layer_index = 0 + time_total = int(data[0].split(";TIME:")[1].split("\n")[0]) + number_of_layers = 0 + time_elapsed = 0 + + # If at least one of the settings is disabled, there is enough room on the display to display "layer" + first_section = data[0] + lines = first_section.split("\n") + for line in lines: + if line.startswith(";TIME:"): + tindex = lines.index(line) + cura_time = int(line.split(":")[1]) + print_time = cura_time * speed_factor + hhh = print_time/3600 + hr = round(hhh // 1) + mmm = round((hhh % 1) * 60) + orig_hhh = cura_time/3600 + orig_hr = round(orig_hhh // 1) + orig_mmm = math.floor((orig_hhh % 1) * 60) + if self.add_m118_line: + lines.insert(len(lines) - 2, f"M118 Adjusted Print Time: {hr} hr {mmm} min") + if self.add_m117_line: + lines.insert(len(lines) - 2, f"M117 ET {hr} hr {mmm} min") + # Add M73 line at beginning + mins = int(60 * hr + mmm) + if self.add_m73_line and (self.add_m73_time or self.add_m73_percent): + if m73_time: + self.m73_str += " R{}".format(mins) + if m73_percent: + self.m73_str += " P0" + lines.insert(tindex + 4, "M73" + self.m73_str) + # If Countdown to pause is enabled then count the pauses + pause_str = "" + if bool(self.getSettingValueByKey("countdown_to_pause")): + pause_count = 0 + pause_setting = self.getSettingValueByKey("pause_cmd").upper() + if pause_setting != "": + pause_cmd = [] + if "," in pause_setting: + pause_cmd = pause_setting.split(",") + else: + pause_cmd.append(pause_setting) + for q in range(0, len(pause_cmd)): + pause_cmd[q] = "\n" + pause_cmd[q] + for num in range(2,len(data) - 2, 1): + for q in range(0,len(pause_cmd)): + if pause_cmd[q] in data[num]: + pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) + pause_str = f"with {pause_count} pause(s)" + else: + pause_str = "" + # This line goes in to convert seconds to hours and minutes + lines.insert(tindex + 1, f";Cura Time Estimate: {orig_hr}hr {orig_mmm}min {pause_str}") + data[0] = "\n".join(lines) + if self.add_m117_line: + data[len(data)-1] += "M117 Orig Cura Est " + str(orig_hr) + "hr " + str(orig_mmm) + "min\n" + if self.add_m118_line: + data[len(data)-1] += "M118 Est w/FudgeFactor " + str(speed_factor * 100) + "% was " + str(hr) + "hr " + str(mmm) + "min\n" + if not display_total_layers or not display_remaining_time: + base_display_text = "layer " + else: + base_display_text = "" + layer = data[len(data)-1] + data[len(data)-1] = layer.replace(";End of Gcode" + "\n", "") + data[len(data)-1] += ";End of Gcode" + "\n" + # Search for the number of layers and the total time from the start code + for index in range(len(data)): + data_section = data[index] + # We have everything we need, save the index of the first layer and exit the loop + if ";LAYER:" in data_section: + first_layer_index = index + break + else: + for line in data_section.split("\n"): + if line.startswith(";LAYER_COUNT:"): + number_of_layers = int(line.split(":")[1]) + if print_sequence == "one_at_a_time": + number_of_layers = 1 + for lay in range(2,len(data)-1,1): + if ";LAYER:" in data[lay]: + number_of_layers += 1 + elif line.startswith(";TIME:"): + time_total = int(line.split(":")[1]) + # for all layers... + current_layer = 0 + for layer_counter in range(len(data)-2): + current_layer += 1 + layer_index = first_layer_index + layer_counter + display_text = base_display_text + display_text += str(current_layer) + # create a list where each element is a single line of code within the layer + lines = data[layer_index].split("\n") + if not ";LAYER:" in data[layer_index]: + current_layer -= 1 + continue + # add the total number of layers if this option is checked + if display_total_layers: + display_text += "/" + str(number_of_layers) + # if display_remaining_time is checked, it is calculated in this loop + if display_remaining_time: + time_remaining_display = " | ET " # initialize the time display + m = (time_total - time_elapsed) // 60 # estimated time in minutes + m *= speed_factor # correct for printing time + m = int(m) + h, m = divmod(m, 60) # convert to hours and minutes + # add the time remaining to the display_text + if h > 0: # if it's more than 1 hour left, display format = xhxxm + time_remaining_display += str(h) + "h" + if m < 10: # add trailing zero if necessary + time_remaining_display += "0" + time_remaining_display += str(m) + "m" + else: + time_remaining_display += str(m) + "m" + display_text += time_remaining_display + # find time_elapsed at the end of the layer (used to calculate the remaining time of the next layer) + if not current_layer == number_of_layers: + for line_index in range(len(lines) - 1, -1, -1): + line = lines[line_index] + if line.startswith(";TIME_ELAPSED:"): + # update time_elapsed for the NEXT layer and exit the loop + time_elapsed = int(float(line.split(":")[1])) + break + # insert the text AFTER the first line of the layer (in case other scripts use ";LAYER:") + for l_index, line in enumerate(lines): + if line.startswith(";LAYER:"): + if self.add_m117_line: + lines[l_index] += "\nM117 " + display_text + if self.add_m118_line: + a1_str = "" + p0_str = "" + if self.add_m118_a1: + a1_str = "A1 " + if self.add_m118_p0: + p0_str = "P0 " + lines[l_index] += "\nM118 " + a1_str + p0_str + display_text + # add M73 line + if display_remaining_time: + mins = int(60 * h + m) + if self.add_m73_line and (self.add_m73_time or self.add_m73_percent): + self.m73_str = "" + if m73_time and display_remaining_time: + self.m73_str += " R{}".format(mins) + if m73_percent: + self.m73_str += " P" + str(round(int(current_layer) / int(number_of_layers) * 100)) + lines[l_index] += "\nM73" + self.m73_str + break + # overwrite the layer with the modified layer + data[layer_index] = "\n".join(lines) + + # If enabled then change the ET to TP for 'Time To Pause' + if bool(self.getSettingValueByKey("countdown_to_pause")): + time_list = [] + time_list.append("0") + time_list.append("0") + this_time = 0 + pause_index = 1 + + # Get the layer times + for num in range(2,len(data) - 1): + layer = data[num] + lines = layer.split("\n") + for line in lines: + if line.startswith(";TIME_ELAPSED:"): + this_time = (float(line.split(":")[1]))*speed_factor + time_list.append(str(this_time)) + for p_cmd in pause_cmd: + if p_cmd in layer: + for qnum in range(num - 1, pause_index, -1): + time_list[qnum] = str(float(this_time) - float(time_list[qnum])) + "P" + pause_index = num-1 + break + + # Make the adjustments to the M117 (and M118) lines that are prior to a pause + for num in range (2, len(data) - 1,1): + layer = data[num] + lines = layer.split("\n") + for line in lines: + try: + if line.startswith("M117") and "|" in line and "P" in time_list[num]: + time_to_go = self._get_time_to_go(time_list[num]) + M117_line = line.split("|")[0] + "| TP " + time_to_go + layer = layer.replace(line, M117_line) + if line.startswith("M118") and "|" in line and "P" in time_list[num]: + time_to_go = self._get_time_to_go(time_list[num]) + M118_line = line.split("|")[0] + "| TP " + time_to_go + layer = layer.replace(line, M118_line) + except: + continue + data[num] = layer + if bool(self.getSettingValueByKey("enable_end_message")): + message_str = self._message_to_user(speed_factor) + Message(title = "[Display Info on LCD] - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() + return data + + def _message_to_user(self, speed_factor: float): # Message the user of the projected finish time of the print print_time = Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601) print_start_time = self.getSettingValueByKey("print_start_time") @@ -600,8 +596,8 @@ class DisplayInfoOnLCD(Script): adjusted_str = "Adjusted Time Estimate..." + str(time_change) finish_str = week_day + " " + str(mo_str) + " " + str(new_time.strftime("%d")) + ", " + str(new_time.strftime("%Y")) + " at " + str(show_hr) + str(new_time.strftime("%M")) + str(show_ampm) return finish_str, estimate_str, adjusted_str, print_start_str - - def get_time_to_go(self, time_str: str): + + def _get_time_to_go(self, time_str: str): alt_time = time_str[:-1] hhh = int(float(alt_time) / 3600) if hhh > 0: @@ -613,4 +609,36 @@ class DisplayInfoOnLCD(Script): mmm = str(round(mmm)) + "m" time_to_go = str(hhr) + str(mmm) if hhr == "": time_to_go = time_to_go + str(sss) + "s" - return time_to_go \ No newline at end of file + return time_to_go + + def _add_stats(self, data: str) -> str: + global_stack = Application.getInstance().getGlobalContainerStack() + # Create a list of the models in the file + model_list = [] + for mdex, layer in enumerate(data): + layer = data[mdex].split("\n") + for line in layer: + if line.startswith(";MESH:") and "NONMESH" not in line: + model_name = line.split(":")[1] + if not model_name in model_list: + model_list.append(model_name) + # Add the Initial Layer Height just below Layer Height in data[0]model_list = [] + extruder_count = global_stack.getProperty("machine_extruder_count", "value") + init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) + nozzle_size_line = ";Nozzle Size (T0): " + str(global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")) + filament_type = "\n;Filament Type (T0): " + str(global_stack.extruderList[0].getProperty("material_type", "value")) + print_temperature_line = ";Print Temperature (T0): " + str(global_stack.extruderList[0].getProperty("material_print_temperature", "value")) + if extruder_count > 1: + nozzle_size_line += "\n;Nozzle Size (T1): " + str(global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")) + filament_type += "\n;Filament type (T1): " + str(global_stack.extruderList[1].getProperty("material_type", "value")) + print_temperature_line += "\n;Print Temperature (T1): " + str(global_stack.extruderList[1].getProperty("material_print_temperature", "value")) + lines = data[0].split("\n") + for index, line in enumerate(lines): + if line.startswith(";Layer height:"): + lines[index] += "\n" + init_layer_hgt_line + "\n" + nozzle_size_line + "\n" + print_temperature_line + if line.startswith(";Filament used"): + lines[index] += filament_type + if "MINX" in line or "MIN.X" in line: + # Add the model list + lines[index - 1] += f"\n;Model List: {str(model_list)}" + return "\n".join(lines) \ No newline at end of file From fba94ae2c48f1ec887c6c4caba04759a86b81e0d Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Wed, 8 Jan 2025 07:27:28 -0500 Subject: [PATCH 021/299] Update AddCoolingProfile.py Changed variable name "curaApp" to "global_stack". Update AddCoolingProfile.py Add except for 'Build Volume Fan' for previous versions. --- .../scripts/AddCoolingProfile.py | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py index 370b0aff96..c6ec748f96 100644 --- a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py +++ b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py @@ -353,10 +353,10 @@ class AddCoolingProfile(Script): def initialize(self) -> None: super().initialize() - curaApp = Application.getInstance().getGlobalContainerStack() - extruder = curaApp.extruderList - extruder_count = curaApp.getProperty("machine_extruder_count", "value") - scripts = curaApp.getMetaDataEntry("post_processing_scripts") + global_stack = Application.getInstance().getGlobalContainerStack() + extruder = global_stack.extruderList + extruder_count = global_stack.getProperty("machine_extruder_count", "value") + scripts = global_stack.getMetaDataEntry("post_processing_scripts") if scripts != None: script_count = scripts.count("AddCoolingProfile") if script_count > 0: @@ -365,8 +365,14 @@ class AddCoolingProfile(Script): if extruder_count > 1: if extruder[0].getProperty("machine_extruder_cooling_fan_number", "value") != extruder[1].getProperty("machine_extruder_cooling_fan_number", "value"): self._instance.setProperty("enable_off_fan_speed_enable", "value", True) - self.has_bv_fan = bool(curaApp.getProperty("build_volume_fan_nr", "value")) - self.bv_fan_nr = int(curaApp.getProperty("build_volume_fan_nr", "value")) + + self.has_bv_fan = False + self.bv_fan_nr = 0 + try: + self.has_bv_fan = bool(global_stack.getProperty("build_volume_fan_nr", "value")) + self.bv_fan_nr = int(global_stack.getProperty("build_volume_fan_nr", "value")) + except: + pass if self.has_bv_fan: self._instance.setProperty("enable_bv_fan", "value", True) @@ -375,12 +381,12 @@ class AddCoolingProfile(Script): if ";POSTPROCESSED" in data[0]: return data #Initialize variables that are buried in if statements. - self.curaApp = Application.getInstance().getGlobalContainerStack() + self.global_stack = Application.getInstance().getGlobalContainerStack() t0_fan = " P0"; t1_fan = " P0"; t2_fan = " P0"; t3_fan = " P0"; is_multi_extr_print = True #Get some information from Cura----------------------------------- - extruder = self.curaApp.extruderList - extruder_count = self.curaApp.getProperty("machine_extruder_count", "value") + extruder = self.global_stack.extruderList + extruder_count = self.global_stack.getProperty("machine_extruder_count", "value") #This will be true when fan scale is 0-255pwm and false when it's RepRap 0-1 (Cura 5.x) fan_mode = True @@ -390,7 +396,7 @@ class AddCoolingProfile(Script): except: pass bed_adhesion = (extruder[0].getProperty("adhesion_type", "value")) - print_sequence = str(self.curaApp.getProperty("print_sequence", "value")) + print_sequence = str(self.global_stack.getProperty("print_sequence", "value")) #Assign the fan numbers to the tools------------------------------ if extruder_count == 1: @@ -727,7 +733,7 @@ class AddCoolingProfile(Script): if modified_data.endswith("\n"): modified_data = modified_data[0:-1] multi_fan_data[l_index] = modified_data # Insure the fans get shut off if 'off_fan_speed' was enabled - if self.curaApp.getProperty("machine_extruder_count", "value") > 1 and self.getSettingValueByKey("enable_off_fan_speed"): + if self.global_stack.getProperty("machine_extruder_count", "value") > 1 and self.getSettingValueByKey("enable_off_fan_speed"): multi_fan_data[-1] += "M106 S0 P1\nM106 S0 P0\n" return multi_fan_data @@ -854,7 +860,7 @@ class AddCoolingProfile(Script): multi_fan_data[l_index] = modified_data modified_data = "" # Insure the fans get shut off if 'off_fan_speed' was enabled - if self.curaApp.getProperty("machine_extruder_count", "value") > 1 and self.getSettingValueByKey("enable_off_fan_speed"): + if self.global_stack.getProperty("machine_extruder_count", "value") > 1 and self.getSettingValueByKey("enable_off_fan_speed"): multi_fan_data[-1] += "M106 S0 P1\nM106 S0 P0\n" return multi_fan_data @@ -949,7 +955,7 @@ class AddCoolingProfile(Script): if bv_end_layer != -1: bv_end_layer -= 1 # Get the PWM speed or if RepRap then the 0-1 speed - if self.curaApp.extruderList[0].getProperty("machine_scale_fan_speed_zero_to_one", "value"): + if self.global_stack.extruderList[0].getProperty("machine_scale_fan_speed_zero_to_one", "value"): bv_fan_speed = round(self.getSettingValueByKey("bv_fan_speed") * .01, 1) else: bv_fan_speed = int(self.getSettingValueByKey("bv_fan_speed") * 2.55) From 3186cce9155d8d1cbee130048a7b6ee2c5efca60 Mon Sep 17 00:00:00 2001 From: Boris Juraga Date: Tue, 21 Jan 2025 09:24:01 +0100 Subject: [PATCH 022/299] initial add of a definition, extruder, quality and variant resources --- resources/definitions/biqu_b2.def.json | 32 ++++++++++++++ .../extruders/biqu_b2_extruder_1.def.json | 16 +++++++ .../biqu/b2/biqu_b2_0.4_PLA_adaptive.inst.cfg | 14 ++++++ .../biqu/b2/biqu_b2_0.4_PLA_draft.inst.cfg | 14 ++++++ .../biqu/b2/biqu_b2_0.4_PLA_low.inst.cfg | 14 ++++++ .../biqu/b2/biqu_b2_0.4_PLA_standard.inst.cfg | 14 ++++++ .../biqu/b2/biqu_b2_0.4_PLA_super.inst.cfg | 14 ++++++ .../biqu/b2/biqu_b2_0.4_PLA_ultra.inst.cfg | 14 ++++++ .../biqu/b2/biqu_b2_global_adaptive.inst.cfg | 43 ++++++++++++++++++ .../biqu/b2/biqu_b2_global_draft.inst.cfg | 42 ++++++++++++++++++ .../biqu/b2/biqu_b2_global_low.inst.cfg | 42 ++++++++++++++++++ .../biqu/b2/biqu_b2_global_standard.inst.cfg | 44 +++++++++++++++++++ .../biqu/b2/biqu_b2_global_super.inst.cfg | 42 ++++++++++++++++++ .../biqu/b2/biqu_b2_global_ultra.inst.cfg | 42 ++++++++++++++++++ resources/variants/biqu/biqu_b2_0.2.inst.cfg | 13 ++++++ resources/variants/biqu/biqu_b2_0.3.inst.cfg | 13 ++++++ resources/variants/biqu/biqu_b2_0.4.inst.cfg | 13 ++++++ resources/variants/biqu/biqu_b2_0.5.inst.cfg | 13 ++++++ resources/variants/biqu/biqu_b2_0.6.inst.cfg | 13 ++++++ resources/variants/biqu/biqu_b2_0.8.inst.cfg | 13 ++++++ 20 files changed, 465 insertions(+) create mode 100644 resources/definitions/biqu_b2.def.json create mode 100644 resources/extruders/biqu_b2_extruder_1.def.json create mode 100644 resources/quality/biqu/b2/biqu_b2_0.4_PLA_adaptive.inst.cfg create mode 100644 resources/quality/biqu/b2/biqu_b2_0.4_PLA_draft.inst.cfg create mode 100644 resources/quality/biqu/b2/biqu_b2_0.4_PLA_low.inst.cfg create mode 100644 resources/quality/biqu/b2/biqu_b2_0.4_PLA_standard.inst.cfg create mode 100644 resources/quality/biqu/b2/biqu_b2_0.4_PLA_super.inst.cfg create mode 100644 resources/quality/biqu/b2/biqu_b2_0.4_PLA_ultra.inst.cfg create mode 100644 resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg create mode 100644 resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg create mode 100644 resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg create mode 100644 resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg create mode 100644 resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg create mode 100644 resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg create mode 100644 resources/variants/biqu/biqu_b2_0.2.inst.cfg create mode 100644 resources/variants/biqu/biqu_b2_0.3.inst.cfg create mode 100644 resources/variants/biqu/biqu_b2_0.4.inst.cfg create mode 100644 resources/variants/biqu/biqu_b2_0.5.inst.cfg create mode 100644 resources/variants/biqu/biqu_b2_0.6.inst.cfg create mode 100644 resources/variants/biqu/biqu_b2_0.8.inst.cfg diff --git a/resources/definitions/biqu_b2.def.json b/resources/definitions/biqu_b2.def.json new file mode 100644 index 0000000000..d5ed45ee85 --- /dev/null +++ b/resources/definitions/biqu_b2.def.json @@ -0,0 +1,32 @@ +{ + "version": 2, + "name": "Biqu B2", + "inherits": "biqu_b1", + "metadata": + { + "visible": true, + "author": "Boris Juraga", + "machine_extruder_trains": { + "0": "biqu_base_extruder_0", + "1": "biqu_b2_extruder_1" + }, + "quality_definition": "biqu_b2" + }, + "overrides": + { + "gantry_height": { "value": 27.5 }, + "machine_extruder_count": { "default_value": 2 }, + "machine_head_with_fans_polygon": + { + "default_value": [ + [-33, 35], + [-33, -23], + [33, -23], + [33, 35] + ] + }, + "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\n;Retract the filament\nG91\nG1 E-30 F300\nG1 Z5\nG90\nG28 X0 Y0" }, + "machine_name": { "default_value": "BIQU B2" }, + "machine_start_gcode": { "default_value": "\nG28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\n\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\n\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT1\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X6.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X6.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X6.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X6.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X6.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X6.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X7.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X7.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X7.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X7.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 \n\nT1\nG92 E0\nG1 F1200 E-30\nG92 E0\n\nT0\nG92 E0\nG1 F1200 E30\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X9.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X9.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X9.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X9.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X9.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X9.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X10.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X10.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X10.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X10.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 ; start print" } + } +} \ No newline at end of file diff --git a/resources/extruders/biqu_b2_extruder_1.def.json b/resources/extruders/biqu_b2_extruder_1.def.json new file mode 100644 index 0000000000..fc5778b071 --- /dev/null +++ b/resources/extruders/biqu_b2_extruder_1.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "Extruder 2", + "inherits": "fdmextruder", + "metadata": + { + "machine": "biqu_b2", + "position": "1" + }, + "overrides": + { + "extruder_nr": { "default_value": 1 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} \ No newline at end of file diff --git a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_adaptive.inst.cfg b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_adaptive.inst.cfg new file mode 100644 index 0000000000..ef478ac259 --- /dev/null +++ b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_adaptive.inst.cfg @@ -0,0 +1,14 @@ +[general] +definition = biqu_b2 +name = Dynamic Quality +version = 4 + +[metadata] +material = generic_pla_175 +quality_type = adaptive +setting_version = 24 +type = quality +variant = 0.4mm Nozzle + +[values] + diff --git a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_draft.inst.cfg b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_draft.inst.cfg new file mode 100644 index 0000000000..526aa6bdf2 --- /dev/null +++ b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_draft.inst.cfg @@ -0,0 +1,14 @@ +[general] +definition = biqu_b2 +name = Draft Quality +version = 4 + +[metadata] +material = generic_pla_175 +quality_type = draft +setting_version = 24 +type = quality +variant = 0.4mm Nozzle + +[values] + diff --git a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_low.inst.cfg b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_low.inst.cfg new file mode 100644 index 0000000000..8ee3e16ff4 --- /dev/null +++ b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_low.inst.cfg @@ -0,0 +1,14 @@ +[general] +definition = biqu_b2 +name = Low Quality +version = 4 + +[metadata] +material = generic_pla_175 +quality_type = low +setting_version = 24 +type = quality +variant = 0.4mm Nozzle + +[values] + diff --git a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_standard.inst.cfg b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_standard.inst.cfg new file mode 100644 index 0000000000..fd6ea4287d --- /dev/null +++ b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_standard.inst.cfg @@ -0,0 +1,14 @@ +[general] +definition = biqu_b2 +name = Standard Quality +version = 4 + +[metadata] +material = generic_pla_175 +quality_type = standard +setting_version = 24 +type = quality +variant = 0.4mm Nozzle + +[values] + diff --git a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_super.inst.cfg b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_super.inst.cfg new file mode 100644 index 0000000000..4d2899b599 --- /dev/null +++ b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_super.inst.cfg @@ -0,0 +1,14 @@ +[general] +definition = biqu_b2 +name = Super Quality +version = 4 + +[metadata] +material = generic_pla_175 +quality_type = super +setting_version = 24 +type = quality +variant = 0.4mm Nozzle + +[values] + diff --git a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_ultra.inst.cfg b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_ultra.inst.cfg new file mode 100644 index 0000000000..247fdcf1a8 --- /dev/null +++ b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_ultra.inst.cfg @@ -0,0 +1,14 @@ +[general] +definition = biqu_b2 +name = Ultra Quality +version = 4 + +[metadata] +material = generic_pla_175 +quality_type = ultra +setting_version = 24 +type = quality +variant = 0.4mm Nozzle + +[values] + diff --git a/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg new file mode 100644 index 0000000000..81178fdeed --- /dev/null +++ b/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg @@ -0,0 +1,43 @@ +[general] +definition = biqu_b2 +name = Dynamic Quality +version = 4 + +[metadata] +global_quality = True +quality_type = adaptive +setting_version = 24 +type = quality +weight = -2 + +[values] +adaptive_layer_height_enabled = true +layer_height = 0.16 +layer_height_0 = 0.20 +support_interface_height = =layer_height*6 +top_bottom_thickness = =layer_height_0+layer_height*4 +wall_thickness = =line_width*3 +cool_fan_full_at_height = 0.6 +cool_fan_speed = 50 +material_final_print_temperature = 190 +material_initial_print_temperature = 190 +material_print_temperature = 190 +material_standby_temperature = 190 +optimize_wall_printing_order = True +prime_tower_min_volume = 135 +retraction_amount = 4 +retraction_extra_prime_amount = 2 +retraction_extrusion_window = 8 +retraction_hop = 3 +retraction_hop_enabled = True +retraction_hop_only_when_collides = True +retraction_min_travel = 10 +retraction_prime_speed = 5 +retraction_speed = 30 +speed_layer_0 = 20 +speed_travel = 60 +speed_wall = 30 +speed_wall_x = 20 +switch_extruder_prime_speed = 10 +switch_extruder_retraction_amount = 40 +switch_extruder_retraction_speeds = 30 diff --git a/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg new file mode 100644 index 0000000000..36d50ada37 --- /dev/null +++ b/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg @@ -0,0 +1,42 @@ +[general] +definition = biqu_b2 +name = Draft Quality +version = 4 + +[metadata] +global_quality = True +quality_type = draft +setting_version = 24 +type = quality +weight = -5 + +[values] +layer_height = 0.32 +layer_height_0 = 0.32 +support_interface_height = =layer_height*4 +top_bottom_thickness = =layer_height_0+layer_height*3 +wall_thickness = =line_width*2 +cool_fan_full_at_height = 0.6 +cool_fan_speed = 50 +material_final_print_temperature = 190 +material_initial_print_temperature = 190 +material_print_temperature = 190 +material_standby_temperature = 190 +optimize_wall_printing_order = True +prime_tower_min_volume = 135 +retraction_amount = 4 +retraction_extra_prime_amount = 2 +retraction_extrusion_window = 8 +retraction_hop = 3 +retraction_hop_enabled = True +retraction_hop_only_when_collides = True +retraction_min_travel = 10 +retraction_prime_speed = 5 +retraction_speed = 30 +speed_layer_0 = 20 +speed_travel = 60 +speed_wall = 30 +speed_wall_x = 20 +switch_extruder_prime_speed = 10 +switch_extruder_retraction_amount = 40 +switch_extruder_retraction_speeds = 30 diff --git a/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg new file mode 100644 index 0000000000..2fb4804640 --- /dev/null +++ b/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg @@ -0,0 +1,42 @@ +[general] +definition = biqu_b2 +name = Low Quality +version = 4 + +[metadata] +global_quality = True +quality_type = low +setting_version = 24 +type = quality +weight = -4 + +[values] +layer_height = 0.28 +layer_height_0 = 0.28 +support_interface_height = =layer_height*4 +top_bottom_thickness = =layer_height_0+layer_height*3 +wall_thickness = =line_width*3 +cool_fan_full_at_height = 0.6 +cool_fan_speed = 50 +material_final_print_temperature = 190 +material_initial_print_temperature = 190 +material_print_temperature = 190 +material_standby_temperature = 190 +optimize_wall_printing_order = True +prime_tower_min_volume = 135 +retraction_amount = 4 +retraction_extra_prime_amount = 2 +retraction_extrusion_window = 8 +retraction_hop = 3 +retraction_hop_enabled = True +retraction_hop_only_when_collides = True +retraction_min_travel = 10 +retraction_prime_speed = 5 +retraction_speed = 30 +speed_layer_0 = 20 +speed_travel = 60 +speed_wall = 30 +speed_wall_x = 20 +switch_extruder_prime_speed = 10 +switch_extruder_retraction_amount = 40 +switch_extruder_retraction_speeds = 30 diff --git a/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg new file mode 100644 index 0000000000..4d2b5660b6 --- /dev/null +++ b/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg @@ -0,0 +1,44 @@ +[general] +definition = biqu_b2 +name = Standard Quality +version = 4 + +[metadata] +global_quality = True +quality_type = standard +setting_version = 24 +type = quality +weight = -3 +position = 0 + +[values] +layer_height = 0.2 +layer_height_0 = 0.2 +support_interface_height = =layer_height*4 +top_bottom_thickness = =layer_height_0+layer_height*3 +wall_thickness = =line_width*3 +brim_width = 4 +cool_fan_full_at_height = 0.6 +cool_fan_speed = 50 +material_final_print_temperature = 190 +material_initial_print_temperature = 190 +material_print_temperature = 190 +material_standby_temperature = 190 +optimize_wall_printing_order = True +prime_tower_min_volume = 135 +retraction_amount = 4 +retraction_extra_prime_amount = 2 +retraction_extrusion_window = 8 +retraction_hop = 3 +retraction_hop_enabled = True +retraction_hop_only_when_collides = True +retraction_min_travel = 10 +retraction_prime_speed = 5 +retraction_speed = 30 +speed_layer_0 = 20 +speed_travel = 60 +speed_wall = 30 +speed_wall_x = 20 +switch_extruder_prime_speed = 10 +switch_extruder_retraction_amount = 40 +switch_extruder_retraction_speeds = 30 \ No newline at end of file diff --git a/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg new file mode 100644 index 0000000000..fc9860a695 --- /dev/null +++ b/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg @@ -0,0 +1,42 @@ +[general] +definition = biqu_b2 +name = Super Quality +version = 4 + +[metadata] +global_quality = True +quality_type = super +setting_version = 24 +type = quality +weight = -1 + +[values] +layer_height = 0.12 +layer_height_0 = 0.12 +support_interface_height = =layer_height*8 +top_bottom_thickness = =layer_height_0+layer_height*6 +wall_thickness = =line_width*3 +cool_fan_full_at_height = 0.6 +cool_fan_speed = 50 +material_final_print_temperature = 190 +material_initial_print_temperature = 190 +material_print_temperature = 190 +material_standby_temperature = 190 +optimize_wall_printing_order = True +prime_tower_min_volume = 135 +retraction_amount = 4 +retraction_extra_prime_amount = 2 +retraction_extrusion_window = 8 +retraction_hop = 3 +retraction_hop_enabled = True +retraction_hop_only_when_collides = True +retraction_min_travel = 10 +retraction_prime_speed = 5 +retraction_speed = 30 +speed_layer_0 = 20 +speed_travel = 60 +speed_wall = 30 +speed_wall_x = 20 +switch_extruder_prime_speed = 10 +switch_extruder_retraction_amount = 40 +switch_extruder_retraction_speeds = 30 \ No newline at end of file diff --git a/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg new file mode 100644 index 0000000000..55fad68102 --- /dev/null +++ b/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg @@ -0,0 +1,42 @@ +[general] +definition = biqu_b2 +name = Ultra Quality +version = 4 + +[metadata] +global_quality = True +quality_type = ultra +setting_version = 24 +type = quality +weight = 0 + +[values] +layer_height = 0.08 +layer_height_0 = 0.12 +support_interface_height = =layer_height*12 +top_bottom_thickness = =layer_height_0+layer_height*10 +wall_thickness = =line_width*4 +cool_fan_full_at_height = 0.6 +cool_fan_speed = 50 +material_final_print_temperature = 190 +material_initial_print_temperature = 190 +material_print_temperature = 190 +material_standby_temperature = 190 +optimize_wall_printing_order = True +prime_tower_min_volume = 135 +retraction_amount = 4 +retraction_extra_prime_amount = 2 +retraction_extrusion_window = 8 +retraction_hop = 3 +retraction_hop_enabled = True +retraction_hop_only_when_collides = True +retraction_min_travel = 10 +retraction_prime_speed = 5 +retraction_speed = 30 +speed_layer_0 = 20 +speed_travel = 60 +speed_wall = 30 +speed_wall_x = 20 +switch_extruder_prime_speed = 10 +switch_extruder_retraction_amount = 40 +switch_extruder_retraction_speeds = 30 \ No newline at end of file diff --git a/resources/variants/biqu/biqu_b2_0.2.inst.cfg b/resources/variants/biqu/biqu_b2_0.2.inst.cfg new file mode 100644 index 0000000000..8f7d063b93 --- /dev/null +++ b/resources/variants/biqu/biqu_b2_0.2.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = biqu_b2 +name = 0.2mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 24 +type = variant + +[values] +machine_nozzle_size = 0.2 + diff --git a/resources/variants/biqu/biqu_b2_0.3.inst.cfg b/resources/variants/biqu/biqu_b2_0.3.inst.cfg new file mode 100644 index 0000000000..e6381dfe80 --- /dev/null +++ b/resources/variants/biqu/biqu_b2_0.3.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = biqu_b2 +name = 0.3mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 24 +type = variant + +[values] +machine_nozzle_size = 0.3 + diff --git a/resources/variants/biqu/biqu_b2_0.4.inst.cfg b/resources/variants/biqu/biqu_b2_0.4.inst.cfg new file mode 100644 index 0000000000..99958af88d --- /dev/null +++ b/resources/variants/biqu/biqu_b2_0.4.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = biqu_b2 +name = 0.4mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 24 +type = variant + +[values] +machine_nozzle_size = 0.4 + diff --git a/resources/variants/biqu/biqu_b2_0.5.inst.cfg b/resources/variants/biqu/biqu_b2_0.5.inst.cfg new file mode 100644 index 0000000000..194e5a79c4 --- /dev/null +++ b/resources/variants/biqu/biqu_b2_0.5.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = biqu_b2 +name = 0.5mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 24 +type = variant + +[values] +machine_nozzle_size = 0.5 + diff --git a/resources/variants/biqu/biqu_b2_0.6.inst.cfg b/resources/variants/biqu/biqu_b2_0.6.inst.cfg new file mode 100644 index 0000000000..828843f658 --- /dev/null +++ b/resources/variants/biqu/biqu_b2_0.6.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = biqu_b2 +name = 0.6mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 24 +type = variant + +[values] +machine_nozzle_size = 0.6 + diff --git a/resources/variants/biqu/biqu_b2_0.8.inst.cfg b/resources/variants/biqu/biqu_b2_0.8.inst.cfg new file mode 100644 index 0000000000..8bc16cfade --- /dev/null +++ b/resources/variants/biqu/biqu_b2_0.8.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = biqu_b2 +name = 0.8mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 24 +type = variant + +[values] +machine_nozzle_size = 0.8 + From b56f7db5a05b3dfbeed61939f5a538d20d6ef757 Mon Sep 17 00:00:00 2001 From: Boris Juraga Date: Tue, 21 Jan 2025 14:19:42 +0100 Subject: [PATCH 023/299] learned about shared nozzles and shared heaters --- resources/definitions/biqu_b2.def.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/definitions/biqu_b2.def.json b/resources/definitions/biqu_b2.def.json index d5ed45ee85..6768751716 100644 --- a/resources/definitions/biqu_b2.def.json +++ b/resources/definitions/biqu_b2.def.json @@ -27,6 +27,9 @@ }, "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\n;Retract the filament\nG91\nG1 E-30 F300\nG1 Z5\nG90\nG28 X0 Y0" }, "machine_name": { "default_value": "BIQU B2" }, - "machine_start_gcode": { "default_value": "\nG28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\n\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\n\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT1\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X6.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X6.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X6.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X6.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X6.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X6.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X7.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X7.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X7.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X7.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 \n\nT1\nG92 E0\nG1 F1200 E-30\nG92 E0\n\nT0\nG92 E0\nG1 F1200 E30\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X9.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X9.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X9.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X9.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X9.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X9.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X10.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X10.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X10.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X10.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 ; start print" } + "machine_start_gcode": { "default_value": "G28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT1\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X6.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X6.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X6.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X6.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X6.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X6.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X7.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X7.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X7.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X7.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 \nT1\nG92 E0\nG1 F1200 E-30\nG92 E0\nT0\nG92 E0\nG1 F1200 E30\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X9.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X9.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X9.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X9.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X9.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X9.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X10.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X10.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X10.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X10.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nG92 E0 ; start print" }, + "machine_extruders_share_heater": { "default_value": true }, + "machine_extruders_share_nozzle": { "default_value": true }, + "machine_extruders_shared_nozzle_initial_retraction": { "default_value": 30 } } } \ No newline at end of file From a0d2d6fb620eecc2d56b05666f40b7b1f9ce6fec Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 28 Jan 2025 09:02:10 +0100 Subject: [PATCH 024/299] Add setting for retract/unretract during travel move CURA-11978 --- resources/definitions/fdmprinter.def.json | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index c1392e57ba..2425df01b1 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -4278,6 +4278,32 @@ "settable_per_mesh": false, "settable_per_extruder": true }, + "retraction_during_travel_ratio": + { + "label": "Retraction During Travel Move", + "description": "The ratio of retraction performed during the travel move, with the remainder completed while the nozzle is stationary, before traveling
  • When 0, the entire retraction is performed while stationary, before the travel begins
  • When 100, the entire retraction is performed during the travel move, bypassing the stationary phase
", + "unit": "%", + "type": "float", + "default_value": 0, + "minimum_value": 0, + "maximum_value": 100, + "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "prime_during_travel_ratio": + { + "label": "Prime During Travel Move", + "description": "The ratio of priming performed during the travel move, with the remainder completed while the nozzle is stationary, after traveling
  • When 0, the entire priming is performed while stationary, after the travel ends
  • When 100, the entire priming is performed during the travel move, allowing the print to start immediately
", + "unit": "%", + "type": "float", + "default_value": 0, + "minimum_value": 0, + "maximum_value": 100, + "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", + "settable_per_mesh": false, + "settable_per_extruder": true + }, "retraction_speed": { "label": "Retraction Speed", From 369600c29acb088ab1b763878b35c8a128c27773 Mon Sep 17 00:00:00 2001 From: Boris Juraga Date: Thu, 30 Jan 2025 14:41:51 +0100 Subject: [PATCH 025/299] profile looks good --- resources/definitions/biqu_b2.def.json | 4 ++- .../biqu/b2/biqu_b2_global_adaptive.inst.cfg | 25 ++++--------------- .../biqu/b2/biqu_b2_global_draft.inst.cfg | 25 ++++--------------- .../biqu/b2/biqu_b2_global_low.inst.cfg | 25 ++++--------------- .../biqu/b2/biqu_b2_global_standard.inst.cfg | 24 +++--------------- .../biqu/b2/biqu_b2_global_super.inst.cfg | 23 +++-------------- .../biqu/b2/biqu_b2_global_ultra.inst.cfg | 23 +++-------------- 7 files changed, 30 insertions(+), 119 deletions(-) diff --git a/resources/definitions/biqu_b2.def.json b/resources/definitions/biqu_b2.def.json index 6768751716..c174db33db 100644 --- a/resources/definitions/biqu_b2.def.json +++ b/resources/definitions/biqu_b2.def.json @@ -30,6 +30,8 @@ "machine_start_gcode": { "default_value": "G28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT1\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X6.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X6.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X6.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X6.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X6.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X6.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X7.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X7.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X7.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X7.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 \nT1\nG92 E0\nG1 F1200 E-30\nG92 E0\nT0\nG92 E0\nG1 F1200 E30\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X9.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X9.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X9.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X9.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X9.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X9.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X10.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X10.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X10.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X10.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nG92 E0 ; start print" }, "machine_extruders_share_heater": { "default_value": true }, "machine_extruders_share_nozzle": { "default_value": true }, - "machine_extruders_shared_nozzle_initial_retraction": { "default_value": 30 } + "machine_extruders_shared_nozzle_initial_retraction": { "default_value": 30 }, + "prime_tower_enable": { "default_value": true }, + "prime_tower_mode": { "default_value": "interleaved" } } } \ No newline at end of file diff --git a/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg index 81178fdeed..cd755a1cff 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg @@ -17,27 +17,12 @@ layer_height_0 = 0.20 support_interface_height = =layer_height*6 top_bottom_thickness = =layer_height_0+layer_height*4 wall_thickness = =line_width*3 -cool_fan_full_at_height = 0.6 -cool_fan_speed = 50 -material_final_print_temperature = 190 -material_initial_print_temperature = 190 +material_final_print_temperature = 195 +material_initial_print_temperature = 195 material_print_temperature = 190 -material_standby_temperature = 190 +material_standby_temperature = 195 optimize_wall_printing_order = True -prime_tower_min_volume = 135 -retraction_amount = 4 -retraction_extra_prime_amount = 2 -retraction_extrusion_window = 8 -retraction_hop = 3 -retraction_hop_enabled = True -retraction_hop_only_when_collides = True -retraction_min_travel = 10 -retraction_prime_speed = 5 -retraction_speed = 30 -speed_layer_0 = 20 -speed_travel = 60 -speed_wall = 30 -speed_wall_x = 20 +prime_tower_min_volume = 150 switch_extruder_prime_speed = 10 switch_extruder_retraction_amount = 40 -switch_extruder_retraction_speeds = 30 +switch_extruder_retraction_speeds = 30 \ No newline at end of file diff --git a/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg index 36d50ada37..92deadd38c 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg @@ -16,27 +16,12 @@ layer_height_0 = 0.32 support_interface_height = =layer_height*4 top_bottom_thickness = =layer_height_0+layer_height*3 wall_thickness = =line_width*2 -cool_fan_full_at_height = 0.6 -cool_fan_speed = 50 -material_final_print_temperature = 190 -material_initial_print_temperature = 190 +material_final_print_temperature = 195 +material_initial_print_temperature = 195 material_print_temperature = 190 -material_standby_temperature = 190 +material_standby_temperature = 195 optimize_wall_printing_order = True -prime_tower_min_volume = 135 -retraction_amount = 4 -retraction_extra_prime_amount = 2 -retraction_extrusion_window = 8 -retraction_hop = 3 -retraction_hop_enabled = True -retraction_hop_only_when_collides = True -retraction_min_travel = 10 -retraction_prime_speed = 5 -retraction_speed = 30 -speed_layer_0 = 20 -speed_travel = 60 -speed_wall = 30 -speed_wall_x = 20 +prime_tower_min_volume = 150 switch_extruder_prime_speed = 10 switch_extruder_retraction_amount = 40 -switch_extruder_retraction_speeds = 30 +switch_extruder_retraction_speeds = 30 \ No newline at end of file diff --git a/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg index 2fb4804640..0455a6ec20 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg @@ -16,27 +16,12 @@ layer_height_0 = 0.28 support_interface_height = =layer_height*4 top_bottom_thickness = =layer_height_0+layer_height*3 wall_thickness = =line_width*3 -cool_fan_full_at_height = 0.6 -cool_fan_speed = 50 -material_final_print_temperature = 190 -material_initial_print_temperature = 190 +material_final_print_temperature = 195 +material_initial_print_temperature = 195 material_print_temperature = 190 -material_standby_temperature = 190 +material_standby_temperature = 195 optimize_wall_printing_order = True -prime_tower_min_volume = 135 -retraction_amount = 4 -retraction_extra_prime_amount = 2 -retraction_extrusion_window = 8 -retraction_hop = 3 -retraction_hop_enabled = True -retraction_hop_only_when_collides = True -retraction_min_travel = 10 -retraction_prime_speed = 5 -retraction_speed = 30 -speed_layer_0 = 20 -speed_travel = 60 -speed_wall = 30 -speed_wall_x = 20 +prime_tower_min_volume = 150 switch_extruder_prime_speed = 10 switch_extruder_retraction_amount = 40 -switch_extruder_retraction_speeds = 30 +switch_extruder_retraction_speeds = 30 \ No newline at end of file diff --git a/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg index 4d2b5660b6..a0fb268e52 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg @@ -17,28 +17,12 @@ layer_height_0 = 0.2 support_interface_height = =layer_height*4 top_bottom_thickness = =layer_height_0+layer_height*3 wall_thickness = =line_width*3 -brim_width = 4 -cool_fan_full_at_height = 0.6 -cool_fan_speed = 50 -material_final_print_temperature = 190 -material_initial_print_temperature = 190 +material_final_print_temperature = 195 +material_initial_print_temperature = 195 material_print_temperature = 190 -material_standby_temperature = 190 +material_standby_temperature = 195 optimize_wall_printing_order = True -prime_tower_min_volume = 135 -retraction_amount = 4 -retraction_extra_prime_amount = 2 -retraction_extrusion_window = 8 -retraction_hop = 3 -retraction_hop_enabled = True -retraction_hop_only_when_collides = True -retraction_min_travel = 10 -retraction_prime_speed = 5 -retraction_speed = 30 -speed_layer_0 = 20 -speed_travel = 60 -speed_wall = 30 -speed_wall_x = 20 +prime_tower_min_volume = 150 switch_extruder_prime_speed = 10 switch_extruder_retraction_amount = 40 switch_extruder_retraction_speeds = 30 \ No newline at end of file diff --git a/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg index fc9860a695..fd54805c04 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg @@ -16,27 +16,12 @@ layer_height_0 = 0.12 support_interface_height = =layer_height*8 top_bottom_thickness = =layer_height_0+layer_height*6 wall_thickness = =line_width*3 -cool_fan_full_at_height = 0.6 -cool_fan_speed = 50 -material_final_print_temperature = 190 -material_initial_print_temperature = 190 +material_final_print_temperature = 195 +material_initial_print_temperature = 195 material_print_temperature = 190 -material_standby_temperature = 190 +material_standby_temperature = 195 optimize_wall_printing_order = True -prime_tower_min_volume = 135 -retraction_amount = 4 -retraction_extra_prime_amount = 2 -retraction_extrusion_window = 8 -retraction_hop = 3 -retraction_hop_enabled = True -retraction_hop_only_when_collides = True -retraction_min_travel = 10 -retraction_prime_speed = 5 -retraction_speed = 30 -speed_layer_0 = 20 -speed_travel = 60 -speed_wall = 30 -speed_wall_x = 20 +prime_tower_min_volume = 150 switch_extruder_prime_speed = 10 switch_extruder_retraction_amount = 40 switch_extruder_retraction_speeds = 30 \ No newline at end of file diff --git a/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg index 55fad68102..cbc194ceb6 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg @@ -16,27 +16,12 @@ layer_height_0 = 0.12 support_interface_height = =layer_height*12 top_bottom_thickness = =layer_height_0+layer_height*10 wall_thickness = =line_width*4 -cool_fan_full_at_height = 0.6 -cool_fan_speed = 50 -material_final_print_temperature = 190 -material_initial_print_temperature = 190 +material_final_print_temperature = 195 +material_initial_print_temperature = 195 material_print_temperature = 190 -material_standby_temperature = 190 +material_standby_temperature = 195 optimize_wall_printing_order = True -prime_tower_min_volume = 135 -retraction_amount = 4 -retraction_extra_prime_amount = 2 -retraction_extrusion_window = 8 -retraction_hop = 3 -retraction_hop_enabled = True -retraction_hop_only_when_collides = True -retraction_min_travel = 10 -retraction_prime_speed = 5 -retraction_speed = 30 -speed_layer_0 = 20 -speed_travel = 60 -speed_wall = 30 -speed_wall_x = 20 +prime_tower_min_volume = 150 switch_extruder_prime_speed = 10 switch_extruder_retraction_amount = 40 switch_extruder_retraction_speeds = 30 \ No newline at end of file From ea576d0ee6093a16eeac260beeae0eb3be2c9e9c Mon Sep 17 00:00:00 2001 From: Boris Juraga Date: Sun, 2 Feb 2025 10:44:08 +0100 Subject: [PATCH 026/299] add more clarity to the start/end gcode --- resources/definitions/biqu_b2.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/biqu_b2.def.json b/resources/definitions/biqu_b2.def.json index c174db33db..88ac6d589a 100644 --- a/resources/definitions/biqu_b2.def.json +++ b/resources/definitions/biqu_b2.def.json @@ -25,9 +25,9 @@ [33, 35] ] }, - "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\n;Retract the filament\nG91\nG1 E-30 F300\nG1 Z5\nG90\nG28 X0 Y0" }, + "machine_end_gcode": { "default_value": ";BEGIN OF CUSTOM END GCODE\nM104 S0\nM140 S0\n;Retract the filament\nG91\nG1 E-30 F300\nG1 Z5\nG90\nG28 X0 Y0\n;END OF CUSTOM END GCODE" }, "machine_name": { "default_value": "BIQU B2" }, - "machine_start_gcode": { "default_value": "G28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT1\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X6.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X6.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X6.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X6.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X6.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X6.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X7.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X7.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X7.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X7.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 \nT1\nG92 E0\nG1 F1200 E-30\nG92 E0\nT0\nG92 E0\nG1 F1200 E30\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X9.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X9.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X9.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X9.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X9.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X9.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X10.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X10.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X10.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X10.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nG92 E0 ; start print" }, + "machine_start_gcode": { "default_value": ";BEGIN OF CUSTOM START GCODE\nG28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT1\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X6.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X6.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X6.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X6.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X6.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X6.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X7.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X7.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X7.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X7.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 \nT1\nG92 E0\nG1 F1200 E-30\nG92 E0\nT0\nG92 E0\nG1 F1200 E30\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X9.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X9.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X9.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X9.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X9.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X9.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X10.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X10.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X10.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X10.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nG92 E0\n;END OF CUSTOM START GCODE\n; start print" }, "machine_extruders_share_heater": { "default_value": true }, "machine_extruders_share_nozzle": { "default_value": true }, "machine_extruders_shared_nozzle_initial_retraction": { "default_value": 30 }, From e7def395c61dbfe01bd3907b86b6998b4a8ab9aa Mon Sep 17 00:00:00 2001 From: Boris Juraga Date: Sun, 2 Feb 2025 10:59:28 +0100 Subject: [PATCH 027/299] reset extruder to initial one --- resources/definitions/biqu_b2.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/biqu_b2.def.json b/resources/definitions/biqu_b2.def.json index 88ac6d589a..6fe0d9004f 100644 --- a/resources/definitions/biqu_b2.def.json +++ b/resources/definitions/biqu_b2.def.json @@ -27,7 +27,7 @@ }, "machine_end_gcode": { "default_value": ";BEGIN OF CUSTOM END GCODE\nM104 S0\nM140 S0\n;Retract the filament\nG91\nG1 E-30 F300\nG1 Z5\nG90\nG28 X0 Y0\n;END OF CUSTOM END GCODE" }, "machine_name": { "default_value": "BIQU B2" }, - "machine_start_gcode": { "default_value": ";BEGIN OF CUSTOM START GCODE\nG28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT1\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X6.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X6.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X6.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X6.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X6.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X6.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X7.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X7.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X7.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X7.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 \nT1\nG92 E0\nG1 F1200 E-30\nG92 E0\nT0\nG92 E0\nG1 F1200 E30\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X9.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X9.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X9.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X9.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X9.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X9.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X10.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X10.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X10.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X10.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nG92 E0\n;END OF CUSTOM START GCODE\n; start print" }, + "machine_start_gcode": { "default_value": ";BEGIN OF CUSTOM START GCODE\nG28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT1\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X6.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X6.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X6.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X6.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X6.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X6.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X7.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X7.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X7.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X7.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 \nT1\nG92 E0\nG1 F1200 E-30\nG92 E0\nT0\nG92 E0\nG1 F1200 E30\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X9.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X9.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X9.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X9.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X9.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X9.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X10.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X10.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X10.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X10.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nG92 E0\n;END OF CUSTOM START GCODE\nT{initial_extruder_nr} ; RESET EXTRUDER TO INITIAL\n; start print" }, "machine_extruders_share_heater": { "default_value": true }, "machine_extruders_share_nozzle": { "default_value": true }, "machine_extruders_shared_nozzle_initial_retraction": { "default_value": 30 }, From 017a05fff7067a4f8740c482dc2dd6da1cc0ddc1 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sun, 2 Feb 2025 08:02:59 -0500 Subject: [PATCH 028/299] Update DisplayInfoOnLCD.py Changed the fialment type 'get' from: 'getProperty' to 'material.getMetaDataEntry' --- .../PostProcessingPlugin/scripts/DisplayInfoOnLCD.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 2177f91f3b..b19f222f2a 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -202,7 +202,7 @@ class DisplayInfoOnLCD(Script): "countdown_to_pause": { "label": "Countdown to Pauses", - "description": "This must run AFTER any script that adds a pause. Instead of the remaining print time the LCD will show the estimated time to the next layer that has a pause (TP).", + "description": "This must run AFTER any script that adds a pause. Instead of the remaining print time the LCD will show the estimated time to the next layer that has a pause (TP). Countdown to Pause is not available when in One-at-a-Time' mode.", "type": "bool", "default_value": false, "enabled": "display_option == 'display_progress' and enable_countdown and display_remaining_time" @@ -252,7 +252,8 @@ class DisplayInfoOnLCD(Script): else: data = self._display_progress(data) return data - # This is from the original 'Display Filename and Layer on LCD' + + # This is from the original 'Display Filename and Layer on LCD' def _display_filename_layer(self, data: str) -> str: data[0] = self._add_stats(data) max_layer = 0 @@ -385,7 +386,7 @@ class DisplayInfoOnLCD(Script): for q in range(0,len(pause_cmd)): if pause_cmd[q] in data[num]: pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) - pause_str = f"with {pause_count} pause(s)" + pause_str = f"with {pause_count} pause" + ("s" if pause_count > 1 else "") else: pause_str = "" # This line goes in to convert seconds to hours and minutes @@ -626,11 +627,11 @@ class DisplayInfoOnLCD(Script): extruder_count = global_stack.getProperty("machine_extruder_count", "value") init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) nozzle_size_line = ";Nozzle Size (T0): " + str(global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")) - filament_type = "\n;Filament Type (T0): " + str(global_stack.extruderList[0].getProperty("material_type", "value")) + filament_type = "\n;Filament Type (T0): " + str(global_stack.extruderList[0].material.getMetaDataEntry("material", "")) print_temperature_line = ";Print Temperature (T0): " + str(global_stack.extruderList[0].getProperty("material_print_temperature", "value")) if extruder_count > 1: nozzle_size_line += "\n;Nozzle Size (T1): " + str(global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")) - filament_type += "\n;Filament type (T1): " + str(global_stack.extruderList[1].getProperty("material_type", "value")) + filament_type += "\n;Filament type (T1): " + str(global_stack.extruderList[1].material.getMetaDataEntry("material", "")) print_temperature_line += "\n;Print Temperature (T1): " + str(global_stack.extruderList[1].getProperty("material_print_temperature", "value")) lines = data[0].split("\n") for index, line in enumerate(lines): From 850228498792684a4b282d40dedeea52bbafbc26 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 5 Feb 2025 10:33:51 +0100 Subject: [PATCH 029/299] Disable retract during travel for printers that handle retraction CURA-11978 --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 1323f93a73..cf43fde121 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -4300,7 +4300,7 @@ "default_value": 0, "minimum_value": 0, "maximum_value": 100, - "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", + "enabled": "retraction_enable and not machine_firmware_retract and machine_gcode_flavor != \"UltiGCode\" and machine_gcode_flavor != \"BFB\"", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -4313,7 +4313,7 @@ "default_value": 0, "minimum_value": 0, "maximum_value": 100, - "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", + "enabled": "retraction_enable and not machine_firmware_retract and machine_gcode_flavor != \"UltiGCode\" and machine_gcode_flavor != \"BFB\"", "settable_per_mesh": false, "settable_per_extruder": true }, From 87413f6b6da7570ddc557ff23735458b7a442cd9 Mon Sep 17 00:00:00 2001 From: Boris Juraga Date: Thu, 6 Feb 2025 23:28:06 +0100 Subject: [PATCH 030/299] adjust the start and end gcode --- resources/definitions/biqu_b2.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/biqu_b2.def.json b/resources/definitions/biqu_b2.def.json index 6fe0d9004f..3676ca8955 100644 --- a/resources/definitions/biqu_b2.def.json +++ b/resources/definitions/biqu_b2.def.json @@ -25,9 +25,9 @@ [33, 35] ] }, - "machine_end_gcode": { "default_value": ";BEGIN OF CUSTOM END GCODE\nM104 S0\nM140 S0\n;Retract the filament\nG91\nG1 E-30 F300\nG1 Z5\nG90\nG28 X0 Y0\n;END OF CUSTOM END GCODE" }, + "machine_end_gcode": { "default_value": ";BEGIN OF CUSTOM END GCODE\nM104 S0\nM140 S0\n;Retract the filament\nG91\nG1 E-30 F300\nG1 Z5\nG90\nG28 X0 Y{machine_depth}\n;END OF CUSTOM END GCODE" }, "machine_name": { "default_value": "BIQU B2" }, - "machine_start_gcode": { "default_value": ";BEGIN OF CUSTOM START GCODE\nG28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT1\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X6.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X6.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X6.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X6.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X6.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X6.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X7.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X7.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X7.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X7.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 \nT1\nG92 E0\nG1 F1200 E-30\nG92 E0\nT0\nG92 E0\nG1 F1200 E30\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X9.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X9.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X9.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X9.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X9.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X9.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X10.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X10.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X10.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X10.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nG92 E0\n;END OF CUSTOM START GCODE\nT{initial_extruder_nr} ; RESET EXTRUDER TO INITIAL\n; start print" }, + "machine_start_gcode": { "default_value": ";BEGIN OF CUSTOM START GCODE\nG28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT1\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X6.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X6.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X6.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X6.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X6.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X6.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X7.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X7.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X7.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X7.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 \nT1\nG92 E0\nG1 F1200 E-30\nG92 E0\nT0\nG92 E0\nG1 F1200 E30\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X9.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X9.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X9.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X9.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X9.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X9.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X10.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X10.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X10.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X10.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nG92 E0\nT{initial_extruder_nr} ; RESET EXTRUDER TO INITIAL\n; start print\n;END OF CUSTOM START GCODE" }, "machine_extruders_share_heater": { "default_value": true }, "machine_extruders_share_nozzle": { "default_value": true }, "machine_extruders_shared_nozzle_initial_retraction": { "default_value": 30 }, From d92196da5346cba0e36d46882599f20c57c8e15a Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 12 Feb 2025 17:22:27 +0100 Subject: [PATCH 031/299] Exclude plugins available in Marketplace from backups. part of CURA-12156 --- cura/API/Backups.py | 15 +++---- cura/Backups/Backup.py | 35 ++++++++++++--- cura/Backups/BackupsManager.py | 9 ++-- plugins/CuraDrive/src/CreateBackupJob.py | 54 +++++++++++++++++++----- 4 files changed, 87 insertions(+), 26 deletions(-) diff --git a/cura/API/Backups.py b/cura/API/Backups.py index 1940d38a36..07001d22e2 100644 --- a/cura/API/Backups.py +++ b/cura/API/Backups.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018 Ultimaker B.V. +# Copyright (c) 2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. from typing import Tuple, Optional, TYPE_CHECKING, Dict, Any @@ -9,14 +9,10 @@ if TYPE_CHECKING: class Backups: - """The back-ups API provides a version-proof bridge between Cura's - - BackupManager and plug-ins that hook into it. + """The back-ups API provides a version-proof bridge between Cura's BackupManager and plug-ins that hook into it. Usage: - .. code-block:: python - from cura.API import CuraAPI api = CuraAPI() api.backups.createBackup() @@ -26,13 +22,13 @@ class Backups: def __init__(self, application: "CuraApplication") -> None: self.manager = BackupsManager(application) - def createBackup(self) -> Tuple[Optional[bytes], Optional[Dict[str, Any]]]: + def createBackup(self, available_remote_plugins: frozenset[str] = frozenset()) -> Tuple[Optional[bytes], Optional[Dict[str, Any]]]: """Create a new back-up using the BackupsManager. :return: Tuple containing a ZIP file with the back-up data and a dict with metadata about the back-up. """ - return self.manager.createBackup() + return self.manager.createBackup(available_remote_plugins) def restoreBackup(self, zip_file: bytes, meta_data: Dict[str, Any]) -> None: """Restore a back-up using the BackupsManager. @@ -42,3 +38,6 @@ class Backups: """ return self.manager.restoreBackup(zip_file, meta_data) + + def shouldReinstallDownloadablePlugins(self) -> bool: + return self.manager.shouldReinstallDownloadablePlugins() diff --git a/cura/Backups/Backup.py b/cura/Backups/Backup.py index 19655df531..9f35e54ef1 100644 --- a/cura/Backups/Backup.py +++ b/cura/Backups/Backup.py @@ -1,5 +1,6 @@ -# Copyright (c) 2021 Ultimaker B.V. +# Copyright (c) 2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. +import json import io import os @@ -13,6 +14,7 @@ from UM import i18nCatalog from UM.Logger import Logger from UM.Message import Message from UM.Platform import Platform +from UM.PluginRegistry import PluginRegistry from UM.Resources import Resources from UM.Version import Version @@ -30,10 +32,14 @@ class Backup: """These files should be ignored when making a backup.""" IGNORED_FOLDERS = [] # type: List[str] + """These folders should be ignored when making a backup.""" SECRETS_SETTINGS = ["general/ultimaker_auth_data"] """Secret preferences that need to obfuscated when making a backup of Cura""" + TO_INSTALL_FILE = "packages.json" + """File that contains the 'to_install' dictionary, that manages plugins to be installed on next startup.""" + catalog = i18nCatalog("cura") """Re-use translation catalog""" @@ -42,7 +48,7 @@ class Backup: self.zip_file = zip_file # type: Optional[bytes] self.meta_data = meta_data # type: Optional[Dict[str, str]] - def makeFromCurrent(self) -> None: + def makeFromCurrent(self, available_remote_plugins: frozenset[str] = frozenset()) -> None: """Create a back-up from the current user config folder.""" cura_release = self._application.getVersion() @@ -92,21 +98,40 @@ class Backup: # Restore the obfuscated settings self._illuminate(**secrets) - def _makeArchive(self, buffer: "io.BytesIO", root_path: str) -> Optional[ZipFile]: + def _fillToInstallsJson(self, file_path: str, reinstall_on_restore: dict[str, str], archive: ZipFile) -> None: + pass # TODO! + + def _findRedownloadablePlugins(self, available_remote_plugins: frozenset) -> dict[str, str]: + """ Find all plugins that should be able to be reinstalled from the Marketplace. + + :param plugins_path: Path to all plugins in the user-space. + :return: Set of all package-id's of plugins that can be reinstalled from the Marketplace. + """ + plugin_reg = PluginRegistry.getInstance() + id = "id" + return {v["location"]: v[id] for v in plugin_reg.getAllMetaData() + if v[id] in available_remote_plugins and not plugin_reg.isBundledPlugin(v[id])} + + def _makeArchive(self, buffer: "io.BytesIO", root_path: str, available_remote_plugins: frozenset) -> Optional[ZipFile]: """Make a full archive from the given root path with the given name. :param root_path: The root directory to archive recursively. :return: The archive as bytes. """ ignore_string = re.compile("|".join(self.IGNORED_FILES + self.IGNORED_FOLDERS)) + reinstall_instead_plugins = self._findRedownloadablePlugins(available_remote_plugins) try: archive = ZipFile(buffer, "w", ZIP_DEFLATED) - for root, folders, files in os.walk(root_path): + for root, folders, files in os.walk(root_path, topdown=True): + folders[:] = [f for f in folders if f not in reinstall_instead_plugins] for item_name in folders + files: absolute_path = os.path.join(root, item_name) if ignore_string.search(absolute_path): continue - archive.write(absolute_path, absolute_path[len(root_path) + len(os.sep):]) + if item_name == self.TO_INSTALL_FILE: + self._fillToInstallsJson(absolute_path, reinstall_instead_plugins, archive) + else: + archive.write(absolute_path, absolute_path[len(root_path) + len(os.sep):]) archive.close() return archive except (IOError, OSError, BadZipfile) as error: diff --git a/cura/Backups/BackupsManager.py b/cura/Backups/BackupsManager.py index 6c4670edb6..90dfc5e34e 100644 --- a/cura/Backups/BackupsManager.py +++ b/cura/Backups/BackupsManager.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018 Ultimaker B.V. +# Copyright (c) 2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. from typing import Dict, Optional, Tuple, TYPE_CHECKING @@ -22,7 +22,10 @@ class BackupsManager: def __init__(self, application: "CuraApplication") -> None: self._application = application - def createBackup(self) -> Tuple[Optional[bytes], Optional[Dict[str, str]]]: + def shouldReinstallDownloadablePlugins(self) -> bool: + return True + + def createBackup(self, available_remote_plugins: frozenset[str] = frozenset()) -> Tuple[Optional[bytes], Optional[Dict[str, str]]]: """ Get a back-up of the current configuration. @@ -31,7 +34,7 @@ class BackupsManager: self._disableAutoSave() backup = Backup(self._application) - backup.makeFromCurrent() + backup.makeFromCurrent(available_remote_plugins if self.shouldReinstallDownloadablePlugins() else frozenset()) self._enableAutoSave() # We don't return a Backup here because we want plugins only to interact with our API and not full objects. return backup.zip_file, backup.meta_data diff --git a/plugins/CuraDrive/src/CreateBackupJob.py b/plugins/CuraDrive/src/CreateBackupJob.py index 7d772769ed..cdd1d569c7 100644 --- a/plugins/CuraDrive/src/CreateBackupJob.py +++ b/plugins/CuraDrive/src/CreateBackupJob.py @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Ultimaker B.V. +# Copyright (c) 2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. import json import threading @@ -13,11 +13,14 @@ from UM.Message import Message from UM.TaskManagement.HttpRequestManager import HttpRequestManager from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from UM.i18n import i18nCatalog +from cura.ApplicationMetadata import CuraSDKVersion from cura.CuraApplication import CuraApplication from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope +import cura.UltimakerCloud.UltimakerCloudConstants as UltimakerCloudConstants catalog = i18nCatalog("cura") +PACKAGES_URL = f"{UltimakerCloudConstants.CuraCloudAPIRoot}/cura-packages/v{UltimakerCloudConstants.CuraCloudAPIVersion}/cura/v{CuraSDKVersion}/packages" class CreateBackupJob(Job): """Creates backup zip, requests upload url and uploads the backup file to cloud storage.""" @@ -40,23 +43,54 @@ class CreateBackupJob(Job): self._job_done = threading.Event() """Set when the job completes. Does not indicate success.""" self.backup_upload_error_message = "" - """After the job completes, an empty string indicates success. Othrerwise, the value is a translated message.""" + """After the job completes, an empty string indicates success. Otherwise, the value is a translated message.""" + + def _setPluginFetchErrorMessage(self, error_msg: str) -> None: + Logger.error(f"Fetching plugins for backup resulted in error: {error_msg}") + self.backup_upload_error_message = "Couldn't update currently available plugins, backup stopped." + self._upload_message.hide() + self._job_done.set() def run(self) -> None: - upload_message = Message(catalog.i18nc("@info:backup_status", "Creating your backup..."), + self._upload_message = Message(catalog.i18nc("@info:backup_status", "Fetch re-downloadable package-ids..."), title = self.MESSAGE_TITLE, progress = -1) - upload_message.show() + self._upload_message.show() + CuraApplication.getInstance().processEvents() + + if CuraApplication.getInstance().getCuraAPI().backups.shouldReinstallDownloadablePlugins(): + request_url = f"{PACKAGES_URL}?package_type=plugin" + scope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) + HttpRequestManager.getInstance().get( + request_url, + scope=scope, + callback=self._continueRun, + error_callback=lambda reply, error: self._setPluginFetchErrorMessage(str(error)), + ) + else: + self._continueRun() + + def _continueRun(self, reply: "QNetworkReply" = None) -> None: + if reply is not None: + response_data = HttpRequestManager.readJSON(reply) + if "data" not in response_data: + self._setPluginFetchErrorMessage(f"Missing 'data' from response. Keys in response: {response_data.keys()}") + return + available_remote_plugins = frozenset({v["package_id"] for v in response_data["data"]}) + else: + available_remote_plugins = frozenset() + + self._upload_message.setText(catalog.i18nc("@info:backup_status", "Creating your backup...")) CuraApplication.getInstance().processEvents() cura_api = CuraApplication.getInstance().getCuraAPI() - self._backup_zip, backup_meta_data = cura_api.backups.createBackup() + self._backup_zip, backup_meta_data = cura_api.backups.createBackup(available_remote_plugins) if not self._backup_zip or not backup_meta_data: self.backup_upload_error_message = catalog.i18nc("@info:backup_status", "There was an error while creating your backup.") - upload_message.hide() + self._upload_message.hide() return - upload_message.setText(catalog.i18nc("@info:backup_status", "Uploading your backup...")) + self._upload_message.setText(catalog.i18nc("@info:backup_status", "Uploading your backup...")) CuraApplication.getInstance().processEvents() # Create an upload entry for the backup. @@ -66,11 +100,11 @@ class CreateBackupJob(Job): self._job_done.wait() if self.backup_upload_error_message == "": - upload_message.setText(catalog.i18nc("@info:backup_status", "Your backup has finished uploading.")) - upload_message.setProgress(None) # Hide progress bar + self._upload_message.setText(catalog.i18nc("@info:backup_status", "Your backup has finished uploading.")) + self._upload_message.setProgress(None) # Hide progress bar else: # some error occurred. This error is presented to the user by DrivePluginExtension - upload_message.hide() + self._upload_message.hide() def _requestUploadSlot(self, backup_metadata: Dict[str, Any], backup_size: int) -> None: """Request a backup upload slot from the API. From 3adf94cffb0450bc83ddf9aee4853153651c5910 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Fri, 14 Feb 2025 10:59:38 +0100 Subject: [PATCH 032/299] move settings to experimental category --- resources/definitions/fdmprinter.def.json | 52 +++++++++++------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index cf43fde121..48342b2eb1 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -4291,32 +4291,6 @@ "settable_per_mesh": false, "settable_per_extruder": true }, - "retraction_during_travel_ratio": - { - "label": "Retraction During Travel Move", - "description": "The ratio of retraction performed during the travel move, with the remainder completed while the nozzle is stationary, before traveling
  • When 0, the entire retraction is performed while stationary, before the travel begins
  • When 100, the entire retraction is performed during the travel move, bypassing the stationary phase
", - "unit": "%", - "type": "float", - "default_value": 0, - "minimum_value": 0, - "maximum_value": 100, - "enabled": "retraction_enable and not machine_firmware_retract and machine_gcode_flavor != \"UltiGCode\" and machine_gcode_flavor != \"BFB\"", - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "prime_during_travel_ratio": - { - "label": "Prime During Travel Move", - "description": "The ratio of priming performed during the travel move, with the remainder completed while the nozzle is stationary, after traveling
  • When 0, the entire priming is performed while stationary, after the travel ends
  • When 100, the entire priming is performed during the travel move, allowing the print to start immediately
", - "unit": "%", - "type": "float", - "default_value": 0, - "minimum_value": 0, - "maximum_value": 100, - "enabled": "retraction_enable and not machine_firmware_retract and machine_gcode_flavor != \"UltiGCode\" and machine_gcode_flavor != \"BFB\"", - "settable_per_mesh": false, - "settable_per_extruder": true - }, "retraction_speed": { "label": "Retraction Speed", @@ -9015,6 +8989,32 @@ "default_value": true, "settable_per_mesh": true }, + "retraction_during_travel_ratio": + { + "label": "Retraction During Travel Move", + "description": "The ratio of retraction performed during the travel move, with the remainder completed while the nozzle is stationary, before traveling
  • When 0, the entire retraction is performed while stationary, before the travel begins
  • When 100, the entire retraction is performed during the travel move, bypassing the stationary phase
", + "unit": "%", + "type": "float", + "default_value": 0, + "minimum_value": 0, + "maximum_value": 100, + "enabled": "retraction_enable and not machine_firmware_retract and machine_gcode_flavor != \"UltiGCode\" and machine_gcode_flavor != \"BFB\"", + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "prime_during_travel_ratio": + { + "label": "Prime During Travel Move", + "description": "The ratio of priming performed during the travel move, with the remainder completed while the nozzle is stationary, after traveling
  • When 0, the entire priming is performed while stationary, after the travel ends
  • When 100, the entire priming is performed during the travel move, allowing the print to start immediately
", + "unit": "%", + "type": "float", + "default_value": 0, + "minimum_value": 0, + "maximum_value": 100, + "enabled": "retraction_enable and not machine_firmware_retract and machine_gcode_flavor != \"UltiGCode\" and machine_gcode_flavor != \"BFB\"", + "settable_per_mesh": false, + "settable_per_extruder": true + }, "scarf_joint_seam_length": { "label": "Scarf Seam Length", From 78ba8d834d17888ba3447fb845d0e01eba702a1c Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 24 Feb 2025 09:20:56 +0100 Subject: [PATCH 033/299] Set proper version for nightly stable build --- .github/workflows/nightly-stable.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly-stable.yml b/.github/workflows/nightly-stable.yml index e166027dd8..1535daa415 100644 --- a/.github/workflows/nightly-stable.yml +++ b/.github/workflows/nightly-stable.yml @@ -10,7 +10,7 @@ jobs: build-nightly: uses: ./.github/workflows/nightly.yml with: - cura_conan_version: "cura/[*]@ultimaker/stable" + cura_conan_version: "cura/[*]" release_tag: "nightly-stable" caller_workflow: "nightly-stable.yml" secrets: inherit From 0f8fe06059cf6bc5eb03a88b1d7aec0a82d84fdb Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 26 Feb 2025 16:11:21 +0100 Subject: [PATCH 034/299] Bump version to 5.11 --- conandata.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/conandata.yml b/conandata.yml index 9ad6f889b5..abca7197d3 100644 --- a/conandata.yml +++ b/conandata.yml @@ -1,15 +1,15 @@ -version: "5.10.0-beta.1" +version: "5.11.0-alpha.0" requirements: - - "cura_resources/5.10.0-beta.1" - - "uranium/5.10.0-beta.1" - - "curaengine/5.10.0-beta.1" - - "cura_binary_data/5.10.0-beta.1" - - "fdm_materials/5.10.0-beta.1" + - "cura_resources/5.11.0-alpha.0" + - "uranium/5.11.0-alpha.0" + - "curaengine/5.11.0-alpha.0" + - "cura_binary_data/5.11.0-alpha.0" + - "fdm_materials/5.11.0-alpha.0" - "dulcificum/5.10.0" - "pysavitar/5.10.0" - "pynest2d/5.10.0" requirements_internal: - - "fdm_materials/5.10.0-beta.1" + - "fdm_materials/5.11.0-alpha.0" - "cura_private_data/5.10.0-alpha.0@internal/testing" requirements_enterprise: - "native_cad_plugin/2.0.0" From f468cd5150440c007aeebbc163bf569f055bb4c0 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 26 Feb 2025 16:25:04 +0100 Subject: [PATCH 035/299] Bump version to 5.11 --- resources/conandata.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/conandata.yml b/resources/conandata.yml index 8236ba70b5..0644c1a42e 100644 --- a/resources/conandata.yml +++ b/resources/conandata.yml @@ -1 +1 @@ -version: "5.10.0-beta.1" +version: "5.11.0-alpha.0" From b67769b2383d186abd4622e62f88eca411c09b4b Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 26 Feb 2025 16:29:16 +0100 Subject: [PATCH 036/299] Fix dependency version --- conandata.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/conandata.yml b/conandata.yml index abca7197d3..e93a6d6cac 100644 --- a/conandata.yml +++ b/conandata.yml @@ -1,15 +1,15 @@ version: "5.11.0-alpha.0" requirements: - - "cura_resources/5.11.0-alpha.0" - - "uranium/5.11.0-alpha.0" - - "curaengine/5.11.0-alpha.0" - - "cura_binary_data/5.11.0-alpha.0" - - "fdm_materials/5.11.0-alpha.0" + - "cura_resources/5.11.0-alpha.0@ultimaker/testing" + - "uranium/5.11.0-alpha.0@ultimaker/testing" + - "curaengine/5.11.0-alpha.0@ultimaker/testing" + - "cura_binary_data/5.11.0-alpha.0@ultimaker/testing" + - "fdm_materials/5.11.0-alpha.0@ultimaker/testing" - "dulcificum/5.10.0" - "pysavitar/5.10.0" - "pynest2d/5.10.0" requirements_internal: - - "fdm_materials/5.11.0-alpha.0" + - "fdm_materials/5.11.0-alpha.0@ultimaker/testing" - "cura_private_data/5.10.0-alpha.0@internal/testing" requirements_enterprise: - "native_cad_plugin/2.0.0" From d167e3f28ed8843786414faa5a0331a5d3ee33fa Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 27 Feb 2025 16:52:27 +0100 Subject: [PATCH 037/299] Work in progress on pulling plugins out of the backups. It's now in a state where it can actually upload ... something (that should work). Not tested the restore yet. I did run into trouble with the max concurrent requests, which I had to up to [more than 4, now on 8] to get it to work -- I'm not sure if I'm just working around a bug here, or if that's expected behaviour. part of CURA-12156 --- cura/API/Backups.py | 4 +- cura/Backups/Backup.py | 67 ++++++++++++------ cura/Backups/BackupsManager.py | 5 +- plugins/CuraDrive/src/CreateBackupJob.py | 4 ++ plugins/CuraDrive/src/RestoreBackupJob.py | 82 +++++++++++++++++++++-- 5 files changed, 132 insertions(+), 30 deletions(-) diff --git a/cura/API/Backups.py b/cura/API/Backups.py index 07001d22e2..a52dcbfb6b 100644 --- a/cura/API/Backups.py +++ b/cura/API/Backups.py @@ -30,14 +30,14 @@ class Backups: return self.manager.createBackup(available_remote_plugins) - def restoreBackup(self, zip_file: bytes, meta_data: Dict[str, Any]) -> None: + def restoreBackup(self, zip_file: bytes, meta_data: Dict[str, Any], auto_close: bool = True) -> None: """Restore a back-up using the BackupsManager. :param zip_file: A ZIP file containing the actual back-up data. :param meta_data: Some metadata needed for restoring a back-up, like the Cura version number. """ - return self.manager.restoreBackup(zip_file, meta_data) + return self.manager.restoreBackup(zip_file, meta_data, auto_close=auto_close) def shouldReinstallDownloadablePlugins(self) -> bool: return self.manager.shouldReinstallDownloadablePlugins() diff --git a/cura/Backups/Backup.py b/cura/Backups/Backup.py index 9f35e54ef1..1163169b94 100644 --- a/cura/Backups/Backup.py +++ b/cura/Backups/Backup.py @@ -1,5 +1,7 @@ # Copyright (c) 2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. +import tempfile + import json import io @@ -8,7 +10,7 @@ import re import shutil from copy import deepcopy from zipfile import ZipFile, ZIP_DEFLATED, BadZipfile -from typing import Dict, Optional, TYPE_CHECKING, List +from typing import Callable, Dict, Optional, TYPE_CHECKING, List from UM import i18nCatalog from UM.Logger import Logger @@ -37,9 +39,6 @@ class Backup: SECRETS_SETTINGS = ["general/ultimaker_auth_data"] """Secret preferences that need to obfuscated when making a backup of Cura""" - TO_INSTALL_FILE = "packages.json" - """File that contains the 'to_install' dictionary, that manages plugins to be installed on next startup.""" - catalog = i18nCatalog("cura") """Re-use translation catalog""" @@ -74,7 +73,7 @@ class Backup: # Create an empty buffer and write the archive to it. buffer = io.BytesIO() - archive = self._makeArchive(buffer, version_data_dir) + archive = self._makeArchive(buffer, version_data_dir, available_remote_plugins) if archive is None: return files = archive.namelist() @@ -83,9 +82,7 @@ class Backup: machine_count = max(len([s for s in files if "machine_instances/" in s]) - 1, 0) # If people delete their profiles but not their preferences, it can still make a backup, and report -1 profiles. Server crashes on this. material_count = max(len([s for s in files if "materials/" in s]) - 1, 0) profile_count = max(len([s for s in files if "quality_changes/" in s]) - 1, 0) - # We don't store plugins anymore, since if you can make backups, you have an account (and the plugins are - # on the marketplace anyway) - plugin_count = 0 + plugin_count = len([s for s in files if "plugin.json" in s]) # Store the archive and metadata so the BackupManager can fetch them when needed. self.zip_file = buffer.getvalue() self.meta_data = { @@ -98,19 +95,43 @@ class Backup: # Restore the obfuscated settings self._illuminate(**secrets) - def _fillToInstallsJson(self, file_path: str, reinstall_on_restore: dict[str, str], archive: ZipFile) -> None: - pass # TODO! + def _fillToInstallsJson(self, file_path: str, reinstall_on_restore: frozenset[str], add_to_archive: Callable[[str], None]) -> Optional[str]: + """ Moves all plugin-data (in a config-file) for plugins that could be (re)installed from the Marketplace from + 'installed' to 'to_installs' before adding that file to the archive. - def _findRedownloadablePlugins(self, available_remote_plugins: frozenset) -> dict[str, str]: + Note that the 'filename'-entry in the package-data (of the plugins) might not be valid anymore on restore. + We'll replace it on restore instead, as that's the time when the new package is downloaded. + + :param file_path: Absolute path to the packages-file. + :param reinstall_on_restore: A set of plugins that _can_ be reinstalled from the Marketplace. + :param add_to_archive: A function/lambda that takes a filename and adds it to the archive. + """ + with open(file_path, "r") as file: + data = json.load(file) + reinstall, keep_in = {}, {} + for install_id, install_info in data["installed"].items(): + (reinstall if install_id in reinstall_on_restore else keep_in)[install_id] = install_info + data["installed"] = keep_in + data["to_install"].update(reinstall) + if data is not None: + tmpfile = tempfile.NamedTemporaryFile(delete=False) + with open(tmpfile.name, "w") as outfile: + json.dump(data, outfile) + add_to_archive(tmpfile.name) + return tmpfile.name + return None + + def _findRedownloadablePlugins(self, available_remote_plugins: frozenset) -> (frozenset[str], frozenset[str]): """ Find all plugins that should be able to be reinstalled from the Marketplace. :param plugins_path: Path to all plugins in the user-space. - :return: Set of all package-id's of plugins that can be reinstalled from the Marketplace. + :return: Tuple of a set of plugin-ids and a set of plugin-paths. """ plugin_reg = PluginRegistry.getInstance() id = "id" - return {v["location"]: v[id] for v in plugin_reg.getAllMetaData() - if v[id] in available_remote_plugins and not plugin_reg.isBundledPlugin(v[id])} + plugins = [v for v in plugin_reg.getAllMetaData() + if v[id] in available_remote_plugins and not plugin_reg.isBundledPlugin(v[id])] + return frozenset([v[id] for v in plugins]), frozenset([v["location"] for v in plugins]) def _makeArchive(self, buffer: "io.BytesIO", root_path: str, available_remote_plugins: frozenset) -> Optional[ZipFile]: """Make a full archive from the given root path with the given name. @@ -119,20 +140,28 @@ class Backup: :return: The archive as bytes. """ ignore_string = re.compile("|".join(self.IGNORED_FILES + self.IGNORED_FOLDERS)) - reinstall_instead_plugins = self._findRedownloadablePlugins(available_remote_plugins) + reinstall_instead_ids, reinstall_instead_paths = self._findRedownloadablePlugins(available_remote_plugins) + tmpfiles = [] try: archive = ZipFile(buffer, "w", ZIP_DEFLATED) + add_path_to_archive = lambda path: archive.write(path, path[len(root_path) + len(os.sep):]) for root, folders, files in os.walk(root_path, topdown=True): - folders[:] = [f for f in folders if f not in reinstall_instead_plugins] + folders[:] = [f for f in folders if f not in reinstall_instead_paths] for item_name in folders + files: absolute_path = os.path.join(root, item_name) if ignore_string.search(absolute_path): continue - if item_name == self.TO_INSTALL_FILE: - self._fillToInstallsJson(absolute_path, reinstall_instead_plugins, archive) + if item_name == "packages.json": + tmpfiles.append( + self._fillToInstallsJson(absolute_path, reinstall_instead_ids, add_path_to_archive)) else: - archive.write(absolute_path, absolute_path[len(root_path) + len(os.sep):]) + add_path_to_archive(absolute_path) archive.close() + for tmpfile_path in tmpfiles: + try: + os.remove(tmpfile_path) + except IOError as ex: + Logger.warning(f"Couldn't remove temporary file '{tmpfile_path}' because '{ex}'.") return archive except (IOError, OSError, BadZipfile) as error: Logger.log("e", "Could not create archive from user data directory: %s", error) diff --git a/cura/Backups/BackupsManager.py b/cura/Backups/BackupsManager.py index 90dfc5e34e..67d6c84601 100644 --- a/cura/Backups/BackupsManager.py +++ b/cura/Backups/BackupsManager.py @@ -39,12 +39,13 @@ class BackupsManager: # We don't return a Backup here because we want plugins only to interact with our API and not full objects. return backup.zip_file, backup.meta_data - def restoreBackup(self, zip_file: bytes, meta_data: Dict[str, str]) -> None: + def restoreBackup(self, zip_file: bytes, meta_data: Dict[str, str], auto_close: bool = True) -> None: """ Restore a back-up from a given ZipFile. :param zip_file: A bytes object containing the actual back-up. :param meta_data: A dict containing some metadata that is needed to restore the back-up correctly. + :param auto_close: Normally, Cura will need to close immediately after restoring the back-up. """ if not meta_data.get("cura_release", None): @@ -57,7 +58,7 @@ class BackupsManager: backup = Backup(self._application, zip_file = zip_file, meta_data = meta_data) restored = backup.restore() - if restored: + if restored and auto_close: # At this point, Cura will need to restart for the changes to take effect. # We don't want to store the data at this point as that would override the just-restored backup. self._application.windowClosed(save_data = False) diff --git a/plugins/CuraDrive/src/CreateBackupJob.py b/plugins/CuraDrive/src/CreateBackupJob.py index cdd1d569c7..6297af305f 100644 --- a/plugins/CuraDrive/src/CreateBackupJob.py +++ b/plugins/CuraDrive/src/CreateBackupJob.py @@ -118,6 +118,8 @@ class CreateBackupJob(Job): } }).encode() + CuraApplication.getInstance().processEvents() # Needed?? + HttpRequestManager.getInstance().put( self._api_backup_url, data = payload, @@ -125,6 +127,8 @@ class CreateBackupJob(Job): error_callback = self._onUploadSlotCompleted, scope = self._json_cloud_scope) + CuraApplication.getInstance().processEvents() # Needed?? + def _onUploadSlotCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None) -> None: if HttpRequestManager.safeHttpStatus(reply) >= 300: replyText = HttpRequestManager.readText(reply) diff --git a/plugins/CuraDrive/src/RestoreBackupJob.py b/plugins/CuraDrive/src/RestoreBackupJob.py index 54c94b389e..c5fd1fceae 100644 --- a/plugins/CuraDrive/src/RestoreBackupJob.py +++ b/plugins/CuraDrive/src/RestoreBackupJob.py @@ -1,8 +1,12 @@ # Copyright (c) 2021 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +import tempfile + +import json import base64 import hashlib +import os import threading from tempfile import NamedTemporaryFile from typing import Optional, Any, Dict @@ -12,9 +16,16 @@ from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest from UM.Job import Job from UM.Logger import Logger from UM.PackageManager import catalog +from UM.Resources import Resources from UM.TaskManagement.HttpRequestManager import HttpRequestManager -from cura.CuraApplication import CuraApplication +from UM.Version import Version +from cura.ApplicationMetadata import CuraSDKVersion +from cura.CuraApplication import CuraApplication +from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope +import cura.UltimakerCloud.UltimakerCloudConstants as UltimakerCloudConstants + +PACKAGES_URL = f"{UltimakerCloudConstants.CuraCloudAPIRoot}/cura-packages/v{UltimakerCloudConstants.CuraCloudAPIVersion}/cura/v{CuraSDKVersion}/packages" class RestoreBackupJob(Job): """Downloads a backup and overwrites local configuration with the backup. @@ -60,8 +71,8 @@ class RestoreBackupJob(Job): # We store the file in a temporary path fist to ensure integrity. try: - temporary_backup_file = NamedTemporaryFile(delete = False) - with open(temporary_backup_file.name, "wb") as write_backup: + self._temporary_backup_file = NamedTemporaryFile(delete = False) + with open(self._temporary_backup_file.name, "wb") as write_backup: app = CuraApplication.getInstance() bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE) while bytes_read: @@ -74,18 +85,75 @@ class RestoreBackupJob(Job): self._job_done.set() return - if not self._verifyMd5Hash(temporary_backup_file.name, self._backup.get("md5_hash", "")): + if not self._verifyMd5Hash(self._temporary_backup_file.name, self._backup.get("md5_hash", "")): # Don't restore the backup if the MD5 hashes do not match. # This can happen if the download was interrupted. Logger.log("w", "Remote and local MD5 hashes do not match, not restoring backup.") self.restore_backup_error_message = self.DEFAULT_ERROR_MESSAGE # Tell Cura to place the backup back in the user data folder. - with open(temporary_backup_file.name, "rb") as read_backup: + metadata = self._backup.get("metadata", {}) + with open(self._temporary_backup_file.name, "rb") as read_backup: cura_api = CuraApplication.getInstance().getCuraAPI() - cura_api.backups.restoreBackup(read_backup.read(), self._backup.get("metadata", {})) + cura_api.backups.restoreBackup(read_backup.read(), metadata, auto_close=False) - self._job_done.set() + # Read packages data-file, to get the 'to_install' plugin-ids. + version_to_restore = Version(metadata.get("cura_release", "dev")) + version_str = f"{version_to_restore.getMajor()}.{version_to_restore.getMinor()}" + packages_path = os.path.abspath(os.path.join(os.path.abspath( + Resources.getConfigStoragePath()), "..", version_str, "packages.json")) + if not os.path.exists(packages_path): + self._job_done.set() + return + + to_install = set() + try: + with open(packages_path, "r") as packages_file: + packages_json = json.load(packages_file) + if "to_install" in packages_json and "package_id" in packages_json["to_install"]: + to_install.add(packages_json["to_install"]["package_id"]) + except IOError as ex: + pass # TODO! (log + message) + + if len(to_install) < 1: + self._job_done.set() + return + + # Download all re-installable plugins packages, so they can be put back on start-up. + redownload_errors = [] + def packageDownloadCallback(package_id: str, msg: "QNetworkReply", err: "QNetworkReply.NetworkError" = None) -> None: + if err is not None or HttpRequestManager.safeHttpStatus(msg) != 200: + redownload_errors.append(err) + to_install.remove(package_id) + + try: + with tempfile.NamedTemporaryFile(mode="wb+", suffix=".curapackage") as temp_file: + bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE) + while bytes_read: + temp_file.write(bytes_read) + bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE) + # self._app.processEvents() + # self._progress[package_id]["file_written"] = temp_file.name + if not CuraApplication.getInstance().getPackageManager().installPackage(temp_file.name): + redownload_errors.append(f"Couldn't install package '{package_id}'.") + except IOError as ex: + redownload_errors.append(f"Couldn't read package '{package_id}' because '{ex}'.") + + if len(to_install) < 1: + if len(redownload_errors) == 0: + self._job_done.set() + else: + print("|".join(redownload_errors)) # TODO: Message / Log instead. + self._job_done.set() # NOTE: Set job probably not the right call here... (depends on wether or not that in the end closes the app or not...) + + self._package_download_scope = UltimakerCloudScope(CuraApplication.getInstance()) + for package_id in to_install: + HttpRequestManager.getInstance().get( + f"{PACKAGES_URL}/{package_id}/download", + scope=self._package_download_scope, + callback=lambda msg: packageDownloadCallback(package_id, msg), + error_callback=lambda msg, err: packageDownloadCallback(package_id, msg, err) + ) @staticmethod def _verifyMd5Hash(file_path: str, known_hash: str) -> bool: From e39f5ca7ae11603c81a560b09c263cff2b90e513 Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Wed, 5 Mar 2025 12:31:29 +0000 Subject: [PATCH 038/299] Trigger Curator build after resource build --- .github/workflows/conan-package-resources.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/conan-package-resources.yml b/.github/workflows/conan-package-resources.yml index 7394a81ab7..cb1ebefd64 100644 --- a/.github/workflows/conan-package-resources.yml +++ b/.github/workflows/conan-package-resources.yml @@ -30,3 +30,13 @@ jobs: platform_mac: false install_system_dependencies: false secrets: inherit + + signal-curator: + needs: conan-package + runs-on: ubuntu-latest + steps: + - name: Trigger Curator Workflow + run: | + gh workflow run --repo ultimaker/curator -r main package.yml + env: + GITHUB_TOKEN: ${{ secrets.CURATOR_TRIGGER_PAT_C3PO }} From 06cbb2c65cfb47f0a0126d0f201cdecefb3c7273 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Thu, 13 Mar 2025 20:40:59 -0400 Subject: [PATCH 039/299] Update FilamentChange.py Hide the "Z-Move" when in "use firmware configuration" mode. --- plugins/PostProcessingPlugin/scripts/FilamentChange.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/FilamentChange.py b/plugins/PostProcessingPlugin/scripts/FilamentChange.py index 6fe28ef2f2..f51ba73ffb 100644 --- a/plugins/PostProcessingPlugin/scripts/FilamentChange.py +++ b/plugins/PostProcessingPlugin/scripts/FilamentChange.py @@ -92,7 +92,7 @@ class FilamentChange(Script): "type": "float", "default_value": 0, "minimum_value": 0, - "enabled": "enabled" + "enabled": "enabled and not firmware_config" }, "retract_method": { From ce4c18a60c174013efc556201f74a2aa47d7d23d Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 19 Mar 2025 11:40:21 +0100 Subject: [PATCH 040/299] This name wasn't the same as in the complete settings list. Even worse, support type there already means something else. Done in main for supposedly 5.11 instead of 5.10 since the translations might not work since they have a different context/label here. resolution of CURA-12485 --- .../Recommended/RecommendedSupportSelector.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml b/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml index c1b36676c7..48a164819d 100644 --- a/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml +++ b/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml @@ -46,7 +46,7 @@ RecommendedSettingSection contents: [ RecommendedSettingItem { - settingName: catalog.i18nc("@action:label", "Support Type") + settingName: catalog.i18nc("@action:label", "Support Structure") tooltipText: catalog.i18nc("@label", "Chooses between the techniques available to generate support. \n\n\"Normal\" support creates a support structure directly below the overhanging parts and drops those areas straight down. \n\n\"Tree\" support creates branches towards the overhanging areas that support the model on the tips of those branches, and allows the branches to crawl around the model to support it from the build plate as much as possible.") isCompressed: enableSupportRow.isCompressed From a9018a06c4233132ce717bfbbecbce6141f8ec4e Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 19 Mar 2025 15:39:00 +0100 Subject: [PATCH 041/299] Have developer/tester/etc. builds be distinct per biweekly day. Less cause for confusion when sending out internal builds to test/develop on. CURA-12469 --- conanfile.py | 24 ++++++++++++++++++++++++ resources/themes/daily_test_colors.json | 16 ++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 resources/themes/daily_test_colors.json diff --git a/conanfile.py b/conanfile.py index b3e070e3b3..c727a6d293 100644 --- a/conanfile.py +++ b/conanfile.py @@ -1,8 +1,10 @@ +import json import os import requests import yaml import tempfile import tarfile +from datetime import datetime from io import StringIO from pathlib import Path from git import Repo @@ -562,6 +564,25 @@ class CuraConan(ConanFile): self.cpp.package.bindirs = ["bin"] self.cpp.package.resdirs = ["resources", "plugins", "packaging"] + def _make_internal_distinct(self): + test_colors_path = Path(self.source_folder, "resources", "themes", "daily_test_colors.json") + if self.options.internal: + biweekly_day = (datetime.now() - datetime(2025, 3, 14)).days + with test_colors_path.open("r") as test_colors_file: + test_colors = json.load(test_colors_file) + for theme_dir in Path(self.source_folder, "resources", "themes").iterdir(): + if theme_dir.is_dir(): + theme_path = Path(theme_dir, "theme.json") + if theme_path.exists(): + with theme_path.open("r") as theme_file: + theme = json.load(theme_file) + if theme["colors"]: + theme["colors"]["main_window_header_background"] = test_colors[biweekly_day] + with theme_path.open("w") as theme_file: + json.dump(theme, theme_file) + elif test_colors_path.exists(): + test_colors_path.unlink() + def generate(self): copy(self, "cura_app.py", self.source_folder, str(self._script_dir)) @@ -581,6 +602,9 @@ class CuraConan(ConanFile): copy(self, "bundled_*.json", native_cad_plugin.resdirs[1], str(Path(self.source_folder, "resources", "bundled_packages")), keep_path = False) + # Make internal versions built on different days distinct, so people don't get confused while testing. + self._make_internal_distinct() + # Copy resources of cura_binary_data cura_binary_data = self.dependencies["cura_binary_data"].cpp_info copy(self, "*", cura_binary_data.resdirs[0], str(self._share_dir.joinpath("cura")), keep_path = True) diff --git a/resources/themes/daily_test_colors.json b/resources/themes/daily_test_colors.json new file mode 100644 index 0000000000..1cfa2baa74 --- /dev/null +++ b/resources/themes/daily_test_colors.json @@ -0,0 +1,16 @@ +[ + [ 62, 33, 55, 255], + [126, 196, 193, 255], + [126, 196, 193, 255], + [215, 155, 125, 255], + [228, 148, 58, 255], + [192, 199, 65, 255], + [157, 48, 59, 255], + [140, 143, 174, 255], + [ 23, 67, 75, 255], + [ 23, 67, 75, 255], + [154, 99, 72, 255], + [112, 55, 127, 255], + [100, 125, 52, 255], + [210, 100, 113, 255] +] From bc4d57348cc223f115e384aa0a72baa0a585ed97 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 19 Mar 2025 16:27:31 +0100 Subject: [PATCH 042/299] Version has been bumped a while ago. Needed to test CURA-12469 (and I suppose it doesn't hurt for anything else that needs the internal data). --- conandata.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conandata.yml b/conandata.yml index 50d27455a2..20392c6e44 100644 --- a/conandata.yml +++ b/conandata.yml @@ -10,7 +10,7 @@ requirements: - "pynest2d/5.10.0" requirements_internal: - "fdm_materials/5.11.0-alpha.0@ultimaker/testing" - - "cura_private_data/5.10.0-alpha.0@internal/testing" + - "cura_private_data/5.11.0-alpha.0@internal/testing" requirements_enterprise: - "native_cad_plugin/2.0.0" urls: From 2b032af13c3ed1e43baa9c706fd0c3581b544c6c Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 19 Mar 2025 16:39:37 +0100 Subject: [PATCH 043/299] Broaden the 'internal' condition a bit. Should help with testing as well. CURA-12469 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index c727a6d293..994dfb63a4 100644 --- a/conanfile.py +++ b/conanfile.py @@ -566,7 +566,7 @@ class CuraConan(ConanFile): def _make_internal_distinct(self): test_colors_path = Path(self.source_folder, "resources", "themes", "daily_test_colors.json") - if self.options.internal: + if "alpha" in self.version: biweekly_day = (datetime.now() - datetime(2025, 3, 14)).days with test_colors_path.open("r") as test_colors_file: test_colors = json.load(test_colors_file) From 82939b2644e598dab75970c9831b78233c444cb5 Mon Sep 17 00:00:00 2001 From: RedBlackAka <140876408+RedBlackAka@users.noreply.github.com> Date: Fri, 21 Feb 2025 15:53:00 +0100 Subject: [PATCH 044/299] Clean up Windows Start Menu --- packaging/NSIS/Ultimaker-Cura.nsi.jinja | 32 +++++++++---------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/packaging/NSIS/Ultimaker-Cura.nsi.jinja b/packaging/NSIS/Ultimaker-Cura.nsi.jinja index ac826af0d9..335626da12 100644 --- a/packaging/NSIS/Ultimaker-Cura.nsi.jinja +++ b/packaging/NSIS/Ultimaker-Cura.nsi.jinja @@ -16,13 +16,11 @@ !define REG_APP_PATH "Software\Microsoft\Windows\CurrentVersion\App Paths\${APP_NAME}-${VERSION}" !define UNINSTALL_PATH "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}-${VERSION}" -!define REG_START_MENU "Start Menu Folder" +!define REG_START_MENU "Start Menu Shortcut" ;Require administrator access RequestExecutionLevel admin -var SM_Folder - ###################################################################### VIProductVersion "${VIVERSION}" @@ -68,7 +66,6 @@ InstallDir "$PROGRAMFILES64\${APP_NAME}" !define MUI_STARTMENUPAGE_REGISTRY_ROOT "${REG_ROOT}" !define MUI_STARTMENUPAGE_REGISTRY_KEY "${UNINSTALL_PATH}" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${REG_START_MENU}" -!insertmacro MUI_PAGE_STARTMENU Application $SM_Folder !endif !insertmacro MUI_PAGE_INSTFILES @@ -108,25 +105,21 @@ WriteUninstaller "$INSTDIR\uninstall.exe" !ifdef REG_START_MENU !insertmacro MUI_STARTMENU_WRITE_BEGIN Application -CreateDirectory "$SMPROGRAMS\$SM_Folder" -CreateShortCut "$SMPROGRAMS\$SM_Folder\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}" -CreateShortCut "$SMPROGRAMS\$SM_Folder\Uninstall ${APP_NAME}.lnk" "$INSTDIR\uninstall.exe" +CreateShortCut "$SMPROGRAMS\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}" !ifdef WEB_SITE WriteIniStr "$INSTDIR\UltiMaker Cura website.url" "InternetShortcut" "URL" "${WEB_SITE}" -CreateShortCut "$SMPROGRAMS\$SM_Folder\UltiMaker Cura website.lnk" "$INSTDIR\UltiMaker Cura website.url" +CreateShortCut "$SMPROGRAMS\UltiMaker Cura website.lnk" "$INSTDIR\UltiMaker Cura website.url" !endif !insertmacro MUI_STARTMENU_WRITE_END !endif !ifndef REG_START_MENU -CreateDirectory "$SMPROGRAMS\{{ app_name }}" -CreateShortCut "$SMPROGRAMS\{{ app_name }}\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}" -CreateShortCut "$SMPROGRAMS\{{ app_name }}\Uninstall ${APP_NAME}.lnk" "$INSTDIR\uninstall.exe" +CreateShortCut "$SMPROGRAMS\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}" !ifdef WEB_SITE WriteIniStr "$INSTDIR\UltiMaker Cura website.url" "InternetShortcut" "URL" "${WEB_SITE}" -CreateShortCut "$SMPROGRAMS\{{ app_name }}\UltiMaker Cura website.lnk" "$INSTDIR\UltiMaker Cura website.url" +CreateShortCut "$SMPROGRAMS\UltiMaker Cura website.lnk" "$INSTDIR\UltiMaker Cura website.url" !endif !endif @@ -184,22 +177,19 @@ Delete "$INSTDIR\${APP_NAME} website.url" RmDir /r /REBOOTOK "$INSTDIR" !ifdef REG_START_MENU -!insertmacro MUI_STARTMENU_GETFOLDER "Application" $SM_Folder -Delete "$SMPROGRAMS\$SM_Folder\${APP_NAME}.lnk" -Delete "$SMPROGRAMS\$SM_Folder\Uninstall ${APP_NAME}.lnk" +Delete "$SMPROGRAMS\${APP_NAME}.lnk" +Delete "$SMPROGRAMS\Uninstall ${APP_NAME}.lnk" !ifdef WEB_SITE -Delete "$SMPROGRAMS\$SM_Folder\UltiMaker Cura website.lnk" +Delete "$SMPROGRAMS\UltiMaker Cura website.lnk" !endif -RmDir "$SMPROGRAMS\$SM_Folder" !endif !ifndef REG_START_MENU -Delete "$SMPROGRAMS\{{ app_name }}\${APP_NAME}.lnk" -Delete "$SMPROGRAMS\{{ app_name }}\Uninstall ${APP_NAME}.lnk" +Delete "$SMPROGRAMS\${APP_NAME}.lnk" +Delete "$SMPROGRAMS\Uninstall ${APP_NAME}.lnk" !ifdef WEB_SITE -Delete "$SMPROGRAMS\{{ app_name }}\UltiMaker Cura website.lnk" +Delete "$SMPROGRAMS\UltiMaker Cura website.lnk" !endif -RmDir "$SMPROGRAMS\{{ app_name }}" !endif !insertmacro APP_UNASSOCIATE "stl" "Cura.model" From cf52772fd19043d20fe2110ef4a539172ff32238 Mon Sep 17 00:00:00 2001 From: Jeremy Salwen Date: Fri, 21 Mar 2025 08:42:43 -0400 Subject: [PATCH 045/299] Enable more retraction settings to be set per-model These retraction settings were already supported on a per-object basis on the backend by https://github.com/Ultimaker/CuraEngine/pull/1769, but were not enabled by the corresponding frontend PR at the time. This helps get incrementally closer to exposing per-model settings https://github.com/Ultimaker/Cura/issues/3193 --- resources/definitions/fdmprinter.def.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index b42b5c417a..ce43289636 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -4553,7 +4553,7 @@ "minimum_value_warning": "-0.0001", "maximum_value_warning": "10.0", "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", - "settable_per_mesh": false, + "settable_per_mesh": true, "settable_per_extruder": true }, "retraction_speed": @@ -4643,7 +4643,7 @@ "maximum_value": 999999999, "type": "int", "enabled": "retraction_enable", - "settable_per_mesh": false, + "settable_per_mesh": true, "settable_per_extruder": true }, "retraction_extrusion_window": @@ -4657,7 +4657,7 @@ "maximum_value_warning": "retraction_amount * 2", "value": "retraction_amount", "enabled": "retraction_enable", - "settable_per_mesh": false, + "settable_per_mesh": true, "settable_per_extruder": true }, "retraction_combing": From 001dfc30af53f0154dc562cd4ddfc0200a7c347c Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 22 Mar 2025 11:10:23 -0400 Subject: [PATCH 046/299] Update AddCoolingProfile.py Re-worked the Build Volume fan code to include a printers Auxiliary fan if there is one. --- .../scripts/AddCoolingProfile.py | 126 ++++++++++-------- 1 file changed, 67 insertions(+), 59 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py index c6ec748f96..e30e83b653 100644 --- a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py +++ b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py @@ -1,18 +1,22 @@ -# Designed in January 2023 by GregValiant (Greg Foresi) -# My design intent was to make this as full featured and "industrial strength" as I could. People printing exotic materials on large custom printers may want to turn the fans off for certain layers, and then back on again later in the print. This script allows that. -# Functions: -# Remove all fan speed lines from the file (optional). This should be enabled for the first instance of the script. It is disabled by default in any following instances. -# "By Layer" allows the user to adjust the fan speed up, or down, or off, within the print. "By Feature" allows different fan speeds for different features (;TYPE:WALL-OUTER, etc.). -# If 'By Feature' then a Start Layer and/or an End Layer can be defined. -# Fan speeds are scaled PWM (0 - 255) or RepRap (0.0 - 1.0) depending on {machine_scale_fan_speed_zero_to_one}. -# A minimum fan speed of 12% is enforced. It is the slowest speed that my cooling fan will turn on so that's what I used. 'M106 S14' (as Cura might insert) was pretty useless. -# If multiple extruders have separate fan circuits the speeds are set at tool changes and conform to the layer or feature setting. There is support for up to 4 layer cooling fan circuits. -# My thanks to @5axes(@CUQ), @fieldOfView(@AHoeben), @Ghostkeeper, and @Torgeir. A special thanks to @RBurema for his patience in reviewing my 'non-pythonic' script. -# 09/14/23 (GV) Added support for One-at-a-Time print sequence. -# 12/15/23 (GV) Split off 'Single Fan By Layer', 'Multi-fan By Layer', 'Single Fan By Feature', and 'Multi-fan By Feature' from the main 'execute' script. -# 01/05/24 (GV) Revised the regex replacements. -# 12/11/24 (GV) Added 'off_fan_speed' for the idle nozzle layer cooling fan. It does not have to go to 0%. -# 01/01/25 (GV) Added 'Build Volume' fan control +""" +Designed in January 2023 by GregValiant (Greg Foresi) + My design intent was to make this as full featured and "industrial strength" as I could. People printing exotic materials on large custom printers may want to turn the fans off for certain layers, and then back on again later in the print. This script allows that. + Functions: + Remove all fan speed lines from the file (optional). This should be enabled for the first instance of the script. It is disabled by default in any following instances. + "By Layer" allows the user to adjust the fan speed up, or down, or off, within the print. "By Feature" allows different fan speeds for different features (;TYPE:WALL-OUTER, etc.). + If 'By Feature' then a Start Layer and/or an End Layer can be defined. + Fan speeds are scaled PWM (0 - 255) or RepRap (0.0 - 1.0) depending on {machine_scale_fan_speed_zero_to_one}. + A minimum fan speed of 12% is enforced. It is the slowest speed that my cooling fan will turn on so that's what I used. 'M106 S14' (as Cura might insert) was pretty useless. + If multiple extruders have separate fan circuits the speeds are set at tool changes and conform to the layer or feature setting. There is support for up to 4 layer cooling fan circuits. + My thanks to @5axes(@CUQ), @fieldOfView(@AHoeben), @Ghostkeeper, and @Torgeir. A special thanks to @RBurema for his patience in reviewing my 'non-pythonic' script. + Changes: + 09/14/23 (GV) Added support for One-at-a-Time print sequence. + 12/15/23 (GV) Split off 'Single Fan By Layer', 'Multi-fan By Layer', 'Single Fan By Feature', and 'Multi-fan By Feature' from the main 'execute' script. + 01/05/24 (GV) Revised the regex replacements. + 12/11/24 (GV) Added 'off_fan_speed' for the idle nozzle layer cooling fan. It does not have to go to 0%. + 01/01/25 (GV) Added 'Build Volume' fan control + 03/15/25 (GV) Added 'Chamber Cooling Fan' control +""" from ..Script import Script from UM.Application import Application @@ -45,7 +49,8 @@ class AddCoolingProfile(Script): "type": "bool", "enabled": true, "value": true, - "default_value": true + "default_value": true, + "read_only": true }, "feature_fan_start_layer": { @@ -305,16 +310,26 @@ class AddCoolingProfile(Script): }, "bv_fan_speed_control_enable": { - "label": "Enable 'Chamber Fan' control", - "description": "Available if the 'Build Volume Fan Number' > 0 in 'Printer Settings'. Provides: On layer, off layer, and PWM speed control of the Chamber fan.", + "label": "Enable 'Chamber/Aux Fan' control", + "description": "Controls the 'Build Volume Fan' or an 'Auxiliary Fan' on printers with that hardware. Provides: 'On' layer, 'Off' layer, and PWM speed control of a secondary fan.", "type": "bool", "default_value": false, "enabled": "enable_bv_fan" }, + "bv_fan_nr": + { + "label": " Chamber/Aux Fan Number", + "description": "The mainboard circuit number of the Chamber or Auxiliary Fan.", + "type": "int", + "unit": "# ", + "default_value": 0, + "minimum_value": 0, + "enabled": "enable_bv_fan and bv_fan_speed_control_enable" + }, "bv_fan_speed": { - "label": " Chamber fan speed %", - "description": "The speed of the Chamber Fan. This will be converted to PWM Duty Cycle (0-255) or (RepRap 0-1 if that is enabled in Cura).", + "label": " Chamber/Aux Fan Speed %", + "description": "The speed of the Chamber or Auxiliary Fan. This will be converted to PWM Duty Cycle (0-255) or (RepRap 0-1 if that is enabled in Cura). If your specified fan does not operate on variable speeds then set this to '100'.", "type": "int", "unit": "% ", "default_value": 50, @@ -324,18 +339,20 @@ class AddCoolingProfile(Script): }, "bv_fan_start_layer": { - "label": " Start Layer", - "description": "The layer number for Chamber Fan start. Use the Cura preview layer number. If you are using a raft the chanber fan will start when the raft finishes.", + "label": " Chamber/Aux Fan Start Layer", + "description": "The layer to start the Chamber or Auxiliary Fan. Use the Cura preview layer number and the fan will start at the beginning of the layer.", "type": "int", + "unit": "Layer# ", "default_value": 1, "minimum_value": 1, "enabled": "enable_bv_fan and bv_fan_speed_control_enable" }, "bv_fan_end_layer": { - "label": " End Layer", - "description": "The layer number for Chamber Fan to turn off. Use the Cura preview layer number or '-1' to indicate the end of the print.", + "label": " Chamber/Aux Fan End Layer", + "description": "The layer number for Chamber or Auxiliary Fan to turn off. Use the Cura preview layer number or '-1' to indicate the end of the print. The fan will run until the end of the layer", "type": "int", + "unit": "Layer# ", "default_value": -1, "minimum_value": -1, "enabled": "enable_bv_fan and bv_fan_speed_control_enable" @@ -343,7 +360,7 @@ class AddCoolingProfile(Script): "enable_bv_fan": { "label": "Hidden setting", - "description": "For printers with heated chambers and chamber fans, this enables 'bv_fan_speed_control_enable'.", + "description": "This is enabled when machine_heated_bed is true, and in turn this enables 'bv_fan_speed_control_enable'.", "type": "bool", "default_value": false, "enabled": false @@ -364,18 +381,10 @@ class AddCoolingProfile(Script): self._instance.setProperty("delete_existing_m106", "value", False) if extruder_count > 1: if extruder[0].getProperty("machine_extruder_cooling_fan_number", "value") != extruder[1].getProperty("machine_extruder_cooling_fan_number", "value"): - self._instance.setProperty("enable_off_fan_speed_enable", "value", True) - - self.has_bv_fan = False - self.bv_fan_nr = 0 - try: - self.has_bv_fan = bool(global_stack.getProperty("build_volume_fan_nr", "value")) - self.bv_fan_nr = int(global_stack.getProperty("build_volume_fan_nr", "value")) - except: - pass - if self.has_bv_fan: + self._instance.setProperty("enable_off_fan_speed_enable", "value", True) + if bool(global_stack.getProperty("machine_heated_bed", "value")): self._instance.setProperty("enable_bv_fan", "value", True) - + def execute(self, data): # Exit if the gcode has been previously post-processed. if ";POSTPROCESSED" in data[0]: @@ -384,7 +393,7 @@ class AddCoolingProfile(Script): self.global_stack = Application.getInstance().getGlobalContainerStack() t0_fan = " P0"; t1_fan = " P0"; t2_fan = " P0"; t3_fan = " P0"; is_multi_extr_print = True - #Get some information from Cura----------------------------------- + #Get some information from Cura extruder = self.global_stack.extruderList extruder_count = self.global_stack.getProperty("machine_extruder_count", "value") @@ -398,14 +407,14 @@ class AddCoolingProfile(Script): bed_adhesion = (extruder[0].getProperty("adhesion_type", "value")) print_sequence = str(self.global_stack.getProperty("print_sequence", "value")) - #Assign the fan numbers to the tools------------------------------ + #Assign the fan numbers to the tools if extruder_count == 1: is_multi_fan = False is_multi_extr_print = False if int((extruder[0].getProperty("machine_extruder_cooling_fan_number", "value"))) > 0: t0_fan = " P" + str((extruder[0].getProperty("machine_extruder_cooling_fan_number", "value"))) else: - #No P parameter if there is a single fan circuit------------------ + # No P parameter if there is a single fan circuit t0_fan = "" #Get the cooling fan numbers for each extruder if the printer has multiple extruders @@ -417,13 +426,13 @@ class AddCoolingProfile(Script): if extruder_count > 2: t2_fan = " P" + str((extruder[2].getProperty("machine_extruder_cooling_fan_number", "value"))) if extruder_count > 3: t3_fan = " P" + str((extruder[3].getProperty("machine_extruder_cooling_fan_number", "value"))) - #Initialize the fan_list with defaults---------------------------- + #Initialize the fan_list with defaults fan_list = ["z"] * 16 for num in range(0,15,2): fan_list[num] = len(data) fan_list[num + 1] = "M106 S0" - #Assign the variable values if "By Layer"------------------------- + #Assign the variable values if "By Layer" by_layer_or_feature = self.getSettingValueByKey("fan_layer_or_feature") if by_layer_or_feature == "by_layer": # By layer doesn't do any feature search so there is no need to look for combing moves @@ -554,7 +563,7 @@ class AddCoolingProfile(Script): else: fan_sp_raft = "M106 S0" - # Start to alter the data----------------------------------------- + # Start to alter the data # Strip the existing M106 lines from the file up to the end of the last layer. If a user wants to use more than one instance of this plugin then they won't want to erase the M106 lines that the preceding plugins inserted so 'delete_existing_m106' is an option. delete_existing_m106 = self.getSettingValueByKey("delete_existing_m106") if delete_existing_m106: @@ -633,28 +642,26 @@ class AddCoolingProfile(Script): data[layer_num] = re.sub(";MESH:NOMESH", ";MESH:NONMESH", layer) data = self._add_travel_comment(data, layer_0_index) - # If there is a build volume fan - if self.has_bv_fan: - if self.getSettingValueByKey("bv_fan_speed_control_enable"): - data = self._control_bv_fan(data) + if bool(self.getSettingValueByKey("bv_fan_speed_control_enable")): + data = self._control_bv_fan(data) - # Single Fan "By Layer"-------------------------------------------- + # Single Fan "By Layer" if by_layer_or_feature == "by_layer" and not is_multi_fan: return self._single_fan_by_layer(data, layer_0_index, fan_list, t0_fan) - # Multi-Fan "By Layer"--------------------------------------------- + # Multi-Fan "By Layer" if by_layer_or_feature == "by_layer" and is_multi_fan: return self._multi_fan_by_layer(data, layer_0_index, fan_list, t0_fan, t1_fan, t2_fan, t3_fan, fan_mode, off_fan_speed) - #Single Fan "By Feature"------------------------------------------ + #Single Fan "By Feature" if by_layer_or_feature == "by_feature" and (not is_multi_fan or not is_multi_extr_print): return self._single_fan_by_feature(data, layer_0_index, the_start_layer, the_end_layer, the_end_is_enabled, fan_list, t0_fan, feature_speed_list, feature_name_list, feature_fan_combing) - #Multi Fan "By Feature"------------------------------------------- + #Multi Fan "By Feature" if by_layer_or_feature == "by_feature" and is_multi_fan: return self._multi_fan_by_feature(data, layer_0_index, the_start_layer, the_end_layer, the_end_is_enabled, fan_list, t0_fan, t1_fan, t2_fan, t3_fan, feature_speed_list, feature_name_list, feature_fan_combing, fan_mode, off_fan_speed) - # The Single Fan "By Layer"---------------------------------------- + # The Single Fan "By Layer" def _single_fan_by_layer(self, data: str, layer_0_index: int, fan_list: str, t0_fan: str)->str: layer_number = "0" single_fan_data = data @@ -671,7 +678,7 @@ class AddCoolingProfile(Script): single_fan_data[l_index] = layer return single_fan_data - # Multi-Fan "By Layer"----------------------------------------- + # Multi-Fan "By Layer" def _multi_fan_by_layer(self, data: str, layer_0_index: int, fan_list: str, t0_fan: str, t1_fan: str, t2_fan: str, t3_fan: str, fan_mode: bool, off_fan_speed: str)->str: multi_fan_data = data layer_number = "0" @@ -737,7 +744,7 @@ class AddCoolingProfile(Script): multi_fan_data[-1] += "M106 S0 P1\nM106 S0 P0\n" return multi_fan_data - # Single fan by feature----------------------------------------------- + # Single fan by feature def _single_fan_by_feature(self, data: str, layer_0_index: int, the_start_layer: str, the_end_layer: str, the_end_is_enabled: str, fan_list: str, t0_fan: str, feature_speed_list: str, feature_name_list: str, feature_fan_combing: bool)->str: single_fan_data = data layer_number = "0" @@ -769,7 +776,7 @@ class AddCoolingProfile(Script): single_fan_data[l_index] = modified_data return single_fan_data - # Multi-fan by feature------------------------------------------------ + # Multi-fan by feature def _multi_fan_by_feature(self, data: str, layer_0_index: int, the_start_layer: str, the_end_layer: str, the_end_is_enabled: str, fan_list: str, t0_fan: str, t1_fan: str, t2_fan: str, t3_fan: str, feature_speed_list: str, feature_name_list: str, feature_fan_combing: bool, fan_mode: bool, off_fan_speed: str)->str: multi_fan_data = data layer_number = "0" @@ -812,7 +819,7 @@ class AddCoolingProfile(Script): if line == "T3": this_fan = t3_fan prev_fan = this_fan - # Start to make insertions------------------------------------- + # Start to make insertions for l_index in range(start_index+1,len(multi_fan_data)-1,1): layer = multi_fan_data[l_index] lines = layer.split("\n") @@ -930,7 +937,7 @@ class AddCoolingProfile(Script): if g0_index == -1: g0_index = lines.index(line) elif not line.startswith("G0 ") and not is_travel: - # Add additional 'NONMESH' lines to shut the fan off during long combing moves-------- + # Add additional 'NONMESH' lines to shut the fan off during long combing moves if g0_count > 5: if not is_travel: new_data.insert(g0_index + insert_index, ";MESH:NONMESH") @@ -952,6 +959,7 @@ class AddCoolingProfile(Script): # Control the chamber fan bv_start_layer = self.getSettingValueByKey("bv_fan_start_layer") - 1 bv_end_layer = self.getSettingValueByKey("bv_fan_end_layer") + bv_fan_nr = self.getSettingValueByKey("bv_fan_nr") if bv_end_layer != -1: bv_end_layer -= 1 # Get the PWM speed or if RepRap then the 0-1 speed @@ -962,18 +970,18 @@ class AddCoolingProfile(Script): # Turn the chamber fan on for index, layer in enumerate(bv_data): if ";LAYER:" + str(bv_start_layer) + "\n" in layer: - bv_data[index] = re.sub(f";LAYER:{bv_start_layer}", f";LAYER:{bv_start_layer}\nM106 S{bv_fan_speed} P{self.bv_fan_nr}",layer) + bv_data[index] = re.sub(f";LAYER:{bv_start_layer}", f";LAYER:{bv_start_layer}\nM106 S{bv_fan_speed} P{bv_fan_nr}",layer) break # Turn the chamber fan off if bv_end_layer == -1: - bv_data[len(bv_data)-2] += f"M106 S0 P{self.bv_fan_nr}\n" + bv_data[len(bv_data)-2] += f"M106 S0 P{bv_fan_nr}\n" else: for index, layer in enumerate(bv_data): if ";LAYER:" + str(bv_end_layer) + "\n" in layer: lines = layer.split("\n") for fdex, line in enumerate(lines): if ";TIME_ELAPSED:" in line: - lines[fdex] = f"M106 S0 P{self.bv_fan_nr}\n" + line + lines[fdex] = f"M106 S0 P{bv_fan_nr}\n" + line bv_data[index] = "\n".join(lines) break return bv_data \ No newline at end of file From a94f5e0f28f29d8589a76f7623ed7dcdb7ff9d2d Mon Sep 17 00:00:00 2001 From: HellAholic Date: Sat, 22 Mar 2025 17:53:48 +0100 Subject: [PATCH 047/299] Add space after # for the comments --- .../scripts/AddCoolingProfile.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py index e30e83b653..bbf90b764c 100644 --- a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py +++ b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py @@ -389,17 +389,17 @@ class AddCoolingProfile(Script): # Exit if the gcode has been previously post-processed. if ";POSTPROCESSED" in data[0]: return data - #Initialize variables that are buried in if statements. + # Initialize variables that are buried in if statements. self.global_stack = Application.getInstance().getGlobalContainerStack() t0_fan = " P0"; t1_fan = " P0"; t2_fan = " P0"; t3_fan = " P0"; is_multi_extr_print = True - #Get some information from Cura + # Get some information from Cura extruder = self.global_stack.extruderList extruder_count = self.global_stack.getProperty("machine_extruder_count", "value") - #This will be true when fan scale is 0-255pwm and false when it's RepRap 0-1 (Cura 5.x) + # This will be true when fan scale is 0-255pwm and false when it's RepRap 0-1 (Cura 5.x) fan_mode = True - #For 4.x versions that don't have the 0-1 option + # For 4.x versions that don't have the 0-1 option try: fan_mode = not bool(extruder[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) except: @@ -407,7 +407,7 @@ class AddCoolingProfile(Script): bed_adhesion = (extruder[0].getProperty("adhesion_type", "value")) print_sequence = str(self.global_stack.getProperty("print_sequence", "value")) - #Assign the fan numbers to the tools + # Assign the fan numbers to the tools if extruder_count == 1: is_multi_fan = False is_multi_extr_print = False @@ -417,7 +417,7 @@ class AddCoolingProfile(Script): # No P parameter if there is a single fan circuit t0_fan = "" - #Get the cooling fan numbers for each extruder if the printer has multiple extruders + # Get the cooling fan numbers for each extruder if the printer has multiple extruders elif extruder_count > 1: is_multi_fan = True t0_fan = " P" + str((extruder[0].getProperty("machine_extruder_cooling_fan_number", "value"))) @@ -426,13 +426,13 @@ class AddCoolingProfile(Script): if extruder_count > 2: t2_fan = " P" + str((extruder[2].getProperty("machine_extruder_cooling_fan_number", "value"))) if extruder_count > 3: t3_fan = " P" + str((extruder[3].getProperty("machine_extruder_cooling_fan_number", "value"))) - #Initialize the fan_list with defaults + # Initialize the fan_list with defaults fan_list = ["z"] * 16 for num in range(0,15,2): fan_list[num] = len(data) fan_list[num + 1] = "M106 S0" - #Assign the variable values if "By Layer" + # Assign the variable values if "By Layer" by_layer_or_feature = self.getSettingValueByKey("fan_layer_or_feature") if by_layer_or_feature == "by_layer": # By layer doesn't do any feature search so there is no need to look for combing moves @@ -653,11 +653,11 @@ class AddCoolingProfile(Script): if by_layer_or_feature == "by_layer" and is_multi_fan: return self._multi_fan_by_layer(data, layer_0_index, fan_list, t0_fan, t1_fan, t2_fan, t3_fan, fan_mode, off_fan_speed) - #Single Fan "By Feature" + # Single Fan "By Feature" if by_layer_or_feature == "by_feature" and (not is_multi_fan or not is_multi_extr_print): return self._single_fan_by_feature(data, layer_0_index, the_start_layer, the_end_layer, the_end_is_enabled, fan_list, t0_fan, feature_speed_list, feature_name_list, feature_fan_combing) - #Multi Fan "By Feature" + # Multi Fan "By Feature" if by_layer_or_feature == "by_feature" and is_multi_fan: return self._multi_fan_by_feature(data, layer_0_index, the_start_layer, the_end_layer, the_end_is_enabled, fan_list, t0_fan, t1_fan, t2_fan, t3_fan, feature_speed_list, feature_name_list, feature_fan_combing, fan_mode, off_fan_speed) @@ -871,7 +871,7 @@ class AddCoolingProfile(Script): multi_fan_data[-1] += "M106 S0 P1\nM106 S0 P0\n" return multi_fan_data - #Try to catch layer input errors, set the minimum speed to 12%, and put the strings together + # Try to catch layer input errors, set the minimum speed to 12%, and put the strings together def _layer_checker(self, fan_string: str, ty_pe: str, fan_mode: bool) -> str: fan_string_l = str(fan_string.split("/")[0]) try: From 99b198339ac3447ee5d419ab8b08a4ff40ce1159 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 22 Mar 2025 15:41:39 -0400 Subject: [PATCH 048/299] Update AddCoolingProfile.py Update per requested changes. Comments are consistent with "# ". global_stack, extruder_list, extruder_count are assigned to "self". --- .../scripts/AddCoolingProfile.py | 60 +++++++++---------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py index bbf90b764c..6e43e98969 100644 --- a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py +++ b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py @@ -14,8 +14,7 @@ Designed in January 2023 by GregValiant (Greg Foresi) 12/15/23 (GV) Split off 'Single Fan By Layer', 'Multi-fan By Layer', 'Single Fan By Feature', and 'Multi-fan By Feature' from the main 'execute' script. 01/05/24 (GV) Revised the regex replacements. 12/11/24 (GV) Added 'off_fan_speed' for the idle nozzle layer cooling fan. It does not have to go to 0%. - 01/01/25 (GV) Added 'Build Volume' fan control - 03/15/25 (GV) Added 'Chamber Cooling Fan' control + 03/22/25 (GV) Added 'Chamber Cooling Fan / Auxiliary Fan' control. """ from ..Script import Script @@ -370,19 +369,19 @@ class AddCoolingProfile(Script): def initialize(self) -> None: super().initialize() - global_stack = Application.getInstance().getGlobalContainerStack() - extruder = global_stack.extruderList - extruder_count = global_stack.getProperty("machine_extruder_count", "value") - scripts = global_stack.getMetaDataEntry("post_processing_scripts") + self.global_stack = Application.getInstance().getGlobalContainerStack() + self.extruder_list = self.global_stack.extruderList + self.extruder_count = self.global_stack.getProperty("machine_extruder_count", "value") + scripts = self.global_stack.getMetaDataEntry("post_processing_scripts") if scripts != None: script_count = scripts.count("AddCoolingProfile") if script_count > 0: # Set 'Remove M106 lines' to "false" if there is already an instance of this script running. self._instance.setProperty("delete_existing_m106", "value", False) - if extruder_count > 1: - if extruder[0].getProperty("machine_extruder_cooling_fan_number", "value") != extruder[1].getProperty("machine_extruder_cooling_fan_number", "value"): + if self.extruder_count > 1: + if self.extruder_list[0].getProperty("machine_extruder_cooling_fan_number", "value") != self.extruder_list[1].getProperty("machine_extruder_cooling_fan_number", "value"): self._instance.setProperty("enable_off_fan_speed_enable", "value", True) - if bool(global_stack.getProperty("machine_heated_bed", "value")): + if bool(self.global_stack.getProperty("machine_heated_bed", "value")): self._instance.setProperty("enable_bv_fan", "value", True) def execute(self, data): @@ -390,41 +389,36 @@ class AddCoolingProfile(Script): if ";POSTPROCESSED" in data[0]: return data # Initialize variables that are buried in if statements. - self.global_stack = Application.getInstance().getGlobalContainerStack() t0_fan = " P0"; t1_fan = " P0"; t2_fan = " P0"; t3_fan = " P0"; is_multi_extr_print = True - # Get some information from Cura - extruder = self.global_stack.extruderList - extruder_count = self.global_stack.getProperty("machine_extruder_count", "value") - # This will be true when fan scale is 0-255pwm and false when it's RepRap 0-1 (Cura 5.x) fan_mode = True # For 4.x versions that don't have the 0-1 option try: - fan_mode = not bool(extruder[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) + fan_mode = not bool(self.extruder_list[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) except: pass - bed_adhesion = (extruder[0].getProperty("adhesion_type", "value")) + bed_adhesion = (self.extruder_list[0].getProperty("adhesion_type", "value")) print_sequence = str(self.global_stack.getProperty("print_sequence", "value")) # Assign the fan numbers to the tools - if extruder_count == 1: + if self.extruder_count == 1: is_multi_fan = False is_multi_extr_print = False - if int((extruder[0].getProperty("machine_extruder_cooling_fan_number", "value"))) > 0: - t0_fan = " P" + str((extruder[0].getProperty("machine_extruder_cooling_fan_number", "value"))) + if int((self.extruder_list[0].getProperty("machine_extruder_cooling_fan_number", "value"))) > 0: + t0_fan = " P" + str((self.extruder_list[0].getProperty("machine_extruder_cooling_fan_number", "value"))) else: # No P parameter if there is a single fan circuit t0_fan = "" # Get the cooling fan numbers for each extruder if the printer has multiple extruders - elif extruder_count > 1: + elif self.extruder_count > 1: is_multi_fan = True - t0_fan = " P" + str((extruder[0].getProperty("machine_extruder_cooling_fan_number", "value"))) + t0_fan = " P" + str((self.extruder_list[0].getProperty("machine_extruder_cooling_fan_number", "value"))) if is_multi_fan: - if extruder_count > 1: t1_fan = " P" + str((extruder[1].getProperty("machine_extruder_cooling_fan_number", "value"))) - if extruder_count > 2: t2_fan = " P" + str((extruder[2].getProperty("machine_extruder_cooling_fan_number", "value"))) - if extruder_count > 3: t3_fan = " P" + str((extruder[3].getProperty("machine_extruder_cooling_fan_number", "value"))) + if self.extruder_count > 1: t1_fan = " P" + str((self.extruder_list[1].getProperty("machine_extruder_cooling_fan_number", "value"))) + if self.extruder_count > 2: t2_fan = " P" + str((self.extruder_list[2].getProperty("machine_extruder_cooling_fan_number", "value"))) + if self.extruder_count > 3: t3_fan = " P" + str((self.extruder_list[3].getProperty("machine_extruder_cooling_fan_number", "value"))) # Initialize the fan_list with defaults fan_list = ["z"] * 16 @@ -488,7 +482,7 @@ class AddCoolingProfile(Script): # For multi-extruder printers with separate fans the 'idle' nozzle fan can be left on for ooze control off_fan_speed = 0 - if extruder_count > 1: + if self.extruder_count > 1: if self.getSettingValueByKey("enable_off_fan_speed"): if fan_mode: off_fan_speed = round(int(self.getSettingValueByKey("off_fan_speed")) * 2.55) @@ -629,9 +623,9 @@ class AddCoolingProfile(Script): temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t0_fan)) # If there are multiple cooling fans shut them all off if is_multi_fan: - if extruder_count > 1 and t1_fan != t0_fan: temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t1_fan)) - if extruder_count > 2 and t2_fan != t1_fan and t2_fan != t0_fan: temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t2_fan)) - if extruder_count > 3 and t3_fan != t2_fan and t3_fan != t1_fan and t3_fan != t0_fan: temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t3_fan)) + if self.extruder_count > 1 and t1_fan != t0_fan: temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t1_fan)) + if self.extruder_count > 2 and t2_fan != t1_fan and t2_fan != t0_fan: temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t2_fan)) + if self.extruder_count > 3 and t3_fan != t2_fan and t3_fan != t1_fan and t3_fan != t0_fan: temp_startup.insert(len(temp_startup)-2,"M106 S0" + str(t3_fan)) data[1] = "\n".join(temp_startup) # If 'feature_fan_combing' is True then add additional 'MESH:NONMESH' lines for travel moves over 5 lines long @@ -740,7 +734,7 @@ class AddCoolingProfile(Script): if modified_data.endswith("\n"): modified_data = modified_data[0:-1] multi_fan_data[l_index] = modified_data # Insure the fans get shut off if 'off_fan_speed' was enabled - if self.global_stack.getProperty("machine_extruder_count", "value") > 1 and self.getSettingValueByKey("enable_off_fan_speed"): + if self.extruder_count > 1 and self.getSettingValueByKey("enable_off_fan_speed"): multi_fan_data[-1] += "M106 S0 P1\nM106 S0 P0\n" return multi_fan_data @@ -867,7 +861,7 @@ class AddCoolingProfile(Script): multi_fan_data[l_index] = modified_data modified_data = "" # Insure the fans get shut off if 'off_fan_speed' was enabled - if self.global_stack.getProperty("machine_extruder_count", "value") > 1 and self.getSettingValueByKey("enable_off_fan_speed"): + if self.extruder_count > 1 and self.getSettingValueByKey("enable_off_fan_speed"): multi_fan_data[-1] += "M106 S0 P1\nM106 S0 P0\n" return multi_fan_data @@ -963,13 +957,13 @@ class AddCoolingProfile(Script): if bv_end_layer != -1: bv_end_layer -= 1 # Get the PWM speed or if RepRap then the 0-1 speed - if self.global_stack.extruderList[0].getProperty("machine_scale_fan_speed_zero_to_one", "value"): + if self.extruder_list[0].getProperty("machine_scale_fan_speed_zero_to_one", "value"): bv_fan_speed = round(self.getSettingValueByKey("bv_fan_speed") * .01, 1) else: bv_fan_speed = int(self.getSettingValueByKey("bv_fan_speed") * 2.55) # Turn the chamber fan on for index, layer in enumerate(bv_data): - if ";LAYER:" + str(bv_start_layer) + "\n" in layer: + if f";LAYER:{bv_start_layer}\n" in layer: bv_data[index] = re.sub(f";LAYER:{bv_start_layer}", f";LAYER:{bv_start_layer}\nM106 S{bv_fan_speed} P{bv_fan_nr}",layer) break # Turn the chamber fan off @@ -977,7 +971,7 @@ class AddCoolingProfile(Script): bv_data[len(bv_data)-2] += f"M106 S0 P{bv_fan_nr}\n" else: for index, layer in enumerate(bv_data): - if ";LAYER:" + str(bv_end_layer) + "\n" in layer: + if f";LAYER:{bv_end_layer}\n" in layer: lines = layer.split("\n") for fdex, line in enumerate(lines): if ";TIME_ELAPSED:" in line: From 416b159a7ea3c82516aaf88cf6cd145fb1d2e921 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 22 Mar 2025 11:18:30 -0400 Subject: [PATCH 049/299] Update DisplayInfoOnLCD.py Added the "time to pause" to the user message. Update DisplayInfoOnLCD.py update --- .../scripts/DisplayInfoOnLCD.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index b19f222f2a..49222882bc 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -488,8 +488,8 @@ class DisplayInfoOnLCD(Script): data[layer_index] = "\n".join(lines) # If enabled then change the ET to TP for 'Time To Pause' + time_list = [] if bool(self.getSettingValueByKey("countdown_to_pause")): - time_list = [] time_list.append("0") time_list.append("0") this_time = 0 @@ -528,11 +528,11 @@ class DisplayInfoOnLCD(Script): continue data[num] = layer if bool(self.getSettingValueByKey("enable_end_message")): - message_str = self._message_to_user(speed_factor) + message_str = self._message_to_user(data, speed_factor, pause_cmd) Message(title = "[Display Info on LCD] - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() return data - def _message_to_user(self, speed_factor: float): + def _message_to_user(self, data: str, speed_factor: float, pause_cmd: str) -> str: # Message the user of the projected finish time of the print print_time = Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601) print_start_time = self.getSettingValueByKey("print_start_time") @@ -596,6 +596,15 @@ class DisplayInfoOnLCD(Script): estimate_str = "Cura Time Estimate.........." + str(print_time) adjusted_str = "Adjusted Time Estimate..." + str(time_change) finish_str = week_day + " " + str(mo_str) + " " + str(new_time.strftime("%d")) + ", " + str(new_time.strftime("%Y")) + " at " + str(show_hr) + str(new_time.strftime("%M")) + str(show_ampm) + + # If there are pauses and if countdown is enabled, then add the time-to-pause to the message. + if bool(self.getSettingValueByKey("countdown_to_pause")): + num = 1 + for layer in data: + for p_cmd in pause_cmd: + if p_cmd in layer or "Do the actual pause" in layer: + adjusted_str += "\n" + self._get_time_to_go(layer.split("TIME_ELAPSED:")[1].split("\n")[0]) + " ET from start to pause #" + str(num) + num += 1 return finish_str, estimate_str, adjusted_str, print_start_str def _get_time_to_go(self, time_str: str): @@ -623,7 +632,7 @@ class DisplayInfoOnLCD(Script): model_name = line.split(":")[1] if not model_name in model_list: model_list.append(model_name) - # Add the Initial Layer Height just below Layer Height in data[0]model_list = [] + # Add some settings to data[0] extruder_count = global_stack.getProperty("machine_extruder_count", "value") init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) nozzle_size_line = ";Nozzle Size (T0): " + str(global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")) From ee5c37bd808d4e15dea6306b5deaf0038f9885df Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sun, 23 Mar 2025 07:09:04 -0400 Subject: [PATCH 050/299] Update DisplayInfoOnLCD.py Fixed the m118_str/m118_text confusion. --- .../scripts/DisplayInfoOnLCD.py | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 49222882bc..6315e28af1 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -241,7 +241,6 @@ class DisplayInfoOnLCD(Script): self.add_m118_line = self.getSettingValueByKey("add_m118_line") self.add_m118_a1 = self.getSettingValueByKey("add_m118_a1") self.add_m118_p0 = self.getSettingValueByKey("add_m118_p0") - self.m118_str = "M118 " self.m118_text = "M118 " self.add_m73_line = self.getSettingValueByKey("add_m73_line") self.add_m73_time = self.getSettingValueByKey("add_m73_time") @@ -302,15 +301,11 @@ class DisplayInfoOnLCD(Script): if self.add_m117_line: lines.insert(line_index + 1, display_text) if self.add_m118_line: - if not (self.add_m118_p0 and self.add_m118_a1): - self.m118_str = self.m118_text - if self.add_m118_a1 and not self.add_m118_p0: - self.m118_str = self.m118_text.replace("M118 ","M118 A1 ") - if self.add_m118_p0 and not self.add_m118_a1: - self.m118_str = self.m118_text.replace("M118 ","M118 P0 ") - if self.add_m118_p0 and self.add_m118_a1: - self.m118_str = self.m118_text.replace("M118 ","M118 A1 P0 ") - lines.insert(line_index + 2, self.m118_str) + if self.add_m118_a1: + self.m118_text = self.m118_text.replace("M118 ","M118 A1 ") + if self.add_m118_p0: + self.m118_text = self.m118_text.replace("M118 ","M118 P0 ") + lines.insert(line_index + 2, self.m118_text) i += 1 final_lines = "\n".join(lines) data[layer_index] = final_lines @@ -466,13 +461,12 @@ class DisplayInfoOnLCD(Script): if self.add_m117_line: lines[l_index] += "\nM117 " + display_text if self.add_m118_line: - a1_str = "" - p0_str = "" + m118_str = "\nM118 " if self.add_m118_a1: - a1_str = "A1 " + m118_str += "A1 " if self.add_m118_p0: - p0_str = "P0 " - lines[l_index] += "\nM118 " + a1_str + p0_str + display_text + m118_str += "P0 " + lines[l_index] += m118_str + display_text # add M73 line if display_remaining_time: mins = int(60 * h + m) From f0d198507a6acd7d1852eb06cecc8813eab96f43 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sun, 23 Mar 2025 07:30:23 -0400 Subject: [PATCH 051/299] Update DisplayInfoOnLCD.py Requested changes --- .../scripts/DisplayInfoOnLCD.py | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 6315e28af1..85b9744856 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -38,7 +38,6 @@ import time import datetime import math from UM.Message import Message -import re class DisplayInfoOnLCD(Script): @@ -48,7 +47,11 @@ class DisplayInfoOnLCD(Script): if Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") == "all_at_once": enable_countdown = True self._instance.setProperty("enable_countdown", "value", enable_countdown) - except: + except AttributeError: + # Handle cases where the global container stack or its properties are not accessible + pass + except KeyError: + # Handle cases where the "print_sequence" property is missing pass def getSettingDataString(self): @@ -461,12 +464,12 @@ class DisplayInfoOnLCD(Script): if self.add_m117_line: lines[l_index] += "\nM117 " + display_text if self.add_m118_line: - m118_str = "\nM118 " + m118_text = "\nM118 " if self.add_m118_a1: - m118_str += "A1 " + m118_text += "A1 " if self.add_m118_p0: - m118_str += "P0 " - lines[l_index] += m118_str + display_text + m118_text += "P0 " + lines[l_index] += m118_text + display_text # add M73 line if display_remaining_time: mins = int(60 * h + m) @@ -589,7 +592,7 @@ class DisplayInfoOnLCD(Script): print_start_str = "Print Start Time.................Now" estimate_str = "Cura Time Estimate.........." + str(print_time) adjusted_str = "Adjusted Time Estimate..." + str(time_change) - finish_str = week_day + " " + str(mo_str) + " " + str(new_time.strftime("%d")) + ", " + str(new_time.strftime("%Y")) + " at " + str(show_hr) + str(new_time.strftime("%M")) + str(show_ampm) + finish_str = f"{week_day} {mo_str} {new_time.strftime('%d')}, {new_time.strftime('%Y')} at {show_hr}{new_time.strftime('%M')}{show_ampm}" # If there are pauses and if countdown is enabled, then add the time-to-pause to the message. if bool(self.getSettingValueByKey("countdown_to_pause")): @@ -602,17 +605,20 @@ class DisplayInfoOnLCD(Script): return finish_str, estimate_str, adjusted_str, print_start_str def _get_time_to_go(self, time_str: str): + """ + Converts a time string in seconds to a human-readable format (e.g., "2h30m"). + :param time_str: The time string in seconds. + :return: A formatted string representing the time. + """ alt_time = time_str[:-1] - hhh = int(float(alt_time) / 3600) - if hhh > 0: - hhr = str(hhh) + "h" - else: - hhr = "" - mmm = ((float(alt_time) / 3600) - (int(float(alt_time) / 3600))) * 60 - sss = int((mmm - int(mmm)) * 60) - mmm = str(round(mmm)) + "m" - time_to_go = str(hhr) + str(mmm) - if hhr == "": time_to_go = time_to_go + str(sss) + "s" + total_seconds = float(alt_time) + hours = int(total_seconds // 3600) + minutes = int((total_seconds % 3600) // 60) + seconds = int(total_seconds % 60) + time_to_go = f"{hours}h" if hours > 0 else "" + time_to_go += f"{minutes}m" + if hours == 0: + time_to_go += f"{seconds}s" return time_to_go def _add_stats(self, data: str) -> str: From fa8e4b26cf36f697a12452003e90780ab563a4aa Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 25 Mar 2025 08:46:12 +0100 Subject: [PATCH 052/299] Delete test-colors path in any case + small refactors. Less indents and more logging. part of CURA-12469 --- conanfile.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/conanfile.py b/conanfile.py index 994dfb63a4..9e1bc26239 100644 --- a/conanfile.py +++ b/conanfile.py @@ -566,22 +566,27 @@ class CuraConan(ConanFile): def _make_internal_distinct(self): test_colors_path = Path(self.source_folder, "resources", "themes", "daily_test_colors.json") + if not test_colors_path.exists(): + print(f"Could not find '{str(test_colors_path)}'. Won't generate rotating colors for alpha builds.") + return if "alpha" in self.version: biweekly_day = (datetime.now() - datetime(2025, 3, 14)).days with test_colors_path.open("r") as test_colors_file: test_colors = json.load(test_colors_file) for theme_dir in Path(self.source_folder, "resources", "themes").iterdir(): - if theme_dir.is_dir(): - theme_path = Path(theme_dir, "theme.json") - if theme_path.exists(): - with theme_path.open("r") as theme_file: - theme = json.load(theme_file) - if theme["colors"]: - theme["colors"]["main_window_header_background"] = test_colors[biweekly_day] - with theme_path.open("w") as theme_file: - json.dump(theme, theme_file) - elif test_colors_path.exists(): - test_colors_path.unlink() + if not theme_dir.is_dir(): + continue + theme_path = Path(theme_dir, "theme.json") + if not theme_path.exists(): + print(f"('Colorize-by-day' alpha builds): Skipping {str(theme_path)}, could not find file.") + continue + with theme_path.open("r") as theme_file: + theme = json.load(theme_file) + if theme["colors"]: + theme["colors"]["main_window_header_background"] = test_colors[biweekly_day] + with theme_path.open("w") as theme_file: + json.dump(theme, theme_file) + test_colors_path.unlink() def generate(self): copy(self, "cura_app.py", self.source_folder, str(self._script_dir)) From c91862f4bb9d894d28fa517b81e30ab08fd5d8ef Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 25 Mar 2025 20:33:01 +0100 Subject: [PATCH 053/299] Make the conversion to uppercase optional - Add the option type bool - Set to be enabled by default - Add condition to only convert if bool value is true --- .../scripts/InsertAtLayerChange.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py b/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py index ea783b08d8..cec857a8af 100644 --- a/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py +++ b/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py @@ -1,6 +1,7 @@ # Copyright (c) 2020 Ultimaker B.V. # Created by Wayne Porter # Re-write in April of 2024 by GregValiant (Greg Foresi) +# Made convert inserted text to upper-case optional March 2025 by HellAholic # Changes: # Added an 'Enable' setting # Added support for multi-line insertions (comma delimited) @@ -82,6 +83,14 @@ class InsertAtLayerChange(Script): "type": "str", "default_value": "", "enabled": "enabled" + }, + "convert_to_upper": + { + "label": "Convert to upper-case", + "description": "Convert all inserted text to upper-case as some firmwares don't understand lower-case.", + "type": "bool", + "default_value": true, + "enabled": "enabled" } } }""" @@ -91,7 +100,7 @@ class InsertAtLayerChange(Script): if not bool(self.getSettingValueByKey("enabled")): return data #Initialize variables - mycode = self.getSettingValueByKey("gcode_to_add").upper() + mycode = self.getSettingValueByKey("gcode_to_add").upper() if bool(self.getSettingValueByKey("convert_to_upper")) else self.getSettingValueByKey("gcode_to_add") start_layer = int(self.getSettingValueByKey("start_layer")) end_layer = int(self.getSettingValueByKey("end_layer")) when_to_insert = self.getSettingValueByKey("insert_frequency") From c33a32209311f0fb96c60db25e6743141e2a4064 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 26 Mar 2025 08:57:43 +0100 Subject: [PATCH 054/299] Also remove website link. Would otherwise be hanging loose in the start-menu somehwere. done as part of CURA-12502 --- packaging/NSIS/Ultimaker-Cura.nsi.jinja | 24 +--------------------- packaging/NSIS/create_windows_installer.py | 3 +-- packaging/msi/create_windows_msi.py | 3 +-- 3 files changed, 3 insertions(+), 27 deletions(-) diff --git a/packaging/NSIS/Ultimaker-Cura.nsi.jinja b/packaging/NSIS/Ultimaker-Cura.nsi.jinja index 335626da12..8c5d48f9dd 100644 --- a/packaging/NSIS/Ultimaker-Cura.nsi.jinja +++ b/packaging/NSIS/Ultimaker-Cura.nsi.jinja @@ -1,9 +1,8 @@ -# Copyright (c) 2022 UltiMaker B.V. +# Copyright (c) 2025 UltiMaker # Cura's build system is released under the terms of the AGPLv3 or higher. !define APP_NAME "{{ app_name }}" !define COMP_NAME "{{ company }}" -!define WEB_SITE "{{ web_site }}" !define VERSION "{{ version }}" !define VIVERSION "{{ version_major }}.{{ version_minor }}.{{ version_patch }}.0" !define COPYRIGHT "Copyright (c) {{ year }} {{ company }}" @@ -107,20 +106,11 @@ WriteUninstaller "$INSTDIR\uninstall.exe" !insertmacro MUI_STARTMENU_WRITE_BEGIN Application CreateShortCut "$SMPROGRAMS\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}" -!ifdef WEB_SITE -WriteIniStr "$INSTDIR\UltiMaker Cura website.url" "InternetShortcut" "URL" "${WEB_SITE}" -CreateShortCut "$SMPROGRAMS\UltiMaker Cura website.lnk" "$INSTDIR\UltiMaker Cura website.url" -!endif !insertmacro MUI_STARTMENU_WRITE_END !endif !ifndef REG_START_MENU CreateShortCut "$SMPROGRAMS\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}" - -!ifdef WEB_SITE -WriteIniStr "$INSTDIR\UltiMaker Cura website.url" "InternetShortcut" "URL" "${WEB_SITE}" -CreateShortCut "$SMPROGRAMS\UltiMaker Cura website.lnk" "$INSTDIR\UltiMaker Cura website.url" -!endif !endif WriteRegStr ${REG_ROOT} "${REG_APP_PATH}" "" "$INSTDIR\${MAIN_APP_EXE}" @@ -131,9 +121,6 @@ WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayIcon" "$INSTDIR\${MAIN_APP_ WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayVersion" "${VERSION}" WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "Publisher" "${COMP_NAME}" -!ifdef WEB_SITE -WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "URLInfoAbout" "${WEB_SITE}" -!endif SectionEnd ###################################################################### @@ -170,26 +157,17 @@ RmDir "$INSTDIR\share\uranium" RmDir "$INSTDIR\share" Delete "$INSTDIR\uninstall.exe" -!ifdef WEB_SITE -Delete "$INSTDIR\${APP_NAME} website.url" -!endif RmDir /r /REBOOTOK "$INSTDIR" !ifdef REG_START_MENU Delete "$SMPROGRAMS\${APP_NAME}.lnk" Delete "$SMPROGRAMS\Uninstall ${APP_NAME}.lnk" -!ifdef WEB_SITE -Delete "$SMPROGRAMS\UltiMaker Cura website.lnk" -!endif !endif !ifndef REG_START_MENU Delete "$SMPROGRAMS\${APP_NAME}.lnk" Delete "$SMPROGRAMS\Uninstall ${APP_NAME}.lnk" -!ifdef WEB_SITE -Delete "$SMPROGRAMS\UltiMaker Cura website.lnk" -!endif !endif !insertmacro APP_UNASSOCIATE "stl" "Cura.model" diff --git a/packaging/NSIS/create_windows_installer.py b/packaging/NSIS/create_windows_installer.py index d15d62b951..e01c757dbb 100644 --- a/packaging/NSIS/create_windows_installer.py +++ b/packaging/NSIS/create_windows_installer.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 UltiMaker +# Copyright (c) 2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. @@ -51,7 +51,6 @@ def generate_nsi(source_path: str, dist_path: str, filename: str, version: str): version_minor = str(parsed_version.minor), version_patch = str(parsed_version.patch), company = "UltiMaker", - web_site = "https://ultimaker.com", year = datetime.now().year, cura_license_file = str(source_loc.joinpath("packaging", "cura_license.txt")), compression_method = "LZMA", # ZLIB, BZIP2 or LZMA diff --git a/packaging/msi/create_windows_msi.py b/packaging/msi/create_windows_msi.py index e44a9a924b..12c64ed24f 100644 --- a/packaging/msi/create_windows_msi.py +++ b/packaging/msi/create_windows_msi.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 UltiMaker +# Copyright (c) 2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. @@ -40,7 +40,6 @@ def generate_wxs(source_path: Path, dist_path: Path, filename: Path, app_name: s version_minor=str(parsed_version.minor), version_patch=str(parsed_version.patch), company="UltiMaker", - web_site="https://ultimaker.com", year=datetime.now().year, upgrade_code=str(uuid.uuid5(uuid.NAMESPACE_DNS, app_name)), cura_license_file=str(source_loc.joinpath("packaging", "msi", "cura_license.rtf")), From 460df87d1d0ad4289b5cdcbefd6a669526f7eec5 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 27 Mar 2025 10:47:18 +0100 Subject: [PATCH 055/299] Indicates that changing option requires a restart CURA-12486 Also move the note at the bottom of the page, because now labels from different categories use it, and this is where people should look for it. --- resources/qml/Preferences/GeneralPage.qml | 27 +++++++++++------------ 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 62cab53a78..42469c6cf6 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -360,17 +360,6 @@ UM.PreferencesPage } } - UM.Label - { - id: languageCaption - - //: Language change warning - text: catalog.i18nc("@label", "*You will need to restart the application for these changes to have effect.") - wrapMode: Text.WordWrap - font.italic: true - - } - Item { //: Spacer @@ -705,7 +694,7 @@ UM.PreferencesPage UM.CheckBox { id: singleInstanceCheckbox - text: catalog.i18nc("@option:check","Use a single instance of Cura") + text: catalog.i18nc("@option:check","Use a single instance of Cura *") checked: boolCheck(UM.Preferences.getValue("cura/single_instance")) onCheckedChanged: UM.Preferences.setValue("cura/single_instance", checked) @@ -1101,8 +1090,6 @@ UM.PreferencesPage } } - - /* Multi-buildplate functionality is disabled because it's broken. See CURA-4975 for the ticket to remove it. Item { //: Spacer @@ -1110,6 +1097,18 @@ UM.PreferencesPage width: UM.Theme.getSize("default_margin").height } + UM.Label + { + id: languageCaption + + //: Language change warning + text: catalog.i18nc("@label", "*You will need to restart the application for these changes to have effect.") + wrapMode: Text.WordWrap + font.italic: true + } + + /* Multi-buildplate functionality is disabled because it's broken. See CURA-4975 for the ticket to remove it. + Label { font.bold: true From 0fd7766db3fabbf0416a37c8b30b2ecbc1049fb8 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 28 Mar 2025 14:14:27 +0100 Subject: [PATCH 056/299] Fix color-switching code which only worked until 27/03 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 9e1bc26239..28f45e7c24 100644 --- a/conanfile.py +++ b/conanfile.py @@ -570,9 +570,9 @@ class CuraConan(ConanFile): print(f"Could not find '{str(test_colors_path)}'. Won't generate rotating colors for alpha builds.") return if "alpha" in self.version: - biweekly_day = (datetime.now() - datetime(2025, 3, 14)).days with test_colors_path.open("r") as test_colors_file: test_colors = json.load(test_colors_file) + biweekly_day = (datetime.now() - datetime(2025, 3, 14)).days % len(test_colors) for theme_dir in Path(self.source_folder, "resources", "themes").iterdir(): if not theme_dir.is_dir(): continue From 1045dc976059f2c4a83103f33240d3e631083d11 Mon Sep 17 00:00:00 2001 From: Frederic Meeuwissen <13856291+Frederic98@users.noreply.github.com> Date: Mon, 31 Mar 2025 12:59:43 +0200 Subject: [PATCH 057/299] Add machine_nozzle_size to variants --- resources/variants/ultimaker_s3_aa04.inst.cfg | 1 + resources/variants/ultimaker_s3_bb04.inst.cfg | 1 + resources/variants/ultimaker_s5_aa04.inst.cfg | 1 + resources/variants/ultimaker_s5_bb04.inst.cfg | 1 + resources/variants/ultimaker_s7_aa04.inst.cfg | 1 + resources/variants/ultimaker_s7_bb04.inst.cfg | 1 + resources/variants/ultimaker_s8_bb04.inst.cfg | 1 + 7 files changed, 7 insertions(+) diff --git a/resources/variants/ultimaker_s3_aa04.inst.cfg b/resources/variants/ultimaker_s3_aa04.inst.cfg index 94d27e150b..e3f4aaff2b 100644 --- a/resources/variants/ultimaker_s3_aa04.inst.cfg +++ b/resources/variants/ultimaker_s3_aa04.inst.cfg @@ -12,6 +12,7 @@ type = variant brim_width = 7 machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = AA 0.4 +machine_nozzle_size = 0.4 machine_nozzle_tip_outer_diameter = 1.0 retraction_amount = 6.5 speed_print = 70 diff --git a/resources/variants/ultimaker_s3_bb04.inst.cfg b/resources/variants/ultimaker_s3_bb04.inst.cfg index 022b4f945c..7923a5a28e 100644 --- a/resources/variants/ultimaker_s3_bb04.inst.cfg +++ b/resources/variants/ultimaker_s3_bb04.inst.cfg @@ -15,6 +15,7 @@ acceleration_support_bottom = =math.ceil(acceleration_support_interface * 100 / acceleration_support_interface = =math.ceil(acceleration_support * 1500 / 2000) machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = BB 0.4 +machine_nozzle_size = 0.4 machine_nozzle_tip_outer_diameter = 1.0 speed_prime_tower = =math.ceil(speed_print * 10 / 35) speed_support = =math.ceil(speed_print * 25 / 35) diff --git a/resources/variants/ultimaker_s5_aa04.inst.cfg b/resources/variants/ultimaker_s5_aa04.inst.cfg index ef846a089d..69aae0757e 100644 --- a/resources/variants/ultimaker_s5_aa04.inst.cfg +++ b/resources/variants/ultimaker_s5_aa04.inst.cfg @@ -12,6 +12,7 @@ type = variant brim_width = 7 machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = AA 0.4 +machine_nozzle_size = 0.4 machine_nozzle_tip_outer_diameter = 1.0 retraction_amount = 6.5 speed_print = 70 diff --git a/resources/variants/ultimaker_s5_bb04.inst.cfg b/resources/variants/ultimaker_s5_bb04.inst.cfg index ce287e127b..294b39b8c7 100644 --- a/resources/variants/ultimaker_s5_bb04.inst.cfg +++ b/resources/variants/ultimaker_s5_bb04.inst.cfg @@ -15,6 +15,7 @@ acceleration_support_bottom = =math.ceil(acceleration_support_interface * 100 / acceleration_support_interface = =math.ceil(acceleration_support * 1500 / 2000) machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = BB 0.4 +machine_nozzle_size = 0.4 machine_nozzle_tip_outer_diameter = 1.0 speed_prime_tower = =math.ceil(speed_print * 10 / 35) speed_support = =math.ceil(speed_print * 25 / 35) diff --git a/resources/variants/ultimaker_s7_aa04.inst.cfg b/resources/variants/ultimaker_s7_aa04.inst.cfg index 7d5a08d117..ee4ebdceaf 100644 --- a/resources/variants/ultimaker_s7_aa04.inst.cfg +++ b/resources/variants/ultimaker_s7_aa04.inst.cfg @@ -12,6 +12,7 @@ type = variant brim_width = 7 machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = AA 0.4 +machine_nozzle_size = 0.4 machine_nozzle_tip_outer_diameter = 1.0 retraction_amount = 6.5 speed_print = 70 diff --git a/resources/variants/ultimaker_s7_bb04.inst.cfg b/resources/variants/ultimaker_s7_bb04.inst.cfg index 1bfa216167..18aa61ff4b 100644 --- a/resources/variants/ultimaker_s7_bb04.inst.cfg +++ b/resources/variants/ultimaker_s7_bb04.inst.cfg @@ -15,6 +15,7 @@ acceleration_support_bottom = =math.ceil(acceleration_support_interface * 100 / acceleration_support_interface = =math.ceil(acceleration_support * 1500 / 2000) machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = BB 0.4 +machine_nozzle_size = 0.4 machine_nozzle_tip_outer_diameter = 1.0 retraction_amount = 4.5 speed_prime_tower = =math.ceil(speed_print * 10 / 35) diff --git a/resources/variants/ultimaker_s8_bb04.inst.cfg b/resources/variants/ultimaker_s8_bb04.inst.cfg index 388ce27ec2..d92874e448 100644 --- a/resources/variants/ultimaker_s8_bb04.inst.cfg +++ b/resources/variants/ultimaker_s8_bb04.inst.cfg @@ -11,6 +11,7 @@ type = variant [values] machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = BB 0.4 +machine_nozzle_size = 0.4 machine_nozzle_tip_outer_diameter = 1.0 retraction_amount = 4.5 support_bottom_height = =layer_height * 2 From b295ca7d041776d2f7c06be4146fbac0e043424f Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 1 Apr 2025 15:10:27 +0200 Subject: [PATCH 058/299] Workaround for process-events during multiple http requests. Would not work otherwise, but that should have been true in the old situation then as well? CURA-12156 --- plugins/CuraDrive/src/CreateBackupJob.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/CuraDrive/src/CreateBackupJob.py b/plugins/CuraDrive/src/CreateBackupJob.py index 6297af305f..67083d2e83 100644 --- a/plugins/CuraDrive/src/CreateBackupJob.py +++ b/plugins/CuraDrive/src/CreateBackupJob.py @@ -98,7 +98,12 @@ class CreateBackupJob(Job): backup_meta_data["description"] = "{}.backup.{}.cura.zip".format(timestamp, backup_meta_data["cura_release"]) self._requestUploadSlot(backup_meta_data, len(self._backup_zip)) - self._job_done.wait() + # Note: One 'process events' call wasn't enough with the changed situation somehow. + active_done_check = False + while not active_done_check: + CuraApplication.getInstance().processEvents() + active_done_check = self._job_done.wait(0.02) + if self.backup_upload_error_message == "": self._upload_message.setText(catalog.i18nc("@info:backup_status", "Your backup has finished uploading.")) self._upload_message.setProgress(None) # Hide progress bar @@ -117,9 +122,6 @@ class CreateBackupJob(Job): "metadata": backup_metadata } }).encode() - - CuraApplication.getInstance().processEvents() # Needed?? - HttpRequestManager.getInstance().put( self._api_backup_url, data = payload, @@ -127,8 +129,6 @@ class CreateBackupJob(Job): error_callback = self._onUploadSlotCompleted, scope = self._json_cloud_scope) - CuraApplication.getInstance().processEvents() # Needed?? - def _onUploadSlotCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None) -> None: if HttpRequestManager.safeHttpStatus(reply) >= 300: replyText = HttpRequestManager.readText(reply) From 1e00176cace283d3ea84c2a91b43e28d33564c51 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 1 Apr 2025 15:12:14 +0200 Subject: [PATCH 059/299] Add basic definition for BambuLab X1 CURA-12074 --- resources/definitions/bambulabs_x1.def.json | 333 +++ .../bambulabs_x1_extruder_0.def.json | 16 + .../bambulabs_x1_extruder_1.def.json | 16 + .../bambulabs_x1_extruder_2.def.json | 16 + .../bambulabs_x1_extruder_3.def.json | 16 + resources/images/bambulabs-3dp-logo.png | Bin 0 -> 35459 bytes resources/meshes/bambulabs-3dp-X1.obj | 1999 +++++++++++++++++ .../bambulabs_x1_0.4_PLA_standard.inst.cfg | 15 + .../bambu/bambulabs_x1_normal.inst.cfg | 14 + .../bambulabs_x1c_0.4_PLA_standard.inst.cfg | 15 + .../variants/bambu/bambulabs_p1p_0.4.inst.cfg | 13 + .../variants/bambu/bambulabs_p1s_0.4.inst.cfg | 13 + .../variants/bambu/bambulabs_x1_0.4.inst.cfg | 13 + .../variants/bambu/bambulabs_x1c_0.4.inst.cfg | 13 + 14 files changed, 2492 insertions(+) create mode 100644 resources/definitions/bambulabs_x1.def.json create mode 100644 resources/extruders/bambulabs_x1_extruder_0.def.json create mode 100644 resources/extruders/bambulabs_x1_extruder_1.def.json create mode 100644 resources/extruders/bambulabs_x1_extruder_2.def.json create mode 100644 resources/extruders/bambulabs_x1_extruder_3.def.json create mode 100644 resources/images/bambulabs-3dp-logo.png create mode 100644 resources/meshes/bambulabs-3dp-X1.obj create mode 100644 resources/quality/bambu/bambulabs_x1_0.4_PLA_standard.inst.cfg create mode 100644 resources/quality/bambu/bambulabs_x1_normal.inst.cfg create mode 100644 resources/quality/bambu/bambulabs_x1c_0.4_PLA_standard.inst.cfg create mode 100644 resources/variants/bambu/bambulabs_p1p_0.4.inst.cfg create mode 100644 resources/variants/bambu/bambulabs_p1s_0.4.inst.cfg create mode 100644 resources/variants/bambu/bambulabs_x1_0.4.inst.cfg create mode 100644 resources/variants/bambu/bambulabs_x1c_0.4.inst.cfg diff --git a/resources/definitions/bambulabs_x1.def.json b/resources/definitions/bambulabs_x1.def.json new file mode 100644 index 0000000000..f43123407a --- /dev/null +++ b/resources/definitions/bambulabs_x1.def.json @@ -0,0 +1,333 @@ +{ + "version": 2, + "name": "BambuLabs X1", + "inherits": "fdmprinter", + "metadata": + { + "visible": true, + "author": "Mariska", + "manufacturer": "BambuLabs", + "file_formats": "text/x-gcode", + "platform": "bambulabs-3dp-X1.obj", + "has_machine_quality": true, + "has_material": true, + "has_variants": true, + "has_variant_buildplates": false, + "has_textured_buildplate": true, + "machine_extruder_trains": { + "0": "bambulabs_x1_extruder_0", + "1": "bambulabs_x1_extruder_1", + "2": "bambulabs_x1_extruder_2", + "3": "bambulabs_x1_extruder_3" + }, + "platform_offset": [ + -130, + 0, + 130 + ], + "platform_texture": "bambulabs-3dp-logo.png", + "preferred_variant_name": "X1C 0.4mm", + "weight": 3 + }, + "settings": { + "platform_adhesion": + { + "children": + { + "machine_buildplate": + { + "enabled": true, + "default_value": "textured_pei_plate", + "options": + { + "cool_plate": "Cool Plate", + "engineering_plate": "Engineering Plate", + "textured_pei_plate": "Textured PEI Plate", + "high_temp_plate": "High Temp Plate" + }, + "label": "Build Plate Type", + "description": "The type of the build plate installed on the printer.", + "type": "enum", + "settable_per_mesh": false, + "settable_per_extruder": false, + "settable_per_meshgroup": false + }, + "machine_scan_first_layer": + { + "label": "Scan the first layer", + "description": "Whether to scan the first layer for layer adhesion problems.", + "default_value": true, + "value": "machine_buildplate!='textured_pei_plate'", + "type": "bool", + "settable_per_mesh": false, + "settable_per_extruder": false, + "settable_per_meshgroup": false, + "enabled": true + } + } + }, + "material": + { + "children":{ + "material_max_flowrate": + { + "label": "Material Maximum Flowrate", + "description": "Maximum flowrate that the printer can extrude for the material", + "unit": "mm\u00b3/s", + "type": "float", + "default_value": 16, + "value": "16", + "minimum_value": "0", + "maximum_value": "machine_max_feedrate_e * (material_diameter/2)**2 * math.pi", + "enabled": true, + "settable_per_mesh": false, + "settable_per_extruder": true + } + } + } + }, + "overrides": + { + "line_width": { "value": 0.42 }, + "machine_acceleration": { "value": 10000 }, + "machine_center_is_zero": { "value": false }, + "machine_depth": { "value": 256 }, + "machine_end_gcode": { "default_value": "M400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos \nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of \"timelapse_record_flag\"\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (machine_height + 100.0) < 25}\n G1 Z{machine_height + 100.0} F600\n G1 Z{machine_height +98.0}\n{else}\n G1 Z250 F600\n G1 Z248\n{endif}\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X128 Y250 F3600\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\n" }, + "machine_extruder_count": { "value": 4 }, + "machine_heated_bed": { "value": true }, + "machine_height": { "value": 251 }, + "machine_nozzle_size": { "value": 0.4 }, + "machine_show_variants": { "value": true }, + "machine_start_gcode": { "default_value": ";===== machine: X1 =========================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_bed_temperature_layer_0} ;wait for bed temp\n\n;=========register first layer scan=====\n{if machine_scan_first_layer}\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T{initial_extruder_nr}\n G1 X54 F12000\n G1 Y265\n M400\nM621 S{initial_extruder_nr}A\nM620.1 E F{material_max_flowrate/2.4053*60} T{material_print_temperature, initial_extruder_nr}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{-machine_width/2 if machine_center_is_zero else initial_extruder_nr} Y{-machine_depth/2 if machine_center_is_zero else initial_extruder_nr} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if machine_scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{material_print_temperature, initial_extruder_nr}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y11 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n{if machine_buildplate=='textured_pei_plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if acceleration_wall_0 > 0, initial_extruder_nr}\n M204 S{acceleration_wall_0, initial_extruder_nr}\n {else}\n M204 S{acceleration_print, initial_extruder_nr}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{material_print_temperature, initial_extruder_nr} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60/4} C5.000 D{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60, initial_extruder_nr} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{material_print_temperature, initial_extruder_nr}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X185.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X190.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X195.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X200.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X205.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X210.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X215.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X220.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X225.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_amount, initial_extruder_nr} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_amount, initial_extruder_nr} F1800\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nG0 X253 E6.4 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.6) * 60, initial_extruder_nr}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" }, + "machine_use_extruder_offset_to_offset_coords": { "value": false }, + "machine_width": { "value": 256 }, + "material_diameter": { "value": 1.75 }, + "relative_extrusion": { "value": true }, + "retraction_speed": { "value": 30 }, + "speed_travel": + { + "maximum_value": "800", + "value": "500" + }, + "acceleration_infill": { "value": "acceleration_print" }, + "acceleration_layer_0": { "value": 2000 }, + "acceleration_prime_tower": { "value": "acceleration_print" }, + "acceleration_print": { "value": 20000 }, + "acceleration_print_layer_0": { "value": "acceleration_layer_0" }, + "acceleration_roofing": { "value": "acceleration_wall_0" }, + "acceleration_skirt_brim": { "value": "acceleration_layer_0" }, + "acceleration_support": { "value": "acceleration_print" }, + "acceleration_support_bottom": { "value": "acceleration_support_interface" }, + "acceleration_support_infill": { "value": "acceleration_support" }, + "acceleration_support_interface": { "value": "acceleration_support" }, + "acceleration_support_roof": { "value": "acceleration_support_interface" }, + "acceleration_topbottom": { "value": "acceleration_print" }, + "acceleration_travel": { "value": 20000 }, + "acceleration_travel_enabled": { "value": true }, + "acceleration_travel_layer_0": { "value": "acceleration_layer_0" }, + "acceleration_wall": { "value": "acceleration_print/8" }, + "acceleration_wall_0": { "value": "acceleration_wall" }, + "acceleration_wall_0_roofing": { "value": "acceleration_wall_0" }, + "acceleration_wall_x": { "value": "acceleration_print" }, + "acceleration_wall_x_roofing": { "value": "acceleration_wall" }, + "adhesion_type": { "value": "'skirt'" }, + "bottom_thickness": { "value": 0.6 }, + "bridge_skin_speed": + { + "unit": "mm/s", + "value": "bridge_wall_speed" + }, + "bridge_sparse_infill_max_density": { "value": 50 }, + "bridge_wall_min_length": { "value": 10 }, + "bridge_wall_speed": + { + "unit": "mm/s", + "value": 50 + }, + "cool_min_layer_time": { "value": 6 }, + "cool_min_speed": { "value": 6 }, + "cool_min_temperature": { "value": "material_print_temperature-15" }, + "default_material_print_temperature": { "maximum_value_warning": 320 }, + "extra_infill_lines_to_support_skins": { "value": "'walls_and_lines'" }, + "gradual_flow_enabled": { "value": false }, + "hole_xy_offset": { "value": 0.075 }, + "infill_overlap": { "value": 10 }, + "infill_pattern": { "value": "'zigzag' if infill_sparse_density > 80 else 'grid'" }, + "infill_sparse_density": { "value": 15 }, + "infill_wall_line_count": { "value": "1 if infill_sparse_density > 80 else 0" }, + "jerk_infill": { "value": "jerk_print" }, + "jerk_layer_0": { "value": "jerk_print/2" }, + "jerk_prime_tower": { "value": "jerk_print" }, + "jerk_print": { "value": "50" }, + "jerk_print_layer_0": { "value": "jerk_layer_0" }, + "jerk_roofing": { "value": "jerk_wall_0" }, + "jerk_skirt_brim": { "value": "jerk_layer_0" }, + "jerk_support": { "value": "jerk_print" }, + "jerk_support_bottom": { "value": "jerk_support_interface" }, + "jerk_support_infill": { "value": "jerk_support" }, + "jerk_support_interface": { "value": "jerk_support" }, + "jerk_support_roof": { "value": "jerk_support_interface" }, + "jerk_topbottom": { "value": "jerk_print" }, + "jerk_travel": { "value": 50 }, + "jerk_travel_enabled": { "value": true }, + "jerk_travel_layer_0": { "value": "jerk_travel" }, + "jerk_wall": { "value": "jerk_print/5" }, + "jerk_wall_0": { "value": "jerk_wall" }, + "jerk_wall_0_roofing": { "value": "jerk_wall_0" }, + "jerk_wall_x": { "value": "jerk_print" }, + "jerk_wall_x_roofing": { "value": "jerk_wall_0" }, + "machine_max_feedrate_e": { "value": 150 }, + "machine_max_feedrate_x": { "value": 500 }, + "machine_max_feedrate_y": { "value": 500 }, + "machine_max_feedrate_z": { "value": 15 }, + "machine_max_jerk_e": { "default_value": 100 }, + "machine_max_jerk_xy": { "default_value": 5000 }, + "machine_max_jerk_z": { "default_value": 100 }, + "machine_name": { "default_value": "BambuLabs Bambu X1" }, + "machine_nozzle_cool_down_speed": { "default_value": 1.3 }, + "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, + "max_skin_angle_for_expansion": { "value": 45 }, + "meshfix_maximum_resolution": { "value": 0.4 }, + "min_infill_area": { "default_value": 10 }, + "optimize_wall_printing_order": { "value": false }, + "retraction_amount": { "value": 0.5 }, + "retraction_combing_max_distance": { "value": 100 }, + "retraction_extra_prime_amount": { "value": 0.12 }, + "retraction_hop": { "value": 0.2 }, + "retraction_hop_after_extruder_switch_height": { "value": 2 }, + "retraction_hop_enabled": { "value": true }, + "retraction_min_travel": { "value": "5 if support_enable and support_structure=='tree' else line_width * 2" }, + "retraction_prime_speed": { "value": 15 }, + "skin_edge_support_thickness": { "value": 0 }, + "skin_material_flow": { "value": 95 }, + "skin_overlap": { "value": 0 }, + "skin_preshrink": { "value": 0 }, + "skirt_line_count": { "value": 5 }, + "small_skin_on_surface": { "value": false }, + "small_skin_width": { "value": 4 }, + "speed_infill": + { + "maximum_value_warning": 500, + "value": "speed_print" + }, + "speed_ironing": + { + "maximum_value_warning": 500, + "value": 20 + }, + "speed_layer_0": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_prime_tower": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_print": + { + "maximum_value_warning": 500, + "value": 300 + }, + "speed_print_layer_0": + { + "maximum_value_warning": 500, + "value": "speed_layer_0" + }, + "speed_roofing": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_skirt_brim": + { + "maximum_value_warning": 500, + "value": "speed_layer_0" + }, + "speed_support": + { + "maximum_value_warning": 500, + "value": "speed_wall_0" + }, + "speed_support_bottom": + { + "maximum_value_warning": 500, + "value": "speed_support_interface" + }, + "speed_support_infill": + { + "maximum_value_warning": 500, + "value": "speed_support" + }, + "speed_support_interface": + { + "maximum_value_warning": 500, + "value": 50 + }, + "speed_support_roof": + { + "maximum_value_warning": 500, + "value": "speed_support_interface" + }, + "speed_topbottom": + { + "maximum_value_warning": 500, + "value": "speed_print" + }, + "speed_travel": + { + "maximum_value": 500, + "value": 500 + }, + "speed_travel_layer_0": + { + "maximum_value": 500, + "value": 150 + }, + "speed_wall": + { + "maximum_value_warning": 500, + "value": "speed_print*2/3" + }, + "speed_wall_0": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_wall_0_roofing": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_wall_x": + { + "maximum_value_warning": 500, + "value": "speed_print" + }, + "speed_wall_x_roofing": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "support_brim_line_count": { "value": 5 }, + "support_density": { "value": 15 }, + "support_infill_rate": { "value": "80 if gradual_support_infill_steps != 0 else 15" }, + "support_pattern": { "value": "'gyroid'" }, + "support_structure": { "value": "'tree'" }, + "travel_avoid_other_parts": { "value": false }, + "wall_0_acceleration": { "value": 1000 }, + "wall_0_deceleration": { "value": 1000 }, + "wall_0_end_speed_ratio": { "value": 100 }, + "wall_0_speed_split_distance": { "value": 0.2 }, + "wall_0_start_speed_ratio": { "value": 100 }, + "wall_0_wipe_dist": { "value": 0 }, + "wall_material_flow": { "value": 95 }, + "wall_overhang_angle": { "value": 45 }, + "wall_overhang_speed_factor": { "value": 50 }, + "wall_x_material_flow": { "value": 100 }, + "z_seam_corner": { "value": "'z_seam_corner_weighted'" }, + "z_seam_position": { "value": "'backright'" }, + "z_seam_type": { "value": "'sharpest_corner'" } + } +} diff --git a/resources/extruders/bambulabs_x1_extruder_0.def.json b/resources/extruders/bambulabs_x1_extruder_0.def.json new file mode 100644 index 0000000000..57dd9bbdcf --- /dev/null +++ b/resources/extruders/bambulabs_x1_extruder_0.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulabs_x1", + "position": "0" + }, + "overrides": + { + "extruder_nr": { "default_value": 0 }, + "material_diameter": { "default_value": 1.75 }, + "machine_extruder_change_duration": { "default_value": 29 } + } +} diff --git a/resources/extruders/bambulabs_x1_extruder_1.def.json b/resources/extruders/bambulabs_x1_extruder_1.def.json new file mode 100644 index 0000000000..7b660260ee --- /dev/null +++ b/resources/extruders/bambulabs_x1_extruder_1.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulabs_x1", + "position": "1" + }, + "overrides": + { + "extruder_nr": { "default_value": 1 }, + "material_diameter": { "default_value": 1.75 }, + "machine_extruder_change_duration": { "default_value": 29 } + } +} diff --git a/resources/extruders/bambulabs_x1_extruder_2.def.json b/resources/extruders/bambulabs_x1_extruder_2.def.json new file mode 100644 index 0000000000..691d08c039 --- /dev/null +++ b/resources/extruders/bambulabs_x1_extruder_2.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulabs_x1", + "position": "2" + }, + "overrides": + { + "extruder_nr": { "default_value": 2 }, + "material_diameter": { "default_value": 1.75 }, + "machine_extruder_change_duration": { "default_value": 29 } + } +} diff --git a/resources/extruders/bambulabs_x1_extruder_3.def.json b/resources/extruders/bambulabs_x1_extruder_3.def.json new file mode 100644 index 0000000000..c9250b5be4 --- /dev/null +++ b/resources/extruders/bambulabs_x1_extruder_3.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulabs_x1", + "position": "3" + }, + "overrides": + { + "extruder_nr": { "default_value": 3 }, + "material_diameter": { "default_value": 1.75 }, + "machine_extruder_change_duration": { "default_value": 29 } + } +} diff --git a/resources/images/bambulabs-3dp-logo.png b/resources/images/bambulabs-3dp-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..930337a695fc0b8f9dd0824e0c7a1dfac16ea8b2 GIT binary patch literal 35459 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 Date: Tue, 1 Apr 2025 13:13:53 +0000 Subject: [PATCH 060/299] Apply printer-linter format --- resources/definitions/bambulabs_x1.def.json | 174 +++++++++--------- .../bambulabs_x1_extruder_0.def.json | 6 +- .../bambulabs_x1_extruder_1.def.json | 6 +- .../bambulabs_x1_extruder_2.def.json | 6 +- .../bambulabs_x1_extruder_3.def.json | 6 +- .../bambulabs_x1_0.4_PLA_standard.inst.cfg | 1 - .../bambu/bambulabs_x1_normal.inst.cfg | 29 +-- .../bambulabs_x1c_0.4_PLA_standard.inst.cfg | 1 - 8 files changed, 113 insertions(+), 116 deletions(-) diff --git a/resources/definitions/bambulabs_x1.def.json b/resources/definitions/bambulabs_x1.def.json index f43123407a..a08a69bdf0 100644 --- a/resources/definitions/bambulabs_x1.def.json +++ b/resources/definitions/bambulabs_x1.def.json @@ -11,15 +11,16 @@ "platform": "bambulabs-3dp-X1.obj", "has_machine_quality": true, "has_material": true, - "has_variants": true, - "has_variant_buildplates": false, "has_textured_buildplate": true, - "machine_extruder_trains": { - "0": "bambulabs_x1_extruder_0", - "1": "bambulabs_x1_extruder_1", - "2": "bambulabs_x1_extruder_2", - "3": "bambulabs_x1_extruder_3" - }, + "has_variant_buildplates": false, + "has_variants": true, + "machine_extruder_trains": + { + "0": "bambulabs_x1_extruder_0", + "1": "bambulabs_x1_extruder_1", + "2": "bambulabs_x1_extruder_2", + "3": "bambulabs_x1_extruder_3" + }, "platform_offset": [ -130, 0, @@ -29,87 +30,9 @@ "preferred_variant_name": "X1C 0.4mm", "weight": 3 }, - "settings": { - "platform_adhesion": - { - "children": - { - "machine_buildplate": - { - "enabled": true, - "default_value": "textured_pei_plate", - "options": - { - "cool_plate": "Cool Plate", - "engineering_plate": "Engineering Plate", - "textured_pei_plate": "Textured PEI Plate", - "high_temp_plate": "High Temp Plate" - }, - "label": "Build Plate Type", - "description": "The type of the build plate installed on the printer.", - "type": "enum", - "settable_per_mesh": false, - "settable_per_extruder": false, - "settable_per_meshgroup": false - }, - "machine_scan_first_layer": - { - "label": "Scan the first layer", - "description": "Whether to scan the first layer for layer adhesion problems.", - "default_value": true, - "value": "machine_buildplate!='textured_pei_plate'", - "type": "bool", - "settable_per_mesh": false, - "settable_per_extruder": false, - "settable_per_meshgroup": false, - "enabled": true - } - } - }, - "material": - { - "children":{ - "material_max_flowrate": - { - "label": "Material Maximum Flowrate", - "description": "Maximum flowrate that the printer can extrude for the material", - "unit": "mm\u00b3/s", - "type": "float", - "default_value": 16, - "value": "16", - "minimum_value": "0", - "maximum_value": "machine_max_feedrate_e * (material_diameter/2)**2 * math.pi", - "enabled": true, - "settable_per_mesh": false, - "settable_per_extruder": true - } - } - } - }, "overrides": { - "line_width": { "value": 0.42 }, - "machine_acceleration": { "value": 10000 }, - "machine_center_is_zero": { "value": false }, - "machine_depth": { "value": 256 }, - "machine_end_gcode": { "default_value": "M400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos \nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of \"timelapse_record_flag\"\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (machine_height + 100.0) < 25}\n G1 Z{machine_height + 100.0} F600\n G1 Z{machine_height +98.0}\n{else}\n G1 Z250 F600\n G1 Z248\n{endif}\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X128 Y250 F3600\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\n" }, - "machine_extruder_count": { "value": 4 }, - "machine_heated_bed": { "value": true }, - "machine_height": { "value": 251 }, - "machine_nozzle_size": { "value": 0.4 }, - "machine_show_variants": { "value": true }, - "machine_start_gcode": { "default_value": ";===== machine: X1 =========================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_bed_temperature_layer_0} ;wait for bed temp\n\n;=========register first layer scan=====\n{if machine_scan_first_layer}\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T{initial_extruder_nr}\n G1 X54 F12000\n G1 Y265\n M400\nM621 S{initial_extruder_nr}A\nM620.1 E F{material_max_flowrate/2.4053*60} T{material_print_temperature, initial_extruder_nr}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{-machine_width/2 if machine_center_is_zero else initial_extruder_nr} Y{-machine_depth/2 if machine_center_is_zero else initial_extruder_nr} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if machine_scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{material_print_temperature, initial_extruder_nr}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y11 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n{if machine_buildplate=='textured_pei_plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if acceleration_wall_0 > 0, initial_extruder_nr}\n M204 S{acceleration_wall_0, initial_extruder_nr}\n {else}\n M204 S{acceleration_print, initial_extruder_nr}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{material_print_temperature, initial_extruder_nr} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60/4} C5.000 D{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60, initial_extruder_nr} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{material_print_temperature, initial_extruder_nr}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X185.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X190.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X195.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X200.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X205.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X210.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X215.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X220.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X225.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_amount, initial_extruder_nr} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_amount, initial_extruder_nr} F1800\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nG0 X253 E6.4 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.6) * 60, initial_extruder_nr}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" }, - "machine_use_extruder_offset_to_offset_coords": { "value": false }, - "machine_width": { "value": 256 }, - "material_diameter": { "value": 1.75 }, - "relative_extrusion": { "value": true }, - "retraction_speed": { "value": 30 }, - "speed_travel": - { - "maximum_value": "800", - "value": "500" - }, - "acceleration_infill": { "value": "acceleration_print" }, + "acceleration_infill": { "value": "acceleration_print" }, "acceleration_layer_0": { "value": 2000 }, "acceleration_prime_tower": { "value": "acceleration_print" }, "acceleration_print": { "value": 20000 }, @@ -176,6 +99,14 @@ "jerk_wall_0_roofing": { "value": "jerk_wall_0" }, "jerk_wall_x": { "value": "jerk_print" }, "jerk_wall_x_roofing": { "value": "jerk_wall_0" }, + "line_width": { "value": 0.42 }, + "machine_acceleration": { "value": 10000 }, + "machine_center_is_zero": { "value": false }, + "machine_depth": { "value": 256 }, + "machine_end_gcode": { "default_value": "M400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos \nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of \"timelapse_record_flag\"\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (machine_height + 100.0) < 25}\n G1 Z{machine_height + 100.0} F600\n G1 Z{machine_height +98.0}\n{else}\n G1 Z250 F600\n G1 Z248\n{endif}\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X128 Y250 F3600\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\n" }, + "machine_extruder_count": { "value": 4 }, + "machine_heated_bed": { "value": true }, + "machine_height": { "value": 251 }, "machine_max_feedrate_e": { "value": 150 }, "machine_max_feedrate_x": { "value": 500 }, "machine_max_feedrate_y": { "value": 500 }, @@ -186,10 +117,17 @@ "machine_name": { "default_value": "BambuLabs Bambu X1" }, "machine_nozzle_cool_down_speed": { "default_value": 1.3 }, "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, + "machine_nozzle_size": { "value": 0.4 }, + "machine_show_variants": { "value": true }, + "machine_start_gcode": { "default_value": ";===== machine: X1 =========================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_bed_temperature_layer_0} ;wait for bed temp\n\n;=========register first layer scan=====\n{if machine_scan_first_layer}\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T{initial_extruder_nr}\n G1 X54 F12000\n G1 Y265\n M400\nM621 S{initial_extruder_nr}A\nM620.1 E F{material_max_flowrate/2.4053*60} T{material_print_temperature, initial_extruder_nr}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{-machine_width/2 if machine_center_is_zero else initial_extruder_nr} Y{-machine_depth/2 if machine_center_is_zero else initial_extruder_nr} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if machine_scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{material_print_temperature, initial_extruder_nr}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y11 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n{if machine_buildplate=='textured_pei_plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if acceleration_wall_0 > 0, initial_extruder_nr}\n M204 S{acceleration_wall_0, initial_extruder_nr}\n {else}\n M204 S{acceleration_print, initial_extruder_nr}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{material_print_temperature, initial_extruder_nr} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60/4} C5.000 D{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60, initial_extruder_nr} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{material_print_temperature, initial_extruder_nr}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X185.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X190.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X195.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X200.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X205.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X210.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X215.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X220.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X225.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_amount, initial_extruder_nr} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_amount, initial_extruder_nr} F1800\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nG0 X253 E6.4 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.6) * 60, initial_extruder_nr}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" }, + "machine_use_extruder_offset_to_offset_coords": { "value": false }, + "machine_width": { "value": 256 }, + "material_diameter": { "value": 1.75 }, "max_skin_angle_for_expansion": { "value": 45 }, "meshfix_maximum_resolution": { "value": 0.4 }, "min_infill_area": { "default_value": 10 }, "optimize_wall_printing_order": { "value": false }, + "relative_extrusion": { "value": true }, "retraction_amount": { "value": 0.5 }, "retraction_combing_max_distance": { "value": 100 }, "retraction_extra_prime_amount": { "value": 0.12 }, @@ -198,6 +136,7 @@ "retraction_hop_enabled": { "value": true }, "retraction_min_travel": { "value": "5 if support_enable and support_structure=='tree' else line_width * 2" }, "retraction_prime_speed": { "value": 15 }, + "retraction_speed": { "value": 30 }, "skin_edge_support_thickness": { "value": 0 }, "skin_material_flow": { "value": 95 }, "skin_overlap": { "value": 0 }, @@ -329,5 +268,64 @@ "z_seam_corner": { "value": "'z_seam_corner_weighted'" }, "z_seam_position": { "value": "'backright'" }, "z_seam_type": { "value": "'sharpest_corner'" } + }, + "settings": + { + "material": + { + "children": + { + "material_max_flowrate": + { + "default_value": 16, + "description": "Maximum flowrate that the printer can extrude for the material", + "enabled": true, + "label": "Material Maximum Flowrate", + "maximum_value": "machine_max_feedrate_e * (material_diameter/2)**2 * math.pi", + "minimum_value": "0", + "settable_per_extruder": true, + "settable_per_mesh": false, + "type": "float", + "unit": "mm\u00b3/s", + "value": "16" + } + } + }, + "platform_adhesion": + { + "children": + { + "machine_buildplate": + { + "default_value": "textured_pei_plate", + "description": "The type of the build plate installed on the printer.", + "enabled": true, + "label": "Build Plate Type", + "options": + { + "cool_plate": "Cool Plate", + "engineering_plate": "Engineering Plate", + "high_temp_plate": "High Temp Plate", + "textured_pei_plate": "Textured PEI Plate" + }, + "settable_per_extruder": false, + "settable_per_mesh": false, + "settable_per_meshgroup": false, + "type": "enum" + }, + "machine_scan_first_layer": + { + "default_value": true, + "description": "Whether to scan the first layer for layer adhesion problems.", + "enabled": true, + "label": "Scan the first layer", + "settable_per_extruder": false, + "settable_per_mesh": false, + "settable_per_meshgroup": false, + "type": "bool", + "value": "machine_buildplate!='textured_pei_plate'" + } + } + } } -} +} \ No newline at end of file diff --git a/resources/extruders/bambulabs_x1_extruder_0.def.json b/resources/extruders/bambulabs_x1_extruder_0.def.json index 57dd9bbdcf..213ba9dde5 100644 --- a/resources/extruders/bambulabs_x1_extruder_0.def.json +++ b/resources/extruders/bambulabs_x1_extruder_0.def.json @@ -10,7 +10,7 @@ "overrides": { "extruder_nr": { "default_value": 0 }, - "material_diameter": { "default_value": 1.75 }, - "machine_extruder_change_duration": { "default_value": 29 } + "machine_extruder_change_duration": { "default_value": 29 }, + "material_diameter": { "default_value": 1.75 } } -} +} \ No newline at end of file diff --git a/resources/extruders/bambulabs_x1_extruder_1.def.json b/resources/extruders/bambulabs_x1_extruder_1.def.json index 7b660260ee..07a4371240 100644 --- a/resources/extruders/bambulabs_x1_extruder_1.def.json +++ b/resources/extruders/bambulabs_x1_extruder_1.def.json @@ -10,7 +10,7 @@ "overrides": { "extruder_nr": { "default_value": 1 }, - "material_diameter": { "default_value": 1.75 }, - "machine_extruder_change_duration": { "default_value": 29 } + "machine_extruder_change_duration": { "default_value": 29 }, + "material_diameter": { "default_value": 1.75 } } -} +} \ No newline at end of file diff --git a/resources/extruders/bambulabs_x1_extruder_2.def.json b/resources/extruders/bambulabs_x1_extruder_2.def.json index 691d08c039..833243d6fb 100644 --- a/resources/extruders/bambulabs_x1_extruder_2.def.json +++ b/resources/extruders/bambulabs_x1_extruder_2.def.json @@ -10,7 +10,7 @@ "overrides": { "extruder_nr": { "default_value": 2 }, - "material_diameter": { "default_value": 1.75 }, - "machine_extruder_change_duration": { "default_value": 29 } + "machine_extruder_change_duration": { "default_value": 29 }, + "material_diameter": { "default_value": 1.75 } } -} +} \ No newline at end of file diff --git a/resources/extruders/bambulabs_x1_extruder_3.def.json b/resources/extruders/bambulabs_x1_extruder_3.def.json index c9250b5be4..5e434c06a7 100644 --- a/resources/extruders/bambulabs_x1_extruder_3.def.json +++ b/resources/extruders/bambulabs_x1_extruder_3.def.json @@ -10,7 +10,7 @@ "overrides": { "extruder_nr": { "default_value": 3 }, - "material_diameter": { "default_value": 1.75 }, - "machine_extruder_change_duration": { "default_value": 29 } + "machine_extruder_change_duration": { "default_value": 29 }, + "material_diameter": { "default_value": 1.75 } } -} +} \ No newline at end of file diff --git a/resources/quality/bambu/bambulabs_x1_0.4_PLA_standard.inst.cfg b/resources/quality/bambu/bambulabs_x1_0.4_PLA_standard.inst.cfg index ab1d68e1ef..e0c4b3e9cb 100644 --- a/resources/quality/bambu/bambulabs_x1_0.4_PLA_standard.inst.cfg +++ b/resources/quality/bambu/bambulabs_x1_0.4_PLA_standard.inst.cfg @@ -12,4 +12,3 @@ variant = X1 0.4mm [values] - diff --git a/resources/quality/bambu/bambulabs_x1_normal.inst.cfg b/resources/quality/bambu/bambulabs_x1_normal.inst.cfg index c093e41f08..524031f31b 100644 --- a/resources/quality/bambu/bambulabs_x1_normal.inst.cfg +++ b/resources/quality/bambu/bambulabs_x1_normal.inst.cfg @@ -1,14 +1,15 @@ -[general] -definition = bambulabs_x1 -name = Normal -version = 4 - -[metadata] -global_quality = True -quality_type = normal -setting_version = 22 -type = quality -weight = 0 - -[values] -layer_height = 0.2 +[general] +definition = bambulabs_x1 +name = Normal +version = 4 + +[metadata] +global_quality = True +quality_type = normal +setting_version = 22 +type = quality +weight = 0 + +[values] +layer_height = 0.2 + diff --git a/resources/quality/bambu/bambulabs_x1c_0.4_PLA_standard.inst.cfg b/resources/quality/bambu/bambulabs_x1c_0.4_PLA_standard.inst.cfg index 372c959c0b..f820de5ece 100644 --- a/resources/quality/bambu/bambulabs_x1c_0.4_PLA_standard.inst.cfg +++ b/resources/quality/bambu/bambulabs_x1c_0.4_PLA_standard.inst.cfg @@ -12,4 +12,3 @@ variant = X1C 0.4mm [values] - From 86edf25403f0bdb5f02cbea8b07e14f9581b564e Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 1 Apr 2025 15:35:30 +0200 Subject: [PATCH 061/299] Fix initial bed leveling position CURA-12074 --- resources/definitions/bambulabs_x1.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/bambulabs_x1.def.json b/resources/definitions/bambulabs_x1.def.json index a08a69bdf0..0a4fb3effb 100644 --- a/resources/definitions/bambulabs_x1.def.json +++ b/resources/definitions/bambulabs_x1.def.json @@ -119,7 +119,7 @@ "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, "machine_nozzle_size": { "value": 0.4 }, "machine_show_variants": { "value": true }, - "machine_start_gcode": { "default_value": ";===== machine: X1 =========================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_bed_temperature_layer_0} ;wait for bed temp\n\n;=========register first layer scan=====\n{if machine_scan_first_layer}\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T{initial_extruder_nr}\n G1 X54 F12000\n G1 Y265\n M400\nM621 S{initial_extruder_nr}A\nM620.1 E F{material_max_flowrate/2.4053*60} T{material_print_temperature, initial_extruder_nr}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{-machine_width/2 if machine_center_is_zero else initial_extruder_nr} Y{-machine_depth/2 if machine_center_is_zero else initial_extruder_nr} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if machine_scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{material_print_temperature, initial_extruder_nr}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y11 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n{if machine_buildplate=='textured_pei_plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if acceleration_wall_0 > 0, initial_extruder_nr}\n M204 S{acceleration_wall_0, initial_extruder_nr}\n {else}\n M204 S{acceleration_print, initial_extruder_nr}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{material_print_temperature, initial_extruder_nr} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60/4} C5.000 D{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60, initial_extruder_nr} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{material_print_temperature, initial_extruder_nr}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X185.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X190.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X195.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X200.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X205.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X210.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X215.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X220.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X225.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_amount, initial_extruder_nr} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_amount, initial_extruder_nr} F1800\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nG0 X253 E6.4 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.6) * 60, initial_extruder_nr}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" }, + "machine_start_gcode": { "default_value": ";===== machine: X1 =========================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_bed_temperature_layer_0} ;wait for bed temp\n\n;=========register first layer scan=====\n{if machine_scan_first_layer}\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T{initial_extruder_nr}\n G1 X54 F12000\n G1 Y265\n M400\nM621 S{initial_extruder_nr}A\nM620.1 E F{material_max_flowrate/2.4053*60} T{material_print_temperature, initial_extruder_nr}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if machine_scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{material_print_temperature, initial_extruder_nr}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y11 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n{if machine_buildplate=='textured_pei_plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if acceleration_wall_0 > 0, initial_extruder_nr}\n M204 S{acceleration_wall_0, initial_extruder_nr}\n {else}\n M204 S{acceleration_print, initial_extruder_nr}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{material_print_temperature, initial_extruder_nr} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60/4} C5.000 D{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60, initial_extruder_nr} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{material_print_temperature, initial_extruder_nr}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X185.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X190.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X195.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X200.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X205.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X210.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X215.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X220.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X225.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_amount, initial_extruder_nr} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_amount, initial_extruder_nr} F1800\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nG0 X253 E6.4 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.6) * 60, initial_extruder_nr}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" }, "machine_use_extruder_offset_to_offset_coords": { "value": false }, "machine_width": { "value": 256 }, "material_diameter": { "value": 1.75 }, From c857dab0f76196a803871da1b10a331458b262ee Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 1 Apr 2025 16:47:17 +0200 Subject: [PATCH 062/299] Logging (mostly on errors). CURA-12156 --- plugins/CuraDrive/src/RestoreBackupJob.py | 42 ++++++++++++++--------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/plugins/CuraDrive/src/RestoreBackupJob.py b/plugins/CuraDrive/src/RestoreBackupJob.py index c5fd1fceae..e7cd66daf8 100644 --- a/plugins/CuraDrive/src/RestoreBackupJob.py +++ b/plugins/CuraDrive/src/RestoreBackupJob.py @@ -1,11 +1,8 @@ -# Copyright (c) 2021 Ultimaker B.V. +# Copyright (c) 2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. -import tempfile - -import json - import base64 import hashlib +import json import os import threading from tempfile import NamedTemporaryFile @@ -49,7 +46,6 @@ class RestoreBackupJob(Job): self.restore_backup_error_message = "" def run(self) -> None: - url = self._backup.get("download_url") assert url is not None @@ -59,7 +55,11 @@ class RestoreBackupJob(Job): error_callback = self._onRestoreRequestCompleted ) - self._job_done.wait() # A job is considered finished when the run function completes + # Note: Just to be sure, use the same structure here as in CreateBackupJob. + active_done_check = False + while not active_done_check: + CuraApplication.getInstance().processEvents() + active_done_check = self._job_done.wait(0.02) def _onRestoreRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None) -> None: if not HttpRequestManager.replyIndicatesSuccess(reply, error): @@ -80,7 +80,7 @@ class RestoreBackupJob(Job): bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE) app.processEvents() except EnvironmentError as e: - Logger.log("e", f"Unable to save backed up files due to computer limitations: {str(e)}") + Logger.error(f"Unable to save backed up files due to computer limitations: {str(e)}") self.restore_backup_error_message = self.DEFAULT_ERROR_MESSAGE self._job_done.set() return @@ -88,8 +88,10 @@ class RestoreBackupJob(Job): if not self._verifyMd5Hash(self._temporary_backup_file.name, self._backup.get("md5_hash", "")): # Don't restore the backup if the MD5 hashes do not match. # This can happen if the download was interrupted. - Logger.log("w", "Remote and local MD5 hashes do not match, not restoring backup.") + Logger.error("Remote and local MD5 hashes do not match, not restoring backup.") self.restore_backup_error_message = self.DEFAULT_ERROR_MESSAGE + self._job_done.set() + return # Tell Cura to place the backup back in the user data folder. metadata = self._backup.get("metadata", {}) @@ -103,6 +105,8 @@ class RestoreBackupJob(Job): packages_path = os.path.abspath(os.path.join(os.path.abspath( Resources.getConfigStoragePath()), "..", version_str, "packages.json")) if not os.path.exists(packages_path): + Logger.error(f"Can't find path '{packages_path}' to tell what packages should be redownloaded.") + self.restore_backup_error_message = self.DEFAULT_ERROR_MESSAGE self._job_done.set() return @@ -113,9 +117,13 @@ class RestoreBackupJob(Job): if "to_install" in packages_json and "package_id" in packages_json["to_install"]: to_install.add(packages_json["to_install"]["package_id"]) except IOError as ex: - pass # TODO! (log + message) + Logger.error(f"Couldn't open '{packages_path}' because '{str(ex)}' to get packages to re-install.") + self.restore_backup_error_message = self.DEFAULT_ERROR_MESSAGE + self._job_done.set() + return if len(to_install) < 1: + Logger.info("No packages to reinstall, early out.") self._job_done.set() return @@ -127,24 +135,26 @@ class RestoreBackupJob(Job): to_install.remove(package_id) try: - with tempfile.NamedTemporaryFile(mode="wb+", suffix=".curapackage") as temp_file: + with NamedTemporaryFile(mode="wb+", suffix=".curapackage") as temp_file: bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE) while bytes_read: temp_file.write(bytes_read) bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE) - # self._app.processEvents() - # self._progress[package_id]["file_written"] = temp_file.name + CuraApplication.getInstance().processEvents() if not CuraApplication.getInstance().getPackageManager().installPackage(temp_file.name): redownload_errors.append(f"Couldn't install package '{package_id}'.") except IOError as ex: - redownload_errors.append(f"Couldn't read package '{package_id}' because '{ex}'.") + redownload_errors.append(f"Couldn't process package '{package_id}' because '{ex}'.") if len(to_install) < 1: if len(redownload_errors) == 0: + Logger.info("All packages redownloaded!") self._job_done.set() else: - print("|".join(redownload_errors)) # TODO: Message / Log instead. - self._job_done.set() # NOTE: Set job probably not the right call here... (depends on wether or not that in the end closes the app or not...) + msgs = "\n - ".join(redownload_errors) + Logger.error(f"Couldn't re-install at least one package(s) because: {msgs}") + self.restore_backup_error_message = self.DEFAULT_ERROR_MESSAGE + self._job_done.set() self._package_download_scope = UltimakerCloudScope(CuraApplication.getInstance()) for package_id in to_install: From 6458c17de5b2a92a3179e2747b75c6ea394f138e Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 2 Apr 2025 13:09:21 +0200 Subject: [PATCH 063/299] Save 'pluginless' bakcup correctly. - Fix: Save the tempfile to the archive under the 'original' name (it is a rewrite of) instead of saving it to the archive under it's own name, which skipped the original file completely in a sense (the info was there, but as a tempfile). - Fix: Also make sure the correct folders where ignored, as reinstall paths where the complete path, not the basename. part of CURA-12156 --- cura/Backups/Backup.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/cura/Backups/Backup.py b/cura/Backups/Backup.py index 1163169b94..a409c4c689 100644 --- a/cura/Backups/Backup.py +++ b/cura/Backups/Backup.py @@ -95,7 +95,7 @@ class Backup: # Restore the obfuscated settings self._illuminate(**secrets) - def _fillToInstallsJson(self, file_path: str, reinstall_on_restore: frozenset[str], add_to_archive: Callable[[str], None]) -> Optional[str]: + def _fillToInstallsJson(self, file_path: str, reinstall_on_restore: frozenset[str], add_to_archive: Callable[[str, str], None]) -> Optional[str]: """ Moves all plugin-data (in a config-file) for plugins that could be (re)installed from the Marketplace from 'installed' to 'to_installs' before adding that file to the archive. @@ -104,7 +104,7 @@ class Backup: :param file_path: Absolute path to the packages-file. :param reinstall_on_restore: A set of plugins that _can_ be reinstalled from the Marketplace. - :param add_to_archive: A function/lambda that takes a filename and adds it to the archive. + :param add_to_archive: A function/lambda that takes a filename and adds it to the archive (as the 2nd name). """ with open(file_path, "r") as file: data = json.load(file) @@ -117,7 +117,7 @@ class Backup: tmpfile = tempfile.NamedTemporaryFile(delete=False) with open(tmpfile.name, "w") as outfile: json.dump(data, outfile) - add_to_archive(tmpfile.name) + add_to_archive(tmpfile.name, file_path) return tmpfile.name return None @@ -144,18 +144,17 @@ class Backup: tmpfiles = [] try: archive = ZipFile(buffer, "w", ZIP_DEFLATED) - add_path_to_archive = lambda path: archive.write(path, path[len(root_path) + len(os.sep):]) + add_path_to_archive = lambda path, alt_path: archive.write(path, alt_path[len(root_path) + len(os.sep):]) for root, folders, files in os.walk(root_path, topdown=True): - folders[:] = [f for f in folders if f not in reinstall_instead_paths] for item_name in folders + files: absolute_path = os.path.join(root, item_name) - if ignore_string.search(absolute_path): + if ignore_string.search(absolute_path) or any([absolute_path.startswith(x) for x in reinstall_instead_paths]): continue if item_name == "packages.json": tmpfiles.append( self._fillToInstallsJson(absolute_path, reinstall_instead_ids, add_path_to_archive)) else: - add_path_to_archive(absolute_path) + add_path_to_archive(absolute_path, absolute_path) archive.close() for tmpfile_path in tmpfiles: try: From 1f4f432d49c2649521fde3233de4943bcacfb080 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 2 Apr 2025 13:13:25 +0200 Subject: [PATCH 064/299] Restore Backups: Fix reading which packages need to be reinstalled. Also save the version, so we can get the correct url when redownloading the package (see next commits). part of CURA-12156 --- plugins/CuraDrive/src/RestoreBackupJob.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/plugins/CuraDrive/src/RestoreBackupJob.py b/plugins/CuraDrive/src/RestoreBackupJob.py index e7cd66daf8..4127df7aa6 100644 --- a/plugins/CuraDrive/src/RestoreBackupJob.py +++ b/plugins/CuraDrive/src/RestoreBackupJob.py @@ -110,12 +110,17 @@ class RestoreBackupJob(Job): self._job_done.set() return - to_install = set() + to_install = {} try: with open(packages_path, "r") as packages_file: packages_json = json.load(packages_file) - if "to_install" in packages_json and "package_id" in packages_json["to_install"]: - to_install.add(packages_json["to_install"]["package_id"]) + if "to_install" in packages_json: + for package_data in packages_json["to_install"].values(): + if "package_info" not in package_data: + continue + package_info = package_data["package_info"] + if "package_id" in package_info and "sdk_version_semver" in package_info: + to_install[package_info["package_id"]] = package_info["sdk_version_semver"] except IOError as ex: Logger.error(f"Couldn't open '{packages_path}' because '{str(ex)}' to get packages to re-install.") self.restore_backup_error_message = self.DEFAULT_ERROR_MESSAGE @@ -132,7 +137,7 @@ class RestoreBackupJob(Job): def packageDownloadCallback(package_id: str, msg: "QNetworkReply", err: "QNetworkReply.NetworkError" = None) -> None: if err is not None or HttpRequestManager.safeHttpStatus(msg) != 200: redownload_errors.append(err) - to_install.remove(package_id) + del to_install[package_id] try: with NamedTemporaryFile(mode="wb+", suffix=".curapackage") as temp_file: From 43d9e1d522e449c9880428f7d7fd0f8f3a111073 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 2 Apr 2025 13:15:35 +0200 Subject: [PATCH 065/299] Restore Backups: Fix handling the (re)downloaded tempfile. Was opening the tempfile for handling when it was still open for writing. Also the wrong net-reply got used (reply instead of msg). part of CURA-12156 --- plugins/CuraDrive/src/RestoreBackupJob.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/CuraDrive/src/RestoreBackupJob.py b/plugins/CuraDrive/src/RestoreBackupJob.py index 4127df7aa6..aa48ca5c18 100644 --- a/plugins/CuraDrive/src/RestoreBackupJob.py +++ b/plugins/CuraDrive/src/RestoreBackupJob.py @@ -140,14 +140,15 @@ class RestoreBackupJob(Job): del to_install[package_id] try: - with NamedTemporaryFile(mode="wb+", suffix=".curapackage") as temp_file: - bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE) + with NamedTemporaryFile(mode="wb", suffix=".curapackage", delete=False) as temp_file: + bytes_read = msg.read(self.DISK_WRITE_BUFFER_SIZE) while bytes_read: temp_file.write(bytes_read) - bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE) + bytes_read = msg.read(self.DISK_WRITE_BUFFER_SIZE) CuraApplication.getInstance().processEvents() - if not CuraApplication.getInstance().getPackageManager().installPackage(temp_file.name): - redownload_errors.append(f"Couldn't install package '{package_id}'.") + temp_file.close() + if not CuraApplication.getInstance().getPackageManager().installPackage(temp_file.name): + redownload_errors.append(f"Couldn't install package '{package_id}'.") except IOError as ex: redownload_errors.append(f"Couldn't process package '{package_id}' because '{ex}'.") From 1fb89e0e7d80635e60ce4bf38e2b1853c66d4ac8 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 2 Apr 2025 13:19:01 +0200 Subject: [PATCH 066/299] Restore Backups: Correctly handle requests to redownload plugins. - Fix: Need to fill the package's API version into the (template) URL, instead of using latest. - Fix: Loop was closing over the package ID, which caused the recieving function to always only get the last handled package ID instead of the one it needed to handle. part of CURA-12156 --- plugins/CuraDrive/src/RestoreBackupJob.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/plugins/CuraDrive/src/RestoreBackupJob.py b/plugins/CuraDrive/src/RestoreBackupJob.py index aa48ca5c18..817d819abf 100644 --- a/plugins/CuraDrive/src/RestoreBackupJob.py +++ b/plugins/CuraDrive/src/RestoreBackupJob.py @@ -22,7 +22,7 @@ from cura.CuraApplication import CuraApplication from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope import cura.UltimakerCloud.UltimakerCloudConstants as UltimakerCloudConstants -PACKAGES_URL = f"{UltimakerCloudConstants.CuraCloudAPIRoot}/cura-packages/v{UltimakerCloudConstants.CuraCloudAPIVersion}/cura/v{CuraSDKVersion}/packages" +PACKAGES_URL_TEMPLATE = f"{UltimakerCloudConstants.CuraCloudAPIRoot}/cura-packages/v{UltimakerCloudConstants.CuraCloudAPIVersion}/cura/v{{0}}/packages/{{1}}/download" class RestoreBackupJob(Job): """Downloads a backup and overwrites local configuration with the backup. @@ -163,13 +163,15 @@ class RestoreBackupJob(Job): self._job_done.set() self._package_download_scope = UltimakerCloudScope(CuraApplication.getInstance()) - for package_id in to_install: - HttpRequestManager.getInstance().get( - f"{PACKAGES_URL}/{package_id}/download", - scope=self._package_download_scope, - callback=lambda msg: packageDownloadCallback(package_id, msg), - error_callback=lambda msg, err: packageDownloadCallback(package_id, msg, err) - ) + for package_id, package_api_version in to_install.items(): + def handlePackageId(package_id: str = package_id): + HttpRequestManager.getInstance().get( + PACKAGES_URL_TEMPLATE.format(package_api_version, package_id), + scope=self._package_download_scope, + callback=lambda msg: packageDownloadCallback(package_id, msg), + error_callback=lambda msg, err: packageDownloadCallback(package_id, msg, err) + ) + handlePackageId(package_id) @staticmethod def _verifyMd5Hash(file_path: str, known_hash: str) -> bool: From f31daee257d77debd4edcf11eb253d7c10c4db12 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 3 Apr 2025 11:53:42 +0200 Subject: [PATCH 067/299] Rename brand (without final S) and add A1 mini CURA-12074 --- .../definitions/bambulab_a1mini.def.json | 331 +++ ...ulabs_x1.def.json => bambulab_x1.def.json} | 16 +- .../bambulab_a1mini_extruder_0.def.json | 18 + .../bambulab_a1mini_extruder_1.def.json | 18 + .../bambulab_a1mini_extruder_2.def.json | 18 + .../bambulab_a1mini_extruder_3.def.json | 18 + .../extruders/bambulab_x1_extruder_0.def.json | 18 + ...f.json => bambulab_x1_extruder_1.def.json} | 2 +- ...f.json => bambulab_x1_extruder_2.def.json} | 2 +- ...f.json => bambulab_x1_extruder_3.def.json} | 2 +- .../bambulabs_x1_extruder_0.def.json | 16 - ...s-3dp-logo.png => bambulab-buildplate.png} | Bin resources/meshes/bambulab_a1mini.obj | 1978 +++++++++++++++++ .../{bambulabs-3dp-X1.obj => bambulab_x1.obj} | 0 .../bambulab_a1mini_0.4_PLA_standard.inst.cfg | 14 + .../bambu/bambulab_a1mini_normal.inst.cfg | 15 + ... => bambulab_x1_0.4_PLA_standard.inst.cfg} | 2 +- ...l.inst.cfg => bambulab_x1_normal.inst.cfg} | 2 +- ...=> bambulab_x1c_0.4_PLA_standard.inst.cfg} | 2 +- .../variants/bambu/bambulab_a1_0.4.inst.cfg | 13 + ...0.4.inst.cfg => bambulab_p1p_0.4.inst.cfg} | 2 +- ...0.4.inst.cfg => bambulab_p1s_0.4.inst.cfg} | 2 +- ..._0.4.inst.cfg => bambulab_x1_0.4.inst.cfg} | 2 +- ...0.4.inst.cfg => bambulab_x1c_0.4.inst.cfg} | 2 +- 24 files changed, 2459 insertions(+), 34 deletions(-) create mode 100644 resources/definitions/bambulab_a1mini.def.json rename resources/definitions/{bambulabs_x1.def.json => bambulab_x1.def.json} (99%) create mode 100644 resources/extruders/bambulab_a1mini_extruder_0.def.json create mode 100644 resources/extruders/bambulab_a1mini_extruder_1.def.json create mode 100644 resources/extruders/bambulab_a1mini_extruder_2.def.json create mode 100644 resources/extruders/bambulab_a1mini_extruder_3.def.json create mode 100644 resources/extruders/bambulab_x1_extruder_0.def.json rename resources/extruders/{bambulabs_x1_extruder_1.def.json => bambulab_x1_extruder_1.def.json} (90%) rename resources/extruders/{bambulabs_x1_extruder_2.def.json => bambulab_x1_extruder_2.def.json} (90%) rename resources/extruders/{bambulabs_x1_extruder_3.def.json => bambulab_x1_extruder_3.def.json} (90%) delete mode 100644 resources/extruders/bambulabs_x1_extruder_0.def.json rename resources/images/{bambulabs-3dp-logo.png => bambulab-buildplate.png} (100%) create mode 100644 resources/meshes/bambulab_a1mini.obj rename resources/meshes/{bambulabs-3dp-X1.obj => bambulab_x1.obj} (100%) create mode 100644 resources/quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg create mode 100644 resources/quality/bambu/bambulab_a1mini_normal.inst.cfg rename resources/quality/bambu/{bambulabs_x1_0.4_PLA_standard.inst.cfg => bambulab_x1_0.4_PLA_standard.inst.cfg} (86%) rename resources/quality/bambu/{bambulabs_x1_normal.inst.cfg => bambulab_x1_normal.inst.cfg} (86%) rename resources/quality/bambu/{bambulabs_x1c_0.4_PLA_standard.inst.cfg => bambulab_x1c_0.4_PLA_standard.inst.cfg} (86%) create mode 100644 resources/variants/bambu/bambulab_a1_0.4.inst.cfg rename resources/variants/bambu/{bambulabs_p1s_0.4.inst.cfg => bambulab_p1p_0.4.inst.cfg} (84%) rename resources/variants/bambu/{bambulabs_p1p_0.4.inst.cfg => bambulab_p1s_0.4.inst.cfg} (84%) rename resources/variants/bambu/{bambulabs_x1_0.4.inst.cfg => bambulab_x1_0.4.inst.cfg} (84%) rename resources/variants/bambu/{bambulabs_x1c_0.4.inst.cfg => bambulab_x1c_0.4.inst.cfg} (84%) diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json new file mode 100644 index 0000000000..b7dcec29f6 --- /dev/null +++ b/resources/definitions/bambulab_a1mini.def.json @@ -0,0 +1,331 @@ +{ + "version": 2, + "name": "BambuLab A1 mini", + "inherits": "fdmprinter", + "metadata": + { + "visible": true, + "author": "Mariska", + "manufacturer": "BambuLab", + "file_formats": "text/x-gcode", + "platform": "bambulab_a1mini.obj", + "has_machine_quality": true, + "has_material": true, + "has_textured_buildplate": true, + "has_variant_buildplates": false, + "has_variants": true, + "machine_extruder_trains": + { + "0": "bambulab_a1mini_extruder_0", + "1": "bambulab_a1mini_extruder_1", + "2": "bambulab_a1mini_extruder_2", + "3": "bambulab_a1mini_extruder_3" + }, + "platform_offset": [ + -90, + 0, + 90 + ], + "platform_texture": "bambulab-buildplate.png", + "preferred_variant_name": "X1C 0.4mm", + "weight": 3 + }, + "overrides": + { + "acceleration_infill": { "value": "acceleration_print" }, + "acceleration_layer_0": { "value": 2000 }, + "acceleration_prime_tower": { "value": "acceleration_print" }, + "acceleration_print": { "value": 20000 }, + "acceleration_print_layer_0": { "value": "acceleration_layer_0" }, + "acceleration_roofing": { "value": "acceleration_wall_0" }, + "acceleration_skirt_brim": { "value": "acceleration_layer_0" }, + "acceleration_support": { "value": "acceleration_print" }, + "acceleration_support_bottom": { "value": "acceleration_support_interface" }, + "acceleration_support_infill": { "value": "acceleration_support" }, + "acceleration_support_interface": { "value": "acceleration_support" }, + "acceleration_support_roof": { "value": "acceleration_support_interface" }, + "acceleration_topbottom": { "value": "acceleration_print" }, + "acceleration_travel": { "value": 20000 }, + "acceleration_travel_enabled": { "value": true }, + "acceleration_travel_layer_0": { "value": "acceleration_layer_0" }, + "acceleration_wall": { "value": "acceleration_print/8" }, + "acceleration_wall_0": { "value": "acceleration_wall" }, + "acceleration_wall_0_roofing": { "value": "acceleration_wall_0" }, + "acceleration_wall_x": { "value": "acceleration_print" }, + "acceleration_wall_x_roofing": { "value": "acceleration_wall" }, + "adhesion_type": { "value": "'skirt'" }, + "bottom_thickness": { "value": 0.6 }, + "bridge_skin_speed": + { + "unit": "mm/s", + "value": "bridge_wall_speed" + }, + "bridge_sparse_infill_max_density": { "value": 50 }, + "bridge_wall_min_length": { "value": 10 }, + "bridge_wall_speed": + { + "unit": "mm/s", + "value": 50 + }, + "cool_min_layer_time": { "value": 6 }, + "cool_min_speed": { "value": 6 }, + "cool_min_temperature": { "value": "material_print_temperature-15" }, + "default_material_print_temperature": { "maximum_value_warning": 320 }, + "extra_infill_lines_to_support_skins": { "value": "'walls_and_lines'" }, + "gradual_flow_enabled": { "value": false }, + "hole_xy_offset": { "value": 0.075 }, + "infill_overlap": { "value": 10 }, + "infill_pattern": { "value": "'zigzag' if infill_sparse_density > 80 else 'grid'" }, + "infill_sparse_density": { "value": 15 }, + "infill_wall_line_count": { "value": "1 if infill_sparse_density > 80 else 0" }, + "jerk_infill": { "value": "jerk_print" }, + "jerk_layer_0": { "value": "jerk_print/2" }, + "jerk_prime_tower": { "value": "jerk_print" }, + "jerk_print": { "value": "50" }, + "jerk_print_layer_0": { "value": "jerk_layer_0" }, + "jerk_roofing": { "value": "jerk_wall_0" }, + "jerk_skirt_brim": { "value": "jerk_layer_0" }, + "jerk_support": { "value": "jerk_print" }, + "jerk_support_bottom": { "value": "jerk_support_interface" }, + "jerk_support_infill": { "value": "jerk_support" }, + "jerk_support_interface": { "value": "jerk_support" }, + "jerk_support_roof": { "value": "jerk_support_interface" }, + "jerk_topbottom": { "value": "jerk_print" }, + "jerk_travel": { "value": 50 }, + "jerk_travel_enabled": { "value": true }, + "jerk_travel_layer_0": { "value": "jerk_travel" }, + "jerk_wall": { "value": "jerk_print/5" }, + "jerk_wall_0": { "value": "jerk_wall" }, + "jerk_wall_0_roofing": { "value": "jerk_wall_0" }, + "jerk_wall_x": { "value": "jerk_print" }, + "jerk_wall_x_roofing": { "value": "jerk_wall_0" }, + "line_width": { "value": 0.42 }, + "machine_acceleration": { "value": 10000 }, + "machine_center_is_zero": { "value": false }, + "machine_depth": { "value": 180 }, + "machine_end_gcode": { "default_value": "M400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos \nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of \"timelapse_record_flag\"\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (machine_height + 100.0) < 25}\n G1 Z{machine_height + 100.0} F600\n G1 Z{machine_height +98.0}\n{else}\n G1 Z250 F600\n G1 Z248\n{endif}\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X128 Y250 F3600\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\n" }, + "machine_extruder_count": { "value": 4 }, + "machine_heated_bed": { "value": true }, + "machine_height": { "value": 175 }, + "machine_max_feedrate_e": { "value": 150 }, + "machine_max_feedrate_x": { "value": 500 }, + "machine_max_feedrate_y": { "value": 500 }, + "machine_max_feedrate_z": { "value": 15 }, + "machine_max_jerk_e": { "default_value": 100 }, + "machine_max_jerk_xy": { "default_value": 5000 }, + "machine_max_jerk_z": { "default_value": 100 }, + "machine_name": { "default_value": "BambuLabs Bambu X1" }, + "machine_nozzle_cool_down_speed": { "default_value": 1.3 }, + "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, + "machine_nozzle_size": { "value": 0.4 }, + "machine_show_variants": { "value": true }, + "machine_start_gcode": { "default_value": ";===== machine: X1 =========================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_bed_temperature_layer_0} ;wait for bed temp\n\n;=========register first layer scan=====\n{if machine_scan_first_layer}\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T{initial_extruder_nr}\n G1 X54 F12000\n G1 Y265\n M400\nM621 S{initial_extruder_nr}A\nM620.1 E F{material_max_flowrate/2.4053*60} T{material_print_temperature, initial_extruder_nr}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if machine_scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{material_print_temperature, initial_extruder_nr}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y11 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n{if machine_buildplate=='textured_pei_plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if acceleration_wall_0 > 0, initial_extruder_nr}\n M204 S{acceleration_wall_0, initial_extruder_nr}\n {else}\n M204 S{acceleration_print, initial_extruder_nr}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{material_print_temperature, initial_extruder_nr} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60/4} C5.000 D{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60, initial_extruder_nr} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{material_print_temperature, initial_extruder_nr}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X185.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X190.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X195.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X200.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X205.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X210.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X215.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X220.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X225.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_amount, initial_extruder_nr} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_amount, initial_extruder_nr} F1800\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nG0 X253 E6.4 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.6) * 60, initial_extruder_nr}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" }, + "machine_use_extruder_offset_to_offset_coords": { "value": false }, + "machine_width": { "value": 180 }, + "material_diameter": { "value": 1.75 }, + "max_skin_angle_for_expansion": { "value": 45 }, + "meshfix_maximum_resolution": { "value": 0.4 }, + "min_infill_area": { "default_value": 10 }, + "optimize_wall_printing_order": { "value": false }, + "relative_extrusion": { "value": true }, + "retraction_amount": { "value": 0.5 }, + "retraction_combing_max_distance": { "value": 100 }, + "retraction_extra_prime_amount": { "value": 0.12 }, + "retraction_hop": { "value": 0.2 }, + "retraction_hop_after_extruder_switch_height": { "value": 2 }, + "retraction_hop_enabled": { "value": true }, + "retraction_min_travel": { "value": "5 if support_enable and support_structure=='tree' else line_width * 2" }, + "retraction_prime_speed": { "value": 15 }, + "retraction_speed": { "value": 30 }, + "skin_edge_support_thickness": { "value": 0 }, + "skin_material_flow": { "value": 95 }, + "skin_overlap": { "value": 0 }, + "skin_preshrink": { "value": 0 }, + "skirt_line_count": { "value": 5 }, + "small_skin_on_surface": { "value": false }, + "small_skin_width": { "value": 4 }, + "speed_infill": + { + "maximum_value_warning": 500, + "value": "speed_print" + }, + "speed_ironing": + { + "maximum_value_warning": 500, + "value": 20 + }, + "speed_layer_0": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_prime_tower": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_print": + { + "maximum_value_warning": 500, + "value": 300 + }, + "speed_print_layer_0": + { + "maximum_value_warning": 500, + "value": "speed_layer_0" + }, + "speed_roofing": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_skirt_brim": + { + "maximum_value_warning": 500, + "value": "speed_layer_0" + }, + "speed_support": + { + "maximum_value_warning": 500, + "value": "speed_wall_0" + }, + "speed_support_bottom": + { + "maximum_value_warning": 500, + "value": "speed_support_interface" + }, + "speed_support_infill": + { + "maximum_value_warning": 500, + "value": "speed_support" + }, + "speed_support_interface": + { + "maximum_value_warning": 500, + "value": 50 + }, + "speed_support_roof": + { + "maximum_value_warning": 500, + "value": "speed_support_interface" + }, + "speed_topbottom": + { + "maximum_value_warning": 500, + "value": "speed_print" + }, + "speed_travel": + { + "maximum_value": 500, + "value": 500 + }, + "speed_travel_layer_0": + { + "maximum_value": 500, + "value": 150 + }, + "speed_wall": + { + "maximum_value_warning": 500, + "value": "speed_print*2/3" + }, + "speed_wall_0": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_wall_0_roofing": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_wall_x": + { + "maximum_value_warning": 500, + "value": "speed_print" + }, + "speed_wall_x_roofing": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "support_brim_line_count": { "value": 5 }, + "support_density": { "value": 15 }, + "support_infill_rate": { "value": "80 if gradual_support_infill_steps != 0 else 15" }, + "support_pattern": { "value": "'gyroid'" }, + "support_structure": { "value": "'tree'" }, + "travel_avoid_other_parts": { "value": false }, + "wall_0_acceleration": { "value": 1000 }, + "wall_0_deceleration": { "value": 1000 }, + "wall_0_end_speed_ratio": { "value": 100 }, + "wall_0_speed_split_distance": { "value": 0.2 }, + "wall_0_start_speed_ratio": { "value": 100 }, + "wall_0_wipe_dist": { "value": 0 }, + "wall_material_flow": { "value": 95 }, + "wall_overhang_angle": { "value": 45 }, + "wall_overhang_speed_factor": { "value": 50 }, + "wall_x_material_flow": { "value": 100 }, + "z_seam_corner": { "value": "'z_seam_corner_weighted'" }, + "z_seam_position": { "value": "'backright'" }, + "z_seam_type": { "value": "'sharpest_corner'" } + }, + "settings": + { + "material": + { + "children": + { + "material_max_flowrate": + { + "default_value": 16, + "description": "Maximum flowrate that the printer can extrude for the material", + "enabled": true, + "label": "Material Maximum Flowrate", + "maximum_value": "machine_max_feedrate_e * (material_diameter/2)**2 * math.pi", + "minimum_value": "0", + "settable_per_extruder": true, + "settable_per_mesh": false, + "type": "float", + "unit": "mm\u00b3/s", + "value": "16" + } + } + }, + "platform_adhesion": + { + "children": + { + "machine_buildplate": + { + "default_value": "textured_pei_plate", + "description": "The type of the build plate installed on the printer.", + "enabled": true, + "label": "Build Plate Type", + "options": + { + "cool_plate": "Cool Plate", + "engineering_plate": "Engineering Plate", + "high_temp_plate": "High Temp Plate", + "textured_pei_plate": "Textured PEI Plate" + }, + "settable_per_extruder": false, + "settable_per_mesh": false, + "settable_per_meshgroup": false, + "type": "enum" + }, + "machine_scan_first_layer": + { + "default_value": true, + "description": "Whether to scan the first layer for layer adhesion problems.", + "enabled": true, + "label": "Scan the first layer", + "settable_per_extruder": false, + "settable_per_mesh": false, + "settable_per_meshgroup": false, + "type": "bool", + "value": "machine_buildplate!='textured_pei_plate'" + } + } + } + } +} \ No newline at end of file diff --git a/resources/definitions/bambulabs_x1.def.json b/resources/definitions/bambulab_x1.def.json similarity index 99% rename from resources/definitions/bambulabs_x1.def.json rename to resources/definitions/bambulab_x1.def.json index 0a4fb3effb..5f6523d72b 100644 --- a/resources/definitions/bambulabs_x1.def.json +++ b/resources/definitions/bambulab_x1.def.json @@ -1,14 +1,14 @@ { "version": 2, - "name": "BambuLabs X1", + "name": "BambuLab X1", "inherits": "fdmprinter", "metadata": { "visible": true, "author": "Mariska", - "manufacturer": "BambuLabs", + "manufacturer": "BambuLab", "file_formats": "text/x-gcode", - "platform": "bambulabs-3dp-X1.obj", + "platform": "bambulab_x1.obj", "has_machine_quality": true, "has_material": true, "has_textured_buildplate": true, @@ -16,17 +16,17 @@ "has_variants": true, "machine_extruder_trains": { - "0": "bambulabs_x1_extruder_0", - "1": "bambulabs_x1_extruder_1", - "2": "bambulabs_x1_extruder_2", - "3": "bambulabs_x1_extruder_3" + "0": "bambulab_x1_extruder_0", + "1": "bambulab_x1_extruder_1", + "2": "bambulab_x1_extruder_2", + "3": "bambulab_x1_extruder_3" }, "platform_offset": [ -130, 0, 130 ], - "platform_texture": "bambulabs-3dp-logo.png", + "platform_texture": "bambulab-buildplate.png", "preferred_variant_name": "X1C 0.4mm", "weight": 3 }, diff --git a/resources/extruders/bambulab_a1mini_extruder_0.def.json b/resources/extruders/bambulab_a1mini_extruder_0.def.json new file mode 100644 index 0000000000..63ceeb76d3 --- /dev/null +++ b/resources/extruders/bambulab_a1mini_extruder_0.def.json @@ -0,0 +1,18 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulabs_a1mini", + "position": "0" + }, + "overrides": + { + "extruder_nr": { "default_value": 0 }, + "machine_extruder_change_duration": { "default_value": 29 }, + "machine_extruder_end_code": { "default_value": "M104 S{material_standby_temperature}\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, + "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, + "material_diameter": { "default_value": 1.75 } + } +} \ No newline at end of file diff --git a/resources/extruders/bambulab_a1mini_extruder_1.def.json b/resources/extruders/bambulab_a1mini_extruder_1.def.json new file mode 100644 index 0000000000..ba4dc63cfe --- /dev/null +++ b/resources/extruders/bambulab_a1mini_extruder_1.def.json @@ -0,0 +1,18 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulabs_a1mini", + "position": "1" + }, + "overrides": + { + "extruder_nr": { "default_value": 0 }, + "machine_extruder_change_duration": { "default_value": 29 }, + "machine_extruder_end_code": { "default_value": "M104 S{material_standby_temperature}\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, + "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, + "material_diameter": { "default_value": 1.75 } + } +} \ No newline at end of file diff --git a/resources/extruders/bambulab_a1mini_extruder_2.def.json b/resources/extruders/bambulab_a1mini_extruder_2.def.json new file mode 100644 index 0000000000..7793b3e8a8 --- /dev/null +++ b/resources/extruders/bambulab_a1mini_extruder_2.def.json @@ -0,0 +1,18 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulabs_a1mini", + "position": "2" + }, + "overrides": + { + "extruder_nr": { "default_value": 0 }, + "machine_extruder_change_duration": { "default_value": 29 }, + "machine_extruder_end_code": { "default_value": "M104 S{material_standby_temperature}\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, + "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, + "material_diameter": { "default_value": 1.75 } + } +} \ No newline at end of file diff --git a/resources/extruders/bambulab_a1mini_extruder_3.def.json b/resources/extruders/bambulab_a1mini_extruder_3.def.json new file mode 100644 index 0000000000..15447f6f41 --- /dev/null +++ b/resources/extruders/bambulab_a1mini_extruder_3.def.json @@ -0,0 +1,18 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulabs_a1mini", + "position": "3" + }, + "overrides": + { + "extruder_nr": { "default_value": 0 }, + "machine_extruder_change_duration": { "default_value": 29 }, + "machine_extruder_end_code": { "default_value": "M104 S{material_standby_temperature}\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, + "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, + "material_diameter": { "default_value": 1.75 } + } +} \ No newline at end of file diff --git a/resources/extruders/bambulab_x1_extruder_0.def.json b/resources/extruders/bambulab_x1_extruder_0.def.json new file mode 100644 index 0000000000..c405dc6431 --- /dev/null +++ b/resources/extruders/bambulab_x1_extruder_0.def.json @@ -0,0 +1,18 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulab_x1", + "position": "0" + }, + "overrides": + { + "extruder_nr": { "default_value": 0 }, + "machine_extruder_change_duration": { "default_value": 29 }, + "machine_extruder_end_code": { "default_value": "M104 S{material_standby_temperature}\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, + "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, + "material_diameter": { "default_value": 1.75 } + } +} \ No newline at end of file diff --git a/resources/extruders/bambulabs_x1_extruder_1.def.json b/resources/extruders/bambulab_x1_extruder_1.def.json similarity index 90% rename from resources/extruders/bambulabs_x1_extruder_1.def.json rename to resources/extruders/bambulab_x1_extruder_1.def.json index 07a4371240..e5c305232a 100644 --- a/resources/extruders/bambulabs_x1_extruder_1.def.json +++ b/resources/extruders/bambulab_x1_extruder_1.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "bambulabs_x1", + "machine": "bambulab_x1", "position": "1" }, "overrides": diff --git a/resources/extruders/bambulabs_x1_extruder_2.def.json b/resources/extruders/bambulab_x1_extruder_2.def.json similarity index 90% rename from resources/extruders/bambulabs_x1_extruder_2.def.json rename to resources/extruders/bambulab_x1_extruder_2.def.json index 833243d6fb..8250fdebfc 100644 --- a/resources/extruders/bambulabs_x1_extruder_2.def.json +++ b/resources/extruders/bambulab_x1_extruder_2.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "bambulabs_x1", + "machine": "bambulab_x1", "position": "2" }, "overrides": diff --git a/resources/extruders/bambulabs_x1_extruder_3.def.json b/resources/extruders/bambulab_x1_extruder_3.def.json similarity index 90% rename from resources/extruders/bambulabs_x1_extruder_3.def.json rename to resources/extruders/bambulab_x1_extruder_3.def.json index 5e434c06a7..b2c6927d45 100644 --- a/resources/extruders/bambulabs_x1_extruder_3.def.json +++ b/resources/extruders/bambulab_x1_extruder_3.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "bambulabs_x1", + "machine": "bambulab_x1", "position": "3" }, "overrides": diff --git a/resources/extruders/bambulabs_x1_extruder_0.def.json b/resources/extruders/bambulabs_x1_extruder_0.def.json deleted file mode 100644 index 213ba9dde5..0000000000 --- a/resources/extruders/bambulabs_x1_extruder_0.def.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "version": 2, - "name": "Extruder", - "inherits": "fdmextruder", - "metadata": - { - "machine": "bambulabs_x1", - "position": "0" - }, - "overrides": - { - "extruder_nr": { "default_value": 0 }, - "machine_extruder_change_duration": { "default_value": 29 }, - "material_diameter": { "default_value": 1.75 } - } -} \ No newline at end of file diff --git a/resources/images/bambulabs-3dp-logo.png b/resources/images/bambulab-buildplate.png similarity index 100% rename from resources/images/bambulabs-3dp-logo.png rename to resources/images/bambulab-buildplate.png diff --git a/resources/meshes/bambulab_a1mini.obj b/resources/meshes/bambulab_a1mini.obj new file mode 100644 index 0000000000..5bddcd90a6 --- /dev/null +++ b/resources/meshes/bambulab_a1mini.obj @@ -0,0 +1,1978 @@ +# Blender 4.4.0 +# www.blender.org +mtllib bambulabs-a1mini.mtl +o bambulab_a1m +v 181.982834 180.261444 -0.600000 +v 181.982834 180.261459 0.000000 +v 182.000000 180.000000 0.000000 +v -2.000000 180.000000 0.000000 +v 182.000000 180.000000 -0.600000 +v 182.000000 -7.131783 0.000000 +v -2.000000 0.000000 0.000000 +v -1.982835 -0.261453 0.000000 +v 179.800003 -6.343558 0.000000 +v 49.852898 -2.600989 0.000000 +v 50.133736 -2.809235 0.000000 +v 162.852371 -2.814206 0.000000 +v 49.552856 -2.421132 0.000000 +v 49.236404 -2.271438 0.000000 +v 48.906788 -2.153522 0.000000 +v 48.567451 -2.068540 0.000000 +v 48.221615 -2.017208 0.000000 +v 47.871796 -2.000000 0.000000 +v 0.000000 -2.000000 0.000000 +v -0.261449 -1.982835 0.000000 +v -0.518171 -1.931701 0.000000 +v -0.765877 -1.847535 0.000000 +v -1.000370 -1.731819 0.000000 +v -1.217698 -1.586549 0.000000 +v -1.414195 -1.414204 0.000000 +v -1.586541 -1.217708 0.000000 +v -1.731813 -1.000380 0.000000 +v -1.847531 -0.765886 0.000000 +v -1.931700 -0.518178 0.000000 +v 171.138290 -2.814206 0.000000 +v 179.211777 -2.814206 0.000000 +v 179.342834 -2.828996 0.000000 +v 167.274673 -2.814206 0.000000 +v 179.800003 -3.402431 0.000000 +v 179.785217 -3.271375 0.000000 +v 179.741669 -3.147067 0.000000 +v 179.671616 -3.035642 0.000000 +v 179.578568 -2.942598 0.000000 +v 179.467148 -2.872545 0.000000 +v 181.931702 180.518173 -0.600000 +v 181.931702 180.518173 0.000000 +v -1.982835 180.261444 0.000000 +v 181.847534 180.765869 -0.600000 +v 181.847534 180.765884 0.000000 +v -1.931701 180.518173 0.000000 +v 181.731812 181.000366 -0.600000 +v 181.731812 181.000381 0.000000 +v -1.847535 180.765869 0.000000 +v 181.586548 181.217697 -0.600000 +v 181.586548 181.217712 0.000000 +v -1.731819 181.000366 0.000000 +v 181.414200 181.414200 -0.600000 +v 181.414200 181.414200 0.000000 +v -1.586549 181.217697 0.000000 +v 181.217712 181.586548 -0.600000 +v 181.217697 181.586548 0.000000 +v -1.414204 181.414200 0.000000 +v 181.000381 181.731812 -0.600000 +v 181.000366 181.731812 0.000000 +v -1.217708 181.586548 0.000000 +v 180.765884 181.847534 -0.600000 +v 180.765869 181.847534 0.000000 +v -1.000380 181.731812 0.000000 +v 180.518173 181.931702 -0.600000 +v 180.518173 181.931702 0.000000 +v -0.765886 181.847534 0.000000 +v 180.261459 181.982834 -0.600000 +v 180.261444 181.982834 0.000000 +v 148.928421 182.000000 0.000000 +v -0.518178 181.931702 0.000000 +v 180.000000 182.000000 -0.600000 +v 180.000000 182.000000 0.000000 +v 111.443146 182.000000 0.000000 +v 148.928421 182.000000 -0.600000 +v -0.518171 181.931702 -0.600000 +v 31.071573 182.000000 -0.600000 +v 68.556854 182.000000 -0.600000 +v 111.443146 182.000000 -0.600000 +v -0.261449 181.982834 -0.600000 +v 0.000000 182.000000 -0.600000 +v -0.765877 181.847534 -0.600000 +v -1.000370 181.731812 -0.600000 +v -1.217698 181.586548 -0.600000 +v -1.414195 181.414200 -0.600000 +v -1.586541 181.217712 -0.600000 +v -1.731813 181.000381 -0.600000 +v -1.847531 180.765884 -0.600000 +v -1.931700 180.518173 -0.600000 +v -1.982835 180.261459 -0.600000 +v 182.000000 -7.131783 -0.600000 +v -2.000000 180.000000 -0.600000 +v 179.671616 -3.035635 -0.600000 +v 179.741653 -3.147059 -0.600000 +v -2.000000 0.000000 -0.600000 +v -1.982835 -0.261449 -0.600000 +v -0.261453 181.982834 0.000000 +v 31.071573 182.000000 0.000000 +v 0.000000 182.000000 0.000000 +v 68.556854 182.000000 0.000000 +v 68.164452 182.019302 0.000000 +v 31.332619 182.017105 0.000000 +v 31.589205 182.068146 0.000000 +v 31.332619 182.017105 -0.600000 +v 67.776512 182.076889 0.000000 +v 31.836939 182.152237 0.000000 +v 31.589205 182.068146 -0.600000 +v 67.395866 182.172211 0.000000 +v 32.071579 182.267960 0.000000 +v 31.836939 182.152237 -0.600000 +v 67.026123 182.304489 0.000000 +v 32.289101 182.413300 0.000000 +v 32.071579 182.267960 -0.600000 +v 66.671143 182.472397 0.000000 +v 32.485786 182.585785 0.000000 +v 32.289101 182.413300 -0.600000 +v 61.780155 187.119843 0.000000 +v 37.019848 187.119843 0.000000 +v 32.485786 182.585785 -0.600000 +v 65.728424 183.171570 0.000000 +v 66.019547 182.907745 0.000000 +v 66.334579 182.674149 0.000000 +v 61.529186 187.344116 0.000000 +v 37.270813 187.344116 0.000000 +v 37.019848 187.119843 -0.600000 +v 61.254848 187.538727 0.000000 +v 37.545155 187.538727 0.000000 +v 37.270813 187.344116 -0.600000 +v 60.960442 187.701431 0.000000 +v 37.839558 187.701431 0.000000 +v 37.545155 187.538727 -0.600000 +v 60.649696 187.830139 0.000000 +v 38.150303 187.830139 0.000000 +v 37.839558 187.701431 -0.600000 +v 60.326481 187.923279 0.000000 +v 38.473522 187.923279 0.000000 +v 38.150303 187.830139 -0.600000 +v 59.994873 187.979645 0.000000 +v 38.805126 187.979645 0.000000 +v 38.473522 187.923279 -0.600000 +v 59.658833 187.998520 0.000000 +v 39.141167 187.998520 0.000000 +v 38.805126 187.979645 -0.600000 +v 39.141167 187.998520 -0.600000 +v 59.658833 187.998520 -0.600000 +v 59.994873 187.979645 -0.600000 +v 60.326481 187.923279 -0.600000 +v 60.649696 187.830139 -0.600000 +v 60.960442 187.701431 -0.600000 +v 61.254848 187.538727 -0.600000 +v 61.529186 187.344116 -0.600000 +v 61.780155 187.119843 -0.600000 +v 65.728424 183.171570 -0.600000 +v 66.019547 182.907745 -0.600000 +v 66.334579 182.674149 -0.600000 +v 66.671143 182.472397 -0.600000 +v 67.026123 182.304489 -0.600000 +v 67.395866 182.172211 -0.600000 +v 67.776512 182.076889 -0.600000 +v 68.164452 182.019302 -0.600000 +v 148.667389 182.017105 0.000000 +v 111.835548 182.019302 0.000000 +v 148.410797 182.068146 0.000000 +v 112.223488 182.076889 0.000000 +v 111.835548 182.019302 -0.600000 +v 148.163055 182.152237 0.000000 +v 112.604134 182.172211 0.000000 +v 112.223488 182.076889 -0.600000 +v 147.928421 182.267960 0.000000 +v 112.973877 182.304489 0.000000 +v 112.604134 182.172211 -0.600000 +v 147.710892 182.413300 0.000000 +v 113.328857 182.472397 0.000000 +v 112.973877 182.304489 -0.600000 +v 147.514221 182.585785 0.000000 +v 113.665421 182.674149 0.000000 +v 113.328857 182.472397 -0.600000 +v 142.980148 187.119843 0.000000 +v 113.980453 182.907745 0.000000 +v 113.665421 182.674149 -0.600000 +v 114.271576 183.171570 0.000000 +v 113.980453 182.907745 -0.600000 +v 118.219849 187.119843 0.000000 +v 114.271576 183.171570 -0.600000 +v 142.729187 187.344116 0.000000 +v 118.470818 187.344116 0.000000 +v 118.219849 187.119843 -0.600000 +v 142.454849 187.538727 0.000000 +v 118.745155 187.538727 0.000000 +v 118.470818 187.344116 -0.600000 +v 142.160446 187.701431 0.000000 +v 119.039558 187.701431 0.000000 +v 118.745155 187.538727 -0.600000 +v 141.849701 187.830139 0.000000 +v 119.350304 187.830139 0.000000 +v 119.039558 187.701431 -0.600000 +v 141.526474 187.923279 0.000000 +v 119.673523 187.923279 0.000000 +v 119.350304 187.830139 -0.600000 +v 141.194870 187.979645 0.000000 +v 120.005127 187.979645 0.000000 +v 119.673523 187.923279 -0.600000 +v 140.858826 187.998520 0.000000 +v 120.341164 187.998520 0.000000 +v 120.005127 187.979645 -0.600000 +v 120.341164 187.998520 -0.600000 +v 140.858826 187.998520 -0.600000 +v 141.194870 187.979645 -0.600000 +v 141.526474 187.923279 -0.600000 +v 141.849701 187.830139 -0.600000 +v 142.160446 187.701431 -0.600000 +v 142.454849 187.538727 -0.600000 +v 142.729187 187.344116 -0.600000 +v 142.980148 187.119843 -0.600000 +v 147.514221 182.585785 -0.600000 +v 147.710892 182.413300 -0.600000 +v 147.928421 182.267960 -0.600000 +v 148.163055 182.152237 -0.600000 +v 148.410797 182.068146 -0.600000 +v 148.667389 182.017105 -0.600000 +v 55.436195 -8.087358 0.000000 +v 181.982834 -7.393232 0.000000 +v 57.954765 -7.065864 0.000000 +v 179.211777 -6.931783 0.000000 +v 174.789474 -6.931783 0.000000 +v 179.342834 -6.916994 0.000000 +v 179.467133 -6.873447 0.000000 +v 179.578568 -6.803397 0.000000 +v 179.671616 -6.710354 0.000000 +v 179.741653 -6.598929 0.000000 +v 179.785217 -6.474618 0.000000 +v 181.931702 -7.649953 0.000000 +v 181.982834 -7.393236 -0.600000 +v 181.847534 -7.897660 0.000000 +v 181.931702 -7.649961 -0.600000 +v 181.731812 -8.132153 0.000000 +v 181.847534 -7.897669 -0.600000 +v 55.695721 -8.322548 0.000000 +v 181.586548 -8.349481 0.000000 +v 181.731812 -8.132162 -0.600000 +v 55.976562 -8.530794 0.000000 +v 181.414200 -8.545978 0.000000 +v 181.586548 -8.349491 -0.600000 +v 56.276600 -8.710651 0.000000 +v 181.217712 -8.718324 0.000000 +v 181.414200 -8.545987 -0.600000 +v 56.593052 -8.860345 0.000000 +v 181.000381 -8.863596 0.000000 +v 181.217697 -8.718331 -0.600000 +v 56.922668 -8.978261 0.000000 +v 180.765884 -8.979314 0.000000 +v 181.000366 -8.863602 -0.600000 +v 57.262009 -9.063243 0.000000 +v 180.518173 -9.063482 0.000000 +v 180.765869 -8.979318 -0.600000 +v 57.607841 -9.114575 0.000000 +v 180.261459 -9.114618 0.000000 +v 180.518173 -9.063484 -0.600000 +v 57.957661 -9.131783 0.000000 +v 180.000000 -9.131783 0.000000 +v 180.261444 -9.114618 -0.600000 +v 180.000000 -9.131783 -0.600000 +v 57.957661 -9.131783 -0.600000 +v 57.607841 -9.114575 -0.600000 +v 57.262009 -9.063243 -0.600000 +v 56.922668 -8.978261 -0.600000 +v 56.593052 -8.860345 -0.600000 +v 56.276600 -8.710651 -0.600000 +v 55.976562 -8.530794 -0.600000 +v 55.695721 -8.322548 -0.600000 +v 56.531078 -5.102371 0.000000 +v 50.393261 -3.044425 0.000000 +v 55.436195 -8.087358 -0.600000 +v 56.476082 -5.331511 0.000000 +v 56.457661 -5.565891 0.000000 +v 56.476318 -5.801738 0.000000 +v 56.531746 -6.031444 0.000000 +v 56.622189 -6.248860 0.000000 +v 56.744408 -6.447986 0.000000 +v 56.897247 -6.626748 0.000000 +v 57.076130 -6.779497 0.000000 +v 57.276272 -6.902172 0.000000 +v 57.492882 -6.992045 0.000000 +v 57.720848 -7.047056 0.000000 +v 50.393261 -3.044425 -0.600000 +v 57.726280 -4.083871 0.000000 +v 57.960556 -4.065919 0.000000 +v 162.322479 -3.147059 0.000000 +v 57.497280 -4.138318 0.000000 +v 57.279163 -4.228147 0.000000 +v 57.077423 -4.351354 0.000000 +v 56.897232 -4.505049 0.000000 +v 56.743641 -4.684847 0.000000 +v 56.621258 -4.884737 0.000000 +v 162.721313 -2.828995 0.000000 +v 162.597000 -2.872542 0.000000 +v 162.485580 -2.942592 0.000000 +v 162.392532 -3.035635 0.000000 +v 50.133736 -2.809235 -0.600000 +v 49.852898 -2.600989 -0.600000 +v 49.552856 -2.421132 -0.600000 +v 49.236404 -2.271438 -0.600000 +v 48.906788 -2.153522 -0.600000 +v 48.567451 -2.068540 -0.600000 +v 48.221615 -2.017208 -0.600000 +v 47.871796 -2.000000 -0.600000 +v 0.000000 -2.000000 -0.600000 +v -0.261453 -1.982835 -0.600000 +v -0.518178 -1.931700 -0.600000 +v -0.765886 -1.847531 -0.600000 +v -1.000380 -1.731813 -0.600000 +v -1.217708 -1.586541 -0.600000 +v -1.414204 -1.414195 -0.600000 +v -1.586549 -1.217698 -0.600000 +v -1.731819 -1.000370 -0.600000 +v -1.847535 -0.765877 -0.600000 +v -1.931701 -0.518171 -0.600000 +v 162.264145 -3.402431 0.000000 +v 59.439003 -5.330044 0.000000 +v 59.457661 -5.565891 0.000000 +v 59.457661 -5.565891 -0.600000 +v 59.439240 -5.800272 0.000000 +v 59.439003 -5.801738 -0.600000 +v 59.383575 -5.100339 0.000000 +v 59.384243 -5.102371 -0.600000 +v 59.439240 -5.331511 -0.600000 +v 59.293133 -4.882923 0.000000 +v 59.294064 -4.884737 -0.600000 +v 59.170914 -4.683797 0.000000 +v 59.171680 -4.684847 -0.600000 +v 59.018074 -4.505035 0.000000 +v 59.018089 -4.505049 -0.600000 +v 58.839191 -4.352286 0.000000 +v 58.639050 -4.229611 0.000000 +v 58.837898 -4.351354 -0.600000 +v 58.422440 -4.139738 0.000000 +v 58.636158 -4.228147 -0.600000 +v 58.194473 -4.084727 0.000000 +v 58.418041 -4.138318 -0.600000 +v 58.189041 -4.083871 -0.600000 +v 57.954765 -4.065919 -0.600000 +v 162.278931 -3.271371 0.000000 +v 57.720848 -4.084727 -0.600000 +v 57.492882 -4.139738 -0.600000 +v 57.276272 -4.229611 -0.600000 +v 57.076130 -4.352286 -0.600000 +v 56.744408 -4.683797 -0.600000 +v 56.897247 -4.505035 -0.600000 +v 56.622189 -4.882923 -0.600000 +v 56.531746 -5.100339 -0.600000 +v 56.476318 -5.330044 -0.600000 +v 56.457661 -5.565891 -0.600000 +v 56.531078 -6.029412 -0.600000 +v 56.476082 -5.800272 -0.600000 +v 56.621258 -6.247046 -0.600000 +v 56.743641 -6.446936 -0.600000 +v 56.897232 -6.626734 -0.600000 +v 57.077423 -6.780429 -0.600000 +v 57.279163 -6.903636 -0.600000 +v 57.497280 -6.993465 -0.600000 +v 57.726280 -7.047912 -0.600000 +v 170.925842 -6.931783 0.000000 +v 57.960556 -7.065864 -0.600000 +v 58.189041 -7.047912 0.000000 +v 162.852371 -6.931783 0.000000 +v 58.194473 -7.047056 -0.600000 +v 58.418041 -6.993465 0.000000 +v 162.721298 -6.916993 0.000000 +v 58.636158 -6.903636 0.000000 +v 58.422440 -6.992045 -0.600000 +v 162.485565 -6.803391 0.000000 +v 58.837898 -6.780429 0.000000 +v 58.639050 -6.902172 -0.600000 +v 162.597000 -6.873444 0.000000 +v 162.392532 -6.710347 0.000000 +v 59.018089 -6.626734 0.000000 +v 58.839191 -6.779497 -0.600000 +v 162.278931 -6.474614 0.000000 +v 59.171680 -6.446936 0.000000 +v 59.170914 -6.447986 -0.600000 +v 162.322479 -6.598922 0.000000 +v 59.018074 -6.626748 -0.600000 +v 162.264145 -6.343558 0.000000 +v 59.294064 -6.247046 0.000000 +v 59.293133 -6.248860 -0.600000 +v 59.384243 -6.029412 0.000000 +v 59.383575 -6.031444 -0.600000 +v 179.211777 -2.814206 -0.600000 +v 179.342834 -2.828995 -0.600000 +v 167.351654 -2.819277 0.000000 +v 171.047104 -2.828715 0.000000 +v 171.138290 -2.814206 -0.600000 +v 167.499771 -2.858983 0.000000 +v 170.965240 -2.870517 0.000000 +v 171.047104 -2.828715 -0.600000 +v 167.426849 -2.834250 0.000000 +v 167.568832 -2.893058 0.000000 +v 170.900497 -2.935263 0.000000 +v 170.965240 -2.870517 -0.600000 +v 167.690613 -2.986493 0.000000 +v 170.858688 -3.017124 0.000000 +v 170.900497 -2.935263 -0.600000 +v 167.632584 -2.935639 0.000000 +v 170.844177 -3.108319 0.000000 +v 170.858688 -3.017124 -0.600000 +v 171.133820 -6.429701 0.000000 +v 170.854202 -3.184409 0.000000 +v 170.844177 -3.108319 -0.600000 +v 170.883606 -3.255397 0.000000 +v 170.854202 -3.184409 -0.600000 +v 170.930328 -3.316288 0.000000 +v 170.883606 -3.255397 -0.600000 +v 171.219955 -6.637671 0.000000 +v 174.373535 -6.759496 0.000000 +v 170.930328 -3.316288 -0.600000 +v 171.209946 -6.561580 0.000000 +v 171.180542 -6.490592 0.000000 +v 171.163651 -6.810726 0.000000 +v 174.431549 -6.810350 0.000000 +v 174.373535 -6.759496 -0.600000 +v 171.205460 -6.728865 0.000000 +v 174.495316 -6.852931 0.000000 +v 174.431549 -6.810350 -0.600000 +v 171.098907 -6.875472 0.000000 +v 174.564362 -6.887006 0.000000 +v 174.495316 -6.852931 -0.600000 +v 171.017044 -6.917274 0.000000 +v 174.637283 -6.911739 0.000000 +v 174.564362 -6.887006 -0.600000 +v 174.712479 -6.926712 0.000000 +v 174.637283 -6.911739 -0.600000 +v 174.712479 -6.926712 -0.600000 +v 174.789474 -6.931783 -0.600000 +v 179.211777 -6.931783 -0.600000 +v 179.342834 -6.916993 -0.600000 +v 179.467148 -6.873444 -0.600000 +v 179.578568 -6.803391 -0.600000 +v 179.671616 -6.710347 -0.600000 +v 179.741669 -6.598922 -0.600000 +v 179.785217 -6.474614 -0.600000 +v 179.800003 -6.343558 -0.600000 +v 179.800003 -3.402431 -0.600000 +v 179.785217 -3.271371 -0.600000 +v 179.578568 -2.942592 -0.600000 +v 179.467133 -2.872542 -0.600000 +v 167.274673 -2.814206 -0.600000 +v 167.351654 -2.819277 -0.600000 +v 162.852371 -2.814206 -0.600000 +v 162.721298 -2.828996 -0.600000 +v 162.597000 -2.872545 -0.600000 +v 162.485565 -2.942598 -0.600000 +v 162.392532 -3.035642 -0.600000 +v 162.322479 -3.147067 -0.600000 +v 162.278931 -3.271375 -0.600000 +v 162.264145 -3.402431 -0.600000 +v 162.264145 -6.343558 -0.600000 +v 162.278931 -6.474618 -0.600000 +v 162.322479 -6.598929 -0.600000 +v 162.392532 -6.710354 -0.600000 +v 162.485580 -6.803397 -0.600000 +v 162.597000 -6.873447 -0.600000 +v 162.721313 -6.916994 -0.600000 +v 162.852371 -6.931783 -0.600000 +v 170.925842 -6.931783 -0.600000 +v 171.017044 -6.917274 -0.600000 +v 171.098907 -6.875472 -0.600000 +v 171.163651 -6.810726 -0.600000 +v 171.205460 -6.728865 -0.600000 +v 171.219955 -6.637671 -0.600000 +v 171.209946 -6.561580 -0.600000 +v 171.180542 -6.490592 -0.600000 +v 171.133820 -6.429701 -0.600000 +v 167.690613 -2.986493 -0.600000 +v 167.632584 -2.935639 -0.600000 +v 167.568832 -2.893058 -0.600000 +v 167.499771 -2.858983 -0.600000 +v 167.426849 -2.834250 -0.600000 +vn 0.9978 0.0656 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn 0.9979 0.0654 -0.0000 +vn 1.0000 -0.0000 -0.0000 +vn 0.9807 0.1954 -0.0000 +vn 0.9807 0.1953 -0.0000 +vn 0.9469 0.3217 -0.0000 +vn 0.9468 0.3218 -0.0000 +vn 0.8968 0.4425 -0.0000 +vn 0.8967 0.4426 -0.0000 +vn 0.8314 0.5557 -0.0000 +vn 0.7518 0.6594 -0.0000 +vn 0.6594 0.7518 -0.0000 +vn 0.5557 0.8314 -0.0000 +vn 0.4425 0.8968 -0.0000 +vn 0.3217 0.9468 -0.0000 +vn 0.3218 0.9468 -0.0000 +vn 0.1953 0.9807 -0.0000 +vn 0.1954 0.9807 -0.0000 +vn 0.0655 0.9979 -0.0000 +vn -0.0000 1.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vn -1.0000 -0.0000 -0.0000 +vn -0.9979 -0.0655 -0.0000 +vn -0.9979 0.0655 -0.0000 +vn -0.9807 0.1953 -0.0000 +vn -0.9468 0.3217 -0.0000 +vn -0.9807 0.1954 -0.0000 +vn -0.8968 0.4425 -0.0000 +vn -0.8314 0.5557 -0.0000 +vn -0.7518 0.6594 -0.0000 +vn -0.6594 0.7518 -0.0000 +vn -0.5557 0.8314 -0.0000 +vn -0.4425 0.8967 -0.0000 +vn -0.3217 0.9468 -0.0000 +vn -0.1953 0.9807 -0.0000 +vn -0.0655 0.9979 -0.0000 +vn -0.0654 0.9979 -0.0000 +vn -0.1951 0.9808 -0.0000 +vn -0.3214 0.9469 -0.0000 +vn -0.4423 0.8969 -0.0000 +vn -0.5556 0.8315 -0.0000 +vn -0.6593 0.7518 -0.0000 +vn -0.7071 0.7071 -0.0000 +vn -0.6663 0.7457 -0.0000 +vn -0.5786 0.8156 -0.0000 +vn -0.6664 0.7456 -0.0000 +vn -0.4837 0.8752 -0.0000 +vn -0.3827 0.9239 -0.0000 +vn -0.2769 0.9609 -0.0000 +vn -0.1676 0.9859 -0.0000 +vn -0.0561 0.9984 -0.0000 +vn 0.0561 0.9984 -0.0000 +vn 0.1676 0.9859 -0.0000 +vn 0.2769 0.9609 -0.0000 +vn 0.3827 0.9239 -0.0000 +vn 0.4837 0.8752 -0.0000 +vn 0.5786 0.8156 -0.0000 +vn 0.6663 0.7457 -0.0000 +vn 0.7071 0.7071 -0.0000 +vn 0.6715 0.7410 -0.0000 +vn 0.5956 0.8033 -0.0000 +vn 0.5142 0.8577 -0.0000 +vn 0.4276 0.9040 -0.0000 +vn 0.3368 0.9416 -0.0000 +vn 0.2429 0.9700 -0.0000 +vn 0.1468 0.9892 -0.0000 +vn 0.0491 0.9988 -0.0000 +vn -0.0491 0.9988 -0.0000 +vn -0.1468 0.9892 -0.0000 +vn -0.2429 0.9700 -0.0000 +vn -0.3369 0.9416 -0.0000 +vn -0.4276 0.9040 -0.0000 +vn -0.3368 0.9416 -0.0000 +vn -0.5141 0.8577 -0.0000 +vn -0.5956 0.8033 -0.0000 +vn -0.5142 0.8577 -0.0000 +vn -0.6715 0.7410 -0.0000 +vn 0.3826 0.9239 -0.0000 +vn 0.6664 0.7456 -0.0000 +vn 0.5556 0.8315 -0.0000 +vn 0.6593 0.7518 -0.0000 +vn 0.4423 0.8969 -0.0000 +vn 0.5555 0.8315 -0.0000 +vn 0.3214 0.9469 -0.0000 +vn 0.4424 0.8968 -0.0000 +vn 0.1951 0.9808 -0.0000 +vn 0.0654 0.9979 -0.0000 +vn 0.9979 -0.0654 -0.0000 +vn 0.9807 -0.1953 -0.0000 +vn 0.9978 -0.0656 -0.0000 +vn 0.9468 -0.3218 -0.0000 +vn 0.9807 -0.1954 -0.0000 +vn 0.8967 -0.4426 -0.0000 +vn 0.9469 -0.3217 -0.0000 +vn 0.8314 -0.5557 -0.0000 +vn 0.8968 -0.4425 -0.0000 +vn 0.7517 -0.6595 -0.0000 +vn 0.6594 -0.7518 -0.0000 +vn 0.7518 -0.6593 -0.0000 +vn 0.5557 -0.8314 -0.0000 +vn 0.4425 -0.8968 -0.0000 +vn 0.3218 -0.9468 -0.0000 +vn 0.1954 -0.9807 -0.0000 +vn 0.3217 -0.9468 -0.0000 +vn 0.0655 -0.9979 -0.0000 +vn 0.1953 -0.9807 -0.0000 +vn -0.0000 -1.0000 -0.0000 +vn -0.0491 -0.9988 -0.0000 +vn -0.1468 -0.9892 -0.0000 +vn -0.2429 -0.9700 -0.0000 +vn -0.3368 -0.9416 -0.0000 +vn -0.4276 -0.9040 -0.0000 +vn -0.5141 -0.8577 -0.0000 +vn -0.5956 -0.8033 -0.0000 +vn -0.6715 -0.7410 -0.0000 +vn -0.7071 -0.7071 -0.0000 +vn -0.0655 -0.9979 -0.0000 +vn -0.1953 -0.9807 -0.0000 +vn -0.3217 -0.9468 -0.0000 +vn -0.4425 -0.8968 -0.0000 +vn -0.5557 -0.8314 -0.0000 +vn -0.6594 -0.7518 -0.0000 +vn -0.7518 -0.6594 -0.0000 +vn -0.8314 -0.5557 -0.0000 +vn -0.8968 -0.4425 -0.0000 +vn -0.9468 -0.3217 -0.0000 +vn -0.9807 -0.1953 -0.0000 +vn -0.9969 -0.0788 -0.0000 +vn -0.9969 0.0784 0.0002 +vn -0.9969 0.0788 -0.0000 +vn -0.9721 -0.2345 -0.0003 +vn -0.9969 -0.0784 -0.0002 +vn -0.9724 -0.2334 0.0002 +vn -0.9233 -0.3841 -0.0003 +vn -0.9238 -0.3828 0.0003 +vn -0.8523 -0.5231 -0.0002 +vn -0.8528 -0.5222 0.0003 +vn -0.7601 -0.6499 -0.0000 +vn -0.7604 -0.6495 0.0002 +vn -0.6494 -0.7605 -0.0000 +vn -0.5226 -0.8526 -0.0002 +vn -0.6490 -0.7608 0.0002 +vn -0.3832 -0.9237 -0.0004 +vn -0.5212 -0.8534 0.0004 +vn -0.2346 -0.9721 -0.0006 +vn -0.3808 -0.9247 0.0006 +vn -0.0801 -0.9968 -0.0007 +vn -0.2313 -0.9729 0.0007 +vn 0.0764 -0.9971 -0.0007 +vn -0.0764 -0.9971 0.0007 +vn 0.2313 -0.9729 -0.0007 +vn 0.0801 -0.9968 0.0007 +vn 0.3808 -0.9246 -0.0006 +vn 0.2346 -0.9721 0.0006 +vn 0.5212 -0.8534 -0.0004 +vn 0.3832 -0.9237 0.0004 +vn 0.6489 -0.7608 -0.0002 +vn 0.5226 -0.8526 0.0002 +vn 0.7603 -0.6495 -0.0002 +vn 0.7601 -0.6498 -0.0000 +vn 0.6494 -0.7605 -0.0000 +vn 0.8528 -0.5222 -0.0003 +vn 0.8523 -0.5231 0.0002 +vn 0.9238 -0.3828 -0.0003 +vn 0.9233 -0.3841 0.0003 +vn 0.9724 -0.2334 -0.0002 +vn 0.9721 -0.2345 0.0003 +vn 0.9969 -0.0784 0.0002 +vn 0.9969 0.0788 -0.0000 +vn 0.9969 -0.0788 -0.0000 +vn 0.9721 0.2345 -0.0003 +vn 0.9724 0.2334 0.0002 +vn 0.9969 0.0784 -0.0002 +vn 0.9233 0.3841 -0.0003 +vn 0.9238 0.3828 0.0003 +vn 0.8523 0.5231 -0.0002 +vn 0.8528 0.5222 0.0003 +vn 0.7601 0.6498 -0.0000 +vn 0.7603 0.6495 0.0002 +vn 0.6494 0.7605 -0.0000 +vn 0.5226 0.8526 -0.0002 +vn 0.6489 0.7608 0.0002 +vn 0.3832 0.9237 -0.0004 +vn 0.5212 0.8534 0.0004 +vn 0.2346 0.9721 -0.0006 +vn 0.3808 0.9246 0.0006 +vn 0.0801 0.9968 -0.0007 +vn 0.2313 0.9729 0.0007 +vn -0.0764 0.9971 -0.0007 +vn 0.0764 0.9971 0.0007 +vn -0.2313 0.9729 -0.0007 +vn -0.0801 0.9968 0.0007 +vn -0.3808 0.9247 -0.0006 +vn -0.2346 0.9721 0.0006 +vn -0.5212 0.8534 -0.0004 +vn -0.3832 0.9237 0.0004 +vn -0.6490 0.7608 -0.0002 +vn -0.5226 0.8526 0.0002 +vn -0.7604 0.6495 -0.0002 +vn -0.7601 0.6499 -0.0000 +vn -0.6494 0.7605 -0.0000 +vn -0.8528 0.5222 -0.0003 +vn -0.8523 0.5231 0.0002 +vn -0.9238 0.3828 -0.0003 +vn -0.9233 0.3841 0.0003 +vn -0.9724 0.2334 -0.0002 +vn -0.9721 0.2345 0.0003 +vn -0.1121 -0.9937 -0.0000 +vn 0.1572 -0.9876 -0.0000 +vn 0.4548 -0.8906 -0.0000 +vn 0.1571 -0.9876 -0.0000 +vn 0.7071 -0.7071 -0.0000 +vn 0.8906 -0.4548 -0.0000 +vn 0.7072 -0.7070 -0.0000 +vn 0.9876 -0.1570 -0.0000 +vn 0.9914 0.1306 -0.0000 +vn 0.9875 -0.1575 -0.0000 +vn 0.9240 0.3823 -0.0000 +vn 0.9914 0.1309 -0.0000 +vn 0.7934 0.6087 -0.0000 +vn 0.9238 0.3829 -0.0000 +vn 0.7932 0.6089 -0.0000 +vn 0.6590 0.7521 -0.0000 +vn 0.5552 0.8317 -0.0000 +vn 0.6592 0.7520 -0.0000 +vn 0.4426 0.8967 -0.0000 +vn 0.5554 0.8316 -0.0000 +vn 0.3211 0.9470 -0.0000 +vn 0.3213 0.9470 -0.0000 +vn 0.0657 0.9978 -0.0000 +vn -0.1121 0.9937 -0.0000 +vn -0.3306 0.9438 -0.0000 +vn -0.5321 0.8467 -0.0000 +vn -0.3307 0.9437 -0.0000 +vn -0.5323 0.8466 -0.0000 +vn -0.8466 0.5322 -0.0000 +vn -0.7072 0.7070 -0.0000 +vn -0.9438 0.3306 -0.0000 +vn -0.8465 0.5324 -0.0000 +vn -0.9937 0.1120 -0.0000 +vn -0.9937 0.1122 -0.0000 +vn -0.9937 -0.1122 -0.0000 +vn -0.9438 -0.3306 -0.0000 +vn -0.9937 -0.1120 -0.0000 +vn -0.8465 -0.5324 -0.0000 +vn -0.9438 -0.3305 -0.0000 +vn -0.7072 -0.7070 -0.0000 +vn -0.8466 -0.5322 -0.0000 +vn -0.5323 -0.8466 -0.0000 +vn -0.3307 -0.9437 -0.0000 +vn -0.5321 -0.8467 -0.0000 +vn -0.3306 -0.9438 -0.0000 +vn -0.0658 -0.9978 -0.0000 +vn -0.0657 -0.9978 -0.0000 +vn 0.1121 -0.9937 -0.0000 +vn 0.3306 -0.9438 -0.0000 +vn 0.5323 -0.8466 -0.0000 +vn 0.7073 -0.7070 -0.0000 +vn 0.5321 -0.8467 -0.0000 +vn 0.8466 -0.5322 -0.0000 +vn 0.9437 -0.3307 -0.0000 +vn 0.8466 -0.5323 -0.0000 +vn 0.9937 -0.1120 -0.0000 +vn 0.9438 -0.3306 -0.0000 +vn 0.9937 -0.1122 -0.0000 +vn 0.9937 0.1122 -0.0000 +vn 0.9438 0.3306 -0.0000 +vn 0.9937 0.1120 -0.0000 +vn 0.8466 0.5323 -0.0000 +vn 0.9437 0.3307 -0.0000 +vn 0.8466 0.5322 -0.0000 +vn 0.5321 0.8467 -0.0000 +vn 0.7073 0.7070 -0.0000 +vn 0.3306 0.9438 -0.0000 +vn 0.5323 0.8466 -0.0000 +vn 0.1121 0.9937 -0.0000 +vn -0.1572 0.9876 -0.0000 +vn -0.4547 0.8907 -0.0000 +vn -0.1571 0.9876 -0.0000 +vn -0.7070 0.7073 -0.0000 +vn -0.4549 0.8905 -0.0000 +vn -0.8906 0.4548 -0.0000 +vn -0.9876 0.1570 -0.0000 +vn -0.9914 -0.1306 -0.0000 +vn -0.9239 -0.3826 -0.0000 +vn -0.9915 -0.1302 -0.0000 +vn -0.7934 -0.6087 -0.0000 +vn -0.9238 -0.3829 -0.0000 +vn -0.6590 -0.7521 -0.0000 +vn -0.5555 -0.8315 -0.0000 +vn -0.4424 -0.8968 -0.0000 +vn -0.5554 -0.8316 -0.0000 +vn -0.3212 -0.9470 -0.0000 +vn -0.4426 -0.8967 -0.0000 +vn -0.3211 -0.9470 -0.0000 +vn 0.0001 -0.0000 -1.0000 +vt 0.000000 0.000000 +vt 0.000000 0.959425 +vt 1.000000 0.959425 +vt 0.999907 0.960752 +vt 0.000000 0.046324 +vt 0.000093 0.044997 +vt 0.988044 0.014144 +vt 1.000000 0.010146 +vt 0.281809 0.033129 +vt 0.283336 0.032073 +vt 0.895937 0.032048 +vt 0.280179 0.034042 +vt 0.278459 0.034801 +vt 0.276667 0.035399 +vt 0.274823 0.035830 +vt 0.272944 0.036091 +vt 0.271042 0.036178 +vt 0.010870 0.036178 +vt 0.009449 0.036265 +vt 0.008053 0.036524 +vt 0.006707 0.036951 +vt 0.005433 0.037538 +vt 0.004252 0.038275 +vt 0.003184 0.039150 +vt 0.002247 0.040146 +vt 0.001458 0.041249 +vt 0.000829 0.042438 +vt 0.000371 0.043695 +vt 0.940969 0.032048 +vt 0.984847 0.032048 +vt 0.985559 0.031973 +vt 0.919971 0.032048 +vt 0.988044 0.029064 +vt 0.987963 0.029729 +vt 0.987727 0.030359 +vt 0.987346 0.030924 +vt 0.986840 0.031396 +vt 0.986235 0.031752 +vt 0.000093 0.960752 +vt 0.999629 0.962054 +vt 0.000371 0.962054 +vt 0.999171 0.963311 +vt 0.000829 0.963310 +vt 0.998542 0.964500 +vt 0.001458 0.964500 +vt 0.997753 0.965603 +vt 0.002247 0.965603 +vt 0.996816 0.966599 +vt 0.003184 0.966599 +vt 0.995748 0.967474 +vt 0.004252 0.967474 +vt 0.994567 0.968210 +vt 0.005433 0.968210 +vt 0.993293 0.968798 +vt 0.006707 0.968798 +vt 0.991947 0.969225 +vt 0.990551 0.969484 +vt 0.820263 0.969571 +vt 0.008053 0.969225 +vt 0.989130 0.969571 +vt 0.616539 0.969571 +vt 0.179737 0.969571 +vt 0.010870 0.969571 +vt 0.009449 0.969484 +vt 0.383461 0.969571 +vt 0.381329 0.969669 +vt 0.181156 0.969658 +vt 0.182550 0.969917 +vt 0.379220 0.969961 +vt 0.183896 0.970343 +vt 0.377151 0.970445 +vt 0.185172 0.970930 +vt 0.375142 0.971116 +vt 0.186354 0.971667 +vt 0.373213 0.971967 +vt 0.187423 0.972543 +vt 0.346631 0.995543 +vt 0.212064 0.995543 +vt 0.368089 0.975514 +vt 0.369671 0.974176 +vt 0.371384 0.972991 +vt 0.345267 0.996681 +vt 0.213428 0.996681 +vt 0.343776 0.997668 +vt 0.214919 0.997668 +vt 0.342176 0.998493 +vt 0.216519 0.998493 +vt 0.340488 0.999146 +vt 0.218208 0.999146 +vt 0.338731 0.999618 +vt 0.219965 0.999618 +vt 0.336929 0.999904 +vt 0.221767 0.999904 +vt 0.335102 1.000000 +vt 0.223593 1.000000 +vt 0.818845 0.969658 +vt 0.618672 0.969669 +vt 0.817450 0.969917 +vt 0.620780 0.969961 +vt 0.816104 0.970343 +vt 0.622849 0.970445 +vt 0.814829 0.970930 +vt 0.624858 0.971116 +vt 0.813646 0.971667 +vt 0.626787 0.971967 +vt 0.812577 0.972543 +vt 0.628616 0.972991 +vt 0.787936 0.995543 +vt 0.630329 0.974176 +vt 0.631911 0.975514 +vt 0.653369 0.995543 +vt 0.786572 0.996681 +vt 0.654733 0.996681 +vt 0.785081 0.997668 +vt 0.656224 0.997668 +vt 0.783481 0.998493 +vt 0.657824 0.998493 +vt 0.781792 0.999146 +vt 0.659513 0.999146 +vt 0.780035 0.999618 +vt 0.661269 0.999618 +vt 0.778233 0.999904 +vt 0.663071 0.999904 +vt 0.776407 1.000000 +vt 0.664898 1.000000 +vt 0.312153 0.005298 +vt 0.999907 0.008819 +vt 0.325841 0.010480 +vt 0.984847 0.011160 +vt 0.960812 0.011160 +vt 0.985559 0.011235 +vt 0.986234 0.011456 +vt 0.986840 0.011811 +vt 0.987346 0.012283 +vt 0.987726 0.012849 +vt 0.987963 0.013479 +vt 0.999629 0.007517 +vt 0.999171 0.006260 +vt 0.998542 0.005071 +vt 0.313564 0.004105 +vt 0.997753 0.003968 +vt 0.315090 0.003049 +vt 0.996816 0.002972 +vt 0.316721 0.002136 +vt 0.995749 0.002097 +vt 0.318441 0.001377 +vt 0.994567 0.001360 +vt 0.320232 0.000779 +vt 0.993293 0.000773 +vt 0.322076 0.000348 +vt 0.991947 0.000347 +vt 0.323956 0.000087 +vt 0.990551 0.000087 +vt 0.325857 0.000000 +vt 0.989130 0.000000 +vt 0.318104 0.020440 +vt 0.284746 0.030880 +vt 0.317805 0.019278 +vt 0.317705 0.018089 +vt 0.317806 0.016893 +vt 0.318107 0.015727 +vt 0.318599 0.014624 +vt 0.319263 0.013614 +vt 0.320094 0.012708 +vt 0.321066 0.011933 +vt 0.322154 0.011310 +vt 0.323331 0.010854 +vt 0.324570 0.010575 +vt 0.324599 0.025607 +vt 0.325873 0.025698 +vt 0.893057 0.030359 +vt 0.323355 0.025331 +vt 0.322169 0.024875 +vt 0.321073 0.024250 +vt 0.320094 0.023471 +vt 0.319259 0.022558 +vt 0.318594 0.021544 +vt 0.895225 0.031973 +vt 0.894549 0.031752 +vt 0.893943 0.031396 +vt 0.893438 0.030924 +vt 0.892740 0.029064 +vt 0.333908 0.019285 +vt 0.334009 0.018089 +vt 0.333909 0.016900 +vt 0.333606 0.020451 +vt 0.333115 0.021554 +vt 0.332451 0.022564 +vt 0.331620 0.023471 +vt 0.330648 0.024245 +vt 0.329560 0.024868 +vt 0.328383 0.025324 +vt 0.327144 0.025603 +vt 0.892820 0.029729 +vt 0.939814 0.011160 +vt 0.895937 0.011160 +vt 0.895224 0.011235 +vt 0.329544 0.011303 +vt 0.328359 0.010847 +vt 0.327114 0.010571 +vt 0.893943 0.011811 +vt 0.330641 0.011928 +vt 0.894549 0.011456 +vt 0.893438 0.012283 +vt 0.331620 0.012708 +vt 0.892820 0.013479 +vt 0.332455 0.013620 +vt 0.893057 0.012849 +vt 0.892740 0.014144 +vt 0.333120 0.014634 +vt 0.333610 0.015738 +vt 0.920389 0.032022 +vt 0.940473 0.031974 +vt 0.921194 0.031821 +vt 0.940029 0.031762 +vt 0.920798 0.031946 +vt 0.921570 0.031648 +vt 0.939677 0.031434 +vt 0.922232 0.031174 +vt 0.939449 0.031018 +vt 0.921916 0.031432 +vt 0.939371 0.030556 +vt 0.940945 0.013707 +vt 0.939425 0.030170 +vt 0.939585 0.029810 +vt 0.939839 0.029501 +vt 0.941413 0.012652 +vt 0.958552 0.012034 +vt 0.941358 0.013038 +vt 0.941199 0.013398 +vt 0.941107 0.011774 +vt 0.958867 0.011776 +vt 0.941334 0.012189 +vt 0.959214 0.011560 +vt 0.940755 0.011446 +vt 0.959589 0.011387 +vt 0.940310 0.011234 +vt 0.959985 0.011262 +vt 0.960394 0.011186 +s 0 +usemtl Material.001 +f 1/1/1 2/1/1 3/1/1 +f 4/2/2 3/3/2 2/4/2 +f 5/1/3 1/1/3 3/1/3 +f 6/1/4 5/1/4 3/1/4 +f 4/2/2 7/5/2 3/3/2 +f 8/6/2 3/3/2 7/5/2 +f 9/7/2 6/8/2 3/3/2 +f 10/9/2 11/10/2 3/3/2 +f 12/11/2 3/3/2 11/10/2 +f 13/12/2 10/9/2 3/3/2 +f 14/13/2 13/12/2 3/3/2 +f 15/14/2 14/13/2 3/3/2 +f 16/15/2 15/14/2 3/3/2 +f 17/16/2 16/15/2 3/3/2 +f 18/17/2 17/16/2 3/3/2 +f 19/18/2 18/17/2 3/3/2 +f 20/19/2 19/18/2 3/3/2 +f 21/20/2 20/19/2 3/3/2 +f 22/21/2 21/20/2 3/3/2 +f 23/22/2 22/21/2 3/3/2 +f 24/23/2 23/22/2 3/3/2 +f 25/24/2 24/23/2 3/3/2 +f 26/25/2 25/24/2 3/3/2 +f 27/26/2 26/25/2 3/3/2 +f 28/27/2 27/26/2 3/3/2 +f 29/28/2 28/27/2 3/3/2 +f 8/6/2 29/28/2 3/3/2 +f 30/29/2 31/30/2 3/3/2 +f 32/31/2 3/3/2 31/30/2 +f 33/32/2 30/29/2 3/3/2 +f 34/33/2 9/7/2 3/3/2 +f 35/34/2 34/33/2 3/3/2 +f 36/35/2 35/34/2 3/3/2 +f 37/36/2 36/35/2 3/3/2 +f 38/37/2 37/36/2 3/3/2 +f 39/38/2 38/37/2 3/3/2 +f 32/31/2 39/38/2 3/3/2 +f 12/11/2 33/32/2 3/3/2 +f 40/1/5 41/1/5 2/1/5 +f 42/39/2 2/4/2 41/40/2 +f 1/1/6 40/1/6 2/1/6 +f 42/39/2 4/2/2 2/4/2 +f 43/1/7 44/1/7 41/1/7 +f 45/41/2 41/40/2 44/42/2 +f 40/1/8 43/1/8 41/1/8 +f 45/41/2 42/39/2 41/40/2 +f 46/1/9 47/1/9 44/1/9 +f 48/43/2 44/42/2 47/44/2 +f 43/1/10 46/1/10 44/1/10 +f 48/43/2 45/41/2 44/42/2 +f 49/1/11 50/1/11 47/1/11 +f 51/45/2 47/44/2 50/46/2 +f 46/1/11 49/1/11 47/1/11 +f 51/45/2 48/43/2 47/44/2 +f 52/1/12 53/1/12 50/1/12 +f 54/47/2 50/46/2 53/48/2 +f 49/1/12 52/1/12 50/1/12 +f 54/47/2 51/45/2 50/46/2 +f 55/1/13 56/1/13 53/1/13 +f 57/49/2 53/48/2 56/50/2 +f 52/1/13 55/1/13 53/1/13 +f 57/49/2 54/47/2 53/48/2 +f 58/1/14 59/1/14 56/1/14 +f 60/51/2 56/50/2 59/52/2 +f 55/1/14 58/1/14 56/1/14 +f 60/51/2 57/49/2 56/50/2 +f 61/1/15 62/1/15 59/1/15 +f 63/53/2 59/52/2 62/54/2 +f 58/1/15 61/1/15 59/1/15 +f 63/53/2 60/51/2 59/52/2 +f 64/1/16 65/1/16 62/1/16 +f 66/55/2 62/54/2 65/56/2 +f 61/1/17 64/1/17 62/1/17 +f 66/55/2 63/53/2 62/54/2 +f 67/1/18 68/1/18 65/1/18 +f 65/56/2 68/57/2 69/58/2 +f 64/1/19 67/1/19 65/1/19 +f 70/59/2 66/55/2 65/56/2 +f 71/1/20 72/1/20 68/1/20 +f 68/57/2 72/60/2 69/58/2 +f 67/1/20 71/1/20 68/1/20 +f 65/56/2 69/58/2 73/61/2 +f 74/1/21 72/1/21 71/1/21 +f 73/61/2 70/59/2 65/56/2 +f 74/1/21 69/1/21 72/1/21 +f 74/1/22 71/1/22 67/1/22 +f 75/1/22 76/1/22 77/1/22 +f 74/1/22 67/1/22 64/1/22 +f 64/1/22 78/1/22 74/1/22 +f 64/1/22 77/1/22 78/1/22 +f 77/1/22 64/1/22 75/1/22 +f 79/1/22 80/1/22 76/1/22 +f 75/1/22 64/1/22 61/1/22 +f 75/1/22 79/1/22 76/1/22 +f 81/1/22 61/1/22 58/1/22 +f 81/1/22 75/1/22 61/1/22 +f 82/1/22 58/1/22 55/1/22 +f 82/1/22 81/1/22 58/1/22 +f 83/1/22 55/1/22 52/1/22 +f 83/1/22 82/1/22 55/1/22 +f 84/1/22 52/1/22 49/1/22 +f 84/1/22 83/1/22 52/1/22 +f 85/1/22 49/1/22 46/1/22 +f 85/1/22 84/1/22 49/1/22 +f 86/1/22 46/1/22 43/1/22 +f 86/1/22 85/1/22 46/1/22 +f 87/1/22 43/1/22 40/1/22 +f 87/1/22 86/1/22 43/1/22 +f 88/1/22 40/1/22 1/1/22 +f 88/1/22 87/1/22 40/1/22 +f 89/1/22 1/1/22 5/1/22 +f 89/1/22 88/1/22 1/1/22 +f 90/1/4 5/1/4 6/1/4 +f 89/1/22 5/1/22 91/1/22 +f 92/1/22 91/1/22 5/1/22 +f 93/1/22 5/1/22 90/1/22 +f 93/1/22 92/1/22 5/1/22 +f 94/1/23 7/1/23 4/1/23 +f 95/1/24 8/1/24 7/1/24 +f 94/1/24 95/1/24 7/1/24 +f 91/1/25 4/1/25 42/1/25 +f 91/1/23 94/1/23 4/1/23 +f 89/1/26 42/1/26 45/1/26 +f 89/1/25 91/1/25 42/1/25 +f 88/1/27 45/1/27 48/1/27 +f 89/1/28 45/1/28 88/1/28 +f 87/1/29 48/1/29 51/1/29 +f 88/1/27 48/1/27 87/1/27 +f 86/1/30 51/1/30 54/1/30 +f 87/1/29 51/1/29 86/1/29 +f 85/1/31 54/1/31 57/1/31 +f 86/1/30 54/1/30 85/1/30 +f 84/1/32 57/1/32 60/1/32 +f 85/1/31 57/1/31 84/1/31 +f 83/1/33 60/1/33 63/1/33 +f 84/1/32 60/1/32 83/1/32 +f 82/1/34 63/1/34 66/1/34 +f 83/1/33 63/1/33 82/1/33 +f 81/1/35 66/1/35 70/1/35 +f 82/1/34 66/1/34 81/1/34 +f 75/1/36 70/1/36 96/1/36 +f 81/1/35 70/1/35 75/1/35 +f 97/62/2 98/63/2 96/64/2 +f 79/1/37 96/1/37 98/1/37 +f 97/62/2 96/64/2 70/59/2 +f 70/59/2 99/65/2 97/62/2 +f 70/59/2 73/61/2 99/65/2 +f 75/1/36 96/1/36 79/1/36 +f 80/1/21 98/1/21 97/1/21 +f 79/1/37 98/1/37 80/1/37 +f 100/66/2 101/67/2 97/62/2 +f 76/1/38 97/1/38 101/1/38 +f 99/65/2 100/66/2 97/62/2 +f 80/1/21 97/1/21 76/1/21 +f 100/66/2 102/68/2 101/67/2 +f 103/1/39 101/1/39 102/1/39 +f 76/1/38 101/1/38 103/1/38 +f 104/69/2 105/70/2 102/68/2 +f 106/1/40 102/1/40 105/1/40 +f 100/66/2 104/69/2 102/68/2 +f 103/1/39 102/1/39 106/1/39 +f 107/71/2 108/72/2 105/70/2 +f 109/1/41 105/1/41 108/1/41 +f 104/69/2 107/71/2 105/70/2 +f 106/1/40 105/1/40 109/1/40 +f 110/73/2 111/74/2 108/72/2 +f 112/1/42 108/1/42 111/1/42 +f 107/71/2 110/73/2 108/72/2 +f 109/1/41 108/1/41 112/1/41 +f 113/75/2 114/76/2 111/74/2 +f 115/1/43 111/1/43 114/1/43 +f 110/73/2 113/75/2 111/74/2 +f 112/1/42 111/1/42 115/1/42 +f 116/77/2 117/78/2 114/76/2 +f 118/1/44 114/1/44 117/1/44 +f 119/79/2 116/77/2 114/76/2 +f 120/80/2 119/79/2 114/76/2 +f 121/81/2 120/80/2 114/76/2 +f 113/75/2 121/81/2 114/76/2 +f 115/1/43 114/1/43 118/1/43 +f 122/82/2 123/83/2 117/78/2 +f 124/1/45 117/1/45 123/1/45 +f 116/77/2 122/82/2 117/78/2 +f 118/1/44 117/1/44 124/1/44 +f 125/84/2 126/85/2 123/83/2 +f 127/1/46 123/1/46 126/1/46 +f 122/82/2 125/84/2 123/83/2 +f 124/1/47 123/1/47 127/1/47 +f 128/86/2 129/87/2 126/85/2 +f 130/1/48 126/1/48 129/1/48 +f 125/84/2 128/86/2 126/85/2 +f 127/1/46 126/1/46 130/1/46 +f 131/88/2 132/89/2 129/87/2 +f 133/1/49 129/1/49 132/1/49 +f 128/86/2 131/88/2 129/87/2 +f 130/1/48 129/1/48 133/1/48 +f 134/90/2 135/91/2 132/89/2 +f 136/1/50 132/1/50 135/1/50 +f 131/88/2 134/90/2 132/89/2 +f 133/1/49 132/1/49 136/1/49 +f 137/92/2 138/93/2 135/91/2 +f 139/1/51 135/1/51 138/1/51 +f 134/90/2 137/92/2 135/91/2 +f 136/1/50 135/1/50 139/1/50 +f 140/94/2 141/95/2 138/93/2 +f 142/1/52 138/1/52 141/1/52 +f 137/92/2 140/94/2 138/93/2 +f 139/1/51 138/1/51 142/1/51 +f 143/1/21 141/1/21 140/1/21 +f 142/1/52 141/1/52 143/1/52 +f 144/1/53 140/1/53 137/1/53 +f 143/1/21 140/1/21 144/1/21 +f 145/1/54 137/1/54 134/1/54 +f 144/1/53 137/1/53 145/1/53 +f 146/1/55 134/1/55 131/1/55 +f 145/1/54 134/1/54 146/1/54 +f 147/1/56 131/1/56 128/1/56 +f 146/1/55 131/1/55 147/1/55 +f 148/1/57 128/1/57 125/1/57 +f 147/1/56 128/1/56 148/1/56 +f 149/1/58 125/1/58 122/1/58 +f 148/1/57 125/1/57 149/1/57 +f 150/1/59 122/1/59 116/1/59 +f 149/1/58 122/1/58 150/1/58 +f 151/1/60 116/1/60 119/1/60 +f 150/1/59 116/1/59 151/1/59 +f 152/1/61 119/1/61 120/1/61 +f 151/1/60 119/1/60 152/1/60 +f 153/1/62 120/1/62 121/1/62 +f 152/1/61 120/1/61 153/1/61 +f 154/1/63 121/1/63 113/1/63 +f 153/1/62 121/1/62 154/1/62 +f 155/1/64 113/1/64 110/1/64 +f 154/1/63 113/1/63 155/1/63 +f 156/1/65 110/1/65 107/1/65 +f 155/1/64 110/1/64 156/1/64 +f 157/1/66 107/1/66 104/1/66 +f 156/1/65 107/1/65 157/1/65 +f 158/1/67 104/1/67 100/1/67 +f 157/1/66 104/1/66 158/1/66 +f 159/1/68 100/1/68 99/1/68 +f 158/1/67 100/1/67 159/1/67 +f 77/1/21 99/1/21 73/1/21 +f 159/1/68 99/1/68 77/1/68 +f 160/96/2 161/97/2 73/61/2 +f 78/1/69 73/1/69 161/1/69 +f 69/58/2 160/96/2 73/61/2 +f 77/1/21 73/1/21 78/1/21 +f 162/98/2 163/99/2 161/97/2 +f 164/1/70 161/1/70 163/1/70 +f 160/96/2 162/98/2 161/97/2 +f 78/1/69 161/1/69 164/1/69 +f 165/100/2 166/101/2 163/99/2 +f 167/1/71 163/1/71 166/1/71 +f 162/98/2 165/100/2 163/99/2 +f 164/1/70 163/1/70 167/1/70 +f 168/102/2 169/103/2 166/101/2 +f 170/1/72 166/1/72 169/1/72 +f 165/100/2 168/102/2 166/101/2 +f 167/1/71 166/1/71 170/1/71 +f 171/104/2 172/105/2 169/103/2 +f 173/1/73 169/1/73 172/1/73 +f 168/102/2 171/104/2 169/103/2 +f 170/1/74 169/1/74 173/1/74 +f 174/106/2 175/107/2 172/105/2 +f 176/1/75 172/1/75 175/1/75 +f 171/104/2 174/106/2 172/105/2 +f 173/1/73 172/1/73 176/1/73 +f 177/108/2 178/109/2 175/107/2 +f 179/1/76 175/1/76 178/1/76 +f 174/106/2 177/108/2 175/107/2 +f 176/1/77 175/1/77 179/1/77 +f 177/108/2 180/110/2 178/109/2 +f 181/1/78 178/1/78 180/1/78 +f 179/1/76 178/1/76 181/1/76 +f 177/108/2 182/111/2 180/110/2 +f 183/1/44 180/1/44 182/1/44 +f 181/1/78 180/1/78 183/1/78 +f 184/112/2 185/113/2 182/111/2 +f 186/1/47 182/1/47 185/1/47 +f 177/108/2 184/112/2 182/111/2 +f 183/1/44 182/1/44 186/1/44 +f 187/114/2 188/115/2 185/113/2 +f 189/1/46 185/1/46 188/1/46 +f 184/112/2 187/114/2 185/113/2 +f 186/1/45 185/1/45 189/1/45 +f 190/116/2 191/117/2 188/115/2 +f 192/1/48 188/1/48 191/1/48 +f 187/114/2 190/116/2 188/115/2 +f 189/1/46 188/1/46 192/1/46 +f 193/118/2 194/119/2 191/117/2 +f 195/1/49 191/1/49 194/1/49 +f 190/116/2 193/118/2 191/117/2 +f 192/1/48 191/1/48 195/1/48 +f 196/120/2 197/121/2 194/119/2 +f 198/1/50 194/1/50 197/1/50 +f 193/118/2 196/120/2 194/119/2 +f 195/1/49 194/1/49 198/1/49 +f 199/122/2 200/123/2 197/121/2 +f 201/1/51 197/1/51 200/1/51 +f 196/120/2 199/122/2 197/121/2 +f 198/1/50 197/1/50 201/1/50 +f 202/124/2 203/125/2 200/123/2 +f 204/1/52 200/1/52 203/1/52 +f 199/122/2 202/124/2 200/123/2 +f 201/1/51 200/1/51 204/1/51 +f 205/1/21 203/1/21 202/1/21 +f 204/1/52 203/1/52 205/1/52 +f 206/1/53 202/1/53 199/1/53 +f 205/1/21 202/1/21 206/1/21 +f 207/1/54 199/1/54 196/1/54 +f 206/1/53 199/1/53 207/1/53 +f 208/1/55 196/1/55 193/1/55 +f 207/1/54 196/1/54 208/1/54 +f 209/1/56 193/1/56 190/1/56 +f 208/1/55 193/1/55 209/1/55 +f 210/1/57 190/1/57 187/1/57 +f 209/1/79 190/1/79 210/1/79 +f 211/1/58 187/1/58 184/1/58 +f 210/1/57 187/1/57 211/1/57 +f 212/1/59 184/1/59 177/1/59 +f 211/1/58 184/1/58 212/1/58 +f 213/1/60 177/1/60 174/1/60 +f 212/1/80 177/1/80 213/1/80 +f 214/1/13 174/1/13 171/1/13 +f 213/1/60 174/1/60 214/1/60 +f 215/1/81 171/1/81 168/1/81 +f 214/1/82 171/1/82 215/1/82 +f 216/1/83 168/1/83 165/1/83 +f 215/1/84 168/1/84 216/1/84 +f 217/1/85 165/1/85 162/1/85 +f 216/1/86 165/1/86 217/1/86 +f 218/1/87 162/1/87 160/1/87 +f 217/1/85 162/1/85 218/1/85 +f 219/1/88 160/1/88 69/1/88 +f 218/1/87 160/1/87 219/1/87 +f 219/1/88 69/1/88 74/1/88 +f 220/126/2 221/127/2 6/8/2 +f 90/1/89 6/1/89 221/1/89 +f 222/128/2 220/126/2 6/8/2 +f 6/8/2 223/129/2 224/130/2 +f 225/131/2 223/129/2 6/8/2 +f 226/132/2 225/131/2 6/8/2 +f 227/133/2 226/132/2 6/8/2 +f 228/134/2 227/133/2 6/8/2 +f 229/135/2 228/134/2 6/8/2 +f 230/136/2 229/135/2 6/8/2 +f 9/7/2 230/136/2 6/8/2 +f 220/126/2 231/137/2 221/127/2 +f 232/1/90 221/1/90 231/1/90 +f 90/1/91 221/1/91 232/1/91 +f 220/126/2 233/138/2 231/137/2 +f 234/1/92 231/1/92 233/1/92 +f 232/1/93 231/1/93 234/1/93 +f 220/126/2 235/139/2 233/138/2 +f 236/1/94 233/1/94 235/1/94 +f 234/1/95 233/1/95 236/1/95 +f 237/140/2 238/141/2 235/139/2 +f 239/1/96 235/1/96 238/1/96 +f 220/126/2 237/140/2 235/139/2 +f 236/1/97 235/1/97 239/1/97 +f 240/142/2 241/143/2 238/141/2 +f 242/1/98 238/1/98 241/1/98 +f 237/140/2 240/142/2 238/141/2 +f 239/1/96 238/1/96 242/1/96 +f 243/144/2 244/145/2 241/143/2 +f 245/1/99 241/1/99 244/1/99 +f 240/142/2 243/144/2 241/143/2 +f 242/1/100 241/1/100 245/1/100 +f 246/146/2 247/147/2 244/145/2 +f 248/1/101 244/1/101 247/1/101 +f 243/144/2 246/146/2 244/145/2 +f 245/1/99 244/1/99 248/1/99 +f 249/148/2 250/149/2 247/147/2 +f 251/1/102 247/1/102 250/1/102 +f 246/146/2 249/148/2 247/147/2 +f 248/1/101 247/1/101 251/1/101 +f 252/150/2 253/151/2 250/149/2 +f 254/1/103 250/1/103 253/1/103 +f 249/148/2 252/150/2 250/149/2 +f 251/1/102 250/1/102 254/1/102 +f 255/152/2 256/153/2 253/151/2 +f 257/1/104 253/1/104 256/1/104 +f 252/150/2 255/152/2 253/151/2 +f 254/1/105 253/1/105 257/1/105 +f 258/154/2 259/155/2 256/153/2 +f 260/1/106 256/1/106 259/1/106 +f 255/152/2 258/154/2 256/153/2 +f 257/1/107 256/1/107 260/1/107 +f 261/1/108 259/1/108 258/1/108 +f 260/1/106 259/1/106 261/1/106 +f 262/1/109 258/1/109 255/1/109 +f 261/1/108 258/1/108 262/1/108 +f 263/1/110 255/1/110 252/1/110 +f 262/1/109 255/1/109 263/1/109 +f 264/1/111 252/1/111 249/1/111 +f 263/1/110 252/1/110 264/1/110 +f 265/1/112 249/1/112 246/1/112 +f 264/1/111 249/1/111 265/1/111 +f 266/1/113 246/1/113 243/1/113 +f 265/1/112 246/1/112 266/1/112 +f 267/1/114 243/1/114 240/1/114 +f 266/1/113 243/1/113 267/1/113 +f 268/1/115 240/1/115 237/1/115 +f 267/1/114 240/1/114 268/1/114 +f 269/1/116 237/1/116 220/1/116 +f 268/1/115 237/1/115 269/1/115 +f 270/156/2 271/157/2 220/126/2 +f 272/1/117 220/1/117 271/1/117 +f 273/158/2 270/156/2 220/126/2 +f 274/159/2 273/158/2 220/126/2 +f 275/160/2 274/159/2 220/126/2 +f 276/161/2 275/160/2 220/126/2 +f 277/162/2 276/161/2 220/126/2 +f 278/163/2 277/162/2 220/126/2 +f 279/164/2 278/163/2 220/126/2 +f 280/165/2 279/164/2 220/126/2 +f 281/166/2 280/165/2 220/126/2 +f 282/167/2 281/166/2 220/126/2 +f 283/168/2 282/167/2 220/126/2 +f 222/128/2 283/168/2 220/126/2 +f 269/1/116 220/1/116 272/1/116 +f 12/11/2 11/10/2 271/157/2 +f 284/1/116 271/1/116 11/1/116 +f 285/169/2 286/170/2 271/157/2 +f 287/171/2 271/157/2 286/170/2 +f 288/172/2 285/169/2 271/157/2 +f 289/173/2 288/172/2 271/157/2 +f 290/174/2 289/173/2 271/157/2 +f 291/175/2 290/174/2 271/157/2 +f 292/176/2 291/175/2 271/157/2 +f 293/177/2 292/176/2 271/157/2 +f 270/156/2 293/177/2 271/157/2 +f 294/178/2 12/11/2 271/157/2 +f 295/179/2 294/178/2 271/157/2 +f 296/180/2 295/179/2 271/157/2 +f 297/181/2 296/180/2 271/157/2 +f 287/171/2 297/181/2 271/157/2 +f 272/1/117 271/1/117 284/1/117 +f 298/1/115 11/1/115 10/1/115 +f 284/1/116 11/1/116 298/1/116 +f 299/1/114 10/1/114 13/1/114 +f 298/1/115 10/1/115 299/1/115 +f 300/1/113 13/1/113 14/1/113 +f 299/1/114 13/1/114 300/1/114 +f 301/1/112 14/1/112 15/1/112 +f 300/1/113 14/1/113 301/1/113 +f 302/1/111 15/1/111 16/1/111 +f 301/1/112 15/1/112 302/1/112 +f 303/1/110 16/1/110 17/1/110 +f 302/1/111 16/1/111 303/1/111 +f 304/1/109 17/1/109 18/1/109 +f 303/1/110 17/1/110 304/1/110 +f 305/1/108 18/1/108 19/1/108 +f 304/1/109 18/1/109 305/1/109 +f 306/1/118 19/1/118 20/1/118 +f 305/1/108 19/1/108 306/1/108 +f 307/1/119 20/1/119 21/1/119 +f 307/1/118 306/1/118 20/1/118 +f 308/1/120 21/1/120 22/1/120 +f 308/1/119 307/1/119 21/1/119 +f 309/1/121 22/1/121 23/1/121 +f 309/1/120 308/1/120 22/1/120 +f 310/1/122 23/1/122 24/1/122 +f 310/1/121 309/1/121 23/1/121 +f 311/1/123 24/1/123 25/1/123 +f 311/1/122 310/1/122 24/1/122 +f 312/1/124 25/1/124 26/1/124 +f 312/1/123 311/1/123 25/1/123 +f 313/1/125 26/1/125 27/1/125 +f 313/1/124 312/1/124 26/1/124 +f 314/1/126 27/1/126 28/1/126 +f 314/1/125 313/1/125 27/1/125 +f 315/1/127 28/1/127 29/1/127 +f 315/1/126 314/1/126 28/1/126 +f 316/1/128 29/1/128 8/1/128 +f 316/1/127 315/1/127 29/1/127 +f 95/1/128 316/1/128 8/1/128 +f 317/182/2 318/183/2 319/184/2 +f 320/1/129 319/1/129 318/1/129 +f 317/182/2 319/184/2 321/185/2 +f 322/1/130 321/1/130 319/1/130 +f 322/1/131 319/1/131 320/1/131 +f 317/182/2 323/186/2 318/183/2 +f 324/1/132 318/1/132 323/1/132 +f 325/1/133 320/1/133 318/1/133 +f 325/1/134 318/1/134 324/1/134 +f 317/182/2 326/187/2 323/186/2 +f 327/1/135 323/1/135 326/1/135 +f 324/1/136 323/1/136 327/1/136 +f 317/182/2 328/188/2 326/187/2 +f 329/1/137 326/1/137 328/1/137 +f 327/1/138 326/1/138 329/1/138 +f 317/182/2 330/189/2 328/188/2 +f 331/1/139 328/1/139 330/1/139 +f 329/1/140 328/1/140 331/1/140 +f 317/182/2 332/190/2 330/189/2 +f 331/1/141 330/1/141 332/1/141 +f 317/182/2 333/191/2 332/190/2 +f 334/1/142 332/1/142 333/1/142 +f 331/1/143 332/1/143 334/1/143 +f 317/182/2 335/192/2 333/191/2 +f 336/1/144 333/1/144 335/1/144 +f 334/1/145 333/1/145 336/1/145 +f 317/182/2 337/193/2 335/192/2 +f 338/1/146 335/1/146 337/1/146 +f 336/1/147 335/1/147 338/1/147 +f 317/182/2 286/170/2 337/193/2 +f 339/1/148 337/1/148 286/1/148 +f 338/1/149 337/1/149 339/1/149 +f 340/1/150 286/1/150 285/1/150 +f 341/194/2 287/171/2 286/170/2 +f 317/182/2 341/194/2 286/170/2 +f 339/1/151 286/1/151 340/1/151 +f 342/1/152 285/1/152 288/1/152 +f 340/1/153 285/1/153 342/1/153 +f 343/1/154 288/1/154 289/1/154 +f 342/1/155 288/1/155 343/1/155 +f 344/1/156 289/1/156 290/1/156 +f 343/1/157 289/1/157 344/1/157 +f 345/1/158 290/1/158 291/1/158 +f 344/1/159 290/1/159 345/1/159 +f 346/1/160 291/1/160 292/1/160 +f 347/1/161 291/1/161 346/1/161 +f 345/1/162 291/1/162 347/1/162 +f 348/1/163 292/1/163 293/1/163 +f 346/1/164 292/1/164 348/1/164 +f 349/1/165 293/1/165 270/1/165 +f 348/1/166 293/1/166 349/1/166 +f 350/1/167 270/1/167 273/1/167 +f 349/1/168 270/1/168 350/1/168 +f 350/1/169 273/1/169 274/1/169 +f 351/1/170 274/1/170 275/1/170 +f 350/1/171 274/1/171 351/1/171 +f 352/1/172 275/1/172 276/1/172 +f 353/1/173 275/1/173 352/1/173 +f 351/1/174 275/1/174 353/1/174 +f 354/1/175 276/1/175 277/1/175 +f 352/1/176 276/1/176 354/1/176 +f 355/1/177 277/1/177 278/1/177 +f 354/1/178 277/1/178 355/1/178 +f 356/1/179 278/1/179 279/1/179 +f 355/1/180 278/1/180 356/1/180 +f 356/1/181 279/1/181 280/1/181 +f 357/1/182 280/1/182 281/1/182 +f 356/1/183 280/1/183 357/1/183 +f 358/1/184 281/1/184 282/1/184 +f 357/1/185 281/1/185 358/1/185 +f 359/1/186 282/1/186 283/1/186 +f 358/1/187 282/1/187 359/1/187 +f 360/1/188 283/1/188 222/1/188 +f 359/1/189 283/1/189 360/1/189 +f 6/8/2 224/130/2 361/195/2 +f 362/1/190 222/1/190 363/1/190 +f 360/1/191 222/1/191 362/1/191 +f 6/8/2 361/195/2 364/196/2 +f 365/1/192 363/1/192 366/1/192 +f 362/1/193 363/1/193 365/1/193 +f 367/197/2 368/198/2 366/199/2 +f 369/1/194 366/1/194 368/1/194 +f 364/196/2 222/128/2 6/8/2 +f 364/196/2 363/200/2 222/128/2 +f 364/196/2 367/197/2 366/199/2 +f 364/196/2 366/199/2 363/200/2 +f 365/1/195 366/1/195 369/1/195 +f 370/201/2 371/202/2 368/198/2 +f 372/1/196 368/1/196 371/1/196 +f 373/203/2 370/201/2 368/198/2 +f 367/197/2 373/203/2 368/198/2 +f 369/1/197 368/1/197 372/1/197 +f 374/204/2 375/205/2 371/202/2 +f 376/1/198 371/1/198 375/1/198 +f 370/201/2 374/204/2 371/202/2 +f 372/1/199 371/1/199 376/1/199 +f 377/206/2 378/207/2 375/205/2 +f 379/1/200 375/1/200 378/1/200 +f 380/208/2 377/206/2 375/205/2 +f 374/204/2 380/208/2 375/205/2 +f 381/1/201 375/1/201 379/1/201 +f 376/1/202 375/1/202 381/1/202 +f 382/209/2 383/210/2 378/207/2 +f 384/1/203 378/1/203 383/1/203 +f 377/206/2 382/209/2 378/207/2 +f 379/1/204 378/1/204 384/1/204 +f 317/182/2 385/211/2 383/210/2 +f 386/1/205 383/1/205 385/1/205 +f 382/209/2 317/182/2 383/210/2 +f 384/1/206 383/1/206 386/1/206 +f 317/182/2 321/185/2 385/211/2 +f 322/1/207 385/1/207 321/1/207 +f 386/1/208 385/1/208 322/1/208 +f 387/1/108 31/1/108 30/1/108 +f 388/1/209 32/1/209 31/1/209 +f 388/1/209 31/1/209 387/1/209 +f 389/212/2 390/213/2 30/29/2 +f 391/1/210 30/1/210 390/1/210 +f 389/212/2 30/29/2 33/32/2 +f 387/1/108 30/1/108 391/1/108 +f 392/214/2 393/215/2 390/213/2 +f 394/1/211 390/1/211 393/1/211 +f 395/216/2 392/214/2 390/213/2 +f 389/212/2 395/216/2 390/213/2 +f 394/1/212 391/1/212 390/1/212 +f 396/217/2 397/218/2 393/215/2 +f 398/1/213 393/1/213 397/1/213 +f 392/214/2 396/217/2 393/215/2 +f 394/1/211 393/1/211 398/1/211 +f 399/219/2 400/220/2 397/218/2 +f 401/1/214 397/1/214 400/1/214 +f 402/221/2 399/219/2 397/218/2 +f 396/217/2 402/221/2 397/218/2 +f 398/1/215 397/1/215 401/1/215 +f 399/219/2 403/222/2 400/220/2 +f 404/1/216 400/1/216 403/1/216 +f 401/1/214 400/1/214 404/1/214 +f 405/223/2 406/224/2 403/222/2 +f 407/1/217 403/1/217 406/1/217 +f 399/219/2 405/223/2 403/222/2 +f 404/1/218 403/1/218 407/1/218 +f 405/223/2 408/225/2 406/224/2 +f 409/1/219 406/1/219 408/1/219 +f 407/1/220 406/1/220 409/1/220 +f 405/223/2 410/226/2 408/225/2 +f 411/1/221 408/1/221 410/1/221 +f 409/1/222 408/1/222 411/1/222 +f 412/227/2 413/228/2 410/226/2 +f 414/1/60 410/1/60 413/1/60 +f 415/229/2 412/227/2 410/226/2 +f 416/230/2 415/229/2 410/226/2 +f 405/223/2 416/230/2 410/226/2 +f 411/1/223 410/1/223 414/1/223 +f 417/231/2 418/232/2 413/228/2 +f 419/1/224 413/1/224 418/1/224 +f 420/233/2 417/231/2 413/228/2 +f 412/227/2 420/233/2 413/228/2 +f 414/1/60 413/1/60 419/1/60 +f 417/231/2 421/234/2 418/232/2 +f 422/1/225 418/1/225 421/1/225 +f 419/1/226 418/1/226 422/1/226 +f 423/235/2 424/236/2 421/234/2 +f 425/1/227 421/1/227 424/1/227 +f 417/231/2 423/235/2 421/234/2 +f 422/1/228 421/1/228 425/1/228 +f 426/237/2 427/238/2 424/236/2 +f 428/1/229 424/1/229 427/1/229 +f 423/235/2 426/237/2 424/236/2 +f 425/1/227 424/1/227 428/1/227 +f 426/237/2 429/239/2 427/238/2 +f 430/1/18 427/1/18 429/1/18 +f 428/1/230 427/1/230 430/1/230 +f 361/195/2 224/130/2 429/239/2 +f 431/1/231 429/1/231 224/1/231 +f 426/237/2 361/195/2 429/239/2 +f 430/1/18 429/1/18 431/1/18 +f 432/1/21 224/1/21 223/1/21 +f 431/1/231 224/1/231 432/1/231 +f 433/1/232 223/1/232 225/1/232 +f 432/1/21 223/1/21 433/1/21 +f 434/1/233 225/1/233 226/1/233 +f 433/1/232 225/1/232 434/1/232 +f 435/1/234 226/1/234 227/1/234 +f 434/1/235 226/1/235 435/1/235 +f 436/1/44 227/1/44 228/1/44 +f 435/1/236 227/1/236 436/1/236 +f 437/1/237 228/1/237 229/1/237 +f 436/1/238 228/1/238 437/1/238 +f 438/1/239 229/1/239 230/1/239 +f 437/1/240 229/1/240 438/1/240 +f 439/1/241 230/1/241 9/1/241 +f 438/1/239 230/1/239 439/1/239 +f 440/1/23 9/1/23 34/1/23 +f 439/1/242 9/1/242 440/1/242 +f 441/1/243 34/1/243 35/1/243 +f 440/1/23 34/1/23 441/1/23 +f 442/1/244 35/1/244 36/1/244 +f 441/1/245 35/1/245 442/1/245 +f 93/1/246 36/1/246 37/1/246 +f 442/1/247 36/1/247 93/1/247 +f 92/1/248 37/1/248 38/1/248 +f 93/1/249 37/1/249 92/1/249 +f 443/1/250 38/1/250 39/1/250 +f 92/1/117 38/1/117 443/1/117 +f 444/1/251 39/1/251 32/1/251 +f 443/1/252 39/1/252 444/1/252 +f 444/1/253 32/1/253 388/1/253 +f 445/1/108 33/1/108 12/1/108 +f 446/1/254 389/1/254 33/1/254 +f 446/1/255 33/1/255 445/1/255 +f 447/1/256 12/1/256 294/1/256 +f 445/1/108 12/1/108 447/1/108 +f 448/1/257 294/1/257 295/1/257 +f 447/1/256 294/1/256 448/1/256 +f 449/1/258 295/1/258 296/1/258 +f 448/1/257 295/1/257 449/1/257 +f 450/1/259 296/1/259 297/1/259 +f 449/1/260 296/1/260 450/1/260 +f 451/1/261 297/1/261 287/1/261 +f 450/1/213 297/1/213 451/1/213 +f 452/1/262 287/1/262 341/1/262 +f 451/1/263 287/1/263 452/1/263 +f 453/1/264 341/1/264 317/1/264 +f 452/1/265 341/1/265 453/1/265 +f 454/1/4 317/1/4 382/1/4 +f 453/1/266 317/1/266 454/1/266 +f 455/1/267 382/1/267 377/1/267 +f 454/1/4 382/1/4 455/1/4 +f 456/1/268 377/1/268 380/1/268 +f 456/1/269 455/1/269 377/1/269 +f 457/1/270 380/1/270 374/1/270 +f 456/1/271 380/1/271 457/1/271 +f 458/1/60 374/1/60 370/1/60 +f 457/1/272 374/1/272 458/1/272 +f 459/1/273 370/1/273 373/1/273 +f 458/1/274 370/1/274 459/1/274 +f 460/1/275 373/1/275 367/1/275 +f 459/1/276 373/1/276 460/1/276 +f 461/1/277 367/1/277 364/1/277 +f 460/1/275 367/1/275 461/1/275 +f 462/1/21 364/1/21 361/1/21 +f 461/1/277 364/1/277 462/1/277 +f 463/1/278 361/1/278 426/1/278 +f 462/1/21 361/1/21 463/1/21 +f 464/1/279 426/1/279 423/1/279 +f 463/1/280 426/1/280 464/1/280 +f 465/1/281 423/1/281 417/1/281 +f 464/1/282 423/1/282 465/1/282 +f 466/1/283 417/1/283 420/1/283 +f 465/1/238 417/1/238 466/1/238 +f 467/1/284 420/1/284 412/1/284 +f 466/1/283 420/1/283 467/1/283 +f 468/1/285 412/1/285 415/1/285 +f 467/1/284 412/1/284 468/1/284 +f 469/1/286 415/1/286 416/1/286 +f 468/1/287 415/1/287 469/1/287 +f 470/1/288 416/1/288 405/1/288 +f 469/1/289 416/1/289 470/1/289 +f 471/1/117 405/1/117 399/1/117 +f 470/1/288 405/1/288 471/1/288 +f 472/1/290 399/1/290 402/1/290 +f 471/1/117 399/1/117 472/1/117 +f 473/1/291 402/1/291 396/1/291 +f 472/1/290 402/1/290 473/1/290 +f 474/1/292 396/1/292 392/1/292 +f 473/1/293 396/1/293 474/1/293 +f 475/1/294 392/1/294 395/1/294 +f 474/1/295 392/1/295 475/1/295 +f 476/1/119 395/1/119 389/1/119 +f 475/1/296 395/1/296 476/1/296 +f 476/1/119 389/1/119 446/1/119 +f 305/1/22 306/1/22 307/1/22 +f 305/1/22 307/1/22 308/1/22 +f 305/1/22 308/1/22 309/1/22 +f 305/1/22 309/1/22 310/1/22 +f 305/1/22 310/1/22 311/1/22 +f 387/1/22 311/1/22 312/1/22 +f 387/1/22 305/1/22 311/1/22 +f 387/1/22 312/1/22 313/1/22 +f 387/1/22 313/1/22 314/1/22 +f 387/1/22 314/1/22 315/1/22 +f 387/1/22 315/1/22 316/1/22 +f 387/1/22 316/1/22 95/1/22 +f 387/1/22 95/1/22 94/1/22 +f 387/1/22 94/1/22 91/1/22 +f 388/1/22 387/1/22 91/1/22 +f 444/1/22 388/1/22 91/1/22 +f 443/1/22 444/1/22 91/1/22 +f 92/1/297 443/1/297 91/1/297 +f 387/1/22 304/1/22 305/1/22 +f 387/1/22 303/1/22 304/1/22 +f 387/1/22 302/1/22 303/1/22 +f 387/1/22 301/1/22 302/1/22 +f 387/1/22 300/1/22 301/1/22 +f 387/1/22 299/1/22 300/1/22 +f 299/1/22 387/1/22 391/1/22 +f 451/1/22 284/1/22 298/1/22 +f 299/1/22 391/1/22 445/1/22 +f 299/1/22 445/1/22 447/1/22 +f 450/1/22 451/1/22 298/1/22 +f 449/1/22 450/1/22 298/1/22 +f 448/1/22 449/1/22 298/1/22 +f 447/1/22 448/1/22 298/1/22 +f 447/1/22 298/1/22 299/1/22 +f 358/1/22 272/1/22 284/1/22 +f 357/1/22 358/1/22 284/1/22 +f 356/1/22 357/1/22 284/1/22 +f 355/1/22 356/1/22 284/1/22 +f 354/1/22 355/1/22 284/1/22 +f 352/1/22 354/1/22 284/1/22 +f 353/1/22 352/1/22 284/1/22 +f 351/1/22 353/1/22 284/1/22 +f 350/1/22 351/1/22 284/1/22 +f 349/1/22 350/1/22 284/1/22 +f 348/1/22 349/1/22 284/1/22 +f 346/1/22 348/1/22 284/1/22 +f 347/1/22 346/1/22 284/1/22 +f 345/1/22 347/1/22 284/1/22 +f 344/1/22 345/1/22 284/1/22 +f 343/1/22 344/1/22 284/1/22 +f 342/1/22 343/1/22 284/1/22 +f 340/1/22 342/1/22 284/1/22 +f 454/1/22 340/1/22 284/1/22 +f 453/1/22 454/1/22 284/1/22 +f 452/1/22 453/1/22 284/1/22 +f 451/1/22 452/1/22 284/1/22 +f 239/1/22 269/1/22 272/1/22 +f 236/1/22 239/1/22 272/1/22 +f 362/1/22 236/1/22 272/1/22 +f 360/1/22 362/1/22 272/1/22 +f 359/1/22 360/1/22 272/1/22 +f 358/1/22 359/1/22 272/1/22 +f 242/1/22 268/1/22 269/1/22 +f 239/1/22 242/1/22 269/1/22 +f 245/1/22 267/1/22 268/1/22 +f 242/1/22 245/1/22 268/1/22 +f 248/1/22 266/1/22 267/1/22 +f 245/1/22 248/1/22 267/1/22 +f 251/1/22 265/1/22 266/1/22 +f 248/1/22 251/1/22 266/1/22 +f 254/1/22 264/1/22 265/1/22 +f 251/1/22 254/1/22 265/1/22 +f 260/1/22 263/1/22 264/1/22 +f 257/1/22 260/1/22 264/1/22 +f 254/1/22 257/1/22 264/1/22 +f 261/1/22 262/1/22 263/1/22 +f 260/1/22 261/1/22 263/1/22 +f 362/1/22 234/1/22 236/1/22 +f 362/1/22 232/1/22 234/1/22 +f 362/1/22 90/1/22 232/1/22 +f 365/1/22 369/1/22 90/1/22 +f 462/1/22 90/1/22 369/1/22 +f 362/1/22 365/1/22 90/1/22 +f 442/1/22 93/1/22 90/1/22 +f 441/1/22 442/1/22 90/1/22 +f 440/1/22 441/1/22 90/1/22 +f 439/1/22 440/1/22 90/1/22 +f 438/1/22 439/1/22 90/1/22 +f 437/1/22 438/1/22 90/1/22 +f 436/1/22 437/1/22 90/1/22 +f 435/1/22 436/1/22 90/1/22 +f 434/1/22 435/1/22 90/1/22 +f 433/1/22 434/1/22 90/1/22 +f 432/1/22 433/1/22 90/1/22 +f 463/1/22 432/1/22 90/1/22 +f 462/1/22 463/1/22 90/1/22 +f 164/1/22 219/1/22 74/1/22 +f 78/1/22 164/1/22 74/1/22 +f 164/1/22 218/1/22 219/1/22 +f 167/1/22 217/1/22 218/1/22 +f 164/1/22 167/1/22 218/1/22 +f 170/1/22 216/1/22 217/1/22 +f 167/1/22 170/1/22 217/1/22 +f 173/1/22 215/1/22 216/1/22 +f 170/1/22 173/1/22 216/1/22 +f 176/1/22 214/1/22 215/1/22 +f 173/1/22 176/1/22 215/1/22 +f 186/1/22 213/1/22 214/1/22 +f 183/1/22 186/1/22 214/1/22 +f 181/1/22 183/1/22 214/1/22 +f 179/1/22 181/1/22 214/1/22 +f 176/1/22 179/1/22 214/1/22 +f 189/1/22 212/1/22 213/1/22 +f 186/1/22 189/1/22 213/1/22 +f 192/1/22 211/1/22 212/1/22 +f 189/1/22 192/1/22 212/1/22 +f 195/1/22 210/1/22 211/1/22 +f 192/1/22 195/1/22 211/1/22 +f 198/1/22 209/1/22 210/1/22 +f 195/1/22 198/1/22 210/1/22 +f 201/1/22 208/1/22 209/1/22 +f 198/1/22 201/1/22 209/1/22 +f 204/1/22 207/1/22 208/1/22 +f 201/1/22 204/1/22 208/1/22 +f 205/1/22 206/1/22 207/1/22 +f 204/1/22 205/1/22 207/1/22 +f 103/1/22 159/1/22 77/1/22 +f 76/1/22 103/1/22 77/1/22 +f 106/1/22 158/1/22 159/1/22 +f 103/1/22 106/1/22 159/1/22 +f 109/1/22 157/1/22 158/1/22 +f 106/1/22 109/1/22 158/1/22 +f 112/1/22 156/1/22 157/1/22 +f 109/1/22 112/1/22 157/1/22 +f 115/1/22 155/1/22 156/1/22 +f 112/1/22 115/1/22 156/1/22 +f 118/1/22 154/1/22 155/1/22 +f 115/1/22 118/1/22 155/1/22 +f 124/1/22 153/1/22 154/1/22 +f 118/1/22 124/1/22 154/1/22 +f 124/1/22 152/1/22 153/1/22 +f 124/1/22 151/1/22 152/1/22 +f 127/1/22 150/1/22 151/1/22 +f 124/1/22 127/1/22 151/1/22 +f 130/1/22 149/1/22 150/1/22 +f 127/1/22 130/1/22 150/1/22 +f 133/1/22 148/1/22 149/1/22 +f 130/1/22 133/1/22 149/1/22 +f 136/1/22 147/1/22 148/1/22 +f 133/1/22 136/1/22 148/1/22 +f 139/1/22 146/1/22 147/1/22 +f 136/1/22 139/1/22 147/1/22 +f 142/1/22 145/1/22 146/1/22 +f 139/1/22 142/1/22 146/1/22 +f 143/1/22 144/1/22 145/1/22 +f 142/1/22 143/1/22 145/1/22 +f 455/1/22 322/1/22 320/1/22 +f 455/1/22 320/1/22 325/1/22 +f 455/1/22 386/1/22 322/1/22 +f 455/1/22 384/1/22 386/1/22 +f 455/1/22 379/1/22 384/1/22 +f 457/1/22 381/1/22 379/1/22 +f 456/1/22 379/1/22 455/1/22 +f 456/1/22 457/1/22 379/1/22 +f 458/1/22 376/1/22 381/1/22 +f 457/1/22 458/1/22 381/1/22 +f 460/1/22 372/1/22 376/1/22 +f 459/1/22 460/1/22 376/1/22 +f 458/1/22 459/1/22 376/1/22 +f 462/1/22 369/1/22 372/1/22 +f 461/1/22 462/1/22 372/1/22 +f 460/1/22 461/1/22 372/1/22 +f 455/1/22 339/1/22 340/1/22 +f 454/1/22 455/1/22 340/1/22 +f 455/1/22 338/1/22 339/1/22 +f 455/1/22 336/1/22 338/1/22 +f 455/1/22 334/1/22 336/1/22 +f 455/1/22 331/1/22 334/1/22 +f 455/1/22 329/1/22 331/1/22 +f 455/1/22 327/1/22 329/1/22 +f 455/1/22 324/1/22 327/1/22 +f 455/1/22 325/1/22 324/1/22 +f 445/1/22 391/1/22 394/1/22 +f 464/1/22 431/1/22 432/1/22 +f 463/1/22 464/1/22 432/1/22 +f 464/1/22 430/1/22 431/1/22 +f 465/1/22 428/1/22 430/1/22 +f 464/1/22 465/1/22 430/1/22 +f 465/1/22 425/1/22 428/1/22 +f 466/1/22 422/1/22 425/1/22 +f 465/1/22 466/1/22 425/1/22 +f 467/1/22 419/1/22 422/1/22 +f 466/1/22 467/1/22 422/1/22 +f 471/1/22 414/1/22 419/1/22 +f 470/1/22 471/1/22 419/1/22 +f 469/1/22 470/1/22 419/1/22 +f 468/1/22 469/1/22 419/1/22 +f 467/1/22 468/1/22 419/1/22 +f 472/1/22 411/1/22 414/1/22 +f 471/1/22 472/1/22 414/1/22 +f 472/1/22 409/1/22 411/1/22 +f 472/1/22 407/1/22 409/1/22 +f 472/1/22 404/1/22 407/1/22 +f 473/1/22 401/1/22 404/1/22 +f 472/1/22 473/1/22 404/1/22 +f 474/1/22 398/1/22 401/1/22 +f 473/1/22 474/1/22 401/1/22 +f 476/1/22 394/1/22 398/1/22 +f 475/1/22 476/1/22 398/1/22 +f 474/1/22 475/1/22 398/1/22 +f 446/1/22 445/1/22 394/1/22 +f 476/1/22 446/1/22 394/1/22 diff --git a/resources/meshes/bambulabs-3dp-X1.obj b/resources/meshes/bambulab_x1.obj similarity index 100% rename from resources/meshes/bambulabs-3dp-X1.obj rename to resources/meshes/bambulab_x1.obj diff --git a/resources/quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg b/resources/quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg new file mode 100644 index 0000000000..ca75694f01 --- /dev/null +++ b/resources/quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg @@ -0,0 +1,14 @@ +[general] +definition = bambulab_a1mini +name = Standard +version = 4 + +[metadata] +material = generic_pla +quality_type = normal +setting_version = 23 +type = quality +variant = A1 0.4mm + +[values] + diff --git a/resources/quality/bambu/bambulab_a1mini_normal.inst.cfg b/resources/quality/bambu/bambulab_a1mini_normal.inst.cfg new file mode 100644 index 0000000000..a5dc2aaa4b --- /dev/null +++ b/resources/quality/bambu/bambulab_a1mini_normal.inst.cfg @@ -0,0 +1,15 @@ +[general] +definition = bambulab_a1mini +name = Normal +version = 4 + +[metadata] +global_quality = True +quality_type = normal +setting_version = 22 +type = quality +weight = 0 + +[values] +layer_height = 0.2 + diff --git a/resources/quality/bambu/bambulabs_x1_0.4_PLA_standard.inst.cfg b/resources/quality/bambu/bambulab_x1_0.4_PLA_standard.inst.cfg similarity index 86% rename from resources/quality/bambu/bambulabs_x1_0.4_PLA_standard.inst.cfg rename to resources/quality/bambu/bambulab_x1_0.4_PLA_standard.inst.cfg index e0c4b3e9cb..282ecefc55 100644 --- a/resources/quality/bambu/bambulabs_x1_0.4_PLA_standard.inst.cfg +++ b/resources/quality/bambu/bambulab_x1_0.4_PLA_standard.inst.cfg @@ -1,5 +1,5 @@ [general] -definition = bambulabs_x1 +definition = bambulab_x1 name = Standard version = 4 diff --git a/resources/quality/bambu/bambulabs_x1_normal.inst.cfg b/resources/quality/bambu/bambulab_x1_normal.inst.cfg similarity index 86% rename from resources/quality/bambu/bambulabs_x1_normal.inst.cfg rename to resources/quality/bambu/bambulab_x1_normal.inst.cfg index 524031f31b..6ea1c1ffea 100644 --- a/resources/quality/bambu/bambulabs_x1_normal.inst.cfg +++ b/resources/quality/bambu/bambulab_x1_normal.inst.cfg @@ -1,5 +1,5 @@ [general] -definition = bambulabs_x1 +definition = bambulab_x1 name = Normal version = 4 diff --git a/resources/quality/bambu/bambulabs_x1c_0.4_PLA_standard.inst.cfg b/resources/quality/bambu/bambulab_x1c_0.4_PLA_standard.inst.cfg similarity index 86% rename from resources/quality/bambu/bambulabs_x1c_0.4_PLA_standard.inst.cfg rename to resources/quality/bambu/bambulab_x1c_0.4_PLA_standard.inst.cfg index f820de5ece..c71b9ecab8 100644 --- a/resources/quality/bambu/bambulabs_x1c_0.4_PLA_standard.inst.cfg +++ b/resources/quality/bambu/bambulab_x1c_0.4_PLA_standard.inst.cfg @@ -1,5 +1,5 @@ [general] -definition = bambulabs_x1 +definition = bambulab_x1 name = Standard version = 4 diff --git a/resources/variants/bambu/bambulab_a1_0.4.inst.cfg b/resources/variants/bambu/bambulab_a1_0.4.inst.cfg new file mode 100644 index 0000000000..73cf569f8a --- /dev/null +++ b/resources/variants/bambu/bambulab_a1_0.4.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = bambulab_a1mini +name = A1 0.4mm +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 23 +type = variant + +[values] +machine_nozzle_size = 0.4 + diff --git a/resources/variants/bambu/bambulabs_p1s_0.4.inst.cfg b/resources/variants/bambu/bambulab_p1p_0.4.inst.cfg similarity index 84% rename from resources/variants/bambu/bambulabs_p1s_0.4.inst.cfg rename to resources/variants/bambu/bambulab_p1p_0.4.inst.cfg index ca346e0b5f..e649c718b6 100644 --- a/resources/variants/bambu/bambulabs_p1s_0.4.inst.cfg +++ b/resources/variants/bambu/bambulab_p1p_0.4.inst.cfg @@ -1,5 +1,5 @@ [general] -definition = bambulabs_x1 +definition = bambulab_x1 name = P1P 0.4mm version = 4 diff --git a/resources/variants/bambu/bambulabs_p1p_0.4.inst.cfg b/resources/variants/bambu/bambulab_p1s_0.4.inst.cfg similarity index 84% rename from resources/variants/bambu/bambulabs_p1p_0.4.inst.cfg rename to resources/variants/bambu/bambulab_p1s_0.4.inst.cfg index ca346e0b5f..e649c718b6 100644 --- a/resources/variants/bambu/bambulabs_p1p_0.4.inst.cfg +++ b/resources/variants/bambu/bambulab_p1s_0.4.inst.cfg @@ -1,5 +1,5 @@ [general] -definition = bambulabs_x1 +definition = bambulab_x1 name = P1P 0.4mm version = 4 diff --git a/resources/variants/bambu/bambulabs_x1_0.4.inst.cfg b/resources/variants/bambu/bambulab_x1_0.4.inst.cfg similarity index 84% rename from resources/variants/bambu/bambulabs_x1_0.4.inst.cfg rename to resources/variants/bambu/bambulab_x1_0.4.inst.cfg index 449c1289a7..3f42f77494 100644 --- a/resources/variants/bambu/bambulabs_x1_0.4.inst.cfg +++ b/resources/variants/bambu/bambulab_x1_0.4.inst.cfg @@ -1,5 +1,5 @@ [general] -definition = bambulabs_x1 +definition = bambulab_x1 name = X1 0.4mm version = 4 diff --git a/resources/variants/bambu/bambulabs_x1c_0.4.inst.cfg b/resources/variants/bambu/bambulab_x1c_0.4.inst.cfg similarity index 84% rename from resources/variants/bambu/bambulabs_x1c_0.4.inst.cfg rename to resources/variants/bambu/bambulab_x1c_0.4.inst.cfg index dea4010809..58cabff35e 100644 --- a/resources/variants/bambu/bambulabs_x1c_0.4.inst.cfg +++ b/resources/variants/bambu/bambulab_x1c_0.4.inst.cfg @@ -1,5 +1,5 @@ [general] -definition = bambulabs_x1 +definition = bambulab_x1 name = X1C 0.4mm version = 4 From db72527b6bf939fe01433fb13f34c83bd468e5e0 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 4 Apr 2025 11:07:32 +0200 Subject: [PATCH 068/299] Basically working A1 mini (single color) CURA-12074 --- resources/definitions/bambulab_a1mini.def.json | 6 +++--- resources/extruders/bambulab_x1_extruder_0.def.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index b7dcec29f6..d5410046fc 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -103,7 +103,7 @@ "machine_acceleration": { "value": 10000 }, "machine_center_is_zero": { "value": false }, "machine_depth": { "value": 180 }, - "machine_end_gcode": { "default_value": "M400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos \nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of \"timelapse_record_flag\"\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (machine_height + 100.0) < 25}\n G1 Z{machine_height + 100.0} F600\n G1 Z{machine_height +98.0}\n{else}\n G1 Z250 F600\n G1 Z248\n{endif}\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X128 Y250 F3600\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\n" }, + "machine_end_gcode": { "default_value": ";===== date: 20231229 =====================\n;turn off nozzle clog detect\nG392 S0\n\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X0 Y{machine_depth} F18000 ; move to safe pos\nG1 X-13.0 F3000 ; move to safe pos\n{if !magic_spiralize && print_sequence != 'one_at_a_time'}\nM1002 judge_flag timelapse_record_flag\nM622 J1\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM991 S0 P-1 ;end timelapse at safe pos\nM623\n{endif}\n\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\n;G1 X27 F15000 ; wipe\n\n; pull back filament to AMS\nM620 S255\nG1 X181 F12000\nT255\nG1 X0 F18000\nG1 X-13.0 F3000\nG1 X0 F18000 ; wipe\nM621 S255\n\nM104 S0 ; turn off hotend\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\nG1 Z180 F600\nG1 Z180\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X-13 Y180 F3600\n\nG91\nG1 Z-1 F600\nG90\nM83\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\n;=====printer finish sound=========\nM17\nM400 S1\nM1006 S1\nM1006 A0 B20 L100 C37 D20 M100 E42 F20 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C46 D10 M100 E46 F10 N100\nM1006 A44 B20 L100 C39 D20 M100 E48 F20 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C39 D10 M100 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C39 D10 M100 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B10 L100 C0 D10 M100 E48 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B20 L100 C41 D20 M100 E49 F20 N100\nM1006 A0 B20 L100 C0 D20 M100 E0 F20 N100\nM1006 A0 B20 L100 C37 D20 M100 E37 F20 N100\nM1006 W\n;=====printer finish sound=========\nM400 S1\nM18 X Y Z\n" }, "machine_extruder_count": { "value": 4 }, "machine_heated_bed": { "value": true }, "machine_height": { "value": 175 }, @@ -119,7 +119,7 @@ "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, "machine_nozzle_size": { "value": 0.4 }, "machine_show_variants": { "value": true }, - "machine_start_gcode": { "default_value": ";===== machine: X1 =========================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_bed_temperature_layer_0} ;wait for bed temp\n\n;=========register first layer scan=====\n{if machine_scan_first_layer}\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T{initial_extruder_nr}\n G1 X54 F12000\n G1 Y265\n M400\nM621 S{initial_extruder_nr}A\nM620.1 E F{material_max_flowrate/2.4053*60} T{material_print_temperature, initial_extruder_nr}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if machine_scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{material_print_temperature, initial_extruder_nr}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y11 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n{if machine_buildplate=='textured_pei_plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if acceleration_wall_0 > 0, initial_extruder_nr}\n M204 S{acceleration_wall_0, initial_extruder_nr}\n {else}\n M204 S{acceleration_print, initial_extruder_nr}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{material_print_temperature, initial_extruder_nr} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60/4} C5.000 D{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60, initial_extruder_nr} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{material_print_temperature, initial_extruder_nr}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X185.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X190.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X195.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X200.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X205.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X210.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X215.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X220.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X225.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_amount, initial_extruder_nr} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_amount, initial_extruder_nr} F1800\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nG0 X253 E6.4 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.6) * 60, initial_extruder_nr}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" }, + "machine_start_gcode": { "default_value": ";===== machine: A1 mini =========================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S170\nM140 S{material_bed_temperature_layer_0}\nG392 S0 ;turn off clog detect\nM9833.2\n;=====start printer sound ===================\nM17\nM400 S1\nM1006 S1\nM1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\nM1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\nM1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\nM1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\nM1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-13.5 F3000\n M400\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\n M104 S{material_print_temperature, initial_extruder_nr}\n G92 E0\n G1 E50 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\n M104 S{material_print_temperature_layer_0-40, material_print_temperature_layer_0}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{material_print_temperature_layer_0-40, initial_extruder_nr}\n G392 S0 ;turn off clog detect\nM621 S{initial_extruder_nr}A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\nM1002 gcode_claim_action : 3\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S{material_bed_temperature_layer_0};set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n\n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.3 F18000 ;Move to start position\n M400\n G0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 Y0 Z0 F20000\n M400\n\n G1 X-13.5 Y0 Z10 F10000\n M400\n\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of 'draw extrinsic para cali paint'\n\n;===== extrude cali test ===============================\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.3 F18000 ;Move to start position\nG0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\nG0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate=='Textured PEI Plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n" }, "machine_use_extruder_offset_to_offset_coords": { "value": false }, "machine_width": { "value": 180 }, "material_diameter": { "value": 1.75 }, @@ -157,7 +157,7 @@ "speed_layer_0": { "maximum_value_warning": 500, - "value": "speed_wall" + "value": "speed_print/6" }, "speed_prime_tower": { diff --git a/resources/extruders/bambulab_x1_extruder_0.def.json b/resources/extruders/bambulab_x1_extruder_0.def.json index c405dc6431..a25f79212b 100644 --- a/resources/extruders/bambulab_x1_extruder_0.def.json +++ b/resources/extruders/bambulab_x1_extruder_0.def.json @@ -11,7 +11,7 @@ { "extruder_nr": { "default_value": 0 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": "M104 S{material_standby_temperature}\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, + "machine_extruder_end_code": { "default_value": "M620 S[next_extruder]A\nM204 S9000\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E-{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\n{else}\nM620.11 S0\n{endif}\nM400\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\nM628 S1\nG92 E0\nG1 E{retraction_distances_when_cut[previous_extruder]} F[old_filament_e_feedrate]\nM400\nM629 S1\n{else}\nM620.11 S0\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == 'PETG'}\nM109 S260\n{elsif filament_type[next_extruder] == 'PVA'}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" }, "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, "material_diameter": { "default_value": 1.75 } } From d78d19820b0138fdcaacd20e136dbf3d08c0223c Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Fri, 4 Apr 2025 08:27:10 -0400 Subject: [PATCH 069/299] Update PurgeLinesAndUnload.py Missed a newline in line 499. --- plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py b/plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py index a356fec379..ca95359e29 100644 --- a/plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py +++ b/plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py @@ -496,7 +496,7 @@ class PurgeLinesAndUnload(Script): """Generates G-code lines for prime blob adjustment.""" gcode_lines = [ f"G1 F{retract_speed} E{retract_distance} ; Unretract", - "G92 E0 ; Reset extruder" + "G92 E0 ; Reset extruder\n" ] return "\n".join(gcode_lines) From 014ed05e73fda4d6c932a879c3058f2aca27b7b3 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 9 Apr 2025 12:03:27 +0200 Subject: [PATCH 070/299] Basically working A1 mini (multi-color) CURA-12074 --- resources/definitions/bambulab_a1mini.def.json | 3 +++ resources/definitions/fdmprinter.def.json | 3 ++- resources/extruders/bambulab_a1mini_extruder_0.def.json | 7 ++++--- resources/extruders/bambulab_a1mini_extruder_1.def.json | 9 +++++---- resources/extruders/bambulab_a1mini_extruder_2.def.json | 9 +++++---- resources/extruders/bambulab_a1mini_extruder_3.def.json | 9 +++++---- 6 files changed, 24 insertions(+), 16 deletions(-) diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index d5410046fc..c36be92e47 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -105,6 +105,7 @@ "machine_depth": { "value": 180 }, "machine_end_gcode": { "default_value": ";===== date: 20231229 =====================\n;turn off nozzle clog detect\nG392 S0\n\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X0 Y{machine_depth} F18000 ; move to safe pos\nG1 X-13.0 F3000 ; move to safe pos\n{if !magic_spiralize && print_sequence != 'one_at_a_time'}\nM1002 judge_flag timelapse_record_flag\nM622 J1\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM991 S0 P-1 ;end timelapse at safe pos\nM623\n{endif}\n\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\n;G1 X27 F15000 ; wipe\n\n; pull back filament to AMS\nM620 S255\nG1 X181 F12000\nT255\nG1 X0 F18000\nG1 X-13.0 F3000\nG1 X0 F18000 ; wipe\nM621 S255\n\nM104 S0 ; turn off hotend\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\nG1 Z180 F600\nG1 Z180\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X-13 Y180 F3600\n\nG91\nG1 Z-1 F600\nG90\nM83\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\n;=====printer finish sound=========\nM17\nM400 S1\nM1006 S1\nM1006 A0 B20 L100 C37 D20 M100 E42 F20 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C46 D10 M100 E46 F10 N100\nM1006 A44 B20 L100 C39 D20 M100 E48 F20 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C39 D10 M100 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C39 D10 M100 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B10 L100 C0 D10 M100 E48 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B20 L100 C41 D20 M100 E49 F20 N100\nM1006 A0 B20 L100 C0 D20 M100 E0 F20 N100\nM1006 A0 B20 L100 C37 D20 M100 E37 F20 N100\nM1006 W\n;=====printer finish sound=========\nM400 S1\nM18 X Y Z\n" }, "machine_extruder_count": { "value": 4 }, + "machine_gcode_flavor": { "value": "BambuLab" }, "machine_heated_bed": { "value": true }, "machine_height": { "value": 175 }, "machine_max_feedrate_e": { "value": 150 }, @@ -122,11 +123,13 @@ "machine_start_gcode": { "default_value": ";===== machine: A1 mini =========================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S170\nM140 S{material_bed_temperature_layer_0}\nG392 S0 ;turn off clog detect\nM9833.2\n;=====start printer sound ===================\nM17\nM400 S1\nM1006 S1\nM1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\nM1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\nM1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\nM1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\nM1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-13.5 F3000\n M400\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\n M104 S{material_print_temperature, initial_extruder_nr}\n G92 E0\n G1 E50 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\n M104 S{material_print_temperature_layer_0-40, material_print_temperature_layer_0}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{material_print_temperature_layer_0-40, initial_extruder_nr}\n G392 S0 ;turn off clog detect\nM621 S{initial_extruder_nr}A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\nM1002 gcode_claim_action : 3\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S{material_bed_temperature_layer_0};set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n\n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.3 F18000 ;Move to start position\n M400\n G0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 Y0 Z0 F20000\n M400\n\n G1 X-13.5 Y0 Z10 F10000\n M400\n\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of 'draw extrinsic para cali paint'\n\n;===== extrude cali test ===============================\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.3 F18000 ;Move to start position\nG0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\nG0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate=='Textured PEI Plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n" }, "machine_use_extruder_offset_to_offset_coords": { "value": false }, "machine_width": { "value": 180 }, + "material_flush_purge_speed": { "default_value": 500 }, "material_diameter": { "value": 1.75 }, "max_skin_angle_for_expansion": { "value": 45 }, "meshfix_maximum_resolution": { "value": 0.4 }, "min_infill_area": { "default_value": 10 }, "optimize_wall_printing_order": { "value": false }, + "prime_tower_min_volume": { "default_value": 100 }, "relative_extrusion": { "value": true }, "retraction_amount": { "value": 0.5 }, "retraction_combing_max_distance": { "value": 100 }, diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index b42b5c417a..f0019da331 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -388,7 +388,8 @@ "Makerbot": "Makerbot", "BFB": "Bits from Bytes", "MACH3": "Mach3", - "Repetier": "Repetier" + "Repetier": "Repetier", + "BambuLab": "BambuLab" }, "default_value": "RepRap (Marlin/Sprinter)", "settable_per_mesh": false, diff --git a/resources/extruders/bambulab_a1mini_extruder_0.def.json b/resources/extruders/bambulab_a1mini_extruder_0.def.json index 63ceeb76d3..960c4b0171 100644 --- a/resources/extruders/bambulab_a1mini_extruder_0.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_0.def.json @@ -11,8 +11,9 @@ { "extruder_nr": { "default_value": 0 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": "M104 S{material_standby_temperature}\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, - "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, - "material_diameter": { "default_value": 1.75 } + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-{switch_extruder_retraction_amount, extruder_nr} F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{(prime_tower_min_volume/(line_width*layer_height)) / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, + "material_diameter": { "default_value": 1.75 }, + "switch_extruder_retraction_amount": { "default_value": 18 } } } \ No newline at end of file diff --git a/resources/extruders/bambulab_a1mini_extruder_1.def.json b/resources/extruders/bambulab_a1mini_extruder_1.def.json index ba4dc63cfe..201889d569 100644 --- a/resources/extruders/bambulab_a1mini_extruder_1.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_1.def.json @@ -9,10 +9,11 @@ }, "overrides": { - "extruder_nr": { "default_value": 0 }, + "extruder_nr": { "default_value": 1 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": "M104 S{material_standby_temperature}\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, - "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, - "material_diameter": { "default_value": 1.75 } + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-{switch_extruder_retraction_amount, extruder_nr} F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{(prime_tower_min_volume/(line_width*layer_height)) / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, + "material_diameter": { "default_value": 1.75 }, + "switch_extruder_retraction_amount": { "default_value": 18 } } } \ No newline at end of file diff --git a/resources/extruders/bambulab_a1mini_extruder_2.def.json b/resources/extruders/bambulab_a1mini_extruder_2.def.json index 7793b3e8a8..3490418c01 100644 --- a/resources/extruders/bambulab_a1mini_extruder_2.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_2.def.json @@ -9,10 +9,11 @@ }, "overrides": { - "extruder_nr": { "default_value": 0 }, + "extruder_nr": { "default_value": 2 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": "M104 S{material_standby_temperature}\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, - "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, - "material_diameter": { "default_value": 1.75 } + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-{switch_extruder_retraction_amount, extruder_nr} F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{(prime_tower_min_volume/(line_width*layer_height)) / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, + "material_diameter": { "default_value": 1.75 }, + "switch_extruder_retraction_amount": { "default_value": 18 } } } \ No newline at end of file diff --git a/resources/extruders/bambulab_a1mini_extruder_3.def.json b/resources/extruders/bambulab_a1mini_extruder_3.def.json index 15447f6f41..60428e4f02 100644 --- a/resources/extruders/bambulab_a1mini_extruder_3.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_3.def.json @@ -9,10 +9,11 @@ }, "overrides": { - "extruder_nr": { "default_value": 0 }, + "extruder_nr": { "default_value": 3 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": "M104 S{material_standby_temperature}\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, - "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, - "material_diameter": { "default_value": 1.75 } + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-{switch_extruder_retraction_amount, extruder_nr} F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{(prime_tower_min_volume/(line_width*layer_height)) / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, + "material_diameter": { "default_value": 1.75 }, + "switch_extruder_retraction_amount": { "default_value": 18 } } } \ No newline at end of file From 931dc1343274ca2dd59e549e24da45b58940c079 Mon Sep 17 00:00:00 2001 From: wawanbreton <601114+wawanbreton@users.noreply.github.com> Date: Wed, 9 Apr 2025 10:05:05 +0000 Subject: [PATCH 071/299] Apply printer-linter format --- resources/definitions/bambulab_a1mini.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index c36be92e47..3e4b85ec57 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -123,8 +123,8 @@ "machine_start_gcode": { "default_value": ";===== machine: A1 mini =========================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S170\nM140 S{material_bed_temperature_layer_0}\nG392 S0 ;turn off clog detect\nM9833.2\n;=====start printer sound ===================\nM17\nM400 S1\nM1006 S1\nM1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\nM1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\nM1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\nM1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\nM1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-13.5 F3000\n M400\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\n M104 S{material_print_temperature, initial_extruder_nr}\n G92 E0\n G1 E50 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\n M104 S{material_print_temperature_layer_0-40, material_print_temperature_layer_0}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{material_print_temperature_layer_0-40, initial_extruder_nr}\n G392 S0 ;turn off clog detect\nM621 S{initial_extruder_nr}A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\nM1002 gcode_claim_action : 3\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S{material_bed_temperature_layer_0};set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n\n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.3 F18000 ;Move to start position\n M400\n G0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 Y0 Z0 F20000\n M400\n\n G1 X-13.5 Y0 Z10 F10000\n M400\n\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of 'draw extrinsic para cali paint'\n\n;===== extrude cali test ===============================\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.3 F18000 ;Move to start position\nG0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\nG0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate=='Textured PEI Plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n" }, "machine_use_extruder_offset_to_offset_coords": { "value": false }, "machine_width": { "value": 180 }, - "material_flush_purge_speed": { "default_value": 500 }, "material_diameter": { "value": 1.75 }, + "material_flush_purge_speed": { "default_value": 500 }, "max_skin_angle_for_expansion": { "value": 45 }, "meshfix_maximum_resolution": { "value": 0.4 }, "min_infill_area": { "default_value": 10 }, From 7789c86c521b6995db59f942829e08283f56dc34 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 9 Apr 2025 15:29:40 +0200 Subject: [PATCH 072/299] Improved A1 mini multi-color printing CURA-12074 --- resources/definitions/bambulab_a1mini.def.json | 6 ++++++ resources/extruders/bambulab_a1mini_extruder_0.def.json | 4 ++-- resources/extruders/bambulab_a1mini_extruder_1.def.json | 4 ++-- resources/extruders/bambulab_a1mini_extruder_2.def.json | 4 ++-- resources/extruders/bambulab_a1mini_extruder_3.def.json | 4 ++-- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 3e4b85ec57..111ec67bbb 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -124,10 +124,16 @@ "machine_use_extruder_offset_to_offset_coords": { "value": false }, "machine_width": { "value": 180 }, "material_diameter": { "value": 1.75 }, + "material_flush_purge_length": + { + "default_value": 100, + "enabled": true + }, "material_flush_purge_speed": { "default_value": 500 }, "max_skin_angle_for_expansion": { "value": 45 }, "meshfix_maximum_resolution": { "value": 0.4 }, "min_infill_area": { "default_value": 10 }, + "switch_extruder_retraction_amount": { "value": 5 }, "optimize_wall_printing_order": { "value": false }, "prime_tower_min_volume": { "default_value": 100 }, "relative_extrusion": { "value": true }, diff --git a/resources/extruders/bambulab_a1mini_extruder_0.def.json b/resources/extruders/bambulab_a1mini_extruder_0.def.json index 960c4b0171..a9d6dedb7e 100644 --- a/resources/extruders/bambulab_a1mini_extruder_0.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_0.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 0 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-{switch_extruder_retraction_amount, extruder_nr} F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, - "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{(prime_tower_min_volume/(line_width*layer_height)) / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E18 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E18 F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } } diff --git a/resources/extruders/bambulab_a1mini_extruder_1.def.json b/resources/extruders/bambulab_a1mini_extruder_1.def.json index 201889d569..a01dd4294f 100644 --- a/resources/extruders/bambulab_a1mini_extruder_1.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_1.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 1 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-{switch_extruder_retraction_amount, extruder_nr} F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, - "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{(prime_tower_min_volume/(line_width*layer_height)) / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E18 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E18 F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } } diff --git a/resources/extruders/bambulab_a1mini_extruder_2.def.json b/resources/extruders/bambulab_a1mini_extruder_2.def.json index 3490418c01..e8490ed1ea 100644 --- a/resources/extruders/bambulab_a1mini_extruder_2.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_2.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 2 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-{switch_extruder_retraction_amount, extruder_nr} F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, - "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{(prime_tower_min_volume/(line_width*layer_height)) / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E18 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E18 F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } } diff --git a/resources/extruders/bambulab_a1mini_extruder_3.def.json b/resources/extruders/bambulab_a1mini_extruder_3.def.json index 60428e4f02..7d45756318 100644 --- a/resources/extruders/bambulab_a1mini_extruder_3.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_3.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 3 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-{switch_extruder_retraction_amount, extruder_nr} F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E{switch_extruder_retraction_amount, extruder_nr} F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, - "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{(prime_tower_min_volume/(line_width*layer_height)) / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{((prime_tower_min_volume/(line_width*layer_height)) / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E18 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E18 F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } } From b0460cee258f02a448687ca1533d19cc4b649c52 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 9 Apr 2025 15:33:29 +0200 Subject: [PATCH 073/299] Set A1 mini proper name CURA-12074 --- resources/definitions/bambulab_a1mini.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 111ec67bbb..3fa7e88236 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -115,7 +115,7 @@ "machine_max_jerk_e": { "default_value": 100 }, "machine_max_jerk_xy": { "default_value": 5000 }, "machine_max_jerk_z": { "default_value": 100 }, - "machine_name": { "default_value": "BambuLabs Bambu X1" }, + "machine_name": { "default_value": "BambuLabs Bambu A1 mini" }, "machine_nozzle_cool_down_speed": { "default_value": 1.3 }, "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, "machine_nozzle_size": { "value": 0.4 }, From 6601dcebd29aee4a53a34e57c8d8189975575062 Mon Sep 17 00:00:00 2001 From: wawanbreton <601114+wawanbreton@users.noreply.github.com> Date: Wed, 9 Apr 2025 13:35:11 +0000 Subject: [PATCH 074/299] Apply printer-linter format --- resources/definitions/bambulab_a1mini.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 3fa7e88236..7ec683da35 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -133,7 +133,6 @@ "max_skin_angle_for_expansion": { "value": 45 }, "meshfix_maximum_resolution": { "value": 0.4 }, "min_infill_area": { "default_value": 10 }, - "switch_extruder_retraction_amount": { "value": 5 }, "optimize_wall_printing_order": { "value": false }, "prime_tower_min_volume": { "default_value": 100 }, "relative_extrusion": { "value": true }, @@ -263,6 +262,7 @@ "support_infill_rate": { "value": "80 if gradual_support_infill_steps != 0 else 15" }, "support_pattern": { "value": "'gyroid'" }, "support_structure": { "value": "'tree'" }, + "switch_extruder_retraction_amount": { "value": 5 }, "travel_avoid_other_parts": { "value": false }, "wall_0_acceleration": { "value": 1000 }, "wall_0_deceleration": { "value": 1000 }, From fc1404139c8b66cd5a37bb97fbcf01aaad4687fb Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 9 Apr 2025 15:37:07 +0200 Subject: [PATCH 075/299] Set A1 mini proper nozzle name CURA-12074 --- resources/definitions/bambulab_a1mini.def.json | 2 +- .../quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg | 2 +- resources/variants/bambu/bambulab_a1_0.4.inst.cfg | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 7ec683da35..414eba0065 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -27,7 +27,7 @@ 90 ], "platform_texture": "bambulab-buildplate.png", - "preferred_variant_name": "X1C 0.4mm", + "preferred_variant_name": "0.4mm", "weight": 3 }, "overrides": diff --git a/resources/quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg b/resources/quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg index ca75694f01..4a412b07a3 100644 --- a/resources/quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg +++ b/resources/quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg @@ -8,7 +8,7 @@ material = generic_pla quality_type = normal setting_version = 23 type = quality -variant = A1 0.4mm +variant = 0.4mm [values] diff --git a/resources/variants/bambu/bambulab_a1_0.4.inst.cfg b/resources/variants/bambu/bambulab_a1_0.4.inst.cfg index 73cf569f8a..357c894b8c 100644 --- a/resources/variants/bambu/bambulab_a1_0.4.inst.cfg +++ b/resources/variants/bambu/bambulab_a1_0.4.inst.cfg @@ -1,6 +1,6 @@ [general] definition = bambulab_a1mini -name = A1 0.4mm +name = 0.4mm version = 4 [metadata] From e1246beb67966b035492bd217a93af532a4e0509 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 12 Apr 2025 14:11:09 -0400 Subject: [PATCH 076/299] Update DisplayInfoOnLCD.py Minor changes to the statistics added to the beginning of the gcode. --- .../scripts/DisplayInfoOnLCD.py | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 85b9744856..abff57c804 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -319,7 +319,7 @@ class DisplayInfoOnLCD(Script): # This is from 'Show Progress on LCD' def _display_progress(self, data: str) -> str: - # Add some print settings to the start of the gcode + # Add some common print settings to the start of the gcode data[0] = self._add_stats(data) # Get settings print_sequence = Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") @@ -344,6 +344,7 @@ class DisplayInfoOnLCD(Script): # If at least one of the settings is disabled, there is enough room on the display to display "layer" first_section = data[0] lines = first_section.split("\n") + pause_cmd = [] for line in lines: if line.startswith(";TIME:"): tindex = lines.index(line) @@ -530,7 +531,9 @@ class DisplayInfoOnLCD(Script): return data def _message_to_user(self, data: str, speed_factor: float, pause_cmd: str) -> str: - # Message the user of the projected finish time of the print + """ + Message the user of the projected finish time of the print and when any pauses might occur + """ print_time = Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601) print_start_time = self.getSettingValueByKey("print_start_time") # If the user entered a print start time make sure it is in the correct format or ignore it. @@ -623,7 +626,10 @@ class DisplayInfoOnLCD(Script): def _add_stats(self, data: str) -> str: global_stack = Application.getInstance().getGlobalContainerStack() - # Create a list of the models in the file + """ + Make a list of the models in the file. + Add some of the filament stats to the first section of the gcode. + """ model_list = [] for mdex, layer in enumerate(data): layer = data[mdex].split("\n") @@ -632,22 +638,34 @@ class DisplayInfoOnLCD(Script): model_name = line.split(":")[1] if not model_name in model_list: model_list.append(model_name) - # Add some settings to data[0] + # Filament stats extruder_count = global_stack.getProperty("machine_extruder_count", "value") init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) - nozzle_size_line = ";Nozzle Size (T0): " + str(global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")) - filament_type = "\n;Filament Type (T0): " + str(global_stack.extruderList[0].material.getMetaDataEntry("material", "")) - print_temperature_line = ";Print Temperature (T0): " + str(global_stack.extruderList[0].getProperty("material_print_temperature", "value")) + filament_line_t0 = ";Extruder 1 (T0)\n" + filament_amount = Application.getInstance().getPrintInformation().materialLengths + filament_line_t0 += f"; Filament used: {filament_amount[0]}m\n" + filament_line_t0 += f"; Filament Type: {global_stack.extruderList[0].material.getMetaDataEntry("material", "")}\n" + filament_line_t0 += f"; Filament Dia.: {global_stack.extruderList[0].getProperty("material_diameter", "value")}mm\n" + filament_line_t0 += f"; Nozzle Size : {global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")}mm\n" + filament_line_t0 += f"; Print Temp. : {global_stack.extruderList[0].getProperty("material_print_temperature", "value")}°" + + # if there is more than one extruder then get the stats for the second one. + filament_line_t1 = "" if extruder_count > 1: - nozzle_size_line += "\n;Nozzle Size (T1): " + str(global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")) - filament_type += "\n;Filament type (T1): " + str(global_stack.extruderList[1].material.getMetaDataEntry("material", "")) - print_temperature_line += "\n;Print Temperature (T1): " + str(global_stack.extruderList[1].getProperty("material_print_temperature", "value")) + filament_line_t1 = "\n;Extruder 2 (T1)\n" + filament_line_t1 += f"; Filament used: {filament_amount[1]}m\n" + filament_line_t1 += f"; Filament Type: {global_stack.extruderList[1].material.getMetaDataEntry("material", "")}\n" + filament_line_t1 += f"; Filament Dia.: {global_stack.extruderList[1].getProperty("material_diameter", "value")}mm\n" + filament_line_t1 += f"; Nozzle Size : {global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")}mm\n" + filament_line_t1 += f"; Print Temp. : {global_stack.extruderList[1].getProperty("material_print_temperature", "value")}°" + + # Add the stats to the gcode file lines = data[0].split("\n") for index, line in enumerate(lines): if line.startswith(";Layer height:"): - lines[index] += "\n" + init_layer_hgt_line + "\n" + nozzle_size_line + "\n" + print_temperature_line + lines[index] += "\n" + init_layer_hgt_line if line.startswith(";Filament used"): - lines[index] += filament_type + lines[index] = filament_line_t0 + filament_line_t1 if "MINX" in line or "MIN.X" in line: # Add the model list lines[index - 1] += f"\n;Model List: {str(model_list)}" From 1b518b8c926096d1835f50e64147d17b1cf6198b Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 12 Apr 2025 14:13:53 -0400 Subject: [PATCH 077/299] Update DisplayInfoOnLCD.py Changes to the print statistics entered into the gcode. --- .../scripts/DisplayInfoOnLCD.py | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index abff57c804..e68b4c92c8 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -1,5 +1,6 @@ """ Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 +<<<<<<< Updated upstream Modified: Joshua Pope-Lewis on November 16, 2018 Display Progress on LCD by Mathias Lyngklip Kjeldgaard, Alexander Gee, Kimmo Toivanen, Inigo Martinez on July 31, 2019 Show Progress was adapted from Display Progress by Louis Wooters on January 6, 2020. His changes are included here. @@ -29,6 +30,35 @@ Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It uses the Time Fudge Factor. The user may enter a print start time. +======= +Modified: Joshua Pope-Lewis on November 16, 2018 +Display Progress on LCD by Mathias Lyngklip Kjeldgaard, Alexander Gee, Kimmo Toivanen, Inigo Martinez on July 31, 2019 +Show Progress was adapted from Display Progress by Louis Wooters on January 6, 2020. His changes are included here. +--------------------------------------------------------------- +DisplayNameOrProgressOnLCD.py +Cura Post-Process plugin +Combines 'Display Filename and Layer on the LCD' with 'Display Progress' +Combined and with additions by: GregValiant (Greg Foresi) +Date: September 8, 2023 +NOTE: This combined post processor will make 'Display Filename and Layer on the LCD' and 'Display Progress' obsolete +Description: Display Filename and Layer options: + Status messages sent to the printer... + - Scrolling (SCROLL_LONG_FILENAMES) if enabled in Marlin and you aren't printing a small item select this option. + - Name: By default it will use the name generated by Cura (EG: TT_Test_Cube) - You may enter a custom name here + - Start Num: Choose which number you prefer for the initial layer, 0 or 1 + - Max Layer: Enabling this will show how many layers are in the entire print (EG: Layer 1 of 265!) + - Add prefix 'Printing': Enabling this will add the prefix 'Printing' + - Example Line on LCD: Printing Layer 0 of 395 3DBenchy + Display Progress options: + - Display Total Layer Count + - Disply Time Remaining for the print + - Time Fudge Factor % - Divide the Actual Print Time by the Cura Estimate. Enter as a percentage and the displayed time will be adjusted. This allows you to bring the displayed time closer to reality (Ex: Entering 87.5 would indicate an adjustment to 87.5% of the Cura estimate). + - Example line on LCD: 1/479 | ET 2h13m + - Time to Pauses changes the M117/M118 lines to countdown to the next pause as 1/479 | TP 2h36m + - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. + - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) + - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It takes into account the Time Fudge Factor. The user may enter a print start time. This is also available for Display Filename. +>>>>>>> Stashed changes """ from ..Script import Script @@ -240,6 +270,7 @@ class DisplayInfoOnLCD(Script): def execute(self, data): display_option = self.getSettingValueByKey("display_option") +<<<<<<< Updated upstream self.add_m117_line = self.getSettingValueByKey("add_m117_line") self.add_m118_line = self.getSettingValueByKey("add_m118_line") self.add_m118_a1 = self.getSettingValueByKey("add_m118_a1") @@ -249,12 +280,21 @@ class DisplayInfoOnLCD(Script): self.add_m73_time = self.getSettingValueByKey("add_m73_time") self.add_m73_percent = self.getSettingValueByKey("add_m73_percent") self.m73_str = "" +======= + add_m118_line = self.getSettingValueByKey("add_m118_line") + add_m73_line = self.getSettingValueByKey("add_m73_line") + add_m73_time = self.getSettingValueByKey("add_m73_time") + add_m73_percent = self.getSettingValueByKey("add_m73_percent") + + # This is Display Filename and Layer on LCD +>>>>>>> Stashed changes if display_option == "filename_layer": data = self._display_filename_layer(data) else: data = self._display_progress(data) return data +<<<<<<< Updated upstream # This is from the original 'Display Filename and Layer on LCD' def _display_filename_layer(self, data: str) -> str: data[0] = self._add_stats(data) @@ -280,6 +320,28 @@ class DisplayInfoOnLCD(Script): self.m118_text = octo_text + str(i) layer_index = data.index(layer) lines = layer.split("\n") +======= + # Display Progress (from 'Show Progress' and 'Display Progress on LCD') + elif display_option == "display_progress": + # get settings + display_total_layers = self.getSettingValueByKey("display_total_layers") + display_remaining_time = self.getSettingValueByKey("display_remaining_time") + speed_factor = self.getSettingValueByKey("speed_factor") / 100 + m73_time = False + m73_percent = False + if add_m73_line and add_m73_time: + m73_time = True + if add_m73_line and add_m73_percent: + m73_percent = True + # initialize global variables + first_layer_index = 0 + time_total = 0 + number_of_layers = 0 + time_elapsed = 0 + # if at least one of the settings is disabled, there is enough room on the display to display "layer" + first_section = data[0] + lines = first_section.split("\n") +>>>>>>> Stashed changes for line in lines: if line.startswith(";LAYER_COUNT:"): max_layer = line From 03aa64448a5a410b040e8fb550cf4e22abf0ff0f Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sun, 30 Mar 2025 18:28:58 -0400 Subject: [PATCH 078/299] Update AddCoolingProfile.py Update AddCoolingProfile.py Un-trapped ValueError in line 782. It might also be an IndexError. I left it open. Update AddCoolingProfile.py Change an IndexError to a ValueError --- .../scripts/AddCoolingProfile.py | 59 ++++++++++++++----- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py index 6e43e98969..64678189ab 100644 --- a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py +++ b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py @@ -286,7 +286,7 @@ class AddCoolingProfile(Script): "description": "For machines with independent layer cooling fans. Leaving a fan running while the other nozzle is printing can help with oozing. You can pick the speed % for the idle nozzle layer cooling fan to hold at.", "type": "bool", "default_value": false, - "enabled": "enable_off_fan_speed_enable" + "enabled": "enable_off_fan_speed_enable and self.extruder_count > 1" }, "off_fan_speed": { @@ -297,7 +297,7 @@ class AddCoolingProfile(Script): "minimum_value": 0, "maximum_value": 100, "unit": "% ", - "enabled": "enable_off_fan_speed_enable and enable_off_fan_speed" + "enabled": "enable_off_fan_speed_enable and enable_off_fan_speed and self.extruder_count > 1" }, "enable_off_fan_speed_enable": { @@ -378,13 +378,35 @@ class AddCoolingProfile(Script): if script_count > 0: # Set 'Remove M106 lines' to "false" if there is already an instance of this script running. self._instance.setProperty("delete_existing_m106", "value", False) + self._instance.setProperty("enable_off_fan_speed_enable", "value", False) if self.extruder_count > 1: if self.extruder_list[0].getProperty("machine_extruder_cooling_fan_number", "value") != self.extruder_list[1].getProperty("machine_extruder_cooling_fan_number", "value"): - self._instance.setProperty("enable_off_fan_speed_enable", "value", True) + self._instance.setProperty("enable_off_fan_speed_enable", "value", True) if bool(self.global_stack.getProperty("machine_heated_bed", "value")): self._instance.setProperty("enable_bv_fan", "value", True) - + def execute(self, data): + """ + Collect the settings from Cura and from this script + params: + t0_fan thru t3_fan: The fan numbers for up to 4 layer cooling circuits + fan_mode: Whether the fan scale will be 0-255 PWM (when true) or 0-1 RepRap (when false) + bed_adhesion: Is only important if a raft is enabled + print_seuence: Options are slightly different if in One-at-a-Time mode + is_multi-fan: Used to distinguish between a multi-extruder with a single fan for each nozzle, or one fan for both nozzles. + is_multi_extr_print: For the slight difference in handling a multi-extruder printer and a print that only uses one of the extruders. + fan_list: A list of fan speeds (even numbered items) and layer numbers (odd numbered items) + feature_speed_list: A list of the speeds for each ';TYPE:' in the gcode + feature_name_list: The list of each 'TYPE' in the gcode + off_fan_speed: The speed that will be maintained by the fan for the inactive extruder (for an anti-oozing effect) + init_fan: The fan number of the first extruder used in a print + delete_existing_m106: The first instance of the script in the post processing list should remove the CUra M106 lines. Following instances should not delete the changes made by the first instance. + feature_fan_combing: Whether or not to shut the cooling fan off during travel moves. + the_start_layer: When in By Feature this is the user selected start of the fan changes. + the_end_layer: When in By Feature this is the user selected end of the fan changes + the_end_is_enabled: When in By Feature, if the fan control ends before the print ends, then this will enable the Final Fan Speed to carry through to the print end. + + """ # Exit if the gcode has been previously post-processed. if ";POSTPROCESSED" in data[0]: return data @@ -396,8 +418,9 @@ class AddCoolingProfile(Script): # For 4.x versions that don't have the 0-1 option try: fan_mode = not bool(self.extruder_list[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) - except: + except AttributeError: pass + bed_adhesion = (self.extruder_list[0].getProperty("adhesion_type", "value")) print_sequence = str(self.global_stack.getProperty("print_sequence", "value")) @@ -454,7 +477,7 @@ class AddCoolingProfile(Script): # Catch a possible input error. if the_end_layer < the_start_layer: the_end_layer = the_start_layer - except: + except ValueError: the_end_layer = -1 # If there is an input error then default to the entire gcode file. # Get the speed for each feature @@ -480,7 +503,7 @@ class AddCoolingProfile(Script): if the_end_layer == -1 or the_end_is_enabled == False: the_end_layer = len(data) + 2 - # For multi-extruder printers with separate fans the 'idle' nozzle fan can be left on for ooze control + # For multi-extruder printers with separate cooling fans the 'idle' nozzle fan can be left on for ooze control off_fan_speed = 0 if self.extruder_count > 1: if self.getSettingValueByKey("enable_off_fan_speed"): @@ -494,7 +517,7 @@ class AddCoolingProfile(Script): number_of_raft_layers = 0 layer_0_index = 0 # Catch the number of raft layers. - for l_num in range(1,10,1): + for l_num in range(1,len(data) - 1): layer = data[l_num] if ";LAYER:-" in layer: number_of_raft_layers += 1 @@ -511,7 +534,7 @@ class AddCoolingProfile(Script): T2_used = False T3_used = False # Bypass the file header and ending gcode. - for num in range(1,len(data)-1,1): + for num in range(1,len(data)-1): lines = data[num] if "T0" in lines: T0_used = True @@ -635,10 +658,10 @@ class AddCoolingProfile(Script): layer = data[layer_num] data[layer_num] = re.sub(";MESH:NOMESH", ";MESH:NONMESH", layer) data = self._add_travel_comment(data, layer_0_index) - + if bool(self.getSettingValueByKey("bv_fan_speed_control_enable")): data = self._control_bv_fan(data) - + # Single Fan "By Layer" if by_layer_or_feature == "by_layer" and not is_multi_fan: return self._single_fan_by_layer(data, layer_0_index, fan_list, t0_fan) @@ -681,11 +704,12 @@ class AddCoolingProfile(Script): this_fan = str(t0_fan) start_index = str(len(multi_fan_data)) for num in range(0,15,2): + # The fan_list may not be in ascending order. Get the lowest layer number try: if int(fan_list[num]) < int(start_index): start_index = str(fan_list[num]) - except: + except ValueError: pass # Move the start point if delete_existing_m106 is false start_index = int(start_index) + int(layer_0_index) @@ -706,12 +730,13 @@ class AddCoolingProfile(Script): elif line == "T3": prev_fan = this_fan this_fan = t3_fan + # With Active Tool tracked - now the body of changes can start for l_index in range(int(start_index),len(multi_fan_data)-1,1): modified_data = "" layer = multi_fan_data[l_index] fan_lines = layer.split("\n") for fan_line in fan_lines: - # Prepare to shut down the previous fan and start the next one. + # Prepare to turn off the previous fan and start the next one. if fan_line.startswith("T"): if fan_line == "T0": this_fan = str(t0_fan) if fan_line == "T1": this_fan = str(t1_fan) @@ -751,6 +776,7 @@ class AddCoolingProfile(Script): for line in lines: if ";LAYER:" in line: layer_number = str(line.split(":")[1]) + continue if int(layer_number) >= int(the_start_layer) and int(layer_number) < int(the_end_layer)-1: temp = line.split(" ")[0] try: @@ -836,8 +862,9 @@ class AddCoolingProfile(Script): temp = line.split(" ")[0] try: name_index = feature_name_list.index(temp) - except: + except IndexError: name_index = -1 + if name_index != -1: modified_data += line + "\n" + feature_speed_list[name_index] + this_fan + "\n" current_fan_speed = str(feature_speed_list[name_index].split("S")[1]) @@ -848,6 +875,7 @@ class AddCoolingProfile(Script): current_fan_speed = "0" else: modified_data += line + "\n" + # If an end layer is defined - Insert the final speed and set the other variables to Final Speed to finish the file # There cannot be a 'break' here because if there are multiple fan numbers they still need to be shut off and turned on. elif line == ";LAYER:" + str(the_end_layer): @@ -857,6 +885,7 @@ class AddCoolingProfile(Script): else: # Layer and Tool get inserted into modified_data above. All other lines go into modified_data here if not line.startswith("T") and not line.startswith(";LAYER:"): modified_data += line + "\n" + if modified_data.endswith("\n"): modified_data = modified_data[0: - 1] multi_fan_data[l_index] = modified_data modified_data = "" @@ -950,7 +979,7 @@ class AddCoolingProfile(Script): return comment_data def _control_bv_fan(self, bv_data: str) -> str: - # Control the chamber fan + # Control any secondary fan. Can be used for an Auxilliary/Chamber fan bv_start_layer = self.getSettingValueByKey("bv_fan_start_layer") - 1 bv_end_layer = self.getSettingValueByKey("bv_fan_end_layer") bv_fan_nr = self.getSettingValueByKey("bv_fan_nr") From 9f4324fe92a27ba584091e6edd567beaa6ef06ef Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 14 Apr 2025 08:33:16 +0200 Subject: [PATCH 079/299] Fine-tune multi color printing, and allow prime tower CURA-12074 When prime tower is enabled, use it as a flush so that we don't have to use the usual flushing sequence of the printer, which is much slower --- resources/definitions/bambulab_a1mini.def.json | 17 ++++++++++++----- .../bambulab_a1mini_extruder_0.def.json | 4 ++-- .../bambulab_a1mini_extruder_1.def.json | 4 ++-- .../bambulab_a1mini_extruder_2.def.json | 4 ++-- .../bambulab_a1mini_extruder_3.def.json | 4 ++-- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 414eba0065..1972f8d40e 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -120,21 +120,28 @@ "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, "machine_nozzle_size": { "value": 0.4 }, "machine_show_variants": { "value": true }, - "machine_start_gcode": { "default_value": ";===== machine: A1 mini =========================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S170\nM140 S{material_bed_temperature_layer_0}\nG392 S0 ;turn off clog detect\nM9833.2\n;=====start printer sound ===================\nM17\nM400 S1\nM1006 S1\nM1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\nM1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\nM1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\nM1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\nM1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-13.5 F3000\n M400\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\n M104 S{material_print_temperature, initial_extruder_nr}\n G92 E0\n G1 E50 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\n M104 S{material_print_temperature_layer_0-40, material_print_temperature_layer_0}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{material_print_temperature_layer_0-40, initial_extruder_nr}\n G392 S0 ;turn off clog detect\nM621 S{initial_extruder_nr}A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\nM1002 gcode_claim_action : 3\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S{material_bed_temperature_layer_0};set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n\n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.3 F18000 ;Move to start position\n M400\n G0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 Y0 Z0 F20000\n M400\n\n G1 X-13.5 Y0 Z10 F10000\n M400\n\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of 'draw extrinsic para cali paint'\n\n;===== extrude cali test ===============================\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.3 F18000 ;Move to start position\nG0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\nG0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate=='Textured PEI Plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n" }, + "machine_start_gcode": { "default_value": ";===== machine: A1 mini =========================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S170\nM140 S{material_bed_temperature_layer_0}\nG392 S0 ;turn off clog detect\nM9833.2\n;=====start printer sound ===================\nM17\nM400 S1\n; M1006 S1\n; M1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-13.5 F3000\n M400\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\n M104 S{material_print_temperature, initial_extruder_nr}\n G92 E0\n G1 E50 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\n M104 S{material_print_temperature_layer_0-40, material_print_temperature_layer_0}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{material_print_temperature_layer_0-40, initial_extruder_nr}\n G392 S0 ;turn off clog detect\nM621 S{initial_extruder_nr}A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 3\n{endif}\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n{endif}\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S{material_bed_temperature_layer_0};set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n\n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.3 F18000 ;Move to start position\n M400\n G0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 Y0 Z0 F20000\n M400\n\n G1 X-13.5 Y0 Z10 F10000\n M400\n\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of 'draw extrinsic para cali paint'\n\n;===== extrude cali test ===============================\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.3 F18000 ;Move to start position\nG0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\nG0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate=='Textured PEI Plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n" }, "machine_use_extruder_offset_to_offset_coords": { "value": false }, "machine_width": { "value": 180 }, "material_diameter": { "value": 1.75 }, "material_flush_purge_length": { - "default_value": 100, - "enabled": true + "default_value": 80, + "enabled": "not prime_tower_enable" + }, + "material_flush_purge_speed": + { + "default_value": 500, + "enabled": "not prime_tower_enable" }, - "material_flush_purge_speed": { "default_value": 500 }, "max_skin_angle_for_expansion": { "value": 45 }, "meshfix_maximum_resolution": { "value": 0.4 }, "min_infill_area": { "default_value": 10 }, "optimize_wall_printing_order": { "value": false }, - "prime_tower_min_volume": { "default_value": 100 }, + "prime_tower_min_volume": { "default_value": 200 }, + "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, + "prime_tower_position_y": { "value": "(resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, + "prime_tower_size": { "default_value": 40 }, "relative_extrusion": { "value": true }, "retraction_amount": { "value": 0.5 }, "retraction_combing_max_distance": { "value": 100 }, diff --git a/resources/extruders/bambulab_a1mini_extruder_0.def.json b/resources/extruders/bambulab_a1mini_extruder_0.def.json index a9d6dedb7e..87f8b4be3d 100644 --- a/resources/extruders/bambulab_a1mini_extruder_0.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_0.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 0 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E18 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E18 F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, - "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } } diff --git a/resources/extruders/bambulab_a1mini_extruder_1.def.json b/resources/extruders/bambulab_a1mini_extruder_1.def.json index a01dd4294f..9e136fc866 100644 --- a/resources/extruders/bambulab_a1mini_extruder_1.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_1.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 1 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E18 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E18 F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, - "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } } diff --git a/resources/extruders/bambulab_a1mini_extruder_2.def.json b/resources/extruders/bambulab_a1mini_extruder_2.def.json index e8490ed1ea..94d3abb0b7 100644 --- a/resources/extruders/bambulab_a1mini_extruder_2.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_2.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 2 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E18 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E18 F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, - "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } } diff --git a/resources/extruders/bambulab_a1mini_extruder_3.def.json b/resources/extruders/bambulab_a1mini_extruder_3.def.json index 7d45756318..4e6339d387 100644 --- a/resources/extruders/bambulab_a1mini_extruder_3.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_3.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 3 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG1 Z{machine_height + 3.0} F1200\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\nM620.11 S1 I{extruder_nr} E18 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E18 F{material_flush_purge_speed}\nM400\nM629 S1\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, - "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{prime_tower_min_volume/(line_width*layer_height)} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\nM628 S0\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\nM629\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-{retraction_amount * 2} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nG1 Z{machine_height + 3.0} F3000\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } } From 14bf34d96a3fbccdc69c4c14fcef4f9486507e5d Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 15 Apr 2025 21:08:33 +0200 Subject: [PATCH 080/299] Adjust code to review comments. - Use delete-on-close instead. - Prevent infinite loops. part of CURA-12156 --- cura/Backups/Backup.py | 2 +- plugins/CuraDrive/src/CreateBackupJob.py | 6 +++--- plugins/CuraDrive/src/RestoreBackupJob.py | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cura/Backups/Backup.py b/cura/Backups/Backup.py index a409c4c689..1438ce293a 100644 --- a/cura/Backups/Backup.py +++ b/cura/Backups/Backup.py @@ -114,7 +114,7 @@ class Backup: data["installed"] = keep_in data["to_install"].update(reinstall) if data is not None: - tmpfile = tempfile.NamedTemporaryFile(delete=False) + tmpfile = tempfile.NamedTemporaryFile(delete_on_close=False) with open(tmpfile.name, "w") as outfile: json.dump(data, outfile) add_to_archive(tmpfile.name, file_path) diff --git a/plugins/CuraDrive/src/CreateBackupJob.py b/plugins/CuraDrive/src/CreateBackupJob.py index 67083d2e83..4820f886ab 100644 --- a/plugins/CuraDrive/src/CreateBackupJob.py +++ b/plugins/CuraDrive/src/CreateBackupJob.py @@ -99,10 +99,10 @@ class CreateBackupJob(Job): self._requestUploadSlot(backup_meta_data, len(self._backup_zip)) # Note: One 'process events' call wasn't enough with the changed situation somehow. - active_done_check = False - while not active_done_check: + for _ in range(5000): CuraApplication.getInstance().processEvents() - active_done_check = self._job_done.wait(0.02) + if self._job_done.wait(0.02): + break if self.backup_upload_error_message == "": self._upload_message.setText(catalog.i18nc("@info:backup_status", "Your backup has finished uploading.")) diff --git a/plugins/CuraDrive/src/RestoreBackupJob.py b/plugins/CuraDrive/src/RestoreBackupJob.py index 817d819abf..503b39547a 100644 --- a/plugins/CuraDrive/src/RestoreBackupJob.py +++ b/plugins/CuraDrive/src/RestoreBackupJob.py @@ -56,10 +56,10 @@ class RestoreBackupJob(Job): ) # Note: Just to be sure, use the same structure here as in CreateBackupJob. - active_done_check = False - while not active_done_check: + for _ in range(5000): CuraApplication.getInstance().processEvents() - active_done_check = self._job_done.wait(0.02) + if self._job_done.wait(0.02): + break def _onRestoreRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None) -> None: if not HttpRequestManager.replyIndicatesSuccess(reply, error): @@ -71,7 +71,7 @@ class RestoreBackupJob(Job): # We store the file in a temporary path fist to ensure integrity. try: - self._temporary_backup_file = NamedTemporaryFile(delete = False) + self._temporary_backup_file = NamedTemporaryFile(delete_on_close = False) with open(self._temporary_backup_file.name, "wb") as write_backup: app = CuraApplication.getInstance() bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE) From bf8d31aa515e1be3a19525b689dec84fee7f7be9 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Mon, 14 Apr 2025 09:04:34 -0400 Subject: [PATCH 081/299] Update DisplayInfoOnLCD.py Add the 'Quality Name' to the gcode with the other settings. Update DisplayInfoOnLCD.py Touchups. Update DisplayInfoOnLCD.py Minor change --- .../scripts/DisplayInfoOnLCD.py | 72 ++----------------- 1 file changed, 6 insertions(+), 66 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index e68b4c92c8..e016bbd3d6 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -1,6 +1,5 @@ """ Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 -<<<<<<< Updated upstream Modified: Joshua Pope-Lewis on November 16, 2018 Display Progress on LCD by Mathias Lyngklip Kjeldgaard, Alexander Gee, Kimmo Toivanen, Inigo Martinez on July 31, 2019 Show Progress was adapted from Display Progress by Louis Wooters on January 6, 2020. His changes are included here. @@ -30,35 +29,6 @@ Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It uses the Time Fudge Factor. The user may enter a print start time. -======= -Modified: Joshua Pope-Lewis on November 16, 2018 -Display Progress on LCD by Mathias Lyngklip Kjeldgaard, Alexander Gee, Kimmo Toivanen, Inigo Martinez on July 31, 2019 -Show Progress was adapted from Display Progress by Louis Wooters on January 6, 2020. His changes are included here. ---------------------------------------------------------------- -DisplayNameOrProgressOnLCD.py -Cura Post-Process plugin -Combines 'Display Filename and Layer on the LCD' with 'Display Progress' -Combined and with additions by: GregValiant (Greg Foresi) -Date: September 8, 2023 -NOTE: This combined post processor will make 'Display Filename and Layer on the LCD' and 'Display Progress' obsolete -Description: Display Filename and Layer options: - Status messages sent to the printer... - - Scrolling (SCROLL_LONG_FILENAMES) if enabled in Marlin and you aren't printing a small item select this option. - - Name: By default it will use the name generated by Cura (EG: TT_Test_Cube) - You may enter a custom name here - - Start Num: Choose which number you prefer for the initial layer, 0 or 1 - - Max Layer: Enabling this will show how many layers are in the entire print (EG: Layer 1 of 265!) - - Add prefix 'Printing': Enabling this will add the prefix 'Printing' - - Example Line on LCD: Printing Layer 0 of 395 3DBenchy - Display Progress options: - - Display Total Layer Count - - Disply Time Remaining for the print - - Time Fudge Factor % - Divide the Actual Print Time by the Cura Estimate. Enter as a percentage and the displayed time will be adjusted. This allows you to bring the displayed time closer to reality (Ex: Entering 87.5 would indicate an adjustment to 87.5% of the Cura estimate). - - Example line on LCD: 1/479 | ET 2h13m - - Time to Pauses changes the M117/M118 lines to countdown to the next pause as 1/479 | TP 2h36m - - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. - - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) - - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It takes into account the Time Fudge Factor. The user may enter a print start time. This is also available for Display Filename. ->>>>>>> Stashed changes """ from ..Script import Script @@ -270,7 +240,6 @@ class DisplayInfoOnLCD(Script): def execute(self, data): display_option = self.getSettingValueByKey("display_option") -<<<<<<< Updated upstream self.add_m117_line = self.getSettingValueByKey("add_m117_line") self.add_m118_line = self.getSettingValueByKey("add_m118_line") self.add_m118_a1 = self.getSettingValueByKey("add_m118_a1") @@ -280,21 +249,12 @@ class DisplayInfoOnLCD(Script): self.add_m73_time = self.getSettingValueByKey("add_m73_time") self.add_m73_percent = self.getSettingValueByKey("add_m73_percent") self.m73_str = "" -======= - add_m118_line = self.getSettingValueByKey("add_m118_line") - add_m73_line = self.getSettingValueByKey("add_m73_line") - add_m73_time = self.getSettingValueByKey("add_m73_time") - add_m73_percent = self.getSettingValueByKey("add_m73_percent") - - # This is Display Filename and Layer on LCD ->>>>>>> Stashed changes if display_option == "filename_layer": data = self._display_filename_layer(data) else: data = self._display_progress(data) return data -<<<<<<< Updated upstream # This is from the original 'Display Filename and Layer on LCD' def _display_filename_layer(self, data: str) -> str: data[0] = self._add_stats(data) @@ -320,28 +280,6 @@ class DisplayInfoOnLCD(Script): self.m118_text = octo_text + str(i) layer_index = data.index(layer) lines = layer.split("\n") -======= - # Display Progress (from 'Show Progress' and 'Display Progress on LCD') - elif display_option == "display_progress": - # get settings - display_total_layers = self.getSettingValueByKey("display_total_layers") - display_remaining_time = self.getSettingValueByKey("display_remaining_time") - speed_factor = self.getSettingValueByKey("speed_factor") / 100 - m73_time = False - m73_percent = False - if add_m73_line and add_m73_time: - m73_time = True - if add_m73_line and add_m73_percent: - m73_percent = True - # initialize global variables - first_layer_index = 0 - time_total = 0 - number_of_layers = 0 - time_elapsed = 0 - # if at least one of the settings is disabled, there is enough room on the display to display "layer" - first_section = data[0] - lines = first_section.split("\n") ->>>>>>> Stashed changes for line in lines: if line.startswith(";LAYER_COUNT:"): max_layer = line @@ -710,7 +648,7 @@ class DisplayInfoOnLCD(Script): filament_line_t0 += f"; Filament Dia.: {global_stack.extruderList[0].getProperty("material_diameter", "value")}mm\n" filament_line_t0 += f"; Nozzle Size : {global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")}mm\n" filament_line_t0 += f"; Print Temp. : {global_stack.extruderList[0].getProperty("material_print_temperature", "value")}°" - + # if there is more than one extruder then get the stats for the second one. filament_line_t1 = "" if extruder_count > 1: @@ -720,15 +658,17 @@ class DisplayInfoOnLCD(Script): filament_line_t1 += f"; Filament Dia.: {global_stack.extruderList[1].getProperty("material_diameter", "value")}mm\n" filament_line_t1 += f"; Nozzle Size : {global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")}mm\n" filament_line_t1 += f"; Print Temp. : {global_stack.extruderList[1].getProperty("material_print_temperature", "value")}°" - + # Add the stats to the gcode file lines = data[0].split("\n") for index, line in enumerate(lines): if line.startswith(";Layer height:"): - lines[index] += "\n" + init_layer_hgt_line + lines[index] += f"\n{init_layer_hgt_line}" + lines[index] += f"\n;Base Quality Name : '{global_stack.quality.getMetaDataEntry("name", "")}'" + lines[index] += f"\n;Custom Quality Name: '{global_stack.qualityChanges.getMetaDataEntry("name")}'" if line.startswith(";Filament used"): lines[index] = filament_line_t0 + filament_line_t1 if "MINX" in line or "MIN.X" in line: - # Add the model list + # Add the Object List lines[index - 1] += f"\n;Model List: {str(model_list)}" return "\n".join(lines) \ No newline at end of file From 09af18ec8fa77f6ce4ed5a598a5bc7f2888bbae1 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 16 Apr 2025 09:09:22 +0200 Subject: [PATCH 082/299] Export proper thumbnail and gcode into BambuLab 3mf format CURA-12099 --- plugins/3MFWriter/ThreeMFWriter.py | 43 ++++++++++++++++++- plugins/3MFWriter/__init__.py | 10 ++++- .../definitions/bambulab_a1mini.def.json | 2 +- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index a3eb43ca32..24d23a71ca 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -1,11 +1,16 @@ # Copyright (c) 2015-2022 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +import hashlib + +from io import StringIO + import json import re import threading from typing import Optional, cast, List, Dict, Pattern, Set +from UM.PluginRegistry import PluginRegistry from UM.Mesh.MeshWriter import MeshWriter from UM.Math.Vector import Vector from UM.Logger import Logger @@ -50,8 +55,12 @@ from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") THUMBNAIL_PATH = "Metadata/thumbnail.png" +THUMBNAIL_PATH_MULTIPLATE = "Metadata/plate_1.png" +THUMBNAIL_PATH_MULTIPLATE_SMALL = "Metadata/plate_1_small.png" MODEL_PATH = "3D/3dmodel.model" PACKAGE_METADATA_PATH = "Cura/packages.json" +GCODE_PATH = "Metadata/Plate_1.gcode" +GCODE_MD5_PATH = f"{GCODE_PATH}.md5" class ThreeMFWriter(MeshWriter): def __init__(self): @@ -201,9 +210,10 @@ class ThreeMFWriter(MeshWriter): painter.end() - def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode, export_settings_model = None) -> bool: + def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode, export_settings_model = None, **kwargs) -> bool: self._archive = None # Reset archive archive = zipfile.ZipFile(stream, "w", compression = zipfile.ZIP_DEFLATED) + add_extra_data = kwargs.get("mime_type", "") == "application/vnd.bambulab-package.3dmanufacturing-3dmodel+xml" try: model_file = zipfile.ZipInfo(MODEL_PATH) # Because zipfile is stupid and ignores archive-level compression settings when writing with ZipInfo. @@ -222,6 +232,9 @@ class ThreeMFWriter(MeshWriter): relations_element = ET.Element("Relationships", xmlns = self._namespaces["relationships"]) model_relation_element = ET.SubElement(relations_element, "Relationship", Target = "/" + MODEL_PATH, Id = "rel0", Type = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel") + if add_extra_data: + self._storeGCode(archive) + # Attempt to add a thumbnail snapshot = self._createSnapshot() if snapshot: @@ -237,6 +250,15 @@ class ThreeMFWriter(MeshWriter): # Don't try to compress snapshot file, because the PNG is pretty much as compact as it will get archive.writestr(thumbnail_file, thumbnail_buffer.data()) + if add_extra_data: + archive.writestr(zipfile.ZipInfo(THUMBNAIL_PATH_MULTIPLATE), thumbnail_buffer.data()) + + small_snapshot = snapshot.scaled(128, 128, transformMode = Qt.TransformationMode.SmoothTransformation) + small_thumbnail_buffer = QBuffer() + small_thumbnail_buffer.open(QBuffer.OpenModeFlag.ReadWrite) + small_snapshot.save(small_thumbnail_buffer, "PNG") + archive.writestr(zipfile.ZipInfo(THUMBNAIL_PATH_MULTIPLATE_SMALL), small_thumbnail_buffer.data()) + # Add PNG to content types file thumbnail_type = ET.SubElement(content_types, "Default", Extension="png", ContentType="image/png") # Add thumbnail relation to _rels/.rels file @@ -319,6 +341,25 @@ class ThreeMFWriter(MeshWriter): return True + def _storeGCode(self, archive): + gcode_textio = StringIO() # We have to convert the g-code into bytes. + gcode_writer = cast(MeshWriter, PluginRegistry.getInstance().getPluginObject("GCodeWriter")) + success = gcode_writer.write(gcode_textio, None) + + if success: + gcode_data = gcode_textio.getvalue().encode("UTF-8") + archive.writestr(zipfile.ZipInfo(GCODE_PATH), gcode_data) + + # Calculate and store the MD5 sum of the gcode data + md5_hash = hashlib.md5(gcode_data).hexdigest() + archive.writestr(zipfile.ZipInfo(GCODE_MD5_PATH), md5_hash.encode("UTF-8")) + return True + else: + error_msg = catalog.i18nc("@info:error", "Can't write GCode to 3MF file") + self.setInformation(error_msg) + Logger.error(error_msg) + return False + @staticmethod def _storeMetadataJson(metadata: Dict[str, List[Dict[str, str]]], archive: zipfile.ZipFile, path: str) -> None: """Stores metadata inside archive path as json file""" diff --git a/plugins/3MFWriter/__init__.py b/plugins/3MFWriter/__init__.py index 980aefdf85..5d8a2e4d20 100644 --- a/plugins/3MFWriter/__init__.py +++ b/plugins/3MFWriter/__init__.py @@ -28,11 +28,17 @@ def getMetaData(): metaData["mesh_writer"] = { "output": [ { - "extension": "3mf", + "extension": workspace_extension, "description": i18n_catalog.i18nc("@item:inlistbox", "3MF file"), "mime_type": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml", "mode": ThreeMFWriter.ThreeMFWriter.OutputMode.BinaryMode }, + { + "extension": f"gcode.{workspace_extension}", + "description": i18n_catalog.i18nc("@item:inlistbox", "BambuLab 3MF file"), + "mime_type": "application/vnd.bambulab-package.3dmanufacturing-3dmodel+xml", + "mode": ThreeMFWorkspaceWriter.ThreeMFWorkspaceWriter.OutputMode.BinaryMode + } ] } metaData["workspace_writer"] = { @@ -44,7 +50,7 @@ def getMetaData(): "mode": ThreeMFWorkspaceWriter.ThreeMFWorkspaceWriter.OutputMode.BinaryMode }, { - "extension": "3mf", + "extension": workspace_extension, "description": i18n_catalog.i18nc("@item:inlistbox", "Universal Cura Project"), "mime_type": "application/x-ucp", "mode": ThreeMFWorkspaceWriter.ThreeMFWorkspaceWriter.OutputMode.BinaryMode diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 1972f8d40e..6cc1785654 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -7,7 +7,7 @@ "visible": true, "author": "Mariska", "manufacturer": "BambuLab", - "file_formats": "text/x-gcode", + "file_formats": "application/vnd.bambulab-package.3dmanufacturing-3dmodel+xml", "platform": "bambulab_a1mini.obj", "has_machine_quality": true, "has_material": true, From f45cbeb5f4a8e250a9e9d5d4532cd636de0ec37d Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 16 Apr 2025 13:18:40 +0200 Subject: [PATCH 083/299] Remove spurious (and maybe erroneous?) empty line. CURA-12502 --- packaging/NSIS/Ultimaker-Cura.nsi.jinja | 1 - 1 file changed, 1 deletion(-) diff --git a/packaging/NSIS/Ultimaker-Cura.nsi.jinja b/packaging/NSIS/Ultimaker-Cura.nsi.jinja index 8c5d48f9dd..53d8777e5f 100644 --- a/packaging/NSIS/Ultimaker-Cura.nsi.jinja +++ b/packaging/NSIS/Ultimaker-Cura.nsi.jinja @@ -105,7 +105,6 @@ WriteUninstaller "$INSTDIR\uninstall.exe" !ifdef REG_START_MENU !insertmacro MUI_STARTMENU_WRITE_BEGIN Application CreateShortCut "$SMPROGRAMS\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}" - !insertmacro MUI_STARTMENU_WRITE_END !endif From f69d80f6a0e26ec5ec49e3eac06777aa26949e69 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 16 Apr 2025 15:08:58 +0200 Subject: [PATCH 084/299] Allow selecting material mapping on printer CURA-12099 --- cura/Settings/CuraContainerStack.py | 3 + plugins/3MFWriter/ThreeMFWriter.py | 176 ++++++++++++++---- .../definitions/bambulab_a1mini.def.json | 2 +- resources/definitions/bambulab_x1.def.json | 2 +- 4 files changed, 148 insertions(+), 35 deletions(-) diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py index ef1c9561af..fd7f7c7575 100755 --- a/cura/Settings/CuraContainerStack.py +++ b/cura/Settings/CuraContainerStack.py @@ -402,6 +402,9 @@ class CuraContainerStack(ContainerStack): return super().getProperty(key, property_name, context) + def getValue(self, key: str, context = None) -> Any: + return self.getProperty(key, "value", context) + class _ContainerIndexes: """Private helper class to keep track of container positions and their types.""" diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 24d23a71ca..be0fa1a01b 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -10,6 +10,8 @@ import threading from typing import Optional, cast, List, Dict, Pattern, Set +from Machines.Models.ExtrudersModel import ExtrudersModel +from Settings.ExtruderStack import ExtruderStack from UM.PluginRegistry import PluginRegistry from UM.Mesh.MeshWriter import MeshWriter from UM.Math.Vector import Vector @@ -54,13 +56,17 @@ from .SettingsExportGroup import SettingsExportGroup from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") -THUMBNAIL_PATH = "Metadata/thumbnail.png" -THUMBNAIL_PATH_MULTIPLATE = "Metadata/plate_1.png" -THUMBNAIL_PATH_MULTIPLATE_SMALL = "Metadata/plate_1_small.png" MODEL_PATH = "3D/3dmodel.model" PACKAGE_METADATA_PATH = "Cura/packages.json" -GCODE_PATH = "Metadata/Plate_1.gcode" +METADATA_PATH = "Metadata" +THUMBNAIL_PATH = f"{METADATA_PATH}/thumbnail.png" +THUMBNAIL_PATH_MULTIPLATE = f"{METADATA_PATH}/plate_1.png" +THUMBNAIL_PATH_MULTIPLATE_SMALL = f"{METADATA_PATH}/plate_1_small.png" +GCODE_PATH = f"{METADATA_PATH}/plate_1.gcode" GCODE_MD5_PATH = f"{GCODE_PATH}.md5" +MODEL_SETTINGS_PATH = f"{METADATA_PATH}/model_settings.config" +PLATE_DESC_PATH = f"{METADATA_PATH}/plate_1.json" +SLICE_INFO_PATH = f"{METADATA_PATH}/slice_info.config" class ThreeMFWriter(MeshWriter): def __init__(self): @@ -220,20 +226,24 @@ class ThreeMFWriter(MeshWriter): model_file.compress_type = zipfile.ZIP_DEFLATED # Create content types file - content_types_file = zipfile.ZipInfo("[Content_Types].xml") - content_types_file.compress_type = zipfile.ZIP_DEFLATED content_types = ET.Element("Types", xmlns = self._namespaces["content-types"]) rels_type = ET.SubElement(content_types, "Default", Extension = "rels", ContentType = "application/vnd.openxmlformats-package.relationships+xml") model_type = ET.SubElement(content_types, "Default", Extension = "model", ContentType = "application/vnd.ms-package.3dmanufacturing-3dmodel+xml") # Create _rels/.rels file - relations_file = zipfile.ZipInfo("_rels/.rels") - relations_file.compress_type = zipfile.ZIP_DEFLATED - relations_element = ET.Element("Relationships", xmlns = self._namespaces["relationships"]) - model_relation_element = ET.SubElement(relations_element, "Relationship", Target = "/" + MODEL_PATH, Id = "rel0", Type = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel") + relations_element = self._makeRelationsTree() + model_relation_element = ET.SubElement(relations_element, "Relationship", Target="/" + MODEL_PATH, + Id="rel0", + Type="http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel") + + # Create Metadata/_rels/model_settings.config.rels + metadata_relations_element = self._makeRelationsTree() if add_extra_data: - self._storeGCode(archive) + self._storeGCode(archive, metadata_relations_element) + self._storeModelSettings(archive) + self._storePlateDesc(archive) + self._storeSliceInfo(archive) # Attempt to add a thumbnail snapshot = self._createSnapshot() @@ -246,25 +256,35 @@ class ThreeMFWriter(MeshWriter): thumbnail_buffer.open(QBuffer.OpenModeFlag.ReadWrite) snapshot.save(thumbnail_buffer, "PNG") - thumbnail_file = zipfile.ZipInfo(THUMBNAIL_PATH) - # Don't try to compress snapshot file, because the PNG is pretty much as compact as it will get - archive.writestr(thumbnail_file, thumbnail_buffer.data()) + # Add PNG to content types file + thumbnail_type = ET.SubElement(content_types, "Default", Extension="png", ContentType="image/png") if add_extra_data: archive.writestr(zipfile.ZipInfo(THUMBNAIL_PATH_MULTIPLATE), thumbnail_buffer.data()) + extra_thumbnail_relation_element = ET.SubElement(relations_element, "Relationship", + Target="/" + THUMBNAIL_PATH_MULTIPLATE, Id="rel-2", + Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail") + extra_thumbnail_relation_element_duplicate = ET.SubElement(relations_element, "Relationship", + Target="/" + THUMBNAIL_PATH_MULTIPLATE, Id="rel-4", + Type="http://schemas.bambulab.com/package/2021/cover-thumbnail-middle") small_snapshot = snapshot.scaled(128, 128, transformMode = Qt.TransformationMode.SmoothTransformation) small_thumbnail_buffer = QBuffer() small_thumbnail_buffer.open(QBuffer.OpenModeFlag.ReadWrite) small_snapshot.save(small_thumbnail_buffer, "PNG") archive.writestr(zipfile.ZipInfo(THUMBNAIL_PATH_MULTIPLATE_SMALL), small_thumbnail_buffer.data()) + thumbnail_small_relation_element = ET.SubElement(relations_element, "Relationship", + Target="/" + THUMBNAIL_PATH_MULTIPLATE_SMALL, Id="rel-5", + Type="http://schemas.bambulab.com/package/2021/cover-thumbnail-small") + else: + thumbnail_file = zipfile.ZipInfo(THUMBNAIL_PATH) + # Don't try to compress snapshot file, because the PNG is pretty much as compact as it will get + archive.writestr(thumbnail_file, thumbnail_buffer.data()) - # Add PNG to content types file - thumbnail_type = ET.SubElement(content_types, "Default", Extension="png", ContentType="image/png") - # Add thumbnail relation to _rels/.rels file - thumbnail_relation_element = ET.SubElement(relations_element, "Relationship", - Target="/" + THUMBNAIL_PATH, Id="rel1", - Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail") + # Add thumbnail relation to _rels/.rels file + thumbnail_relation_element = ET.SubElement(relations_element, "Relationship", + Target="/" + THUMBNAIL_PATH, Id="rel1", + Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail") # Write material metadata packages_metadata = self._getMaterialPackageMetadata() + self._getPluginPackageMetadata() @@ -327,8 +347,10 @@ class ThreeMFWriter(MeshWriter): scene_string = parser.sceneToString(savitar_scene) archive.writestr(model_file, scene_string) - archive.writestr(content_types_file, b' \n' + ET.tostring(content_types)) - archive.writestr(relations_file, b' \n' + ET.tostring(relations_element)) + self._storeElementTree(archive, "[Content_Types].xml", content_types) + self._storeElementTree(archive, "_rels/.rels", relations_element) + if len(metadata_relations_element) > 0: + self._storeElementTree(archive, "Metadata/_rels/model_settings.config.rels", metadata_relations_element) except Exception as error: Logger.logException("e", "Error writing zip file") self.setInformation(str(error)) @@ -341,24 +363,112 @@ class ThreeMFWriter(MeshWriter): return True - def _storeGCode(self, archive): + @staticmethod + def _storeElementTree(archive: zipfile.ZipFile, file_path: str, root_element: ET.Element): + file = zipfile.ZipInfo(file_path) + file.compress_type = zipfile.ZIP_DEFLATED + archive.writestr(file, b' \n' + ET.tostring(root_element)) + + def _storeGCode(self, archive: zipfile.ZipFile, metadata_relations_element: ET.Element): gcode_textio = StringIO() # We have to convert the g-code into bytes. gcode_writer = cast(MeshWriter, PluginRegistry.getInstance().getPluginObject("GCodeWriter")) success = gcode_writer.write(gcode_textio, None) - if success: - gcode_data = gcode_textio.getvalue().encode("UTF-8") - archive.writestr(zipfile.ZipInfo(GCODE_PATH), gcode_data) - - # Calculate and store the MD5 sum of the gcode data - md5_hash = hashlib.md5(gcode_data).hexdigest() - archive.writestr(zipfile.ZipInfo(GCODE_MD5_PATH), md5_hash.encode("UTF-8")) - return True - else: + if not success: error_msg = catalog.i18nc("@info:error", "Can't write GCode to 3MF file") self.setInformation(error_msg) Logger.error(error_msg) - return False + raise Exception(error_msg) + + gcode_data = gcode_textio.getvalue().encode("UTF-8") + archive.writestr(zipfile.ZipInfo(GCODE_PATH), gcode_data) + + gcode_relation_element = ET.SubElement(metadata_relations_element, "Relationship", + Target=f"/{GCODE_PATH}", Id="rel-1", + Type="http://schemas.bambulab.com/package/2021/gcode") + + # Calculate and store the MD5 sum of the gcode data + md5_hash = hashlib.md5(gcode_data).hexdigest() + archive.writestr(zipfile.ZipInfo(GCODE_MD5_PATH), md5_hash.encode("UTF-8")) + + def _storeModelSettings(self, archive: zipfile.ZipFile): + config = ET.Element("config") + plate = ET.SubElement(config, "plate") + plater_id = ET.SubElement(plate, "metadata", key="plater_id", value="1") + plater_id = ET.SubElement(plate, "metadata", key="plater_name", value="") + plater_id = ET.SubElement(plate, "metadata", key="locked", value="false") + plater_id = ET.SubElement(plate, "metadata", key="filament_map_mode", value="Auto For Flush") + extruders_count = len(CuraApplication.getInstance().getExtruderManager().extruderIds) + plater_id = ET.SubElement(plate, "metadata", key="filament_maps", value=" ".join("1" for _ in range(extruders_count))) + plater_id = ET.SubElement(plate, "metadata", key="gcode_file", value=GCODE_PATH) + plater_id = ET.SubElement(plate, "metadata", key="thumbnail_file", value=THUMBNAIL_PATH_MULTIPLATE) + plater_id = ET.SubElement(plate, "metadata", key="pattern_bbox_file", value=PLATE_DESC_PATH) + + self._storeElementTree(archive, MODEL_SETTINGS_PATH, config) + + def _storePlateDesc(self, archive: zipfile.ZipFile): + plate_desc = {} + + filament_ids = [] + filament_colors = [] + + for extruder in CuraApplication.getInstance().getExtruderManager().getUsedExtruderStacks(): + filament_ids.append(extruder.getValue("extruder_nr")) + filament_colors.append(self._getMaterialColor(extruder)) + + plate_desc["filament_ids"] = filament_ids + plate_desc["filament_colors"] = filament_colors + plate_desc["first_extruder"] = CuraApplication.getInstance().getExtruderManager().getInitialExtruderNr() + plate_desc["is_seq_print"] = Application.getInstance().getGlobalContainerStack().getValue("print_sequence") == "one_at_a_time" + plate_desc["nozzle_diameter"] = CuraApplication.getInstance().getExtruderManager().getActiveExtruderStack().getValue("machine_nozzle_size") + plate_desc["version"] = 2 + + file = zipfile.ZipInfo(PLATE_DESC_PATH) + file.compress_type = zipfile.ZIP_DEFLATED + archive.writestr(file, json.dumps(plate_desc).encode("UTF-8")) + + def _storeSliceInfo(self, archive: zipfile.ZipFile): + config = ET.Element("config") + + header = ET.SubElement(config, "header") + header_type = ET.SubElement(header, "header_item", key="X-BBL-Client-Type", value="slicer") + header_version = ET.SubElement(header, "header_item", key="X-BBL-Client-Version", value="02.00.01.50") + + plate = ET.SubElement(config, "plate") + index = ET.SubElement(plate, "metadata", key="index", value="1") + nozzle_diameter = ET.SubElement(plate, + "metadata", + key="nozzle_diameters", + value=str(CuraApplication.getInstance().getExtruderManager().getActiveExtruderStack().getValue("machine_nozzle_size"))) + + print_information = CuraApplication.getInstance().getPrintInformation() + for index, extruder in enumerate(Application.getInstance().getGlobalContainerStack().extruderList): + used_m = print_information.materialLengths[index] + used_g = print_information.materialWeights[index] + if used_m > 0.0 and used_g > 0.0: + filament = ET.SubElement(plate, + "filament", + id=str(extruder.getValue("extruder_nr") + 1), + tray_info_idx="GFA00", + type=extruder.material.getMetaDataEntry("material", ""), + color=self._getMaterialColor(extruder), + used_m=str(used_m), + used_g=str(used_g)) + + self._storeElementTree(archive, SLICE_INFO_PATH, config) + + def _makeRelationsTree(self): + return ET.Element("Relationships", xmlns=self._namespaces["relationships"]) + + @staticmethod + def _getMaterialColor(extruder: ExtruderStack) -> str: + position = int(extruder.getMetaDataEntry("position", default="0")) + try: + default_color = ExtrudersModel.defaultColors[position] + except IndexError: + default_color = "#e0e000" + color_code = extruder.material.getMetaDataEntry("color_code", default=default_color) + return color_code.upper() @staticmethod def _storeMetadataJson(metadata: Dict[str, List[Dict[str, str]]], archive: zipfile.ZipFile, path: str) -> None: diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 6cc1785654..102064b702 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -115,7 +115,7 @@ "machine_max_jerk_e": { "default_value": 100 }, "machine_max_jerk_xy": { "default_value": 5000 }, "machine_max_jerk_z": { "default_value": 100 }, - "machine_name": { "default_value": "BambuLabs Bambu A1 mini" }, + "machine_name": { "default_value": "BambuLab Bambu A1 mini" }, "machine_nozzle_cool_down_speed": { "default_value": 1.3 }, "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, "machine_nozzle_size": { "value": 0.4 }, diff --git a/resources/definitions/bambulab_x1.def.json b/resources/definitions/bambulab_x1.def.json index 5f6523d72b..ce18463df6 100644 --- a/resources/definitions/bambulab_x1.def.json +++ b/resources/definitions/bambulab_x1.def.json @@ -114,7 +114,7 @@ "machine_max_jerk_e": { "default_value": 100 }, "machine_max_jerk_xy": { "default_value": 5000 }, "machine_max_jerk_z": { "default_value": 100 }, - "machine_name": { "default_value": "BambuLabs Bambu X1" }, + "machine_name": { "default_value": "BambuLab Bambu X1" }, "machine_nozzle_cool_down_speed": { "default_value": 1.3 }, "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, "machine_nozzle_size": { "value": 0.4 }, From 1e18e0e63d7a305a4d795955e2d90577e708f0b7 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Wed, 16 Apr 2025 09:22:30 -0400 Subject: [PATCH 085/299] Update AddCoolingProfile.py Found a bug. The ";LAYER:" line was not being added to the "modified data" string when in "single_fan_by_feature" mode. Update AddCoolingProfile.py bug fix for the bug fix. --- plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py index 64678189ab..b046a77c2f 100644 --- a/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py +++ b/plugins/PostProcessingPlugin/scripts/AddCoolingProfile.py @@ -776,7 +776,6 @@ class AddCoolingProfile(Script): for line in lines: if ";LAYER:" in line: layer_number = str(line.split(":")[1]) - continue if int(layer_number) >= int(the_start_layer) and int(layer_number) < int(the_end_layer)-1: temp = line.split(" ")[0] try: @@ -789,6 +788,7 @@ class AddCoolingProfile(Script): if feature_fan_combing == True: modified_data += "M106 S0" + t0_fan + "\n" modified_data += line + "\n" + # If an End Layer is defined and is less than the last layer then insert the Final Speed if line == ";LAYER:" + str(the_end_layer) and the_end_is_enabled == True: modified_data += feature_speed_list[len(feature_speed_list) - 1] + t0_fan + "\n" From afc22638baa738a33fa121513f124574482f6113 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 17 Apr 2025 11:34:13 +0200 Subject: [PATCH 086/299] Use original (refined) build plate setting CURA-12099 --- .../definitions/bambulab_a1mini.def.json | 51 +++++-------------- resources/definitions/fdmprinter.def.json | 4 +- 2 files changed, 15 insertions(+), 40 deletions(-) diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 102064b702..894189e303 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -101,6 +101,17 @@ "jerk_wall_x_roofing": { "value": "jerk_wall_0" }, "line_width": { "value": 0.42 }, "machine_acceleration": { "value": 10000 }, + "machine_buildplate_type": + { + "default_value": "textured_pei_plate", + "options": + { + "cool_plate": "Cool Plate", + "engineering_plate": "Engineering Plate", + "high_temp_plate": "High Temp Plate", + "textured_pei_plate": "Textured PEI Plate" + } + }, "machine_center_is_zero": { "value": false }, "machine_depth": { "value": 180 }, "machine_end_gcode": { "default_value": ";===== date: 20231229 =====================\n;turn off nozzle clog detect\nG392 S0\n\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X0 Y{machine_depth} F18000 ; move to safe pos\nG1 X-13.0 F3000 ; move to safe pos\n{if !magic_spiralize && print_sequence != 'one_at_a_time'}\nM1002 judge_flag timelapse_record_flag\nM622 J1\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM991 S0 P-1 ;end timelapse at safe pos\nM623\n{endif}\n\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\n;G1 X27 F15000 ; wipe\n\n; pull back filament to AMS\nM620 S255\nG1 X181 F12000\nT255\nG1 X0 F18000\nG1 X-13.0 F3000\nG1 X0 F18000 ; wipe\nM621 S255\n\nM104 S0 ; turn off hotend\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\nG1 Z180 F600\nG1 Z180\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X-13 Y180 F3600\n\nG91\nG1 Z-1 F600\nG90\nM83\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\n;=====printer finish sound=========\nM17\nM400 S1\nM1006 S1\nM1006 A0 B20 L100 C37 D20 M100 E42 F20 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C46 D10 M100 E46 F10 N100\nM1006 A44 B20 L100 C39 D20 M100 E48 F20 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C39 D10 M100 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C39 D10 M100 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B10 L100 C0 D10 M100 E48 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B20 L100 C41 D20 M100 E49 F20 N100\nM1006 A0 B20 L100 C0 D20 M100 E0 F20 N100\nM1006 A0 B20 L100 C37 D20 M100 E37 F20 N100\nM1006 W\n;=====printer finish sound=========\nM400 S1\nM18 X Y Z\n" }, @@ -120,7 +131,7 @@ "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, "machine_nozzle_size": { "value": 0.4 }, "machine_show_variants": { "value": true }, - "machine_start_gcode": { "default_value": ";===== machine: A1 mini =========================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S170\nM140 S{material_bed_temperature_layer_0}\nG392 S0 ;turn off clog detect\nM9833.2\n;=====start printer sound ===================\nM17\nM400 S1\n; M1006 S1\n; M1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-13.5 F3000\n M400\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\n M104 S{material_print_temperature, initial_extruder_nr}\n G92 E0\n G1 E50 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\n M104 S{material_print_temperature_layer_0-40, material_print_temperature_layer_0}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{material_print_temperature_layer_0-40, initial_extruder_nr}\n G392 S0 ;turn off clog detect\nM621 S{initial_extruder_nr}A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 3\n{endif}\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n{endif}\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S{material_bed_temperature_layer_0};set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n\n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.3 F18000 ;Move to start position\n M400\n G0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 Y0 Z0 F20000\n M400\n\n G1 X-13.5 Y0 Z10 F10000\n M400\n\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of 'draw extrinsic para cali paint'\n\n;===== extrude cali test ===============================\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.3 F18000 ;Move to start position\nG0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\nG0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate=='Textured PEI Plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n" }, + "machine_start_gcode": { "default_value": ";===== machine: A1 mini =========================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S170\nM140 S{material_bed_temperature_layer_0}\nG392 S0 ;turn off clog detect\nM9833.2\n;=====start printer sound ===================\nM17\nM400 S1\n; M1006 S1\n; M1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-13.5 F3000\n M400\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\n M104 S{material_print_temperature, initial_extruder_nr}\n G92 E0\n G1 E50 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\n M104 S{material_print_temperature_layer_0-40, material_print_temperature_layer_0}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{material_print_temperature_layer_0-40, initial_extruder_nr}\n G392 S0 ;turn off clog detect\nM621 S{initial_extruder_nr}A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 3\n{endif}\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n{endif}\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S{material_bed_temperature_layer_0};set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n\n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.3 F18000 ;Move to start position\n M400\n G0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 Y0 Z0 F20000\n M400\n\n G1 X-13.5 Y0 Z10 F10000\n M400\n\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of 'draw extrinsic para cali paint'\n\n;===== extrude cali test ===============================\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.3 F18000 ;Move to start position\nG0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\nG0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate_type=='textured_pei_plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n" }, "machine_use_extruder_offset_to_offset_coords": { "value": false }, "machine_width": { "value": 180 }, "material_diameter": { "value": 1.75 }, @@ -138,7 +149,7 @@ "meshfix_maximum_resolution": { "value": 0.4 }, "min_infill_area": { "default_value": 10 }, "optimize_wall_printing_order": { "value": false }, - "prime_tower_min_volume": { "default_value": 200 }, + "prime_tower_min_volume": { "default_value": 250 }, "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, "prime_tower_position_y": { "value": "(resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, "prime_tower_size": { "default_value": 40 }, @@ -306,42 +317,6 @@ "value": "16" } } - }, - "platform_adhesion": - { - "children": - { - "machine_buildplate": - { - "default_value": "textured_pei_plate", - "description": "The type of the build plate installed on the printer.", - "enabled": true, - "label": "Build Plate Type", - "options": - { - "cool_plate": "Cool Plate", - "engineering_plate": "Engineering Plate", - "high_temp_plate": "High Temp Plate", - "textured_pei_plate": "Textured PEI Plate" - }, - "settable_per_extruder": false, - "settable_per_mesh": false, - "settable_per_meshgroup": false, - "type": "enum" - }, - "machine_scan_first_layer": - { - "default_value": true, - "description": "Whether to scan the first layer for layer adhesion problems.", - "enabled": true, - "label": "Scan the first layer", - "settable_per_extruder": false, - "settable_per_mesh": false, - "settable_per_meshgroup": false, - "type": "bool", - "value": "machine_buildplate!='textured_pei_plate'" - } - } } } } \ No newline at end of file diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index f0019da331..1dec529416 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -214,8 +214,8 @@ }, "machine_buildplate_type": { - "label": "Build Plate Material", - "description": "The material of the build plate installed on the printer.", + "label": "Build Plate Type", + "description": "The type of build plate installed on the printer.", "default_value": "glass", "type": "enum", "options": From c28ab219a0d5521ef9b1a5f6cb43df6f829b5642 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 17 Apr 2025 13:25:24 +0200 Subject: [PATCH 087/299] Fix possibly wrong returned initial extruder CURA-12099 --- cura/Settings/ExtruderManager.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 3181016f69..cd39947bf8 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -15,6 +15,7 @@ from UM.Scene.Selection import Selection from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator from UM.Settings.ContainerRegistry import ContainerRegistry # Finding containers by ID. from cura.Machines.ContainerTree import ContainerTree +from cura.Settings.ExtruderStack import ExtruderStack from typing import Any, cast, Dict, List, Optional, TYPE_CHECKING, Union @@ -304,6 +305,11 @@ class ExtruderManager(QObject): Logger.log("e", "Unable to find one or more of the extruders in %s", used_extruder_stack_ids) return [] + def getFirstUsedExtruderStack(self)-> ExtruderStack: + used_extruders = self.getUsedExtruderStacks() + sorted_extruders = sorted(used_extruders, key=lambda extruder: extruder.getValue("extruder_nr")) + return sorted_extruders[0] + def getInitialExtruderNr(self) -> int: """Get the extruder that the print will start with. @@ -320,8 +326,7 @@ class ExtruderManager(QObject): skirt_brim_extruder_nr = global_stack.getProperty("skirt_brim_extruder_nr", "value") # if the skirt_brim_extruder_nr is -1, then we use the first used extruder if skirt_brim_extruder_nr == -1: - used_extruders = self.getUsedExtruderStacks() - return used_extruders[0].position + return self.getFirstUsedExtruderStack().getValue("extruder_nr") else: return skirt_brim_extruder_nr if adhesion_type == "raft": @@ -332,7 +337,7 @@ class ExtruderManager(QObject): return global_stack.getProperty("support_infill_extruder_nr", "value") # REALLY no adhesion? Use the first used extruder. - return self.getUsedExtruderStacks()[0].getProperty("extruder_nr", "value") + return self.getFirstUsedExtruderStack().getValue("extruder_nr") def removeMachineExtruders(self, machine_id: str) -> None: """Removes the container stack and user profile for the extruders for a specific machine. From a4cf0a116242abf6d6a345f67caafe216080a3e0 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 17 Apr 2025 13:25:48 +0200 Subject: [PATCH 088/299] Enable prime tower by default and set proper overhang speeds CURA-12099 --- resources/definitions/bambulab_a1mini.def.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 894189e303..9afb31e8ea 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -149,6 +149,9 @@ "meshfix_maximum_resolution": { "value": 0.4 }, "min_infill_area": { "default_value": 10 }, "optimize_wall_printing_order": { "value": false }, + "wall_overhang_angle": { "default_value": 10 }, + "wall_overhang_speed_factors": { "default_value": "[25,15,5,5]" }, + "prime_tower_enable": { "default_value": true }, "prime_tower_min_volume": { "default_value": 250 }, "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, "prime_tower_position_y": { "value": "(resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, From 14375b171d100e2aa54aa669b658aac148c18f39 Mon Sep 17 00:00:00 2001 From: wawanbreton <601114+wawanbreton@users.noreply.github.com> Date: Thu, 17 Apr 2025 11:27:50 +0000 Subject: [PATCH 089/299] Apply printer-linter format --- resources/definitions/bambulab_a1mini.def.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 9afb31e8ea..0a6c1632d8 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -149,8 +149,6 @@ "meshfix_maximum_resolution": { "value": 0.4 }, "min_infill_area": { "default_value": 10 }, "optimize_wall_printing_order": { "value": false }, - "wall_overhang_angle": { "default_value": 10 }, - "wall_overhang_speed_factors": { "default_value": "[25,15,5,5]" }, "prime_tower_enable": { "default_value": true }, "prime_tower_min_volume": { "default_value": 250 }, "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, @@ -294,6 +292,7 @@ "wall_material_flow": { "value": 95 }, "wall_overhang_angle": { "value": 45 }, "wall_overhang_speed_factor": { "value": 50 }, + "wall_overhang_speed_factors": { "default_value": "[25,15,5,5]" }, "wall_x_material_flow": { "value": 100 }, "z_seam_corner": { "value": "'z_seam_corner_weighted'" }, "z_seam_position": { "value": "'backright'" }, From 2db896e80fcb7dcef778295e1ba778eaba77a963 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 22 Apr 2025 10:24:06 +0200 Subject: [PATCH 090/299] win/pacakging -- Start menu-macro is only needed for when in folder? Also it fails now since it seems like this macro _expects_ a folder to be set. CURA-12502 --- packaging/NSIS/Ultimaker-Cura.nsi.jinja | 3 --- 1 file changed, 3 deletions(-) diff --git a/packaging/NSIS/Ultimaker-Cura.nsi.jinja b/packaging/NSIS/Ultimaker-Cura.nsi.jinja index 53d8777e5f..9f61e6950c 100644 --- a/packaging/NSIS/Ultimaker-Cura.nsi.jinja +++ b/packaging/NSIS/Ultimaker-Cura.nsi.jinja @@ -61,7 +61,6 @@ InstallDir "$PROGRAMFILES64\${APP_NAME}" !ifdef REG_START_MENU !define MUI_STARTMENUPAGE_NODISABLE -!define MUI_STARTMENUPAGE_DEFAULTFOLDER "UltiMaker Cura" !define MUI_STARTMENUPAGE_REGISTRY_ROOT "${REG_ROOT}" !define MUI_STARTMENUPAGE_REGISTRY_KEY "${UNINSTALL_PATH}" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${REG_START_MENU}" @@ -103,9 +102,7 @@ SetOutPath "$INSTDIR" WriteUninstaller "$INSTDIR\uninstall.exe" !ifdef REG_START_MENU -!insertmacro MUI_STARTMENU_WRITE_BEGIN Application CreateShortCut "$SMPROGRAMS\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}" -!insertmacro MUI_STARTMENU_WRITE_END !endif !ifndef REG_START_MENU From 38e1140454cb85e3abf5bc374fe1eabeb75e4abd Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 22 Apr 2025 10:53:40 +0200 Subject: [PATCH 091/299] Add base profile for A1 CURA-12346 --- resources/definitions/bambulab_a1.def.json | 42 +++ .../definitions/bambulab_a1mini.def.json | 289 +---------------- resources/definitions/bambulab_base.def.json | 294 ++++++++++++++++++ resources/definitions/bambulab_x1.def.json | 4 +- .../extruders/bambulab_a1_extruder_0.def.json | 19 ++ .../extruders/bambulab_a1_extruder_1.def.json | 19 ++ .../extruders/bambulab_a1_extruder_2.def.json | 19 ++ .../extruders/bambulab_a1_extruder_3.def.json | 19 ++ .../bambulab_a1mini_extruder_0.def.json | 2 +- .../bambulab_a1mini_extruder_1.def.json | 2 +- .../bambulab_a1mini_extruder_2.def.json | 2 +- .../bambulab_a1mini_extruder_3.def.json | 2 +- .../extruders/bambulab_x1_extruder_1.def.json | 2 + .../extruders/bambulab_x1_extruder_2.def.json | 2 + .../extruders/bambulab_x1_extruder_3.def.json | 2 + .../bambulab_a1_0.4_PLA_standard.inst.cfg | 14 + .../quality/bambu/bambulab_a1_normal.inst.cfg | 15 + .../bambulab_a1mini_0.4_PLA_standard.inst.cfg | 2 +- .../bambu/bambulab_a1mini_normal.inst.cfg | 2 +- .../bambulab_x1_0.4_PLA_standard.inst.cfg | 2 +- .../quality/bambu/bambulab_x1_normal.inst.cfg | 2 +- .../bambulab_x1c_0.4_PLA_standard.inst.cfg | 2 +- .../variants/bambu/bambulab_a1_0.4.inst.cfg | 4 +- .../bambu/bambulab_a1mini_0.4.inst.cfg | 13 + .../variants/bambu/bambulab_p1p_0.4.inst.cfg | 2 +- .../variants/bambu/bambulab_p1s_0.4.inst.cfg | 2 +- .../variants/bambu/bambulab_x1_0.4.inst.cfg | 2 +- .../variants/bambu/bambulab_x1c_0.4.inst.cfg | 2 +- 28 files changed, 480 insertions(+), 303 deletions(-) create mode 100644 resources/definitions/bambulab_a1.def.json create mode 100644 resources/definitions/bambulab_base.def.json create mode 100644 resources/extruders/bambulab_a1_extruder_0.def.json create mode 100644 resources/extruders/bambulab_a1_extruder_1.def.json create mode 100644 resources/extruders/bambulab_a1_extruder_2.def.json create mode 100644 resources/extruders/bambulab_a1_extruder_3.def.json create mode 100644 resources/quality/bambu/bambulab_a1_0.4_PLA_standard.inst.cfg create mode 100644 resources/quality/bambu/bambulab_a1_normal.inst.cfg create mode 100644 resources/variants/bambu/bambulab_a1mini_0.4.inst.cfg diff --git a/resources/definitions/bambulab_a1.def.json b/resources/definitions/bambulab_a1.def.json new file mode 100644 index 0000000000..bbcee00fb5 --- /dev/null +++ b/resources/definitions/bambulab_a1.def.json @@ -0,0 +1,42 @@ +{ + "version": 2, + "name": "BambuLab A1", + "inherits": "bambulab_base", + "metadata": + { + "platform": "bambulab_x1.obj", + "has_machine_quality": true, + "has_material": true, + "has_textured_buildplate": true, + "has_variant_buildplates": false, + "has_variants": true, + "machine_extruder_trains": + { + "0": "bambulab_a1_extruder_0", + "1": "bambulab_a1_extruder_1", + "2": "bambulab_a1_extruder_2", + "3": "bambulab_a1_extruder_3" + }, + "platform_offset": [ + -130, + 0, + 130 + ], + "platform_texture": "bambulab-buildplate.png", + "preferred_variant_name": "0.4mm", + "visible": true, + "weight": 3 + }, + "overrides": + { + "machine_depth": { "value": 256 }, + "machine_end_gcode": { "default_value": ";===== date: 20231229 =====================\n;turn off nozzle clog detect\nG392 S0\n\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X0 Y{machine_depth} F18000 ; move to safe pos\nG1 X-13.0 F3000 ; move to safe pos\n{if !magic_spiralize && print_sequence != 'one_at_a_time'}\nM1002 judge_flag timelapse_record_flag\nM622 J1\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM991 S0 P-1 ;end timelapse at safe pos\nM623\n{endif}\n\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\n;G1 X27 F15000 ; wipe\n\n; pull back filament to AMS\nM620 S255\nG1 X181 F12000\nT255\nG1 X0 F18000\nG1 X-13.0 F3000\nG1 X0 F18000 ; wipe\nM621 S255\n\nM104 S0 ; turn off hotend\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\nG1 Z180 F600\nG1 Z180\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X-13 Y180 F3600\n\nG91\nG1 Z-1 F600\nG90\nM83\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\n;=====printer finish sound=========\nM17\nM400 S1\nM1006 S1\nM1006 A0 B20 L100 C37 D20 M100 E42 F20 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C46 D10 M100 E46 F10 N100\nM1006 A44 B20 L100 C39 D20 M100 E48 F20 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C39 D10 M100 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C39 D10 M100 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B10 L100 C0 D10 M100 E48 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B20 L100 C41 D20 M100 E49 F20 N100\nM1006 A0 B20 L100 C0 D20 M100 E0 F20 N100\nM1006 A0 B20 L100 C37 D20 M100 E37 F20 N100\nM1006 W\n;=====printer finish sound=========\nM400 S1\nM18 X Y Z\n" }, + "machine_extruder_count": { "value": 4 }, + "machine_height": { "value": 251 }, + "machine_name": { "default_value": "BambuLab Bambu A1" }, + "machine_start_gcode": { "default_value": ";===== machine: A1 =========================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S170\nM140 S{material_bed_temperature_layer_0}\nG392 S0 ;turn off clog detect\nM9833.2\n;=====start printer sound ===================\nM17\nM400 S1\n; M1006 S1\n; M1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-13.5 F3000\n M400\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\n M104 S{material_print_temperature, initial_extruder_nr}\n G92 E0\n G1 E50 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\n M104 S{material_print_temperature_layer_0-40, material_print_temperature_layer_0}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{material_print_temperature_layer_0-40, initial_extruder_nr}\n G392 S0 ;turn off clog detect\nM621 S{initial_extruder_nr}A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 3\n{endif}\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n{endif}\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S{material_bed_temperature_layer_0};set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n\n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.3 F18000 ;Move to start position\n M400\n G0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 Y0 Z0 F20000\n M400\n\n G1 X-13.5 Y0 Z10 F10000\n M400\n\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of 'draw extrinsic para cali paint'\n\n;===== extrude cali test ===============================\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.3 F18000 ;Move to start position\nG0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\nG0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate_type=='textured_pei_plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n" }, + "machine_width": { "value": 256 }, + "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, + "prime_tower_position_y": { "value": "(resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" } + } +} \ No newline at end of file diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 9afb31e8ea..3d8431c6b4 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -1,13 +1,9 @@ { "version": 2, "name": "BambuLab A1 mini", - "inherits": "fdmprinter", + "inherits": "bambulab_base", "metadata": { - "visible": true, - "author": "Mariska", - "manufacturer": "BambuLab", - "file_formats": "application/vnd.bambulab-package.3dmanufacturing-3dmodel+xml", "platform": "bambulab_a1mini.obj", "has_machine_quality": true, "has_material": true, @@ -28,298 +24,19 @@ ], "platform_texture": "bambulab-buildplate.png", "preferred_variant_name": "0.4mm", + "visible": true, "weight": 3 }, "overrides": { - "acceleration_infill": { "value": "acceleration_print" }, - "acceleration_layer_0": { "value": 2000 }, - "acceleration_prime_tower": { "value": "acceleration_print" }, - "acceleration_print": { "value": 20000 }, - "acceleration_print_layer_0": { "value": "acceleration_layer_0" }, - "acceleration_roofing": { "value": "acceleration_wall_0" }, - "acceleration_skirt_brim": { "value": "acceleration_layer_0" }, - "acceleration_support": { "value": "acceleration_print" }, - "acceleration_support_bottom": { "value": "acceleration_support_interface" }, - "acceleration_support_infill": { "value": "acceleration_support" }, - "acceleration_support_interface": { "value": "acceleration_support" }, - "acceleration_support_roof": { "value": "acceleration_support_interface" }, - "acceleration_topbottom": { "value": "acceleration_print" }, - "acceleration_travel": { "value": 20000 }, - "acceleration_travel_enabled": { "value": true }, - "acceleration_travel_layer_0": { "value": "acceleration_layer_0" }, - "acceleration_wall": { "value": "acceleration_print/8" }, - "acceleration_wall_0": { "value": "acceleration_wall" }, - "acceleration_wall_0_roofing": { "value": "acceleration_wall_0" }, - "acceleration_wall_x": { "value": "acceleration_print" }, - "acceleration_wall_x_roofing": { "value": "acceleration_wall" }, - "adhesion_type": { "value": "'skirt'" }, - "bottom_thickness": { "value": 0.6 }, - "bridge_skin_speed": - { - "unit": "mm/s", - "value": "bridge_wall_speed" - }, - "bridge_sparse_infill_max_density": { "value": 50 }, - "bridge_wall_min_length": { "value": 10 }, - "bridge_wall_speed": - { - "unit": "mm/s", - "value": 50 - }, - "cool_min_layer_time": { "value": 6 }, - "cool_min_speed": { "value": 6 }, - "cool_min_temperature": { "value": "material_print_temperature-15" }, - "default_material_print_temperature": { "maximum_value_warning": 320 }, - "extra_infill_lines_to_support_skins": { "value": "'walls_and_lines'" }, - "gradual_flow_enabled": { "value": false }, - "hole_xy_offset": { "value": 0.075 }, - "infill_overlap": { "value": 10 }, - "infill_pattern": { "value": "'zigzag' if infill_sparse_density > 80 else 'grid'" }, - "infill_sparse_density": { "value": 15 }, - "infill_wall_line_count": { "value": "1 if infill_sparse_density > 80 else 0" }, - "jerk_infill": { "value": "jerk_print" }, - "jerk_layer_0": { "value": "jerk_print/2" }, - "jerk_prime_tower": { "value": "jerk_print" }, - "jerk_print": { "value": "50" }, - "jerk_print_layer_0": { "value": "jerk_layer_0" }, - "jerk_roofing": { "value": "jerk_wall_0" }, - "jerk_skirt_brim": { "value": "jerk_layer_0" }, - "jerk_support": { "value": "jerk_print" }, - "jerk_support_bottom": { "value": "jerk_support_interface" }, - "jerk_support_infill": { "value": "jerk_support" }, - "jerk_support_interface": { "value": "jerk_support" }, - "jerk_support_roof": { "value": "jerk_support_interface" }, - "jerk_topbottom": { "value": "jerk_print" }, - "jerk_travel": { "value": 50 }, - "jerk_travel_enabled": { "value": true }, - "jerk_travel_layer_0": { "value": "jerk_travel" }, - "jerk_wall": { "value": "jerk_print/5" }, - "jerk_wall_0": { "value": "jerk_wall" }, - "jerk_wall_0_roofing": { "value": "jerk_wall_0" }, - "jerk_wall_x": { "value": "jerk_print" }, - "jerk_wall_x_roofing": { "value": "jerk_wall_0" }, - "line_width": { "value": 0.42 }, - "machine_acceleration": { "value": 10000 }, - "machine_buildplate_type": - { - "default_value": "textured_pei_plate", - "options": - { - "cool_plate": "Cool Plate", - "engineering_plate": "Engineering Plate", - "high_temp_plate": "High Temp Plate", - "textured_pei_plate": "Textured PEI Plate" - } - }, - "machine_center_is_zero": { "value": false }, "machine_depth": { "value": 180 }, "machine_end_gcode": { "default_value": ";===== date: 20231229 =====================\n;turn off nozzle clog detect\nG392 S0\n\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X0 Y{machine_depth} F18000 ; move to safe pos\nG1 X-13.0 F3000 ; move to safe pos\n{if !magic_spiralize && print_sequence != 'one_at_a_time'}\nM1002 judge_flag timelapse_record_flag\nM622 J1\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM991 S0 P-1 ;end timelapse at safe pos\nM623\n{endif}\n\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\n;G1 X27 F15000 ; wipe\n\n; pull back filament to AMS\nM620 S255\nG1 X181 F12000\nT255\nG1 X0 F18000\nG1 X-13.0 F3000\nG1 X0 F18000 ; wipe\nM621 S255\n\nM104 S0 ; turn off hotend\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\nG1 Z180 F600\nG1 Z180\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X-13 Y180 F3600\n\nG91\nG1 Z-1 F600\nG90\nM83\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\n;=====printer finish sound=========\nM17\nM400 S1\nM1006 S1\nM1006 A0 B20 L100 C37 D20 M100 E42 F20 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C46 D10 M100 E46 F10 N100\nM1006 A44 B20 L100 C39 D20 M100 E48 F20 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C39 D10 M100 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C39 D10 M100 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B10 L100 C0 D10 M100 E48 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B20 L100 C41 D20 M100 E49 F20 N100\nM1006 A0 B20 L100 C0 D20 M100 E0 F20 N100\nM1006 A0 B20 L100 C37 D20 M100 E37 F20 N100\nM1006 W\n;=====printer finish sound=========\nM400 S1\nM18 X Y Z\n" }, "machine_extruder_count": { "value": 4 }, - "machine_gcode_flavor": { "value": "BambuLab" }, - "machine_heated_bed": { "value": true }, "machine_height": { "value": 175 }, - "machine_max_feedrate_e": { "value": 150 }, - "machine_max_feedrate_x": { "value": 500 }, - "machine_max_feedrate_y": { "value": 500 }, - "machine_max_feedrate_z": { "value": 15 }, - "machine_max_jerk_e": { "default_value": 100 }, - "machine_max_jerk_xy": { "default_value": 5000 }, - "machine_max_jerk_z": { "default_value": 100 }, "machine_name": { "default_value": "BambuLab Bambu A1 mini" }, - "machine_nozzle_cool_down_speed": { "default_value": 1.3 }, - "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, - "machine_nozzle_size": { "value": 0.4 }, - "machine_show_variants": { "value": true }, "machine_start_gcode": { "default_value": ";===== machine: A1 mini =========================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S170\nM140 S{material_bed_temperature_layer_0}\nG392 S0 ;turn off clog detect\nM9833.2\n;=====start printer sound ===================\nM17\nM400 S1\n; M1006 S1\n; M1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-13.5 F3000\n M400\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\n M104 S{material_print_temperature, initial_extruder_nr}\n G92 E0\n G1 E50 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\n M104 S{material_print_temperature_layer_0-40, material_print_temperature_layer_0}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{material_print_temperature_layer_0-40, initial_extruder_nr}\n G392 S0 ;turn off clog detect\nM621 S{initial_extruder_nr}A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 3\n{endif}\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n{endif}\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S{material_bed_temperature_layer_0};set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n\n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.3 F18000 ;Move to start position\n M400\n G0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 Y0 Z0 F20000\n M400\n\n G1 X-13.5 Y0 Z10 F10000\n M400\n\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of 'draw extrinsic para cali paint'\n\n;===== extrude cali test ===============================\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.3 F18000 ;Move to start position\nG0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\nG0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate_type=='textured_pei_plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n" }, - "machine_use_extruder_offset_to_offset_coords": { "value": false }, "machine_width": { "value": 180 }, - "material_diameter": { "value": 1.75 }, - "material_flush_purge_length": - { - "default_value": 80, - "enabled": "not prime_tower_enable" - }, - "material_flush_purge_speed": - { - "default_value": 500, - "enabled": "not prime_tower_enable" - }, - "max_skin_angle_for_expansion": { "value": 45 }, - "meshfix_maximum_resolution": { "value": 0.4 }, - "min_infill_area": { "default_value": 10 }, - "optimize_wall_printing_order": { "value": false }, - "wall_overhang_angle": { "default_value": 10 }, - "wall_overhang_speed_factors": { "default_value": "[25,15,5,5]" }, - "prime_tower_enable": { "default_value": true }, - "prime_tower_min_volume": { "default_value": 250 }, "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, - "prime_tower_position_y": { "value": "(resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, - "prime_tower_size": { "default_value": 40 }, - "relative_extrusion": { "value": true }, - "retraction_amount": { "value": 0.5 }, - "retraction_combing_max_distance": { "value": 100 }, - "retraction_extra_prime_amount": { "value": 0.12 }, - "retraction_hop": { "value": 0.2 }, - "retraction_hop_after_extruder_switch_height": { "value": 2 }, - "retraction_hop_enabled": { "value": true }, - "retraction_min_travel": { "value": "5 if support_enable and support_structure=='tree' else line_width * 2" }, - "retraction_prime_speed": { "value": 15 }, - "retraction_speed": { "value": 30 }, - "skin_edge_support_thickness": { "value": 0 }, - "skin_material_flow": { "value": 95 }, - "skin_overlap": { "value": 0 }, - "skin_preshrink": { "value": 0 }, - "skirt_line_count": { "value": 5 }, - "small_skin_on_surface": { "value": false }, - "small_skin_width": { "value": 4 }, - "speed_infill": - { - "maximum_value_warning": 500, - "value": "speed_print" - }, - "speed_ironing": - { - "maximum_value_warning": 500, - "value": 20 - }, - "speed_layer_0": - { - "maximum_value_warning": 500, - "value": "speed_print/6" - }, - "speed_prime_tower": - { - "maximum_value_warning": 500, - "value": "speed_wall" - }, - "speed_print": - { - "maximum_value_warning": 500, - "value": 300 - }, - "speed_print_layer_0": - { - "maximum_value_warning": 500, - "value": "speed_layer_0" - }, - "speed_roofing": - { - "maximum_value_warning": 500, - "value": "speed_wall" - }, - "speed_skirt_brim": - { - "maximum_value_warning": 500, - "value": "speed_layer_0" - }, - "speed_support": - { - "maximum_value_warning": 500, - "value": "speed_wall_0" - }, - "speed_support_bottom": - { - "maximum_value_warning": 500, - "value": "speed_support_interface" - }, - "speed_support_infill": - { - "maximum_value_warning": 500, - "value": "speed_support" - }, - "speed_support_interface": - { - "maximum_value_warning": 500, - "value": 50 - }, - "speed_support_roof": - { - "maximum_value_warning": 500, - "value": "speed_support_interface" - }, - "speed_topbottom": - { - "maximum_value_warning": 500, - "value": "speed_print" - }, - "speed_travel": - { - "maximum_value": 500, - "value": 500 - }, - "speed_travel_layer_0": - { - "maximum_value": 500, - "value": 150 - }, - "speed_wall": - { - "maximum_value_warning": 500, - "value": "speed_print*2/3" - }, - "speed_wall_0": - { - "maximum_value_warning": 500, - "value": "speed_wall" - }, - "speed_wall_0_roofing": - { - "maximum_value_warning": 500, - "value": "speed_wall" - }, - "speed_wall_x": - { - "maximum_value_warning": 500, - "value": "speed_print" - }, - "speed_wall_x_roofing": - { - "maximum_value_warning": 500, - "value": "speed_wall" - }, - "support_brim_line_count": { "value": 5 }, - "support_density": { "value": 15 }, - "support_infill_rate": { "value": "80 if gradual_support_infill_steps != 0 else 15" }, - "support_pattern": { "value": "'gyroid'" }, - "support_structure": { "value": "'tree'" }, - "switch_extruder_retraction_amount": { "value": 5 }, - "travel_avoid_other_parts": { "value": false }, - "wall_0_acceleration": { "value": 1000 }, - "wall_0_deceleration": { "value": 1000 }, - "wall_0_end_speed_ratio": { "value": 100 }, - "wall_0_speed_split_distance": { "value": 0.2 }, - "wall_0_start_speed_ratio": { "value": 100 }, - "wall_0_wipe_dist": { "value": 0 }, - "wall_material_flow": { "value": 95 }, - "wall_overhang_angle": { "value": 45 }, - "wall_overhang_speed_factor": { "value": 50 }, - "wall_x_material_flow": { "value": 100 }, - "z_seam_corner": { "value": "'z_seam_corner_weighted'" }, - "z_seam_position": { "value": "'backright'" }, - "z_seam_type": { "value": "'sharpest_corner'" } - }, - "settings": - { - "material": - { - "children": - { - "material_max_flowrate": - { - "default_value": 16, - "description": "Maximum flowrate that the printer can extrude for the material", - "enabled": true, - "label": "Material Maximum Flowrate", - "maximum_value": "machine_max_feedrate_e * (material_diameter/2)**2 * math.pi", - "minimum_value": "0", - "settable_per_extruder": true, - "settable_per_mesh": false, - "type": "float", - "unit": "mm\u00b3/s", - "value": "16" - } - } - } + "prime_tower_position_y": { "value": "(resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" } } } \ No newline at end of file diff --git a/resources/definitions/bambulab_base.def.json b/resources/definitions/bambulab_base.def.json new file mode 100644 index 0000000000..4150349335 --- /dev/null +++ b/resources/definitions/bambulab_base.def.json @@ -0,0 +1,294 @@ +{ + "version": 2, + "name": "BambuLab base definition", + "inherits": "fdmprinter", + "metadata": + { + "visible": false, + "author": "UltiMaker", + "manufacturer": "BambuLab", + "file_formats": "application/vnd.bambulab-package.3dmanufacturing-3dmodel+xml" + }, + "overrides": + { + "acceleration_infill": { "value": "acceleration_print" }, + "acceleration_layer_0": { "value": 2000 }, + "acceleration_prime_tower": { "value": "acceleration_print" }, + "acceleration_print": { "value": 20000 }, + "acceleration_print_layer_0": { "value": "acceleration_layer_0" }, + "acceleration_roofing": { "value": "acceleration_wall_0" }, + "acceleration_skirt_brim": { "value": "acceleration_layer_0" }, + "acceleration_support": { "value": "acceleration_print" }, + "acceleration_support_bottom": { "value": "acceleration_support_interface" }, + "acceleration_support_infill": { "value": "acceleration_support" }, + "acceleration_support_interface": { "value": "acceleration_support" }, + "acceleration_support_roof": { "value": "acceleration_support_interface" }, + "acceleration_topbottom": { "value": "acceleration_print" }, + "acceleration_travel": { "value": 20000 }, + "acceleration_travel_enabled": { "value": true }, + "acceleration_travel_layer_0": { "value": "acceleration_layer_0" }, + "acceleration_wall": { "value": "acceleration_print/8" }, + "acceleration_wall_0": { "value": "acceleration_wall" }, + "acceleration_wall_0_roofing": { "value": "acceleration_wall_0" }, + "acceleration_wall_x": { "value": "acceleration_print" }, + "acceleration_wall_x_roofing": { "value": "acceleration_wall" }, + "adhesion_type": { "value": "'skirt'" }, + "bottom_thickness": { "value": 0.6 }, + "bridge_skin_speed": + { + "unit": "mm/s", + "value": "bridge_wall_speed" + }, + "bridge_sparse_infill_max_density": { "value": 50 }, + "bridge_wall_min_length": { "value": 10 }, + "bridge_wall_speed": + { + "unit": "mm/s", + "value": 50 + }, + "cool_min_layer_time": { "value": 6 }, + "cool_min_speed": { "value": 6 }, + "cool_min_temperature": { "value": "material_print_temperature-15" }, + "default_material_print_temperature": { "maximum_value_warning": 320 }, + "extra_infill_lines_to_support_skins": { "value": "'walls_and_lines'" }, + "gradual_flow_enabled": { "value": false }, + "hole_xy_offset": { "value": 0.075 }, + "infill_overlap": { "value": 10 }, + "infill_pattern": { "value": "'zigzag' if infill_sparse_density > 80 else 'grid'" }, + "infill_sparse_density": { "value": 15 }, + "infill_wall_line_count": { "value": "1 if infill_sparse_density > 80 else 0" }, + "jerk_infill": { "value": "jerk_print" }, + "jerk_layer_0": { "value": "jerk_print/2" }, + "jerk_prime_tower": { "value": "jerk_print" }, + "jerk_print": { "value": "50" }, + "jerk_print_layer_0": { "value": "jerk_layer_0" }, + "jerk_roofing": { "value": "jerk_wall_0" }, + "jerk_skirt_brim": { "value": "jerk_layer_0" }, + "jerk_support": { "value": "jerk_print" }, + "jerk_support_bottom": { "value": "jerk_support_interface" }, + "jerk_support_infill": { "value": "jerk_support" }, + "jerk_support_interface": { "value": "jerk_support" }, + "jerk_support_roof": { "value": "jerk_support_interface" }, + "jerk_topbottom": { "value": "jerk_print" }, + "jerk_travel": { "value": 50 }, + "jerk_travel_enabled": { "value": true }, + "jerk_travel_layer_0": { "value": "jerk_travel" }, + "jerk_wall": { "value": "jerk_print/5" }, + "jerk_wall_0": { "value": "jerk_wall" }, + "jerk_wall_0_roofing": { "value": "jerk_wall_0" }, + "jerk_wall_x": { "value": "jerk_print" }, + "jerk_wall_x_roofing": { "value": "jerk_wall_0" }, + "line_width": { "value": 0.42 }, + "machine_acceleration": { "value": 10000 }, + "machine_buildplate_type": + { + "default_value": "textured_pei_plate", + "options": + { + "cool_plate": "Cool Plate", + "engineering_plate": "Engineering Plate", + "high_temp_plate": "High Temp Plate", + "textured_pei_plate": "Textured PEI Plate" + } + }, + "machine_center_is_zero": { "default_value": false }, + "machine_gcode_flavor": { "default_value": "BambuLab" }, + "machine_heated_bed": { "default_value": true }, + "machine_max_feedrate_e": { "value": 150 }, + "machine_max_feedrate_x": { "value": 500 }, + "machine_max_feedrate_y": { "value": 500 }, + "machine_max_feedrate_z": { "value": 15 }, + "machine_max_jerk_e": { "default_value": 100 }, + "machine_max_jerk_xy": { "default_value": 5000 }, + "machine_max_jerk_z": { "default_value": 100 }, + "machine_nozzle_cool_down_speed": { "default_value": 1.3 }, + "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "machine_show_variants": { "value": true }, + "machine_use_extruder_offset_to_offset_coords": { "value": false }, + "material_diameter": { "default_value": 1.75 }, + "material_flush_purge_length": + { + "default_value": 80, + "enabled": "not prime_tower_enable" + }, + "material_flush_purge_speed": + { + "default_value": 500, + "enabled": "not prime_tower_enable" + }, + "max_skin_angle_for_expansion": { "value": 45 }, + "meshfix_maximum_resolution": { "value": 0.4 }, + "min_infill_area": { "default_value": 10 }, + "optimize_wall_printing_order": { "value": false }, + "prime_tower_enable": { "default_value": true }, + "prime_tower_line_width": { "value": "1.5 * line_width" }, + "prime_tower_min_volume": { "default_value": 250 }, + "prime_tower_size": { "default_value": 40 }, + "relative_extrusion": { "value": true }, + "retraction_amount": { "value": 0.5 }, + "retraction_combing_max_distance": { "value": 100 }, + "retraction_extra_prime_amount": { "value": 0.12 }, + "retraction_hop": { "value": 0.2 }, + "retraction_hop_after_extruder_switch_height": { "value": 2 }, + "retraction_hop_enabled": { "value": true }, + "retraction_min_travel": { "value": "5 if support_enable and support_structure=='tree' else line_width * 2" }, + "retraction_prime_speed": { "value": 15 }, + "retraction_speed": { "value": 30 }, + "skin_edge_support_thickness": { "value": 0 }, + "skin_material_flow": { "value": 95 }, + "skin_overlap": { "value": 0 }, + "skin_preshrink": { "value": 0 }, + "skirt_line_count": { "value": 5 }, + "small_skin_on_surface": { "value": false }, + "small_skin_width": { "value": 4 }, + "speed_infill": + { + "maximum_value_warning": 500, + "value": "speed_print" + }, + "speed_ironing": + { + "maximum_value_warning": 500, + "value": 20 + }, + "speed_layer_0": + { + "maximum_value_warning": 500, + "value": "speed_print/6" + }, + "speed_prime_tower": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_print": + { + "maximum_value_warning": 500, + "value": 300 + }, + "speed_print_layer_0": + { + "maximum_value_warning": 500, + "value": "speed_layer_0" + }, + "speed_roofing": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_skirt_brim": + { + "maximum_value_warning": 500, + "value": "speed_layer_0" + }, + "speed_support": + { + "maximum_value_warning": 500, + "value": "speed_wall_0" + }, + "speed_support_bottom": + { + "maximum_value_warning": 500, + "value": "speed_support_interface" + }, + "speed_support_infill": + { + "maximum_value_warning": 500, + "value": "speed_support" + }, + "speed_support_interface": + { + "maximum_value_warning": 500, + "value": 50 + }, + "speed_support_roof": + { + "maximum_value_warning": 500, + "value": "speed_support_interface" + }, + "speed_topbottom": + { + "maximum_value_warning": 500, + "value": "speed_print" + }, + "speed_travel": + { + "maximum_value": 500, + "value": 500 + }, + "speed_travel_layer_0": + { + "maximum_value": 500, + "value": 150 + }, + "speed_wall": + { + "maximum_value_warning": 500, + "value": "speed_print*2/3" + }, + "speed_wall_0": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_wall_0_roofing": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "speed_wall_x": + { + "maximum_value_warning": 500, + "value": "speed_print" + }, + "speed_wall_x_roofing": + { + "maximum_value_warning": 500, + "value": "speed_wall" + }, + "support_brim_line_count": { "value": 5 }, + "support_density": { "value": 15 }, + "support_infill_rate": { "value": "80 if gradual_support_infill_steps != 0 else 15" }, + "support_pattern": { "value": "'gyroid'" }, + "support_structure": { "value": "'tree'" }, + "switch_extruder_retraction_amount": { "value": 5 }, + "travel_avoid_other_parts": { "value": false }, + "wall_0_acceleration": { "value": 1000 }, + "wall_0_deceleration": { "value": 1000 }, + "wall_0_end_speed_ratio": { "value": 100 }, + "wall_0_speed_split_distance": { "value": 0.2 }, + "wall_0_start_speed_ratio": { "value": 100 }, + "wall_0_wipe_dist": { "value": 0 }, + "wall_material_flow": { "value": 95 }, + "wall_overhang_angle": { "value": 10 }, + "wall_overhang_speed_factors": { "default_value": "[25,15,5,5]" }, + "wall_x_material_flow": { "value": 100 }, + "z_seam_corner": { "value": "'z_seam_corner_weighted'" }, + "z_seam_position": { "value": "'backright'" }, + "z_seam_type": { "value": "'sharpest_corner'" } + }, + "settings": + { + "material": + { + "children": + { + "material_max_flowrate": + { + "default_value": 16, + "description": "Maximum flowrate that the printer can extrude for the material", + "enabled": true, + "label": "Material Maximum Flowrate", + "maximum_value": "machine_max_feedrate_e * (material_diameter/2)**2 * math.pi", + "minimum_value": "0", + "settable_per_extruder": true, + "settable_per_mesh": false, + "type": "float", + "unit": "mm\u00b3/s", + "value": "16" + } + } + } + } +} \ No newline at end of file diff --git a/resources/definitions/bambulab_x1.def.json b/resources/definitions/bambulab_x1.def.json index ce18463df6..45a4929f74 100644 --- a/resources/definitions/bambulab_x1.def.json +++ b/resources/definitions/bambulab_x1.def.json @@ -5,7 +5,7 @@ "metadata": { "visible": true, - "author": "Mariska", + "author": "UltiMaker", "manufacturer": "BambuLab", "file_formats": "text/x-gcode", "platform": "bambulab_x1.obj", @@ -119,7 +119,7 @@ "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, "machine_nozzle_size": { "value": 0.4 }, "machine_show_variants": { "value": true }, - "machine_start_gcode": { "default_value": ";===== machine: X1 =========================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_bed_temperature_layer_0} ;wait for bed temp\n\n;=========register first layer scan=====\n{if machine_scan_first_layer}\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T{initial_extruder_nr}\n G1 X54 F12000\n G1 Y265\n M400\nM621 S{initial_extruder_nr}A\nM620.1 E F{material_max_flowrate/2.4053*60} T{material_print_temperature, initial_extruder_nr}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if (material_type=='PLA' and (material_bed_temperature >45 or material_bed_temperature_layer_0 >45)), initial_extruder_nr}\n M106 P3 S180\n{elif (material_type=='PLA' and (material_bed_temperature >50 or material_bed_temperature_layer_0 >50)), initial_extruder_nr}\n M106 P3 S255\n{endif};Prevent PLA from jamming\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if machine_scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{material_print_temperature, initial_extruder_nr}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y11 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n{if machine_buildplate=='textured_pei_plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if acceleration_wall_0 > 0, initial_extruder_nr}\n M204 S{acceleration_wall_0, initial_extruder_nr}\n {else}\n M204 S{acceleration_print, initial_extruder_nr}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{material_print_temperature, initial_extruder_nr} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60/4} C5.000 D{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60, initial_extruder_nr} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{material_print_temperature, initial_extruder_nr}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X185.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X190.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X195.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X200.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X205.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X210.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X215.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X220.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X225.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_amount, initial_extruder_nr} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_amount, initial_extruder_nr} F1800\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nG0 X253 E6.4 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.6) * 60, initial_extruder_nr}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" }, + "machine_start_gcode": { "default_value": "" }, "machine_use_extruder_offset_to_offset_coords": { "value": false }, "machine_width": { "value": 256 }, "material_diameter": { "value": 1.75 }, diff --git a/resources/extruders/bambulab_a1_extruder_0.def.json b/resources/extruders/bambulab_a1_extruder_0.def.json new file mode 100644 index 0000000000..fa8bf82a66 --- /dev/null +++ b/resources/extruders/bambulab_a1_extruder_0.def.json @@ -0,0 +1,19 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulab_a1", + "position": "0" + }, + "overrides": + { + "extruder_nr": { "default_value": 0 }, + "machine_extruder_change_duration": { "default_value": 29 }, + "machine_extruder_end_code": { "default_value": ";===== A1 extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1 extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1 extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1 extruder start {extruder_nr} finish =====\n" }, + "material_diameter": { "default_value": 1.75 }, + "switch_extruder_retraction_amount": { "default_value": 18 } + } +} \ No newline at end of file diff --git a/resources/extruders/bambulab_a1_extruder_1.def.json b/resources/extruders/bambulab_a1_extruder_1.def.json new file mode 100644 index 0000000000..108fecb2d1 --- /dev/null +++ b/resources/extruders/bambulab_a1_extruder_1.def.json @@ -0,0 +1,19 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulab_a1", + "position": "1" + }, + "overrides": + { + "extruder_nr": { "default_value": 1 }, + "machine_extruder_change_duration": { "default_value": 29 }, + "machine_extruder_end_code": { "default_value": ";===== A1 extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1 extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1 extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1 extruder start {extruder_nr} finish =====\n" }, + "material_diameter": { "default_value": 1.75 }, + "switch_extruder_retraction_amount": { "default_value": 18 } + } +} \ No newline at end of file diff --git a/resources/extruders/bambulab_a1_extruder_2.def.json b/resources/extruders/bambulab_a1_extruder_2.def.json new file mode 100644 index 0000000000..d1ff6bf06c --- /dev/null +++ b/resources/extruders/bambulab_a1_extruder_2.def.json @@ -0,0 +1,19 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulab_a1", + "position": "2" + }, + "overrides": + { + "extruder_nr": { "default_value": 2 }, + "machine_extruder_change_duration": { "default_value": 29 }, + "machine_extruder_end_code": { "default_value": ";===== A1 extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1 extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1 extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1 extruder start {extruder_nr} finish =====\n" }, + "material_diameter": { "default_value": 1.75 }, + "switch_extruder_retraction_amount": { "default_value": 18 } + } +} \ No newline at end of file diff --git a/resources/extruders/bambulab_a1_extruder_3.def.json b/resources/extruders/bambulab_a1_extruder_3.def.json new file mode 100644 index 0000000000..7b82623d9a --- /dev/null +++ b/resources/extruders/bambulab_a1_extruder_3.def.json @@ -0,0 +1,19 @@ +{ + "version": 2, + "name": "Extruder", + "inherits": "fdmextruder", + "metadata": + { + "machine": "bambulab_a1", + "position": "3" + }, + "overrides": + { + "extruder_nr": { "default_value": 3 }, + "machine_extruder_change_duration": { "default_value": 29 }, + "machine_extruder_end_code": { "default_value": ";===== A1 extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1 extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1 extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1 extruder start {extruder_nr} finish =====\n" }, + "material_diameter": { "default_value": 1.75 }, + "switch_extruder_retraction_amount": { "default_value": 18 } + } +} \ No newline at end of file diff --git a/resources/extruders/bambulab_a1mini_extruder_0.def.json b/resources/extruders/bambulab_a1mini_extruder_0.def.json index 87f8b4be3d..a9240362f0 100644 --- a/resources/extruders/bambulab_a1mini_extruder_0.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_0.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "bambulabs_a1mini", + "machine": "bambulab_a1mini", "position": "0" }, "overrides": diff --git a/resources/extruders/bambulab_a1mini_extruder_1.def.json b/resources/extruders/bambulab_a1mini_extruder_1.def.json index 9e136fc866..0c7a20f213 100644 --- a/resources/extruders/bambulab_a1mini_extruder_1.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_1.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "bambulabs_a1mini", + "machine": "bambulab_a1mini", "position": "1" }, "overrides": diff --git a/resources/extruders/bambulab_a1mini_extruder_2.def.json b/resources/extruders/bambulab_a1mini_extruder_2.def.json index 94d3abb0b7..cc697e5ea7 100644 --- a/resources/extruders/bambulab_a1mini_extruder_2.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_2.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "bambulabs_a1mini", + "machine": "bambulab_a1mini", "position": "2" }, "overrides": diff --git a/resources/extruders/bambulab_a1mini_extruder_3.def.json b/resources/extruders/bambulab_a1mini_extruder_3.def.json index 4e6339d387..16f59581fb 100644 --- a/resources/extruders/bambulab_a1mini_extruder_3.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_3.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "bambulabs_a1mini", + "machine": "bambulab_a1mini", "position": "3" }, "overrides": diff --git a/resources/extruders/bambulab_x1_extruder_1.def.json b/resources/extruders/bambulab_x1_extruder_1.def.json index e5c305232a..2377d4199c 100644 --- a/resources/extruders/bambulab_x1_extruder_1.def.json +++ b/resources/extruders/bambulab_x1_extruder_1.def.json @@ -11,6 +11,8 @@ { "extruder_nr": { "default_value": 1 }, "machine_extruder_change_duration": { "default_value": 29 }, + "machine_extruder_end_code": { "default_value": "M620 S[next_extruder]A\nM204 S9000\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E-{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\n{else}\nM620.11 S0\n{endif}\nM400\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\nM628 S1\nG92 E0\nG1 E{retraction_distances_when_cut[previous_extruder]} F[old_filament_e_feedrate]\nM400\nM629 S1\n{else}\nM620.11 S0\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == 'PETG'}\nM109 S260\n{elsif filament_type[next_extruder] == 'PVA'}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" }, + "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, "material_diameter": { "default_value": 1.75 } } } \ No newline at end of file diff --git a/resources/extruders/bambulab_x1_extruder_2.def.json b/resources/extruders/bambulab_x1_extruder_2.def.json index 8250fdebfc..62c87c794e 100644 --- a/resources/extruders/bambulab_x1_extruder_2.def.json +++ b/resources/extruders/bambulab_x1_extruder_2.def.json @@ -11,6 +11,8 @@ { "extruder_nr": { "default_value": 2 }, "machine_extruder_change_duration": { "default_value": 29 }, + "machine_extruder_end_code": { "default_value": "M620 S[next_extruder]A\nM204 S9000\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E-{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\n{else}\nM620.11 S0\n{endif}\nM400\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\nM628 S1\nG92 E0\nG1 E{retraction_distances_when_cut[previous_extruder]} F[old_filament_e_feedrate]\nM400\nM629 S1\n{else}\nM620.11 S0\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == 'PETG'}\nM109 S260\n{elsif filament_type[next_extruder] == 'PVA'}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" }, + "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, "material_diameter": { "default_value": 1.75 } } } \ No newline at end of file diff --git a/resources/extruders/bambulab_x1_extruder_3.def.json b/resources/extruders/bambulab_x1_extruder_3.def.json index b2c6927d45..ab7752b74f 100644 --- a/resources/extruders/bambulab_x1_extruder_3.def.json +++ b/resources/extruders/bambulab_x1_extruder_3.def.json @@ -11,6 +11,8 @@ { "extruder_nr": { "default_value": 3 }, "machine_extruder_change_duration": { "default_value": 29 }, + "machine_extruder_end_code": { "default_value": "M620 S[next_extruder]A\nM204 S9000\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E-{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\n{else}\nM620.11 S0\n{endif}\nM400\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\nM628 S1\nG92 E0\nG1 E{retraction_distances_when_cut[previous_extruder]} F[old_filament_e_feedrate]\nM400\nM629 S1\n{else}\nM620.11 S0\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == 'PETG'}\nM109 S260\n{elsif filament_type[next_extruder] == 'PVA'}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" }, + "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, "material_diameter": { "default_value": 1.75 } } } \ No newline at end of file diff --git a/resources/quality/bambu/bambulab_a1_0.4_PLA_standard.inst.cfg b/resources/quality/bambu/bambulab_a1_0.4_PLA_standard.inst.cfg new file mode 100644 index 0000000000..9f2878702e --- /dev/null +++ b/resources/quality/bambu/bambulab_a1_0.4_PLA_standard.inst.cfg @@ -0,0 +1,14 @@ +[general] +definition = bambulab_a1 +name = Standard +version = 4 + +[metadata] +material = generic_pla +quality_type = normal +setting_version = 25 +type = quality +variant = 0.4mm + +[values] + diff --git a/resources/quality/bambu/bambulab_a1_normal.inst.cfg b/resources/quality/bambu/bambulab_a1_normal.inst.cfg new file mode 100644 index 0000000000..a3fd08879e --- /dev/null +++ b/resources/quality/bambu/bambulab_a1_normal.inst.cfg @@ -0,0 +1,15 @@ +[general] +definition = bambulab_a1 +name = Normal +version = 4 + +[metadata] +global_quality = True +quality_type = normal +setting_version = 25 +type = quality +weight = 0 + +[values] +layer_height = 0.2 + diff --git a/resources/quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg b/resources/quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg index 4a412b07a3..95c665155d 100644 --- a/resources/quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg +++ b/resources/quality/bambu/bambulab_a1mini_0.4_PLA_standard.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] material = generic_pla quality_type = normal -setting_version = 23 +setting_version = 25 type = quality variant = 0.4mm diff --git a/resources/quality/bambu/bambulab_a1mini_normal.inst.cfg b/resources/quality/bambu/bambulab_a1mini_normal.inst.cfg index a5dc2aaa4b..afb403d8f1 100644 --- a/resources/quality/bambu/bambulab_a1mini_normal.inst.cfg +++ b/resources/quality/bambu/bambulab_a1mini_normal.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] global_quality = True quality_type = normal -setting_version = 22 +setting_version = 25 type = quality weight = 0 diff --git a/resources/quality/bambu/bambulab_x1_0.4_PLA_standard.inst.cfg b/resources/quality/bambu/bambulab_x1_0.4_PLA_standard.inst.cfg index 282ecefc55..01ba90dcb9 100644 --- a/resources/quality/bambu/bambulab_x1_0.4_PLA_standard.inst.cfg +++ b/resources/quality/bambu/bambulab_x1_0.4_PLA_standard.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] material = generic_pla quality_type = normal -setting_version = 23 +setting_version = 25 type = quality variant = X1 0.4mm diff --git a/resources/quality/bambu/bambulab_x1_normal.inst.cfg b/resources/quality/bambu/bambulab_x1_normal.inst.cfg index 6ea1c1ffea..22c501ee36 100644 --- a/resources/quality/bambu/bambulab_x1_normal.inst.cfg +++ b/resources/quality/bambu/bambulab_x1_normal.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] global_quality = True quality_type = normal -setting_version = 22 +setting_version = 25 type = quality weight = 0 diff --git a/resources/quality/bambu/bambulab_x1c_0.4_PLA_standard.inst.cfg b/resources/quality/bambu/bambulab_x1c_0.4_PLA_standard.inst.cfg index c71b9ecab8..7fa47f0f52 100644 --- a/resources/quality/bambu/bambulab_x1c_0.4_PLA_standard.inst.cfg +++ b/resources/quality/bambu/bambulab_x1c_0.4_PLA_standard.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] material = generic_pla quality_type = normal -setting_version = 23 +setting_version = 25 type = quality variant = X1C 0.4mm diff --git a/resources/variants/bambu/bambulab_a1_0.4.inst.cfg b/resources/variants/bambu/bambulab_a1_0.4.inst.cfg index 357c894b8c..0823eb58b3 100644 --- a/resources/variants/bambu/bambulab_a1_0.4.inst.cfg +++ b/resources/variants/bambu/bambulab_a1_0.4.inst.cfg @@ -1,11 +1,11 @@ [general] -definition = bambulab_a1mini +definition = bambulab_a1 name = 0.4mm version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 25 type = variant [values] diff --git a/resources/variants/bambu/bambulab_a1mini_0.4.inst.cfg b/resources/variants/bambu/bambulab_a1mini_0.4.inst.cfg new file mode 100644 index 0000000000..fceec9b0e8 --- /dev/null +++ b/resources/variants/bambu/bambulab_a1mini_0.4.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = bambulab_a1mini +name = 0.4mm +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 25 +type = variant + +[values] +machine_nozzle_size = 0.4 + diff --git a/resources/variants/bambu/bambulab_p1p_0.4.inst.cfg b/resources/variants/bambu/bambulab_p1p_0.4.inst.cfg index e649c718b6..d18e04731e 100644 --- a/resources/variants/bambu/bambulab_p1p_0.4.inst.cfg +++ b/resources/variants/bambu/bambulab_p1p_0.4.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 25 type = variant [values] diff --git a/resources/variants/bambu/bambulab_p1s_0.4.inst.cfg b/resources/variants/bambu/bambulab_p1s_0.4.inst.cfg index e649c718b6..d18e04731e 100644 --- a/resources/variants/bambu/bambulab_p1s_0.4.inst.cfg +++ b/resources/variants/bambu/bambulab_p1s_0.4.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 25 type = variant [values] diff --git a/resources/variants/bambu/bambulab_x1_0.4.inst.cfg b/resources/variants/bambu/bambulab_x1_0.4.inst.cfg index 3f42f77494..d3f5248b2d 100644 --- a/resources/variants/bambu/bambulab_x1_0.4.inst.cfg +++ b/resources/variants/bambu/bambulab_x1_0.4.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 25 type = variant [values] diff --git a/resources/variants/bambu/bambulab_x1c_0.4.inst.cfg b/resources/variants/bambu/bambulab_x1c_0.4.inst.cfg index 58cabff35e..1a82636741 100644 --- a/resources/variants/bambu/bambulab_x1c_0.4.inst.cfg +++ b/resources/variants/bambu/bambulab_x1c_0.4.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 25 type = variant [values] From a6e324b748490c80a79f21939d830d42c5a5d43e Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 22 Apr 2025 11:32:51 +0200 Subject: [PATCH 092/299] Fix extruder stack corruption CURA-12346 For some dark reason, importing the ExtruderStack class in the ThreeMFWriter somehow corrupts the loading of the extruders stacks. As it is imported only for typing, do the import only for type-checking. --- plugins/3MFWriter/ThreeMFWriter.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index be0fa1a01b..20c7e5d05c 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -8,10 +8,12 @@ import json import re import threading -from typing import Optional, cast, List, Dict, Pattern, Set +from typing import Optional, cast, List, Dict, Set, TYPE_CHECKING + +if TYPE_CHECKING: + from Settings.ExtruderStack import ExtruderStack from Machines.Models.ExtrudersModel import ExtrudersModel -from Settings.ExtruderStack import ExtruderStack from UM.PluginRegistry import PluginRegistry from UM.Mesh.MeshWriter import MeshWriter from UM.Math.Vector import Vector @@ -461,7 +463,7 @@ class ThreeMFWriter(MeshWriter): return ET.Element("Relationships", xmlns=self._namespaces["relationships"]) @staticmethod - def _getMaterialColor(extruder: ExtruderStack) -> str: + def _getMaterialColor(extruder: "ExtruderStack") -> str: position = int(extruder.getMetaDataEntry("position", default="0")) try: default_color = ExtrudersModel.defaultColors[position] From 204258f7e3cbe3fbd90f91e351ca45a7e732e8b6 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 22 Apr 2025 12:54:58 +0200 Subject: [PATCH 093/299] Set default gyroid infill pattern for BambuLab printers CURA-12346 Grid infill prints very ugly at high speeds, this one is much cleaner and provides a proper surface for roofs --- resources/definitions/bambulab_base.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/bambulab_base.def.json b/resources/definitions/bambulab_base.def.json index 4150349335..fb6c9e3208 100644 --- a/resources/definitions/bambulab_base.def.json +++ b/resources/definitions/bambulab_base.def.json @@ -54,7 +54,7 @@ "gradual_flow_enabled": { "value": false }, "hole_xy_offset": { "value": 0.075 }, "infill_overlap": { "value": 10 }, - "infill_pattern": { "value": "'zigzag' if infill_sparse_density > 80 else 'grid'" }, + "infill_pattern": { "value": "'zigzag' if infill_sparse_density > 80 else 'gyroid'" }, "infill_sparse_density": { "value": 15 }, "infill_wall_line_count": { "value": "1 if infill_sparse_density > 80 else 0" }, "jerk_infill": { "value": "jerk_print" }, From 7731ee4b241ece88d726c5a58c25ccc2968cfce7 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 22 Apr 2025 16:01:32 +0200 Subject: [PATCH 094/299] Basically working import from BambuStudio/OrcaSlicer 3MF CURA-12099 --- plugins/3MFReader/ThreeMFReader.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 9d4ace1698..45ab2e7d2f 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -94,7 +94,7 @@ class ThreeMFReader(MeshReader): return temp_mat @staticmethod - def _convertSavitarNodeToUMNode(savitar_node: Savitar.SceneNode, file_name: str = "") -> Optional[SceneNode]: + def _convertSavitarNodeToUMNode(savitar_node: Savitar.SceneNode, file_name: str = "", archive: zipfile.ZipFile = None) -> Optional[SceneNode]: """Convenience function that converts a SceneNode object (as obtained from libSavitar) to a scene node. :returns: Scene node. @@ -115,6 +115,10 @@ class ThreeMFReader(MeshReader): active_build_plate = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate + component_path = savitar_node.getComponentPath() + if component_path != "" and archive is not None: + savitar_node.parseComponentData(archive.open(component_path.lstrip("/")).read()) + um_node = CuraSceneNode() # This adds a SettingOverrideDecorator um_node.addDecorator(BuildPlateDecorator(active_build_plate)) try: @@ -143,7 +147,7 @@ class ThreeMFReader(MeshReader): um_node.setMeshData(mesh_data) for child in savitar_node.getChildren(): - child_node = ThreeMFReader._convertSavitarNodeToUMNode(child) + child_node = ThreeMFReader._convertSavitarNodeToUMNode(child, archive=archive) if child_node: um_node.addChild(child_node) @@ -232,7 +236,7 @@ class ThreeMFReader(MeshReader): CuraApplication.getInstance().getController().getScene().setMetaDataEntry(key, value) for node in scene_3mf.getSceneNodes(): - um_node = ThreeMFReader._convertSavitarNodeToUMNode(node, file_name) + um_node = ThreeMFReader._convertSavitarNodeToUMNode(node, file_name, archive) if um_node is None: continue From 89a83c0440ef84d0fcc996ac3c6480c026f5891b Mon Sep 17 00:00:00 2001 From: wawanbreton <601114+wawanbreton@users.noreply.github.com> Date: Tue, 22 Apr 2025 14:16:19 +0000 Subject: [PATCH 095/299] Apply printer-linter format --- resources/definitions/bambulab_a1.def.json | 2 +- resources/definitions/bambulab_a1mini.def.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/bambulab_a1.def.json b/resources/definitions/bambulab_a1.def.json index bbcee00fb5..7079267692 100644 --- a/resources/definitions/bambulab_a1.def.json +++ b/resources/definitions/bambulab_a1.def.json @@ -4,6 +4,7 @@ "inherits": "bambulab_base", "metadata": { + "visible": true, "platform": "bambulab_x1.obj", "has_machine_quality": true, "has_material": true, @@ -24,7 +25,6 @@ ], "platform_texture": "bambulab-buildplate.png", "preferred_variant_name": "0.4mm", - "visible": true, "weight": 3 }, "overrides": diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 3d8431c6b4..258f104a4e 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -4,6 +4,7 @@ "inherits": "bambulab_base", "metadata": { + "visible": true, "platform": "bambulab_a1mini.obj", "has_machine_quality": true, "has_material": true, @@ -24,7 +25,6 @@ ], "platform_texture": "bambulab-buildplate.png", "preferred_variant_name": "0.4mm", - "visible": true, "weight": 3 }, "overrides": From d980b5ae2e3fcb424137591ed3627ff093016d15 Mon Sep 17 00:00:00 2001 From: Luke Brewer <79376204+lukbrew25@users.noreply.github.com> Date: Tue, 22 Apr 2025 10:36:24 -0500 Subject: [PATCH 096/299] Add support for Toybox Alpha One --- .../definitions/toybox_alpha_one.def.json | 25 +++++++++++++++++++ .../toybox_alpha_one_extruder_0.def.json | 16 ++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 resources/definitions/toybox_alpha_one.def.json create mode 100644 resources/extruders/toybox_alpha_one_extruder_0.def.json diff --git a/resources/definitions/toybox_alpha_one.def.json b/resources/definitions/toybox_alpha_one.def.json new file mode 100644 index 0000000000..a2d83c5f10 --- /dev/null +++ b/resources/definitions/toybox_alpha_one.def.json @@ -0,0 +1,25 @@ +{ + "version": 2, + "name": "Toybox Alpha One", + "inherits": "fdmprinter", + "metadata": + { + "visible": true, + "author": "lukbrew25", + "manufacturer": "Toybox", + "file_formats": "text/x-gcode", + "has_machine_quality": false, + "machine_extruder_trains": { "0": "toybox_alpha_one_extruder_0" } + }, + "overrides": + { + "gantry_height": { "value": "0.0" }, + "machine_depth": { "default_value": 80 }, + "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, + "machine_height": { "default_value": 90 }, + "machine_name": { "default_value": "Toybox Alpha One" }, + "machine_start_gcode": { "default_value": "G90\nM82" }, + "machine_width": { "default_value": 70 }, + "material_diameter": { "default_value": 1.75 } + } +} \ No newline at end of file diff --git a/resources/extruders/toybox_alpha_one_extruder_0.def.json b/resources/extruders/toybox_alpha_one_extruder_0.def.json new file mode 100644 index 0000000000..a2787d0ed3 --- /dev/null +++ b/resources/extruders/toybox_alpha_one_extruder_0.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": + { + "machine": "toybox_alpha_one", + "position": "0" + }, + "overrides": + { + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 }, + "machine_nozzle_offset_x": { "default_value": -3.0 } + } +} \ No newline at end of file From de8bf1a5dfe1767f8648ea1403e34c32aada5ad0 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 23 Apr 2025 08:49:36 +0200 Subject: [PATCH 097/299] Fix 3MF export imports. done as part of CURA-12099 --- plugins/3MFReader/__init__.py | 2 +- plugins/3MFWriter/ThreeMFWriter.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/3MFReader/__init__.py b/plugins/3MFReader/__init__.py index 5e2b68fce0..d468783a90 100644 --- a/plugins/3MFReader/__init__.py +++ b/plugins/3MFReader/__init__.py @@ -23,7 +23,7 @@ def getMetaData() -> Dict: if "3MFReader.ThreeMFReader" in sys.modules: metaData["mesh_reader"] = [ { - "extension": "3mf", + "extension": workspace_extension, "description": catalog.i18nc("@item:inlistbox", "3MF File") } ] diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index be0fa1a01b..61aec6b664 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -10,8 +10,6 @@ import threading from typing import Optional, cast, List, Dict, Pattern, Set -from Machines.Models.ExtrudersModel import ExtrudersModel -from Settings.ExtruderStack import ExtruderStack from UM.PluginRegistry import PluginRegistry from UM.Mesh.MeshWriter import MeshWriter from UM.Math.Vector import Vector @@ -26,7 +24,9 @@ from UM.Settings.ContainerRegistry import ContainerRegistry from cura.CuraApplication import CuraApplication from cura.CuraPackageManager import CuraPackageManager +from cura.Machines.Models.ExtrudersModel import ExtrudersModel from cura.Settings import CuraContainerStack +from cura.Settings.ExtruderStack import ExtruderStack from cura.Utils.Threading import call_on_qt_thread from cura.Scene.CuraSceneNode import CuraSceneNode from cura.Snapshot import Snapshot From 9b10467f3e993bd55a53ee937561702572911c21 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 23 Apr 2025 16:22:32 +0200 Subject: [PATCH 098/299] Probably 'open as model' should not apply if the 3mf isn't a project file. This would cause the 3MF projects from other vendors, which isn't a 'project' to us in the sense that it isn't a Cura project, to have their models 'arranged', unless the file was opened via 'recent files', in which case the open mode was set to always ask instead. done as part of CURA-12099 --- cura/CuraApplication.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 6e4da621ff..87657af5f5 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -188,6 +188,7 @@ class CuraApplication(QtApplication): self._single_instance = None self._open_project_mode: Optional[str] = None + self._read_operation_is_project_file: Optional[bool] = None self._cura_formula_functions = None # type: Optional[CuraFormulaFunctions] @@ -2015,18 +2016,18 @@ class CuraApplication(QtApplication): self.deleteAll() break - is_project_file = self.checkIsValidProjectFile(file) + self._read_operation_is_project_file = self.checkIsValidProjectFile(file) if self._open_project_mode is None: self._open_project_mode = self.getPreferences().getValue("cura/choice_on_open_project") - if is_project_file and self._open_project_mode == "open_as_project": + if self._read_operation_is_project_file and self._open_project_mode == "open_as_project": # open as project immediately without presenting a dialog workspace_handler = self.getWorkspaceFileHandler() workspace_handler.readLocalFile(file, add_to_recent_files_hint = add_to_recent_files) return - if is_project_file and self._open_project_mode == "always_ask": + if self._read_operation_is_project_file and self._open_project_mode == "always_ask": # present a dialog asking to open as project or import models self.callLater(self.openProjectFile.emit, file, add_to_recent_files) return @@ -2164,7 +2165,7 @@ class CuraApplication(QtApplication): nodes_to_arrange.append(node) # If the file is a project,and models are to be loaded from a that project, # models inside file should be arranged in buildplate. - elif self._open_project_mode == "open_as_model": + elif self._read_operation_is_project_file and self._open_project_mode == "open_as_model": nodes_to_arrange.append(node) # This node is deep copied from some other node which already has a BuildPlateDecorator, but the deepcopy From 7ec0fa89ac955cc45ce3014a825bb6637837bbef Mon Sep 17 00:00:00 2001 From: Luke Brewer <79376204+lukbrew25@users.noreply.github.com> Date: Wed, 23 Apr 2025 10:02:46 -0500 Subject: [PATCH 099/299] Add Alpha 2 to name as both Alpha 1 and 2 are supported by this profile --- ...box_alpha_one.def.json => toybox_alpha_one_two.def.json} | 6 +++--- ..._0.def.json => toybox_alpha_one_two_extruder_0.def.json} | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename resources/definitions/{toybox_alpha_one.def.json => toybox_alpha_one_two.def.json} (78%) rename resources/extruders/{toybox_alpha_one_extruder_0.def.json => toybox_alpha_one_two_extruder_0.def.json} (88%) diff --git a/resources/definitions/toybox_alpha_one.def.json b/resources/definitions/toybox_alpha_one_two.def.json similarity index 78% rename from resources/definitions/toybox_alpha_one.def.json rename to resources/definitions/toybox_alpha_one_two.def.json index a2d83c5f10..6dc32a5fa7 100644 --- a/resources/definitions/toybox_alpha_one.def.json +++ b/resources/definitions/toybox_alpha_one_two.def.json @@ -1,6 +1,6 @@ { "version": 2, - "name": "Toybox Alpha One", + "name": "Toybox Alpha One/Two", "inherits": "fdmprinter", "metadata": { @@ -9,7 +9,7 @@ "manufacturer": "Toybox", "file_formats": "text/x-gcode", "has_machine_quality": false, - "machine_extruder_trains": { "0": "toybox_alpha_one_extruder_0" } + "machine_extruder_trains": { "0": "toybox_alpha_one_two_extruder_0" } }, "overrides": { @@ -17,7 +17,7 @@ "machine_depth": { "default_value": 80 }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "machine_height": { "default_value": 90 }, - "machine_name": { "default_value": "Toybox Alpha One" }, + "machine_name": { "default_value": "Toybox Alpha One/Two" }, "machine_start_gcode": { "default_value": "G90\nM82" }, "machine_width": { "default_value": 70 }, "material_diameter": { "default_value": 1.75 } diff --git a/resources/extruders/toybox_alpha_one_extruder_0.def.json b/resources/extruders/toybox_alpha_one_two_extruder_0.def.json similarity index 88% rename from resources/extruders/toybox_alpha_one_extruder_0.def.json rename to resources/extruders/toybox_alpha_one_two_extruder_0.def.json index a2787d0ed3..1bc498f9fb 100644 --- a/resources/extruders/toybox_alpha_one_extruder_0.def.json +++ b/resources/extruders/toybox_alpha_one_two_extruder_0.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "toybox_alpha_one", + "machine": "toybox_alpha_one_two", "position": "0" }, "overrides": From 6f790a6ab65df5bc9ed8eeff80b37c88f2c005ac Mon Sep 17 00:00:00 2001 From: Luke Brewer <79376204+lukbrew25@users.noreply.github.com> Date: Wed, 23 Apr 2025 19:46:27 -0500 Subject: [PATCH 100/299] Add extruder_nr to extruder def.json --- resources/extruders/toybox_alpha_one_two_extruder_0.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/extruders/toybox_alpha_one_two_extruder_0.def.json b/resources/extruders/toybox_alpha_one_two_extruder_0.def.json index 1bc498f9fb..cb39ebf85b 100644 --- a/resources/extruders/toybox_alpha_one_two_extruder_0.def.json +++ b/resources/extruders/toybox_alpha_one_two_extruder_0.def.json @@ -9,6 +9,7 @@ }, "overrides": { + "extruder_nr": { "default_value": 0 }, "machine_nozzle_size": { "default_value": 0.4 }, "material_diameter": { "default_value": 1.75 }, "machine_nozzle_offset_x": { "default_value": -3.0 } From 4ff70ac46f5cfbbffc98d8e207daa86524bb0563 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 24 Apr 2025 09:23:27 +0200 Subject: [PATCH 101/299] Fix exporting Bambu 3mf format to removable drive CURA-12099 --- .../RemovableDriveOutputDevice/RemovableDriveOutputDevice.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py b/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py index a9a0666d9c..2ddf8aa334 100644 --- a/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py +++ b/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py @@ -101,7 +101,8 @@ class RemovableDriveOutputDevice(OutputDevice): self._stream = open(file_name, "wt", buffering = 1, encoding = "utf-8") else: #Binary mode. self._stream = open(file_name, "wb", buffering = 1) - job = WriteFileJob(writer, self._stream, nodes, preferred_format["mode"]) + writer_args = {"mime_type": preferred_format["mime_type"]} + job = WriteFileJob(writer, self._stream, nodes, preferred_format["mode"], writer_args) job.setFileName(file_name) job.progress.connect(self._onProgress) job.finished.connect(self._onFinished) From 17ab7a4890f976d244af205f9ee1e5da07fe6be1 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 24 Apr 2025 09:55:23 +0200 Subject: [PATCH 102/299] Bump pySavitar version CURA-12099 --- conandata.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conandata.yml b/conandata.yml index 20392c6e44..3181d601e5 100644 --- a/conandata.yml +++ b/conandata.yml @@ -6,7 +6,7 @@ requirements: - "cura_binary_data/5.11.0-alpha.0@ultimaker/testing" - "fdm_materials/5.11.0-alpha.0@ultimaker/testing" - "dulcificum/5.10.0" - - "pysavitar/5.10.0" + - "pysavitar/5.11.0-alpha.0" - "pynest2d/5.10.0" requirements_internal: - "fdm_materials/5.11.0-alpha.0@ultimaker/testing" From 254087cb45d9eb8ec6c380c45b06c272ece23981 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 24 Apr 2025 12:57:58 +0200 Subject: [PATCH 103/299] Split-out bambu-specific elements to their own 3MF 'variant'. part of CURA-12099 --- plugins/3MFWriter/BambuLabVariant.py | 168 +++++++++++++++++++++++++++ plugins/3MFWriter/DefaultVariant.py | 33 ++++++ plugins/3MFWriter/ThreeMFVariant.py | 74 ++++++++++++ plugins/3MFWriter/ThreeMFWriter.py | 167 ++++++-------------------- 4 files changed, 308 insertions(+), 134 deletions(-) create mode 100644 plugins/3MFWriter/BambuLabVariant.py create mode 100644 plugins/3MFWriter/DefaultVariant.py create mode 100644 plugins/3MFWriter/ThreeMFVariant.py diff --git a/plugins/3MFWriter/BambuLabVariant.py b/plugins/3MFWriter/BambuLabVariant.py new file mode 100644 index 0000000000..e30cc110b7 --- /dev/null +++ b/plugins/3MFWriter/BambuLabVariant.py @@ -0,0 +1,168 @@ +# Copyright (c) 2025 UltiMaker +# Cura is released under the terms of the LGPLv3 or higher. + +import hashlib +import json +from io import StringIO +import xml.etree.ElementTree as ET +import zipfile + +from PyQt6.QtCore import Qt, QBuffer +from PyQt6.QtGui import QImage + +from UM.Application import Application +from UM.Logger import Logger +from UM.Mesh.MeshWriter import MeshWriter +from UM.PluginRegistry import PluginRegistry +from typing import cast + +from cura.CuraApplication import CuraApplication + +from .ThreeMFVariant import ThreeMFVariant +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") + +# Path constants +METADATA_PATH = "Metadata" +THUMBNAIL_PATH_MULTIPLATE = f"{METADATA_PATH}/plate_1.png" +THUMBNAIL_PATH_MULTIPLATE_SMALL = f"{METADATA_PATH}/plate_1_small.png" +GCODE_PATH = f"{METADATA_PATH}/plate_1.gcode" +GCODE_MD5_PATH = f"{GCODE_PATH}.md5" +MODEL_SETTINGS_PATH = f"{METADATA_PATH}/model_settings.config" +PLATE_DESC_PATH = f"{METADATA_PATH}/plate_1.json" +SLICE_INFO_PATH = f"{METADATA_PATH}/slice_info.config" + +class BambuLabVariant(ThreeMFVariant): + """BambuLab specific implementation of the 3MF format.""" + + @property + def mime_type(self) -> str: + return "application/vnd.bambulab-package.3dmanufacturing-3dmodel+xml" + + def process_thumbnail(self, snapshot: QImage, thumbnail_buffer: QBuffer, + archive: zipfile.ZipFile, relations_element: ET.Element) -> None: + """Process the thumbnail for BambuLab variant.""" + # Write thumbnail + archive.writestr(zipfile.ZipInfo(THUMBNAIL_PATH_MULTIPLATE), thumbnail_buffer.data()) + + # Add relations elements for thumbnails + ET.SubElement(relations_element, "Relationship", + Target="/" + THUMBNAIL_PATH_MULTIPLATE, Id="rel-2", + Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail") + + ET.SubElement(relations_element, "Relationship", + Target="/" + THUMBNAIL_PATH_MULTIPLATE, Id="rel-4", + Type="http://schemas.bambulab.com/package/2021/cover-thumbnail-middle") + + # Create and save small thumbnail + small_snapshot = snapshot.scaled(128, 128, transformMode=Qt.TransformationMode.SmoothTransformation) + small_thumbnail_buffer = QBuffer() + small_thumbnail_buffer.open(QBuffer.OpenModeFlag.ReadWrite) + small_snapshot.save(small_thumbnail_buffer, "PNG") + + # Write small thumbnail + archive.writestr(zipfile.ZipInfo(THUMBNAIL_PATH_MULTIPLATE_SMALL), small_thumbnail_buffer.data()) + + # Add relation for small thumbnail + ET.SubElement(relations_element, "Relationship", + Target="/" + THUMBNAIL_PATH_MULTIPLATE_SMALL, Id="rel-5", + Type="http://schemas.bambulab.com/package/2021/cover-thumbnail-small") + + def add_extra_files(self, archive: zipfile.ZipFile, metadata_relations_element: ET.Element) -> None: + """Add BambuLab specific files to the archive.""" + self._storeGCode(archive, metadata_relations_element) + self._storeModelSettings(archive) + self._storePlateDesc(archive) + self._storeSliceInfo(archive) + + def _storeGCode(self, archive: zipfile.ZipFile, metadata_relations_element: ET.Element): + """Store GCode data in the archive.""" + gcode_textio = StringIO() + gcode_writer = cast(MeshWriter, PluginRegistry.getInstance().getPluginObject("GCodeWriter")) + success = gcode_writer.write(gcode_textio, None) + + if not success: + error_msg = catalog.i18nc("@info:error", "Can't write GCode to 3MF file") + self._writer.setInformation(error_msg) + Logger.error(error_msg) + raise Exception(error_msg) + + gcode_data = gcode_textio.getvalue().encode("UTF-8") + archive.writestr(zipfile.ZipInfo(GCODE_PATH), gcode_data) + + gcode_relation_element = ET.SubElement(metadata_relations_element, "Relationship", + Target=f"/{GCODE_PATH}", Id="rel-1", + Type="http://schemas.bambulab.com/package/2021/gcode") + + # Calculate and store the MD5 sum of the gcode data + md5_hash = hashlib.md5(gcode_data).hexdigest() + archive.writestr(zipfile.ZipInfo(GCODE_MD5_PATH), md5_hash.encode("UTF-8")) + + def _storeModelSettings(self, archive: zipfile.ZipFile): + """Store model settings in the archive.""" + config = ET.Element("config") + plate = ET.SubElement(config, "plate") + ET.SubElement(plate, "metadata", key="plater_id", value="1") + ET.SubElement(plate, "metadata", key="plater_name", value="") + ET.SubElement(plate, "metadata", key="locked", value="false") + ET.SubElement(plate, "metadata", key="filament_map_mode", value="Auto For Flush") + extruders_count = len(CuraApplication.getInstance().getExtruderManager().extruderIds) + ET.SubElement(plate, "metadata", key="filament_maps", value=" ".join("1" for _ in range(extruders_count))) + ET.SubElement(plate, "metadata", key="gcode_file", value=GCODE_PATH) + ET.SubElement(plate, "metadata", key="thumbnail_file", value=THUMBNAIL_PATH_MULTIPLATE) + ET.SubElement(plate, "metadata", key="pattern_bbox_file", value=PLATE_DESC_PATH) + + self._writer._storeElementTree(archive, MODEL_SETTINGS_PATH, config) + + def _storePlateDesc(self, archive: zipfile.ZipFile): + """Store plate description in the archive.""" + plate_desc = {} + + filament_ids = [] + filament_colors = [] + + for extruder in CuraApplication.getInstance().getExtruderManager().getUsedExtruderStacks(): + filament_ids.append(extruder.getValue("extruder_nr")) + filament_colors.append(self._writer._getMaterialColor(extruder)) + + plate_desc["filament_ids"] = filament_ids + plate_desc["filament_colors"] = filament_colors + plate_desc["first_extruder"] = CuraApplication.getInstance().getExtruderManager().getInitialExtruderNr() + plate_desc["is_seq_print"] = Application.getInstance().getGlobalContainerStack().getValue("print_sequence") == "one_at_a_time" + plate_desc["nozzle_diameter"] = CuraApplication.getInstance().getExtruderManager().getActiveExtruderStack().getValue("machine_nozzle_size") + plate_desc["version"] = 2 + + file = zipfile.ZipInfo(PLATE_DESC_PATH) + file.compress_type = zipfile.ZIP_DEFLATED + archive.writestr(file, json.dumps(plate_desc).encode("UTF-8")) + + def _storeSliceInfo(self, archive: zipfile.ZipFile): + """Store slice information in the archive.""" + config = ET.Element("config") + + header = ET.SubElement(config, "header") + ET.SubElement(header, "header_item", key="X-BBL-Client-Type", value="slicer") + ET.SubElement(header, "header_item", key="X-BBL-Client-Version", value="02.00.01.50") + + plate = ET.SubElement(config, "plate") + ET.SubElement(plate, "metadata", key="index", value="1") + ET.SubElement(plate, + "metadata", + key="nozzle_diameters", + value=str(CuraApplication.getInstance().getExtruderManager().getActiveExtruderStack().getValue("machine_nozzle_size"))) + + print_information = CuraApplication.getInstance().getPrintInformation() + for index, extruder in enumerate(Application.getInstance().getGlobalContainerStack().extruderList): + used_m = print_information.materialLengths[index] + used_g = print_information.materialWeights[index] + if used_m > 0.0 and used_g > 0.0: + ET.SubElement(plate, + "filament", + id=str(extruder.getValue("extruder_nr") + 1), + tray_info_idx="GFA00", + type=extruder.material.getMetaDataEntry("material", ""), + color=self._writer._getMaterialColor(extruder), + used_m=str(used_m), + used_g=str(used_g)) + + self._writer._storeElementTree(archive, SLICE_INFO_PATH, config) \ No newline at end of file diff --git a/plugins/3MFWriter/DefaultVariant.py b/plugins/3MFWriter/DefaultVariant.py new file mode 100644 index 0000000000..52dd381ed1 --- /dev/null +++ b/plugins/3MFWriter/DefaultVariant.py @@ -0,0 +1,33 @@ +# Copyright (c) 2025 UltiMaker +# Cura is released under the terms of the LGPLv3 or higher. + +import xml.etree.ElementTree as ET +import zipfile + +from PyQt6.QtCore import QBuffer +from PyQt6.QtGui import QImage + +from .ThreeMFVariant import ThreeMFVariant + +# Standard 3MF paths +METADATA_PATH = "Metadata" +THUMBNAIL_PATH = f"{METADATA_PATH}/thumbnail.png" + +class DefaultVariant(ThreeMFVariant): + """Default implementation of the 3MF format.""" + + @property + def mime_type(self) -> str: + return "application/vnd.ms-package.3dmanufacturing-3dmodel+xml" + + def process_thumbnail(self, snapshot: QImage, thumbnail_buffer: QBuffer, + archive: zipfile.ZipFile, relations_element: ET.Element) -> None: + """Process the thumbnail for default 3MF variant.""" + thumbnail_file = zipfile.ZipInfo(THUMBNAIL_PATH) + # Don't try to compress snapshot file, because the PNG is pretty much as compact as it will get + archive.writestr(thumbnail_file, thumbnail_buffer.data()) + + # Add thumbnail relation to _rels/.rels file + ET.SubElement(relations_element, "Relationship", + Target="/" + THUMBNAIL_PATH, Id="rel1", + Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail") \ No newline at end of file diff --git a/plugins/3MFWriter/ThreeMFVariant.py b/plugins/3MFWriter/ThreeMFVariant.py new file mode 100644 index 0000000000..9b7f0eadf4 --- /dev/null +++ b/plugins/3MFWriter/ThreeMFVariant.py @@ -0,0 +1,74 @@ +# Copyright (c) 2025 UltiMaker +# Cura is released under the terms of the LGPLv3 or higher. + +from abc import ABC, abstractmethod +from typing import TYPE_CHECKING +import xml.etree.ElementTree as ET +import zipfile + +from PyQt6.QtGui import QImage +from PyQt6.QtCore import QBuffer + +if TYPE_CHECKING: + from .ThreeMFWriter import ThreeMFWriter + +class ThreeMFVariant(ABC): + """Base class for 3MF format variants. + + Different vendors may have their own extensions to the 3MF format, + such as BambuLab's 3MF variant. This class provides an interface + for implementing these variants. + """ + + def __init__(self, writer: 'ThreeMFWriter'): + """ + :param writer: The ThreeMFWriter instance that will use this variant + """ + self._writer = writer + + @property + @abstractmethod + def mime_type(self) -> str: + """The MIME type for this 3MF variant.""" + pass + + def handles_mime_type(self, mime_type: str) -> bool: + """Check if this variant handles the given MIME type. + + :param mime_type: The MIME type to check + :return: True if this variant handles the MIME type, False otherwise + """ + return mime_type == self.mime_type + + def prepare_content_types(self, content_types: ET.Element) -> None: + """Prepare the content types XML element for this variant. + + :param content_types: The content types XML element + """ + pass + + def prepare_relations(self, relations_element: ET.Element) -> None: + """Prepare the relations XML element for this variant. + + :param relations_element: The relations XML element + """ + pass + + def process_thumbnail(self, snapshot: QImage, thumbnail_buffer: QBuffer, + archive: zipfile.ZipFile, relations_element: ET.Element) -> None: + """Process the thumbnail for this variant. + + :param snapshot: The snapshot image + :param thumbnail_buffer: Buffer containing the thumbnail data + :param archive: The zip archive to write to + :param relations_element: The relations XML element + """ + pass + + def add_extra_files(self, archive: zipfile.ZipFile, metadata_relations_element: ET.Element) -> None: + """Add any extra files required by this variant to the archive. + + :param archive: The zip archive to write to + :param metadata_relations_element: The metadata relations XML element + """ + pass \ No newline at end of file diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 61aec6b664..9de117d947 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -1,14 +1,11 @@ -# Copyright (c) 2015-2022 Ultimaker B.V. +# Copyright (c) 2015-2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. -import hashlib - -from io import StringIO import json import re import threading -from typing import Optional, cast, List, Dict, Pattern, Set +from typing import Optional, cast, List, Dict, Set from UM.PluginRegistry import PluginRegistry from UM.Mesh.MeshWriter import MeshWriter @@ -52,21 +49,15 @@ import UM.Application from .SettingsExportModel import SettingsExportModel from .SettingsExportGroup import SettingsExportGroup +from .ThreeMFVariant import ThreeMFVariant +from .DefaultVariant import DefaultVariant +from .BambuLabVariant import BambuLabVariant from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") MODEL_PATH = "3D/3dmodel.model" PACKAGE_METADATA_PATH = "Cura/packages.json" -METADATA_PATH = "Metadata" -THUMBNAIL_PATH = f"{METADATA_PATH}/thumbnail.png" -THUMBNAIL_PATH_MULTIPLATE = f"{METADATA_PATH}/plate_1.png" -THUMBNAIL_PATH_MULTIPLATE_SMALL = f"{METADATA_PATH}/plate_1_small.png" -GCODE_PATH = f"{METADATA_PATH}/plate_1.gcode" -GCODE_MD5_PATH = f"{GCODE_PATH}.md5" -MODEL_SETTINGS_PATH = f"{METADATA_PATH}/model_settings.config" -PLATE_DESC_PATH = f"{METADATA_PATH}/plate_1.json" -SLICE_INFO_PATH = f"{METADATA_PATH}/slice_info.config" class ThreeMFWriter(MeshWriter): def __init__(self): @@ -83,6 +74,12 @@ class ThreeMFWriter(MeshWriter): self._store_archive = False self._lock = threading.Lock() + # Register available variants + self._variants = { + DefaultVariant(self).mime_type: DefaultVariant, + BambuLabVariant(self).mime_type: BambuLabVariant + } + @staticmethod def _convertMatrixToString(matrix): result = "" @@ -216,10 +213,23 @@ class ThreeMFWriter(MeshWriter): painter.end() + def _getVariant(self, mime_type: str) -> ThreeMFVariant: + """Get the appropriate variant for the given MIME type. + + :param mime_type: The MIME type to get the variant for + :return: An instance of the variant for the given MIME type + """ + variant_class = self._variants.get(mime_type, DefaultVariant) + return variant_class(self) + def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode, export_settings_model = None, **kwargs) -> bool: self._archive = None # Reset archive archive = zipfile.ZipFile(stream, "w", compression = zipfile.ZIP_DEFLATED) - add_extra_data = kwargs.get("mime_type", "") == "application/vnd.bambulab-package.3dmanufacturing-3dmodel+xml" + + # Determine which variant to use based on mime type in kwargs + mime_type = kwargs.get("mime_type", DefaultVariant(self).mime_type) + variant = self._getVariant(mime_type) + try: model_file = zipfile.ZipInfo(MODEL_PATH) # Because zipfile is stupid and ignores archive-level compression settings when writing with ZipInfo. @@ -239,11 +249,12 @@ class ThreeMFWriter(MeshWriter): # Create Metadata/_rels/model_settings.config.rels metadata_relations_element = self._makeRelationsTree() - if add_extra_data: - self._storeGCode(archive, metadata_relations_element) - self._storeModelSettings(archive) - self._storePlateDesc(archive) - self._storeSliceInfo(archive) + # Let the variant add its specific files + variant.add_extra_files(archive, metadata_relations_element) + + # Let the variant prepare content types and relations + variant.prepare_content_types(content_types) + variant.prepare_relations(relations_element) # Attempt to add a thumbnail snapshot = self._createSnapshot() @@ -259,32 +270,8 @@ class ThreeMFWriter(MeshWriter): # Add PNG to content types file thumbnail_type = ET.SubElement(content_types, "Default", Extension="png", ContentType="image/png") - if add_extra_data: - archive.writestr(zipfile.ZipInfo(THUMBNAIL_PATH_MULTIPLATE), thumbnail_buffer.data()) - extra_thumbnail_relation_element = ET.SubElement(relations_element, "Relationship", - Target="/" + THUMBNAIL_PATH_MULTIPLATE, Id="rel-2", - Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail") - extra_thumbnail_relation_element_duplicate = ET.SubElement(relations_element, "Relationship", - Target="/" + THUMBNAIL_PATH_MULTIPLATE, Id="rel-4", - Type="http://schemas.bambulab.com/package/2021/cover-thumbnail-middle") - - small_snapshot = snapshot.scaled(128, 128, transformMode = Qt.TransformationMode.SmoothTransformation) - small_thumbnail_buffer = QBuffer() - small_thumbnail_buffer.open(QBuffer.OpenModeFlag.ReadWrite) - small_snapshot.save(small_thumbnail_buffer, "PNG") - archive.writestr(zipfile.ZipInfo(THUMBNAIL_PATH_MULTIPLATE_SMALL), small_thumbnail_buffer.data()) - thumbnail_small_relation_element = ET.SubElement(relations_element, "Relationship", - Target="/" + THUMBNAIL_PATH_MULTIPLATE_SMALL, Id="rel-5", - Type="http://schemas.bambulab.com/package/2021/cover-thumbnail-small") - else: - thumbnail_file = zipfile.ZipInfo(THUMBNAIL_PATH) - # Don't try to compress snapshot file, because the PNG is pretty much as compact as it will get - archive.writestr(thumbnail_file, thumbnail_buffer.data()) - - # Add thumbnail relation to _rels/.rels file - thumbnail_relation_element = ET.SubElement(relations_element, "Relationship", - Target="/" + THUMBNAIL_PATH, Id="rel1", - Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail") + # Let the variant process the thumbnail + variant.process_thumbnail(snapshot, thumbnail_buffer, archive, relations_element) # Write material metadata packages_metadata = self._getMaterialPackageMetadata() + self._getPluginPackageMetadata() @@ -369,94 +356,6 @@ class ThreeMFWriter(MeshWriter): file.compress_type = zipfile.ZIP_DEFLATED archive.writestr(file, b' \n' + ET.tostring(root_element)) - def _storeGCode(self, archive: zipfile.ZipFile, metadata_relations_element: ET.Element): - gcode_textio = StringIO() # We have to convert the g-code into bytes. - gcode_writer = cast(MeshWriter, PluginRegistry.getInstance().getPluginObject("GCodeWriter")) - success = gcode_writer.write(gcode_textio, None) - - if not success: - error_msg = catalog.i18nc("@info:error", "Can't write GCode to 3MF file") - self.setInformation(error_msg) - Logger.error(error_msg) - raise Exception(error_msg) - - gcode_data = gcode_textio.getvalue().encode("UTF-8") - archive.writestr(zipfile.ZipInfo(GCODE_PATH), gcode_data) - - gcode_relation_element = ET.SubElement(metadata_relations_element, "Relationship", - Target=f"/{GCODE_PATH}", Id="rel-1", - Type="http://schemas.bambulab.com/package/2021/gcode") - - # Calculate and store the MD5 sum of the gcode data - md5_hash = hashlib.md5(gcode_data).hexdigest() - archive.writestr(zipfile.ZipInfo(GCODE_MD5_PATH), md5_hash.encode("UTF-8")) - - def _storeModelSettings(self, archive: zipfile.ZipFile): - config = ET.Element("config") - plate = ET.SubElement(config, "plate") - plater_id = ET.SubElement(plate, "metadata", key="plater_id", value="1") - plater_id = ET.SubElement(plate, "metadata", key="plater_name", value="") - plater_id = ET.SubElement(plate, "metadata", key="locked", value="false") - plater_id = ET.SubElement(plate, "metadata", key="filament_map_mode", value="Auto For Flush") - extruders_count = len(CuraApplication.getInstance().getExtruderManager().extruderIds) - plater_id = ET.SubElement(plate, "metadata", key="filament_maps", value=" ".join("1" for _ in range(extruders_count))) - plater_id = ET.SubElement(plate, "metadata", key="gcode_file", value=GCODE_PATH) - plater_id = ET.SubElement(plate, "metadata", key="thumbnail_file", value=THUMBNAIL_PATH_MULTIPLATE) - plater_id = ET.SubElement(plate, "metadata", key="pattern_bbox_file", value=PLATE_DESC_PATH) - - self._storeElementTree(archive, MODEL_SETTINGS_PATH, config) - - def _storePlateDesc(self, archive: zipfile.ZipFile): - plate_desc = {} - - filament_ids = [] - filament_colors = [] - - for extruder in CuraApplication.getInstance().getExtruderManager().getUsedExtruderStacks(): - filament_ids.append(extruder.getValue("extruder_nr")) - filament_colors.append(self._getMaterialColor(extruder)) - - plate_desc["filament_ids"] = filament_ids - plate_desc["filament_colors"] = filament_colors - plate_desc["first_extruder"] = CuraApplication.getInstance().getExtruderManager().getInitialExtruderNr() - plate_desc["is_seq_print"] = Application.getInstance().getGlobalContainerStack().getValue("print_sequence") == "one_at_a_time" - plate_desc["nozzle_diameter"] = CuraApplication.getInstance().getExtruderManager().getActiveExtruderStack().getValue("machine_nozzle_size") - plate_desc["version"] = 2 - - file = zipfile.ZipInfo(PLATE_DESC_PATH) - file.compress_type = zipfile.ZIP_DEFLATED - archive.writestr(file, json.dumps(plate_desc).encode("UTF-8")) - - def _storeSliceInfo(self, archive: zipfile.ZipFile): - config = ET.Element("config") - - header = ET.SubElement(config, "header") - header_type = ET.SubElement(header, "header_item", key="X-BBL-Client-Type", value="slicer") - header_version = ET.SubElement(header, "header_item", key="X-BBL-Client-Version", value="02.00.01.50") - - plate = ET.SubElement(config, "plate") - index = ET.SubElement(plate, "metadata", key="index", value="1") - nozzle_diameter = ET.SubElement(plate, - "metadata", - key="nozzle_diameters", - value=str(CuraApplication.getInstance().getExtruderManager().getActiveExtruderStack().getValue("machine_nozzle_size"))) - - print_information = CuraApplication.getInstance().getPrintInformation() - for index, extruder in enumerate(Application.getInstance().getGlobalContainerStack().extruderList): - used_m = print_information.materialLengths[index] - used_g = print_information.materialWeights[index] - if used_m > 0.0 and used_g > 0.0: - filament = ET.SubElement(plate, - "filament", - id=str(extruder.getValue("extruder_nr") + 1), - tray_info_idx="GFA00", - type=extruder.material.getMetaDataEntry("material", ""), - color=self._getMaterialColor(extruder), - used_m=str(used_m), - used_g=str(used_g)) - - self._storeElementTree(archive, SLICE_INFO_PATH, config) - def _makeRelationsTree(self): return ET.Element("Relationships", xmlns=self._namespaces["relationships"]) From 371f280ab8f3d74e6cbecb59fd4d8a8d9b7e8ac3 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 24 Apr 2025 15:13:24 +0200 Subject: [PATCH 104/299] Add newlines to the end of new files. done as part of CURA-12099 --- plugins/3MFWriter/BambuLabVariant.py | 2 +- plugins/3MFWriter/DefaultVariant.py | 2 +- plugins/3MFWriter/ThreeMFVariant.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/3MFWriter/BambuLabVariant.py b/plugins/3MFWriter/BambuLabVariant.py index e30cc110b7..56337bbc31 100644 --- a/plugins/3MFWriter/BambuLabVariant.py +++ b/plugins/3MFWriter/BambuLabVariant.py @@ -165,4 +165,4 @@ class BambuLabVariant(ThreeMFVariant): used_m=str(used_m), used_g=str(used_g)) - self._writer._storeElementTree(archive, SLICE_INFO_PATH, config) \ No newline at end of file + self._writer._storeElementTree(archive, SLICE_INFO_PATH, config) diff --git a/plugins/3MFWriter/DefaultVariant.py b/plugins/3MFWriter/DefaultVariant.py index 52dd381ed1..7f5522c3af 100644 --- a/plugins/3MFWriter/DefaultVariant.py +++ b/plugins/3MFWriter/DefaultVariant.py @@ -30,4 +30,4 @@ class DefaultVariant(ThreeMFVariant): # Add thumbnail relation to _rels/.rels file ET.SubElement(relations_element, "Relationship", Target="/" + THUMBNAIL_PATH, Id="rel1", - Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail") \ No newline at end of file + Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail") diff --git a/plugins/3MFWriter/ThreeMFVariant.py b/plugins/3MFWriter/ThreeMFVariant.py index 9b7f0eadf4..d8f4e31770 100644 --- a/plugins/3MFWriter/ThreeMFVariant.py +++ b/plugins/3MFWriter/ThreeMFVariant.py @@ -71,4 +71,4 @@ class ThreeMFVariant(ABC): :param archive: The zip archive to write to :param metadata_relations_element: The metadata relations XML element """ - pass \ No newline at end of file + pass From 312407e9b8cb07311b6ed3052cafa333c8fb07aa Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 28 Apr 2025 10:16:57 +0200 Subject: [PATCH 105/299] Adjustments for A1 and start working on X1 CURA-12346 --- resources/definitions/bambulab_a1.def.json | 2 +- resources/definitions/bambulab_x1.def.json | 2 +- resources/extruders/bambulab_a1_extruder_0.def.json | 4 ++-- resources/extruders/bambulab_a1_extruder_1.def.json | 4 ++-- resources/extruders/bambulab_a1_extruder_2.def.json | 4 ++-- resources/extruders/bambulab_a1_extruder_3.def.json | 4 ++-- resources/extruders/bambulab_a1mini_extruder_0.def.json | 2 +- resources/extruders/bambulab_a1mini_extruder_1.def.json | 2 +- resources/extruders/bambulab_a1mini_extruder_2.def.json | 2 +- resources/extruders/bambulab_a1mini_extruder_3.def.json | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/resources/definitions/bambulab_a1.def.json b/resources/definitions/bambulab_a1.def.json index 7079267692..a0edc8f631 100644 --- a/resources/definitions/bambulab_a1.def.json +++ b/resources/definitions/bambulab_a1.def.json @@ -34,7 +34,7 @@ "machine_extruder_count": { "value": 4 }, "machine_height": { "value": 251 }, "machine_name": { "default_value": "BambuLab Bambu A1" }, - "machine_start_gcode": { "default_value": ";===== machine: A1 =========================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S170\nM140 S{material_bed_temperature_layer_0}\nG392 S0 ;turn off clog detect\nM9833.2\n;=====start printer sound ===================\nM17\nM400 S1\n; M1006 S1\n; M1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-13.5 F3000\n M400\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\n M104 S{material_print_temperature, initial_extruder_nr}\n G92 E0\n G1 E50 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\n M104 S{material_print_temperature_layer_0-40, material_print_temperature_layer_0}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{material_print_temperature_layer_0-40, initial_extruder_nr}\n G392 S0 ;turn off clog detect\nM621 S{initial_extruder_nr}A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 3\n{endif}\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n{endif}\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S{material_bed_temperature_layer_0};set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n\n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.3 F18000 ;Move to start position\n M400\n G0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 Y0 Z0 F20000\n M400\n\n G1 X-13.5 Y0 Z10 F10000\n M400\n\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of 'draw extrinsic para cali paint'\n\n;===== extrude cali test ===============================\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.3 F18000 ;Move to start position\nG0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\nG0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate_type=='textured_pei_plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n" }, + "machine_start_gcode": { "default_value": ";===== machine: A1 =========================\n;===== date: 20240620 =====================\nG392 S0\nM9833.2\n;M400\n;M73 P1.717\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S140\nM140 S{material_bed_temperature_layer_0}\n\n;=====start printer sound ===================\nM17\nM400 S1\n; M1006 S1\n; M1006 A0 B10 L100 C37 D10 M60 E37 F10 N60\n; M1006 A0 B10 L100 C41 D10 M60 E41 F10 N60\n; M1006 A0 B10 L100 C44 D10 M60 E44 F10 N60\n; M1006 A0 B10 L100 C0 D10 M60 E0 F10 N60\n; M1006 A43 B10 L100 C46 D10 M70 E39 F10 N80\n; M1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\n; M1006 A0 B10 L100 C43 D10 M60 E39 F10 N80\n; M1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\n; M1006 A0 B10 L100 C41 D10 M80 E41 F10 N80\n; M1006 A0 B10 L100 C44 D10 M80 E44 F10 N80\n; M1006 A0 B10 L100 C49 D10 M80 E49 F10 N80\n; M1006 A0 B10 L100 C0 D10 M80 E0 F10 N80\n; M1006 A44 B10 L100 C48 D10 M60 E39 F10 N80\n; M1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\n; M1006 A0 B10 L100 C44 D10 M80 E39 F10 N80\n; M1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\n; M1006 A43 B10 L100 C46 D10 M60 E39 F10 N80\n; M1006 W\nM18\n;=====start printer sound ===================\n\n;=====avoid end stop =================\nG91\nG380 S2 Z40 F1200\nG380 S3 Z-15 F1200\nG90\n\n;===== reset machine status =================\n;M290 X39 Y39 Z8\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.65 Y1.2 Z0.6 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;M211 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\n\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\nM1002 gcode_claim_action : 13\n\nG28 X\nG91\nG1 Z5 F1200\nG90\nG0 X128 F30000\nG0 Y254 F3000\nG91\nG1 Z-5 F1200\n\nM109 S25 H140\n\nM17 E0.3\nM83\nG1 E10 F1200\nG1 E-0.5 F30\nM17 D\n\nG28 Z P0 T140; home z with low precision,permit 300deg temperature\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\n\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n G90\n G1 Z5 F1200\nM623\n\n;M400\n;M73 P1.717\n\n;===== prepare print temperature and material ==========\nM1002 gcode_claim_action : 24\n\nM400\n;G392 S1\nM211 X0 Y0 Z0 ;turn off soft endstop\nM975 S1 ; turn on\n\nG90\nG1 X-28.5 F30000\nG1 X-48.2 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-48.2 F3000\n M400\n\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\nM621 S{initial_extruder_nr}A\n\nM109 S{material_print_temperature, initial_extruder_nr} H300\nG92 E0\nG1 E50 F200 ; lower extrusion speed to avoid clog\nM400\nM106 P1 S178\nG92 E0\nG1 E5 F200\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E-0.5 F300\n\nG1 X-28.5 F30000\nG1 X-48.2 F3000\nG1 X-28.5 F30000 ;wipe and shake\nG1 X-48.2 F3000\nG1 X-28.5 F30000 ;wipe and shake\nG1 X-48.2 F3000\n\n;G392 S0\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n;M400\n;M73 P1.717\n\n;===== auto extrude cali start =========================\nM975 S1\n;G392 S1\n\nG90\nM83\nT1000\nG1 X-48.2 Y0 Z10 F10000\nM400\nM1002 set_filament_type:UNKNOWN\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\n\nM622 J1\n M1002 gcode_claim_action : 8\n\n M109 S{material_print_temperature, initial_extruder_nr}\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n\n M106 P1 S255\n M400 S5\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n G1 X-48.2 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S255\n M400 S5\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-48.2 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n G1 X-48.2 F3000\n M400\n M106 P1 S0\nM623 ; end of 'draw extrinsic para cali paint'\n\n;G392 S0\n;===== auto extrude cali end ========================\n\n;M400\n;M73 P1.717\n\nM104 S170 ; prepare to wipe nozzle\nM106 S255 ; turn on fan\n\n;===== mech mode fast check start =====================\nM1002 gcode_claim_action : 3\n\nG1 X128 Y128 F20000\nG1 Z5 F1200\nM400 P200\nM970.3 Q1 A5 K0 O3\nM974 Q1 S2 P0\n\nM970.2 Q1 K1 W58 Z0.1\nM974 S2\n\nG1 X128 Y128 F20000\nG1 Z5 F1200\nM400 P200\nM970.3 Q0 A10 K0 O1\nM974 Q0 S2 P0\n\nM970.2 Q0 K1 W78 Z0.1\nM974 S2\n\nM975 S1\nG1 F30000\nG1 X0 Y5\nG28 X ; re-home XY\n\nG1 Z4 F1200\n\n;===== mech mode fast check end =======================\n\n;M400\n;M73 P1.717\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\n\nM975 S1\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\n;===== remove waste by touching start =====\n\nM104 S170 ; set temp down to heatbed acceptable\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nG0 X108 Y-0.5 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X110 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X112 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X114 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X116 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X118 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X120 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X122 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X124 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X126 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X128 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X130 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X132 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X134 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X136 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X138 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X140 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X142 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X144 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X146 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X148 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;===== remove waste by touching end =====\n\nG1 Z10 F1200\nG0 X118 Y261 F30000\nG1 Z5 F1200\nM109 S{material_print_temperature_layer_0-50, initial_extruder_nr}\n\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S140 ; prepare to abl\nG0 Z5 F20000\n\nG0 X128 Y261 F20000 ; move to exposed steel surface\nG0 Z-1.01 F1200 ; stop the nozzle\n\nG91\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z10 F1200\n\n;===== brush material wipe nozzle =====\n\nG90\nG1 Y250 F30000\nG1 X55\nG1 Z1.300 F1200\nG1 Y262.5 F6000\nG91\nG1 X-35 F30000\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Z5.000 F1200\n\nG90\nG1 X30 Y250.000 F30000\nG1 Z1.300 F1200\nG1 Y262.5 F6000\nG91\nG1 X35 F30000\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Z10.000 F1200\n\n;===== brush material wipe nozzle end =====\n\nG90\n;G0 X128 Y261 F20000 ; move to exposed steel surface\nG1 Y250 F30000\nG1 X138\nG1 Y261\nG0 Z-1.01 F1200 ; stop the nozzle\n\nG91\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nM109 S140\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM211 R; pop softend status\n\n;===== wipe nozzle end ================================\n\n;M400\n;M73 P1.717\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\n\nG90\nG1 Z5 F1200\nG1 X0 Y0 F30000\nG29.2 S1 ; turn on ABL\n\nM190 S{material_bed_temperature_layer_0}; ensure bed temp\nM109 S140\nM106 S0 ; turn off fan , too noisy\n\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n\n;===== home after wipe mouth end =======================\n\n;M400\n;M73 P1.717\n\nG1 X108.000 Y-0.500 F30000\nG1 Z0.300 F1200\nM400\nG2814 Z0.32\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; prepare to print\n\n;===== extrude cali test ===============================\n\nM400\n M900 S\n M900 C\n G90\n M83\n\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G0 X128 E8 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X133 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X138 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X143 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X148 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X153 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G91\n G1 X1 Z-0.300\n G1 X4\n G1 Z1 F1200\n G90\n M400\n\nM900 R\n\nM1002 judge_flag extrude_cali_flag\nM622 J1\n G90\n G1 X108.000 Y1.000 F30000\n G91\n G1 Z-0.700 F1200\n G90\n M83\n G0 X128 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X133 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X138 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X143 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X148 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X153 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G91\n G1 X1 Z-0.300\n G1 X4\n G1 Z1 F1200\n G90\n M400\nM623\n\nG1 Z0.2\n\n;M400\n;M73 P1.717\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate_type=='textured_pei_plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\n;G392 S1 ; turn on clog detection\nM1007 S1 ; turn on mass estimation\nG29.4\n" }, "machine_width": { "value": 256 }, "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, "prime_tower_position_y": { "value": "(resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" } diff --git a/resources/definitions/bambulab_x1.def.json b/resources/definitions/bambulab_x1.def.json index 45a4929f74..4d0960ff92 100644 --- a/resources/definitions/bambulab_x1.def.json +++ b/resources/definitions/bambulab_x1.def.json @@ -119,7 +119,7 @@ "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, "machine_nozzle_size": { "value": 0.4 }, "machine_show_variants": { "value": true }, - "machine_start_gcode": { "default_value": "" }, + "machine_start_gcode": { "default_value": ";===== machine: X1 ====================\n;===== date: 20241023 ==================\n;===== start printer sound ================\nM17\nM400 S1\nM1006 S1\nM1006 A0 B10 L100 C37 D10 M60 E37 F10 N60\nM1006 A0 B10 L100 C41 D10 M60 E41 F10 N60\nM1006 A0 B10 L100 C44 D10 M60 E44 F10 N60\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N60\nM1006 A46 B10 L100 C43 D10 M70 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N100\nM1006 A43 B10 L100 C0 D10 M60 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N100\nM1006 A41 B10 L100 C0 D10 M100 E41 F10 N100\nM1006 A44 B10 L100 C0 D10 M100 E44 F10 N100\nM1006 A49 B10 L100 C0 D10 M100 E49 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A48 B10 L100 C44 D10 M60 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N100\nM1006 A44 B10 L100 C0 D10 M90 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N100\nM1006 A46 B10 L100 C43 D10 M60 E39 F10 N100\nM1006 W\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]=='PLA'}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {endif};Prevent PLA from jamming\n M142 P1 R35 S40\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]=='PLA'}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {endif};Prevent PLA from jamming\n M142 P1 R35 S40\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type=='Textured PEI Plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.160\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.080\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of 'draw extrinsic para cali paint'\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.080 K0.160\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.08 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.08}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n;===== purge line to wipe the nozzle ============================\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X18.0 Y2.5 Z0.8 F18000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG1 Z0.2\nG0 X239 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y12 E0.7 F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\n" }, "machine_use_extruder_offset_to_offset_coords": { "value": false }, "machine_width": { "value": 256 }, "material_diameter": { "value": 1.75 }, diff --git a/resources/extruders/bambulab_a1_extruder_0.def.json b/resources/extruders/bambulab_a1_extruder_0.def.json index fa8bf82a66..e2a89b97c4 100644 --- a/resources/extruders/bambulab_a1_extruder_0.def.json +++ b/resources/extruders/bambulab_a1_extruder_0.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 0 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1 extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1 extruder end {extruder_nr} finish =====\n" }, - "machine_extruder_start_code": { "default_value": ";===== A1 extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1 extruder start {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1 extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0 ; turn off mass estimation\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 X267 F18000\nG1 Y128 F9000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1 extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1 extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E6 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S4\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1 extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } } diff --git a/resources/extruders/bambulab_a1_extruder_1.def.json b/resources/extruders/bambulab_a1_extruder_1.def.json index 108fecb2d1..b61a74d199 100644 --- a/resources/extruders/bambulab_a1_extruder_1.def.json +++ b/resources/extruders/bambulab_a1_extruder_1.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 1 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1 extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1 extruder end {extruder_nr} finish =====\n" }, - "machine_extruder_start_code": { "default_value": ";===== A1 extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1 extruder start {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1 extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0 ; turn off mass estimation\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 X267 F18000\nG1 Y128 F9000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1 extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1 extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E6 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S4\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1 extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } } diff --git a/resources/extruders/bambulab_a1_extruder_2.def.json b/resources/extruders/bambulab_a1_extruder_2.def.json index d1ff6bf06c..d439de1d30 100644 --- a/resources/extruders/bambulab_a1_extruder_2.def.json +++ b/resources/extruders/bambulab_a1_extruder_2.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 2 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1 extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1 extruder end {extruder_nr} finish =====\n" }, - "machine_extruder_start_code": { "default_value": ";===== A1 extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1 extruder start {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1 extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0 ; turn off mass estimation\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 X267 F18000\nG1 Y128 F9000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1 extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1 extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E6 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S4\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1 extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } } diff --git a/resources/extruders/bambulab_a1_extruder_3.def.json b/resources/extruders/bambulab_a1_extruder_3.def.json index 7b82623d9a..13b7ec8699 100644 --- a/resources/extruders/bambulab_a1_extruder_3.def.json +++ b/resources/extruders/bambulab_a1_extruder_3.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 3 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1 extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1 extruder end {extruder_nr} finish =====\n" }, - "machine_extruder_start_code": { "default_value": ";===== A1 extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1 extruder start {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1 extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0 ; turn off mass estimation\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 X267 F18000\nG1 Y128 F9000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1 extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_start_code": { "default_value": ";===== A1 extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E6 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S4\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1 extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } } diff --git a/resources/extruders/bambulab_a1mini_extruder_0.def.json b/resources/extruders/bambulab_a1mini_extruder_0.def.json index a9240362f0..57627b20b1 100644 --- a/resources/extruders/bambulab_a1mini_extruder_0.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_0.def.json @@ -11,7 +11,7 @@ { "extruder_nr": { "default_value": 0 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0 ; turn off mass estimation\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 X180 F18000\nG1 Y90 F9000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } diff --git a/resources/extruders/bambulab_a1mini_extruder_1.def.json b/resources/extruders/bambulab_a1mini_extruder_1.def.json index 0c7a20f213..02f2a102ff 100644 --- a/resources/extruders/bambulab_a1mini_extruder_1.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_1.def.json @@ -11,7 +11,7 @@ { "extruder_nr": { "default_value": 1 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0 ; turn off mass estimation\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 X180 F18000\nG1 Y90 F9000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } diff --git a/resources/extruders/bambulab_a1mini_extruder_2.def.json b/resources/extruders/bambulab_a1mini_extruder_2.def.json index cc697e5ea7..9b16132547 100644 --- a/resources/extruders/bambulab_a1mini_extruder_2.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_2.def.json @@ -11,7 +11,7 @@ { "extruder_nr": { "default_value": 2 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0 ; turn off mass estimation\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 X180 F18000\nG1 Y90 F9000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } diff --git a/resources/extruders/bambulab_a1mini_extruder_3.def.json b/resources/extruders/bambulab_a1mini_extruder_3.def.json index 16f59581fb..ee63528e5f 100644 --- a/resources/extruders/bambulab_a1mini_extruder_3.def.json +++ b/resources/extruders/bambulab_a1mini_extruder_3.def.json @@ -11,7 +11,7 @@ { "extruder_nr": { "default_value": 3 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 Y90 F9000\nG1 X180 F18000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, + "machine_extruder_end_code": { "default_value": ";===== A1mini extruder end {extruder_nr} begin =====\nG392 S0\nM1007 S0 ; turn off mass estimation\nM204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 X180 F18000\nG1 Y90 F9000\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if material_print_temperature > 142, extruder_nr}\nM104 S{material_print_temperature, extruder_nr}\n{endif}\n\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A0 F{material_flush_purge_speed}\n\nM628 S1\nG92 E0\nG1 E-18 F{material_flush_purge_speed}\nM400\nM629 S1\n\n;===== A1mini extruder end {extruder_nr} finish =====\n" }, "machine_extruder_start_code": { "default_value": ";===== A1mini extruder start {extruder_nr} begin =====\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\nM620.10 A1 F{material_flush_purge_speed} L{material_flush_purge_length} H{machine_nozzle_size} T{material_print_temperature, extruder_nr}\n\nM400\nG92 E0\n\n{if not prime_tower_enable}\n\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n\nM400\nM106 P1 S60\nG1 E5 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n; G1 E-{retraction_amount} F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nG1 X-3.5 F18000\nG1 X-13.5 F3000\nM400\nM106 P1 S0\n\nM622.1 S0\n\nM621 S{extruder_nr}A\nG392 S0\n\nM1007 S1\n;===== A1mini extruder start {extruder_nr} finish =====\n" }, "material_diameter": { "default_value": 1.75 }, "switch_extruder_retraction_amount": { "default_value": 18 } From 9b4816f93739a6c8a03dbfe71a0f65b57ecf287d Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 28 Apr 2025 13:05:52 +0200 Subject: [PATCH 106/299] Custom start music CURA-12346 --- resources/definitions/bambulab_a1.def.json | 2 +- resources/definitions/bambulab_a1mini.def.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/bambulab_a1.def.json b/resources/definitions/bambulab_a1.def.json index a0edc8f631..28737d9d8d 100644 --- a/resources/definitions/bambulab_a1.def.json +++ b/resources/definitions/bambulab_a1.def.json @@ -34,7 +34,7 @@ "machine_extruder_count": { "value": 4 }, "machine_height": { "value": 251 }, "machine_name": { "default_value": "BambuLab Bambu A1" }, - "machine_start_gcode": { "default_value": ";===== machine: A1 =========================\n;===== date: 20240620 =====================\nG392 S0\nM9833.2\n;M400\n;M73 P1.717\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S140\nM140 S{material_bed_temperature_layer_0}\n\n;=====start printer sound ===================\nM17\nM400 S1\n; M1006 S1\n; M1006 A0 B10 L100 C37 D10 M60 E37 F10 N60\n; M1006 A0 B10 L100 C41 D10 M60 E41 F10 N60\n; M1006 A0 B10 L100 C44 D10 M60 E44 F10 N60\n; M1006 A0 B10 L100 C0 D10 M60 E0 F10 N60\n; M1006 A43 B10 L100 C46 D10 M70 E39 F10 N80\n; M1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\n; M1006 A0 B10 L100 C43 D10 M60 E39 F10 N80\n; M1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\n; M1006 A0 B10 L100 C41 D10 M80 E41 F10 N80\n; M1006 A0 B10 L100 C44 D10 M80 E44 F10 N80\n; M1006 A0 B10 L100 C49 D10 M80 E49 F10 N80\n; M1006 A0 B10 L100 C0 D10 M80 E0 F10 N80\n; M1006 A44 B10 L100 C48 D10 M60 E39 F10 N80\n; M1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\n; M1006 A0 B10 L100 C44 D10 M80 E39 F10 N80\n; M1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\n; M1006 A43 B10 L100 C46 D10 M60 E39 F10 N80\n; M1006 W\nM18\n;=====start printer sound ===================\n\n;=====avoid end stop =================\nG91\nG380 S2 Z40 F1200\nG380 S3 Z-15 F1200\nG90\n\n;===== reset machine status =================\n;M290 X39 Y39 Z8\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.65 Y1.2 Z0.6 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;M211 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\n\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\nM1002 gcode_claim_action : 13\n\nG28 X\nG91\nG1 Z5 F1200\nG90\nG0 X128 F30000\nG0 Y254 F3000\nG91\nG1 Z-5 F1200\n\nM109 S25 H140\n\nM17 E0.3\nM83\nG1 E10 F1200\nG1 E-0.5 F30\nM17 D\n\nG28 Z P0 T140; home z with low precision,permit 300deg temperature\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\n\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n G90\n G1 Z5 F1200\nM623\n\n;M400\n;M73 P1.717\n\n;===== prepare print temperature and material ==========\nM1002 gcode_claim_action : 24\n\nM400\n;G392 S1\nM211 X0 Y0 Z0 ;turn off soft endstop\nM975 S1 ; turn on\n\nG90\nG1 X-28.5 F30000\nG1 X-48.2 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-48.2 F3000\n M400\n\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\nM621 S{initial_extruder_nr}A\n\nM109 S{material_print_temperature, initial_extruder_nr} H300\nG92 E0\nG1 E50 F200 ; lower extrusion speed to avoid clog\nM400\nM106 P1 S178\nG92 E0\nG1 E5 F200\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E-0.5 F300\n\nG1 X-28.5 F30000\nG1 X-48.2 F3000\nG1 X-28.5 F30000 ;wipe and shake\nG1 X-48.2 F3000\nG1 X-28.5 F30000 ;wipe and shake\nG1 X-48.2 F3000\n\n;G392 S0\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n;M400\n;M73 P1.717\n\n;===== auto extrude cali start =========================\nM975 S1\n;G392 S1\n\nG90\nM83\nT1000\nG1 X-48.2 Y0 Z10 F10000\nM400\nM1002 set_filament_type:UNKNOWN\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\n\nM622 J1\n M1002 gcode_claim_action : 8\n\n M109 S{material_print_temperature, initial_extruder_nr}\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n\n M106 P1 S255\n M400 S5\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n G1 X-48.2 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S255\n M400 S5\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-48.2 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n G1 X-48.2 F3000\n M400\n M106 P1 S0\nM623 ; end of 'draw extrinsic para cali paint'\n\n;G392 S0\n;===== auto extrude cali end ========================\n\n;M400\n;M73 P1.717\n\nM104 S170 ; prepare to wipe nozzle\nM106 S255 ; turn on fan\n\n;===== mech mode fast check start =====================\nM1002 gcode_claim_action : 3\n\nG1 X128 Y128 F20000\nG1 Z5 F1200\nM400 P200\nM970.3 Q1 A5 K0 O3\nM974 Q1 S2 P0\n\nM970.2 Q1 K1 W58 Z0.1\nM974 S2\n\nG1 X128 Y128 F20000\nG1 Z5 F1200\nM400 P200\nM970.3 Q0 A10 K0 O1\nM974 Q0 S2 P0\n\nM970.2 Q0 K1 W78 Z0.1\nM974 S2\n\nM975 S1\nG1 F30000\nG1 X0 Y5\nG28 X ; re-home XY\n\nG1 Z4 F1200\n\n;===== mech mode fast check end =======================\n\n;M400\n;M73 P1.717\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\n\nM975 S1\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\n;===== remove waste by touching start =====\n\nM104 S170 ; set temp down to heatbed acceptable\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nG0 X108 Y-0.5 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X110 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X112 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X114 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X116 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X118 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X120 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X122 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X124 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X126 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X128 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X130 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X132 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X134 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X136 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X138 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X140 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X142 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X144 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X146 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X148 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;===== remove waste by touching end =====\n\nG1 Z10 F1200\nG0 X118 Y261 F30000\nG1 Z5 F1200\nM109 S{material_print_temperature_layer_0-50, initial_extruder_nr}\n\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S140 ; prepare to abl\nG0 Z5 F20000\n\nG0 X128 Y261 F20000 ; move to exposed steel surface\nG0 Z-1.01 F1200 ; stop the nozzle\n\nG91\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z10 F1200\n\n;===== brush material wipe nozzle =====\n\nG90\nG1 Y250 F30000\nG1 X55\nG1 Z1.300 F1200\nG1 Y262.5 F6000\nG91\nG1 X-35 F30000\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Z5.000 F1200\n\nG90\nG1 X30 Y250.000 F30000\nG1 Z1.300 F1200\nG1 Y262.5 F6000\nG91\nG1 X35 F30000\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Z10.000 F1200\n\n;===== brush material wipe nozzle end =====\n\nG90\n;G0 X128 Y261 F20000 ; move to exposed steel surface\nG1 Y250 F30000\nG1 X138\nG1 Y261\nG0 Z-1.01 F1200 ; stop the nozzle\n\nG91\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nM109 S140\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM211 R; pop softend status\n\n;===== wipe nozzle end ================================\n\n;M400\n;M73 P1.717\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\n\nG90\nG1 Z5 F1200\nG1 X0 Y0 F30000\nG29.2 S1 ; turn on ABL\n\nM190 S{material_bed_temperature_layer_0}; ensure bed temp\nM109 S140\nM106 S0 ; turn off fan , too noisy\n\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n\n;===== home after wipe mouth end =======================\n\n;M400\n;M73 P1.717\n\nG1 X108.000 Y-0.500 F30000\nG1 Z0.300 F1200\nM400\nG2814 Z0.32\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; prepare to print\n\n;===== extrude cali test ===============================\n\nM400\n M900 S\n M900 C\n G90\n M83\n\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G0 X128 E8 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X133 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X138 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X143 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X148 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X153 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G91\n G1 X1 Z-0.300\n G1 X4\n G1 Z1 F1200\n G90\n M400\n\nM900 R\n\nM1002 judge_flag extrude_cali_flag\nM622 J1\n G90\n G1 X108.000 Y1.000 F30000\n G91\n G1 Z-0.700 F1200\n G90\n M83\n G0 X128 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X133 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X138 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X143 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X148 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X153 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G91\n G1 X1 Z-0.300\n G1 X4\n G1 Z1 F1200\n G90\n M400\nM623\n\nG1 Z0.2\n\n;M400\n;M73 P1.717\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate_type=='textured_pei_plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\n;G392 S1 ; turn on clog detection\nM1007 S1 ; turn on mass estimation\nG29.4\n" }, + "machine_start_gcode": { "default_value": ";===== machine: A1 =========================\n;===== date: 20240620 =====================\nG392 S0\nM9833.2\n;M400\n;M73 P1.717\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S140\nM140 S{material_bed_temperature_layer_0}\n\n;=====start printer sound ===================\n; 'The entertainer' by Scott Joplin\nM17\nM400 S1\nM1006 S1\n\nM1006 A0 B10 C39 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C40 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C41 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C49 D30 L30 M60 E0 F10 N60\nM1006 A0 B10 C41 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C49 D30 L30 M60 E0 F10 N60\nM1006 A0 B10 C41 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C49 D30 L30 M60 E0 F10 N60\n\nM1006 A0 B10 C0 D30 L30 M60 E0 F10 N60\n\nM1006 A0 B10 C49 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C50 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C51 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C53 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C50 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C51 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C53 D30 L30 M60 E0 F10 N60\nM1006 A0 B10 C47 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C51 D30 L30 M60 E0 F10 N60\nM1006 A0 B10 C49 D30 L30 M60 E0 F10 N60\n\nM1006 W\nM18\n;=====start printer sound ===================\n\n;=====avoid end stop =================\nG91\nG380 S2 Z40 F1200\nG380 S3 Z-15 F1200\nG90\n\n;===== reset machine status =================\n;M290 X39 Y39 Z8\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.65 Y1.2 Z0.6 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;M211 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\n\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\nM1002 gcode_claim_action : 13\n\nG28 X\nG91\nG1 Z5 F1200\nG90\nG0 X128 F30000\nG0 Y254 F3000\nG91\nG1 Z-5 F1200\n\nM109 S25 H140\n\nM17 E0.3\nM83\nG1 E10 F1200\nG1 E-0.5 F30\nM17 D\n\nG28 Z P0 T140; home z with low precision,permit 300deg temperature\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\n\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n G90\n G1 Z5 F1200\nM623\n\n;M400\n;M73 P1.717\n\n;===== prepare print temperature and material ==========\nM1002 gcode_claim_action : 24\n\nM400\n;G392 S1\nM211 X0 Y0 Z0 ;turn off soft endstop\nM975 S1 ; turn on\n\nG90\nG1 X-28.5 F30000\nG1 X-48.2 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-48.2 F3000\n M400\n\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\nM621 S{initial_extruder_nr}A\n\nM109 S{material_print_temperature, initial_extruder_nr} H300\nG92 E0\nG1 E50 F200 ; lower extrusion speed to avoid clog\nM400\nM106 P1 S178\nG92 E0\nG1 E5 F200\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E-0.5 F300\n\nG1 X-28.5 F30000\nG1 X-48.2 F3000\nG1 X-28.5 F30000 ;wipe and shake\nG1 X-48.2 F3000\nG1 X-28.5 F30000 ;wipe and shake\nG1 X-48.2 F3000\n\n;G392 S0\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n;M400\n;M73 P1.717\n\n;===== auto extrude cali start =========================\nM975 S1\n;G392 S1\n\nG90\nM83\nT1000\nG1 X-48.2 Y0 Z10 F10000\nM400\nM1002 set_filament_type:UNKNOWN\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\n\nM622 J1\n M1002 gcode_claim_action : 8\n\n M109 S{material_print_temperature, initial_extruder_nr}\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n\n M106 P1 S255\n M400 S5\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n G1 X-48.2 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S255\n M400 S5\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-48.2 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n G1 X-48.2 F3000\n M400\n M106 P1 S0\nM623 ; end of 'draw extrinsic para cali paint'\n\n;G392 S0\n;===== auto extrude cali end ========================\n\n;M400\n;M73 P1.717\n\nM104 S170 ; prepare to wipe nozzle\nM106 S255 ; turn on fan\n\n;===== mech mode fast check start =====================\nM1002 gcode_claim_action : 3\n\nG1 X128 Y128 F20000\nG1 Z5 F1200\nM400 P200\nM970.3 Q1 A5 K0 O3\nM974 Q1 S2 P0\n\nM970.2 Q1 K1 W58 Z0.1\nM974 S2\n\nG1 X128 Y128 F20000\nG1 Z5 F1200\nM400 P200\nM970.3 Q0 A10 K0 O1\nM974 Q0 S2 P0\n\nM970.2 Q0 K1 W78 Z0.1\nM974 S2\n\nM975 S1\nG1 F30000\nG1 X0 Y5\nG28 X ; re-home XY\n\nG1 Z4 F1200\n\n;===== mech mode fast check end =======================\n\n;M400\n;M73 P1.717\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\n\nM975 S1\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\n;===== remove waste by touching start =====\n\nM104 S170 ; set temp down to heatbed acceptable\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nG0 X108 Y-0.5 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X110 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X112 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X114 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X116 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X118 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X120 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X122 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X124 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X126 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X128 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X130 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X132 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X134 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X136 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X138 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X140 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X142 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X144 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X146 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X148 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;===== remove waste by touching end =====\n\nG1 Z10 F1200\nG0 X118 Y261 F30000\nG1 Z5 F1200\nM109 S{material_print_temperature_layer_0-50, initial_extruder_nr}\n\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S140 ; prepare to abl\nG0 Z5 F20000\n\nG0 X128 Y261 F20000 ; move to exposed steel surface\nG0 Z-1.01 F1200 ; stop the nozzle\n\nG91\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z10 F1200\n\n;===== brush material wipe nozzle =====\n\nG90\nG1 Y250 F30000\nG1 X55\nG1 Z1.300 F1200\nG1 Y262.5 F6000\nG91\nG1 X-35 F30000\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Z5.000 F1200\n\nG90\nG1 X30 Y250.000 F30000\nG1 Z1.300 F1200\nG1 Y262.5 F6000\nG91\nG1 X35 F30000\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Z10.000 F1200\n\n;===== brush material wipe nozzle end =====\n\nG90\n;G0 X128 Y261 F20000 ; move to exposed steel surface\nG1 Y250 F30000\nG1 X138\nG1 Y261\nG0 Z-1.01 F1200 ; stop the nozzle\n\nG91\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nM109 S140\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM211 R; pop softend status\n\n;===== wipe nozzle end ================================\n\n;M400\n;M73 P1.717\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\n\nG90\nG1 Z5 F1200\nG1 X0 Y0 F30000\nG29.2 S1 ; turn on ABL\n\nM190 S{material_bed_temperature_layer_0}; ensure bed temp\nM109 S140\nM106 S0 ; turn off fan , too noisy\n\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n\n;===== home after wipe mouth end =======================\n\n;M400\n;M73 P1.717\n\nG1 X108.000 Y-0.500 F30000\nG1 Z0.300 F1200\nM400\nG2814 Z0.32\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; prepare to print\n\n;===== extrude cali test ===============================\n\nM400\n M900 S\n M900 C\n G90\n M83\n\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G0 X128 E8 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X133 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X138 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X143 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X148 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X153 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G91\n G1 X1 Z-0.300\n G1 X4\n G1 Z1 F1200\n G90\n M400\n\nM900 R\n\nM1002 judge_flag extrude_cali_flag\nM622 J1\n G90\n G1 X108.000 Y1.000 F30000\n G91\n G1 Z-0.700 F1200\n G90\n M83\n G0 X128 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X133 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X138 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X143 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X148 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X153 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G91\n G1 X1 Z-0.300\n G1 X4\n G1 Z1 F1200\n G90\n M400\nM623\n\nG1 Z0.2\n\n;M400\n;M73 P1.717\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate_type=='textured_pei_plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\n;G392 S1 ; turn on clog detection\nM1007 S1 ; turn on mass estimation\nG29.4\n" }, "machine_width": { "value": 256 }, "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, "prime_tower_position_y": { "value": "(resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" } diff --git a/resources/definitions/bambulab_a1mini.def.json b/resources/definitions/bambulab_a1mini.def.json index 258f104a4e..490556e4f0 100644 --- a/resources/definitions/bambulab_a1mini.def.json +++ b/resources/definitions/bambulab_a1mini.def.json @@ -34,7 +34,7 @@ "machine_extruder_count": { "value": 4 }, "machine_height": { "value": 175 }, "machine_name": { "default_value": "BambuLab Bambu A1 mini" }, - "machine_start_gcode": { "default_value": ";===== machine: A1 mini =========================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S170\nM140 S{material_bed_temperature_layer_0}\nG392 S0 ;turn off clog detect\nM9833.2\n;=====start printer sound ===================\nM17\nM400 S1\n; M1006 S1\n; M1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\n; M1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\n; M1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\n; M1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\n; M1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-13.5 F3000\n M400\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\n M104 S{material_print_temperature, initial_extruder_nr}\n G92 E0\n G1 E50 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\n M104 S{material_print_temperature_layer_0-40, material_print_temperature_layer_0}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{material_print_temperature_layer_0-40, initial_extruder_nr}\n G392 S0 ;turn off clog detect\nM621 S{initial_extruder_nr}A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 3\n{endif}\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n{endif}\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S{material_bed_temperature_layer_0};set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n\n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.3 F18000 ;Move to start position\n M400\n G0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 Y0 Z0 F20000\n M400\n\n G1 X-13.5 Y0 Z10 F10000\n M400\n\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of 'draw extrinsic para cali paint'\n\n;===== extrude cali test ===============================\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.3 F18000 ;Move to start position\nG0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\nG0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate_type=='textured_pei_plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n" }, + "machine_start_gcode": { "default_value": ";===== machine: A1 mini =========================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{material_type, initial_extruder_nr}\nM104 S170\nM140 S{material_bed_temperature_layer_0}\nG392 S0 ;turn off clog detect\nM9833.2\n;=====start printer sound ===================\n; 'The entertainer' by Scott Joplin\nM17\nM400 S1\nM1006 S1\n\nM1006 A0 B10 C39 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C40 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C41 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C49 D30 L30 M60 E0 F10 N60\nM1006 A0 B10 C41 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C49 D30 L30 M60 E0 F10 N60\nM1006 A0 B10 C41 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C49 D30 L30 M60 E0 F10 N60\n\nM1006 A0 B10 C0 D30 L30 M60 E0 F10 N60\n\nM1006 A0 B10 C49 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C50 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C51 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C53 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C50 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C51 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C53 D30 L30 M60 E0 F10 N60\nM1006 A0 B10 C47 D15 L30 M60 E0 F10 N60\nM1006 A0 B10 C51 D30 L30 M60 E0 F10 N60\nM1006 A0 B10 C49 D30 L30 M60 E0 F10 N60\n\nM1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n M104 S250\n M400\n T{initial_extruder_nr}\n G1 X-13.5 F3000\n M400\n M620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{material_type, initial_extruder_nr}\n M104 S{material_print_temperature, initial_extruder_nr}\n G92 E0\n G1 E50 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{material_max_flowrate/2.4053*60, initial_extruder_nr}\n M109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\n M104 S{material_print_temperature_layer_0-40, material_print_temperature_layer_0}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{material_print_temperature_layer_0-40, initial_extruder_nr}\n G392 S0 ;turn off clog detect\nM621 S{initial_extruder_nr}A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 3\n{endif}\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\n{if material_print_temperature > 2000}\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n{endif}\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S{material_bed_temperature_layer_0};set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A1 X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{material_type, initial_extruder_nr}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n\n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.3 F18000 ;Move to start position\n M400\n G0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\n G0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\n G0 Y0 Z0 F20000\n M400\n\n G1 X-13.5 Y0 Z10 F10000\n M400\n\n G1 E10 F{speed_wall_0*wall_line_width_0*layer_height/2.4*60, initial_extruder_nr}\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} A0.3 H{machine_nozzle_size}; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n\n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{speed_wall_0*wall_line_width_0*layer_height/2.4, initial_extruder_nr} H{machine_nozzle_size}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of 'draw extrinsic para cali paint'\n\n;===== extrude cali test ===============================\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.3 F18000 ;Move to start position\nG0 X88 E10 F{speed_wall_0*wall_line_width_0*layer_height/(24/20) * 60, initial_extruder_nr}\nG0 X93 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X98 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X103 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X108 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 X113 E.3742 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4 * 60, initial_extruder_nr}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate_type=='textured_pei_plate'}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n" }, "machine_width": { "value": 180 }, "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, "prime_tower_position_y": { "value": "(resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" } From 603df28c2adea8a47b470adf780419ecba57aff4 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 28 Apr 2025 13:36:54 +0200 Subject: [PATCH 107/299] Fix all exporters being broken CURA-12099 --- plugins/GCodeGzWriter/GCodeGzWriter.py | 2 +- plugins/GCodeWriter/GCodeWriter.py | 2 +- plugins/MakerbotWriter/MakerbotWriter.py | 2 +- plugins/UFPWriter/UFPWriter.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/GCodeGzWriter/GCodeGzWriter.py b/plugins/GCodeGzWriter/GCodeGzWriter.py index 2bbaaeb0a3..cb5b66fbdc 100644 --- a/plugins/GCodeGzWriter/GCodeGzWriter.py +++ b/plugins/GCodeGzWriter/GCodeGzWriter.py @@ -24,7 +24,7 @@ class GCodeGzWriter(MeshWriter): def __init__(self) -> None: super().__init__(add_to_recent_files = False) - def write(self, stream: BufferedIOBase, nodes: List[SceneNode], mode = MeshWriter.OutputMode.BinaryMode) -> bool: + def write(self, stream: BufferedIOBase, nodes: List[SceneNode], mode = MeshWriter.OutputMode.BinaryMode, **kwargs) -> bool: """Writes the gzipped g-code to a stream. Note that even though the function accepts a collection of nodes, the diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index 9fa4f88614..0eac653b56 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -56,7 +56,7 @@ class GCodeWriter(MeshWriter): self._application = Application.getInstance() - def write(self, stream, nodes, mode = MeshWriter.OutputMode.TextMode): + def write(self, stream, nodes, mode = MeshWriter.OutputMode.TextMode, **kwargs): """Writes the g-code for the entire scene to a stream. Note that even though the function accepts a collection of nodes, the diff --git a/plugins/MakerbotWriter/MakerbotWriter.py b/plugins/MakerbotWriter/MakerbotWriter.py index f35b53a84d..e4dae9376b 100644 --- a/plugins/MakerbotWriter/MakerbotWriter.py +++ b/plugins/MakerbotWriter/MakerbotWriter.py @@ -91,7 +91,7 @@ class MakerbotWriter(MeshWriter): return None - def write(self, stream: BufferedIOBase, nodes: List[SceneNode], mode=MeshWriter.OutputMode.BinaryMode) -> bool: + def write(self, stream: BufferedIOBase, nodes: List[SceneNode], mode=MeshWriter.OutputMode.BinaryMode, **kwargs) -> bool: metadata, file_format = self._getMeta(nodes) if mode != MeshWriter.OutputMode.BinaryMode: Logger.log("e", "MakerbotWriter does not support text mode.") diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index 0cf756b6a4..c5558c1140 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -51,7 +51,7 @@ class UFPWriter(MeshWriter): # Qt thread. The File read/write operations right now are executed on separated threads because they are scheduled # by the Job class. @call_on_qt_thread - def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode): + def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode, **kwargs): archive = VirtualFile() archive.openStream(stream, "application/x-ufp", OpenMode.WriteOnly) From 4f36f980e11b2b44bad7d09de0f22d06c353f92e Mon Sep 17 00:00:00 2001 From: MariMakes <40423138+MariMakes@users.noreply.github.com> Date: Mon, 28 Apr 2025 16:08:26 +0200 Subject: [PATCH 108/299] Updated Slicing Crash issue Contributes to CURA-12465, this should help with getting more focus in the input we are receiving from the slicing crashes. The old one was a bit outdated. --- .github/ISSUE_TEMPLATE/SlicingCrash.yaml | 62 +++++++----------------- 1 file changed, 17 insertions(+), 45 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/SlicingCrash.yaml b/.github/ISSUE_TEMPLATE/SlicingCrash.yaml index 06025886a2..78f9556915 100644 --- a/.github/ISSUE_TEMPLATE/SlicingCrash.yaml +++ b/.github/ISSUE_TEMPLATE/SlicingCrash.yaml @@ -5,38 +5,24 @@ body: - type: markdown attributes: value: | - ### ✨Try our improved Cura 5.7✨ - Before filling out the report below, we want you to try the latest Cura 5.7. - This version of Cura has become significantly more reliable and has an updated slicing engine that will automatically send a report to the Cura Team for analysis. - #### [You can find the downloads here](https://github.com/Ultimaker/Cura/releases/latest) #### - If you still encounter a crash you are still welcome to report the issue so we can use your model as a test case, you can find instructions on how to do that below. + ### ✨Are you stuck? Have you tried these two things? ✨ + 1- Are you on a Cura version lower than Cura 5.7? We really recommend updating because it resolves a lot of slicing crashes! + 2- Have you tried fixing the model with software that repairs 3d files and makes them watertight? + Are you seeing spots and dots on your model? That is Cura indicating that your model is not watertight. - ### Project File - **⚠️ Before you continue, we need your project file to troubleshoot a slicing crash.** - It contains the printer and settings we need for troubleshooting. + If you still encounter a crash you are welcome to report the issue so we can use your model as a test case. + You can find instructions on how to share your model in a Package for Technical Support below. - ![Alt Text](https://user-images.githubusercontent.com/40423138/240616958-5a9751f2-bd34-4808-9752-6fde2e27516e.gif) - - To save a project file go to File -> Save project. - Please make sure to .zip your project file. - For big files, you may need to use [WeTransfer](https://wetransfer.com/) or similar file-sharing sites. - - 🤔 Before you share, please think to yourself. Is this a model that can be shared? - Unfortunately we cannot help if this file is missing. - Do you have the project file? Than let's continue ⬇️ - - ### Questions + 🤔 Before you share, please think to yourself. Is this a model that can be shared on the internet? + **Unfortunately, we cannot help if this file is missing.** + +### Questions - type: input attributes: label: Cura Version - placeholder: 5.6.0 + description: We work hard on improving our slicing crashes. If you are not on the latest version of Cura, [you can download it here](https://github.com/Ultimaker/Cura/releases/latest) validations: required: true -- type: markdown - attributes: - value: | - We work hard on improving our slicing crashes. Our most recent release is 5.7.1. - If you are not on the latest version of Cura, [you can download it here](https://github.com/Ultimaker/Cura/releases/latest) - type: input attributes: label: Operating System @@ -50,27 +36,13 @@ body: description: Which printer was selected in Cura? validations: required: true -- type: input - attributes: - label: Name abnormal settings - description: Are there any settings that you might have changed that caused the crash? Does your model slice when you select the default profiles? - placeholder: - validations: -- type: input - attributes: - label: Describe model location - description: Does your model slice if you rotate the model 90 degrees or if you move it away from the center of the buildplate? - placeholder: - validations: -- type: input - attributes: - label: Describe your model - description: Have you sliced your model succesfully before? Is it watertight? Have you tried doing a quick [Mesh Fix with the Meshtools Plugin](https://marketplace.ultimaker.com/app/cura/plugins/fieldofview/MeshTools)? - validations: - required: true + - type: textarea attributes: - label: Add your .zip here ⬇️ - description: You can add the zip file and additional information that is relevant to the issue in the comments below. + label: Describe your problem and add the package for technical support as a .zip here ⬇️ + description: | + If you still have Cura open with your crash > Click on Help on top bar > Click on Export Package For Technical Support > Compress the file into a zip > Add the file here to your GitHub issue 🔗 + + If you closed Cura, please open Cura to recreate the crash> Select your printer > Load your model > Select your print settings > Click on Help on top bar > Click on Export Package For Technical Support > Compress the file into a zip > Add the file here to your GitHub issue 🔗 validations: required: true From 46216e12829060f0b7fbe64f8706bb7d0d13e2ca Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 29 Apr 2025 09:25:19 +0200 Subject: [PATCH 109/299] Renamed confusing 'Default' variant class to 'Cura3mf'. result of code review of CURA-12099 --- .../3MFWriter/{DefaultVariant.py => Cura3mfVariant.py} | 2 +- plugins/3MFWriter/ThreeMFWriter.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) rename plugins/3MFWriter/{DefaultVariant.py => Cura3mfVariant.py} (97%) diff --git a/plugins/3MFWriter/DefaultVariant.py b/plugins/3MFWriter/Cura3mfVariant.py similarity index 97% rename from plugins/3MFWriter/DefaultVariant.py rename to plugins/3MFWriter/Cura3mfVariant.py index 7f5522c3af..3ae766e651 100644 --- a/plugins/3MFWriter/DefaultVariant.py +++ b/plugins/3MFWriter/Cura3mfVariant.py @@ -13,7 +13,7 @@ from .ThreeMFVariant import ThreeMFVariant METADATA_PATH = "Metadata" THUMBNAIL_PATH = f"{METADATA_PATH}/thumbnail.png" -class DefaultVariant(ThreeMFVariant): +class Cura3mfVariant(ThreeMFVariant): """Default implementation of the 3MF format.""" @property diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 9de117d947..1ca06ef2f4 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -50,7 +50,7 @@ import UM.Application from .SettingsExportModel import SettingsExportModel from .SettingsExportGroup import SettingsExportGroup from .ThreeMFVariant import ThreeMFVariant -from .DefaultVariant import DefaultVariant +from .Cura3mfVariant import Cura3mfVariant from .BambuLabVariant import BambuLabVariant from UM.i18n import i18nCatalog @@ -76,7 +76,7 @@ class ThreeMFWriter(MeshWriter): # Register available variants self._variants = { - DefaultVariant(self).mime_type: DefaultVariant, + Cura3mfVariant(self).mime_type: Cura3mfVariant, BambuLabVariant(self).mime_type: BambuLabVariant } @@ -219,7 +219,7 @@ class ThreeMFWriter(MeshWriter): :param mime_type: The MIME type to get the variant for :return: An instance of the variant for the given MIME type """ - variant_class = self._variants.get(mime_type, DefaultVariant) + variant_class = self._variants.get(mime_type, Cura3mfVariant) return variant_class(self) def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode, export_settings_model = None, **kwargs) -> bool: @@ -227,7 +227,7 @@ class ThreeMFWriter(MeshWriter): archive = zipfile.ZipFile(stream, "w", compression = zipfile.ZIP_DEFLATED) # Determine which variant to use based on mime type in kwargs - mime_type = kwargs.get("mime_type", DefaultVariant(self).mime_type) + mime_type = kwargs.get("mime_type", Cura3mfVariant(self).mime_type) variant = self._getVariant(mime_type) try: From 74f8a2da6ef6c1fb62d457d46dd4e8307b517d84 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 29 Apr 2025 10:18:13 +0200 Subject: [PATCH 110/299] Basically working X1 profile CURA-12101 --- resources/definitions/bambulab_x1.def.json | 279 +----------------- .../extruders/bambulab_x1_extruder_0.def.json | 4 +- .../extruders/bambulab_x1_extruder_1.def.json | 4 +- .../extruders/bambulab_x1_extruder_2.def.json | 4 +- .../extruders/bambulab_x1_extruder_3.def.json | 4 +- 5 files changed, 13 insertions(+), 282 deletions(-) diff --git a/resources/definitions/bambulab_x1.def.json b/resources/definitions/bambulab_x1.def.json index 4d0960ff92..3a77b145f8 100644 --- a/resources/definitions/bambulab_x1.def.json +++ b/resources/definitions/bambulab_x1.def.json @@ -1,13 +1,10 @@ { "version": 2, "name": "BambuLab X1", - "inherits": "fdmprinter", + "inherits": "bambulab_base", "metadata": { "visible": true, - "author": "UltiMaker", - "manufacturer": "BambuLab", - "file_formats": "text/x-gcode", "platform": "bambulab_x1.obj", "has_machine_quality": true, "has_material": true, @@ -32,287 +29,21 @@ }, "overrides": { - "acceleration_infill": { "value": "acceleration_print" }, - "acceleration_layer_0": { "value": 2000 }, - "acceleration_prime_tower": { "value": "acceleration_print" }, - "acceleration_print": { "value": 20000 }, - "acceleration_print_layer_0": { "value": "acceleration_layer_0" }, - "acceleration_roofing": { "value": "acceleration_wall_0" }, - "acceleration_skirt_brim": { "value": "acceleration_layer_0" }, - "acceleration_support": { "value": "acceleration_print" }, - "acceleration_support_bottom": { "value": "acceleration_support_interface" }, - "acceleration_support_infill": { "value": "acceleration_support" }, - "acceleration_support_interface": { "value": "acceleration_support" }, - "acceleration_support_roof": { "value": "acceleration_support_interface" }, - "acceleration_topbottom": { "value": "acceleration_print" }, - "acceleration_travel": { "value": 20000 }, - "acceleration_travel_enabled": { "value": true }, - "acceleration_travel_layer_0": { "value": "acceleration_layer_0" }, - "acceleration_wall": { "value": "acceleration_print/8" }, - "acceleration_wall_0": { "value": "acceleration_wall" }, - "acceleration_wall_0_roofing": { "value": "acceleration_wall_0" }, - "acceleration_wall_x": { "value": "acceleration_print" }, - "acceleration_wall_x_roofing": { "value": "acceleration_wall" }, - "adhesion_type": { "value": "'skirt'" }, - "bottom_thickness": { "value": 0.6 }, - "bridge_skin_speed": - { - "unit": "mm/s", - "value": "bridge_wall_speed" - }, - "bridge_sparse_infill_max_density": { "value": 50 }, - "bridge_wall_min_length": { "value": 10 }, - "bridge_wall_speed": - { - "unit": "mm/s", - "value": 50 - }, - "cool_min_layer_time": { "value": 6 }, - "cool_min_speed": { "value": 6 }, - "cool_min_temperature": { "value": "material_print_temperature-15" }, - "default_material_print_temperature": { "maximum_value_warning": 320 }, - "extra_infill_lines_to_support_skins": { "value": "'walls_and_lines'" }, - "gradual_flow_enabled": { "value": false }, - "hole_xy_offset": { "value": 0.075 }, - "infill_overlap": { "value": 10 }, - "infill_pattern": { "value": "'zigzag' if infill_sparse_density > 80 else 'grid'" }, - "infill_sparse_density": { "value": 15 }, - "infill_wall_line_count": { "value": "1 if infill_sparse_density > 80 else 0" }, - "jerk_infill": { "value": "jerk_print" }, - "jerk_layer_0": { "value": "jerk_print/2" }, - "jerk_prime_tower": { "value": "jerk_print" }, - "jerk_print": { "value": "50" }, - "jerk_print_layer_0": { "value": "jerk_layer_0" }, - "jerk_roofing": { "value": "jerk_wall_0" }, - "jerk_skirt_brim": { "value": "jerk_layer_0" }, - "jerk_support": { "value": "jerk_print" }, - "jerk_support_bottom": { "value": "jerk_support_interface" }, - "jerk_support_infill": { "value": "jerk_support" }, - "jerk_support_interface": { "value": "jerk_support" }, - "jerk_support_roof": { "value": "jerk_support_interface" }, - "jerk_topbottom": { "value": "jerk_print" }, - "jerk_travel": { "value": 50 }, - "jerk_travel_enabled": { "value": true }, - "jerk_travel_layer_0": { "value": "jerk_travel" }, - "jerk_wall": { "value": "jerk_print/5" }, - "jerk_wall_0": { "value": "jerk_wall" }, - "jerk_wall_0_roofing": { "value": "jerk_wall_0" }, - "jerk_wall_x": { "value": "jerk_print" }, - "jerk_wall_x_roofing": { "value": "jerk_wall_0" }, - "line_width": { "value": 0.42 }, - "machine_acceleration": { "value": 10000 }, - "machine_center_is_zero": { "value": false }, "machine_depth": { "value": 256 }, - "machine_end_gcode": { "default_value": "M400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos \nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of \"timelapse_record_flag\"\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (machine_height + 100.0) < 25}\n G1 Z{machine_height + 100.0} F600\n G1 Z{machine_height +98.0}\n{else}\n G1 Z250 F600\n G1 Z248\n{endif}\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X128 Y250 F3600\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\n" }, + "machine_end_gcode": { "default_value": ";===== date: 20240528 =====================\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos\nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of 'timelapse_record_flag'\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\nG1 Z250 F600\nG1 Z248\nM400 P100\nM17 R ; restore z current\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\nM960 S5 P0 ; turn off logo lamp\n" }, "machine_extruder_count": { "value": 4 }, - "machine_heated_bed": { "value": true }, "machine_height": { "value": 251 }, - "machine_max_feedrate_e": { "value": 150 }, - "machine_max_feedrate_x": { "value": 500 }, - "machine_max_feedrate_y": { "value": 500 }, - "machine_max_feedrate_z": { "value": 15 }, - "machine_max_jerk_e": { "default_value": 100 }, - "machine_max_jerk_xy": { "default_value": 5000 }, - "machine_max_jerk_z": { "default_value": 100 }, "machine_name": { "default_value": "BambuLab Bambu X1" }, - "machine_nozzle_cool_down_speed": { "default_value": 1.3 }, - "machine_nozzle_heat_up_speed": { "default_value": 1.9 }, - "machine_nozzle_size": { "value": 0.4 }, - "machine_show_variants": { "value": true }, - "machine_start_gcode": { "default_value": ";===== machine: X1 ====================\n;===== date: 20241023 ==================\n;===== start printer sound ================\nM17\nM400 S1\nM1006 S1\nM1006 A0 B10 L100 C37 D10 M60 E37 F10 N60\nM1006 A0 B10 L100 C41 D10 M60 E41 F10 N60\nM1006 A0 B10 L100 C44 D10 M60 E44 F10 N60\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N60\nM1006 A46 B10 L100 C43 D10 M70 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N100\nM1006 A43 B10 L100 C0 D10 M60 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N100\nM1006 A41 B10 L100 C0 D10 M100 E41 F10 N100\nM1006 A44 B10 L100 C0 D10 M100 E44 F10 N100\nM1006 A49 B10 L100 C0 D10 M100 E49 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A48 B10 L100 C44 D10 M60 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N100\nM1006 A44 B10 L100 C0 D10 M90 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N100\nM1006 A46 B10 L100 C43 D10 M60 E39 F10 N100\nM1006 W\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]=='PLA'}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {endif};Prevent PLA from jamming\n M142 P1 R35 S40\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]=='PLA'}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {endif};Prevent PLA from jamming\n M142 P1 R35 S40\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type=='Textured PEI Plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.160\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.080\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of 'draw extrinsic para cali paint'\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.080 K0.160\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.08 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.08}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n;===== purge line to wipe the nozzle ============================\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X18.0 Y2.5 Z0.8 F18000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG1 Z0.2\nG0 X239 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y12 E0.7 F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\n" }, - "machine_use_extruder_offset_to_offset_coords": { "value": false }, + "machine_start_gcode": { "default_value": ";===== machine: X1 ====================\n;===== date: 20241023 ==================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z0 ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_bed_temperature_layer_0} ;wait for bed temp\n\n{if machine_scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if material_type=='PLA' and (material_bed_temperature_layer_0>45 or material_bed_temperature>45), initial_extruder_nr}\n M106 P3 S180\n M142 P1 R35 S40\n{endif}\n{if material_type=='PLA' and (material_bed_temperature_layer_0<=45 and material_bed_temperature<=45) , initial_extruder_nr}\n M142 P1 R35 S40\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T{initial_extruder_nr}\n G1 X54 F12000\n G1 Y265\n M400\nM621 S{initial_extruder_nr}A\nM620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if material_type=='PLA' and (material_bed_temperature_layer_0>45 or material_bed_temperature>45), initial_extruder_nr}\n M106 P3 S180\n M142 P1 R35 S40\n{endif}\n{if material_type=='PLA' and (material_bed_temperature_layer_0<=45 and material_bed_temperature<=45) , initial_extruder_nr}\n M142 P1 R35 S40\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if machine_scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{material_print_temperature, initial_extruder_nr}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y11 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate_type=='textured_pei_plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if acceleration_print > 0 and acceleration_wall_0 > 0, initial_extruder_nr}\n M204 S{acceleration_wall_0, initial_extruder_nr}\n {endif}\n {if acceleration_print > 0 and acceleration_wall_0 <= 0, initial_extruder_nr}\n M204 S{acceleration_print, initial_extruder_nr}\n {endif}\n\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.160\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.080\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of 'draw extrinsic para cali paint'\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{material_print_temperature, initial_extruder_nr} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60/4, initial_extruder_nr} C5.000 D{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60, initial_extruder_nr} E5.000 F175.000 H1.000 I0.000 J0.080 K0.160\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{material_print_temperature, initial_extruder_nr}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.08 M{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*0.08, initial_extruder_nr}\n M623\n\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X185.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X190.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X195.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X200.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X205.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X210.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X215.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X220.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X225.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n;===== purge line to wipe the nozzle ============================\nG1 E{-retraction_amount, initial_extruder_nr} F1800\nG1 X18.0 Y2.5 Z0.8 F18000.0;Move to start position\nG1 E{retraction_amount, initial_extruder_nr} F1800\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nG1 Z0.2\nG0 X239 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y12 E0.7 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4* 60, initial_extruder_nr}\n" }, "machine_width": { "value": 256 }, - "material_diameter": { "value": 1.75 }, - "max_skin_angle_for_expansion": { "value": 45 }, - "meshfix_maximum_resolution": { "value": 0.4 }, - "min_infill_area": { "default_value": 10 }, - "optimize_wall_printing_order": { "value": false }, - "relative_extrusion": { "value": true }, - "retraction_amount": { "value": 0.5 }, - "retraction_combing_max_distance": { "value": 100 }, - "retraction_extra_prime_amount": { "value": 0.12 }, - "retraction_hop": { "value": 0.2 }, - "retraction_hop_after_extruder_switch_height": { "value": 2 }, - "retraction_hop_enabled": { "value": true }, - "retraction_min_travel": { "value": "5 if support_enable and support_structure=='tree' else line_width * 2" }, - "retraction_prime_speed": { "value": 15 }, - "retraction_speed": { "value": 30 }, - "skin_edge_support_thickness": { "value": 0 }, - "skin_material_flow": { "value": 95 }, - "skin_overlap": { "value": 0 }, - "skin_preshrink": { "value": 0 }, - "skirt_line_count": { "value": 5 }, - "small_skin_on_surface": { "value": false }, - "small_skin_width": { "value": 4 }, - "speed_infill": - { - "maximum_value_warning": 500, - "value": "speed_print" - }, - "speed_ironing": - { - "maximum_value_warning": 500, - "value": 20 - }, - "speed_layer_0": - { - "maximum_value_warning": 500, - "value": "speed_wall" - }, - "speed_prime_tower": - { - "maximum_value_warning": 500, - "value": "speed_wall" - }, - "speed_print": - { - "maximum_value_warning": 500, - "value": 300 - }, - "speed_print_layer_0": - { - "maximum_value_warning": 500, - "value": "speed_layer_0" - }, - "speed_roofing": - { - "maximum_value_warning": 500, - "value": "speed_wall" - }, - "speed_skirt_brim": - { - "maximum_value_warning": 500, - "value": "speed_layer_0" - }, - "speed_support": - { - "maximum_value_warning": 500, - "value": "speed_wall_0" - }, - "speed_support_bottom": - { - "maximum_value_warning": 500, - "value": "speed_support_interface" - }, - "speed_support_infill": - { - "maximum_value_warning": 500, - "value": "speed_support" - }, - "speed_support_interface": - { - "maximum_value_warning": 500, - "value": 50 - }, - "speed_support_roof": - { - "maximum_value_warning": 500, - "value": "speed_support_interface" - }, - "speed_topbottom": - { - "maximum_value_warning": 500, - "value": "speed_print" - }, - "speed_travel": - { - "maximum_value": 500, - "value": 500 - }, - "speed_travel_layer_0": - { - "maximum_value": 500, - "value": 150 - }, - "speed_wall": - { - "maximum_value_warning": 500, - "value": "speed_print*2/3" - }, - "speed_wall_0": - { - "maximum_value_warning": 500, - "value": "speed_wall" - }, - "speed_wall_0_roofing": - { - "maximum_value_warning": 500, - "value": "speed_wall" - }, - "speed_wall_x": - { - "maximum_value_warning": 500, - "value": "speed_print" - }, - "speed_wall_x_roofing": - { - "maximum_value_warning": 500, - "value": "speed_wall" - }, - "support_brim_line_count": { "value": 5 }, - "support_density": { "value": 15 }, - "support_infill_rate": { "value": "80 if gradual_support_infill_steps != 0 else 15" }, - "support_pattern": { "value": "'gyroid'" }, - "support_structure": { "value": "'tree'" }, - "travel_avoid_other_parts": { "value": false }, - "wall_0_acceleration": { "value": 1000 }, - "wall_0_deceleration": { "value": 1000 }, - "wall_0_end_speed_ratio": { "value": 100 }, - "wall_0_speed_split_distance": { "value": 0.2 }, - "wall_0_start_speed_ratio": { "value": 100 }, - "wall_0_wipe_dist": { "value": 0 }, - "wall_material_flow": { "value": 95 }, - "wall_overhang_angle": { "value": 45 }, - "wall_overhang_speed_factor": { "value": 50 }, - "wall_x_material_flow": { "value": 100 }, - "z_seam_corner": { "value": "'z_seam_corner_weighted'" }, - "z_seam_position": { "value": "'backright'" }, - "z_seam_type": { "value": "'sharpest_corner'" } + "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" } }, "settings": { - "material": - { - "children": - { - "material_max_flowrate": - { - "default_value": 16, - "description": "Maximum flowrate that the printer can extrude for the material", - "enabled": true, - "label": "Material Maximum Flowrate", - "maximum_value": "machine_max_feedrate_e * (material_diameter/2)**2 * math.pi", - "minimum_value": "0", - "settable_per_extruder": true, - "settable_per_mesh": false, - "type": "float", - "unit": "mm\u00b3/s", - "value": "16" - } - } - }, "platform_adhesion": { "children": { - "machine_buildplate": - { - "default_value": "textured_pei_plate", - "description": "The type of the build plate installed on the printer.", - "enabled": true, - "label": "Build Plate Type", - "options": - { - "cool_plate": "Cool Plate", - "engineering_plate": "Engineering Plate", - "high_temp_plate": "High Temp Plate", - "textured_pei_plate": "Textured PEI Plate" - }, - "settable_per_extruder": false, - "settable_per_mesh": false, - "settable_per_meshgroup": false, - "type": "enum" - }, "machine_scan_first_layer": { "default_value": true, @@ -323,7 +54,7 @@ "settable_per_mesh": false, "settable_per_meshgroup": false, "type": "bool", - "value": "machine_buildplate!='textured_pei_plate'" + "value": "machine_buildplate_type!='textured_pei_plate'" } } } diff --git a/resources/extruders/bambulab_x1_extruder_0.def.json b/resources/extruders/bambulab_x1_extruder_0.def.json index a25f79212b..3ff6e83c83 100644 --- a/resources/extruders/bambulab_x1_extruder_0.def.json +++ b/resources/extruders/bambulab_x1_extruder_0.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 0 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": "M620 S[next_extruder]A\nM204 S9000\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E-{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\n{else}\nM620.11 S0\n{endif}\nM400\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\nM628 S1\nG92 E0\nG1 E{retraction_distances_when_cut[previous_extruder]} F[old_filament_e_feedrate]\nM400\nM629 S1\n{else}\nM620.11 S0\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == 'PETG'}\nM109 S260\n{elsif filament_type[next_extruder] == 'PVA'}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" }, - "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, + "machine_extruder_end_code": { "default_value": "M204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n\n{if material_print_temperature > 142}\nM104 S{material_print_temperature}\n{endif}\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n\n;{if toolchange_count == 2}\n; get travel path for change filament\n;M620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\n;M620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\n;M620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n;{endif}\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\n" }, + "machine_extruder_start_code": { "default_value": "M620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\n\nG92 E0\n\n; always use highest temperature to flush\n{if material_type == 'PETG'}\nM109 S260\n{elsif material_type == 'PVA'}\nM109 S210\n{else}\nM109 S{material_print_temperature}\n{endif}\n\n{if not prime_tower_enable}\n\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; FLUSH_START\nM400\nM109 S{material_print_temperature}\nG1 E6 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n;G1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\n\nM621 S{extruder_nr}A\n" }, "material_diameter": { "default_value": 1.75 } } } \ No newline at end of file diff --git a/resources/extruders/bambulab_x1_extruder_1.def.json b/resources/extruders/bambulab_x1_extruder_1.def.json index 2377d4199c..777e735fa6 100644 --- a/resources/extruders/bambulab_x1_extruder_1.def.json +++ b/resources/extruders/bambulab_x1_extruder_1.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 1 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": "M620 S[next_extruder]A\nM204 S9000\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E-{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\n{else}\nM620.11 S0\n{endif}\nM400\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\nM628 S1\nG92 E0\nG1 E{retraction_distances_when_cut[previous_extruder]} F[old_filament_e_feedrate]\nM400\nM629 S1\n{else}\nM620.11 S0\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == 'PETG'}\nM109 S260\n{elsif filament_type[next_extruder] == 'PVA'}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" }, - "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, + "machine_extruder_end_code": { "default_value": "M204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n\n{if material_print_temperature > 142}\nM104 S{material_print_temperature}\n{endif}\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n\n;{if toolchange_count == 2}\n; get travel path for change filament\n;M620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\n;M620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\n;M620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n;{endif}\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\n" }, + "machine_extruder_start_code": { "default_value": "M620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\n\nG92 E0\n\n; always use highest temperature to flush\n{if material_type == 'PETG'}\nM109 S260\n{elsif material_type == 'PVA'}\nM109 S210\n{else}\nM109 S{material_print_temperature}\n{endif}\n\n{if not prime_tower_enable}\n\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; FLUSH_START\nM400\nM109 S{material_print_temperature}\nG1 E6 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n;G1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\n\nM621 S{extruder_nr}A\n" }, "material_diameter": { "default_value": 1.75 } } } \ No newline at end of file diff --git a/resources/extruders/bambulab_x1_extruder_2.def.json b/resources/extruders/bambulab_x1_extruder_2.def.json index 62c87c794e..3fad4c692d 100644 --- a/resources/extruders/bambulab_x1_extruder_2.def.json +++ b/resources/extruders/bambulab_x1_extruder_2.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 2 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": "M620 S[next_extruder]A\nM204 S9000\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E-{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\n{else}\nM620.11 S0\n{endif}\nM400\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\nM628 S1\nG92 E0\nG1 E{retraction_distances_when_cut[previous_extruder]} F[old_filament_e_feedrate]\nM400\nM629 S1\n{else}\nM620.11 S0\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == 'PETG'}\nM109 S260\n{elsif filament_type[next_extruder] == 'PVA'}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" }, - "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, + "machine_extruder_end_code": { "default_value": "M204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n\n{if material_print_temperature > 142}\nM104 S{material_print_temperature}\n{endif}\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n\n;{if toolchange_count == 2}\n; get travel path for change filament\n;M620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\n;M620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\n;M620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n;{endif}\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\n" }, + "machine_extruder_start_code": { "default_value": "M620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\n\nG92 E0\n\n; always use highest temperature to flush\n{if material_type == 'PETG'}\nM109 S260\n{elsif material_type == 'PVA'}\nM109 S210\n{else}\nM109 S{material_print_temperature}\n{endif}\n\n{if not prime_tower_enable}\n\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; FLUSH_START\nM400\nM109 S{material_print_temperature}\nG1 E6 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n;G1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\n\nM621 S{extruder_nr}A\n" }, "material_diameter": { "default_value": 1.75 } } } \ No newline at end of file diff --git a/resources/extruders/bambulab_x1_extruder_3.def.json b/resources/extruders/bambulab_x1_extruder_3.def.json index ab7752b74f..751ec2b459 100644 --- a/resources/extruders/bambulab_x1_extruder_3.def.json +++ b/resources/extruders/bambulab_x1_extruder_3.def.json @@ -11,8 +11,8 @@ { "extruder_nr": { "default_value": 3 }, "machine_extruder_change_duration": { "default_value": 29 }, - "machine_extruder_end_code": { "default_value": "M620 S[next_extruder]A\nM204 S9000\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E-{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\n{else}\nM620.11 S0\n{endif}\nM400\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\nM628 S1\nG92 E0\nG1 E{retraction_distances_when_cut[previous_extruder]} F[old_filament_e_feedrate]\nM400\nM629 S1\n{else}\nM620.11 S0\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == 'PETG'}\nM109 S260\n{elsif filament_type[next_extruder] == 'PVA'}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" }, - "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nG91\nG0 Z-0.4 F600\nG90" }, + "machine_extruder_end_code": { "default_value": "M204 S9000\n\nG91 ; set relative positioning\nG1 Z3.0 F1200\nG90 ; back to abolute positioning\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n\n{if material_print_temperature > 142}\nM104 S{material_print_temperature}\n{endif}\n\nM620.11 S1 I{extruder_nr} E-18 F1200\nM400\n\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n\n;{if toolchange_count == 2}\n; get travel path for change filament\n;M620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\n;M620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\n;M620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n;{endif}\n\nM620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\n" }, + "machine_extruder_start_code": { "default_value": "M620.1 E F{material_flush_purge_speed} T{material_print_temperature, extruder_nr}\n\nG92 E0\n\n; always use highest temperature to flush\n{if material_type == 'PETG'}\nM109 S260\n{elsif material_type == 'PVA'}\nM109 S210\n{else}\nM109 S{material_print_temperature}\n{endif}\n\n{if not prime_tower_enable}\n\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{material_print_temperature, extruder_nr}\nM106 P1 S60\nG1 E{material_flush_purge_length / 4.0} F{min(extruderValues('material_flush_purge_speed'))} ; do not need pulsatile flushing for start part\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{min(extruderValues('material_flush_purge_speed'))}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.23} F{material_flush_purge_speed, extruder_nr}\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\nM400\nM1002 set_filament_type:{material_type, extruder_nr}\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n\nM106 P1 S60\n; FLUSH_START\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\nG1 E{(material_flush_purge_length / 4.0) * 0.18} F{material_flush_purge_speed, extruder_nr}\nG1 E{(material_flush_purge_length / 4.0) * 0.02} F50\n; FLUSH_END\nG1 E-{retraction_amount * 2} F1800\nG1 E{retraction_amount * 2} F300\n\n; FLUSH_START\nM400\nM109 S{material_print_temperature}\nG1 E6 F{material_flush_purge_speed, extruder_nr} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\n\n{endif} ; prime_tower_enable\n\nM400\nG92 E0\n;G1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\n\nM621 S{extruder_nr}A\n" }, "material_diameter": { "default_value": 1.75 } } } \ No newline at end of file From d2e625edb37c93c17f213cd2dad0ee9ef6646dce Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 29 Apr 2025 11:28:56 +0200 Subject: [PATCH 111/299] Export project settings into BambuLab 3MF CURA-12101 The printer parses the machine_start_gcode to allow selecting the filaments mapping at start time, without it the user has to set the filaments in fixed order. This is probably a security to ensure the proper filament is loaded at start. --- cura/API/Interface/Settings.py | 36 ++++++++++++++++++---------- plugins/3MFWriter/BambuLabVariant.py | 10 +++++++- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/cura/API/Interface/Settings.py b/cura/API/Interface/Settings.py index 084023b9bd..6437de268a 100644 --- a/cura/API/Interface/Settings.py +++ b/cura/API/Interface/Settings.py @@ -3,7 +3,7 @@ from dataclasses import asdict -from typing import cast, Dict, TYPE_CHECKING +from typing import cast, Dict, TYPE_CHECKING, Any from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.SettingFunction import SettingFunction @@ -54,6 +54,15 @@ class Settings: return self.application.getSidebarCustomMenuItems() + def getAllGlobalSettings(self) -> Dict[str, Any]: + global_stack = cast(GlobalStack, self.application.getGlobalContainerStack()) + + all_settings = {} + for setting in global_stack.getAllKeys(): + all_settings[setting] = self._retrieveValue(global_stack, setting) + + return all_settings + def getSliceMetadata(self) -> Dict[str, Dict[str, Dict[str, str]]]: """Get all changed settings and all settings. For each extruder and the global stack""" print_information = self.application.getPrintInformation() @@ -71,24 +80,16 @@ class Settings: "quality": asdict(machine_manager.activeQualityDisplayNameMap()), } - def _retrieveValue(container: InstanceContainer, setting_: str): - value_ = container.getProperty(setting_, "value") - for _ in range(0, 1024): # Prevent possibly endless loop by not using a limit. - if not isinstance(value_, SettingFunction): - return value_ # Success! - value_ = value_(container) - return 0 # Fallback value after breaking possibly endless loop. - global_stack = cast(GlobalStack, self.application.getGlobalContainerStack()) # Add global user or quality changes global_flattened_changes = InstanceContainer.createMergedInstanceContainer(global_stack.userChanges, global_stack.qualityChanges) for setting in global_flattened_changes.getAllKeys(): - settings["global"]["changes"][setting] = _retrieveValue(global_flattened_changes, setting) + settings["global"]["changes"][setting] = self._retrieveValue(global_flattened_changes, setting) # Get global all settings values without user or quality changes for setting in global_stack.getAllKeys(): - settings["global"]["all_settings"][setting] = _retrieveValue(global_stack, setting) + settings["global"]["all_settings"][setting] = self._retrieveValue(global_stack, setting) for i, extruder in enumerate(global_stack.extruderList): # Add extruder fields to settings dictionary @@ -100,10 +101,19 @@ class Settings: # Add extruder user or quality changes extruder_flattened_changes = InstanceContainer.createMergedInstanceContainer(extruder.userChanges, extruder.qualityChanges) for setting in extruder_flattened_changes.getAllKeys(): - settings[f"extruder_{i}"]["changes"][setting] = _retrieveValue(extruder_flattened_changes, setting) + settings[f"extruder_{i}"]["changes"][setting] = self._retrieveValue(extruder_flattened_changes, setting) # Get extruder all settings values without user or quality changes for setting in extruder.getAllKeys(): - settings[f"extruder_{i}"]["all_settings"][setting] = _retrieveValue(extruder, setting) + settings[f"extruder_{i}"]["all_settings"][setting] = self._retrieveValue(extruder, setting) return settings + + @staticmethod + def _retrieveValue(container: InstanceContainer, setting_: str): + value_ = container.getProperty(setting_, "value") + for _ in range(0, 1024): # Prevent possibly endless loop by not using a limit. + if not isinstance(value_, SettingFunction): + return value_ # Success! + value_ = value_(container) + return 0 # Fallback value after breaking possibly endless loop. \ No newline at end of file diff --git a/plugins/3MFWriter/BambuLabVariant.py b/plugins/3MFWriter/BambuLabVariant.py index 56337bbc31..69814505ad 100644 --- a/plugins/3MFWriter/BambuLabVariant.py +++ b/plugins/3MFWriter/BambuLabVariant.py @@ -31,6 +31,7 @@ GCODE_MD5_PATH = f"{GCODE_PATH}.md5" MODEL_SETTINGS_PATH = f"{METADATA_PATH}/model_settings.config" PLATE_DESC_PATH = f"{METADATA_PATH}/plate_1.json" SLICE_INFO_PATH = f"{METADATA_PATH}/slice_info.config" +PROJECT_SETTINGS_PATH = f"{METADATA_PATH}/project_settings.config" class BambuLabVariant(ThreeMFVariant): """BambuLab specific implementation of the 3MF format.""" @@ -48,7 +49,7 @@ class BambuLabVariant(ThreeMFVariant): # Add relations elements for thumbnails ET.SubElement(relations_element, "Relationship", Target="/" + THUMBNAIL_PATH_MULTIPLATE, Id="rel-2", - Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail") + pe="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail") ET.SubElement(relations_element, "Relationship", Target="/" + THUMBNAIL_PATH_MULTIPLATE, Id="rel-4", @@ -74,6 +75,7 @@ class BambuLabVariant(ThreeMFVariant): self._storeModelSettings(archive) self._storePlateDesc(archive) self._storeSliceInfo(archive) + self._storeProjectSettings(archive) def _storeGCode(self, archive: zipfile.ZipFile, metadata_relations_element: ET.Element): """Store GCode data in the archive.""" @@ -166,3 +168,9 @@ class BambuLabVariant(ThreeMFVariant): used_g=str(used_g)) self._writer._storeElementTree(archive, SLICE_INFO_PATH, config) + + def _storeProjectSettings(self, archive: zipfile.ZipFile): + api = CuraApplication.getInstance().getCuraAPI() + file = zipfile.ZipInfo(PROJECT_SETTINGS_PATH) + json_string = json.dumps(api.interface.settings.getAllGlobalSettings(), separators=(", ", ": "), indent=4) + archive.writestr(file, json_string.encode("UTF-8")) \ No newline at end of file From 6d4377e056331def155ea0a624a6c3cd16008ddd Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 29 Apr 2025 11:30:55 +0200 Subject: [PATCH 112/299] Add disallowed area and reduce printable area CURA-12101 The disallowed area is the place where the print head goes to cut the filament, so it must really be avoided. On other models this place is outside the build area. I also reduced the printable size, otherwise the head would sometimes bump into the borders and gets shifted. --- resources/definitions/bambulab_x1.def.json | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/resources/definitions/bambulab_x1.def.json b/resources/definitions/bambulab_x1.def.json index 3a77b145f8..78a9b38131 100644 --- a/resources/definitions/bambulab_x1.def.json +++ b/resources/definitions/bambulab_x1.def.json @@ -30,13 +30,25 @@ "overrides": { "machine_depth": { "value": 256 }, + "machine_disallowed_areas": + { + "default_value": [ + [ + [-128, 100], + [-110, 100], + [-110, 128], + [-128, 128] + ] + ] + }, "machine_end_gcode": { "default_value": ";===== date: 20240528 =====================\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{machine_height + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos\nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of 'timelapse_record_flag'\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\nG1 Z250 F600\nG1 Z248\nM400 P100\nM17 R ; restore z current\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\nM960 S5 P0 ; turn off logo lamp\n" }, "machine_extruder_count": { "value": 4 }, "machine_height": { "value": 251 }, "machine_name": { "default_value": "BambuLab Bambu X1" }, "machine_start_gcode": { "default_value": ";===== machine: X1 ====================\n;===== date: 20241023 ==================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z0 ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_bed_temperature_layer_0} ;wait for bed temp\n\n{if machine_scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if material_type=='PLA' and (material_bed_temperature_layer_0>45 or material_bed_temperature>45), initial_extruder_nr}\n M106 P3 S180\n M142 P1 R35 S40\n{endif}\n{if material_type=='PLA' and (material_bed_temperature_layer_0<=45 and material_bed_temperature<=45) , initial_extruder_nr}\n M142 P1 R35 S40\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T{initial_extruder_nr}\n G1 X54 F12000\n G1 Y265\n M400\nM621 S{initial_extruder_nr}A\nM620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if material_type=='PLA' and (material_bed_temperature_layer_0>45 or material_bed_temperature>45), initial_extruder_nr}\n M106 P3 S180\n M142 P1 R35 S40\n{endif}\n{if material_type=='PLA' and (material_bed_temperature_layer_0<=45 and material_bed_temperature<=45) , initial_extruder_nr}\n M142 P1 R35 S40\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if machine_scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{material_print_temperature, initial_extruder_nr}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y11 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate_type=='textured_pei_plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if acceleration_print > 0 and acceleration_wall_0 > 0, initial_extruder_nr}\n M204 S{acceleration_wall_0, initial_extruder_nr}\n {endif}\n {if acceleration_print > 0 and acceleration_wall_0 <= 0, initial_extruder_nr}\n M204 S{acceleration_print, initial_extruder_nr}\n {endif}\n\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.160\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.080\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of 'draw extrinsic para cali paint'\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{material_print_temperature, initial_extruder_nr} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60/4, initial_extruder_nr} C5.000 D{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60, initial_extruder_nr} E5.000 F175.000 H1.000 I0.000 J0.080 K0.160\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{material_print_temperature, initial_extruder_nr}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.08 M{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*0.08, initial_extruder_nr}\n M623\n\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X185.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X190.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X195.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X200.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X205.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X210.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X215.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X220.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X225.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n;===== purge line to wipe the nozzle ============================\nG1 E{-retraction_amount, initial_extruder_nr} F1800\nG1 X18.0 Y2.5 Z0.8 F18000.0;Move to start position\nG1 E{retraction_amount, initial_extruder_nr} F1800\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nG1 Z0.2\nG0 X239 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y12 E0.7 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4* 60, initial_extruder_nr}\n" }, "machine_width": { "value": 256 }, - "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" } + "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, + "travel_avoid_distance": { "value": "3" } }, "settings": { From eeaadbc0713e7fe92f05cd6864f5aded8a33be75 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 29 Apr 2025 13:57:06 +0200 Subject: [PATCH 113/299] Add speed settings for auxilary ('build volume') fan. Previously you could only set on/off starting on a certain layer. CURA-12512 --- resources/definitions/fdmprinter.def.json | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index b42b5c417a..44c0573083 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -4884,6 +4884,36 @@ } } }, + "build_volume_fan_speed_0": + { + "label": "Initial Layers Build Volume Fan Speed", + "description": "Build-volume fan speed until 'Build Volume Fan Speed at Layer'.", + "unit": "%", + "type": "float", + "minimum_value": "0", + "maximum_value": "100", + "default_value": 0, + "value": "0.0", + "enabled": "build_volume_fan_nr != 0", + "settable_per_mesh": false, + "settable_per_extruder": false, + "settable_per_meshgroup": false + }, + "build_volume_fan_speed": + { + "label": "Build Volume Fan Speed", + "description": "Build-volume fan speed starting from 'Build Volume Fan Speed at Layer'.", + "unit": "%", + "type": "float", + "minimum_value": "0", + "maximum_value": "100", + "default_value": 100, + "value": "100.0", + "enabled": "build_volume_fan_nr != 0", + "settable_per_mesh": false, + "settable_per_extruder": false, + "settable_per_meshgroup": false + }, "cool_fan_speed": { "label": "Fan Speed", From 22971f984bf4ad9239fc7f719be493b9ba3d4b8c Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 29 Apr 2025 13:58:56 +0200 Subject: [PATCH 114/299] Update description Build _Volume_ Fan. 'Build Fan' doesn't make that much sense. done as part of CURA-12512 --- resources/definitions/fdmprinter.def.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 44c0573083..5b19af0609 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -4855,7 +4855,7 @@ }, "build_fan_full_at_height": { - "label": "Build Fan Speed at Height", + "label": "Build Volume Fan Speed at Height", "description": "The height at which the fans spin on regular fan speed. At the layers below the fan speed gradually increases from Initial Fan Speed to Regular Fan Speed.", "unit": "mm", "type": "float", @@ -4870,8 +4870,8 @@ { "build_fan_full_layer": { - "label": "Build Fan Speed at Layer", - "description": "The layer at which the build fans spin on full fan speed. This value is calculated and rounded to a whole number.", + "label": "Build Volume Fan Speed at Layer", + "description": "The layer at which the build-volume fans spin on full fan speed. This value is calculated and rounded to a whole number.", "type": "int", "default_value": 0, "minimum_value": "0", From 8a2cbb67521a6e304295739d05cd6ac23f6ebd24 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 29 Apr 2025 15:21:47 +0200 Subject: [PATCH 115/299] Fix wrong used settings CURA-12057 --- resources/definitions/bambulab_base.def.json | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/resources/definitions/bambulab_base.def.json b/resources/definitions/bambulab_base.def.json index fb6c9e3208..327e241722 100644 --- a/resources/definitions/bambulab_base.def.json +++ b/resources/definitions/bambulab_base.def.json @@ -177,11 +177,7 @@ "maximum_value_warning": 500, "value": "speed_wall" }, - "speed_skirt_brim": - { - "maximum_value_warning": 500, - "value": "speed_layer_0" - }, + "skirt_brim_speed": { "maximum_value_warning": 500 }, "speed_support": { "maximum_value_warning": 500, @@ -248,7 +244,6 @@ "value": "speed_wall" }, "support_brim_line_count": { "value": 5 }, - "support_density": { "value": 15 }, "support_infill_rate": { "value": "80 if gradual_support_infill_steps != 0 else 15" }, "support_pattern": { "value": "'gyroid'" }, "support_structure": { "value": "'tree'" }, From d1a31b4e5bc7eb4bc3f99f1f0d9182e505f93232 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 29 Apr 2025 15:45:10 +0200 Subject: [PATCH 116/299] Move printer specific settings to global definition CURA-12101 There is a specific unit test that disallows custom settings in printer definitions, so this looks like the proper way of doing it. New settings are disabled by default so should be visible only for the printer that explicitly sets them enabled. --- resources/definitions/bambulab_base.def.json | 24 +----------------- resources/definitions/bambulab_x1.def.json | 26 ++++---------------- resources/definitions/fdmprinter.def.json | 25 +++++++++++++++++++ 3 files changed, 31 insertions(+), 44 deletions(-) diff --git a/resources/definitions/bambulab_base.def.json b/resources/definitions/bambulab_base.def.json index 327e241722..6ec11243ee 100644 --- a/resources/definitions/bambulab_base.def.json +++ b/resources/definitions/bambulab_base.def.json @@ -117,6 +117,7 @@ "default_value": 500, "enabled": "not prime_tower_enable" }, + "material_max_flowrate": { "enabled": true }, "max_skin_angle_for_expansion": { "value": 45 }, "meshfix_maximum_resolution": { "value": 0.4 }, "min_infill_area": { "default_value": 10 }, @@ -262,28 +263,5 @@ "z_seam_corner": { "value": "'z_seam_corner_weighted'" }, "z_seam_position": { "value": "'backright'" }, "z_seam_type": { "value": "'sharpest_corner'" } - }, - "settings": - { - "material": - { - "children": - { - "material_max_flowrate": - { - "default_value": 16, - "description": "Maximum flowrate that the printer can extrude for the material", - "enabled": true, - "label": "Material Maximum Flowrate", - "maximum_value": "machine_max_feedrate_e * (material_diameter/2)**2 * math.pi", - "minimum_value": "0", - "settable_per_extruder": true, - "settable_per_mesh": false, - "type": "float", - "unit": "mm\u00b3/s", - "value": "16" - } - } - } } } \ No newline at end of file diff --git a/resources/definitions/bambulab_x1.def.json b/resources/definitions/bambulab_x1.def.json index 78a9b38131..b1da4f5c73 100644 --- a/resources/definitions/bambulab_x1.def.json +++ b/resources/definitions/bambulab_x1.def.json @@ -45,30 +45,14 @@ "machine_extruder_count": { "value": 4 }, "machine_height": { "value": 251 }, "machine_name": { "default_value": "BambuLab Bambu X1" }, + "machine_scan_first_layer": + { + "enabled": true, + "value": "machine_buildplate_type!='textured_pei_plate'" + }, "machine_start_gcode": { "default_value": ";===== machine: X1 ====================\n;===== date: 20241023 ==================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z0 ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_bed_temperature_layer_0} ;wait for bed temp\n\n{if machine_scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if material_type=='PLA' and (material_bed_temperature_layer_0>45 or material_bed_temperature>45), initial_extruder_nr}\n M106 P3 S180\n M142 P1 R35 S40\n{endif}\n{if material_type=='PLA' and (material_bed_temperature_layer_0<=45 and material_bed_temperature<=45) , initial_extruder_nr}\n M142 P1 R35 S40\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S{initial_extruder_nr}A ; switch material if AMS exist\n M109 S{material_print_temperature_layer_0, initial_extruder_nr}\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T{initial_extruder_nr}\n G1 X54 F12000\n G1 Y265\n M400\nM621 S{initial_extruder_nr}A\nM620.1 E F{material_max_flowrate/2.4053*60, initial_extruder_nr} T{material_print_temperature, initial_extruder_nr}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S{material_print_temperature_layer_0, initial_extruder_nr}\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{material_print_temperature_layer_0-20, initial_extruder_nr}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{-machine_width/2 if machine_center_is_zero else 0} Y{-machine_depth/2 if machine_center_is_zero else 0} I{machine_width} J{machine_depth}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if material_type=='PLA' and (material_bed_temperature_layer_0>45 or material_bed_temperature>45), initial_extruder_nr}\n M106 P3 S180\n M142 P1 R35 S40\n{endif}\n{if material_type=='PLA' and (material_bed_temperature_layer_0<=45 and material_bed_temperature<=45) , initial_extruder_nr}\n M142 P1 R35 S40\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{material_print_temperature_layer_0, initial_extruder_nr} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if machine_scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{material_print_temperature, initial_extruder_nr}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y11 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if machine_buildplate_type=='textured_pei_plate'}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if acceleration_print > 0 and acceleration_wall_0 > 0, initial_extruder_nr}\n M204 S{acceleration_wall_0, initial_extruder_nr}\n {endif}\n {if acceleration_print > 0 and acceleration_wall_0 <= 0, initial_extruder_nr}\n M204 S{acceleration_print, initial_extruder_nr}\n {endif}\n\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.160\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.080\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of 'draw extrinsic para cali paint'\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{material_print_temperature, initial_extruder_nr} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60/4, initial_extruder_nr} C5.000 D{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*60, initial_extruder_nr} E5.000 F175.000 H1.000 I0.000 J0.080 K0.160\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{material_print_temperature, initial_extruder_nr}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X70.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X75.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X80.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X85.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X90.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X95.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X100.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X105.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X110.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X115.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X120.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X125.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X130.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X135.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.08 M{speed_wall_0*wall_line_width_0*layer_height/(1.75*1.75/4*3.14)*0.08, initial_extruder_nr}\n M623\n\n G1 X140.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X145.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X150.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X155.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X160.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X165.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X170.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X175.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X180.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X185.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X190.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X195.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X200.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X205.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X210.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X215.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n G1 X220.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/ 4 * 60, initial_extruder_nr}\n G1 X225.000 E0.31181 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n;===== purge line to wipe the nozzle ============================\nG1 E{-retraction_amount, initial_extruder_nr} F1800\nG1 X18.0 Y2.5 Z0.8 F18000.0;Move to start position\nG1 E{retraction_amount, initial_extruder_nr} F1800\nM109 S{material_print_temperature_layer_0, initial_extruder_nr}\nG1 Z0.2\nG0 X239 E15 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5) * 60, initial_extruder_nr}\nG0 Y12 E0.7 F{speed_wall_0*wall_line_width_0*layer_height/(0.3*0.5)/4* 60, initial_extruder_nr}\n" }, "machine_width": { "value": 256 }, "prime_tower_position_x": { "value": "resolveOrValue('prime_tower_size') + (resolveOrValue('prime_tower_base_size') if (resolveOrValue('adhesion_type') == 'raft' or resolveOrValue('prime_tower_brim_enable')) else 0) + max(max(extruderValues('travel_avoid_distance')) + max(extruderValues('machine_nozzle_offset_y')) + max(extruderValues('support_offset')) + (extruderValue(skirt_brim_extruder_nr, 'skirt_brim_line_width') * extruderValue(skirt_brim_extruder_nr, 'skirt_line_count') * extruderValue(skirt_brim_extruder_nr, 'initial_layer_line_width_factor') / 100 + extruderValue(skirt_brim_extruder_nr, 'skirt_gap') if resolveOrValue('adhesion_type') == 'skirt' else 0) + (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0), max(map(abs, extruderValues('machine_nozzle_offset_y'))), 1) - (resolveOrValue('machine_depth') / 2 if resolveOrValue('machine_center_is_zero') else 0)" }, "travel_avoid_distance": { "value": "3" } - }, - "settings": - { - "platform_adhesion": - { - "children": - { - "machine_scan_first_layer": - { - "default_value": true, - "description": "Whether to scan the first layer for layer adhesion problems.", - "enabled": true, - "label": "Scan the first layer", - "settable_per_extruder": false, - "settable_per_mesh": false, - "settable_per_meshgroup": false, - "type": "bool", - "value": "machine_buildplate_type!='textured_pei_plate'" - } - } - } } } \ No newline at end of file diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 1dec529416..0f2f3520b2 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3377,6 +3377,20 @@ "settable_per_mesh": false, "settable_per_extruder": true, "settable_per_meshgroup": false + }, + "material_max_flowrate": + { + "default_value": 16, + "description": "Maximum flow rate that the printer can extrude for the material", + "enabled": false, + "label": "Material Maximum Flow Rate", + "maximum_value": "machine_max_feedrate_e * (material_diameter/2)**2 * math.pi", + "minimum_value": "0", + "settable_per_extruder": true, + "settable_per_mesh": false, + "type": "float", + "unit": "mm\u00b3/s", + "value": "16" } } }, @@ -7466,6 +7480,17 @@ "limit_to_extruder": "raft_surface_extruder_nr" } } + }, + "machine_scan_first_layer": + { + "default_value": false, + "description": "Whether to scan the first layer for layer adhesion problems.", + "enabled": false, + "label": "Scan the first layer", + "settable_per_extruder": false, + "settable_per_mesh": false, + "settable_per_meshgroup": false, + "type": "bool" } } }, From aefa40d386f8b4ba16d979ac82ea5df9107227ec Mon Sep 17 00:00:00 2001 From: wawanbreton <601114+wawanbreton@users.noreply.github.com> Date: Tue, 29 Apr 2025 13:51:29 +0000 Subject: [PATCH 117/299] Apply printer-linter format --- resources/definitions/bambulab_base.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/bambulab_base.def.json b/resources/definitions/bambulab_base.def.json index 6ec11243ee..a28e606a38 100644 --- a/resources/definitions/bambulab_base.def.json +++ b/resources/definitions/bambulab_base.def.json @@ -140,6 +140,7 @@ "skin_material_flow": { "value": 95 }, "skin_overlap": { "value": 0 }, "skin_preshrink": { "value": 0 }, + "skirt_brim_speed": { "maximum_value_warning": 500 }, "skirt_line_count": { "value": 5 }, "small_skin_on_surface": { "value": false }, "small_skin_width": { "value": 4 }, @@ -178,7 +179,6 @@ "maximum_value_warning": 500, "value": "speed_wall" }, - "skirt_brim_speed": { "maximum_value_warning": 500 }, "speed_support": { "maximum_value_warning": 500, From 3fecc27720cba753da7e0f1b77a55b8bac8b4f35 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 30 Apr 2025 08:09:17 +0200 Subject: [PATCH 118/299] Update build-volume fan-speed descriptions. part of CURA-12512 --- resources/definitions/fdmprinter.def.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 5b19af0609..d973b71ab3 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -4887,13 +4887,12 @@ "build_volume_fan_speed_0": { "label": "Initial Layers Build Volume Fan Speed", - "description": "Build-volume fan speed until 'Build Volume Fan Speed at Layer'.", + "description": "The fan speed (as a percentage) for the auxiliary or build-volume fan, that is set until the layer specified at 'Build Volume Fan Speed at Layer' is reached. After that, the speed is set by 'Build Volume Fan Speed' instead (so not this 'Initial Layers' one).", "unit": "%", "type": "float", "minimum_value": "0", "maximum_value": "100", "default_value": 0, - "value": "0.0", "enabled": "build_volume_fan_nr != 0", "settable_per_mesh": false, "settable_per_extruder": false, @@ -4902,13 +4901,12 @@ "build_volume_fan_speed": { "label": "Build Volume Fan Speed", - "description": "Build-volume fan speed starting from 'Build Volume Fan Speed at Layer'.", + "description": "The fan speed (as a percentage) for the auxiliary or build-volume fan, that is set from the moment that the layer specified at 'Build Volume Fan Speed at Layer' is reached and onwards. Before that, the speed is set by 'Initial Layers Build Volume Fan Speed' instead.", "unit": "%", "type": "float", "minimum_value": "0", "maximum_value": "100", "default_value": 100, - "value": "100.0", "enabled": "build_volume_fan_nr != 0", "settable_per_mesh": false, "settable_per_extruder": false, From 4e1a11c729711d913a88b9f204b1abccc07f7d0a Mon Sep 17 00:00:00 2001 From: Mariska <40423138+MariMakes@users.noreply.github.com> Date: Thu, 1 May 2025 13:25:11 +0200 Subject: [PATCH 119/299] Update SlicingCrash.yaml Add reference to meshtools plugin --- .github/ISSUE_TEMPLATE/SlicingCrash.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/SlicingCrash.yaml b/.github/ISSUE_TEMPLATE/SlicingCrash.yaml index 78f9556915..dddd0f8827 100644 --- a/.github/ISSUE_TEMPLATE/SlicingCrash.yaml +++ b/.github/ISSUE_TEMPLATE/SlicingCrash.yaml @@ -8,7 +8,8 @@ body: ### ✨Are you stuck? Have you tried these two things? ✨ 1- Are you on a Cura version lower than Cura 5.7? We really recommend updating because it resolves a lot of slicing crashes! 2- Have you tried fixing the model with software that repairs 3d files and makes them watertight? - Are you seeing spots and dots on your model? That is Cura indicating that your model is not watertight. + Are you seeing spots and dots on your model? That is Cura indicating that your model is not watertight. + You can try doing a quick [Mesh Fix with the Meshtools Plugin](https://marketplace.ultimaker.com/app/cura/plugins/fieldofview/MeshTools) or other mesh editing software. If you still encounter a crash you are welcome to report the issue so we can use your model as a test case. You can find instructions on how to share your model in a Package for Technical Support below. From ba5795eb7487612a8d8594a70ad14408488b0d94 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Fri, 2 May 2025 10:09:02 +0200 Subject: [PATCH 120/299] Limit extruders for MVP --- resources/definitions/bambulab_x1.def.json | 2 +- .../bambu/bambulab_x1c_0.4_PLA_standard.inst.cfg | 14 -------------- resources/variants/bambu/bambulab_p1p_0.4.inst.cfg | 13 ------------- resources/variants/bambu/bambulab_p1s_0.4.inst.cfg | 13 ------------- resources/variants/bambu/bambulab_x1c_0.4.inst.cfg | 13 ------------- 5 files changed, 1 insertion(+), 54 deletions(-) delete mode 100644 resources/quality/bambu/bambulab_x1c_0.4_PLA_standard.inst.cfg delete mode 100644 resources/variants/bambu/bambulab_p1p_0.4.inst.cfg delete mode 100644 resources/variants/bambu/bambulab_p1s_0.4.inst.cfg delete mode 100644 resources/variants/bambu/bambulab_x1c_0.4.inst.cfg diff --git a/resources/definitions/bambulab_x1.def.json b/resources/definitions/bambulab_x1.def.json index b1da4f5c73..0c6d223e1a 100644 --- a/resources/definitions/bambulab_x1.def.json +++ b/resources/definitions/bambulab_x1.def.json @@ -24,7 +24,7 @@ 130 ], "platform_texture": "bambulab-buildplate.png", - "preferred_variant_name": "X1C 0.4mm", + "preferred_variant_name": "X1 0.4mm", "weight": 3 }, "overrides": diff --git a/resources/quality/bambu/bambulab_x1c_0.4_PLA_standard.inst.cfg b/resources/quality/bambu/bambulab_x1c_0.4_PLA_standard.inst.cfg deleted file mode 100644 index 7fa47f0f52..0000000000 --- a/resources/quality/bambu/bambulab_x1c_0.4_PLA_standard.inst.cfg +++ /dev/null @@ -1,14 +0,0 @@ -[general] -definition = bambulab_x1 -name = Standard -version = 4 - -[metadata] -material = generic_pla -quality_type = normal -setting_version = 25 -type = quality -variant = X1C 0.4mm - -[values] - diff --git a/resources/variants/bambu/bambulab_p1p_0.4.inst.cfg b/resources/variants/bambu/bambulab_p1p_0.4.inst.cfg deleted file mode 100644 index d18e04731e..0000000000 --- a/resources/variants/bambu/bambulab_p1p_0.4.inst.cfg +++ /dev/null @@ -1,13 +0,0 @@ -[general] -definition = bambulab_x1 -name = P1P 0.4mm -version = 4 - -[metadata] -hardware_type = nozzle -setting_version = 25 -type = variant - -[values] -machine_nozzle_size = 0.4 - diff --git a/resources/variants/bambu/bambulab_p1s_0.4.inst.cfg b/resources/variants/bambu/bambulab_p1s_0.4.inst.cfg deleted file mode 100644 index d18e04731e..0000000000 --- a/resources/variants/bambu/bambulab_p1s_0.4.inst.cfg +++ /dev/null @@ -1,13 +0,0 @@ -[general] -definition = bambulab_x1 -name = P1P 0.4mm -version = 4 - -[metadata] -hardware_type = nozzle -setting_version = 25 -type = variant - -[values] -machine_nozzle_size = 0.4 - diff --git a/resources/variants/bambu/bambulab_x1c_0.4.inst.cfg b/resources/variants/bambu/bambulab_x1c_0.4.inst.cfg deleted file mode 100644 index 1a82636741..0000000000 --- a/resources/variants/bambu/bambulab_x1c_0.4.inst.cfg +++ /dev/null @@ -1,13 +0,0 @@ -[general] -definition = bambulab_x1 -name = X1C 0.4mm -version = 4 - -[metadata] -hardware_type = nozzle -setting_version = 25 -type = variant - -[values] -machine_nozzle_size = 0.4 - From b0f175bd5a4eca4b81a13949e58d666886c4a450 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 13 May 2025 08:29:30 +0200 Subject: [PATCH 121/299] Add missing error-handling. There was error handling for the url-request, but not for handling the subsequent resolution. --- cura/CuraApplication.py | 57 ++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 87657af5f5..8af98c2d0e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1895,36 +1895,39 @@ class CuraApplication(QtApplication): query = QUrlQuery(url.query()) model_url = QUrl(query.queryItemValue("file", options=QUrl.ComponentFormattingOption.FullyDecoded)) - def on_finish(response): - content_disposition_header_key = QByteArray("content-disposition".encode()) - - filename = model_url.path().split("/")[-1] + ".stl" - - if response.hasRawHeader(content_disposition_header_key): - # content_disposition is in the format - # ``` - # content_disposition attachment; filename="[FILENAME]" - # ``` - # Use a regex to extract the filename - content_disposition = str(response.rawHeader(content_disposition_header_key).data(), - encoding='utf-8') - content_disposition_match = re.match(r'attachment; filename=(?P.*)', - content_disposition) - if content_disposition_match is not None: - filename = content_disposition_match.group("filename").strip("\"") - - tmp = tempfile.NamedTemporaryFile(suffix=filename, delete=False) - with open(tmp.name, "wb") as f: - f.write(response.readAll()) - - self.readLocalFile(QUrl.fromLocalFile(tmp.name), add_to_recent_files=False) - def on_error(*args, **kwargs): - Logger.log("w", "Could not download file from {0}".format(model_url.url())) - Message("Could not download file: " + str(model_url.url()), + Logger.warning(f"Could not download file from {model_url.url()}") + Message(f"Could not download file: {str(model_url.url())}", title= "Loading Model failed", message_type=Message.MessageType.ERROR).show() - return + + def on_finish(response): + try: + content_disposition_header_key = QByteArray("content-disposition".encode()) + + filename = model_url.path().split("/")[-1] + ".stl" + + if response.hasRawHeader(content_disposition_header_key): + # content_disposition is in the format + # ``` + # content_disposition attachment; filename="[FILENAME]" + # ``` + # Use a regex to extract the filename + content_disposition = str(response.rawHeader(content_disposition_header_key).data(), + encoding='utf-8') + content_disposition_match = re.match(r'attachment; filename=(?P.*)', + content_disposition) + if content_disposition_match is not None: + filename = content_disposition_match.group("filename").strip("\"") + + tmp = tempfile.NamedTemporaryFile(suffix=filename, delete=False) + with open(tmp.name, "wb") as f: + f.write(response.readAll()) + + self.readLocalFile(QUrl.fromLocalFile(tmp.name), add_to_recent_files=False) + except Exception as ex: + Logger.warning(f"Exception {str(ex)}") + on_error() self.getHttpRequestManager().get( model_url.url(), From 93694e2da4090103ce121621efd0fa0a6b978882 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 20 May 2025 15:51:13 +0200 Subject: [PATCH 122/299] W.I.P.: Add paint-shader/layer so it can be used for the UV-painting feature. Currently replacing the 'disabled' batch until we can get it to switch out on command (when we have the painting stage/tool/... pluging up and running. part of CURA-12543 --- plugins/SolidView/SolidView.py | 27 +++++-- resources/shaders/paint.shader | 142 +++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 6 deletions(-) create mode 100644 resources/shaders/paint.shader diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index 7f32b0df7f..1f2dabdbdd 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -1,13 +1,12 @@ # Copyright (c) 2021 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -import os.path from UM.View.View import View from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.Selection import Selection from UM.Resources import Resources -from PyQt6.QtGui import QOpenGLContext, QDesktopServices, QImage -from PyQt6.QtCore import QSize, QUrl +from PyQt6.QtGui import QDesktopServices, QImage +from PyQt6.QtCore import QUrl import numpy as np import time @@ -36,16 +35,20 @@ class SolidView(View): """Standard view for mesh models.""" _show_xray_warning_preference = "view/show_xray_warning" + _show_overhang_preference = "view/show_overhang" + _paint_active_preference = "view/paint_active" def __init__(self): super().__init__() application = Application.getInstance() - application.getPreferences().addPreference("view/show_overhang", True) + application.getPreferences().addPreference(self._show_overhang_preference, True) + application.getPreferences().addPreference(self._paint_active_preference, False) application.globalContainerStackChanged.connect(self._onGlobalContainerChanged) self._enabled_shader = None self._disabled_shader = None self._non_printing_shader = None self._support_mesh_shader = None + self._paint_shader = None self._xray_shader = None self._xray_pass = None @@ -139,6 +142,11 @@ class SolidView(View): min_height = max(min_height, init_layer_height) return min_height + def _setPaintTexture(self): + self._paint_texture = OpenGL.getInstance().createTexture(256, 256) + if self._paint_shader: + self._paint_shader.setTexture(0, self._paint_texture) + def _checkSetup(self): if not self._extruders_model: self._extruders_model = Application.getInstance().getExtrudersModel() @@ -167,6 +175,10 @@ class SolidView(View): self._support_mesh_shader.setUniformValue("u_vertical_stripes", True) self._support_mesh_shader.setUniformValue("u_width", 5.0) + if not self._paint_shader: + self._paint_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "paint.shader")) + self._setPaintTexture() + if not Application.getInstance().getPreferences().getValue(self._show_xray_warning_preference): self._xray_shader = None self._xray_composite_shader = None @@ -204,6 +216,9 @@ class SolidView(View): self._old_composite_shader = self._composite_pass.getCompositeShader() self._composite_pass.setCompositeShader(self._xray_composite_shader) + def setUvPixel(self, x, y, color): + self._paint_texture.setPixel(x, y, color) + def beginRendering(self): scene = self.getController().getScene() renderer = self.getRenderer() @@ -212,7 +227,7 @@ class SolidView(View): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: - if Application.getInstance().getPreferences().getValue("view/show_overhang"): + if Application.getInstance().getPreferences().getValue(self._show_overhang_preference): # Make sure the overhang angle is valid before passing it to the shader if self._support_angle >= 0 and self._support_angle <= 90: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(90 - self._support_angle))) @@ -221,7 +236,7 @@ class SolidView(View): else: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) self._enabled_shader.setUniformValue("u_lowestPrintableHeight", self._lowest_printable_height) - disabled_batch = renderer.createRenderBatch(shader = self._disabled_shader) + disabled_batch = renderer.createRenderBatch(shader = self._paint_shader) #### TODO: put back to 'self._disabled_shader' normal_object_batch = renderer.createRenderBatch(shader = self._enabled_shader) renderer.addRenderBatch(disabled_batch) renderer.addRenderBatch(normal_object_batch) diff --git a/resources/shaders/paint.shader b/resources/shaders/paint.shader new file mode 100644 index 0000000000..83682c7222 --- /dev/null +++ b/resources/shaders/paint.shader @@ -0,0 +1,142 @@ +[shaders] +vertex = + uniform highp mat4 u_modelMatrix; + uniform highp mat4 u_viewMatrix; + uniform highp mat4 u_projectionMatrix; + + uniform highp mat4 u_normalMatrix; + + attribute highp vec4 a_vertex; + attribute highp vec4 a_normal; + attribute highp vec2 a_uvs; + + varying highp vec3 v_vertex; + varying highp vec3 v_normal; + varying highp vec2 v_uvs; + + void main() + { + vec4 world_space_vert = u_modelMatrix * a_vertex; + gl_Position = u_projectionMatrix * u_viewMatrix * world_space_vert; + + v_vertex = world_space_vert.xyz; + v_normal = (u_normalMatrix * normalize(a_normal)).xyz; + + v_uvs = a_uvs; + } + +fragment = + uniform mediump vec4 u_ambientColor; + uniform mediump vec4 u_diffuseColor; + uniform highp vec3 u_lightPosition; + uniform highp vec3 u_viewPosition; + uniform mediump float u_opacity; + uniform sampler2D u_texture; + + varying highp vec3 v_vertex; + varying highp vec3 v_normal; + varying highp vec2 v_uvs; + + void main() + { + mediump vec4 final_color = vec4(0.0); + + /* Ambient Component */ + final_color += u_ambientColor; + + highp vec3 normal = normalize(v_normal); + highp vec3 light_dir = normalize(u_lightPosition - v_vertex); + + /* Diffuse Component */ + highp float n_dot_l = clamp(dot(normal, light_dir), 0.0, 1.0); + final_color += (n_dot_l * u_diffuseColor); + + final_color.a = u_opacity; + + lowp vec4 texture = texture2D(u_texture, v_uvs); + final_color = mix(final_color, texture, texture.a); + + gl_FragColor = final_color; + } + +vertex41core = + #version 410 + uniform highp mat4 u_modelMatrix; + uniform highp mat4 u_viewMatrix; + uniform highp mat4 u_projectionMatrix; + + uniform highp mat4 u_normalMatrix; + + in highp vec4 a_vertex; + in highp vec4 a_normal; + in highp vec2 a_uvs; + + out highp vec3 v_vertex; + out highp vec3 v_normal; + out highp vec2 v_uvs; + + void main() + { + vec4 world_space_vert = u_modelMatrix * a_vertex; + gl_Position = u_projectionMatrix * u_viewMatrix * world_space_vert; + + v_vertex = world_space_vert.xyz; + v_normal = (u_normalMatrix * normalize(a_normal)).xyz; + + v_uvs = a_uvs; + } + +fragment41core = + #version 410 + uniform mediump vec4 u_ambientColor; + uniform mediump vec4 u_diffuseColor; + uniform highp vec3 u_lightPosition; + uniform highp vec3 u_viewPosition; + uniform mediump float u_opacity; + uniform sampler2D u_texture; + + in highp vec3 v_vertex; + in highp vec3 v_normal; + in highp vec2 v_uvs; + out vec4 frag_color; + + void main() + { + mediump vec4 final_color = vec4(0.0); + + /* Ambient Component */ + final_color += u_ambientColor; + + highp vec3 normal = normalize(v_normal); + highp vec3 light_dir = normalize(u_lightPosition - v_vertex); + + /* Diffuse Component */ + highp float n_dot_l = clamp(dot(normal, light_dir), 0.0, 1.0); + final_color += (n_dot_l * u_diffuseColor); + + final_color.a = u_opacity; + + lowp vec4 texture = texture(u_texture, v_uvs); + final_color = mix(final_color, texture, texture.a); + + frag_color = final_color; + } + +[defaults] +u_ambientColor = [0.3, 0.3, 0.3, 1.0] +u_diffuseColor = [1.0, 1.0, 1.0, 1.0] +u_opacity = 0.5 +u_texture = 0 + +[bindings] +u_modelMatrix = model_matrix +u_viewMatrix = view_matrix +u_projectionMatrix = projection_matrix +u_normalMatrix = normal_matrix +u_lightPosition = light_0_position +u_viewPosition = camera_position + +[attributes] +a_vertex = vertex +a_normal = normal +a_uvs = uv0 From 19ea88a8ce474968b53b06f992cccd5964f58fd6 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 20 May 2025 15:56:21 +0200 Subject: [PATCH 123/299] W.I.P. Start of paint-tool plugin UX work. Should be able to paint pixels now if the tools is active, and the model loaded is with UV-coords (that rules out our current impl. of 3MF at the moment -- use OBJ instead), and you position the model outside of the build-plate so the paint-shadr that is temporarily replacing the 'disabled' one is showing. Will need a lot of extra features and optimizations still! part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 135 ++++++++++++++++++++++++++++++++ plugins/PaintTool/PaintTool.qml | 14 ++++ plugins/PaintTool/__init__.py | 21 +++++ plugins/PaintTool/plugin.json | 8 ++ 4 files changed, 178 insertions(+) create mode 100644 plugins/PaintTool/PaintTool.py create mode 100644 plugins/PaintTool/PaintTool.qml create mode 100644 plugins/PaintTool/__init__.py create mode 100644 plugins/PaintTool/plugin.json diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py new file mode 100644 index 0000000000..d7a70581fb --- /dev/null +++ b/plugins/PaintTool/PaintTool.py @@ -0,0 +1,135 @@ +# Copyright (c) 2025 UltiMaker +# Cura is released under the terms of the LGPLv3 or higher. + +from typing import cast, Optional + +import numpy +from PyQt6.QtCore import Qt + +from UM.Application import Application +from UM.Event import Event, MouseEvent, KeyEvent +from UM.Tool import Tool +from cura.PickingPass import PickingPass + + +class PaintTool(Tool): + """Provides the tool to paint meshes. + """ + + def __init__(self) -> None: + super().__init__() + + self._shortcut_key = Qt.Key.Key_P + + """ + # CURA-5966 Make sure to render whenever objects get selected/deselected. + Selection.selectionChanged.connect(self.propertyChanged) + """ + + @staticmethod + def _get_intersect_ratio_via_pt(a, pt, b, c): + # compute the intersection of (param) A - pt with (param) B - (param) C + + # compute unit vectors of directions of lines A and B + udir_a = a - pt + udir_a /= numpy.linalg.norm(udir_a) + udir_b = b - c + udir_b /= numpy.linalg.norm(udir_b) + + # find unit direction vector for line C, which is perpendicular to lines A and B + udir_res = numpy.cross(udir_b, udir_a) + udir_res /= numpy.linalg.norm(udir_res) + + # solve system of equations + rhs = b - a + lhs = numpy.array([udir_a, -udir_b, udir_res]).T + solved = numpy.linalg.solve(lhs, rhs) + + # get the ratio + intersect = ((a + solved[0] * udir_a) + (b + solved[1] * udir_b)) * 0.5 + return numpy.linalg.norm(pt - intersect) / numpy.linalg.norm(a - intersect) + + def event(self, event: Event) -> bool: + """Handle mouse and keyboard events. + + :param event: The event to handle. + :return: Whether this event has been caught by this tool (True) or should + be passed on (False). + """ + super().event(event) + + # Make sure the displayed values are updated if the bounding box of the selected mesh(es) changes + if event.type == Event.ToolActivateEvent: + return False + + if event.type == Event.ToolDeactivateEvent: + return False + + if event.type == Event.KeyPressEvent and cast(KeyEvent, event).key == KeyEvent.ShiftKey: + return False + + if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): + if MouseEvent.LeftButton not in cast(MouseEvent, event).buttons: + return False + if not self._selection_pass: + return False + + camera = self._controller.getScene().getActiveCamera() + if not camera: + return False + + evt = cast(MouseEvent, event) + + ppass = PickingPass(self._selection_pass._width, self._selection_pass._height) + ppass.render() + pt = ppass.getPickedPosition(evt.x, evt.y).getData() + + self._selection_pass._renderObjectsMode() # TODO: <- Fix this! + + node_id = self._selection_pass.getIdAtPosition(evt.x, evt.y) + if node_id is None: + return False + node = Application.getInstance().getController().getScene().findObject(node_id) + if node is None: + return False + + self._selection_pass._renderFacesMode() # TODO: <- Fix this! + + face_id = self._selection_pass.getFaceIdAtPosition(evt.x, evt.y) + if face_id < 0: + return False + + meshdata = node.getMeshDataTransformed() # TODO: <- don't forget to optimize, if the mesh hasn't changed (transforms) then it should be reused! + if not meshdata: + return False + + va, vb, vc = meshdata.getFaceNodes(face_id) + ta, tb, tc = node.getMeshData().getFaceUvCoords(face_id) + + # 'Weight' of each vertex that would produce point pt, so we can generate the texture coordinates from the uv ones of the vertices. + # See (also) https://mathworld.wolfram.com/BarycentricCoordinates.html + wa = PaintTool._get_intersect_ratio_via_pt(va, pt, vb, vc) + wb = PaintTool._get_intersect_ratio_via_pt(vb, pt, vc, va) + wc = PaintTool._get_intersect_ratio_via_pt(vc, pt, va, vb) + wt = wa + wb + wc + wa /= wt + wb /= wt + wc /= wt + texcoords = wa * ta + wb * tb + wc * tc + + solidview = Application.getInstance().getController().getActiveView() + if solidview.getPluginId() != "SolidView": + return False + + solidview.setUvPixel(texcoords[0], texcoords[1], [255, 128, 0, 255]) + + return True + + if event.type == Event.MouseMoveEvent: + evt = cast(MouseEvent, event) + return False #True + + if event.type == Event.MouseReleaseEvent: + return False #True + + return False diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml new file mode 100644 index 0000000000..2e634790c2 --- /dev/null +++ b/plugins/PaintTool/PaintTool.qml @@ -0,0 +1,14 @@ +// Copyright (c) 2025 UltiMaker +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 + +import UM 1.7 as UM + +Item +{ + id: base + width: childrenRect.width + height: childrenRect.height + UM.I18nCatalog { id: catalog; name: "cura"} +} diff --git a/plugins/PaintTool/__init__.py b/plugins/PaintTool/__init__.py new file mode 100644 index 0000000000..38eac5bc45 --- /dev/null +++ b/plugins/PaintTool/__init__.py @@ -0,0 +1,21 @@ +# Copyright (c) 2025 UltiMaker +# Cura is released under the terms of the LGPLv3 or higher. + +from . import PaintTool + +from UM.i18n import i18nCatalog +i18n_catalog = i18nCatalog("cura") + +def getMetaData(): + return { + "tool": { + "name": i18n_catalog.i18nc("@action:button", "Paint"), + "description": i18n_catalog.i18nc("@info:tooltip", "Paint Model"), + "icon": "Visual", + "tool_panel": "PaintTool.qml", + "weight": 0 + } + } + +def register(app): + return { "tool": PaintTool.PaintTool() } diff --git a/plugins/PaintTool/plugin.json b/plugins/PaintTool/plugin.json new file mode 100644 index 0000000000..2a55d677d2 --- /dev/null +++ b/plugins/PaintTool/plugin.json @@ -0,0 +1,8 @@ +{ + "name": "Paint Tools", + "author": "UltiMaker", + "version": "1.0.0", + "description": "Provides the paint tools.", + "api": 8, + "i18n-catalog": "cura" +} From c5592eea83ec188bf6a8f5956c304f22f7c396b5 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 21 May 2025 15:19:07 +0200 Subject: [PATCH 124/299] Slightly optimize and refactor the w.i.p. paint-tool. Just enought so that the truly ugly things are out of it. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 47 ++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index d7a70581fb..3ee94db1d9 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -8,6 +8,7 @@ from PyQt6.QtCore import Qt from UM.Application import Application from UM.Event import Event, MouseEvent, KeyEvent +from UM.Scene.Selection import Selection from UM.Tool import Tool from cura.PickingPass import PickingPass @@ -21,10 +22,9 @@ class PaintTool(Tool): self._shortcut_key = Qt.Key.Key_P - """ - # CURA-5966 Make sure to render whenever objects get selected/deselected. - Selection.selectionChanged.connect(self.propertyChanged) - """ + self._node_cache = None + self._mesh_transformed_cache = None + self._cache_dirty = True @staticmethod def _get_intersect_ratio_via_pt(a, pt, b, c): @@ -49,6 +49,9 @@ class PaintTool(Tool): intersect = ((a + solved[0] * udir_a) + (b + solved[1] * udir_b)) * 0.5 return numpy.linalg.norm(pt - intersect) / numpy.linalg.norm(a - intersect) + def _nodeTransformChanged(self, *args) -> None: + self._cache_dirty = True + def event(self, event: Event) -> bool: """Handle mouse and keyboard events. @@ -78,32 +81,33 @@ class PaintTool(Tool): if not camera: return False - evt = cast(MouseEvent, event) - - ppass = PickingPass(self._selection_pass._width, self._selection_pass._height) - ppass.render() - pt = ppass.getPickedPosition(evt.x, evt.y).getData() - - self._selection_pass._renderObjectsMode() # TODO: <- Fix this! - - node_id = self._selection_pass.getIdAtPosition(evt.x, evt.y) - if node_id is None: - return False - node = Application.getInstance().getController().getScene().findObject(node_id) + node = Selection.getAllSelectedObjects()[0] if node is None: return False - self._selection_pass._renderFacesMode() # TODO: <- Fix this! + if node != self._node_cache: + if self._node_cache is not None: + self._node_cache.transformationChanged.disconnect(self._nodeTransformChanged) + self._node_cache = node + self._node_cache.transformationChanged.connect(self._nodeTransformChanged) + if self._cache_dirty: + self._cache_dirty = False + self._mesh_transformed_cache = self._node_cache.getMeshDataTransformed() + if not self._mesh_transformed_cache: + return False + evt = cast(MouseEvent, event) + + self._selection_pass.renderFacesMode() face_id = self._selection_pass.getFaceIdAtPosition(evt.x, evt.y) if face_id < 0: return False - meshdata = node.getMeshDataTransformed() # TODO: <- don't forget to optimize, if the mesh hasn't changed (transforms) then it should be reused! - if not meshdata: - return False + ppass = PickingPass(camera.getViewportWidth(), camera.getViewportHeight()) + ppass.render() + pt = ppass.getPickedPosition(evt.x, evt.y).getData() - va, vb, vc = meshdata.getFaceNodes(face_id) + va, vb, vc = self._mesh_transformed_cache.getFaceNodes(face_id) ta, tb, tc = node.getMeshData().getFaceUvCoords(face_id) # 'Weight' of each vertex that would produce point pt, so we can generate the texture coordinates from the uv ones of the vertices. @@ -120,7 +124,6 @@ class PaintTool(Tool): solidview = Application.getInstance().getController().getActiveView() if solidview.getPluginId() != "SolidView": return False - solidview.setUvPixel(texcoords[0], texcoords[1], [255, 128, 0, 255]) return True From 3ae85e3e2aee73d60f068f0286c9720e71338d46 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 21 May 2025 21:50:17 +0200 Subject: [PATCH 125/299] Refactored paint-view into its own thing. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 18 +++++--- plugins/PaintTool/PaintView.py | 42 +++++++++++++++++++ plugins/PaintTool/__init__.py | 11 ++++- .../PaintTool}/paint.shader | 0 plugins/SolidView/SolidView.py | 16 +------ 5 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 plugins/PaintTool/PaintView.py rename {resources/shaders => plugins/PaintTool}/paint.shader (100%) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 3ee94db1d9..2d204ceff9 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -27,7 +27,7 @@ class PaintTool(Tool): self._cache_dirty = True @staticmethod - def _get_intersect_ratio_via_pt(a, pt, b, c): + def _get_intersect_ratio_via_pt(a, pt, b, c) -> float: # compute the intersection of (param) A - pt with (param) B - (param) C # compute unit vectors of directions of lines A and B @@ -61,12 +61,18 @@ class PaintTool(Tool): """ super().event(event) + controller = Application.getInstance().getController() + # Make sure the displayed values are updated if the bounding box of the selected mesh(es) changes if event.type == Event.ToolActivateEvent: - return False + controller.setActiveStage("PrepareStage") + controller.setActiveView("PaintTool") # Because that's the plugin-name, and the view is registered to it. + return True if event.type == Event.ToolDeactivateEvent: - return False + controller.setActiveStage("PrepareStage") + controller.setActiveView("SolidView") + return True if event.type == Event.KeyPressEvent and cast(KeyEvent, event).key == KeyEvent.ShiftKey: return False @@ -121,10 +127,10 @@ class PaintTool(Tool): wc /= wt texcoords = wa * ta + wb * tb + wc * tc - solidview = Application.getInstance().getController().getActiveView() - if solidview.getPluginId() != "SolidView": + paintview = controller.getActiveView() + if paintview.getPluginId() != "PaintTool": return False - solidview.setUvPixel(texcoords[0], texcoords[1], [255, 128, 0, 255]) + paintview.setUvPixel(texcoords[0], texcoords[1], [255, 128, 0, 255]) return True diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py new file mode 100644 index 0000000000..31a1a7f5f6 --- /dev/null +++ b/plugins/PaintTool/PaintView.py @@ -0,0 +1,42 @@ +# Copyright (c) 2025 UltiMaker +# Cura is released under the terms of the LGPLv3 or higher. +import os + +from UM.PluginRegistry import PluginRegistry +from UM.View.View import View +from UM.Scene.Selection import Selection +from UM.View.GL.OpenGL import OpenGL +from UM.i18n import i18nCatalog + +catalog = i18nCatalog("cura") + + +class PaintView(View): + """View for model-painting.""" + + def __init__(self) -> None: + super().__init__() + self._paint_shader = None + self._paint_texture = None + + def _checkSetup(self): + if not self._paint_shader: + shader_filename = os.path.join(PluginRegistry.getInstance().getPluginPath("PaintTool"), "paint.shader") + self._paint_shader = OpenGL.getInstance().createShaderProgram(shader_filename) + if not self._paint_texture: + self._paint_texture = OpenGL.getInstance().createTexture(256, 256) + self._paint_shader.setTexture(0, self._paint_texture) + + def setUvPixel(self, x, y, color) -> None: + self._paint_texture.setPixel(x, y, color) + + def beginRendering(self) -> None: + renderer = self.getRenderer() + self._checkSetup() + paint_batch = renderer.createRenderBatch(shader=self._paint_shader) + renderer.addRenderBatch(paint_batch) + + node = Selection.getAllSelectedObjects()[0] + if node is None: + return + paint_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix()) diff --git a/plugins/PaintTool/__init__.py b/plugins/PaintTool/__init__.py index 38eac5bc45..301bc49e0d 100644 --- a/plugins/PaintTool/__init__.py +++ b/plugins/PaintTool/__init__.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from . import PaintTool +from . import PaintView from UM.i18n import i18nCatalog i18n_catalog = i18nCatalog("cura") @@ -14,8 +15,16 @@ def getMetaData(): "icon": "Visual", "tool_panel": "PaintTool.qml", "weight": 0 + }, + "view": { + "name": i18n_catalog.i18nc("@item:inmenu", "Paint view"), + "weight": 0, + "visible": False } } def register(app): - return { "tool": PaintTool.PaintTool() } + return { + "tool": PaintTool.PaintTool(), + "view": PaintView.PaintView() + } diff --git a/resources/shaders/paint.shader b/plugins/PaintTool/paint.shader similarity index 100% rename from resources/shaders/paint.shader rename to plugins/PaintTool/paint.shader diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index 1f2dabdbdd..e115267720 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -42,13 +42,11 @@ class SolidView(View): super().__init__() application = Application.getInstance() application.getPreferences().addPreference(self._show_overhang_preference, True) - application.getPreferences().addPreference(self._paint_active_preference, False) application.globalContainerStackChanged.connect(self._onGlobalContainerChanged) self._enabled_shader = None self._disabled_shader = None self._non_printing_shader = None self._support_mesh_shader = None - self._paint_shader = None self._xray_shader = None self._xray_pass = None @@ -142,11 +140,6 @@ class SolidView(View): min_height = max(min_height, init_layer_height) return min_height - def _setPaintTexture(self): - self._paint_texture = OpenGL.getInstance().createTexture(256, 256) - if self._paint_shader: - self._paint_shader.setTexture(0, self._paint_texture) - def _checkSetup(self): if not self._extruders_model: self._extruders_model = Application.getInstance().getExtrudersModel() @@ -175,10 +168,6 @@ class SolidView(View): self._support_mesh_shader.setUniformValue("u_vertical_stripes", True) self._support_mesh_shader.setUniformValue("u_width", 5.0) - if not self._paint_shader: - self._paint_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "paint.shader")) - self._setPaintTexture() - if not Application.getInstance().getPreferences().getValue(self._show_xray_warning_preference): self._xray_shader = None self._xray_composite_shader = None @@ -216,9 +205,6 @@ class SolidView(View): self._old_composite_shader = self._composite_pass.getCompositeShader() self._composite_pass.setCompositeShader(self._xray_composite_shader) - def setUvPixel(self, x, y, color): - self._paint_texture.setPixel(x, y, color) - def beginRendering(self): scene = self.getController().getScene() renderer = self.getRenderer() @@ -236,7 +222,7 @@ class SolidView(View): else: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) self._enabled_shader.setUniformValue("u_lowestPrintableHeight", self._lowest_printable_height) - disabled_batch = renderer.createRenderBatch(shader = self._paint_shader) #### TODO: put back to 'self._disabled_shader' + disabled_batch = renderer.createRenderBatch(shader = self._disabled_shader) normal_object_batch = renderer.createRenderBatch(shader = self._enabled_shader) renderer.addRenderBatch(disabled_batch) renderer.addRenderBatch(normal_object_batch) From a176957fa7b0f7e57ff47c372fbbeb37ad1e8d95 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 22 May 2025 10:14:00 +0200 Subject: [PATCH 126/299] Painting: Set color, brush-size, brush-shape. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 48 ++++++++- plugins/PaintTool/PaintTool.qml | 168 +++++++++++++++++++++++++++++++- plugins/PaintTool/PaintView.py | 7 +- 3 files changed, 219 insertions(+), 4 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 2d204ceff9..5bd0c2187d 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -5,9 +5,11 @@ from typing import cast, Optional import numpy from PyQt6.QtCore import Qt +from typing import List, Tuple from UM.Application import Application from UM.Event import Event, MouseEvent, KeyEvent +from UM.Logger import Logger from UM.Scene.Selection import Selection from UM.Tool import Tool from cura.PickingPass import PickingPass @@ -26,6 +28,31 @@ class PaintTool(Tool): self._mesh_transformed_cache = None self._cache_dirty = True + self._color_str_to_rgba = { + "A": [192, 0, 192, 255], + "B": [232, 128, 0, 255], + "C": [0, 255, 0, 255], + "D": [255, 255, 255, 255], + } + + self._brush_size = 10 + self._brush_color = "A" + self._brush_shape = "A" + + def setPaintType(self, paint_type: str) -> None: + Logger.warning(f"TODO: Implement paint-types ({paint_type}).") + pass + + def setBrushSize(self, brush_size: float) -> None: + self._brush_size = int(brush_size) + print(self._brush_size) + + def setBrushColor(self, brush_color: str) -> None: + self._brush_color = brush_color + + def setBrushShape(self, brush_shape: str) -> None: + self._brush_shape = brush_shape + @staticmethod def _get_intersect_ratio_via_pt(a, pt, b, c) -> float: # compute the intersection of (param) A - pt with (param) B - (param) C @@ -52,6 +79,20 @@ class PaintTool(Tool): def _nodeTransformChanged(self, *args) -> None: self._cache_dirty = True + def _getBrushPixels(self, mid_x: float, mid_y: float, w: float, h: float) -> List[Tuple[float, float]]: + res = [] + include = False + for y in range(-self._brush_size, self._brush_size + 1): + for x in range(-self._brush_size, self._brush_size + 1): + match self._brush_shape: + case "A": + include = True + case "B": + include = x * x + y * y <= self._brush_size * self._brush_size + if include: + res.append((mid_x + (x / w), mid_y + (y / h))) + return res + def event(self, event: Event) -> bool: """Handle mouse and keyboard events. @@ -128,9 +169,12 @@ class PaintTool(Tool): texcoords = wa * ta + wb * tb + wc * tc paintview = controller.getActiveView() - if paintview.getPluginId() != "PaintTool": + if paintview is None or paintview.getPluginId() != "PaintTool": return False - paintview.setUvPixel(texcoords[0], texcoords[1], [255, 128, 0, 255]) + color = self._color_str_to_rgba[self._brush_color] + w, h = paintview.getUvTexDimensions() + for (x, y) in self._getBrushPixels(texcoords[0], texcoords[1], float(w), float(h)): + paintview.setUvPixel(x, y, color) return True diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index 2e634790c2..902d5a700d 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -1,7 +1,8 @@ // Copyright (c) 2025 UltiMaker // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 +import QtQuick +import QtQuick.Layouts import UM 1.7 as UM @@ -11,4 +12,169 @@ Item width: childrenRect.width height: childrenRect.height UM.I18nCatalog { id: catalog; name: "cura"} + + ColumnLayout + { + RowLayout + { + UM.ToolbarButton + { + id: paintTypeA + + text: catalog.i18nc("@action:button", "Paint Type A") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("Buildplate") + color: UM.Theme.getColor("icon") + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setPaintType", "A") + } + + UM.ToolbarButton + { + id: paintTypeB + + text: catalog.i18nc("@action:button", "Paint Type B") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("BlackMagic") + color: UM.Theme.getColor("icon") + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setPaintType", "B") + } + } + + RowLayout + { + UM.ToolbarButton + { + id: colorButtonA + + text: catalog.i18nc("@action:button", "Color A") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("Eye") + color: "purple" + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setBrushColor", "A") + } + + UM.ToolbarButton + { + id: colorButtonB + + text: catalog.i18nc("@action:button", "Color B") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("Eye") + color: "orange" + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setBrushColor", "B") + } + + UM.ToolbarButton + { + id: colorButtonC + + text: catalog.i18nc("@action:button", "Color C") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("Eye") + color: "green" + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setBrushColor", "C") + } + + UM.ToolbarButton + { + id: colorButtonD + + text: catalog.i18nc("@action:button", "Color D") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("Eye") + color: "ghostwhite" + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setBrushColor", "D") + } + } + + RowLayout + { + UM.ToolbarButton + { + id: shapeSquareButton + + text: catalog.i18nc("@action:button", "Square Brush") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("MeshTypeNormal") + color: UM.Theme.getColor("icon") + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setBrushShape", "A") + } + + UM.ToolbarButton + { + id: shapeCircleButton + + text: catalog.i18nc("@action:button", "Round Brush") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("CircleOutline") + color: UM.Theme.getColor("icon") + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("setBrushShape", "B") + } + + UM.Slider + { + id: shapeSizeSlider + + from: 1 + to: 50 + value: 10 + + onPressedChanged: function(pressed) + { + if(! pressed) + { + UM.Controller.triggerActionWithData("setBrushSize", shapeSizeSlider.value) + } + } + } + } + } } diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 31a1a7f5f6..0923d007d7 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -18,18 +18,23 @@ class PaintView(View): super().__init__() self._paint_shader = None self._paint_texture = None + self._tex_width = 256 + self._tex_height = 256 def _checkSetup(self): if not self._paint_shader: shader_filename = os.path.join(PluginRegistry.getInstance().getPluginPath("PaintTool"), "paint.shader") self._paint_shader = OpenGL.getInstance().createShaderProgram(shader_filename) if not self._paint_texture: - self._paint_texture = OpenGL.getInstance().createTexture(256, 256) + self._paint_texture = OpenGL.getInstance().createTexture(self._tex_width, self._tex_height) self._paint_shader.setTexture(0, self._paint_texture) def setUvPixel(self, x, y, color) -> None: self._paint_texture.setPixel(x, y, color) + def getUvTexDimensions(self): + return self._tex_width, self._tex_height + def beginRendering(self) -> None: renderer = self.getRenderer() self._checkSetup() From 33b5918acd65e2c14db5dd86893d3247b9932a5a Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 22 May 2025 11:02:08 +0200 Subject: [PATCH 127/299] Painting: Sort-of able to drag the mouse now, not just click. Also typing. The way it now works is way too slow though, and it doesn't add 'inbetween' the moude-move-positions yet. Also several other things of course. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 121 +++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 44 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 5bd0c2187d..bbcd80cef0 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -5,13 +5,15 @@ from typing import cast, Optional import numpy from PyQt6.QtCore import Qt -from typing import List, Tuple +from typing import Dict, List, Tuple from UM.Application import Application from UM.Event import Event, MouseEvent, KeyEvent from UM.Logger import Logger +from UM.Scene.SceneNode import SceneNode from UM.Scene.Selection import Selection from UM.Tool import Tool +from UM.View.View import View from cura.PickingPass import PickingPass @@ -22,22 +24,27 @@ class PaintTool(Tool): def __init__(self) -> None: super().__init__() - self._shortcut_key = Qt.Key.Key_P + self._picking_pass: Optional[PickingPass] = None - self._node_cache = None + self._shortcut_key: Qt.Key = Qt.Key.Key_P + + self._node_cache: Optional[SceneNode] = None self._mesh_transformed_cache = None - self._cache_dirty = True + self._cache_dirty: bool = True - self._color_str_to_rgba = { + self._color_str_to_rgba: Dict[str, List[int]] = { "A": [192, 0, 192, 255], "B": [232, 128, 0, 255], "C": [0, 255, 0, 255], "D": [255, 255, 255, 255], } - self._brush_size = 10 - self._brush_color = "A" - self._brush_shape = "A" + self._brush_size: int = 10 + self._brush_color: str = "A" + self._brush_shape: str = "A" + + self._mouse_held: bool = False + self._mouse_drags: List[Tuple[int, int]] = [] def setPaintType(self, paint_type: str) -> None: Logger.warning(f"TODO: Implement paint-types ({paint_type}).") @@ -54,7 +61,7 @@ class PaintTool(Tool): self._brush_shape = brush_shape @staticmethod - def _get_intersect_ratio_via_pt(a, pt, b, c) -> float: + def _get_intersect_ratio_via_pt(a: numpy.ndarray, pt: numpy.ndarray, b: numpy.ndarray, c: numpy.ndarray) -> float: # compute the intersection of (param) A - pt with (param) B - (param) C # compute unit vectors of directions of lines A and B @@ -90,9 +97,41 @@ class PaintTool(Tool): case "B": include = x * x + y * y <= self._brush_size * self._brush_size if include: - res.append((mid_x + (x / w), mid_y + (y / h))) + xx = mid_x + (x / w) + yy = mid_y + (y / h) + if xx < 0 or xx > 1 or yy < 0 or yy > 1: + continue + res.append((xx, yy)) return res + def _handleMouseAction(self, node: SceneNode, paintview: View, x: int, y: int) -> bool: + face_id = self._selection_pass.getFaceIdAtPosition(x, y) + if face_id < 0: + return False + + pt = self._picking_pass.getPickedPosition(x, y).getData() + + va, vb, vc = self._mesh_transformed_cache.getFaceNodes(face_id) + ta, tb, tc = node.getMeshData().getFaceUvCoords(face_id) + + # 'Weight' of each vertex that would produce point pt, so we can generate the texture coordinates from the uv ones of the vertices. + # See (also) https://mathworld.wolfram.com/BarycentricCoordinates.html + wa = PaintTool._get_intersect_ratio_via_pt(va, pt, vb, vc) + wb = PaintTool._get_intersect_ratio_via_pt(vb, pt, vc, va) + wc = PaintTool._get_intersect_ratio_via_pt(vc, pt, va, vb) + wt = wa + wb + wc + wa /= wt + wb /= wt + wc /= wt + texcoords = wa * ta + wb * tb + wc * tc + + color = self._color_str_to_rgba[self._brush_color] + w, h = paintview.getUvTexDimensions() + for (x, y) in self._getBrushPixels(texcoords[0], texcoords[1], float(w), float(h)): + paintview.setUvPixel(x, y, color) + + return True + def event(self, event: Event) -> bool: """Handle mouse and keyboard events. @@ -118,9 +157,18 @@ class PaintTool(Tool): if event.type == Event.KeyPressEvent and cast(KeyEvent, event).key == KeyEvent.ShiftKey: return False - if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): + if event.type == Event.MouseReleaseEvent and self._controller.getToolsEnabled(): if MouseEvent.LeftButton not in cast(MouseEvent, event).buttons: return False + + self._mouse_held = False + drags = self._mouse_drags.copy() + self._mouse_drags.clear() + + paintview = controller.getActiveView() + if paintview is None or paintview.getPluginId() != "PaintTool": + return False + if not self._selection_pass: return False @@ -144,45 +192,30 @@ class PaintTool(Tool): return False evt = cast(MouseEvent, event) + drags.append((evt.x, evt.y)) + + if not self._picking_pass: + self._picking_pass = PickingPass(camera.getViewportWidth(), camera.getViewportHeight()) + self._picking_pass.render() self._selection_pass.renderFacesMode() - face_id = self._selection_pass.getFaceIdAtPosition(evt.x, evt.y) - if face_id < 0: + + res = False + for (x, y) in drags: + res |= self._handleMouseAction(node, paintview, x, y) + return res + + if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): + if MouseEvent.LeftButton not in cast(MouseEvent, event).buttons: return False - - ppass = PickingPass(camera.getViewportWidth(), camera.getViewportHeight()) - ppass.render() - pt = ppass.getPickedPosition(evt.x, evt.y).getData() - - va, vb, vc = self._mesh_transformed_cache.getFaceNodes(face_id) - ta, tb, tc = node.getMeshData().getFaceUvCoords(face_id) - - # 'Weight' of each vertex that would produce point pt, so we can generate the texture coordinates from the uv ones of the vertices. - # See (also) https://mathworld.wolfram.com/BarycentricCoordinates.html - wa = PaintTool._get_intersect_ratio_via_pt(va, pt, vb, vc) - wb = PaintTool._get_intersect_ratio_via_pt(vb, pt, vc, va) - wc = PaintTool._get_intersect_ratio_via_pt(vc, pt, va, vb) - wt = wa + wb + wc - wa /= wt - wb /= wt - wc /= wt - texcoords = wa * ta + wb * tb + wc * tc - - paintview = controller.getActiveView() - if paintview is None or paintview.getPluginId() != "PaintTool": - return False - color = self._color_str_to_rgba[self._brush_color] - w, h = paintview.getUvTexDimensions() - for (x, y) in self._getBrushPixels(texcoords[0], texcoords[1], float(w), float(h)): - paintview.setUvPixel(x, y, color) - + self._mouse_held = True return True if event.type == Event.MouseMoveEvent: + if not self._mouse_held: + return False evt = cast(MouseEvent, event) - return False #True - - if event.type == Event.MouseReleaseEvent: - return False #True + self._mouse_drags.append((evt.x, evt.y)) + return True return False From 61523062178e53c99651a8f6787302dc9c7cf468 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Thu, 22 May 2025 12:12:42 -0400 Subject: [PATCH 128/299] Update DisplayInfoOnLCD.py Made some changes to the print stats that are added to the gcode. Update DisplayInfoOnLCD.py --- plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index e016bbd3d6..0e3b52c81f 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -647,7 +647,8 @@ class DisplayInfoOnLCD(Script): filament_line_t0 += f"; Filament Type: {global_stack.extruderList[0].material.getMetaDataEntry("material", "")}\n" filament_line_t0 += f"; Filament Dia.: {global_stack.extruderList[0].getProperty("material_diameter", "value")}mm\n" filament_line_t0 += f"; Nozzle Size : {global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")}mm\n" - filament_line_t0 += f"; Print Temp. : {global_stack.extruderList[0].getProperty("material_print_temperature", "value")}°" + filament_line_t0 += f"; Print Temp. : {global_stack.extruderList[0].getProperty("material_print_temperature", "value")}°\n" + filament_line_t0 += f"; Bed Temp. : {global_stack.extruderList[0].getProperty("material_bed_temperature", "value")}°" # if there is more than one extruder then get the stats for the second one. filament_line_t1 = "" @@ -668,6 +669,11 @@ class DisplayInfoOnLCD(Script): lines[index] += f"\n;Custom Quality Name: '{global_stack.qualityChanges.getMetaDataEntry("name")}'" if line.startswith(";Filament used"): lines[index] = filament_line_t0 + filament_line_t1 + # The target machine "machine_name" is actually the printer model. This adds the user defined printer name to the "TARGET_MACHINE" line. + if line.startswith(";TARGET_MACHINE"): + machine_model = str(global_stack.getProperty("machine_name", "value")) + machine_name = str(global_stack.getName()) + lines[index] += f" / {machine_name}" if "MINX" in line or "MIN.X" in line: # Add the Object List lines[index - 1] += f"\n;Model List: {str(model_list)}" From c726d610866ee142003635e0ab6b1733f31854c9 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 23 May 2025 10:07:02 +0200 Subject: [PATCH 129/299] Disable nightly builds They don't properly work since the conan2 migration, and it seems nobody is actually using them anymore, so deactivating them for now, and will reactivate when we have fixed the conan packages versions issues. --- .github/workflows/nightly-stable.yml | 8 ++++---- .github/workflows/nightly-testing.yml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/nightly-stable.yml b/.github/workflows/nightly-stable.yml index 1535daa415..2790947ae8 100644 --- a/.github/workflows/nightly-stable.yml +++ b/.github/workflows/nightly-stable.yml @@ -1,10 +1,10 @@ name: Nightly build - stable release run-name: Nightly build - stable release -on: - schedule: - # Daily at 5:15 CET - - cron: '15 4 * * *' +# on: +# schedule: +# # Daily at 5:15 CET +# - cron: '15 4 * * *' jobs: build-nightly: diff --git a/.github/workflows/nightly-testing.yml b/.github/workflows/nightly-testing.yml index c1ccb67f1c..13f3670514 100644 --- a/.github/workflows/nightly-testing.yml +++ b/.github/workflows/nightly-testing.yml @@ -1,10 +1,10 @@ name: Nightly build - dev release run-name: Nightly build - dev release -on: - schedule: - # Daily at 4:15 CET - - cron: '15 3 * * *' +# on: +# schedule: +# # Daily at 4:15 CET +# - cron: '15 3 * * *' jobs: build-nightly: From 86777ac666dd75bfa9a9ade7a3cdf671f4ec72ed Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 26 May 2025 11:52:53 +0200 Subject: [PATCH 130/299] Add new travel types and display z-hops CURA-11978 --- cura/LayerDataBuilder.py | 10 +- cura/LayerPolygon.py | 26 ++-- plugins/CuraEngineBackend/Cura.proto | 4 +- plugins/GCodeReader/FlavorParser.py | 17 ++- plugins/SimulationView/SimulationPass.py | 4 +- plugins/SimulationView/SimulationView.py | 6 +- plugins/SimulationView/layers.shader | 14 +- plugins/SimulationView/layers3d.shader | 67 +++++++--- plugins/SimulationView/layers3d_shadow.shader | 125 +++++++++++------- plugins/SimulationView/layers_shadow.shader | 10 +- resources/themes/cura-light/theme.json | 2 + 11 files changed, 181 insertions(+), 104 deletions(-) diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index d8801c9e7b..ff80307223 100755 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -80,9 +80,13 @@ class LayerDataBuilder(MeshBuilder): material_colors = numpy.zeros((line_dimensions.shape[0], 4), dtype=numpy.float32) for extruder_nr in range(material_color_map.shape[0]): material_colors[extruders == extruder_nr] = material_color_map[extruder_nr] - # Set material_colors with indices where line_types (also numpy array) == MoveCombingType - material_colors[line_types == LayerPolygon.MoveCombingType] = colors[line_types == LayerPolygon.MoveCombingType] - material_colors[line_types == LayerPolygon.MoveRetractionType] = colors[line_types == LayerPolygon.MoveRetractionType] + # Set material_colors with indices where line_types (also numpy array) == MoveUnretractedType + material_colors[line_types == LayerPolygon.MoveUnretractedType] = colors[line_types == LayerPolygon.MoveUnretractedType] + material_colors[line_types == LayerPolygon.MoveRetractedType] = colors[line_types == LayerPolygon.MoveRetractedType] + material_colors[line_types == LayerPolygon.MoveWhileRetractingType] = colors[ + line_types == LayerPolygon.MoveWhileRetractingType] + material_colors[line_types == LayerPolygon.MoveWhileUnretractingType] = colors[ + line_types == LayerPolygon.MoveWhileUnretractingType] attributes = { "line_dimensions": { diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index e772a8b78e..c4d57c07a0 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -19,15 +19,21 @@ class LayerPolygon: SkirtType = 5 InfillType = 6 SupportInfillType = 7 - MoveCombingType = 8 - MoveRetractionType = 9 + MoveUnretractedType = 8 + MoveRetractedType = 9 SupportInterfaceType = 10 PrimeTowerType = 11 - __number_of_types = 12 + MoveWhileRetractingType = 12 + MoveWhileUnretractingType = 13 + __number_of_types = 14 - __jump_map = numpy.logical_or(numpy.logical_or(numpy.arange(__number_of_types) == NoneType, - numpy.arange(__number_of_types) == MoveCombingType), - numpy.arange(__number_of_types) == MoveRetractionType) + __jump_map = numpy.logical_or(numpy.logical_or(numpy.logical_or( + numpy.arange(__number_of_types) == NoneType, + numpy.arange(__number_of_types) == MoveUnretractedType), + numpy.logical_or( + numpy.arange(__number_of_types) == MoveRetractedType, + numpy.arange(__number_of_types) == MoveWhileRetractingType)), + numpy.arange(__number_of_types) == MoveWhileUnretractingType) def __init__(self, extruder: int, line_types: numpy.ndarray, data: numpy.ndarray, line_widths: numpy.ndarray, line_thicknesses: numpy.ndarray, line_feedrates: numpy.ndarray) -> None: @@ -269,10 +275,12 @@ class LayerPolygon: theme.getColor("layerview_skirt").getRgbF(), # SkirtType theme.getColor("layerview_infill").getRgbF(), # InfillType theme.getColor("layerview_support_infill").getRgbF(), # SupportInfillType - theme.getColor("layerview_move_combing").getRgbF(), # MoveCombingType - theme.getColor("layerview_move_retraction").getRgbF(), # MoveRetractionType + theme.getColor("layerview_move_combing").getRgbF(), # MoveUnretractedType + theme.getColor("layerview_move_retraction").getRgbF(), # MoveRetractedType theme.getColor("layerview_support_interface").getRgbF(), # SupportInterfaceType - theme.getColor("layerview_prime_tower").getRgbF() # PrimeTowerType + theme.getColor("layerview_prime_tower").getRgbF(), # PrimeTowerType + theme.getColor("layerview_move_while_retracting").getRgbF(), # MoveWhileRetracting + theme.getColor("layerview_move_while_unretracting").getRgbF(), # MoveWhileUnretracting ]) return cls.__color_map diff --git a/plugins/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto index 238829ba64..8018c9186f 100644 --- a/plugins/CuraEngineBackend/Cura.proto +++ b/plugins/CuraEngineBackend/Cura.proto @@ -78,8 +78,8 @@ message Polygon { SkirtType = 5; InfillType = 6; SupportInfillType = 7; - MoveCombingType = 8; - MoveRetractionType = 9; + MoveUnretractedType = 8; + MoveRetractedType = 9; SupportInterfaceType = 10; PrimeTowerType = 11; } diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py index 74dbeadec0..f83a9bbb34 100644 --- a/plugins/GCodeReader/FlavorParser.py +++ b/plugins/GCodeReader/FlavorParser.py @@ -133,7 +133,10 @@ class FlavorParser: if i > 0: line_feedrates[i - 1] = point[3] line_types[i - 1] = point[5] - if point[5] in [LayerPolygon.MoveCombingType, LayerPolygon.MoveRetractionType]: + if point[5] in [LayerPolygon.MoveUnretractedType, + LayerPolygon.MoveRetractedType, + LayerPolygon.MoveWhileRetractingType, + LayerPolygon.MoveWhileUnretractingType]: line_widths[i - 1] = 0.1 line_thicknesses[i - 1] = 0.0 # Travels are set as zero thickness lines else: @@ -196,7 +199,7 @@ class FlavorParser: path.append([x, y, z, f, new_extrusion_value + self._extrusion_length_offset[self._extruder_number], self._layer_type]) # extrusion self._previous_extrusion_value = new_extrusion_value else: - path.append([x, y, z, f, new_extrusion_value + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveRetractionType]) # retraction + path.append([x, y, z, f, new_extrusion_value + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveRetractedType]) # retraction e[self._extruder_number] = new_extrusion_value # Only when extruding we can determine the latest known "layer height" which is the difference in height between extrusions @@ -205,9 +208,9 @@ class FlavorParser: self._current_layer_thickness = z - self._previous_z # allow a tiny overlap self._previous_z = z elif self._previous_extrusion_value > e[self._extruder_number]: - path.append([x, y, z, f, e[self._extruder_number] + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveRetractionType]) + path.append([x, y, z, f, e[self._extruder_number] + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveRetractedType]) else: - path.append([x, y, z, f, e[self._extruder_number] + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveCombingType]) + path.append([x, y, z, f, e[self._extruder_number] + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveUnretractedType]) return self._position(x, y, z, f, e) @@ -419,7 +422,7 @@ class FlavorParser: self._createPolygon(self._current_layer_thickness, current_path, self._extruder_offsets.get(self._extruder_number, [0, 0])) current_path.clear() # Start the new layer at the end position of the last layer - current_path.append([current_position.x, current_position.y, current_position.z, current_position.f, current_position.e[self._extruder_number], LayerPolygon.MoveCombingType]) + current_path.append([current_position.x, current_position.y, current_position.z, current_position.f, current_position.e[self._extruder_number], LayerPolygon.MoveUnretractedType]) # When using a raft, the raft layers are stored as layers < 0, it mimics the same behavior # as in ProcessSlicedLayersJob @@ -461,9 +464,9 @@ class FlavorParser: # When changing tool, store the end point of the previous path, then process the code and finally # add another point with the new position of the head. - current_path.append([current_position.x, current_position.y, current_position.z, current_position.f, current_position.e[self._extruder_number], LayerPolygon.MoveCombingType]) + current_path.append([current_position.x, current_position.y, current_position.z, current_position.f, current_position.e[self._extruder_number], LayerPolygon.MoveUnretractedType]) current_position = self.processTCode(global_stack, T, line, current_position, current_path) - current_path.append([current_position.x, current_position.y, current_position.z, current_position.f, current_position.e[self._extruder_number], LayerPolygon.MoveCombingType]) + current_path.append([current_position.x, current_position.y, current_position.z, current_position.f, current_position.e[self._extruder_number], LayerPolygon.MoveUnretractedType]) if line.startswith("M"): M = self._getInt(line, "M") diff --git a/plugins/SimulationView/SimulationPass.py b/plugins/SimulationView/SimulationPass.py index 080b02bd9e..840fd7f6dc 100644 --- a/plugins/SimulationView/SimulationPass.py +++ b/plugins/SimulationView/SimulationPass.py @@ -202,9 +202,9 @@ class SimulationPass(RenderPass): self._layer_shader.setUniformValue("u_next_vertex", not_a_vector) self._layer_shader.setUniformValue("u_last_line_ratio", 1.0) - # The first line does not have a previous line: add a MoveCombingType in front for start detection + # The first line does not have a previous line: add a MoveUnretractedType in front for start detection # this way the first start of the layer can also be drawn - prev_line_types = numpy.concatenate([numpy.asarray([LayerPolygon.MoveCombingType], dtype = numpy.float32), layer_data._attributes["line_types"]["value"]]) + prev_line_types = numpy.concatenate([numpy.asarray([LayerPolygon.MoveUnretractedType], dtype = numpy.float32), layer_data._attributes["line_types"]["value"]]) # Remove the last element prev_line_types = prev_line_types[0:layer_data._attributes["line_types"]["value"].size] layer_data._attributes["prev_line_types"] = {'opengl_type': 'float', 'value': prev_line_types, 'opengl_name': 'a_prev_line_type'} diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py index 10861acfd0..083fc73bf1 100644 --- a/plugins/SimulationView/SimulationView.py +++ b/plugins/SimulationView/SimulationView.py @@ -608,8 +608,10 @@ class SimulationView(CuraView): visible_line_types.append(LayerPolygon.SupportInterfaceType) visible_line_types_with_extrusion = visible_line_types.copy() # Copy before travel moves are added if self.getShowTravelMoves(): - visible_line_types.append(LayerPolygon.MoveCombingType) - visible_line_types.append(LayerPolygon.MoveRetractionType) + visible_line_types.append(LayerPolygon.MoveUnretractedType) + visible_line_types.append(LayerPolygon.MoveRetractedType) + visible_line_types.append(LayerPolygon.MoveWhileRetractingType) + visible_line_types.append(LayerPolygon.MoveWhileUnretractingType) for node in DepthFirstIterator(self.getController().getScene().getRoot()): layer_data = node.callDecoration("getLayerData") diff --git a/plugins/SimulationView/layers.shader b/plugins/SimulationView/layers.shader index e6210c2b65..d5079fd82b 100644 --- a/plugins/SimulationView/layers.shader +++ b/plugins/SimulationView/layers.shader @@ -22,8 +22,8 @@ vertex = gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_vertex; // shade the color depending on the extruder index v_color = a_color; - // 8 and 9 are travel moves - if ((a_line_type != 8.0) && (a_line_type != 9.0)) { + // 8, 9, 12 and 13 are travel moves + if ((a_line_type != 8.0) && (a_line_type != 9.0) && (a_line_type != 12.0) && (a_line_type != 13.0)) { v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a); } @@ -48,7 +48,9 @@ fragment = void main() { - if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9 + // travel moves: 8, 9, 12, 13 + if ((u_show_travel_moves == 0) && (((v_line_type >= 7.5) && (v_line_type <= 9.5)) || + ((v_line_type >= 11.5) && (v_line_type <= 13.5)))) { // discard movements discard; } @@ -100,7 +102,7 @@ vertex41core = { gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_vertex; v_color = a_color; - if ((a_line_type != 8) && (a_line_type != 9)) { + if ((a_line_type != 8) && (a_line_type != 9) && (a_line_type != 12) && (a_line_type != 13)) { v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a); } @@ -120,7 +122,9 @@ fragment41core = void main() { - if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9 + // travel moves: 8, 9, 12, 13 + if ((u_show_travel_moves == 0) && (((v_line_type >= 7.5) && (v_line_type <= 9.5)) || + ((v_line_type >= 11.5) && (v_line_type <= 13.5)))) { // discard movements discard; } diff --git a/plugins/SimulationView/layers3d.shader b/plugins/SimulationView/layers3d.shader index 494a07083d..e2f57823f3 100644 --- a/plugins/SimulationView/layers3d.shader +++ b/plugins/SimulationView/layers3d.shader @@ -228,22 +228,26 @@ geometry41core = { highp mat4 viewProjectionMatrix = u_projectionMatrix * u_viewMatrix; - vec4 g_vertex_delta; - vec3 g_vertex_normal_horz; // horizontal and vertical in respect to layers - vec4 g_vertex_offset_horz; // vec4 to match gl_in[x].gl_Position + // Vertices are declared as vec4 so that they can be used for calculations with gl_in[x].gl_Position + vec3 g_vertex_delta; + vec3 g_vertex_normal_horz; + vec4 g_vertex_offset_horz; vec3 g_vertex_normal_vert; vec4 g_vertex_offset_vert; vec3 g_vertex_normal_horz_head; vec4 g_vertex_offset_horz_head; + vec3 g_axial_plan_vector; + vec3 g_radial_plan_vector; float size_x; float size_y; - if ((v_extruder_opacity[0][int(mod(v_extruder[0], 4))][v_extruder[0] / 4] == 0.0) && (v_line_type[0] != 8) && (v_line_type[0] != 9)) { + if ((v_extruder_opacity[0][int(mod(v_extruder[0], 4))][v_extruder[0] / 4] == 0.0) && + (v_line_type[0] != 8) && (v_line_type[0] != 9) && (v_line_type[0] != 12) && (v_line_type[0] != 13)) { return; } - // See LayerPolygon; 8 is MoveCombingType, 9 is RetractionType - if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9))) { + // See LayerPolygon; 8 is MoveUnretractedType, 9 is RetractionType, 12 is MoveWhileRetractingType, 13 is MoveWhileUnretractingType + if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9) || (v_line_type[0] == 12) || (v_line_type[0] == 13))) { return; } if ((u_show_helpers == 0) && ((v_line_type[0] == 4) || (v_line_type[0] == 5) || (v_line_type[0] == 7) || (v_line_type[0] == 10) || v_line_type[0] == 11)) { @@ -256,7 +260,7 @@ geometry41core = return; } - if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { + if ((v_line_type[0] == 8) || (v_line_type[0] == 9) || (v_line_type[0] == 12) || (v_line_type[0] == 13)) { // fixed size for movements size_x = 0.05; } else { @@ -264,26 +268,47 @@ geometry41core = } size_y = v_line_dim[1].y / 2 + 0.01; - g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; //Actual movement exhibited by the line. - g_vertex_normal_horz_head = normalize(vec3(-g_vertex_delta.x, -g_vertex_delta.y, -g_vertex_delta.z)); //Lengthwise normal vector pointing backwards. - g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); //Lengthwise offset vector pointing backwards. + g_vertex_delta = (gl_in[1].gl_Position - gl_in[0].gl_Position).xyz; //Actual movement exhibited by the line. - g_vertex_normal_horz = normalize(vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x)); //Normal vector pointing right. + if (g_vertex_delta == vec3(0.0)) { + return; + } + + if (g_vertex_delta.y == 0.0) + { + // vector is in the horizontal plan, radial vector is a simple rotation around Y axis + g_radial_plan_vector = vec3(g_vertex_delta.z, 0.0, -g_vertex_delta.x); + } + else if(g_vertex_delta.x == 0.0 && g_vertex_delta.z == 0.0) + { + // delta vector is purely vertical, display the line rotated vertically so that it is visible in front and side views + g_radial_plan_vector = vec3(1.0, 0.0, -1.0); + } + else + { + // delta vector is completely 3D + g_axial_plan_vector = vec3(g_vertex_delta.x, 0.0, g_vertex_delta.z); // Vector projected in the horizontal plan + g_radial_plan_vector = cross(g_vertex_delta, g_axial_plan_vector); // Radial vector in the horizontal plan, pointing right. + } + + g_vertex_normal_horz_head = normalize(g_vertex_delta); //Lengthwise normal vector + g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); //Lengthwise offset vector + + g_vertex_normal_horz = normalize(g_radial_plan_vector); //Normal vector pointing right. g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //Offset vector pointing right. g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); //Upwards normal vector. g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0); //Upwards offset vector. Goes up by half the layer thickness. - if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { //Travel or retraction moves. - vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert); + if ((v_line_type[0] == 8) || (v_line_type[0] == 9) || (v_line_type[0] == 12) || (v_line_type[0] == 13)) { //Travel or retraction moves. + vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert); vec4 va_up = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert); vec4 va_down = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert); - vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert); + vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert); vec4 vb_down = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert); vec4 vb_up = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert); // Travels: flat plane with pointy ends - myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up); myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_head); myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_down); myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up); @@ -308,8 +333,8 @@ geometry41core = vec4 vb_p_horz = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); //Line end, right vertex. vec4 va_m_vert = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); //Line start, bottom vertex. vec4 vb_m_vert = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); //Line end, bottom vertex. - vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); //Line start, tip. - vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); //Line end, tip. + vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz_head); //Line start, tip. + vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz_head); //Line end, tip. // All normal lines are rendered as 3d tubes. myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); @@ -328,14 +353,14 @@ geometry41core = // left side myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_p_vert); - myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz_head, va_head); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz_head, va_head); myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz); EndPrimitive(); myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz); myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_vert, va_m_vert); - myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz_head, va_head); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz_head, va_head); myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); EndPrimitive(); @@ -343,14 +368,14 @@ geometry41core = // right side myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_p_vert); - myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, vb_head); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz_head, vb_head); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz); EndPrimitive(); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, vb_m_vert); - myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, vb_head); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz_head, vb_head); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz); EndPrimitive(); diff --git a/plugins/SimulationView/layers3d_shadow.shader b/plugins/SimulationView/layers3d_shadow.shader index 88268938c9..47637cfb20 100644 --- a/plugins/SimulationView/layers3d_shadow.shader +++ b/plugins/SimulationView/layers3d_shadow.shader @@ -95,22 +95,26 @@ geometry41core = { highp mat4 viewProjectionMatrix = u_projectionMatrix * u_viewMatrix; - vec4 g_vertex_delta; - vec3 g_vertex_normal_horz; // horizontal and vertical in respect to layers - vec4 g_vertex_offset_horz; // vec4 to match gl_in[x].gl_Position + // Vertices are declared as vec4 so that they can be used for calculations with gl_in[x].gl_Position + vec3 g_vertex_delta; + vec3 g_vertex_normal_horz; + vec4 g_vertex_offset_horz; vec3 g_vertex_normal_vert; vec4 g_vertex_offset_vert; vec3 g_vertex_normal_horz_head; vec4 g_vertex_offset_horz_head; + vec3 g_axial_plan_vector; + vec3 g_radial_plan_vector; float size_x; float size_y; - if ((v_extruder_opacity[0][int(mod(v_extruder[0], 4))][v_extruder[0] / 4] == 0.0) && (v_line_type[0] != 8) && (v_line_type[0] != 9)) { + if ((v_extruder_opacity[0][int(mod(v_extruder[0], 4))][v_extruder[0] / 4] == 0.0) && + (v_line_type[0] != 8) && (v_line_type[0] != 9) && (v_line_type[0] != 12) && (v_line_type[0] != 13)) { return; } - // See LayerPolygon; 8 is MoveCombingType, 9 is RetractionType - if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9))) { + // See LayerPolygon; 8 is MoveUnretractedType, 9 is RetractionType, 12 is MoveWhileRetractingType, 13 is MoveWhileUnretractingType + if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9) || (v_line_type[0] == 12) || (v_line_type[0] == 13))) { return; } if ((u_show_helpers == 0) && ((v_line_type[0] == 4) || (v_line_type[0] == 5) || (v_line_type[0] == 7) || (v_line_type[0] == 10))) { @@ -123,7 +127,7 @@ geometry41core = return; } - if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { + if ((v_line_type[0] == 8) || (v_line_type[0] == 9) || (v_line_type[0] == 12) || (v_line_type[0] == 13)) { // fixed size for movements size_x = 0.05; } else { @@ -131,93 +135,114 @@ geometry41core = } size_y = v_line_dim[1].y / 2 + 0.01; - g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; - g_vertex_normal_horz_head = normalize(vec3(-g_vertex_delta.x, -g_vertex_delta.y, -g_vertex_delta.z)); - g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); + g_vertex_delta = (gl_in[1].gl_Position - gl_in[0].gl_Position).xyz; //Actual movement exhibited by the line. - g_vertex_normal_horz = normalize(vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x)); + if (g_vertex_delta == vec3(0.0)) { + return; + } - g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //size * g_vertex_normal_horz; - g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); - g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0); + if (g_vertex_delta.y == 0.0) + { + // vector is in the horizontal plan, radial vector is a simple rotation around Y axis + g_radial_plan_vector = vec3(g_vertex_delta.z, 0.0, -g_vertex_delta.x); + } + else if(g_vertex_delta.x == 0.0 && g_vertex_delta.z == 0.0) + { + // delta vector is purely vertical, display the line rotated vertically so that it is visible in front and side views + g_radial_plan_vector = vec3(1.0, 0.0, -1.0); + } + else + { + // delta vector is completely 3D + g_axial_plan_vector = vec3(g_vertex_delta.x, 0.0, g_vertex_delta.z); // Vector projected in the horizontal plan + g_radial_plan_vector = cross(g_vertex_delta, g_axial_plan_vector); // Radial vector in the horizontal plan, pointing right. + } - if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { - vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert); + g_vertex_normal_horz_head = normalize(g_vertex_delta); //Lengthwise normal vector + g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); //Lengthwise offset vector + + g_vertex_normal_horz = normalize(g_radial_plan_vector); //Normal vector pointing right. + g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //Offset vector pointing right. + + g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); //Upwards normal vector. + g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0); //Upwards offset vector. Goes up by half the layer thickness. + + if ((v_line_type[0] == 8) || (v_line_type[0] == 9) || (v_line_type[0] == 12) || (v_line_type[0] == 13)) { + vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert); vec4 va_up = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert); vec4 va_down = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert); - vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert); + vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert); vec4 vb_down = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert); vec4 vb_up = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert); // Travels: flat plane with pointy ends - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_head); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_down); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_head); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_down); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_down); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_up); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_head); //And reverse so that the line is also visible from the back side. myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_up); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_down); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_down); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_head); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_up); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_down); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_head); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_up); EndPrimitive(); } else { - vec4 va_m_horz = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); - vec4 vb_m_horz = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); - vec4 va_p_vert = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); - vec4 vb_p_vert = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); - vec4 va_p_horz = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); - vec4 vb_p_horz = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); - vec4 va_m_vert = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); - vec4 vb_m_vert = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); - vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); - vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); + vec4 va_m_horz = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); //Line start, left vertex. + vec4 vb_m_horz = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); //Line end, left vertex. + vec4 va_p_vert = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); //Line start, top vertex. + vec4 vb_p_vert = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); //Line end, top vertex. + vec4 va_p_horz = viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); //Line start, right vertex. + vec4 vb_p_horz = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); //Line end, right vertex. + vec4 va_m_vert = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); //Line start, bottom vertex. + vec4 vb_m_vert = viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); //Line end, bottom vertex. + vec4 va_head = viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz_head); //Line start, tip. + vec4 vb_head = viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz_head); //Line end, tip. // All normal lines are rendered as 3d tubes. - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_p_vert); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_p_vert); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_p_vert); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz); - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, va_m_vert); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_vert, va_m_vert); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, vb_m_vert); - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz); EndPrimitive(); // left side - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, va_p_vert); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, va_head); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_vert, va_p_vert); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz_head, va_head); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz); EndPrimitive(); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, va_p_horz); - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, va_m_vert); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, va_head); - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, va_m_horz); + myEmitVertex(v_vertex[0], v_color[1], g_vertex_normal_horz, va_p_horz); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_vert, va_m_vert); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz_head, va_head); + myEmitVertex(v_vertex[0], v_color[1], -g_vertex_normal_horz, va_m_horz); EndPrimitive(); // right side myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, vb_p_vert); - myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, vb_head); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz_head, vb_head); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz); EndPrimitive(); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, vb_m_horz); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, vb_m_vert); - myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, vb_head); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz_head, vb_head); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, vb_p_horz); EndPrimitive(); diff --git a/plugins/SimulationView/layers_shadow.shader b/plugins/SimulationView/layers_shadow.shader index 4bc2de3d0b..73278914b7 100644 --- a/plugins/SimulationView/layers_shadow.shader +++ b/plugins/SimulationView/layers_shadow.shader @@ -48,8 +48,10 @@ fragment = void main() { - if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) - { // actually, 8 and 9 + // travel moves: 8, 9, 12, 13 + if ((u_show_travel_moves == 0) && (((v_line_type >= 7.5) && (v_line_type <= 9.5)) || + ((v_line_type >= 11.5) && (v_line_type <= 13.5)))) { + { // discard movements discard; } @@ -124,7 +126,9 @@ fragment41core = void main() { - if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9 + // travel moves: 8, 9, 12, 13 + if ((u_show_travel_moves == 0) && (((v_line_type >= 7.5) && (v_line_type <= 9.5)) || + ((v_line_type >= 11.5) && (v_line_type <= 13.5)))) { // discard movements discard; } diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 1ae316f96c..377e70f5b6 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -463,6 +463,8 @@ "layerview_support_infill": [0, 230, 230, 127], "layerview_move_combing": [0, 0, 255, 255], "layerview_move_retraction": [128, 127, 255, 255], + "layerview_move_while_retracting": [127, 255, 255, 255], + "layerview_move_while_unretracting": [255, 127, 255, 255], "layerview_support_interface": [63, 127, 255, 127], "layerview_prime_tower": [0, 255, 255, 255], "layerview_nozzle": [224, 192, 16, 64], From e1d579c6c8f7720deb05dd21e3892b1f914c6e34 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 26 May 2025 16:53:34 +0200 Subject: [PATCH 131/299] Display legend tooltip for travel types CURA-11978 --- .../SimulationViewMenuComponent.qml | 87 +++++++++++++++++-- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/plugins/SimulationView/SimulationViewMenuComponent.qml b/plugins/SimulationView/SimulationViewMenuComponent.qml index d434d883eb..dcd2c7d178 100644 --- a/plugins/SimulationView/SimulationViewMenuComponent.qml +++ b/plugins/SimulationView/SimulationViewMenuComponent.qml @@ -227,29 +227,52 @@ Cura.ExpandableComponent id: typesLegendModel Component.onCompleted: { + const travelsTypesModel = [ + { + label: catalog.i18nc("@label", "Unretracted"), + colorId: "layerview_move_combing" + }, + { + label: catalog.i18nc("@label", "Retracted"), + colorId: "layerview_move_retraction" + }, + { + label: catalog.i18nc("@label", "Retracting"), + colorId: "layerview_move_while_retracting" + }, + { + label: catalog.i18nc("@label", "Unretracting"), + colorId: "layerview_move_while_unretracting" + } + ]; + typesLegendModel.append({ label: catalog.i18nc("@label", "Travels"), initialValue: viewSettings.show_travel_moves, preference: "layerview/show_travel_moves", - colorId: "layerview_move_combing" + colorId: "layerview_move_combing", + subTypesModel: travelsTypesModel }); typesLegendModel.append({ label: catalog.i18nc("@label", "Helpers"), initialValue: viewSettings.show_helpers, preference: "layerview/show_helpers", - colorId: "layerview_support" + colorId: "layerview_support", + subTypesModel: [] }); typesLegendModel.append({ label: catalog.i18nc("@label", "Shell"), initialValue: viewSettings.show_skin, preference: "layerview/show_skin", - colorId: "layerview_inset_0" + colorId: "layerview_inset_0", + subTypesModel: [] }); typesLegendModel.append({ label: catalog.i18nc("@label", "Infill"), initialValue: viewSettings.show_infill, preference: "layerview/show_infill", - colorId: "layerview_infill" + colorId: "layerview_infill", + subTypesModel: [] }); if (! UM.SimulationView.compatibilityMode) { @@ -257,7 +280,8 @@ Cura.ExpandableComponent label: catalog.i18nc("@label", "Starts"), initialValue: viewSettings.show_starts, preference: "layerview/show_starts", - colorId: "layerview_starts" + colorId: "layerview_starts", + subTypesModel: [] }); } } @@ -273,6 +297,7 @@ Cura.ExpandableComponent Rectangle { + id: rectangleColor anchors.verticalCenter: parent.verticalCenter anchors.right: legendModelCheckBox.right width: UM.Theme.getSize("layerview_legend_size").width @@ -281,6 +306,58 @@ Cura.ExpandableComponent border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") visible: viewSettings.show_legend + + MouseArea + { + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.NoButton + enabled: subTypesModel.count > 0 + + onEntered: tooltip.show() + onExited: tooltip.hide() + + UM.ToolTip + { + id: tooltip + delay: 0 + width: subTypesColumn.implicitWidth + 2 * UM.Theme.getSize("thin_margin").width + height: subTypesColumn.implicitHeight + 2 * UM.Theme.getSize("thin_margin").width + + contentItem: Column + { + id: subTypesColumn + padding: 0 + spacing: UM.Theme.getSize("layerview_row_spacing").height + + Repeater + { + model: subTypesModel + UM.Label + { + text: label + + height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height + width: UM.Theme.getSize("layerview_menu_size").width + color: UM.Theme.getColor("setting_control_text") + Rectangle + { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + + width: UM.Theme.getSize("layerview_legend_size").width + height: UM.Theme.getSize("layerview_legend_size").height + + color: UM.Theme.getColor(model.colorId) + + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + } + } + } + } + } + } } UM.Label From 704f9453f0a1cfd554eb4b18cb31b293fa4c917e Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 27 May 2025 17:03:38 +0200 Subject: [PATCH 132/299] Properly completed drag to paint (no more just clicking points). The most important thing to make it work is actually notifying the scene that something has changed -- the rest are just refactorings and (hopefully) optimizations. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 48 +++++++++++++++++---------------- plugins/PaintTool/PaintTool.qml | 2 +- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index bbcd80cef0..503d380987 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -1,11 +1,10 @@ # Copyright (c) 2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. - -from typing import cast, Optional +from copy import deepcopy import numpy from PyQt6.QtCore import Qt -from typing import Dict, List, Tuple +from typing import cast, Dict, List, Optional, Tuple from UM.Application import Application from UM.Event import Event, MouseEvent, KeyEvent @@ -14,6 +13,7 @@ from UM.Scene.SceneNode import SceneNode from UM.Scene.Selection import Selection from UM.Tool import Tool from UM.View.View import View + from cura.PickingPass import PickingPass @@ -44,7 +44,7 @@ class PaintTool(Tool): self._brush_shape: str = "A" self._mouse_held: bool = False - self._mouse_drags: List[Tuple[int, int]] = [] + self._last_mouse_drag: Optional[Tuple[int, int]] = None def setPaintType(self, paint_type: str) -> None: Logger.warning(f"TODO: Implement paint-types ({paint_type}).") @@ -52,7 +52,6 @@ class PaintTool(Tool): def setBrushSize(self, brush_size: float) -> None: self._brush_size = int(brush_size) - print(self._brush_size) def setBrushColor(self, brush_color: str) -> None: self._brush_color = brush_color @@ -89,8 +88,8 @@ class PaintTool(Tool): def _getBrushPixels(self, mid_x: float, mid_y: float, w: float, h: float) -> List[Tuple[float, float]]: res = [] include = False - for y in range(-self._brush_size, self._brush_size + 1): - for x in range(-self._brush_size, self._brush_size + 1): + for y in range(-self._brush_size//2, (self._brush_size + 1)//2): + for x in range(-self._brush_size//2, (self._brush_size + 1)//2): match self._brush_shape: case "A": include = True @@ -160,10 +159,24 @@ class PaintTool(Tool): if event.type == Event.MouseReleaseEvent and self._controller.getToolsEnabled(): if MouseEvent.LeftButton not in cast(MouseEvent, event).buttons: return False - self._mouse_held = False - drags = self._mouse_drags.copy() - self._mouse_drags.clear() + self._last_mouse_drag = None + return True + + is_moved = event.type == Event.MouseMoveEvent + is_pressed = event.type == Event.MousePressEvent + if (is_moved or is_pressed) and self._controller.getToolsEnabled(): + if is_moved and not self._mouse_held: + return False + + evt = cast(MouseEvent, event) + if is_pressed: + if MouseEvent.LeftButton not in evt.buttons: + return False + else: + self._mouse_held = True + drags = ([self._last_mouse_drag] if self._last_mouse_drag else []) + [(evt.x, evt.y)] + self._last_mouse_drag = (evt.x, evt.y) paintview = controller.getActiveView() if paintview is None or paintview.getPluginId() != "PaintTool": @@ -203,19 +216,8 @@ class PaintTool(Tool): res = False for (x, y) in drags: res |= self._handleMouseAction(node, paintview, x, y) + if res: + Application.getInstance().getController().getScene().sceneChanged.emit(node) return res - if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): - if MouseEvent.LeftButton not in cast(MouseEvent, event).buttons: - return False - self._mouse_held = True - return True - - if event.type == Event.MouseMoveEvent: - if not self._mouse_held: - return False - evt = cast(MouseEvent, event) - self._mouse_drags.append((evt.x, evt.y)) - return True - return False diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index 902d5a700d..82d6d90ffd 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -164,7 +164,7 @@ Item id: shapeSizeSlider from: 1 - to: 50 + to: 40 value: 10 onPressedChanged: function(pressed) From 96d2caf19542e024b38187fabbb4ea899ec85020 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 28 May 2025 11:00:55 +0200 Subject: [PATCH 133/299] Load UV coordinates from 3MF file CURA-12544 --- plugins/3MFReader/ThreeMFReader.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 45ab2e7d2f..5c8d803f3b 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -94,7 +94,7 @@ class ThreeMFReader(MeshReader): return temp_mat @staticmethod - def _convertSavitarNodeToUMNode(savitar_node: Savitar.SceneNode, file_name: str = "", archive: zipfile.ZipFile = None) -> Optional[SceneNode]: + def _convertSavitarNodeToUMNode(savitar_node: Savitar.SceneNode, file_name: str = "", archive: zipfile.ZipFile = None, scene: Savitar.Scene = None) -> Optional[SceneNode]: """Convenience function that converts a SceneNode object (as obtained from libSavitar) to a scene node. :returns: Scene node. @@ -131,12 +131,19 @@ class ThreeMFReader(MeshReader): um_node.setTransformation(transformation) mesh_builder = MeshBuilder() - data = numpy.fromstring(savitar_node.getMeshData().getFlatVerticesAsBytes(), dtype=numpy.float32) + mesh_data = savitar_node.getMeshData() + + vertices_data = numpy.fromstring(mesh_data.getFlatVerticesAsBytes(), dtype=numpy.float32) + vertices = numpy.resize(vertices_data, (int(vertices_data.size / 3), 3)) + + texture_path = mesh_data.getTexturePath(scene) + uv_data = numpy.fromstring(mesh_data.getUVCoordinatesPerVertexAsBytes(scene), dtype=numpy.float32) + uv_coordinates = numpy.resize(uv_data, (int(uv_data.size / 2), 2)) - vertices = numpy.resize(data, (int(data.size / 3), 3)) mesh_builder.setVertices(vertices) mesh_builder.calculateNormals(fast=True) mesh_builder.setMeshId(node_id) + mesh_builder.setUVCoordinates(uv_coordinates) if file_name: # The filename is used to give the user the option to reload the file if it is changed on disk # It is only set for the root node of the 3mf file @@ -147,7 +154,7 @@ class ThreeMFReader(MeshReader): um_node.setMeshData(mesh_data) for child in savitar_node.getChildren(): - child_node = ThreeMFReader._convertSavitarNodeToUMNode(child, archive=archive) + child_node = ThreeMFReader._convertSavitarNodeToUMNode(child, archive=archive, scene=scene) if child_node: um_node.addChild(child_node) @@ -236,7 +243,7 @@ class ThreeMFReader(MeshReader): CuraApplication.getInstance().getController().getScene().setMetaDataEntry(key, value) for node in scene_3mf.getSceneNodes(): - um_node = ThreeMFReader._convertSavitarNodeToUMNode(node, file_name, archive) + um_node = ThreeMFReader._convertSavitarNodeToUMNode(node, file_name, archive, scene_3mf) if um_node is None: continue @@ -336,7 +343,7 @@ class ThreeMFReader(MeshReader): # Convert the scene to scene nodes nodes = [] for savitar_node in scene.getSceneNodes(): - scene_node = ThreeMFReader._convertSavitarNodeToUMNode(savitar_node, "file_name") + scene_node = ThreeMFReader._convertSavitarNodeToUMNode(savitar_node, "file_name", scene=scene) if scene_node is None: continue nodes.append(scene_node) From 109f37657b8417671846398de6bb39edfc7861bf Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 28 May 2025 12:32:36 +0200 Subject: [PATCH 134/299] Painting UI work: Update image-part(s) instead of pixel(s) w.r.t. render-backend. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 134 ++++++++++++++++++++++----------- plugins/PaintTool/PaintView.py | 12 ++- 2 files changed, 98 insertions(+), 48 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 503d380987..90482d0055 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -1,9 +1,9 @@ # Copyright (c) 2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. -from copy import deepcopy import numpy from PyQt6.QtCore import Qt +from PyQt6.QtGui import QImage, QPainter, QColor, QBrush from typing import cast, Dict, List, Optional, Tuple from UM.Application import Application @@ -12,9 +12,9 @@ from UM.Logger import Logger from UM.Scene.SceneNode import SceneNode from UM.Scene.Selection import Selection from UM.Tool import Tool -from UM.View.View import View from cura.PickingPass import PickingPass +from .PaintView import PaintView class PaintTool(Tool): @@ -42,22 +42,82 @@ class PaintTool(Tool): self._brush_size: int = 10 self._brush_color: str = "A" self._brush_shape: str = "A" + self._brush_image = self._createBrushImage() self._mouse_held: bool = False - self._last_mouse_drag: Optional[Tuple[int, int]] = None + self._last_text_coords: Optional[Tuple[int, int]] = None + + def _createBrushImage(self) -> QImage: + brush_image = QImage(self._brush_size, self._brush_size, QImage.Format.Format_RGBA8888) + brush_image.fill(QColor(255,255,255,0)) + + color = self._color_str_to_rgba[self._brush_color] + qcolor = QColor(color[0], color[1], color[2], color[3]) + + painter = QPainter(brush_image) + painter.setRenderHint(QPainter.RenderHint.Antialiasing, False) + painter.setPen(Qt.PenStyle.NoPen) + painter.setBrush(QBrush(qcolor)) + match self._brush_shape: + case "A": # Square brush + painter.drawRect(0, 0, self._brush_size, self._brush_size) + case "B": # Circle brush + painter.drawEllipse(0, 0, self._brush_size, self._brush_size) + case _: + painter.drawRect(0, 0, self._brush_size, self._brush_size) + painter.end() + + return brush_image + + def _createStrokeImage(self, x0: float, y0: float, x1: float, y1: float) -> Tuple[QImage, Tuple[int, int]]: + distance = numpy.hypot(x1 - x0, y1 - y0) + angle = numpy.arctan2(y1 - y0, x1 - x0) + stroke_width = self._brush_size + stroke_height = int(distance) + self._brush_size + + half_brush_size = self._brush_size // 2 + start_x = int(x0 - half_brush_size) + start_y = int(y0 - half_brush_size) + + stroke_image = QImage(stroke_height, stroke_width, QImage.Format.Format_RGBA8888) + stroke_image.fill(QColor(255,255,255,0)) + + painter = QPainter(stroke_image) + painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform) + painter.setRenderHint(QPainter.RenderHint.Antialiasing, False) + + # rotate the brush-image to follow the stroke-direction + transform = painter.transform() + transform.translate(0, stroke_width / 2) # translate to match the brush-alignment + transform.rotate(-numpy.degrees(angle)) + painter.setTransform(transform) + + # tile the brush along the stroke-length + brush_stride = max(1, half_brush_size) + for i in range(0, int(distance) + brush_stride, brush_stride): + painter.drawImage(i, -stroke_width, self._brush_image) + painter.end() + + return stroke_image, (start_x, start_y) def setPaintType(self, paint_type: str) -> None: Logger.warning(f"TODO: Implement paint-types ({paint_type}).") - pass + pass # FIXME: ... and also please call `self._stroke_image = self._createBrushStrokeImage()` (see other funcs). def setBrushSize(self, brush_size: float) -> None: - self._brush_size = int(brush_size) + if brush_size != self._brush_size: + self._brush_size = int(brush_size) + self._brush_image = self._createBrushImage() def setBrushColor(self, brush_color: str) -> None: - self._brush_color = brush_color + if brush_color != self._brush_color: + self._brush_color = brush_color + self._brush_image = self._createBrushImage() def setBrushShape(self, brush_shape: str) -> None: - self._brush_shape = brush_shape + if brush_shape != self._brush_shape: + self._brush_shape = brush_shape + self._brush_image = self._createBrushImage() @staticmethod def _get_intersect_ratio_via_pt(a: numpy.ndarray, pt: numpy.ndarray, b: numpy.ndarray, c: numpy.ndarray) -> float: @@ -85,28 +145,10 @@ class PaintTool(Tool): def _nodeTransformChanged(self, *args) -> None: self._cache_dirty = True - def _getBrushPixels(self, mid_x: float, mid_y: float, w: float, h: float) -> List[Tuple[float, float]]: - res = [] - include = False - for y in range(-self._brush_size//2, (self._brush_size + 1)//2): - for x in range(-self._brush_size//2, (self._brush_size + 1)//2): - match self._brush_shape: - case "A": - include = True - case "B": - include = x * x + y * y <= self._brush_size * self._brush_size - if include: - xx = mid_x + (x / w) - yy = mid_y + (y / h) - if xx < 0 or xx > 1 or yy < 0 or yy > 1: - continue - res.append((xx, yy)) - return res - - def _handleMouseAction(self, node: SceneNode, paintview: View, x: int, y: int) -> bool: + def _getTexCoordsFromClick(self, node: SceneNode, x: int, y: int) -> Optional[Tuple[float, float]]: face_id = self._selection_pass.getFaceIdAtPosition(x, y) if face_id < 0: - return False + return None pt = self._picking_pass.getPickedPosition(x, y).getData() @@ -123,13 +165,7 @@ class PaintTool(Tool): wb /= wt wc /= wt texcoords = wa * ta + wb * tb + wc * tc - - color = self._color_str_to_rgba[self._brush_color] - w, h = paintview.getUvTexDimensions() - for (x, y) in self._getBrushPixels(texcoords[0], texcoords[1], float(w), float(h)): - paintview.setUvPixel(x, y, color) - - return True + return texcoords def event(self, event: Event) -> bool: """Handle mouse and keyboard events. @@ -160,7 +196,7 @@ class PaintTool(Tool): if MouseEvent.LeftButton not in cast(MouseEvent, event).buttons: return False self._mouse_held = False - self._last_mouse_drag = None + self._last_text_coords = None return True is_moved = event.type == Event.MouseMoveEvent @@ -175,12 +211,11 @@ class PaintTool(Tool): return False else: self._mouse_held = True - drags = ([self._last_mouse_drag] if self._last_mouse_drag else []) + [(evt.x, evt.y)] - self._last_mouse_drag = (evt.x, evt.y) paintview = controller.getActiveView() if paintview is None or paintview.getPluginId() != "PaintTool": return False + paintview = cast(PaintView, paintview) if not self._selection_pass: return False @@ -205,7 +240,6 @@ class PaintTool(Tool): return False evt = cast(MouseEvent, event) - drags.append((evt.x, evt.y)) if not self._picking_pass: self._picking_pass = PickingPass(camera.getViewportWidth(), camera.getViewportHeight()) @@ -213,11 +247,23 @@ class PaintTool(Tool): self._selection_pass.renderFacesMode() - res = False - for (x, y) in drags: - res |= self._handleMouseAction(node, paintview, x, y) - if res: - Application.getInstance().getController().getScene().sceneChanged.emit(node) - return res + texcoords = self._getTexCoordsFromClick(node, evt.x, evt.y) + if texcoords is None: + return False + if self._last_text_coords is None: + self._last_text_coords = texcoords + + w, h = paintview.getUvTexDimensions() + sub_image, (start_x, start_y) = self._createStrokeImage( + self._last_text_coords[0] * w, + self._last_text_coords[1] * h, + texcoords[0] * w, + texcoords[1] * h + ) + paintview.addStroke(sub_image, start_x, start_y) + + self._last_text_coords = texcoords + Application.getInstance().getController().getScene().sceneChanged.emit(node) + return True return False diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 0923d007d7..b86d59b9df 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -1,6 +1,8 @@ # Copyright (c) 2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. + import os +from PyQt6.QtGui import QImage from UM.PluginRegistry import PluginRegistry from UM.View.View import View @@ -18,8 +20,10 @@ class PaintView(View): super().__init__() self._paint_shader = None self._paint_texture = None - self._tex_width = 256 - self._tex_height = 256 + + # FIXME: When the texture UV-unwrapping is done, these two values will need to be set to a proper value (suggest 4096 for both). + self._tex_width = 512 + self._tex_height = 512 def _checkSetup(self): if not self._paint_shader: @@ -29,8 +33,8 @@ class PaintView(View): self._paint_texture = OpenGL.getInstance().createTexture(self._tex_width, self._tex_height) self._paint_shader.setTexture(0, self._paint_texture) - def setUvPixel(self, x, y, color) -> None: - self._paint_texture.setPixel(x, y, color) + def addStroke(self, stroke_image: QImage, start_x: int, start_y: int) -> None: + self._paint_texture.setSubImage(stroke_image, start_x, start_y) def getUvTexDimensions(self): return self._tex_width, self._tex_height From 4e5b0115ea39e01dee33c9d11a3a1c5d81244f9d Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 28 May 2025 14:39:07 +0200 Subject: [PATCH 135/299] Painting: Separate brush image didn't work properly, construct stroke-image by pen instead. This also simplifies things nicely. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 73 ++++++++++++---------------------- 1 file changed, 25 insertions(+), 48 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 90482d0055..648ad9e1b3 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -3,7 +3,7 @@ import numpy from PyQt6.QtCore import Qt -from PyQt6.QtGui import QImage, QPainter, QColor, QBrush +from PyQt6.QtGui import QImage, QPainter, QColor, QBrush, QPen from typing import cast, Dict, List, Optional, Tuple from UM.Application import Application @@ -18,8 +18,7 @@ from .PaintView import PaintView class PaintTool(Tool): - """Provides the tool to paint meshes. - """ + """Provides the tool to paint meshes.""" def __init__(self) -> None: super().__init__() @@ -42,82 +41,60 @@ class PaintTool(Tool): self._brush_size: int = 10 self._brush_color: str = "A" self._brush_shape: str = "A" - self._brush_image = self._createBrushImage() + self._brush_pen: Optional[QPen] = None self._mouse_held: bool = False self._last_text_coords: Optional[Tuple[int, int]] = None - def _createBrushImage(self) -> QImage: - brush_image = QImage(self._brush_size, self._brush_size, QImage.Format.Format_RGBA8888) - brush_image.fill(QColor(255,255,255,0)) - + def _createBrushPen(self) -> QPen: + pen = QPen() + pen.setWidth(self._brush_size) color = self._color_str_to_rgba[self._brush_color] - qcolor = QColor(color[0], color[1], color[2], color[3]) - - painter = QPainter(brush_image) - painter.setRenderHint(QPainter.RenderHint.Antialiasing, False) - painter.setPen(Qt.PenStyle.NoPen) - painter.setBrush(QBrush(qcolor)) + pen.setColor(QColor(color[0], color[1], color[2], color[3])) match self._brush_shape: - case "A": # Square brush - painter.drawRect(0, 0, self._brush_size, self._brush_size) - case "B": # Circle brush - painter.drawEllipse(0, 0, self._brush_size, self._brush_size) - case _: - painter.drawRect(0, 0, self._brush_size, self._brush_size) - painter.end() - - return brush_image + case "A": + pen.setCapStyle(Qt.PenCapStyle.SquareCap) + case "B": + pen.setCapStyle(Qt.PenCapStyle.RoundCap) + return pen def _createStrokeImage(self, x0: float, y0: float, x1: float, y1: float) -> Tuple[QImage, Tuple[int, int]]: - distance = numpy.hypot(x1 - x0, y1 - y0) - angle = numpy.arctan2(y1 - y0, x1 - x0) - stroke_width = self._brush_size - stroke_height = int(distance) + self._brush_size + xdiff = int(x1 - x0) + ydiff = int(y1 - y0) half_brush_size = self._brush_size // 2 - start_x = int(x0 - half_brush_size) - start_y = int(y0 - half_brush_size) + start_x = int(min(x0, x1) - half_brush_size) + start_y = int(min(y0, y1) - half_brush_size) - stroke_image = QImage(stroke_height, stroke_width, QImage.Format.Format_RGBA8888) - stroke_image.fill(QColor(255,255,255,0)) + stroke_image = QImage(abs(xdiff) + self._brush_size, abs(ydiff) + self._brush_size, QImage.Format.Format_RGBA8888) + stroke_image.fill(QColor(0,0,0,0)) painter = QPainter(stroke_image) - painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform) painter.setRenderHint(QPainter.RenderHint.Antialiasing, False) - - # rotate the brush-image to follow the stroke-direction - transform = painter.transform() - transform.translate(0, stroke_width / 2) # translate to match the brush-alignment - transform.rotate(-numpy.degrees(angle)) - painter.setTransform(transform) - - # tile the brush along the stroke-length - brush_stride = max(1, half_brush_size) - for i in range(0, int(distance) + brush_stride, brush_stride): - painter.drawImage(i, -stroke_width, self._brush_image) + painter.setPen(self._brush_pen) + painter.drawLine(int(x0 - start_x), int(y0 - start_y), int(x1 - start_x), int(y1 - start_y)) painter.end() return stroke_image, (start_x, start_y) def setPaintType(self, paint_type: str) -> None: Logger.warning(f"TODO: Implement paint-types ({paint_type}).") - pass # FIXME: ... and also please call `self._stroke_image = self._createBrushStrokeImage()` (see other funcs). + pass # FIXME: ... and also please call `self._brush_pen = self._createBrushPen()` (see other funcs). def setBrushSize(self, brush_size: float) -> None: if brush_size != self._brush_size: self._brush_size = int(brush_size) - self._brush_image = self._createBrushImage() + self._brush_pen = self._createBrushPen() def setBrushColor(self, brush_color: str) -> None: if brush_color != self._brush_color: self._brush_color = brush_color - self._brush_image = self._createBrushImage() + self._brush_pen = self._createBrushPen() def setBrushShape(self, brush_shape: str) -> None: if brush_shape != self._brush_shape: self._brush_shape = brush_shape - self._brush_image = self._createBrushImage() + self._brush_pen = self._createBrushPen() @staticmethod def _get_intersect_ratio_via_pt(a: numpy.ndarray, pt: numpy.ndarray, b: numpy.ndarray, c: numpy.ndarray) -> float: @@ -147,7 +124,7 @@ class PaintTool(Tool): def _getTexCoordsFromClick(self, node: SceneNode, x: int, y: int) -> Optional[Tuple[float, float]]: face_id = self._selection_pass.getFaceIdAtPosition(x, y) - if face_id < 0: + if face_id < 0 or face_id >= node.getMeshData().getFaceCount(): return None pt = self._picking_pass.getPickedPosition(x, y).getData() From 50ea216a608a943f9fb0f03e7f9e7ec6882d9efc Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 28 May 2025 15:13:22 +0200 Subject: [PATCH 136/299] Store UV coordinates to 3MF file CURA-12544 --- plugins/3MFWriter/ThreeMFWriter.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 558b36576f..1cab5c6b71 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -109,7 +109,8 @@ class ThreeMFWriter(MeshWriter): def _convertUMNodeToSavitarNode(um_node, transformation = Matrix(), exported_settings: Optional[Dict[str, Set[str]]] = None, - center_mesh = False): + center_mesh = False, + scene: Savitar.Scene = None): """Convenience function that converts an Uranium SceneNode object to a SavitarSceneNode :returns: Uranium Scene node. @@ -150,7 +151,11 @@ class ThreeMFWriter(MeshWriter): if indices_array is not None: savitar_node.getMeshData().setFacesFromBytes(indices_array) else: - savitar_node.getMeshData().setFacesFromBytes(numpy.arange(mesh_data.getVertices().size / 3, dtype=numpy.int32).tostring()) + savitar_node.getMeshData().setFacesFromBytes(numpy.arange(mesh_data.getVertices().size / 3, dtype=numpy.int32).tobytes()) + + uv_coordinates_array = mesh_data.getUVCoordinatesAsByteArray() + if uv_coordinates_array is not None and len(uv_coordinates_array) > 0: + savitar_node.getMeshData().setUVCoordinatesPerVertexAsBytes(uv_coordinates_array, scene) # Handle per object settings (if any) stack = um_node.callDecoration("getStack") @@ -187,7 +192,8 @@ class ThreeMFWriter(MeshWriter): if child_node.callDecoration("getBuildPlateNumber") != active_build_plate_nr: continue savitar_child_node = ThreeMFWriter._convertUMNodeToSavitarNode(child_node, - exported_settings = exported_settings) + exported_settings = exported_settings, + scene = scene) if savitar_child_node is not None: savitar_node.addChild(savitar_child_node) @@ -320,13 +326,15 @@ class ThreeMFWriter(MeshWriter): savitar_node = ThreeMFWriter._convertUMNodeToSavitarNode(root_child, transformation_matrix, exported_model_settings, - center_mesh = True) + center_mesh = True, + scene = savitar_scene) if savitar_node: savitar_scene.addSceneNode(savitar_node) else: savitar_node = self._convertUMNodeToSavitarNode(node, transformation_matrix, - exported_model_settings) + exported_model_settings, + scene = savitar_scene) if savitar_node: savitar_scene.addSceneNode(savitar_node) @@ -500,7 +508,7 @@ class ThreeMFWriter(MeshWriter): def sceneNodesToString(scene_nodes: [SceneNode]) -> str: savitar_scene = Savitar.Scene() for scene_node in scene_nodes: - savitar_node = ThreeMFWriter._convertUMNodeToSavitarNode(scene_node, center_mesh = True) + savitar_node = ThreeMFWriter._convertUMNodeToSavitarNode(scene_node, center_mesh = True, scene = savitar_scene) savitar_scene.addSceneNode(savitar_node) parser = Savitar.ThreeMFParser() scene_string = parser.sceneToString(savitar_scene) From c9ca999f106ef22207d71f50d22915b1c493a8c5 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 28 May 2025 16:43:33 +0200 Subject: [PATCH 137/299] PaintTool: Undo/Redo should be working now. Also fix missing pen-shape I suppose. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 49 ++++++++++++++++++++++++++---- plugins/PaintTool/PaintTool.qml | 35 +++++++++++++++++++++ plugins/PaintTool/PaintView.py | 54 ++++++++++++++++++++++++++++++--- 3 files changed, 128 insertions(+), 10 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 648ad9e1b3..cf87772d0b 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -41,9 +41,12 @@ class PaintTool(Tool): self._brush_size: int = 10 self._brush_color: str = "A" self._brush_shape: str = "A" - self._brush_pen: Optional[QPen] = None + self._brush_pen: QPen = self._createBrushPen() self._mouse_held: bool = False + self._ctrl_held: bool = False + self._shift_held: bool = False + self._last_text_coords: Optional[Tuple[int, int]] = None def _createBrushPen(self) -> QPen: @@ -96,6 +99,20 @@ class PaintTool(Tool): self._brush_shape = brush_shape self._brush_pen = self._createBrushPen() + def undoStackAction(self, redo_instead: bool) -> bool: + paintview = Application.getInstance().getController().getActiveView() + if paintview is None or paintview.getPluginId() != "PaintTool": + return False + paintview = cast(PaintView, paintview) + if redo_instead: + paintview.redoStroke() + else: + paintview.undoStroke() + nodes = Selection.getAllSelectedObjects() + if len(nodes) > 0: + Application.getInstance().getController().getScene().sceneChanged.emit(nodes[0]) + return True + @staticmethod def _get_intersect_ratio_via_pt(a: numpy.ndarray, pt: numpy.ndarray, b: numpy.ndarray, c: numpy.ndarray) -> float: # compute the intersection of (param) A - pt with (param) B - (param) C @@ -154,6 +171,10 @@ class PaintTool(Tool): super().event(event) controller = Application.getInstance().getController() + nodes = Selection.getAllSelectedObjects() + if len(nodes) <= 0: + return False + node = nodes[0] # Make sure the displayed values are updated if the bounding box of the selected mesh(es) changes if event.type == Event.ToolActivateEvent: @@ -166,7 +187,27 @@ class PaintTool(Tool): controller.setActiveView("SolidView") return True - if event.type == Event.KeyPressEvent and cast(KeyEvent, event).key == KeyEvent.ShiftKey: + if event.type == Event.KeyPressEvent: + evt = cast(KeyEvent, event) + if evt.key == KeyEvent.ControlKey: + self._ctrl_held = True + return True + if evt.key == KeyEvent.ShiftKey: + self._shift_held = True + return True + return False + + if event.type == Event.KeyReleaseEvent: + evt = cast(KeyEvent, event) + if evt.key == KeyEvent.ControlKey: + self._ctrl_held = False + return True + if evt.key == KeyEvent.ShiftKey: + self._shift_held = False + return True + if evt.key == Qt.Key.Key_L and self._ctrl_held: + # NOTE: Ctrl-L is used here instead of Ctrl-Z, as the latter is the application-wide one that takes precedence. + return self.undoStackAction(self._shift_held) return False if event.type == Event.MouseReleaseEvent and self._controller.getToolsEnabled(): @@ -201,10 +242,6 @@ class PaintTool(Tool): if not camera: return False - node = Selection.getAllSelectedObjects()[0] - if node is None: - return False - if node != self._node_cache: if self._node_cache is not None: self._node_cache.transformationChanged.disconnect(self._nodeTransformChanged) diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index 82d6d90ffd..a1fac9c3a3 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -176,5 +176,40 @@ Item } } } + + RowLayout + { + UM.ToolbarButton + { + id: undoButton + + text: catalog.i18nc("@action:button", "Undo Stroke") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("ArrowReset") + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("undoStackAction", false) + } + + UM.ToolbarButton + { + id: redoButton + + text: catalog.i18nc("@action:button", "Redo Stroke") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("ArrowDoubleCircleRight") + } + property bool needBorder: true + + z: 2 + + onClicked: UM.Controller.triggerActionWithData("undoStackAction", true) + } + } } } diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index b86d59b9df..5fb62436c6 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -2,9 +2,13 @@ # Cura is released under the terms of the LGPLv3 or higher. import os -from PyQt6.QtGui import QImage +from typing import Optional, List, Tuple + +from PyQt6.QtGui import QImage, QColor, QPainter from UM.PluginRegistry import PluginRegistry +from UM.View.GL.ShaderProgram import ShaderProgram +from UM.View.GL.Texture import Texture from UM.View.View import View from UM.Scene.Selection import Selection from UM.View.GL.OpenGL import OpenGL @@ -16,15 +20,23 @@ catalog = i18nCatalog("cura") class PaintView(View): """View for model-painting.""" + UNDO_STACK_SIZE = 1024 + def __init__(self) -> None: super().__init__() - self._paint_shader = None - self._paint_texture = None + self._paint_shader: Optional[ShaderProgram] = None + self._paint_texture: Optional[Texture] = None # FIXME: When the texture UV-unwrapping is done, these two values will need to be set to a proper value (suggest 4096 for both). self._tex_width = 512 self._tex_height = 512 + self._stroke_undo_stack: List[Tuple[QImage, int, int]] = [] + self._stroke_redo_stack: List[Tuple[QImage, int, int]] = [] + + self._force_opaque_mask = QImage(2, 2, QImage.Format.Format_Mono) + self._force_opaque_mask.fill(1) + def _checkSetup(self): if not self._paint_shader: shader_filename = os.path.join(PluginRegistry.getInstance().getPluginPath("PaintTool"), "paint.shader") @@ -33,8 +45,42 @@ class PaintView(View): self._paint_texture = OpenGL.getInstance().createTexture(self._tex_width, self._tex_height) self._paint_shader.setTexture(0, self._paint_texture) + def _forceOpaqueDeepCopy(self, image: QImage): + res = QImage(image.width(), image.height(), QImage.Format.Format_RGBA8888) + res.fill(QColor(255, 255, 255, 255)) + painter = QPainter(res) + painter.setRenderHint(QPainter.RenderHint.Antialiasing, False) + painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceOver) + painter.drawImage(0, 0, image) + painter.end() + res.setAlphaChannel(self._force_opaque_mask.scaled(image.width(), image.height())) + return res + def addStroke(self, stroke_image: QImage, start_x: int, start_y: int) -> None: - self._paint_texture.setSubImage(stroke_image, start_x, start_y) + self._stroke_redo_stack.clear() + if len(self._stroke_undo_stack) >= PaintView.UNDO_STACK_SIZE: + self._stroke_undo_stack.pop(0) + undo_image = self._forceOpaqueDeepCopy(self._paint_texture.setSubImage(stroke_image, start_x, start_y)) + if undo_image is not None: + self._stroke_undo_stack.append((undo_image, start_x, start_y)) + + def _applyUndoStacksAction(self, from_stack: List[Tuple[QImage, int, int]], to_stack: List[Tuple[QImage, int, int]]) -> bool: + if len(from_stack) <= 0: + return False + from_image, x, y = from_stack.pop() + to_image = self._forceOpaqueDeepCopy(self._paint_texture.setSubImage(from_image, x, y)) + if to_image is None: + return False + if len(to_stack) >= PaintView.UNDO_STACK_SIZE: + to_stack.pop(0) + to_stack.append((to_image, x, y)) + return True + + def undoStroke(self) -> bool: + return self._applyUndoStacksAction(self._stroke_undo_stack, self._stroke_redo_stack) + + def redoStroke(self) -> bool: + return self._applyUndoStacksAction(self._stroke_redo_stack, self._stroke_undo_stack) def getUvTexDimensions(self): return self._tex_width, self._tex_height From d28c2aac68950efab787353aaa5c3a62ede2033d Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 28 May 2025 17:12:42 +0200 Subject: [PATCH 138/299] Painting: Fix non-drag not producing a circle (square was already OK though). part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index cf87772d0b..2f6d3736f3 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -75,7 +75,10 @@ class PaintTool(Tool): painter = QPainter(stroke_image) painter.setRenderHint(QPainter.RenderHint.Antialiasing, False) painter.setPen(self._brush_pen) - painter.drawLine(int(x0 - start_x), int(y0 - start_y), int(x1 - start_x), int(y1 - start_y)) + if xdiff == 0 and ydiff == 0: + painter.drawPoint(int(x0 - start_x), int(y0 - start_y)) + else: + painter.drawLine(int(x0 - start_x), int(y0 - start_y), int(x1 - start_x), int(y1 - start_y)) painter.end() return stroke_image, (start_x, start_y) From f0764134cc174a4e8ef8fdf70c0f53fe22a99345 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 3 Jun 2025 13:27:57 +0200 Subject: [PATCH 139/299] Store painted texture to 3MF file CURA-12544 Also allows having multiple texture for multiple models while painting --- cura/Scene/SliceableObjectDecorator.py | 11 + plugins/3MFWriter/ThreeMFWriter.py | 55 +- plugins/PaintTool/PaintView.py | 19 +- .../themes/cura-dark-colorblind/theme.json | 27 +- resources/themes/cura-dark/theme.json | 213 +----- .../themes/cura-light-colorblind/theme.json | 30 +- resources/themes/cura-light/theme.json | 690 +----------------- resources/themes/daily_test_colors.json | 16 - 8 files changed, 73 insertions(+), 988 deletions(-) delete mode 100644 resources/themes/daily_test_colors.json diff --git a/cura/Scene/SliceableObjectDecorator.py b/cura/Scene/SliceableObjectDecorator.py index ad51f7d755..a52f7badf4 100644 --- a/cura/Scene/SliceableObjectDecorator.py +++ b/cura/Scene/SliceableObjectDecorator.py @@ -1,12 +1,23 @@ from UM.Scene.SceneNodeDecorator import SceneNodeDecorator +from UM.View.GL.OpenGL import OpenGL +# FIXME: When the texture UV-unwrapping is done, these two values will need to be set to a proper value (suggest 4096 for both). +TEXTURE_WIDTH = 512 +TEXTURE_HEIGHT = 512 + class SliceableObjectDecorator(SceneNodeDecorator): def __init__(self) -> None: super().__init__() + self._paint_texture = None def isSliceable(self) -> bool: return True + def getPaintTexture(self, create_if_required: bool = True): + if self._paint_texture is None and create_if_required: + self._paint_texture = OpenGL.getInstance().createTexture(TEXTURE_WIDTH, TEXTURE_HEIGHT) + return self._paint_texture + def __deepcopy__(self, memo) -> "SliceableObjectDecorator": return type(self)() diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 1cab5c6b71..4cb7840841 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -58,6 +58,8 @@ catalog = i18nCatalog("cura") MODEL_PATH = "3D/3dmodel.model" PACKAGE_METADATA_PATH = "Cura/packages.json" +TEXTURES_PATH = "3D/Textures" +MODEL_RELATIONS_PATH = "3D/_rels/3dmodel.model.rels" class ThreeMFWriter(MeshWriter): def __init__(self): @@ -110,7 +112,10 @@ class ThreeMFWriter(MeshWriter): transformation = Matrix(), exported_settings: Optional[Dict[str, Set[str]]] = None, center_mesh = False, - scene: Savitar.Scene = None): + scene: Savitar.Scene = None, + archive: zipfile.ZipFile = None, + model_relations_element: ET.Element = None, + content_types_element: ET.Element = None): """Convenience function that converts an Uranium SceneNode object to a SavitarSceneNode :returns: Uranium Scene node. @@ -153,9 +158,33 @@ class ThreeMFWriter(MeshWriter): else: savitar_node.getMeshData().setFacesFromBytes(numpy.arange(mesh_data.getVertices().size / 3, dtype=numpy.int32).tobytes()) + texture = um_node.callDecoration("getPaintTexture") uv_coordinates_array = mesh_data.getUVCoordinatesAsByteArray() - if uv_coordinates_array is not None and len(uv_coordinates_array) > 0: - savitar_node.getMeshData().setUVCoordinatesPerVertexAsBytes(uv_coordinates_array, scene) + if texture is not None and archive is not None and uv_coordinates_array is not None and len(uv_coordinates_array) > 0: + texture_image = texture.getImage() + if texture_image is not None: + texture_path = f"{TEXTURES_PATH}/{id(um_node)}.png" + + texture_buffer = QBuffer() + texture_buffer.open(QBuffer.OpenModeFlag.ReadWrite) + texture_image.save(texture_buffer, "PNG") + + texture_file = zipfile.ZipInfo(texture_path) + # Don't try to compress texture file, because the PNG is pretty much as compact as it will get + archive.writestr(texture_file, texture_buffer.data()) + + savitar_node.getMeshData().setUVCoordinatesPerVertexAsBytes(uv_coordinates_array, texture_path, scene) + + # Add texture relation to model relations file + if model_relations_element is not None: + ET.SubElement(model_relations_element, "Relationship", + Target=texture_path, Id=f"rel{len(model_relations_element)+1}", + Type="http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture") + + if content_types_element is not None: + ET.SubElement(content_types_element, "Override", PartName=texture_path, + ContentType="application/vnd.ms-package.3dmanufacturing-3dmodeltexture") + # Handle per object settings (if any) stack = um_node.callDecoration("getStack") @@ -193,7 +222,10 @@ class ThreeMFWriter(MeshWriter): continue savitar_child_node = ThreeMFWriter._convertUMNodeToSavitarNode(child_node, exported_settings = exported_settings, - scene = scene) + scene = scene, + archive = archive, + model_relations_element = model_relations_element, + content_types_element = content_types_element) if savitar_child_node is not None: savitar_node.addChild(savitar_child_node) @@ -255,6 +287,9 @@ class ThreeMFWriter(MeshWriter): # Create Metadata/_rels/model_settings.config.rels metadata_relations_element = self._makeRelationsTree() + # Create model relations + model_relations_element = self._makeRelationsTree() + # Let the variant add its specific files variant.add_extra_files(archive, metadata_relations_element) @@ -327,14 +362,20 @@ class ThreeMFWriter(MeshWriter): transformation_matrix, exported_model_settings, center_mesh = True, - scene = savitar_scene) + scene = savitar_scene, + archive = archive, + model_relations_element = model_relations_element, + content_types_element = content_types) if savitar_node: savitar_scene.addSceneNode(savitar_node) else: savitar_node = self._convertUMNodeToSavitarNode(node, transformation_matrix, exported_model_settings, - scene = savitar_scene) + scene = savitar_scene, + archive = archive, + model_relations_element = model_relations_element, + content_types_element = content_types) if savitar_node: savitar_scene.addSceneNode(savitar_node) @@ -346,6 +387,8 @@ class ThreeMFWriter(MeshWriter): self._storeElementTree(archive, "_rels/.rels", relations_element) if len(metadata_relations_element) > 0: self._storeElementTree(archive, "Metadata/_rels/model_settings.config.rels", metadata_relations_element) + if len(model_relations_element) > 0: + self._storeElementTree(archive, MODEL_RELATIONS_PATH, model_relations_element) except Exception as error: Logger.logException("e", "Error writing zip file") self.setInformation(str(error)) diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index b86d59b9df..c50d957ee2 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -19,25 +19,21 @@ class PaintView(View): def __init__(self) -> None: super().__init__() self._paint_shader = None - self._paint_texture = None - - # FIXME: When the texture UV-unwrapping is done, these two values will need to be set to a proper value (suggest 4096 for both). - self._tex_width = 512 - self._tex_height = 512 + self._current_paint_texture = None def _checkSetup(self): if not self._paint_shader: shader_filename = os.path.join(PluginRegistry.getInstance().getPluginPath("PaintTool"), "paint.shader") self._paint_shader = OpenGL.getInstance().createShaderProgram(shader_filename) - if not self._paint_texture: - self._paint_texture = OpenGL.getInstance().createTexture(self._tex_width, self._tex_height) - self._paint_shader.setTexture(0, self._paint_texture) def addStroke(self, stroke_image: QImage, start_x: int, start_y: int) -> None: - self._paint_texture.setSubImage(stroke_image, start_x, start_y) + if self._current_paint_texture is not None: + self._current_paint_texture.setSubImage(stroke_image, start_x, start_y) def getUvTexDimensions(self): - return self._tex_width, self._tex_height + if self._current_paint_texture is not None: + return self._current_paint_texture.getWidth(), self._current_paint_texture.getHeight() + return 0, 0 def beginRendering(self) -> None: renderer = self.getRenderer() @@ -48,4 +44,7 @@ class PaintView(View): node = Selection.getAllSelectedObjects()[0] if node is None: return + + self._current_paint_texture = node.callDecoration("getPaintTexture") + self._paint_shader.setTexture(0, self._current_paint_texture) paint_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix()) diff --git a/resources/themes/cura-dark-colorblind/theme.json b/resources/themes/cura-dark-colorblind/theme.json index 4a006ee836..4443111b60 100644 --- a/resources/themes/cura-dark-colorblind/theme.json +++ b/resources/themes/cura-dark-colorblind/theme.json @@ -1,26 +1 @@ -{ - "metadata": { - "name": "Colorblind Assist Dark", - "inherits": "cura-dark" - }, - - "colors": { - "x_axis": [212, 0, 0, 255], - "y_axis": [64, 64, 255, 255], - - "model_overhang": [200, 0, 255, 255], - - "xray": [26, 26, 62, 255], - "xray_error": [255, 0, 0, 255], - - "layerview_inset_0": [255, 64, 0, 255], - "layerview_inset_x": [0, 156, 128, 255], - "layerview_skin": [255, 255, 86, 255], - "layerview_support": [255, 255, 0, 255], - - "layerview_infill": [0, 255, 255, 255], - "layerview_support_infill": [0, 200, 200, 255], - - "layerview_move_retraction": [0, 100, 255, 255] - } -} +{"metadata": {"name": "Colorblind Assist Dark", "inherits": "cura-dark"}, "colors": {"x_axis": [212, 0, 0, 255], "y_axis": [64, 64, 255, 255], "model_overhang": [200, 0, 255, 255], "xray": [26, 26, 62, 255], "xray_error": [255, 0, 0, 255], "layerview_inset_0": [255, 64, 0, 255], "layerview_inset_x": [0, 156, 128, 255], "layerview_skin": [255, 255, 86, 255], "layerview_support": [255, 255, 0, 255], "layerview_infill": [0, 255, 255, 255], "layerview_support_infill": [0, 200, 200, 255], "layerview_move_retraction": [0, 100, 255, 255], "main_window_header_background": [192, 199, 65, 255]}} \ No newline at end of file diff --git a/resources/themes/cura-dark/theme.json b/resources/themes/cura-dark/theme.json index 1517b22eb9..29be47e697 100644 --- a/resources/themes/cura-dark/theme.json +++ b/resources/themes/cura-dark/theme.json @@ -1,212 +1 @@ -{ - "metadata": { - "name": "UltiMaker Dark", - "inherits": "cura-light" - }, - - "base_colors": - { - "background_1": [31, 31, 32, 255], - "background_2": [57, 57, 58, 255], - "background_3": [85, 85, 87, 255], - "background_4": [23, 23, 23, 255], - - "accent_1": [25, 110, 240, 255], - "accent_2": [16, 70, 156, 255], - "border_main": [118, 118, 119, 255], - "border_accent_1": [255, 255, 255, 255], - "border_accent_2": [243, 243, 243, 255], - "border_field": [57, 57, 58, 255], - - "text_default": [255, 255, 255, 255], - "text_disabled": [118, 118, 118, 255], - "text_primary_button": [255, 255, 255, 255], - "text_secondary_button": [255, 255, 255, 255], - "text_link_hover": [156, 195, 255, 255], - "text_lighter": [243, 243, 243, 255], - - "um_green_1": [233, 245, 237, 255], - "um_green_5": [36, 162, 73, 255], - "um_green_9": [31, 44, 36, 255], - "um_red_1": [251, 232, 233, 255], - "um_red_5": [218, 30, 40, 255], - "um_red_9": [59, 31, 33, 255], - "um_orange_1": [255, 235, 221, 255], - "um_orange_5": [252, 123, 30, 255], - "um_orange_9": [64, 45, 32, 255], - "um_yellow_1": [255, 248, 225, 255], - "um_yellow_5": [253, 209, 58, 255], - "um_yellow_9": [64, 58, 36, 255] - }, - - "colors": { - "main_background": "background_1", - "detail_background": "background_2", - "message_background": "background_1", - "wide_lining": [31, 36, 39, 255], - "thick_lining": [255, 255, 255, 60], - "lining": "border_main", - "viewport_overlay": "background_1", - - "primary_text": "text_default", - "secondary": [95, 95, 95, 255], - - "expandable_active": "background_2", - "expandable_hover": "background_2", - - "secondary_button": "background_1", - "secondary_button_hover": "background_3", - "secondary_button_text": "text_secondary_button", - - "icon": "text_default", - "toolbar_background": "background_1", - "toolbar_button_active": "background_3", - "toolbar_button_hover": "background_3", - "toolbar_button_active_hover": "background_3", - - "main_window_header_button_background_inactive": "background_4", - "main_window_header_button_text_inactive": "text_primary_button", - "main_window_header_button_text_active": "background_4", - "main_window_header_background": "background_4", - "main_window_header_background_gradient": "background_4", - "main_window_header_button_background_hovered": [46, 46, 46, 255], - - "account_sync_state_icon": [255, 255, 255, 204], - - "machine_selector_printer_icon": [204, 204, 204, 255], - - "text": "text_default", - "text_detail": [255, 255, 255, 172], - "text_link": "accent_1", - "text_inactive": [118, 118, 118, 255], - "text_hover": [255, 255, 255, 255], - "text_scene": [250, 250, 250, 255], - "text_scene_hover": [255, 255, 255, 255], - - "printer_type_label_background": [95, 95, 95, 255], - - "error": [212, 31, 53, 255], - "disabled": [32, 32, 32, 255], - - "button": [39, 44, 48, 255], - "button_hover": [39, 44, 48, 255], - "button_text": "text_default", - "button_disabled": [39, 44, 48, 255], - "button_disabled_text": [255, 255, 255, 101], - - "small_button_text": [255, 255, 255, 197], - "small_button_text_hover": [255, 255, 255, 255], - - "button_tooltip": [39, 44, 48, 255], - - "tab_checked": [39, 44, 48, 255], - "tab_checked_border": [255, 255, 255, 30], - "tab_checked_text": [255, 255, 255, 255], - "tab_unchecked": [39, 44, 48, 255], - "tab_unchecked_border": [255, 255, 255, 30], - "tab_unchecked_text": [255, 255, 255, 101], - "tab_hovered": [39, 44, 48, 255], - "tab_hovered_border": [255, 255, 255, 30], - "tab_hovered_text": [255, 255, 255, 255], - "tab_active": [39, 44, 48, 255], - "tab_active_border": [255, 255, 255, 30], - "tab_active_text": [255, 255, 255, 255], - "tab_background": [39, 44, 48, 255], - - "action_button": "background_1", - "action_button_text": [255, 255, 255, 200], - "action_button_border": "border_main", - "action_button_hovered": [79, 85, 89, 255], - "action_button_hovered_text": "text_default", - "action_button_hovered_border": "border_main", - "action_button_active": [39, 44, 48, 30], - "action_button_active_text": "text_default", - "action_button_active_border": [255, 255, 255, 100], - "action_button_disabled": "background_3", - "action_button_disabled_text": "text_disabled", - "action_button_disabled_border": [255, 255, 255, 30], - - "scrollbar_background": [39, 44, 48, 0], - "scrollbar_handle": [255, 255, 255, 105], - "scrollbar_handle_hover": [255, 255, 255, 255], - "scrollbar_handle_down": [255, 255, 255, 255], - - "setting_category_disabled": [75, 80, 83, 255], - "setting_category_disabled_text": [255, 255, 255, 101], - - "setting_control": "background_2", - "setting_control_selected": [34, 39, 42, 38], - "setting_control_highlight": "background_3", - "setting_control_border": [255, 255, 255, 38], - "setting_control_border_highlight": [12, 169, 227, 255], - "setting_control_text": "text_default", - "setting_control_button": [255, 255, 255, 127], - "setting_control_button_hover": [255, 255, 255, 204], - "setting_control_disabled": [34, 39, 42, 255], - "setting_control_disabled_text": [255, 255, 255, 101], - "setting_control_disabled_border": [255, 255, 255, 101], - "setting_unit": [255, 255, 255, 127], - "setting_validation_error_background": "um_red_9", - "setting_validation_warning_background": "um_yellow_9", - "setting_validation_ok": "background_2", - - "progressbar_background": [255, 255, 255, 48], - "progressbar_control": [255, 255, 255, 197], - - "slider_groove": [127, 127, 127, 255], - "slider_groove_border": [127, 127, 127, 255], - "slider_groove_fill": [245, 245, 245, 255], - "slider_handle": [255, 255, 255, 255], - "slider_handle_active": [68, 192, 255, 255], - - "category_background": "background_3", - - "tooltip": "background_2", - "tooltip_text": "text_default", - - "tool_panel_background": "background_1", - - "viewport_background": "background_1", - "volume_outline": [12, 169, 227, 128], - "buildplate": [169, 169, 169, 255], - "buildplate_grid_minor": [154, 154, 155, 255], - - "disallowed_area": [0, 0, 0, 52], - - "model_selection_outline": [12, 169, 227, 255], - - "material_compatibility_warning": [255, 255, 255, 255], - - "core_compatibility_warning": [255, 255, 255, 255], - - "quality_slider_available": [255, 255, 255, 255], - - "monitor_printer_family_tag": [86, 86, 106, 255], - "monitor_text_disabled": [102, 102, 102, 255], - "monitor_icon_primary": [229, 229, 229, 255], - "monitor_icon_accent": [51, 53, 54, 255], - "monitor_icon_disabled": [102, 102, 102, 255], - - "monitor_secondary_button_hover": [80, 80, 80, 255], - "monitor_card_border": [102, 102, 102, 255], - "monitor_card_background": [51, 53, 54, 255], - "monitor_card_hover": [84, 89, 95, 255], - - "monitor_stage_background": "background_1", - "monitor_stage_background_fade": "background_1", - - "monitor_progress_bar_deactive": [102, 102, 102, 255], - "monitor_progress_bar_empty": [67, 67, 67, 255], - - "monitor_tooltip_text": [229, 229, 229, 255], - "monitor_context_menu": [67, 67, 67, 255], - "monitor_context_menu_hover": [30, 102, 215, 255], - - "monitor_skeleton_loading": [102, 102, 102, 255], - "monitor_placeholder_image": [102, 102, 102, 255], - "monitor_shadow": [4, 10, 13, 255], - - "monitor_carousel_dot": [119, 119, 119, 255], - "monitor_carousel_dot_current": [216, 216, 216, 255] - } -} +{"metadata": {"name": "UltiMaker Dark", "inherits": "cura-light"}, "base_colors": {"background_1": [31, 31, 32, 255], "background_2": [57, 57, 58, 255], "background_3": [85, 85, 87, 255], "background_4": [23, 23, 23, 255], "accent_1": [25, 110, 240, 255], "accent_2": [16, 70, 156, 255], "border_main": [118, 118, 119, 255], "border_accent_1": [255, 255, 255, 255], "border_accent_2": [243, 243, 243, 255], "border_field": [57, 57, 58, 255], "text_default": [255, 255, 255, 255], "text_disabled": [118, 118, 118, 255], "text_primary_button": [255, 255, 255, 255], "text_secondary_button": [255, 255, 255, 255], "text_link_hover": [156, 195, 255, 255], "text_lighter": [243, 243, 243, 255], "um_green_1": [233, 245, 237, 255], "um_green_5": [36, 162, 73, 255], "um_green_9": [31, 44, 36, 255], "um_red_1": [251, 232, 233, 255], "um_red_5": [218, 30, 40, 255], "um_red_9": [59, 31, 33, 255], "um_orange_1": [255, 235, 221, 255], "um_orange_5": [252, 123, 30, 255], "um_orange_9": [64, 45, 32, 255], "um_yellow_1": [255, 248, 225, 255], "um_yellow_5": [253, 209, 58, 255], "um_yellow_9": [64, 58, 36, 255]}, "colors": {"main_background": "background_1", "detail_background": "background_2", "message_background": "background_1", "wide_lining": [31, 36, 39, 255], "thick_lining": [255, 255, 255, 60], "lining": "border_main", "viewport_overlay": "background_1", "primary_text": "text_default", "secondary": [95, 95, 95, 255], "expandable_active": "background_2", "expandable_hover": "background_2", "secondary_button": "background_1", "secondary_button_hover": "background_3", "secondary_button_text": "text_secondary_button", "icon": "text_default", "toolbar_background": "background_1", "toolbar_button_active": "background_3", "toolbar_button_hover": "background_3", "toolbar_button_active_hover": "background_3", "main_window_header_button_background_inactive": "background_4", "main_window_header_button_text_inactive": "text_primary_button", "main_window_header_button_text_active": "background_4", "main_window_header_background": [192, 199, 65, 255], "main_window_header_background_gradient": "background_4", "main_window_header_button_background_hovered": [46, 46, 46, 255], "account_sync_state_icon": [255, 255, 255, 204], "machine_selector_printer_icon": [204, 204, 204, 255], "text": "text_default", "text_detail": [255, 255, 255, 172], "text_link": "accent_1", "text_inactive": [118, 118, 118, 255], "text_hover": [255, 255, 255, 255], "text_scene": [250, 250, 250, 255], "text_scene_hover": [255, 255, 255, 255], "printer_type_label_background": [95, 95, 95, 255], "error": [212, 31, 53, 255], "disabled": [32, 32, 32, 255], "button": [39, 44, 48, 255], "button_hover": [39, 44, 48, 255], "button_text": "text_default", "button_disabled": [39, 44, 48, 255], "button_disabled_text": [255, 255, 255, 101], "small_button_text": [255, 255, 255, 197], "small_button_text_hover": [255, 255, 255, 255], "button_tooltip": [39, 44, 48, 255], "tab_checked": [39, 44, 48, 255], "tab_checked_border": [255, 255, 255, 30], "tab_checked_text": [255, 255, 255, 255], "tab_unchecked": [39, 44, 48, 255], "tab_unchecked_border": [255, 255, 255, 30], "tab_unchecked_text": [255, 255, 255, 101], "tab_hovered": [39, 44, 48, 255], "tab_hovered_border": [255, 255, 255, 30], "tab_hovered_text": [255, 255, 255, 255], "tab_active": [39, 44, 48, 255], "tab_active_border": [255, 255, 255, 30], "tab_active_text": [255, 255, 255, 255], "tab_background": [39, 44, 48, 255], "action_button": "background_1", "action_button_text": [255, 255, 255, 200], "action_button_border": "border_main", "action_button_hovered": [79, 85, 89, 255], "action_button_hovered_text": "text_default", "action_button_hovered_border": "border_main", "action_button_active": [39, 44, 48, 30], "action_button_active_text": "text_default", "action_button_active_border": [255, 255, 255, 100], "action_button_disabled": "background_3", "action_button_disabled_text": "text_disabled", "action_button_disabled_border": [255, 255, 255, 30], "scrollbar_background": [39, 44, 48, 0], "scrollbar_handle": [255, 255, 255, 105], "scrollbar_handle_hover": [255, 255, 255, 255], "scrollbar_handle_down": [255, 255, 255, 255], "setting_category_disabled": [75, 80, 83, 255], "setting_category_disabled_text": [255, 255, 255, 101], "setting_control": "background_2", "setting_control_selected": [34, 39, 42, 38], "setting_control_highlight": "background_3", "setting_control_border": [255, 255, 255, 38], "setting_control_border_highlight": [12, 169, 227, 255], "setting_control_text": "text_default", "setting_control_button": [255, 255, 255, 127], "setting_control_button_hover": [255, 255, 255, 204], "setting_control_disabled": [34, 39, 42, 255], "setting_control_disabled_text": [255, 255, 255, 101], "setting_control_disabled_border": [255, 255, 255, 101], "setting_unit": [255, 255, 255, 127], "setting_validation_error_background": "um_red_9", "setting_validation_warning_background": "um_yellow_9", "setting_validation_ok": "background_2", "progressbar_background": [255, 255, 255, 48], "progressbar_control": [255, 255, 255, 197], "slider_groove": [127, 127, 127, 255], "slider_groove_border": [127, 127, 127, 255], "slider_groove_fill": [245, 245, 245, 255], "slider_handle": [255, 255, 255, 255], "slider_handle_active": [68, 192, 255, 255], "category_background": "background_3", "tooltip": "background_2", "tooltip_text": "text_default", "tool_panel_background": "background_1", "viewport_background": "background_1", "volume_outline": [12, 169, 227, 128], "buildplate": [169, 169, 169, 255], "buildplate_grid_minor": [154, 154, 155, 255], "disallowed_area": [0, 0, 0, 52], "model_selection_outline": [12, 169, 227, 255], "material_compatibility_warning": [255, 255, 255, 255], "core_compatibility_warning": [255, 255, 255, 255], "quality_slider_available": [255, 255, 255, 255], "monitor_printer_family_tag": [86, 86, 106, 255], "monitor_text_disabled": [102, 102, 102, 255], "monitor_icon_primary": [229, 229, 229, 255], "monitor_icon_accent": [51, 53, 54, 255], "monitor_icon_disabled": [102, 102, 102, 255], "monitor_secondary_button_hover": [80, 80, 80, 255], "monitor_card_border": [102, 102, 102, 255], "monitor_card_background": [51, 53, 54, 255], "monitor_card_hover": [84, 89, 95, 255], "monitor_stage_background": "background_1", "monitor_stage_background_fade": "background_1", "monitor_progress_bar_deactive": [102, 102, 102, 255], "monitor_progress_bar_empty": [67, 67, 67, 255], "monitor_tooltip_text": [229, 229, 229, 255], "monitor_context_menu": [67, 67, 67, 255], "monitor_context_menu_hover": [30, 102, 215, 255], "monitor_skeleton_loading": [102, 102, 102, 255], "monitor_placeholder_image": [102, 102, 102, 255], "monitor_shadow": [4, 10, 13, 255], "monitor_carousel_dot": [119, 119, 119, 255], "monitor_carousel_dot_current": [216, 216, 216, 255]}} \ No newline at end of file diff --git a/resources/themes/cura-light-colorblind/theme.json b/resources/themes/cura-light-colorblind/theme.json index 740bf977b2..cc7ed5dfba 100644 --- a/resources/themes/cura-light-colorblind/theme.json +++ b/resources/themes/cura-light-colorblind/theme.json @@ -1,29 +1 @@ -{ - "metadata": { - "name": "Colorblind Assist Light", - "inherits": "cura-light" - }, - - "colors": { - - "x_axis": [200, 0, 0, 255], - "y_axis": [64, 64, 255, 255], - "model_overhang": [200, 0, 255, 255], - "model_selection_outline": [12, 169, 227, 255], - - "xray_error_dark": [255, 0, 0, 255], - "xray_error_light": [255, 255, 0, 255], - "xray": [26, 26, 62, 255], - "xray_error": [255, 0, 0, 255], - - "layerview_inset_0": [255, 64, 0, 255], - "layerview_inset_x": [0, 156, 128, 255], - "layerview_skin": [255, 255, 86, 255], - "layerview_support": [255, 255, 0, 255], - - "layerview_infill": [0, 255, 255, 255], - "layerview_support_infill": [0, 200, 200, 255], - - "layerview_move_retraction": [0, 100, 255, 255] - } -} +{"metadata": {"name": "Colorblind Assist Light", "inherits": "cura-light"}, "colors": {"x_axis": [200, 0, 0, 255], "y_axis": [64, 64, 255, 255], "model_overhang": [200, 0, 255, 255], "model_selection_outline": [12, 169, 227, 255], "xray_error_dark": [255, 0, 0, 255], "xray_error_light": [255, 255, 0, 255], "xray": [26, 26, 62, 255], "xray_error": [255, 0, 0, 255], "layerview_inset_0": [255, 64, 0, 255], "layerview_inset_x": [0, 156, 128, 255], "layerview_skin": [255, 255, 86, 255], "layerview_support": [255, 255, 0, 255], "layerview_infill": [0, 255, 255, 255], "layerview_support_infill": [0, 200, 200, 255], "layerview_move_retraction": [0, 100, 255, 255], "main_window_header_background": [192, 199, 65, 255]}} \ No newline at end of file diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 377e70f5b6..2362155944 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -1,689 +1 @@ -{ - "metadata": { - "name": "UltiMaker" - }, - - "fonts": { - "large": { - "size": 1.35, - "weight": 400, - "family": "Noto Sans" - }, - "large_ja_JP": { - "size": 1.35, - "weight": 400, - "family": "Noto Sans" - }, - "large_zh_CN": { - "size": 1.35, - "weight": 400, - "family": "Noto Sans" - }, - "large_zh_TW": { - "size": 1.35, - "weight": 400, - "family": "Noto Sans" - }, - "large_bold": { - "size": 1.35, - "weight": 600, - "family": "Noto Sans" - }, - "huge": { - "size": 1.8, - "weight": 400, - "family": "Noto Sans" - }, - "huge_bold": { - "size": 1.8, - "weight": 600, - "family": "Noto Sans" - }, - "medium": { - "size": 1.16, - "weight": 400, - "family": "Noto Sans" - }, - "medium_ja_JP": { - "size": 1.16, - "weight": 400, - "family": "Noto Sans" - }, - "medium_zh_CN": { - "size": 1.16, - "weight": 400, - "family": "Noto Sans" - }, - "medium_zh_TW": { - "size": 1.16, - "weight": 400, - "family": "Noto Sans" - }, - "medium_bold": { - "size": 1.16, - "weight": 600, - "family": "Noto Sans" - }, - "default": { - "size": 0.95, - "weight": 400, - "family": "Noto Sans" - }, - "default_ja_JP": { - "size": 1.0, - "weight": 400, - "family": "Noto Sans" - }, - "default_zh_CN": { - "size": 1.0, - "weight": 400, - "family": "Noto Sans" - }, - "default_zh_TW": { - "size": 1.0, - "weight": 400, - "family": "Noto Sans" - }, - "default_bold": { - "size": 0.95, - "weight": 600, - "family": "Noto Sans" - }, - "default_bold_ja_JP": { - "size": 1.0, - "weight": 600, - "family": "Noto Sans" - }, - "default_bold_zh_CN": { - "size": 1.0, - "weight": 600, - "family": "Noto Sans" - }, - "default_bold_zh_TW": { - "size": 1.0, - "weight": 600, - "family": "Noto Sans" - }, - "default_italic": { - "size": 0.95, - "weight": 400, - "italic": true, - "family": "Noto Sans" - }, - "medium_italic": { - "size": 1.16, - "weight": 400, - "italic": true, - "family": "Noto Sans" - }, - "default_italic_ja_JP": { - "size": 1.0, - "weight": 400, - "italic": true, - "family": "Noto Sans" - }, - "default_italic_zh_CN": { - "size": 1.0, - "weight": 400, - "italic": true, - "family": "Noto Sans" - }, - "default_italic_zh_TW": { - "size": 1.0, - "weight": 400, - "italic": true, - "family": "Noto Sans" - }, - "small": { - "size": 0.9, - "weight": 400, - "family": "Noto Sans" - }, - "small_bold": { - "size": 0.9, - "weight": 700, - "family": "Noto Sans" - }, - "small_ja_JP": { - "size": 0.9, - "weight": 400, - "family": "Noto Sans" - }, - "small_zh_CN": { - "size": 0.9, - "weight": 400, - "family": "Noto Sans" - }, - "small_zh_TW": { - "size": 0.9, - "weight": 400, - "family": "Noto Sans" - }, - "small_emphasis": { - "size": 0.9, - "weight": 700, - "family": "Noto Sans" - }, - "small_emphasis_ja_JP": { - "size": 0.9, - "weight": 700, - "family": "Noto Sans" - }, - "small_emphasis_zh_CN": { - "size": 0.9, - "weight": 700, - "family": "Noto Sans" - }, - "small_emphasis_zh_TW": { - "size": 0.9, - "weight": 700, - "family": "Noto Sans" - }, - "tiny_emphasis": { - "size": 0.7, - "weight": 700, - "family": "Noto Sans" - }, - "tiny_emphasis_ja_JP": { - "size": 0.7, - "weight": 700, - "family": "Noto Sans" - }, - "tiny_emphasis_zh_CN": { - "size": 0.7, - "weight": 700, - "family": "Noto Sans" - }, - "tiny_emphasis_zh_TW": { - "size": 0.7, - "weight": 700, - "family": "Noto Sans" - } - }, - - "base_colors": { - "background_1": [255, 255, 255, 255], - "background_2": [243, 243, 243, 255], - "background_3": [232, 240, 253, 255], - "background_4": [3, 12, 66, 255], - - "accent_1": [25, 110, 240, 255], - "accent_2": [16, 70, 156, 255], - "border_main": [212, 212, 212, 255], - "border_accent_1": [25, 110, 240, 255], - "border_accent_2": [16, 70, 156, 255], - "border_field": [180, 180, 180, 255], - - "text_default": [0, 14, 26, 255], - "text_disabled": [180, 180, 180, 255], - "text_primary_button": [255, 255, 255, 255], - "text_secondary_button": [25, 110, 240, 255], - "text_link_hover": [16, 70, 156, 255], - "text_lighter": [108, 108, 108, 255], - - "um_green_1": [233, 245, 237, 255], - "um_green_5": [36, 162, 73, 255], - "um_green_9": [31, 44, 36, 255], - "um_red_1": [251, 232, 233, 255], - "um_red_5": [218, 30, 40, 255], - "um_red_9": [59, 31, 33, 255], - "um_orange_1": [255, 235, 221, 255], - "um_orange_5": [252, 123, 30, 255], - "um_orange_9": [64, 45, 32, 255], - "um_yellow_1": [255, 248, 225, 255], - "um_yellow_5": [253, 209, 58, 255], - "um_yellow_9": [64, 58, 36, 255] - }, - - "colors": { - - "main_background": "background_1", - "detail_background": "background_2", - "wide_lining": [245, 245, 245, 255], - "thick_lining": [180, 180, 180, 255], - "lining": [192, 193, 194, 255], - "viewport_overlay": [246, 246, 246, 255], - - "primary": "accent_1", - "primary_hover": [48, 182, 231, 255], - "primary_text": [255, 255, 255, 255], - "text_selection": [156, 195, 255, 127], - "border": [127, 127, 127, 255], - "border_field": [180, 180, 180, 255], - "secondary": [240, 240, 240, 255], - - "expandable_active": [240, 240, 240, 255], - "expandable_hover": [232, 242, 252, 255], - - "icon": [8, 7, 63, 255], - - "primary_button": "accent_1", - "primary_button_hover": [16, 70, 156, 255], - "primary_button_text": [255, 255, 255, 255], - - "secondary_button": "background_1", - "secondary_button_shadow": [216, 216, 216, 255], - "secondary_button_hover": [232, 240, 253, 255], - "secondary_button_text": "accent_1", - - "main_window_header_background": [8, 7, 63, 255], - "main_window_header_background_gradient": [25, 23, 91, 255], - "main_window_header_button_text_active": [8, 7, 63, 255], - "main_window_header_button_text_inactive": [255, 255, 255, 255], - "main_window_header_button_text_hovered": [255, 255, 255, 255], - "main_window_header_button_background_active": [255, 255, 255, 255], - "main_window_header_button_background_inactive": [255, 255, 255, 0], - "main_window_header_button_background_hovered": [117, 114, 159, 255], - - "account_widget_outline_active": [70, 66, 126, 255], - "account_sync_state_icon": [25, 25, 25, 255], - - "machine_selector_printer_icon": [8, 7, 63, 255], - - "action_panel_secondary": "accent_1", - - "first_run_shadow": [50, 50, 50, 255], - - "toolbar_background": [255, 255, 255, 255], - - "notification_icon": [255, 0, 0, 255], - - "printer_type_label_background": [228, 228, 242, 255], - - "window_disabled_background": [0, 0, 0, 255], - - "text": [25, 25, 25, 255], - "text_disabled": [180, 180, 180, 255], - "text_detail": [174, 174, 174, 128], - "text_link": "accent_1", - "text_inactive": [174, 174, 174, 255], - "text_medium": [128, 128, 128, 255], - "text_scene": [102, 102, 102, 255], - "text_scene_hover": [123, 123, 113, 255], - - "error": [218, 30, 40, 255], - "warning": [253, 209, 58, 255], - "success": [36, 162, 73, 255], - "disabled": [229, 229, 229, 255], - - "toolbar_button_hover": [232, 242, 252, 255], - "toolbar_button_active": [232, 242, 252, 255], - "toolbar_button_active_hover": [232, 242, 252, 255], - - "button_text": [255, 255, 255, 255], - - "small_button_text": [102, 102, 102, 255], - "small_button_text_hover": [8, 7, 63, 255], - - "button_tooltip": [31, 36, 39, 255], - - "extruder_disabled": [255, 255, 255, 102], - - "action_button": [255, 255, 255, 255], - "action_button_hovered": [232, 242, 252, 255], - "action_button_disabled": [245, 245, 245, 255], - "action_button_disabled_text": [196, 196, 196, 255], - "action_button_shadow": [223, 223, 223, 255], - - "scrollbar_background": [255, 255, 255, 255], - "scrollbar_handle": [10, 8, 80, 255], - "scrollbar_handle_hover": [50, 130, 255, 255], - "scrollbar_handle_down": [50, 130, 255, 255], - - "setting_category": "background_1", - "setting_category_disabled": [255, 255, 255, 255], - "setting_category_hover": "background_2", - "setting_category_text": "text_default", - "setting_category_disabled_text": [24, 41, 77, 101], - "setting_category_active_text": "text_default", - - "setting_control": "background_2", - "setting_control_highlight": "background_3", - "setting_control_border": [199, 199, 199, 255], - "setting_control_border_highlight": [50, 130, 255, 255], - "setting_control_text": [35, 35, 35, 255], - "setting_control_button": [102, 102, 102, 255], - "setting_control_button_hover": [8, 7, 63, 255], - "setting_control_disabled": "background_2", - "setting_control_disabled_text": [127, 127, 127, 255], - "setting_control_disabled_border": [127, 127, 127, 255], - "setting_unit": [127, 127, 127, 255], - "setting_validation_error_background": "um_red_1", - "setting_validation_error": "um_red_5", - "setting_validation_warning_background": "um_yellow_1", - "setting_validation_warning": "um_yellow_5", - "setting_validation_ok": "background_2", - - "material_compatibility_warning": [243, 166, 59, 255], - "core_compatibility_warning": [243, 166, 59, 255], - - "progressbar_background": [245, 245, 245, 255], - "progressbar_control": [50, 130, 255, 255], - - "slider_groove": [223, 223, 223, 255], - "slider_groove_fill": [8, 7, 63, 255], - "slider_handle": [8, 7, 63, 255], - "slider_handle_active": [50, 130, 255, 255], - "slider_text_background": [255, 255, 255, 255], - - "quality_slider_unavailable": [179, 179, 179, 255], - "quality_slider_available": [0, 0, 0, 255], - - "checkbox": "background_1", - "checkbox_hover": "background_1", - "checkbox_disabled": "background_2", - "checkbox_border": [180, 180, 180, 255], - "checkbox_border_hover": "border_main", - "checkbox_border_disabled": "text_disabled", - "checkbox_mark": "text_default", - "checkbox_mark_disabled": "text_disabled", - "checkbox_square": [180, 180, 180, 255], - "checkbox_text": "text_default", - "checkbox_text_disabled": "text_disabled", - - "switch": "background_1", - "switch_state_checked": "accent_1", - "switch_state_unchecked": "text_disabled", - - "radio": "background_1", - "radio_disabled": "background_2", - "radio_selected": "accent_1", - "radio_selected_disabled": "text_disabled", - "radio_border": [180, 180, 180, 255], - "radio_border_hover": "border_main", - "radio_border_disabled": "text_disabled", - "radio_dot": "background_1", - "radio_dot_disabled": "background_2", - "radio_text": "text_default", - "radio_text_disabled": "text_disabled", - - "text_field": "background_1", - "text_field_border": [180, 180, 180, 255], - "text_field_border_hovered": "border_main", - "text_field_border_active": "border_accent_2", - "text_field_border_disabled": "background_2", - "text_field_text": "text_default", - "text_field_text_disabled": "text_disabled", - - "category_background": "background_2", - - "tooltip": [25, 25, 25, 255], - "tooltip_text": [255, 255, 255, 255], - - "message_background": [255, 255, 255, 255], - "message_border": [192, 193, 194, 255], - "message_close": [102, 102, 102, 255], - "message_close_hover": [8, 7, 63, 255], - "message_progressbar_background": [245, 245, 245, 255], - "message_progressbar_control": [50, 130, 255, 255], - "message_success_icon": [255, 255, 255, 255], - "message_warning_icon": [0, 0, 0, 255], - "message_error_icon": [255, 255, 255, 255], - - "tool_panel_background": [255, 255, 255, 255], - - "status_offline": [0, 0, 0, 255], - "status_ready": [0, 205, 0, 255], - "status_busy": [50, 130, 255, 255], - "status_paused": [255, 140, 0, 255], - "status_stopped": [236, 82, 80, 255], - - "disabled_axis": [127, 127, 127, 255], - "x_axis": [218, 30, 40, 255], - "y_axis": [25, 110, 240, 255], - "z_axis": [36, 162, 73, 255], - "all_axis": [255, 255, 255, 255], - - "viewport_background": [250, 250, 250, 255], - "volume_outline": [50, 130, 255, 255], - "buildplate": [244, 244, 244, 255], - "buildplate_grid": [180, 180, 180, 255], - "buildplate_grid_minor": [228, 228, 228, 255], - - "convex_hull": [35, 35, 35, 127], - "disallowed_area": [0, 0, 0, 40], - "error_area": [255, 0, 0, 127], - - "model_overhang": [255, 0, 0, 255], - "model_unslicable": [122, 122, 122, 255], - "model_unslicable_alt": [172, 172, 127, 255], - "model_selection_outline": [50, 130, 255, 255], - "model_non_printing": [122, 122, 122, 255], - - "xray": [26, 26, 62, 255], - - "layerview_ghost": [31, 31, 31, 95], - "layerview_none": [255, 255, 255, 255], - "layerview_inset_0": [230, 0, 0, 255], - "layerview_inset_x": [0, 230, 0, 255], - "layerview_skin": [230, 230, 0, 255], - "layerview_support": [0, 230, 230, 127], - "layerview_skirt": [0, 230, 230, 255], - "layerview_infill": [230, 115, 0, 255], - "layerview_support_infill": [0, 230, 230, 127], - "layerview_move_combing": [0, 0, 255, 255], - "layerview_move_retraction": [128, 127, 255, 255], - "layerview_move_while_retracting": [127, 255, 255, 255], - "layerview_move_while_unretracting": [255, 127, 255, 255], - "layerview_support_interface": [63, 127, 255, 127], - "layerview_prime_tower": [0, 255, 255, 255], - "layerview_nozzle": [224, 192, 16, 64], - "layerview_starts": [255, 255, 255, 255], - - - "monitor_printer_family_tag": [228, 228, 242, 255], - "monitor_text_disabled": [238, 238, 238, 255], - "monitor_icon_primary": [10, 8, 80, 255], - "monitor_icon_accent": [255, 255, 255, 255], - "monitor_icon_disabled": [238, 238, 238, 255], - - "monitor_card_border": [192, 193, 194, 255], - "monitor_card_background": [255, 255, 255, 255], - "monitor_card_hover": [232, 242, 252, 255], - - "monitor_stage_background": [246, 246, 246, 255], - "monitor_stage_background_fade": [246, 246, 246, 102], - - "monitor_tooltip": [25, 25, 25, 255], - "monitor_tooltip_text": [255, 255, 255, 255], - "monitor_context_menu": [255, 255, 255, 255], - "monitor_context_menu_hover": [245, 245, 245, 255], - - "monitor_skeleton_loading": [238, 238, 238, 255], - "monitor_placeholder_image": [230, 230, 230, 255], - "monitor_image_overlay": [0, 0, 0, 255], - "monitor_shadow": [200, 200, 200, 255], - - "monitor_carousel_dot": [216, 216, 216, 255], - "monitor_carousel_dot_current": [119, 119, 119, 255], - - "cloud_unavailable": [153, 153, 153, 255], - "connection_badge_background": [255, 255, 255, 255], - "warning_badge_background": [0, 0, 0, 255], - "error_badge_background": [255, 255, 255, 255], - - "border_field_light": [180, 180, 180, 255], - "border_main_light": [212, 212, 212, 255] - }, - - "sizes": { - "window_minimum_size": [80, 48], - "popup_dialog": [40, 36], - "small_popup_dialog": [36, 12], - - "main_window_header": [0.0, 4.0], - - "stage_menu": [0.0, 4.0], - - "account_button": [12, 2.5], - - "print_setup_widget": [38.0, 30.0], - "print_setup_extruder_box": [0.0, 6.0], - "slider_widget_groove": [0.16, 0.16], - "slider_widget_handle": [1.3, 1.3], - "slider_widget_tickmarks": [0.5, 0.5], - "print_setup_big_item": [28, 2.5], - "print_setup_icon": [1.2, 1.2], - "drag_icon": [1.416, 0.25], - - "application_switcher_item": [8, 9], - "application_switcher_icon": [3.75, 3.75], - - "expandable_component_content_header": [0.0, 3.0], - - "configuration_selector": [35.0, 4.0], - - "action_panel_widget": [26.0, 0.0], - "action_panel_information_widget": [20.0, 0.0], - - "machine_selector_widget": [20.0, 4.0], - "machine_selector_widget_content": [25.0, 32.0], - "machine_selector_icon": [2.5, 2.5], - - "views_selector": [16.0, 4.0], - - "printer_type_label": [3.5, 1.5], - - "default_radius": [0.25, 0.25], - - "wide_lining": [0.5, 0.5], - "thick_lining": [0.2, 0.2], - "default_lining": [0.08, 0.08], - - "default_arrow": [0.8, 0.8], - "logo": [16, 2], - - "wide_margin": [2.0, 2.0], - "thick_margin": [1.71, 1.43], - "default_margin": [1.0, 1.0], - "thin_margin": [0.71, 0.71], - "narrow_margin": [0.5, 0.5], - - "extruder_icon": [2.5, 2.5], - - "section": [0.0, 2], - "section_header": [0.0, 2.5], - - "section_control": [0, 1], - "section_icon": [1.5, 1.5], - "section_icon_column": [2.5, 2.5], - - "setting": [25.0, 1.8], - "setting_control": [9.0, 2.0], - "setting_control_radius": [0.15, 0.15], - "setting_control_depth_margin": [1.4, 0.0], - "setting_unit_margin": [0.5, 0.5], - - "standard_list_lineheight": [1.5, 1.5], - "standard_arrow": [1.0, 1.0], - - "card": [25.0, 10], - "card_icon": [6.0, 6.0], - "card_tiny_icon": [1.5, 1.5], - - "button": [4, 4], - "button_icon": [2.5, 2.5], - - "action_button": [15.0, 2.5], - "action_button_icon": [1.5, 1.5], - "action_button_icon_small": [1.0, 1.0], - "action_button_radius": [0.15, 0.15], - - "radio_button": [1.3, 1.3], - - "small_button": [2, 2], - "small_button_icon": [1.5, 1.5], - - "medium_button": [2.5, 2.5], - "medium_button_icon": [2, 2], - - "large_button": [3.0, 3.0], - "large_button_icon": [2.8, 2.8], - - "context_menu": [20, 2], - - "icon_indicator": [1, 1], - - "printer_status_icon": [1.0, 1.0], - - "button_tooltip": [1.0, 1.3], - "button_tooltip_arrow": [0.25, 0.25], - - "progressbar": [26.0, 0.75], - "progressbar_radius": [0.15, 0.15], - - "scrollbar": [0.75, 0.5], - - "slider_groove": [0.5, 0.5], - "slider_groove_radius": [0.15, 0.15], - "slider_handle": [1.5, 1.5], - "slider_layerview_size": [1.0, 34.0], - - "layerview_menu_size": [16.0, 4.0], - "layerview_legend_size": [1.0, 1.0], - "layerview_row": [11.0, 1.5], - "layerview_row_spacing": [0.0, 0.5], - - "checkbox": [1.33, 1.33], - "checkbox_mark": [1, 1], - "checkbox_radius": [0.25, 0.25], - - "spinbox": [6.0, 3.0], - "combobox": [14, 2], - "combobox_wide": [22, 2], - - "tooltip": [20.0, 10.0], - "tooltip_margins": [1.0, 1.0], - "tooltip_arrow_margins": [2.0, 2.0], - - "save_button_save_to_button": [0.3, 2.7], - "save_button_specs_icons": [1.4, 1.4], - - "first_run_shadow_radius": [1.2, 1.2], - - "monitor_preheat_temperature_control": [4.5, 2.0], - - "welcome_wizard_window": [46, 50], - "modal_window_minimum": [60.0, 50.0], - "wizard_progress": [10.0, 0.0], - - "message": [30.0, 5.0], - "message_close": [2, 2], - "message_radius": [0.25, 0.25], - "message_action_button": [0, 2.5], - "message_image": [15.0, 10.0], - "message_type_icon": [2, 2], - "menu": [18, 2], - - "jobspecs_line": [2.0, 2.0], - - "objects_menu_size": [15, 15], - - "notification_icon": [1.5, 1.5], - - "avatar_image": [6.8, 6.8], - - "monitor_shadow_radius": [0.4, 0.4], - "monitor_empty_state_offset": [5.6, 5.6], - "monitor_empty_state_size": [35.0, 25.0], - "monitor_column": [18.0, 1.0], - "monitor_progress_bar": [16.5, 1.0], - - "table_row": [2.0, 2.0], - - "welcome_wizard_content_image_big": [18, 15], - "welcome_wizard_cloud_content_image": [4, 4], - - "banner_icon_size": [2.0, 2.0], - - "marketplace_large_icon": [4.0, 4.0], - - "preferences_page_list_item": [8.0, 2.0], - - "recommended_button_icon": [1.7, 1.7], - - "recommended_section_setting_item": [14.0, 2.0], - - "reset_profile_icon": [1, 1] - } -} +{"metadata": {"name": "UltiMaker"}, "fonts": {"large": {"size": 1.35, "weight": 400, "family": "Noto Sans"}, "large_ja_JP": {"size": 1.35, "weight": 400, "family": "Noto Sans"}, "large_zh_CN": {"size": 1.35, "weight": 400, "family": "Noto Sans"}, "large_zh_TW": {"size": 1.35, "weight": 400, "family": "Noto Sans"}, "large_bold": {"size": 1.35, "weight": 600, "family": "Noto Sans"}, "huge": {"size": 1.8, "weight": 400, "family": "Noto Sans"}, "huge_bold": {"size": 1.8, "weight": 600, "family": "Noto Sans"}, "medium": {"size": 1.16, "weight": 400, "family": "Noto Sans"}, "medium_ja_JP": {"size": 1.16, "weight": 400, "family": "Noto Sans"}, "medium_zh_CN": {"size": 1.16, "weight": 400, "family": "Noto Sans"}, "medium_zh_TW": {"size": 1.16, "weight": 400, "family": "Noto Sans"}, "medium_bold": {"size": 1.16, "weight": 600, "family": "Noto Sans"}, "default": {"size": 0.95, "weight": 400, "family": "Noto Sans"}, "default_ja_JP": {"size": 1.0, "weight": 400, "family": "Noto Sans"}, "default_zh_CN": {"size": 1.0, "weight": 400, "family": "Noto Sans"}, "default_zh_TW": {"size": 1.0, "weight": 400, "family": "Noto Sans"}, "default_bold": {"size": 0.95, "weight": 600, "family": "Noto Sans"}, "default_bold_ja_JP": {"size": 1.0, "weight": 600, "family": "Noto Sans"}, "default_bold_zh_CN": {"size": 1.0, "weight": 600, "family": "Noto Sans"}, "default_bold_zh_TW": {"size": 1.0, "weight": 600, "family": "Noto Sans"}, "default_italic": {"size": 0.95, "weight": 400, "italic": true, "family": "Noto Sans"}, "medium_italic": {"size": 1.16, "weight": 400, "italic": true, "family": "Noto Sans"}, "default_italic_ja_JP": {"size": 1.0, "weight": 400, "italic": true, "family": "Noto Sans"}, "default_italic_zh_CN": {"size": 1.0, "weight": 400, "italic": true, "family": "Noto Sans"}, "default_italic_zh_TW": {"size": 1.0, "weight": 400, "italic": true, "family": "Noto Sans"}, "small": {"size": 0.9, "weight": 400, "family": "Noto Sans"}, "small_bold": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "small_ja_JP": {"size": 0.9, "weight": 400, "family": "Noto Sans"}, "small_zh_CN": {"size": 0.9, "weight": 400, "family": "Noto Sans"}, "small_zh_TW": {"size": 0.9, "weight": 400, "family": "Noto Sans"}, "small_emphasis": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "small_emphasis_ja_JP": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "small_emphasis_zh_CN": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "small_emphasis_zh_TW": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "tiny_emphasis": {"size": 0.7, "weight": 700, "family": "Noto Sans"}, "tiny_emphasis_ja_JP": {"size": 0.7, "weight": 700, "family": "Noto Sans"}, "tiny_emphasis_zh_CN": {"size": 0.7, "weight": 700, "family": "Noto Sans"}, "tiny_emphasis_zh_TW": {"size": 0.7, "weight": 700, "family": "Noto Sans"}}, "base_colors": {"background_1": [255, 255, 255, 255], "background_2": [243, 243, 243, 255], "background_3": [232, 240, 253, 255], "background_4": [3, 12, 66, 255], "accent_1": [25, 110, 240, 255], "accent_2": [16, 70, 156, 255], "border_main": [212, 212, 212, 255], "border_accent_1": [25, 110, 240, 255], "border_accent_2": [16, 70, 156, 255], "border_field": [180, 180, 180, 255], "text_default": [0, 14, 26, 255], "text_disabled": [180, 180, 180, 255], "text_primary_button": [255, 255, 255, 255], "text_secondary_button": [25, 110, 240, 255], "text_link_hover": [16, 70, 156, 255], "text_lighter": [108, 108, 108, 255], "um_green_1": [233, 245, 237, 255], "um_green_5": [36, 162, 73, 255], "um_green_9": [31, 44, 36, 255], "um_red_1": [251, 232, 233, 255], "um_red_5": [218, 30, 40, 255], "um_red_9": [59, 31, 33, 255], "um_orange_1": [255, 235, 221, 255], "um_orange_5": [252, 123, 30, 255], "um_orange_9": [64, 45, 32, 255], "um_yellow_1": [255, 248, 225, 255], "um_yellow_5": [253, 209, 58, 255], "um_yellow_9": [64, 58, 36, 255]}, "colors": {"main_background": "background_1", "detail_background": "background_2", "wide_lining": [245, 245, 245, 255], "thick_lining": [180, 180, 180, 255], "lining": [192, 193, 194, 255], "viewport_overlay": [246, 246, 246, 255], "primary": "accent_1", "primary_hover": [48, 182, 231, 255], "primary_text": [255, 255, 255, 255], "text_selection": [156, 195, 255, 127], "border": [127, 127, 127, 255], "border_field": [180, 180, 180, 255], "secondary": [240, 240, 240, 255], "expandable_active": [240, 240, 240, 255], "expandable_hover": [232, 242, 252, 255], "icon": [8, 7, 63, 255], "primary_button": "accent_1", "primary_button_hover": [16, 70, 156, 255], "primary_button_text": [255, 255, 255, 255], "secondary_button": "background_1", "secondary_button_shadow": [216, 216, 216, 255], "secondary_button_hover": [232, 240, 253, 255], "secondary_button_text": "accent_1", "main_window_header_background": [192, 199, 65, 255], "main_window_header_background_gradient": [25, 23, 91, 255], "main_window_header_button_text_active": [8, 7, 63, 255], "main_window_header_button_text_inactive": [255, 255, 255, 255], "main_window_header_button_text_hovered": [255, 255, 255, 255], "main_window_header_button_background_active": [255, 255, 255, 255], "main_window_header_button_background_inactive": [255, 255, 255, 0], "main_window_header_button_background_hovered": [117, 114, 159, 255], "account_widget_outline_active": [70, 66, 126, 255], "account_sync_state_icon": [25, 25, 25, 255], "machine_selector_printer_icon": [8, 7, 63, 255], "action_panel_secondary": "accent_1", "first_run_shadow": [50, 50, 50, 255], "toolbar_background": [255, 255, 255, 255], "notification_icon": [255, 0, 0, 255], "printer_type_label_background": [228, 228, 242, 255], "window_disabled_background": [0, 0, 0, 255], "text": [25, 25, 25, 255], "text_disabled": [180, 180, 180, 255], "text_detail": [174, 174, 174, 128], "text_link": "accent_1", "text_inactive": [174, 174, 174, 255], "text_medium": [128, 128, 128, 255], "text_scene": [102, 102, 102, 255], "text_scene_hover": [123, 123, 113, 255], "error": [218, 30, 40, 255], "warning": [253, 209, 58, 255], "success": [36, 162, 73, 255], "disabled": [229, 229, 229, 255], "toolbar_button_hover": [232, 242, 252, 255], "toolbar_button_active": [232, 242, 252, 255], "toolbar_button_active_hover": [232, 242, 252, 255], "button_text": [255, 255, 255, 255], "small_button_text": [102, 102, 102, 255], "small_button_text_hover": [8, 7, 63, 255], "button_tooltip": [31, 36, 39, 255], "extruder_disabled": [255, 255, 255, 102], "action_button": [255, 255, 255, 255], "action_button_hovered": [232, 242, 252, 255], "action_button_disabled": [245, 245, 245, 255], "action_button_disabled_text": [196, 196, 196, 255], "action_button_shadow": [223, 223, 223, 255], "scrollbar_background": [255, 255, 255, 255], "scrollbar_handle": [10, 8, 80, 255], "scrollbar_handle_hover": [50, 130, 255, 255], "scrollbar_handle_down": [50, 130, 255, 255], "setting_category": "background_1", "setting_category_disabled": [255, 255, 255, 255], "setting_category_hover": "background_2", "setting_category_text": "text_default", "setting_category_disabled_text": [24, 41, 77, 101], "setting_category_active_text": "text_default", "setting_control": "background_2", "setting_control_highlight": "background_3", "setting_control_border": [199, 199, 199, 255], "setting_control_border_highlight": [50, 130, 255, 255], "setting_control_text": [35, 35, 35, 255], "setting_control_button": [102, 102, 102, 255], "setting_control_button_hover": [8, 7, 63, 255], "setting_control_disabled": "background_2", "setting_control_disabled_text": [127, 127, 127, 255], "setting_control_disabled_border": [127, 127, 127, 255], "setting_unit": [127, 127, 127, 255], "setting_validation_error_background": "um_red_1", "setting_validation_error": "um_red_5", "setting_validation_warning_background": "um_yellow_1", "setting_validation_warning": "um_yellow_5", "setting_validation_ok": "background_2", "material_compatibility_warning": [243, 166, 59, 255], "core_compatibility_warning": [243, 166, 59, 255], "progressbar_background": [245, 245, 245, 255], "progressbar_control": [50, 130, 255, 255], "slider_groove": [223, 223, 223, 255], "slider_groove_fill": [8, 7, 63, 255], "slider_handle": [8, 7, 63, 255], "slider_handle_active": [50, 130, 255, 255], "slider_text_background": [255, 255, 255, 255], "quality_slider_unavailable": [179, 179, 179, 255], "quality_slider_available": [0, 0, 0, 255], "checkbox": "background_1", "checkbox_hover": "background_1", "checkbox_disabled": "background_2", "checkbox_border": [180, 180, 180, 255], "checkbox_border_hover": "border_main", "checkbox_border_disabled": "text_disabled", "checkbox_mark": "text_default", "checkbox_mark_disabled": "text_disabled", "checkbox_square": [180, 180, 180, 255], "checkbox_text": "text_default", "checkbox_text_disabled": "text_disabled", "switch": "background_1", "switch_state_checked": "accent_1", "switch_state_unchecked": "text_disabled", "radio": "background_1", "radio_disabled": "background_2", "radio_selected": "accent_1", "radio_selected_disabled": "text_disabled", "radio_border": [180, 180, 180, 255], "radio_border_hover": "border_main", "radio_border_disabled": "text_disabled", "radio_dot": "background_1", "radio_dot_disabled": "background_2", "radio_text": "text_default", "radio_text_disabled": "text_disabled", "text_field": "background_1", "text_field_border": [180, 180, 180, 255], "text_field_border_hovered": "border_main", "text_field_border_active": "border_accent_2", "text_field_border_disabled": "background_2", "text_field_text": "text_default", "text_field_text_disabled": "text_disabled", "category_background": "background_2", "tooltip": [25, 25, 25, 255], "tooltip_text": [255, 255, 255, 255], "message_background": [255, 255, 255, 255], "message_border": [192, 193, 194, 255], "message_close": [102, 102, 102, 255], "message_close_hover": [8, 7, 63, 255], "message_progressbar_background": [245, 245, 245, 255], "message_progressbar_control": [50, 130, 255, 255], "message_success_icon": [255, 255, 255, 255], "message_warning_icon": [0, 0, 0, 255], "message_error_icon": [255, 255, 255, 255], "tool_panel_background": [255, 255, 255, 255], "status_offline": [0, 0, 0, 255], "status_ready": [0, 205, 0, 255], "status_busy": [50, 130, 255, 255], "status_paused": [255, 140, 0, 255], "status_stopped": [236, 82, 80, 255], "disabled_axis": [127, 127, 127, 255], "x_axis": [218, 30, 40, 255], "y_axis": [25, 110, 240, 255], "z_axis": [36, 162, 73, 255], "all_axis": [255, 255, 255, 255], "viewport_background": [250, 250, 250, 255], "volume_outline": [50, 130, 255, 255], "buildplate": [244, 244, 244, 255], "buildplate_grid": [180, 180, 180, 255], "buildplate_grid_minor": [228, 228, 228, 255], "convex_hull": [35, 35, 35, 127], "disallowed_area": [0, 0, 0, 40], "error_area": [255, 0, 0, 127], "model_overhang": [255, 0, 0, 255], "model_unslicable": [122, 122, 122, 255], "model_unslicable_alt": [172, 172, 127, 255], "model_selection_outline": [50, 130, 255, 255], "model_non_printing": [122, 122, 122, 255], "xray": [26, 26, 62, 255], "layerview_ghost": [31, 31, 31, 95], "layerview_none": [255, 255, 255, 255], "layerview_inset_0": [230, 0, 0, 255], "layerview_inset_x": [0, 230, 0, 255], "layerview_skin": [230, 230, 0, 255], "layerview_support": [0, 230, 230, 127], "layerview_skirt": [0, 230, 230, 255], "layerview_infill": [230, 115, 0, 255], "layerview_support_infill": [0, 230, 230, 127], "layerview_move_combing": [0, 0, 255, 255], "layerview_move_retraction": [128, 127, 255, 255], "layerview_move_while_retracting": [127, 255, 255, 255], "layerview_move_while_unretracting": [255, 127, 255, 255], "layerview_support_interface": [63, 127, 255, 127], "layerview_prime_tower": [0, 255, 255, 255], "layerview_nozzle": [224, 192, 16, 64], "layerview_starts": [255, 255, 255, 255], "monitor_printer_family_tag": [228, 228, 242, 255], "monitor_text_disabled": [238, 238, 238, 255], "monitor_icon_primary": [10, 8, 80, 255], "monitor_icon_accent": [255, 255, 255, 255], "monitor_icon_disabled": [238, 238, 238, 255], "monitor_card_border": [192, 193, 194, 255], "monitor_card_background": [255, 255, 255, 255], "monitor_card_hover": [232, 242, 252, 255], "monitor_stage_background": [246, 246, 246, 255], "monitor_stage_background_fade": [246, 246, 246, 102], "monitor_tooltip": [25, 25, 25, 255], "monitor_tooltip_text": [255, 255, 255, 255], "monitor_context_menu": [255, 255, 255, 255], "monitor_context_menu_hover": [245, 245, 245, 255], "monitor_skeleton_loading": [238, 238, 238, 255], "monitor_placeholder_image": [230, 230, 230, 255], "monitor_image_overlay": [0, 0, 0, 255], "monitor_shadow": [200, 200, 200, 255], "monitor_carousel_dot": [216, 216, 216, 255], "monitor_carousel_dot_current": [119, 119, 119, 255], "cloud_unavailable": [153, 153, 153, 255], "connection_badge_background": [255, 255, 255, 255], "warning_badge_background": [0, 0, 0, 255], "error_badge_background": [255, 255, 255, 255], "border_field_light": [180, 180, 180, 255], "border_main_light": [212, 212, 212, 255]}, "sizes": {"window_minimum_size": [80, 48], "popup_dialog": [40, 36], "small_popup_dialog": [36, 12], "main_window_header": [0.0, 4.0], "stage_menu": [0.0, 4.0], "account_button": [12, 2.5], "print_setup_widget": [38.0, 30.0], "print_setup_extruder_box": [0.0, 6.0], "slider_widget_groove": [0.16, 0.16], "slider_widget_handle": [1.3, 1.3], "slider_widget_tickmarks": [0.5, 0.5], "print_setup_big_item": [28, 2.5], "print_setup_icon": [1.2, 1.2], "drag_icon": [1.416, 0.25], "application_switcher_item": [8, 9], "application_switcher_icon": [3.75, 3.75], "expandable_component_content_header": [0.0, 3.0], "configuration_selector": [35.0, 4.0], "action_panel_widget": [26.0, 0.0], "action_panel_information_widget": [20.0, 0.0], "machine_selector_widget": [20.0, 4.0], "machine_selector_widget_content": [25.0, 32.0], "machine_selector_icon": [2.5, 2.5], "views_selector": [16.0, 4.0], "printer_type_label": [3.5, 1.5], "default_radius": [0.25, 0.25], "wide_lining": [0.5, 0.5], "thick_lining": [0.2, 0.2], "default_lining": [0.08, 0.08], "default_arrow": [0.8, 0.8], "logo": [16, 2], "wide_margin": [2.0, 2.0], "thick_margin": [1.71, 1.43], "default_margin": [1.0, 1.0], "thin_margin": [0.71, 0.71], "narrow_margin": [0.5, 0.5], "extruder_icon": [2.5, 2.5], "section": [0.0, 2], "section_header": [0.0, 2.5], "section_control": [0, 1], "section_icon": [1.5, 1.5], "section_icon_column": [2.5, 2.5], "setting": [25.0, 1.8], "setting_control": [9.0, 2.0], "setting_control_radius": [0.15, 0.15], "setting_control_depth_margin": [1.4, 0.0], "setting_unit_margin": [0.5, 0.5], "standard_list_lineheight": [1.5, 1.5], "standard_arrow": [1.0, 1.0], "card": [25.0, 10], "card_icon": [6.0, 6.0], "card_tiny_icon": [1.5, 1.5], "button": [4, 4], "button_icon": [2.5, 2.5], "action_button": [15.0, 2.5], "action_button_icon": [1.5, 1.5], "action_button_icon_small": [1.0, 1.0], "action_button_radius": [0.15, 0.15], "radio_button": [1.3, 1.3], "small_button": [2, 2], "small_button_icon": [1.5, 1.5], "medium_button": [2.5, 2.5], "medium_button_icon": [2, 2], "large_button": [3.0, 3.0], "large_button_icon": [2.8, 2.8], "context_menu": [20, 2], "icon_indicator": [1, 1], "printer_status_icon": [1.0, 1.0], "button_tooltip": [1.0, 1.3], "button_tooltip_arrow": [0.25, 0.25], "progressbar": [26.0, 0.75], "progressbar_radius": [0.15, 0.15], "scrollbar": [0.75, 0.5], "slider_groove": [0.5, 0.5], "slider_groove_radius": [0.15, 0.15], "slider_handle": [1.5, 1.5], "slider_layerview_size": [1.0, 34.0], "layerview_menu_size": [16.0, 4.0], "layerview_legend_size": [1.0, 1.0], "layerview_row": [11.0, 1.5], "layerview_row_spacing": [0.0, 0.5], "checkbox": [1.33, 1.33], "checkbox_mark": [1, 1], "checkbox_radius": [0.25, 0.25], "spinbox": [6.0, 3.0], "combobox": [14, 2], "combobox_wide": [22, 2], "tooltip": [20.0, 10.0], "tooltip_margins": [1.0, 1.0], "tooltip_arrow_margins": [2.0, 2.0], "save_button_save_to_button": [0.3, 2.7], "save_button_specs_icons": [1.4, 1.4], "first_run_shadow_radius": [1.2, 1.2], "monitor_preheat_temperature_control": [4.5, 2.0], "welcome_wizard_window": [46, 50], "modal_window_minimum": [60.0, 50.0], "wizard_progress": [10.0, 0.0], "message": [30.0, 5.0], "message_close": [2, 2], "message_radius": [0.25, 0.25], "message_action_button": [0, 2.5], "message_image": [15.0, 10.0], "message_type_icon": [2, 2], "menu": [18, 2], "jobspecs_line": [2.0, 2.0], "objects_menu_size": [15, 15], "notification_icon": [1.5, 1.5], "avatar_image": [6.8, 6.8], "monitor_shadow_radius": [0.4, 0.4], "monitor_empty_state_offset": [5.6, 5.6], "monitor_empty_state_size": [35.0, 25.0], "monitor_column": [18.0, 1.0], "monitor_progress_bar": [16.5, 1.0], "table_row": [2.0, 2.0], "welcome_wizard_content_image_big": [18, 15], "welcome_wizard_cloud_content_image": [4, 4], "banner_icon_size": [2.0, 2.0], "marketplace_large_icon": [4.0, 4.0], "preferences_page_list_item": [8.0, 2.0], "recommended_button_icon": [1.7, 1.7], "recommended_section_setting_item": [14.0, 2.0], "reset_profile_icon": [1, 1]}} \ No newline at end of file diff --git a/resources/themes/daily_test_colors.json b/resources/themes/daily_test_colors.json deleted file mode 100644 index 1cfa2baa74..0000000000 --- a/resources/themes/daily_test_colors.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - [ 62, 33, 55, 255], - [126, 196, 193, 255], - [126, 196, 193, 255], - [215, 155, 125, 255], - [228, 148, 58, 255], - [192, 199, 65, 255], - [157, 48, 59, 255], - [140, 143, 174, 255], - [ 23, 67, 75, 255], - [ 23, 67, 75, 255], - [154, 99, 72, 255], - [112, 55, 127, 255], - [100, 125, 52, 255], - [210, 100, 113, 255] -] From 57f811af8818cea54fd1bf720c147ec4bdfcf006 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 3 Jun 2025 15:59:02 +0200 Subject: [PATCH 140/299] Load painted texture from 3MF file CURA-12544 --- cura/Scene/SliceableObjectDecorator.py | 11 ++++++++++- plugins/3MFReader/ThreeMFReader.py | 13 ++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/cura/Scene/SliceableObjectDecorator.py b/cura/Scene/SliceableObjectDecorator.py index a52f7badf4..bb15173c01 100644 --- a/cura/Scene/SliceableObjectDecorator.py +++ b/cura/Scene/SliceableObjectDecorator.py @@ -1,5 +1,11 @@ +import copy + +from typing import Optional + +import UM.View.GL.Texture from UM.Scene.SceneNodeDecorator import SceneNodeDecorator from UM.View.GL.OpenGL import OpenGL +from UM.View.GL.Texture import Texture # FIXME: When the texture UV-unwrapping is done, these two values will need to be set to a proper value (suggest 4096 for both). @@ -14,10 +20,13 @@ class SliceableObjectDecorator(SceneNodeDecorator): def isSliceable(self) -> bool: return True - def getPaintTexture(self, create_if_required: bool = True): + def getPaintTexture(self, create_if_required: bool = True) -> Optional[UM.View.GL.Texture.Texture]: if self._paint_texture is None and create_if_required: self._paint_texture = OpenGL.getInstance().createTexture(TEXTURE_WIDTH, TEXTURE_HEIGHT) return self._paint_texture + def setPaintTexture(self, texture: UM.View.GL.Texture) -> None: + self._paint_texture = texture + def __deepcopy__(self, memo) -> "SliceableObjectDecorator": return type(self)() diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 5c8d803f3b..4275fbc7b5 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -7,6 +7,7 @@ from typing import List, Optional, Union, TYPE_CHECKING, cast import pySavitar as Savitar import numpy +from PyQt6.QtGui import QImage from UM.Logger import Logger from UM.Math.Matrix import Matrix @@ -18,6 +19,8 @@ from UM.Scene.GroupDecorator import GroupDecorator from UM.Scene.SceneNode import SceneNode # For typing. from UM.Scene.SceneNodeSettings import SceneNodeSettings from UM.Util import parseBool +from UM.View.GL.OpenGL import OpenGL +from UM.View.GL.Texture import Texture from cura.CuraApplication import CuraApplication from cura.Machines.ContainerTree import ContainerTree from cura.Scene.BuildPlateDecorator import BuildPlateDecorator @@ -101,7 +104,7 @@ class ThreeMFReader(MeshReader): """ try: node_name = savitar_node.getName() - node_id = savitar_node.getId() + node_id = str(savitar_node.getId()) except AttributeError: Logger.log("e", "Outdated version of libSavitar detected! Please update to the newest version!") node_name = "" @@ -226,6 +229,14 @@ class ThreeMFReader(MeshReader): # affects (auto) slicing sliceable_decorator = SliceableObjectDecorator() um_node.addDecorator(sliceable_decorator) + + if texture_path != "" and archive is not None: + texture_data = archive.open(texture_path).read() + texture_image = QImage.fromData(texture_data, "PNG") + texture = Texture(OpenGL.getInstance()) + texture.setImage(texture_image) + sliceable_decorator.setPaintTexture(texture) + return um_node def _read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]: From 5a4b5bf11992f0e55dd7e8bf9cc7b1ca9708e4c7 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 3 Jun 2025 15:59:44 +0200 Subject: [PATCH 141/299] Allow properly duplicating painted models CURA-12544 --- cura/Scene/SliceableObjectDecorator.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cura/Scene/SliceableObjectDecorator.py b/cura/Scene/SliceableObjectDecorator.py index bb15173c01..c26848ed1a 100644 --- a/cura/Scene/SliceableObjectDecorator.py +++ b/cura/Scene/SliceableObjectDecorator.py @@ -29,4 +29,6 @@ class SliceableObjectDecorator(SceneNodeDecorator): self._paint_texture = texture def __deepcopy__(self, memo) -> "SliceableObjectDecorator": - return type(self)() + copied_decorator = SliceableObjectDecorator() + copied_decorator.setPaintTexture(copy.deepcopy(self.getPaintTexture())) + return copied_decorator From b940179c54f224dfa6420a65a8f91f615f7478b6 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 4 Jun 2025 11:01:51 +0200 Subject: [PATCH 142/299] Set proper tooltip text color CURA-11978 --- plugins/SimulationView/SimulationViewMenuComponent.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/SimulationView/SimulationViewMenuComponent.qml b/plugins/SimulationView/SimulationViewMenuComponent.qml index dcd2c7d178..0e254a005b 100644 --- a/plugins/SimulationView/SimulationViewMenuComponent.qml +++ b/plugins/SimulationView/SimulationViewMenuComponent.qml @@ -339,7 +339,7 @@ Cura.ExpandableComponent height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height width: UM.Theme.getSize("layerview_menu_size").width - color: UM.Theme.getColor("setting_control_text") + color: UM.Theme.getColor("tooltip_text") Rectangle { anchors.verticalCenter: parent.verticalCenter From 542060826d7d2e30232f32e80e731e18242d6843 Mon Sep 17 00:00:00 2001 From: Casper Lamboo Date: Wed, 4 Jun 2025 18:49:54 +0000 Subject: [PATCH 143/299] Remove unused global qualties There were no qualites specified for this intent so they were never used NP-894 --- .../um_s8_global_High_Quality.inst.cfg | 15 --------------- .../um_s8_global_Superdraft_Quality.inst.cfg | 15 --------------- 2 files changed, 30 deletions(-) delete mode 100644 resources/quality/ultimaker_s8/um_s8_global_High_Quality.inst.cfg delete mode 100644 resources/quality/ultimaker_s8/um_s8_global_Superdraft_Quality.inst.cfg diff --git a/resources/quality/ultimaker_s8/um_s8_global_High_Quality.inst.cfg b/resources/quality/ultimaker_s8/um_s8_global_High_Quality.inst.cfg deleted file mode 100644 index d495da9f17..0000000000 --- a/resources/quality/ultimaker_s8/um_s8_global_High_Quality.inst.cfg +++ /dev/null @@ -1,15 +0,0 @@ -[general] -definition = ultimaker_s8 -name = Extra Fine -version = 4 - -[metadata] -global_quality = True -quality_type = high -setting_version = 25 -type = quality -weight = 1 - -[values] -layer_height = =round(0.06 * material_shrinkage_percentage_z / 100, 5) - diff --git a/resources/quality/ultimaker_s8/um_s8_global_Superdraft_Quality.inst.cfg b/resources/quality/ultimaker_s8/um_s8_global_Superdraft_Quality.inst.cfg deleted file mode 100644 index 026e5701de..0000000000 --- a/resources/quality/ultimaker_s8/um_s8_global_Superdraft_Quality.inst.cfg +++ /dev/null @@ -1,15 +0,0 @@ -[general] -definition = ultimaker_s8 -name = Sprint -version = 4 - -[metadata] -global_quality = True -quality_type = superdraft -setting_version = 25 -type = quality -weight = -4 - -[values] -layer_height = =round(0.4 * material_shrinkage_percentage_z / 100, 5) - From 12d788db62facc68334820216b9a38f70806cb80 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 4 Jun 2025 21:00:27 +0200 Subject: [PATCH 144/299] Review comments: Fix crash when click next to object. Refactoring that part to up top caused the problem I think -- getSelectedObject(0) over getAllSelectedObjects()[0] is clearly the better call in this case anyway. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 11 +++++------ plugins/PaintTool/PaintView.py | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 2f6d3736f3..06c066e725 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -111,9 +111,9 @@ class PaintTool(Tool): paintview.redoStroke() else: paintview.undoStroke() - nodes = Selection.getAllSelectedObjects() - if len(nodes) > 0: - Application.getInstance().getController().getScene().sceneChanged.emit(nodes[0]) + node = Selection.getSelectedObject(0) + if node is not None: + Application.getInstance().getController().getScene().sceneChanged.emit(node) return True @staticmethod @@ -174,10 +174,9 @@ class PaintTool(Tool): super().event(event) controller = Application.getInstance().getController() - nodes = Selection.getAllSelectedObjects() - if len(nodes) <= 0: + node = Selection.getSelectedObject(0) + if node is None: return False - node = nodes[0] # Make sure the displayed values are updated if the bounding box of the selected mesh(es) changes if event.type == Event.ToolActivateEvent: diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 5fb62436c6..cf9d0611f0 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -91,7 +91,7 @@ class PaintView(View): paint_batch = renderer.createRenderBatch(shader=self._paint_shader) renderer.addRenderBatch(paint_batch) - node = Selection.getAllSelectedObjects()[0] + node = Selection.getSelectedObject(0) if node is None: return paint_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix()) From 40f02dc15fa0cf2a412ca8420c0594c1451b1f01 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 5 Jun 2025 08:23:22 +0200 Subject: [PATCH 145/299] Defensive coding; deal with degenerate triangles, co-linearity or query pt equal to corner. This shouldn't happen on a well UV-mapped, manifold mesh -- well, unless someone manages to click exactly on one of the triangle corners. Better to get this fixed now then to run into floating point shenanigans later. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 2 ++ plugins/PaintTool/PaintView.py | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 06c066e725..afa3b3d09e 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -119,6 +119,8 @@ class PaintTool(Tool): @staticmethod def _get_intersect_ratio_via_pt(a: numpy.ndarray, pt: numpy.ndarray, b: numpy.ndarray, c: numpy.ndarray) -> float: # compute the intersection of (param) A - pt with (param) B - (param) C + if all(a == pt) or all(b == c) or all(a == c) or all(a == b): + return 1.0 # compute unit vectors of directions of lines A and B udir_a = a - pt diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index cf9d0611f0..f72c483340 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -27,9 +27,8 @@ class PaintView(View): self._paint_shader: Optional[ShaderProgram] = None self._paint_texture: Optional[Texture] = None - # FIXME: When the texture UV-unwrapping is done, these two values will need to be set to a proper value (suggest 4096 for both). - self._tex_width = 512 - self._tex_height = 512 + self._tex_width = 2048 + self._tex_height = 2048 self._stroke_undo_stack: List[Tuple[QImage, int, int]] = [] self._stroke_redo_stack: List[Tuple[QImage, int, int]] = [] From 4a87b48084e5f99dfce7be6c86e09c95dc18451c Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 5 Jun 2025 08:25:20 +0200 Subject: [PATCH 146/299] Stopgap to prevent texture-patch borders from messing up the painting. This code is expandable into the real solution later, see the TODO left in the code by this commit. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index afa3b3d09e..cbb0c97739 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -47,7 +47,8 @@ class PaintTool(Tool): self._ctrl_held: bool = False self._shift_held: bool = False - self._last_text_coords: Optional[Tuple[int, int]] = None + self._last_text_coords: Optional[numpy.ndarray] = None + self._last_face_id: Optional[int] = None def _createBrushPen(self) -> QPen: pen = QPen() @@ -144,10 +145,10 @@ class PaintTool(Tool): def _nodeTransformChanged(self, *args) -> None: self._cache_dirty = True - def _getTexCoordsFromClick(self, node: SceneNode, x: int, y: int) -> Optional[Tuple[float, float]]: + def _getTexCoordsFromClick(self, node: SceneNode, x: int, y: int) -> Tuple[int, Optional[numpy.ndarray]]: face_id = self._selection_pass.getFaceIdAtPosition(x, y) if face_id < 0 or face_id >= node.getMeshData().getFaceCount(): - return None + return face_id, None pt = self._picking_pass.getPickedPosition(x, y).getData() @@ -164,7 +165,7 @@ class PaintTool(Tool): wb /= wt wc /= wt texcoords = wa * ta + wb * tb + wc * tc - return texcoords + return face_id, texcoords def event(self, event: Event) -> bool: """Handle mouse and keyboard events. @@ -219,6 +220,7 @@ class PaintTool(Tool): return False self._mouse_held = False self._last_text_coords = None + self._last_face_id = None return True is_moved = event.type == Event.MouseMoveEvent @@ -265,11 +267,20 @@ class PaintTool(Tool): self._selection_pass.renderFacesMode() - texcoords = self._getTexCoordsFromClick(node, evt.x, evt.y) + face_id, texcoords = self._getTexCoordsFromClick(node, evt.x, evt.y) if texcoords is None: return False if self._last_text_coords is None: self._last_text_coords = texcoords + self._last_face_id = face_id + + if face_id != self._last_face_id: + # TODO: draw two strokes in this case, for the two faces involved + # ... it's worse, for smaller faces we may genuinely require the patch -- and it may even go over _multiple_ patches if the user paints fast enough + # -> for now; make a lookup table for which faces are connected to which, don't split if they are connected, and solve the connection issue(s) later + self._last_text_coords = texcoords + self._last_face_id = face_id + return True w, h = paintview.getUvTexDimensions() sub_image, (start_x, start_y) = self._createStrokeImage( @@ -281,6 +292,7 @@ class PaintTool(Tool): paintview.addStroke(sub_image, start_x, start_y) self._last_text_coords = texcoords + self._last_face_id = face_id Application.getInstance().getController().getScene().sceneChanged.emit(node) return True From 44042eef6aa28e9108f2948f8a5a0b28adbb5808 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 5 Jun 2025 12:45:34 +0200 Subject: [PATCH 147/299] Start to set up UV-unwrapping. Needs the new libreary set up for that. part of CURA-12528 --- plugins/3MFReader/ThreeMFReader.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 45ab2e7d2f..98cae593e1 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -141,6 +141,9 @@ class ThreeMFReader(MeshReader): # The filename is used to give the user the option to reload the file if it is changed on disk # It is only set for the root node of the 3mf file mesh_builder.setFileName(file_name) + + mesh_builder.unwrapNewUvs() + mesh_data = mesh_builder.build() if len(mesh_data.getVertices()): From db8a625d8fdece858d3766b9c24c5685d4ef7e97 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 5 Jun 2025 20:57:24 +0200 Subject: [PATCH 148/299] Update PurgeLinesAndUnload.py Fixes an exception thrown upon a clean start. --- .../PostProcessingPlugin/scripts/PurgeLinesAndUnload.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py b/plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py index ca95359e29..922aad902f 100644 --- a/plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py +++ b/plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py @@ -37,6 +37,10 @@ class PurgeLinesAndUnload(Script): def __init__(self): super().__init__() + + def initialize(self) -> None: + super().initialize() + # Get required values from the global stack and set default values for the script self.global_stack = Application.getInstance().getGlobalContainerStack() self.extruder = self.global_stack.extruderList self.end_purge_location = None @@ -56,9 +60,6 @@ class PurgeLinesAndUnload(Script): self.machine_back = self.machine_depth - 1.0 self.start_x = None self.start_y = None - - def initialize(self) -> None: - super().initialize() # Get the StartUp Gcode from Cura and attempt to catch if it contains purge lines. Message the user if an extrusion is in the startup. startup_gcode = self.global_stack.getProperty("machine_start_gcode", "value") start_lines = startup_gcode.splitlines() From 28d71c643beba999c83bd3887015070e59289fb6 Mon Sep 17 00:00:00 2001 From: whoseyoung Date: Sat, 7 Jun 2025 17:01:31 +0800 Subject: [PATCH 149/299] Update Geeetech 3D printer profiles Added Geeetech M1, M1S model profiles, and modified Thunder model profiles --- resources/definitions/geeetech_M1.def.json | 13 ++-- resources/definitions/geeetech_M1S.def.json | 59 +++++++++++++++++++ .../definitions/geeetech_Thunder.def.json | 5 +- .../geeetech_M1S_0.2.inst.cfg | 13 ++++ .../geeetech_M1S_0.3.inst.cfg | 13 ++++ .../geeetech_M1S_0.4.inst.cfg | 13 ++++ .../geeetech_M1S_0.5.inst.cfg | 13 ++++ .../geeetech_M1S_0.6.inst.cfg | 13 ++++ .../geeetech_M1S_0.8.inst.cfg | 13 ++++ .../geeetech_M1S_1.0.inst.cfg | 13 ++++ .../geeetech_M1_0.2.inst.cfg | 2 +- .../geeetech_M1_0.3.inst.cfg | 2 +- .../geeetech_M1_0.4.inst.cfg | 2 +- .../geeetech_M1_0.5.inst.cfg | 2 +- .../geeetech_M1_0.6.inst.cfg | 2 +- .../geeetech_M1_0.8.inst.cfg | 2 +- .../geeetech_M1_1.0.inst.cfg | 2 +- 17 files changed, 165 insertions(+), 17 deletions(-) create mode 100644 resources/definitions/geeetech_M1S.def.json create mode 100644 resources/variants/geeetech_variants/geeetech_M1S_0.2.inst.cfg create mode 100644 resources/variants/geeetech_variants/geeetech_M1S_0.3.inst.cfg create mode 100644 resources/variants/geeetech_variants/geeetech_M1S_0.4.inst.cfg create mode 100644 resources/variants/geeetech_variants/geeetech_M1S_0.5.inst.cfg create mode 100644 resources/variants/geeetech_variants/geeetech_M1S_0.6.inst.cfg create mode 100644 resources/variants/geeetech_variants/geeetech_M1S_0.8.inst.cfg create mode 100644 resources/variants/geeetech_variants/geeetech_M1S_1.0.inst.cfg diff --git a/resources/definitions/geeetech_M1.def.json b/resources/definitions/geeetech_M1.def.json index 2ab9447205..1bb0c5ce0c 100644 --- a/resources/definitions/geeetech_M1.def.json +++ b/resources/definitions/geeetech_M1.def.json @@ -23,14 +23,13 @@ }, "machine_height": { "default_value": 95 }, "machine_name": { "default_value": "Geeetech M1" }, - "machine_start_gcode": { "default_value": ";Geeetech M1 official wiki URL:https://www.geeetech.com/wiki/index.php/Geeetech_M1_3D_printer \nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM140 S{material_bed_temperature_layer_0} ; Set Bed Temperature\n;M190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 ;Off Fan\nM300 S2500 P1000 ;Play a short tune\nG1 Z0.28 ;Move Z Axis up little to prevent scratching of Heat Bed\nG92 E0 ;Reset Extruder\nG1 Y3 F2400 ;Move to start position\nG1 X75 E40 F500 ;Draw a filament line\nG92 E0 ;Reset Extruder\n;G1 E-0.2 F3000 ;Retract a little\nG1 Z2.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X70 Y3 Z0.27 F3000 ;Quickly wipe away from the filament line\nG92 E0 ;Reset Extruder" }, + "machine_start_gcode": { "default_value": ";Official wiki URL for Geeetech M1:https://www.geeetech.com/wiki/index.php/Geeetech_M1_3D_printer \nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM140 S{material_bed_temperature_layer_0} ; Set Bed Temperature\n;M190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 ;Off Fan\nM300 S2500 P1000 ;Play a short tune\nG1 Z0.28 ;Move Z Axis up little to prevent scratching of Heat Bed\nG92 E0 ;Reset Extruder\nG1 Y3 F2400 ;Move to start position\nG1 X75 E40 F500 ;Draw a filament line\nG92 E0 ;Reset Extruder\n;G1 E-0.2 F3000 ;Retract a little\nG1 Z2.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X70 Y3 Z0.27 F3000 ;Quickly wipe away from the filament line\nG92 E0 ;Reset Extruder" }, "machine_width": { "default_value": 105 }, - "material_print_temperature": - { - "maximum_value": "230", - "value": "205 if speed_infill <=100 else 215 if speed_infill <= 150 else 220 if speed_infill <= 200 else 230" - }, - "retraction_amount": { "value": 1 }, + "material_bed_temperature": { "maximum_value": 60 }, + "material_print_temperature": { "maximum_value": 230 }, + "adhesion_type": { "value": "'brim'" }, + "brim_width": { "value": 2 }, + "retraction_amount": { "value": 2 }, "speed_print": { "maximum_value_warning": "200", diff --git a/resources/definitions/geeetech_M1S.def.json b/resources/definitions/geeetech_M1S.def.json new file mode 100644 index 0000000000..c2156a332e --- /dev/null +++ b/resources/definitions/geeetech_M1S.def.json @@ -0,0 +1,59 @@ +{ + "version": 2, + "name": "Geeetech M1S", + "inherits": "Geeetech_Base_Single_Extruder", + "metadata": + { + "visible": true, + "machine_extruder_trains": { "0": "Geeetech_Single_Extruder" } + }, + "overrides": + { + "gantry_height": { "value": 35 }, + "machine_depth": { "default_value": 105 }, + "machine_end_gcode": { "default_value": "G91 ;Switch to relative positioning\nG1 E-2.5 F2700 ;Retract filament\nG1 E-1.5 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Move away\nG1 Z10 ;lift print head\nG90 ;Switch to absolute positioning\nG28 X Y ;homing XY\nM106 S0 ;off Fan\nM104 S0 ;Cooldown hotend\nM140 S0 ;Cooldown bed\nM84 X Y E ;Disable steppers" }, + "machine_head_with_fans_polygon": + { + "default_value": [ + [-31, 31], + [34, 31], + [34, -40], + [-31, -40] + ] + }, + "machine_height": { "default_value": 95 }, + "machine_name": { "default_value": "Geeetech M1S" }, + "machine_start_gcode": { "default_value": ";Official wiki URL for Geeetech M1S:https://www.geeetech.com/wiki/index.php/Geeetech_M1S_3D_printer \nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM140 S{material_bed_temperature_layer_0} ; Set Bed Temperature\n;M190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 ;Off Fan\nM300 S2500 P1000 ;Play a short tune\nG1 Z0.28 ;Move Z Axis up little to prevent scratching of Heat Bed\nG92 E0 ;Reset Extruder\nG1 Y3 F2400 ;Move to start position\nG1 X75 E40 F500 ;Draw a filament line\nG92 E0 ;Reset Extruder\n;G1 E-0.2 F3000 ;Retract a little\nG1 Z2.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X70 Y3 Z0.27 F3000 ;Quickly wipe away from the filament line\nG92 E0 ;Reset Extruder" }, + "machine_width": { "default_value": 105 }, + "material_bed_temperature": { "maximum_value": 85 }, + "material_print_temperature": { "maximum_value": 250 }, + "adhesion_type": { "value": "'brim'" }, + "brim_width": { "value": 2 }, + "retraction_amount": { "value": 2 }, + "speed_print": + { + "maximum_value_warning": "200", + "value": 120 + }, + "speed_topbottom": + { + "maximum_value_warning": "200", + "value": 60 + }, + "speed_wall": + { + "maximum_value_warning": "200", + "value": 80 + }, + "speed_wall_0": + { + "maximum_value_warning": "200", + "value": 50 + }, + "speed_wall_x": + { + "maximum_value_warning": "200", + "value": 80 + } + } +} \ No newline at end of file diff --git a/resources/definitions/geeetech_Thunder.def.json b/resources/definitions/geeetech_Thunder.def.json index cc3e4044f8..3541a65bee 100644 --- a/resources/definitions/geeetech_Thunder.def.json +++ b/resources/definitions/geeetech_Thunder.def.json @@ -81,13 +81,12 @@ "machine_max_jerk_xy": { "value": 45 }, "machine_max_jerk_z": { "value": 0.8 }, "machine_name": { "default_value": "Geeetech Thunder" }, - "machine_start_gcode": { "default_value": ";Official viki homepage for Thunder:https://www.geeetech.com/wiki/index.php/Geeetech_Thunder_3D_printer \n\nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 P0 ;Off Main Fan\nM107 P1 ;Off Aux Fan\nM2012 P8 S1 F100 ; ON Light\n;M106 P0 S383 ; ON MainFan 150% if need\n;M106 P1 S255 ; ON Aux Fan 100% if need\nG1 Z5.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z0.8 F5000 ; Move to start position\nG1 X0.1 Y200.0 Z1.2 F1500 E30 ; Draw the first line\nG92 E0 ; Reset Extruder\nG1 X0.4 Y200.0 Z1.2 F3000 ; Move to side a little\nG1 X0.4 Y20 Z1.2 F1500 E25 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.4 F3000.0 ; Scrape off nozzle residue" }, + "machine_start_gcode": { "default_value": ";Official wiki URL for Thunder:https://www.geeetech.com/wiki/index.php/Geeetech_Thunder_3D_printer \n\nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 P0 ;Off Main Fan\nM107 P1 ;Off Aux Fan\nM2012 P8 S1 F100 ; ON Light\n;M106 P0 S383 ; ON MainFan 150% if need\n;M106 P1 S255 ; ON Aux Fan 100% if need\nG1 Z5.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z0.8 F5000 ; Move to start position\nG1 X0.1 Y200.0 Z1.2 F1500 E30 ; Draw the first line\nG92 E0 ; Reset Extruder\nG1 X0.4 Y200.0 Z1.2 F3000 ; Move to side a little\nG1 X0.4 Y20 Z1.2 F1500 E25 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.4 F3000.0 ; Scrape off nozzle residue" }, "machine_width": { "default_value": 250 }, "material_flow_layer_0": { "value": 95 }, "material_print_temperature": { - "maximum_value": "250", - "value": "200 if speed_infill <=150 else 205 if speed_infill <= 200 else 215 if speed_infill <= 260 else 220" + "maximum_value": "250" }, "material_print_temperature_layer_0": { diff --git a/resources/variants/geeetech_variants/geeetech_M1S_0.2.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1S_0.2.inst.cfg new file mode 100644 index 0000000000..2ed913b2a4 --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1S_0.2.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1S +name = 0.2mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 25 +type = variant + +[values] +machine_nozzle_size = 0.2 + diff --git a/resources/variants/geeetech_variants/geeetech_M1S_0.3.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1S_0.3.inst.cfg new file mode 100644 index 0000000000..032e25592d --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1S_0.3.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1S +name = 0.3mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 25 +type = variant + +[values] +machine_nozzle_size = 0.3 + diff --git a/resources/variants/geeetech_variants/geeetech_M1S_0.4.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1S_0.4.inst.cfg new file mode 100644 index 0000000000..12306b7acc --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1S_0.4.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1S +name = 0.4mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 25 +type = variant + +[values] +machine_nozzle_size = 0.4 + diff --git a/resources/variants/geeetech_variants/geeetech_M1S_0.5.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1S_0.5.inst.cfg new file mode 100644 index 0000000000..59db9afec4 --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1S_0.5.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1S +name = 0.5mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 25 +type = variant + +[values] +machine_nozzle_size = 0.5 + diff --git a/resources/variants/geeetech_variants/geeetech_M1S_0.6.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1S_0.6.inst.cfg new file mode 100644 index 0000000000..ee92dc8c93 --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1S_0.6.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1S +name = 0.6mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 25 +type = variant + +[values] +machine_nozzle_size = 0.6 + diff --git a/resources/variants/geeetech_variants/geeetech_M1S_0.8.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1S_0.8.inst.cfg new file mode 100644 index 0000000000..0029d6101c --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1S_0.8.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1S +name = 0.8mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 25 +type = variant + +[values] +machine_nozzle_size = 0.8 + diff --git a/resources/variants/geeetech_variants/geeetech_M1S_1.0.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1S_1.0.inst.cfg new file mode 100644 index 0000000000..225b0b3c06 --- /dev/null +++ b/resources/variants/geeetech_variants/geeetech_M1S_1.0.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = geeetech_M1S +name = 1.0mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 25 +type = variant + +[values] +machine_nozzle_size = 1.0 + diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.2.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.2.inst.cfg index 2ab1f4dd00..77bf14e06e 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_0.2.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_0.2.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.3.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.3.inst.cfg index f2cd78d138..f9ecf2eec2 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_0.3.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_0.3.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.4.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.4.inst.cfg index aee452940d..e3c124c614 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_0.4.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_0.4.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.5.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.5.inst.cfg index dbd7e2a69c..5adccce2df 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_0.5.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_0.5.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.6.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.6.inst.cfg index 9c542b5fb2..f61f2febc0 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_0.6.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_0.6.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] diff --git a/resources/variants/geeetech_variants/geeetech_M1_0.8.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_0.8.inst.cfg index 628e670353..0677557124 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_0.8.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_0.8.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] diff --git a/resources/variants/geeetech_variants/geeetech_M1_1.0.inst.cfg b/resources/variants/geeetech_variants/geeetech_M1_1.0.inst.cfg index 7a7618760a..5df54b48df 100644 --- a/resources/variants/geeetech_variants/geeetech_M1_1.0.inst.cfg +++ b/resources/variants/geeetech_variants/geeetech_M1_1.0.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] From c0a23e4f58097a709f510f60a8d6c867819b25b5 Mon Sep 17 00:00:00 2001 From: whoseyoung <78847564+whoseyoung@users.noreply.github.com> Date: Sat, 7 Jun 2025 09:02:39 +0000 Subject: [PATCH 150/299] Apply printer-linter format --- resources/definitions/geeetech_M1.def.json | 4 ++-- resources/definitions/geeetech_M1S.def.json | 4 ++-- resources/definitions/geeetech_Thunder.def.json | 5 +---- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/resources/definitions/geeetech_M1.def.json b/resources/definitions/geeetech_M1.def.json index 1bb0c5ce0c..2782c7c87c 100644 --- a/resources/definitions/geeetech_M1.def.json +++ b/resources/definitions/geeetech_M1.def.json @@ -9,6 +9,8 @@ }, "overrides": { + "adhesion_type": { "value": "'brim'" }, + "brim_width": { "value": 2 }, "gantry_height": { "value": 35 }, "machine_depth": { "default_value": 105 }, "machine_end_gcode": { "default_value": "G91 ;Switch to relative positioning\nG1 E-2.5 F2700 ;Retract filament\nG1 E-1.5 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Move away\nG1 Z10 ;lift print head\nG90 ;Switch to absolute positioning\nG28 X Y ;homing XY\nM106 S0 ;off Fan\nM104 S0 ;Cooldown hotend\nM140 S0 ;Cooldown bed\nM84 X Y E ;Disable steppers" }, @@ -27,8 +29,6 @@ "machine_width": { "default_value": 105 }, "material_bed_temperature": { "maximum_value": 60 }, "material_print_temperature": { "maximum_value": 230 }, - "adhesion_type": { "value": "'brim'" }, - "brim_width": { "value": 2 }, "retraction_amount": { "value": 2 }, "speed_print": { diff --git a/resources/definitions/geeetech_M1S.def.json b/resources/definitions/geeetech_M1S.def.json index c2156a332e..79bfec5a89 100644 --- a/resources/definitions/geeetech_M1S.def.json +++ b/resources/definitions/geeetech_M1S.def.json @@ -9,6 +9,8 @@ }, "overrides": { + "adhesion_type": { "value": "'brim'" }, + "brim_width": { "value": 2 }, "gantry_height": { "value": 35 }, "machine_depth": { "default_value": 105 }, "machine_end_gcode": { "default_value": "G91 ;Switch to relative positioning\nG1 E-2.5 F2700 ;Retract filament\nG1 E-1.5 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Move away\nG1 Z10 ;lift print head\nG90 ;Switch to absolute positioning\nG28 X Y ;homing XY\nM106 S0 ;off Fan\nM104 S0 ;Cooldown hotend\nM140 S0 ;Cooldown bed\nM84 X Y E ;Disable steppers" }, @@ -27,8 +29,6 @@ "machine_width": { "default_value": 105 }, "material_bed_temperature": { "maximum_value": 85 }, "material_print_temperature": { "maximum_value": 250 }, - "adhesion_type": { "value": "'brim'" }, - "brim_width": { "value": 2 }, "retraction_amount": { "value": 2 }, "speed_print": { diff --git a/resources/definitions/geeetech_Thunder.def.json b/resources/definitions/geeetech_Thunder.def.json index 3541a65bee..cf0f9dd5e9 100644 --- a/resources/definitions/geeetech_Thunder.def.json +++ b/resources/definitions/geeetech_Thunder.def.json @@ -84,10 +84,7 @@ "machine_start_gcode": { "default_value": ";Official wiki URL for Thunder:https://www.geeetech.com/wiki/index.php/Geeetech_Thunder_3D_printer \n\nM104 S{material_print_temperature_layer_0} ; Set Hotend Temperature\nM190 S{material_bed_temperature_layer_0} ; Wait for Bed Temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Hotend Temperature\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 P0 ;Off Main Fan\nM107 P1 ;Off Aux Fan\nM2012 P8 S1 F100 ; ON Light\n;M106 P0 S383 ; ON MainFan 150% if need\n;M106 P1 S255 ; ON Aux Fan 100% if need\nG1 Z5.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z0.8 F5000 ; Move to start position\nG1 X0.1 Y200.0 Z1.2 F1500 E30 ; Draw the first line\nG92 E0 ; Reset Extruder\nG1 X0.4 Y200.0 Z1.2 F3000 ; Move to side a little\nG1 X0.4 Y20 Z1.2 F1500 E25 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.4 F3000.0 ; Scrape off nozzle residue" }, "machine_width": { "default_value": 250 }, "material_flow_layer_0": { "value": 95 }, - "material_print_temperature": - { - "maximum_value": "250" - }, + "material_print_temperature": { "maximum_value": "250" }, "material_print_temperature_layer_0": { "maximum_value_warning": 300, From e63243bca81e88655d09e3c20277f42315114216 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 7 Jun 2025 09:09:59 -0400 Subject: [PATCH 151/299] Update DisplayInfoOnLCD.py It turns out that some firmware doesn't like colons within M118 commands. --- plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 0e3b52c81f..89c76769c9 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -357,7 +357,7 @@ class DisplayInfoOnLCD(Script): orig_hr = round(orig_hhh // 1) orig_mmm = math.floor((orig_hhh % 1) * 60) if self.add_m118_line: - lines.insert(len(lines) - 2, f"M118 Adjusted Print Time: {hr} hr {mmm} min") + lines.insert(len(lines) - 2, f"M118 Adjusted Print Time is {hr} hr {mmm} min") if self.add_m117_line: lines.insert(len(lines) - 2, f"M117 ET {hr} hr {mmm} min") # Add M73 line at beginning From b358b93b690bd2106c9c68f50da5f3c73b11fafe Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 10 Jun 2025 08:30:43 +0200 Subject: [PATCH 152/299] Use proper English word for "plane" CURA-12544 The word in French to describe a geometric flat surface if "plan", which is a valid word in English but it doesn't have the same meaning, this got me confused. So replacing "plan" by "plane" because we are actually dealing with a geometrical "plane" (although it doesn't fly). --- plugins/SimulationView/layers3d_shadow.shader | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/SimulationView/layers3d_shadow.shader b/plugins/SimulationView/layers3d_shadow.shader index 47637cfb20..0cf3e4f75a 100644 --- a/plugins/SimulationView/layers3d_shadow.shader +++ b/plugins/SimulationView/layers3d_shadow.shader @@ -103,8 +103,8 @@ geometry41core = vec4 g_vertex_offset_vert; vec3 g_vertex_normal_horz_head; vec4 g_vertex_offset_horz_head; - vec3 g_axial_plan_vector; - vec3 g_radial_plan_vector; + vec3 g_axial_plane_vector; + vec3 g_radial_plane_vector; float size_x; float size_y; @@ -143,25 +143,25 @@ geometry41core = if (g_vertex_delta.y == 0.0) { - // vector is in the horizontal plan, radial vector is a simple rotation around Y axis - g_radial_plan_vector = vec3(g_vertex_delta.z, 0.0, -g_vertex_delta.x); + // vector is in the horizontal plane, radial vector is a simple rotation around Y axis + g_radial_plane_vector = vec3(g_vertex_delta.z, 0.0, -g_vertex_delta.x); } else if(g_vertex_delta.x == 0.0 && g_vertex_delta.z == 0.0) { // delta vector is purely vertical, display the line rotated vertically so that it is visible in front and side views - g_radial_plan_vector = vec3(1.0, 0.0, -1.0); + g_radial_plane_vector = vec3(1.0, 0.0, -1.0); } else { // delta vector is completely 3D - g_axial_plan_vector = vec3(g_vertex_delta.x, 0.0, g_vertex_delta.z); // Vector projected in the horizontal plan - g_radial_plan_vector = cross(g_vertex_delta, g_axial_plan_vector); // Radial vector in the horizontal plan, pointing right. + g_axial_plane_vector = vec3(g_vertex_delta.x, 0.0, g_vertex_delta.z); // Vector projected in the horizontal plane + g_radial_plane_vector = cross(g_vertex_delta, g_axial_plane_vector); // Radial vector in the horizontal plane, pointing right. } g_vertex_normal_horz_head = normalize(g_vertex_delta); //Lengthwise normal vector g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); //Lengthwise offset vector - g_vertex_normal_horz = normalize(g_radial_plan_vector); //Normal vector pointing right. + g_vertex_normal_horz = normalize(g_radial_plane_vector); //Normal vector pointing right. g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //Offset vector pointing right. g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); //Upwards normal vector. From f84923185ded2dde8f614a7ab6f0e50d6290b343 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 10 Jun 2025 08:30:43 +0200 Subject: [PATCH 153/299] Use proper English word for "plane" CURA-12544 The word in French to describe a geometric flat surface if "plan", which is a valid word in English but it doesn't have the same meaning, this got me confused. So replacing "plan" by "plane" because we are actually dealing with a geometrical "plane" (although it doesn't fly). --- plugins/SimulationView/layers3d_shadow.shader | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/SimulationView/layers3d_shadow.shader b/plugins/SimulationView/layers3d_shadow.shader index 47637cfb20..0cf3e4f75a 100644 --- a/plugins/SimulationView/layers3d_shadow.shader +++ b/plugins/SimulationView/layers3d_shadow.shader @@ -103,8 +103,8 @@ geometry41core = vec4 g_vertex_offset_vert; vec3 g_vertex_normal_horz_head; vec4 g_vertex_offset_horz_head; - vec3 g_axial_plan_vector; - vec3 g_radial_plan_vector; + vec3 g_axial_plane_vector; + vec3 g_radial_plane_vector; float size_x; float size_y; @@ -143,25 +143,25 @@ geometry41core = if (g_vertex_delta.y == 0.0) { - // vector is in the horizontal plan, radial vector is a simple rotation around Y axis - g_radial_plan_vector = vec3(g_vertex_delta.z, 0.0, -g_vertex_delta.x); + // vector is in the horizontal plane, radial vector is a simple rotation around Y axis + g_radial_plane_vector = vec3(g_vertex_delta.z, 0.0, -g_vertex_delta.x); } else if(g_vertex_delta.x == 0.0 && g_vertex_delta.z == 0.0) { // delta vector is purely vertical, display the line rotated vertically so that it is visible in front and side views - g_radial_plan_vector = vec3(1.0, 0.0, -1.0); + g_radial_plane_vector = vec3(1.0, 0.0, -1.0); } else { // delta vector is completely 3D - g_axial_plan_vector = vec3(g_vertex_delta.x, 0.0, g_vertex_delta.z); // Vector projected in the horizontal plan - g_radial_plan_vector = cross(g_vertex_delta, g_axial_plan_vector); // Radial vector in the horizontal plan, pointing right. + g_axial_plane_vector = vec3(g_vertex_delta.x, 0.0, g_vertex_delta.z); // Vector projected in the horizontal plane + g_radial_plane_vector = cross(g_vertex_delta, g_axial_plane_vector); // Radial vector in the horizontal plane, pointing right. } g_vertex_normal_horz_head = normalize(g_vertex_delta); //Lengthwise normal vector g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); //Lengthwise offset vector - g_vertex_normal_horz = normalize(g_radial_plan_vector); //Normal vector pointing right. + g_vertex_normal_horz = normalize(g_radial_plane_vector); //Normal vector pointing right. g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //Offset vector pointing right. g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); //Upwards normal vector. From 23edebf6fd1eea9157a36994dc27b4b1853db6dd Mon Sep 17 00:00:00 2001 From: Frederic Meeuwissen <13856291+Frederic98@users.noreply.github.com> Date: Wed, 4 Jun 2025 10:23:34 +0200 Subject: [PATCH 154/299] [PP-639] Remove quality_definition for S8 This caused an infinite loop as it refers to itself --- resources/definitions/ultimaker_s8.def.json | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/definitions/ultimaker_s8.def.json b/resources/definitions/ultimaker_s8.def.json index fb8243cd60..05f1932ce1 100644 --- a/resources/definitions/ultimaker_s8.def.json +++ b/resources/definitions/ultimaker_s8.def.json @@ -48,7 +48,6 @@ "preferred_material": "ultimaker_pla_blue", "preferred_quality_type": "draft", "preferred_variant_name": "AA+ 0.4", - "quality_definition": "ultimaker_s8", "supported_actions": [ "DiscoverUM3Action" ], "supports_material_export": true, "supports_network_connection": true, From cbb9d992e9b3623e6f78b511b33ac75a9e34a111 Mon Sep 17 00:00:00 2001 From: Frederic Meeuwissen <13856291+Frederic98@users.noreply.github.com> Date: Tue, 10 Jun 2025 16:20:42 +0200 Subject: [PATCH 155/299] [PP-639] Inherit S8 from S5 i.s.o. S7 To prevent inheriting `quality_definition: ultimaker_s5` from the S7 --- resources/definitions/ultimaker_s8.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/ultimaker_s8.def.json b/resources/definitions/ultimaker_s8.def.json index 05f1932ce1..b7de27722d 100644 --- a/resources/definitions/ultimaker_s8.def.json +++ b/resources/definitions/ultimaker_s8.def.json @@ -1,7 +1,7 @@ { "version": 2, "name": "UltiMaker S8", - "inherits": "ultimaker_s7", + "inherits": "ultimaker_s5", "metadata": { "visible": true, From a8ab9ecb75c957419a5d3025fbb8bf0f57dbed43 Mon Sep 17 00:00:00 2001 From: Frederic Meeuwissen <13856291+Frederic98@users.noreply.github.com> Date: Tue, 10 Jun 2025 16:21:12 +0200 Subject: [PATCH 156/299] [PP-639] Move some setting overrides from S7 to S5 --- resources/definitions/ultimaker_s5.def.json | 7 ++++++- resources/definitions/ultimaker_s7.def.json | 4 +--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/resources/definitions/ultimaker_s5.def.json b/resources/definitions/ultimaker_s5.def.json index 46d46d33eb..fa6f5a9a38 100644 --- a/resources/definitions/ultimaker_s5.def.json +++ b/resources/definitions/ultimaker_s5.def.json @@ -72,7 +72,11 @@ "brim_width": { "value": "3" }, "build_volume_temperature": { "maximum_value": 50 }, "cool_fan_speed": { "value": "50" }, - "default_material_print_temperature": { "value": "200" }, + "default_material_print_temperature": + { + "maximum_value_warning": "320", + "value": "200" + }, "extruder_prime_pos_abs": { "default_value": true }, "gantry_height": { "value": "55" }, "infill_pattern": { "value": "'zigzag' if infill_sparse_density > 80 else 'triangles'" }, @@ -104,6 +108,7 @@ "machine_nozzle_heat_up_speed": { "default_value": 1.4 }, "machine_start_gcode": { "default_value": "" }, "machine_width": { "default_value": 330 }, + "material_print_temperature_layer_0": { "maximum_value_warning": "320" }, "multiple_mesh_overlap": { "value": "0" }, "optimize_wall_printing_order": { "value": "True" }, "prime_blob_enable": diff --git a/resources/definitions/ultimaker_s7.def.json b/resources/definitions/ultimaker_s7.def.json index 14d9b21168..ac2f927ad4 100644 --- a/resources/definitions/ultimaker_s7.def.json +++ b/resources/definitions/ultimaker_s7.def.json @@ -46,8 +46,6 @@ }, "overrides": { - "default_material_print_temperature": { "maximum_value_warning": "320" }, - "machine_name": { "default_value": "Ultimaker S7" }, - "material_print_temperature_layer_0": { "maximum_value_warning": "320" } + "machine_name": { "default_value": "Ultimaker S7" } } } \ No newline at end of file From 65b0e4f080d0dceb37aeddc8ca9f4d8cc52e6883 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 11 Jun 2025 10:51:47 +0200 Subject: [PATCH 157/299] Add specific message when sending a print to an inactive printer CURA-12557 --- .../src/Cloud/CloudApiClient.py | 22 +++++++++++++++++-- .../src/Cloud/CloudOutputDevice.py | 16 +++++++++----- .../PrintJobUploadPrinterInactiveMessage.py | 20 +++++++++++++++++ 3 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadPrinterInactiveMessage.py diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py index 3c8e53b2e9..0831ceebd3 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py @@ -163,7 +163,7 @@ class CloudApiClient: scope=self._scope, data=b"", callback=self._parseCallback(on_finished, CloudPrintResponse), - error_callback=on_error, + error_callback=self._parseError(on_error), timeout=self.DEFAULT_REQUEST_TIMEOUT) def doPrintJobAction(self, cluster_id: str, cluster_job_id: str, action: str, @@ -256,7 +256,6 @@ class CloudApiClient: """Creates a callback function so that it includes the parsing of the response into the correct model. The callback is added to the 'finished' signal of the reply. - :param reply: The reply that should be listened to. :param on_finished: The callback in case the response is successful. Depending on the endpoint it will be either a list or a single item. :param model: The type of the model to convert the response to. @@ -281,6 +280,25 @@ class CloudApiClient: self._anti_gc_callbacks.append(parse) return parse + def _parseError(self, + on_error: Callable[[CloudError, "QNetworkReply.NetworkError", int], None]) -> Callable[[QNetworkReply, "QNetworkReply.NetworkError"], None]: + + """Creates a callback function so that it includes the parsing of an explicit error response into the correct model. + + :param on_error: The callback in case the response gives an explicit error + """ + + def parse(reply: QNetworkReply, error: "QNetworkReply.NetworkError") -> None: + + self._anti_gc_callbacks.remove(parse) + + http_code, response = self._parseReply(reply) + result = CloudError(**response["errors"][0]) + on_error(result, error, http_code) + + self._anti_gc_callbacks.append(parse) + return parse + @classmethod def getMachineIDMap(cls) -> Dict[str, str]: if cls._machine_id_to_name is None: diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py index 090355a3c0..df486822b7 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py @@ -27,9 +27,11 @@ from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOut from ..Messages.PrintJobUploadBlockedMessage import PrintJobUploadBlockedMessage from ..Messages.PrintJobUploadErrorMessage import PrintJobUploadErrorMessage from ..Messages.PrintJobUploadQueueFullMessage import PrintJobUploadQueueFullMessage +from ..Messages.PrintJobUploadPrinterInactiveMessage import PrintJobUploadPrinterInactiveMessage from ..Messages.PrintJobUploadSuccessMessage import PrintJobUploadSuccessMessage from ..Models.Http.CloudClusterResponse import CloudClusterResponse from ..Models.Http.CloudClusterStatus import CloudClusterStatus +from ..Models.Http.CloudError import CloudError from ..Models.Http.CloudPrintJobUploadRequest import CloudPrintJobUploadRequest from ..Models.Http.CloudPrintResponse import CloudPrintResponse from ..Models.Http.CloudPrintJobResponse import CloudPrintJobResponse @@ -291,19 +293,21 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): self.writeFinished.emit() - def _onPrintUploadSpecificError(self, reply: "QNetworkReply", _: "QNetworkReply.NetworkError"): + def _onPrintUploadSpecificError(self, error: CloudError, _: "QNetworkReply.NetworkError", http_error: int): """ Displays a message when an error occurs specific to uploading print job (i.e. queue is full). """ - error_code = reply.attribute(QNetworkRequest.Attribute.HttpStatusCodeAttribute) - if error_code == 409: - PrintJobUploadQueueFullMessage().show() + if http_error == 409: + if error.code == "printerInactive": + PrintJobUploadPrinterInactiveMessage().show() + else: + PrintJobUploadQueueFullMessage().show() else: PrintJobUploadErrorMessage(I18N_CATALOG.i18nc("@error:send", "Unknown error code when uploading print job: {0}", - error_code)).show() + http_error)).show() - Logger.log("w", "Upload of print job failed specifically with error code {}".format(error_code)) + Logger.log("w", "Upload of print job failed specifically with error code {}".format(http_error)) self._progress.hide() self._pre_upload_print_job = None diff --git a/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadPrinterInactiveMessage.py b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadPrinterInactiveMessage.py new file mode 100644 index 0000000000..324259eea4 --- /dev/null +++ b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadPrinterInactiveMessage.py @@ -0,0 +1,20 @@ +# Copyright (c) 2020 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from UM import i18nCatalog +from UM.Message import Message + + +I18N_CATALOG = i18nCatalog("cura") + + +class PrintJobUploadPrinterInactiveMessage(Message): + """Message shown when uploading a print job to a cluster and the printer is inactive.""" + + def __init__(self) -> None: + super().__init__( + text = I18N_CATALOG.i18nc("@info:status", "The printer is inactive and cannot accept a new print job."), + title = I18N_CATALOG.i18nc("@info:title", "Printer inactive"), + lifetime = 10, + message_type=Message.MessageType.ERROR + ) From 2e9999ed2dd36d0e1e2f5da474e18ef1f5018a77 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 11 Jun 2025 13:51:45 +0200 Subject: [PATCH 158/299] Display the printer activation status CURA-12557 --- cura/Settings/MachineManager.py | 14 +++++++ .../src/Cloud/CloudOutputDevice.py | 13 ++++++ .../src/Models/Http/CloudClusterResponse.py | 6 ++- .../src/Models/Http/CloudClusterStatus.py | 2 + .../qml/PrinterSelector/MachineSelector.qml | 40 ++++++++++++++++--- resources/themes/cura-light/theme.json | 1 + 6 files changed, 69 insertions(+), 7 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 986608cd49..1bdb32f4ac 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -183,10 +183,16 @@ class MachineManager(QObject): self.setActiveMachine(active_machine_id) def _onOutputDevicesChanged(self) -> None: + for printer_output_device in self._printer_output_devices: + if hasattr(printer_output_device, "cloudActiveChanged"): + printer_output_device.cloudActiveChanged.disconnect(self.printerConnectedStatusChanged) + self._printer_output_devices = [] for printer_output_device in self._application.getOutputDeviceManager().getOutputDevices(): if isinstance(printer_output_device, PrinterOutputDevice): self._printer_output_devices.append(printer_output_device) + if hasattr(printer_output_device, "cloudActiveChanged"): + printer_output_device.cloudActiveChanged.connect(self.printerConnectedStatusChanged) self.outputDevicesChanged.emit() @@ -569,6 +575,14 @@ class MachineManager(QObject): def activeMachineIsUsingCloudConnection(self) -> bool: return self.activeMachineHasCloudConnection and not self.activeMachineHasNetworkConnection + @pyqtProperty(bool, notify = printerConnectedStatusChanged) + def activeMachineIsCloudActive(self) -> bool: + if not self._printer_output_devices: + return True + + first_printer = self._printer_output_devices[0] + return True if not hasattr(first_printer, 'cloudActive') else first_printer.cloudActive + def activeMachineNetworkKey(self) -> str: if self._global_container_stack: return self._global_container_stack.getMetaDataEntry("um_network_key", "") diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py index df486822b7..020cafacd8 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py @@ -65,6 +65,8 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): # Therefore, we create a private signal used to trigger the printersChanged signal. _cloudClusterPrintersChanged = pyqtSignal() + cloudActiveChanged = pyqtSignal() + def __init__(self, api_client: CloudApiClient, cluster: CloudClusterResponse, parent: QObject = None) -> None: """Creates a new cloud output device @@ -113,6 +115,9 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): self._pre_upload_print_job = None # type: Optional[CloudPrintJobResponse] self._uploaded_print_job = None # type: Optional[CloudPrintJobResponse] + # Whether the printer is active, i.e. authorized for use i.r.t to workspace limitations + self._active = cluster.display_status != "inactive" + CuraApplication.getInstance().getBackend().backendDone.connect(self._resetPrintJob) CuraApplication.getInstance().getController().getScene().sceneChanged.connect(self._onSceneChanged) @@ -192,6 +197,10 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): self._received_print_jobs = status.print_jobs self._updatePrintJobs(status.print_jobs) + if status.active != self._active: + self._active = status.active + self.cloudActiveChanged.emit() + def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False, file_handler: Optional[FileHandler] = None, filter_by_machine: bool = False, **kwargs) -> None: @@ -436,6 +445,10 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): root_url_prefix = "-staging" if self._account.is_staging else "" return f"https://digitalfactory{root_url_prefix}.ultimaker.com/app/jobs/{self.clusterData.cluster_id}" + @pyqtProperty(bool, notify = cloudActiveChanged) + def cloudActive(self) -> bool: + return self._active + def __del__(self): CuraApplication.getInstance().getBackend().backendDone.disconnect(self._resetPrintJob) CuraApplication.getInstance().getController().getScene().sceneChanged.disconnect(self._onSceneChanged) diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterResponse.py b/plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterResponse.py index 713582b8ad..a1f22f7b36 100644 --- a/plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterResponse.py +++ b/plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterResponse.py @@ -10,7 +10,7 @@ class CloudClusterResponse(BaseModel): """Class representing a cloud connected cluster.""" def __init__(self, cluster_id: str, host_guid: str, host_name: str, is_online: bool, status: str, - host_internal_ip: Optional[str] = None, host_version: Optional[str] = None, + display_status: str, host_internal_ip: Optional[str] = None, host_version: Optional[str] = None, friendly_name: Optional[str] = None, printer_type: str = "ultimaker3", printer_count: int = 1, capabilities: Optional[List[str]] = None, **kwargs) -> None: """Creates a new cluster response object. @@ -20,6 +20,7 @@ class CloudClusterResponse(BaseModel): :param host_name: The name of the printer as configured during the Wi-Fi setup. Used as identifier for end users. :param is_online: Whether this cluster is currently connected to the cloud. :param status: The status of the cluster authentication (active or inactive). + :param display_status: The display status of the cluster. :param host_version: The firmware version of the cluster host. This is where the Stardust client is running on. :param host_internal_ip: The internal IP address of the host printer. :param friendly_name: The human readable name of the host printer. @@ -31,6 +32,7 @@ class CloudClusterResponse(BaseModel): self.host_guid = host_guid self.host_name = host_name self.status = status + self.display_status = display_status self.is_online = is_online self.host_version = host_version self.host_internal_ip = host_internal_ip @@ -51,5 +53,5 @@ class CloudClusterResponse(BaseModel): Convenience function for printing when debugging. :return: A human-readable representation of the data in this object. """ - return str({k: v for k, v in self.__dict__.items() if k in {"cluster_id", "host_guid", "host_name", "status", "is_online", "host_version", "host_internal_ip", "friendly_name", "printer_type", "printer_count", "capabilities"}}) + return str({k: v for k, v in self.__dict__.items() if k in {"cluster_id", "host_guid", "host_name", "status", "display_status", "is_online", "host_version", "host_internal_ip", "friendly_name", "printer_type", "printer_count", "capabilities"}}) diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterStatus.py b/plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterStatus.py index 5cd151d8ef..34249dc67a 100644 --- a/plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterStatus.py +++ b/plugins/UM3NetworkPrinting/src/Models/Http/CloudClusterStatus.py @@ -14,6 +14,7 @@ class CloudClusterStatus(BaseModel): def __init__(self, printers: List[Union[ClusterPrinterStatus, Dict[str, Any]]], print_jobs: List[Union[ClusterPrintJobStatus, Dict[str, Any]]], generated_time: Union[str, datetime], + unavailable: bool = False, **kwargs) -> None: """Creates a new cluster status model object. @@ -23,6 +24,7 @@ class CloudClusterStatus(BaseModel): """ self.generated_time = self.parseDate(generated_time) + self.active = not unavailable self.printers = self.parseModels(ClusterPrinterStatus, printers) self.print_jobs = self.parseModels(ClusterPrintJobStatus, print_jobs) super().__init__(**kwargs) diff --git a/resources/qml/PrinterSelector/MachineSelector.qml b/resources/qml/PrinterSelector/MachineSelector.qml index 1bad1d70bc..7acdd9573b 100644 --- a/resources/qml/PrinterSelector/MachineSelector.qml +++ b/resources/qml/PrinterSelector/MachineSelector.qml @@ -16,6 +16,7 @@ Cura.ExpandablePopup property bool isConnectedCloudPrinter: machineManager.activeMachineHasCloudConnection property bool isCloudRegistered: machineManager.activeMachineHasCloudRegistration property bool isGroup: machineManager.activeMachineIsGroup + property bool isCloudActive: machineManager.activeMachineIsCloudActive property string machineName: { if (isNetworkPrinter && machineManager.activeMachineNetworkGroupName != "") { @@ -40,7 +41,14 @@ Cura.ExpandablePopup } else if (isConnectedCloudPrinter && Cura.API.connectionStatus.isInternetReachable) { - return "printer_cloud_connected" + if (isCloudActive) + { + return "printer_cloud_connected" + } + else + { + return "printer_cloud_inactive" + } } else if (isCloudRegistered) { @@ -53,7 +61,7 @@ Cura.ExpandablePopup } function getConnectionStatusMessage() { - if (connectionStatus == "printer_cloud_not_available") + if (connectionStatus === "printer_cloud_not_available") { if(Cura.API.connectionStatus.isInternetReachable) { @@ -78,6 +86,10 @@ Cura.ExpandablePopup return catalog.i18nc("@status", "The cloud connection is currently unavailable. Please check your internet connection.") } } + else if(connectionStatus === "printer_cloud_inactive") + { + return catalog.i18nc("@status", "This printer is deactivated and can not accept commands or jobs.") + } else { return "" @@ -130,14 +142,18 @@ Cura.ExpandablePopup source: { - if (connectionStatus == "printer_connected") + if (connectionStatus === "printer_connected") { return UM.Theme.getIcon("CheckBlueBG", "low") } - else if (connectionStatus == "printer_cloud_connected" || connectionStatus == "printer_cloud_not_available") + else if (connectionStatus === "printer_cloud_connected" || connectionStatus === "printer_cloud_not_available") { return UM.Theme.getIcon("CloudBadge", "low") } + else if (connectionStatus === "printer_cloud_inactive") + { + return UM.Theme.getIcon("WarningBadge", "low") + } else { return "" @@ -147,7 +163,21 @@ Cura.ExpandablePopup width: UM.Theme.getSize("printer_status_icon").width height: UM.Theme.getSize("printer_status_icon").height - color: connectionStatus == "printer_cloud_not_available" ? UM.Theme.getColor("cloud_unavailable") : UM.Theme.getColor("primary") + color: + { + if (connectionStatus === "printer_cloud_not_available") + { + return UM.Theme.getColor("cloud_unavailable") + } + else if(connectionStatus === "printer_cloud_inactive") + { + return UM.Theme.getColor("cloud_inactive") + } + else + { + return UM.Theme.getColor("primary") + } + } visible: (isNetworkPrinter || isCloudRegistered) && source != "" diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 1ae316f96c..8d09d7837d 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -496,6 +496,7 @@ "monitor_carousel_dot_current": [119, 119, 119, 255], "cloud_unavailable": [153, 153, 153, 255], + "cloud_inactive": "warning", "connection_badge_background": [255, 255, 255, 255], "warning_badge_background": [0, 0, 0, 255], "error_badge_background": [255, 255, 255, 255], From a739fd21f5d705ec639a538a9c1891e03658087a Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 11 Jun 2025 15:48:09 +0200 Subject: [PATCH 159/299] Display inactive DL projects as disabled CURA-12557 --- .../resources/qml/ProjectSummaryCard.qml | 36 ++++++++++++++----- .../resources/qml/SelectProjectPage.qml | 29 ++++++++++----- .../src/DigitalFactoryProjectModel.py | 3 ++ .../src/DigitalFactoryProjectResponse.py | 2 ++ resources/themes/cura-light/theme.json | 2 +- 5 files changed, 55 insertions(+), 17 deletions(-) diff --git a/plugins/DigitalLibrary/resources/qml/ProjectSummaryCard.qml b/plugins/DigitalLibrary/resources/qml/ProjectSummaryCard.qml index ca836ee21d..133cc0edde 100644 --- a/plugins/DigitalLibrary/resources/qml/ProjectSummaryCard.qml +++ b/plugins/DigitalLibrary/resources/qml/ProjectSummaryCard.qml @@ -11,10 +11,10 @@ Cura.RoundedRectangle width: parent.width height: projectImage.height + 2 * UM.Theme.getSize("default_margin").width cornerSide: Cura.RoundedRectangle.Direction.All - border.color: UM.Theme.getColor("lining") + border.color: enabled ? UM.Theme.getColor("lining") : UM.Theme.getColor("action_button_disabled_border") border.width: UM.Theme.getSize("default_lining").width radius: UM.Theme.getSize("default_radius").width - color: UM.Theme.getColor("main_background") + color: getBackgoundColor() signal clicked() property alias imageSource: projectImage.source property alias projectNameText: displayNameLabel.text @@ -22,17 +22,18 @@ Cura.RoundedRectangle property alias projectLastUpdatedText: lastUpdatedLabel.text property alias cardMouseAreaEnabled: cardMouseArea.enabled - onVisibleChanged: color = UM.Theme.getColor("main_background") + onVisibleChanged: color = getBackgroundColor() MouseArea { id: cardMouseArea anchors.fill: parent - hoverEnabled: true - onEntered: base.color = UM.Theme.getColor("action_button_hovered") - onExited: base.color = UM.Theme.getColor("main_background") + hoverEnabled: base.enabled + onEntered: color = getBackgroundColor() + onExited: color = getBackgroundColor() onClicked: base.clicked() } + Row { id: projectInformationRow @@ -73,7 +74,7 @@ Cura.RoundedRectangle width: parent.width height: Math.round(parent.height / 3) elide: Text.ElideRight - color: UM.Theme.getColor("small_button_text") + color: base.enabled ? UM.Theme.getColor("small_button_text") : UM.Theme.getColor("text_disabled") } UM.Label @@ -82,8 +83,27 @@ Cura.RoundedRectangle width: parent.width height: Math.round(parent.height / 3) elide: Text.ElideRight - color: UM.Theme.getColor("small_button_text") + color: base.enabled ? UM.Theme.getColor("small_button_text") : UM.Theme.getColor("text_disabled") } } } + + function getBackgroundColor() + { + if(enabled) + { + if(cardMouseArea.containsMouse) + { + return UM.Theme.getColor("action_button_hovered") + } + else + { + return UM.Theme.getColor("main_background") + } + } + else + { + return UM.Theme.getColor("action_button_disabled") + } + } } \ No newline at end of file diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index faceb4df23..2d0bd30f2b 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -159,17 +159,30 @@ Item Repeater { model: manager.digitalFactoryProjectModel - delegate: ProjectSummaryCard + delegate: Item { - id: projectSummaryCard - imageSource: model.thumbnailUrl || "../images/placeholder.svg" - projectNameText: model.displayName - projectUsernameText: model.username - projectLastUpdatedText: "Last updated: " + model.lastUpdated + width: parent.width + height: projectSummaryCard.height - onClicked: + UM.TooltipArea { - manager.selectedProjectIndex = index + anchors.fill: parent + text: "This project is inactive and cannot be used." + enabled: !model.active + } + + ProjectSummaryCard + { + id: projectSummaryCard + imageSource: model.thumbnailUrl || "../images/placeholder.svg" + projectNameText: model.displayName + projectUsernameText: model.username + projectLastUpdatedText: "Last updated: " + model.lastUpdated + enabled: model.active + + onClicked: { + manager.selectedProjectIndex = index + } } } } diff --git a/plugins/DigitalLibrary/src/DigitalFactoryProjectModel.py b/plugins/DigitalLibrary/src/DigitalFactoryProjectModel.py index bd12a4ca12..7140657508 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryProjectModel.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryProjectModel.py @@ -17,6 +17,7 @@ class DigitalFactoryProjectModel(ListModel): ThumbnailUrlRole = Qt.ItemDataRole.UserRole + 5 UsernameRole = Qt.ItemDataRole.UserRole + 6 LastUpdatedRole = Qt.ItemDataRole.UserRole + 7 + ActiveRole = Qt.ItemDataRole.UserRole + 8 dfProjectModelChanged = pyqtSignal() @@ -28,6 +29,7 @@ class DigitalFactoryProjectModel(ListModel): self.addRoleName(self.ThumbnailUrlRole, "thumbnailUrl") self.addRoleName(self.UsernameRole, "username") self.addRoleName(self.LastUpdatedRole, "lastUpdated") + self.addRoleName(self.ActiveRole, "active") self._projects = [] # type: List[DigitalFactoryProjectResponse] def setProjects(self, df_projects: List[DigitalFactoryProjectResponse]) -> None: @@ -59,5 +61,6 @@ class DigitalFactoryProjectModel(ListModel): "thumbnailUrl": project.thumbnail_url, "username": project.username, "lastUpdated": project.last_updated.strftime(PROJECT_UPDATED_AT_DATETIME_FORMAT) if project.last_updated else "", + "active": project.active, }) self.dfProjectModelChanged.emit() diff --git a/plugins/DigitalLibrary/src/DigitalFactoryProjectResponse.py b/plugins/DigitalLibrary/src/DigitalFactoryProjectResponse.py index bef90e5125..303271f211 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryProjectResponse.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryProjectResponse.py @@ -28,6 +28,7 @@ class DigitalFactoryProjectResponse(BaseModel): team_ids: Optional[List[str]] = None, status: Optional[str] = None, technical_requirements: Optional[Dict[str, Any]] = None, + is_inactive: bool = False, **kwargs) -> None: """ Creates a new digital factory project response object @@ -56,6 +57,7 @@ class DigitalFactoryProjectResponse(BaseModel): self.last_updated = datetime.strptime(last_updated, DIGITAL_FACTORY_RESPONSE_DATETIME_FORMAT) if last_updated else None self.status = status self.technical_requirements = technical_requirements + self.active = not is_inactive super().__init__(**kwargs) def __str__(self) -> str: diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 8d09d7837d..f8686aafcf 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -496,7 +496,7 @@ "monitor_carousel_dot_current": [119, 119, 119, 255], "cloud_unavailable": [153, 153, 153, 255], - "cloud_inactive": "warning", + "cloud_inactive": [253, 209, 58, 255], "connection_badge_background": [255, 255, 255, 255], "warning_badge_background": [0, 0, 0, 255], "error_badge_background": [255, 255, 255, 255], From b6b2da0c148af19614cf90537dd3599263fbc316 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 12 Jun 2025 08:39:59 +0200 Subject: [PATCH 160/299] Change wording as suggested CURA-11978 "Unretraction" is a barbaric word, better use "Priming" instead --- plugins/SimulationView/SimulationViewMenuComponent.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/SimulationView/SimulationViewMenuComponent.qml b/plugins/SimulationView/SimulationViewMenuComponent.qml index 0e254a005b..78b0b2b74f 100644 --- a/plugins/SimulationView/SimulationViewMenuComponent.qml +++ b/plugins/SimulationView/SimulationViewMenuComponent.qml @@ -229,7 +229,7 @@ Cura.ExpandableComponent { const travelsTypesModel = [ { - label: catalog.i18nc("@label", "Unretracted"), + label: catalog.i18nc("@label", "Not retracted"), colorId: "layerview_move_combing" }, { @@ -241,7 +241,7 @@ Cura.ExpandableComponent colorId: "layerview_move_while_retracting" }, { - label: catalog.i18nc("@label", "Unretracting"), + label: catalog.i18nc("@label", "Priming"), colorId: "layerview_move_while_unretracting" } ]; From f9c6d4aad1ea06a95dd064b2c6398a8d37ced57b Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 12 Jun 2025 14:21:36 +0200 Subject: [PATCH 161/299] definition adjustments - If the machine has two extruder trains, they should be defined individually rather than reused from another machine, creates unnecessary linkage between machines. - Added "has_textured_buildplate" --- resources/definitions/biqu_b2.def.json | 3 ++- resources/extruders/biqu_b2_extruder_0.def.json | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 resources/extruders/biqu_b2_extruder_0.def.json diff --git a/resources/definitions/biqu_b2.def.json b/resources/definitions/biqu_b2.def.json index 3676ca8955..a5721d62d4 100644 --- a/resources/definitions/biqu_b2.def.json +++ b/resources/definitions/biqu_b2.def.json @@ -6,8 +6,9 @@ { "visible": true, "author": "Boris Juraga", + "has_textured_buildplate": true, "machine_extruder_trains": { - "0": "biqu_base_extruder_0", + "0": "biqu_b2_extruder_0", "1": "biqu_b2_extruder_1" }, "quality_definition": "biqu_b2" diff --git a/resources/extruders/biqu_b2_extruder_0.def.json b/resources/extruders/biqu_b2_extruder_0.def.json new file mode 100644 index 0000000000..4bfb9686b3 --- /dev/null +++ b/resources/extruders/biqu_b2_extruder_0.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": + { + "machine": "biqu_b2", + "position": "0" + }, + "overrides": + { + "extruder_nr": { "default_value": 0 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} \ No newline at end of file From 45f28184e530eb357d2029faebfb7ee3f2d85f36 Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Thu, 12 Jun 2025 12:47:20 +0000 Subject: [PATCH 162/299] Apply printer-linter format --- resources/definitions/sovol_sv01.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/sovol_sv01.def.json b/resources/definitions/sovol_sv01.def.json index dd64702f7f..5c87d8124e 100644 --- a/resources/definitions/sovol_sv01.def.json +++ b/resources/definitions/sovol_sv01.def.json @@ -26,4 +26,4 @@ "machine_start_gcode": { "default_value": "M201 X500.00 Y500.00 Z100.00 E5000.00 ;Setup machine max acceleration\nM203 X500.00 Y500.00 Z10.00 E50.00 ;Setup machine max feedrate\nM204 P500.00 R1000.00 T500.00 ;Setup Print/Retract/Travel acceleration\nM205 X8.00 Y8.00 Z0.40 E5.00 ;Setup Jerk\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\n\nG28 ;Home\n\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\n" }, "machine_width": { "default_value": 280 } } -} +} \ No newline at end of file From e028f044cb63bb1a73538064e67474032a926f78 Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Thu, 12 Jun 2025 13:18:47 +0000 Subject: [PATCH 163/299] Apply printer-linter format --- resources/extruders/toybox_alpha_one_two_extruder_0.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/extruders/toybox_alpha_one_two_extruder_0.def.json b/resources/extruders/toybox_alpha_one_two_extruder_0.def.json index cb39ebf85b..f7f773257c 100644 --- a/resources/extruders/toybox_alpha_one_two_extruder_0.def.json +++ b/resources/extruders/toybox_alpha_one_two_extruder_0.def.json @@ -10,8 +10,8 @@ "overrides": { "extruder_nr": { "default_value": 0 }, + "machine_nozzle_offset_x": { "default_value": -3.0 }, "machine_nozzle_size": { "default_value": 0.4 }, - "material_diameter": { "default_value": 1.75 }, - "machine_nozzle_offset_x": { "default_value": -3.0 } + "material_diameter": { "default_value": 1.75 } } } \ No newline at end of file From ff0e12705e6c9006522e28dca54ec3353a924f1e Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 12 Jun 2025 15:14:45 +0200 Subject: [PATCH 164/299] Update settings version Update variant setting version --- resources/quality/biqu/b2/biqu_b2_0.4_PLA_adaptive.inst.cfg | 2 +- resources/quality/biqu/b2/biqu_b2_0.4_PLA_draft.inst.cfg | 2 +- resources/quality/biqu/b2/biqu_b2_0.4_PLA_low.inst.cfg | 2 +- resources/quality/biqu/b2/biqu_b2_0.4_PLA_standard.inst.cfg | 2 +- resources/quality/biqu/b2/biqu_b2_0.4_PLA_super.inst.cfg | 2 +- resources/quality/biqu/b2/biqu_b2_0.4_PLA_ultra.inst.cfg | 2 +- resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg | 2 +- resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg | 2 +- resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg | 2 +- resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg | 2 +- resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg | 2 +- resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg | 2 +- resources/variants/biqu/biqu_b2_0.2.inst.cfg | 2 +- resources/variants/biqu/biqu_b2_0.3.inst.cfg | 2 +- resources/variants/biqu/biqu_b2_0.4.inst.cfg | 2 +- resources/variants/biqu/biqu_b2_0.5.inst.cfg | 2 +- resources/variants/biqu/biqu_b2_0.6.inst.cfg | 2 +- resources/variants/biqu/biqu_b2_0.8.inst.cfg | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_adaptive.inst.cfg b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_adaptive.inst.cfg index ef478ac259..b9f8323096 100644 --- a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_adaptive.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_adaptive.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] material = generic_pla_175 quality_type = adaptive -setting_version = 24 +setting_version = 25 type = quality variant = 0.4mm Nozzle diff --git a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_draft.inst.cfg b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_draft.inst.cfg index 526aa6bdf2..57b48a55a5 100644 --- a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_draft.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_draft.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] material = generic_pla_175 quality_type = draft -setting_version = 24 +setting_version = 25 type = quality variant = 0.4mm Nozzle diff --git a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_low.inst.cfg b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_low.inst.cfg index 8ee3e16ff4..d11d6658d4 100644 --- a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_low.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_low.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] material = generic_pla_175 quality_type = low -setting_version = 24 +setting_version = 25 type = quality variant = 0.4mm Nozzle diff --git a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_standard.inst.cfg b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_standard.inst.cfg index fd6ea4287d..fa641937bb 100644 --- a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_standard.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_standard.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] material = generic_pla_175 quality_type = standard -setting_version = 24 +setting_version = 25 type = quality variant = 0.4mm Nozzle diff --git a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_super.inst.cfg b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_super.inst.cfg index 4d2899b599..7aadcb580c 100644 --- a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_super.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_super.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] material = generic_pla_175 quality_type = super -setting_version = 24 +setting_version = 25 type = quality variant = 0.4mm Nozzle diff --git a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_ultra.inst.cfg b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_ultra.inst.cfg index 247fdcf1a8..fbd8a08905 100644 --- a/resources/quality/biqu/b2/biqu_b2_0.4_PLA_ultra.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_0.4_PLA_ultra.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] material = generic_pla_175 quality_type = ultra -setting_version = 24 +setting_version = 25 type = quality variant = 0.4mm Nozzle diff --git a/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg index cd755a1cff..7f67567ef3 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] global_quality = True quality_type = adaptive -setting_version = 24 +setting_version = 25 type = quality weight = -2 diff --git a/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg index 92deadd38c..76cc7f73a0 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] global_quality = True quality_type = draft -setting_version = 24 +setting_version = 25 type = quality weight = -5 diff --git a/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg index 0455a6ec20..63a69c570e 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] global_quality = True quality_type = low -setting_version = 24 +setting_version = 25 type = quality weight = -4 diff --git a/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg index a0fb268e52..67b106a1ba 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] global_quality = True quality_type = standard -setting_version = 24 +setting_version = 25 type = quality weight = -3 position = 0 diff --git a/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg index fd54805c04..da7f8a363f 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] global_quality = True quality_type = super -setting_version = 24 +setting_version = 25 type = quality weight = -1 diff --git a/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg index cbc194ceb6..a3fc49ddbf 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] global_quality = True quality_type = ultra -setting_version = 24 +setting_version = 25 type = quality weight = 0 diff --git a/resources/variants/biqu/biqu_b2_0.2.inst.cfg b/resources/variants/biqu/biqu_b2_0.2.inst.cfg index 8f7d063b93..e86b85d50b 100644 --- a/resources/variants/biqu/biqu_b2_0.2.inst.cfg +++ b/resources/variants/biqu/biqu_b2_0.2.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] diff --git a/resources/variants/biqu/biqu_b2_0.3.inst.cfg b/resources/variants/biqu/biqu_b2_0.3.inst.cfg index e6381dfe80..8469c7e211 100644 --- a/resources/variants/biqu/biqu_b2_0.3.inst.cfg +++ b/resources/variants/biqu/biqu_b2_0.3.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] diff --git a/resources/variants/biqu/biqu_b2_0.4.inst.cfg b/resources/variants/biqu/biqu_b2_0.4.inst.cfg index 99958af88d..472e03489b 100644 --- a/resources/variants/biqu/biqu_b2_0.4.inst.cfg +++ b/resources/variants/biqu/biqu_b2_0.4.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] diff --git a/resources/variants/biqu/biqu_b2_0.5.inst.cfg b/resources/variants/biqu/biqu_b2_0.5.inst.cfg index 194e5a79c4..1ab4eb72d4 100644 --- a/resources/variants/biqu/biqu_b2_0.5.inst.cfg +++ b/resources/variants/biqu/biqu_b2_0.5.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] diff --git a/resources/variants/biqu/biqu_b2_0.6.inst.cfg b/resources/variants/biqu/biqu_b2_0.6.inst.cfg index 828843f658..0ac946844a 100644 --- a/resources/variants/biqu/biqu_b2_0.6.inst.cfg +++ b/resources/variants/biqu/biqu_b2_0.6.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] diff --git a/resources/variants/biqu/biqu_b2_0.8.inst.cfg b/resources/variants/biqu/biqu_b2_0.8.inst.cfg index 8bc16cfade..53b6910342 100644 --- a/resources/variants/biqu/biqu_b2_0.8.inst.cfg +++ b/resources/variants/biqu/biqu_b2_0.8.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 24 +setting_version = 25 type = variant [values] From 8188207cd23acb85bb77d1f09c44f380fb36ca24 Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Thu, 12 Jun 2025 14:12:54 +0000 Subject: [PATCH 165/299] Apply printer-linter format --- resources/definitions/biqu_b2.def.json | 13 +++++++------ .../biqu/b2/biqu_b2_global_adaptive.inst.cfg | 9 +++++---- .../quality/biqu/b2/biqu_b2_global_draft.inst.cfg | 9 +++++---- .../quality/biqu/b2/biqu_b2_global_low.inst.cfg | 9 +++++---- .../biqu/b2/biqu_b2_global_standard.inst.cfg | 11 ++++++----- .../quality/biqu/b2/biqu_b2_global_super.inst.cfg | 9 +++++---- .../quality/biqu/b2/biqu_b2_global_ultra.inst.cfg | 9 +++++---- 7 files changed, 38 insertions(+), 31 deletions(-) diff --git a/resources/definitions/biqu_b2.def.json b/resources/definitions/biqu_b2.def.json index a5721d62d4..85139b82c1 100644 --- a/resources/definitions/biqu_b2.def.json +++ b/resources/definitions/biqu_b2.def.json @@ -7,7 +7,8 @@ "visible": true, "author": "Boris Juraga", "has_textured_buildplate": true, - "machine_extruder_trains": { + "machine_extruder_trains": + { "0": "biqu_b2_extruder_0", "1": "biqu_b2_extruder_1" }, @@ -16,7 +17,11 @@ "overrides": { "gantry_height": { "value": 27.5 }, + "machine_end_gcode": { "default_value": ";BEGIN OF CUSTOM END GCODE\nM104 S0\nM140 S0\n;Retract the filament\nG91\nG1 E-30 F300\nG1 Z5\nG90\nG28 X0 Y{machine_depth}\n;END OF CUSTOM END GCODE" }, "machine_extruder_count": { "default_value": 2 }, + "machine_extruders_share_heater": { "default_value": true }, + "machine_extruders_share_nozzle": { "default_value": true }, + "machine_extruders_shared_nozzle_initial_retraction": { "default_value": 30 }, "machine_head_with_fans_polygon": { "default_value": [ @@ -26,13 +31,9 @@ [33, 35] ] }, - "machine_end_gcode": { "default_value": ";BEGIN OF CUSTOM END GCODE\nM104 S0\nM140 S0\n;Retract the filament\nG91\nG1 E-30 F300\nG1 Z5\nG90\nG28 X0 Y{machine_depth}\n;END OF CUSTOM END GCODE" }, "machine_name": { "default_value": "BIQU B2" }, "machine_start_gcode": { "default_value": ";BEGIN OF CUSTOM START GCODE\nG28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nT1\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X6.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X6.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X6.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X6.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X6.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X6.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X7.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X7.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X7.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X7.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nG92 E0 \nT1\nG92 E0\nG1 F1200 E-30\nG92 E0\nT0\nG92 E0\nG1 F1200 E30\nG92 E0\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X9.1 Y20 Z0.3 F5000.0 ; Move to start position\nM117 Purging\nG1 X9.1 Y200.0 Z0.3 F1500.0 E10 ; Draw the first line\nG1 X9.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X9.4 Y20 Z0.3 F1500.0 E20 ; Draw the second line\nG1 X9.7 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X9.7 Y200.0 Z0.3 F1500.0 E30 ; Draw the three line\nG1 X10.0 Y200.0 Z0.3 F5000.0 ; Move to side a little\nG1 X10.0 Y20 Z0.3 F1500.0 E40 ; Draw the four line\nG1 X10.3 Y20 Z0.3 F5000.0 ; Move to side a little\nG1 X10.3 Y200.0 Z0.3 F1500.0 E50 ; Draw the four line\nT0\nG92 E0\nG1 F1200 E-30\nG92 E0\nG92 E0\nT{initial_extruder_nr} ; RESET EXTRUDER TO INITIAL\n; start print\n;END OF CUSTOM START GCODE" }, - "machine_extruders_share_heater": { "default_value": true }, - "machine_extruders_share_nozzle": { "default_value": true }, - "machine_extruders_shared_nozzle_initial_retraction": { "default_value": 30 }, "prime_tower_enable": { "default_value": true }, - "prime_tower_mode": { "default_value": "interleaved" } + "prime_tower_mode": { "default_value": "interleaved" } } } \ No newline at end of file diff --git a/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg index 7f67567ef3..54484e046e 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_adaptive.inst.cfg @@ -14,15 +14,16 @@ weight = -2 adaptive_layer_height_enabled = true layer_height = 0.16 layer_height_0 = 0.20 -support_interface_height = =layer_height*6 -top_bottom_thickness = =layer_height_0+layer_height*4 -wall_thickness = =line_width*3 material_final_print_temperature = 195 material_initial_print_temperature = 195 material_print_temperature = 190 material_standby_temperature = 195 optimize_wall_printing_order = True prime_tower_min_volume = 150 +support_interface_height = =layer_height*6 switch_extruder_prime_speed = 10 switch_extruder_retraction_amount = 40 -switch_extruder_retraction_speeds = 30 \ No newline at end of file +switch_extruder_retraction_speeds = 30 +top_bottom_thickness = =layer_height_0+layer_height*4 +wall_thickness = =line_width*3 + diff --git a/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg index 76cc7f73a0..e5ebe77ad2 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_draft.inst.cfg @@ -13,15 +13,16 @@ weight = -5 [values] layer_height = 0.32 layer_height_0 = 0.32 -support_interface_height = =layer_height*4 -top_bottom_thickness = =layer_height_0+layer_height*3 -wall_thickness = =line_width*2 material_final_print_temperature = 195 material_initial_print_temperature = 195 material_print_temperature = 190 material_standby_temperature = 195 optimize_wall_printing_order = True prime_tower_min_volume = 150 +support_interface_height = =layer_height*4 switch_extruder_prime_speed = 10 switch_extruder_retraction_amount = 40 -switch_extruder_retraction_speeds = 30 \ No newline at end of file +switch_extruder_retraction_speeds = 30 +top_bottom_thickness = =layer_height_0+layer_height*3 +wall_thickness = =line_width*2 + diff --git a/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg index 63a69c570e..2a0f57981f 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_low.inst.cfg @@ -13,15 +13,16 @@ weight = -4 [values] layer_height = 0.28 layer_height_0 = 0.28 -support_interface_height = =layer_height*4 -top_bottom_thickness = =layer_height_0+layer_height*3 -wall_thickness = =line_width*3 material_final_print_temperature = 195 material_initial_print_temperature = 195 material_print_temperature = 190 material_standby_temperature = 195 optimize_wall_printing_order = True prime_tower_min_volume = 150 +support_interface_height = =layer_height*4 switch_extruder_prime_speed = 10 switch_extruder_retraction_amount = 40 -switch_extruder_retraction_speeds = 30 \ No newline at end of file +switch_extruder_retraction_speeds = 30 +top_bottom_thickness = =layer_height_0+layer_height*3 +wall_thickness = =line_width*3 + diff --git a/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg index 67b106a1ba..e2860c23e3 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_standard.inst.cfg @@ -5,24 +5,25 @@ version = 4 [metadata] global_quality = True +position = 0 quality_type = standard setting_version = 25 type = quality weight = -3 -position = 0 [values] layer_height = 0.2 layer_height_0 = 0.2 -support_interface_height = =layer_height*4 -top_bottom_thickness = =layer_height_0+layer_height*3 -wall_thickness = =line_width*3 material_final_print_temperature = 195 material_initial_print_temperature = 195 material_print_temperature = 190 material_standby_temperature = 195 optimize_wall_printing_order = True prime_tower_min_volume = 150 +support_interface_height = =layer_height*4 switch_extruder_prime_speed = 10 switch_extruder_retraction_amount = 40 -switch_extruder_retraction_speeds = 30 \ No newline at end of file +switch_extruder_retraction_speeds = 30 +top_bottom_thickness = =layer_height_0+layer_height*3 +wall_thickness = =line_width*3 + diff --git a/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg index da7f8a363f..9343fe00df 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_super.inst.cfg @@ -13,15 +13,16 @@ weight = -1 [values] layer_height = 0.12 layer_height_0 = 0.12 -support_interface_height = =layer_height*8 -top_bottom_thickness = =layer_height_0+layer_height*6 -wall_thickness = =line_width*3 material_final_print_temperature = 195 material_initial_print_temperature = 195 material_print_temperature = 190 material_standby_temperature = 195 optimize_wall_printing_order = True prime_tower_min_volume = 150 +support_interface_height = =layer_height*8 switch_extruder_prime_speed = 10 switch_extruder_retraction_amount = 40 -switch_extruder_retraction_speeds = 30 \ No newline at end of file +switch_extruder_retraction_speeds = 30 +top_bottom_thickness = =layer_height_0+layer_height*6 +wall_thickness = =line_width*3 + diff --git a/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg b/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg index a3fc49ddbf..4625e672e3 100644 --- a/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg +++ b/resources/quality/biqu/b2/biqu_b2_global_ultra.inst.cfg @@ -13,15 +13,16 @@ weight = 0 [values] layer_height = 0.08 layer_height_0 = 0.12 -support_interface_height = =layer_height*12 -top_bottom_thickness = =layer_height_0+layer_height*10 -wall_thickness = =line_width*4 material_final_print_temperature = 195 material_initial_print_temperature = 195 material_print_temperature = 190 material_standby_temperature = 195 optimize_wall_printing_order = True prime_tower_min_volume = 150 +support_interface_height = =layer_height*12 switch_extruder_prime_speed = 10 switch_extruder_retraction_amount = 40 -switch_extruder_retraction_speeds = 30 \ No newline at end of file +switch_extruder_retraction_speeds = 30 +top_bottom_thickness = =layer_height_0+layer_height*10 +wall_thickness = =line_width*4 + From 53b91a7b4841456f37021ff80c766699206ac234 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 12 Jun 2025 16:40:28 +0200 Subject: [PATCH 166/299] Add setting to keep retracting during travel CURA-11978 --- resources/definitions/fdmprinter.def.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 3ad11933e6..6747bf9ceb 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -9324,6 +9324,16 @@ "settable_per_mesh": false, "settable_per_extruder": true }, + "keep_retracting_during_travel": + { + "label": "Keep Retracting During Travel", + "description": "When retraction during travel is enabled, and there is more than enough time to perform a full retract during a travel move, spread the retraction over the whole travel move with a lower retraction speed, so that we do not travel with a non-retracting nozzle. This can help reducing oozing.", + "type": "bool", + "default_value": false, + "enabled": "retraction_enable and not machine_firmware_retract and machine_gcode_flavor != \"UltiGCode\" and machine_gcode_flavor != \"BFB\" and retraction_during_travel_ratio > 0", + "settable_per_mesh": false, + "settable_per_extruder": true + }, "prime_during_travel_ratio": { "label": "Prime During Travel Move", From 95227a59fdcad88b95785361f5473ec6f99010c9 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Fri, 13 Jun 2025 11:27:36 +0200 Subject: [PATCH 167/299] Add v2 buildplate texture for hidra and hidra plus --- resources/definitions/hellbot_hidra.def.json | 2 +- .../definitions/hellbot_hidra_plus.def.json | 2 +- resources/definitions/hellbot_magna_SE.def.json | 6 +++--- .../definitions/hellbot_magna_SE_Pro.def.json | 4 ++-- .../images/Hellbot_Hidra_and_Hidra_Plus_V2.png | Bin 0 -> 13726 bytes 5 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 resources/images/Hellbot_Hidra_and_Hidra_Plus_V2.png diff --git a/resources/definitions/hellbot_hidra.def.json b/resources/definitions/hellbot_hidra.def.json index fe1d580354..bf8eb16608 100644 --- a/resources/definitions/hellbot_hidra.def.json +++ b/resources/definitions/hellbot_hidra.def.json @@ -21,7 +21,7 @@ 0, 5 ], - "platform_texture": "hellbot_hidra.png" + "platform_texture": "Hellbot_Hidra_and_Hidra_Plus_V2.png" }, "overrides": { diff --git a/resources/definitions/hellbot_hidra_plus.def.json b/resources/definitions/hellbot_hidra_plus.def.json index dc718dc5f2..70938b5b00 100644 --- a/resources/definitions/hellbot_hidra_plus.def.json +++ b/resources/definitions/hellbot_hidra_plus.def.json @@ -21,7 +21,7 @@ 0, 5 ], - "platform_texture": "hellbot_hidra_plus.png" + "platform_texture": "Hellbot_Hidra_and_Hidra_Plus_V2.png" }, "overrides": { diff --git a/resources/definitions/hellbot_magna_SE.def.json b/resources/definitions/hellbot_magna_SE.def.json index a449a60f01..7f36c24525 100644 --- a/resources/definitions/hellbot_magna_SE.def.json +++ b/resources/definitions/hellbot_magna_SE.def.json @@ -8,11 +8,11 @@ "author": "Hellbot Development Team", "manufacturer": "Hellbot", "file_formats": "text/x-gcode", - "platform": "hellbot_magna_SE.obj", + "platform": "Hellbot_Magna_SE.obj", "has_materials": true, "has_textured_buildplate": true, "machine_extruder_trains": { "0": "hellbot_magna_SE_extruder" }, - "platform_texture": "hellbot_magna_SE.png" + "platform_texture": "Hellbot_Magna_SE.png" }, "overrides": { @@ -24,4 +24,4 @@ "machine_name": { "default_value": "Hellbot Magna SE" }, "machine_width": { "default_value": 230 } } -} \ No newline at end of file +} diff --git a/resources/definitions/hellbot_magna_SE_Pro.def.json b/resources/definitions/hellbot_magna_SE_Pro.def.json index aa71aab37b..eb3120b9ed 100644 --- a/resources/definitions/hellbot_magna_SE_Pro.def.json +++ b/resources/definitions/hellbot_magna_SE_Pro.def.json @@ -12,7 +12,7 @@ "has_materials": true, "has_textured_buildplate": true, "machine_extruder_trains": { "0": "hellbot_magna_SE_Pro_extruder" }, - "platform_texture": "Hellbot_magna_SE_Pro.png" + "platform_texture": "Hellbot_Magna_SE_Pro.png" }, "overrides": { @@ -24,4 +24,4 @@ "machine_name": { "default_value": "Hellbot Magna SE Pro" }, "machine_width": { "default_value": 230 } } -} \ No newline at end of file +} diff --git a/resources/images/Hellbot_Hidra_and_Hidra_Plus_V2.png b/resources/images/Hellbot_Hidra_and_Hidra_Plus_V2.png new file mode 100644 index 0000000000000000000000000000000000000000..1cbdea4aae04bfa83f43f67b59ae3091d1d6d5d7 GIT binary patch literal 13726 zcmeHuXH-*Lv~B>gfQYCRL5N3GR7yalHw#5Yz=rgMA|N$F=#T^pO3y*1cR7G`LT@36 zgebj8iJ=Hc?=^(9x8r^HjW_Oi_r2e5jPoM{vUXW}%{|xrzHiQ%@CQcvd_1B&AP|V} z?j4;+AP{F6@M%4K5ExmfaM=QXj=Z>IjsSspPq056{bMLP2y_;7SLfyv|J0Q+{uiS= z$X^UTr|%~o-Z*$6?u_cUvteH@VqS6oWdnXAa_F$qnWGv;2*Y`wT*I}yj?dqBTgy4a zX9G4nw{usl=aL)x$NT6>l9LKt3T+%b$FN^GZr`7J#rNv4%qzRg;mzkBmX#rAk}wt8 z^)k}t(km_$X&m&L1i8GDMxJQzx13-wn-%>5-*5ak+aPa2Kp9`OVR4;Ri6%?ho4O4GC4Oi_)Q!GizT|7o;0KF>OWU}L z_w)_|XBh%#NwEr%JYY^x^XQL+ju~ID*7b4I@A{_Lkgj)2R4U9+u*^+#H4Pk^zY$B}2{THYW(=c;%o@heT*v_u=Krw}Bj>%s1&? zkohapHd_c-@eU8@#)X}a2+Nt6=6IiJ;CgNcLt|NGn=T|bD6_vnv}`3^4g|VVq=v8& z6HSR~;siYqoT;3Rs(#N63L#zme;D}xX!U;w|BD;`Ymk2p@_!Fh|9Z&39`dh;{C6<^ z@9y|_cl^6M{(s#an?g!T5VKM2KRM&w`jq@N_u|)IL7&BVH3UI*qlW?^&tdr0_SM|n zP~P1YF%jH!w;_Y}4tl0=CO`ZI&TZvqNsd8-1^*cpdDNV><$lI!Ls07gcc&jbh_N%A z=gk8UUb~j8Y zW!xEVkDIH+VDP@rhNm(7loBfv)Yy~n0XIxN_<69+6=i9gmjU@IC;XO26!w~T*ZA~` z+VIHWuf%xWA8q(Cyw6f|^*afXqTPUq%SRKewzIlT3ZMGu6=_vb@?+JNCP-)-?`Im! zm57d#`2rs+t|ze}+=<_25}UvV(_IUG&8BsC3U1C zfl_H*1=ypuG%IToYnY-;NvJQiASgD=94`YAaz(=la!};mxg6IaZwJWagx6Bd{ypwB z?^a#=VJjaWKcRn8)_(T0=1bna!}vU|I6Vxi&}rs;mMaz>I(32WTH2JWo_nS>#V?pO z`K4hE7i3cpnG~KFA1a;@|CTHN5urX9~k=7dhD#qL`DJ2M@@|<4uB| zd8rKu6fnxs7p6or-vVRWUAv>b`Bul3$ih%VzY@re=p$w}sQj5hYN&zN49{#uTLy1J zQ}Rl}ZeIOQ&KqgR%bMvAjF+;7;1Ru}!Sq)aa4mUKU`+*521Gn-^RliKT7zbc8Kb;( z&pf8%pz*a=VwPw%TJkn1nFmh5e15u7);JW>PhUUCpmik8&wT;ywYC~-q4i5-q0y0H zGUghq5Q=f&Sj488kB?a7y@-d<{XcZrH54K!z zfz0&z^uTZ?(cOUe2L}glr#La9)grvF(_q-DU(l2WcD;Tr?%}irQBl4WSfIxxsS{2e z_h&y0Ej5k>M!MQSPn6yGxw!EuJ3PMQ3MGd!6?bycVXkPZ3%vMO$;$xUW=`iT<3c|5 zv1ZPLW{<1lU5AbSfliAi3LlX9J3Y|KAFbqDmAo?cHTRPQFuDbd#srS;dwUY!$Geu) z*Q@i^b^%K*-97cTB?ObO4zJs>L{=T!3ygBL=?11|NXO_vvJ%p7J>-|>Iz`-J?a^3u z#7fT0mfSOCyr}`1Pnj4&ryAYHp#hDK3u$Z4;r_*gho7guhI=&Tz{$7yk1=;yb++a* z;!pWG#E8ccv8*%w9}F{h@lx62n}M5(U!V62AZ9s1Q3 z)y(;u@Oj~~rc-6lcCZY7etR`+cyFtmH{pKJsa;}^rgC5p!;imJfq)H22cd2Qr^_PI zuEXyIrTn^o2g_(7oGrVh`5dzjdC!67kw?Kb)%oxr4 zn;OW0Q#a;d#~AcPVJ}4)tJ+_!gf%zS$+WfS&RVv%1D|$hhxYcSD3L%My9{{R=dk#t!ayO8A83#yj*nO*0gOWL0E;4Mk%@+_V`hD-{6(CZndK zPPUD2VU6n@%65t^w716e?g(S_;x)}k_4vk_PYNM*M!+++wY1H0C%^)AhZCCCL$`V? zP*2Iz7}kru)u1($eRha2YlAxZ^&M1uwjER<8{^CxfHVq}L5?w>xe+N~39I_b!X1S2 z_z10Z2u2pibU9s>hwZ&O)X58;$7LcJ_0kO~$wG1?HE^5laoVcbw;}Vc*7B#NN24)9 zCDRuCZ)wE0ya}U$E4^PN6;>wuz#2-yT_&b}rSkiC3LLr z2$xbq2AI|rU9+uO?K-^f;5zJE48TElcKHXxG|-*s5bpQF26qXB`<^Duy**cbrE%XN zSRFRLm}Sw^o|GXr$&5=$C#C5E1jD+)ZKr@&y(2s@B=CaG%Vz}dm&-Go{ztKuPh=t$ z(-Jx|Q0q>}u{nHUgFj<1P{6=h6UWFy&PW)&p|47zuD>@d45MNnr#se8{zXF7^VhF= z>4BK-!}Juq=T^F#Gd2+{mOV^?BW;?2+gt!{b4w<2XM+!H8Q+D#xpw&NOV>R|liz<> zQi5KC!?t5`lMc9De8qw=7km61Qq)`NBZwf=>Iu)eT&9_2^?Tyc2Yj4DpIsGtcGx5* zf_r~j#hx}yRvznvEhON?gya(aVEh$SEQuQJ?p)}D;<$3RnbT)!YB0eYTJLCRs?<}J zEcpg6dRnYwW-;jaZtq@JguX+y>`L{a8veG!e)lh%H3bJ)c4DFfD&m^7L+%|fyD@fo zoVha;Ek?7;%Xg7*vO4Rt*uIMmv^H9bo4lQkKeHb&2pz{zu~=DmC8A0SIEYOc3z4fF z?ZB(62i&Kk@V9;XlH1z3K?*~d7Bnool27aj8>8&R;ob~+18an^NC|$9*%QjaQ+`jE z$u&Q#D{oi}l-=lZAmiIU!{oGkcGz^nruwz>vx#5x-*{IfXWT^O#onUnOOyAk8ckwq zZ>+}ZgHOwi#w!hxR?w@eDQ7{7QZ_G>X#)`EcPdF^IB2Z_o*A#M%cr5BG2+|aU(Yk* zBoR<@5%I9X-ML0{` zNyR!r)|?w$#^T1X2jQ}qL%(VR&<8`3)&188B_TNaqp{9X4f)_Q59md7!2DpnYW(X% z{1T^&J@0e<29R+lvyQsQy;G)-UT)iAb{NC@M!l@YqU7b+2zXZ<{Cteo+r)G!xh0=e zTf4eh1y-%Ua#MB{oS7(KmO0Cu!qexhJtvh@3IXqeBGz+LLpXz#-LtFL*v2oSFleuY;mABC3D}kp=4vIgJyK%*HKEv= zELbQ|WKmUsU`H?~SLkwh1ul`sivUw@ys)?$0vM9JJL27&1IOtr}is!;jy! z7*z5OTi_%mmu^tZwsrtmkVq^xJP&IB3wVT6lc$0<*63gCzhc!*CnXqzKhvar8|rPo zl5jgpalh8HhB3=X8#ubkLwmNa?PIi?EVRLcV+Q~pAK6=rv+&VIsaYtLO>?XDSqw|C z$mebPh)5{oOIpt=YT})-?2Ty z_qTQXr(f)JYq=SCVjb%MIBc;cUj2CXSX?82hzr0rAC*(FrdGbXrf#nLbz<=4Xezb_ zUZ0JBG{7_N+22whHrzYf{{ZWNvrBjN9iLi@(}II401Es){MY{OESXlLS&Nj{JHb0g zd}?=oqctYCzV7eBncwZL-b!9+U5MiCZ;H)sz&z!4D7WRljINo^S>ky8Ms-tC=S)#v zWUZr`uyTs}XkXv>i7hMmSS@z#JFY?hir*Vhg)uNoq#0u~0~s(!D1G0e?Ym^V0J9uI`_vYJFaaf`{kl3ja8*eL?*m>ow4HlmZ~4=mUsFXy{T_ka04EJZ zNwz?I;`cEyV178;J@0zW;MV|E`RhtE0wZpRD$InW^)lCRYfT&-b{q&m8P5Jwd*kvf z(J^Shv|%%QOrZQRDc*OU#E^7Kofxv_pK}1{#Ti7C3xLXOISk-Obj{ef>4Ksc$6`2e zd1bB50tu{rO%zf{^mweGy_=6SjvmEQyP4t8rx+j8j4{=I*ismB|4YV>VfD+K{}bKI zS72QT?pa=dJ_Ll4`yIas3o9F*3g+V#mNN_1a}6r)>0l$OJ8OVf|DLYf|w2Jga6ZM3d(@^)I1sw<^3Mt9>cR8+GV6u-8$u3{-A>+Nt#*J8wh zAn*uTyKi(@M3*^*rt_;iZux^2qXo=tppn$l5AOM*!rq2{*Iq7!(UO;2WI+dHK%j7i zP>{_D?71)a=NcaEFll~pAmdvh1dJL8TiuXSth|1`$^Bl907a1Ed`ig1j#J2nQ_8!s zaAvfydp^k}_^s*NHhsUbI#=UKvX(#NP@s_;+%2u0NL)N59Nbt#(WlV;dm!&nT9ZEx zhEO|CafTfEC{}9As(|1e4iyQf)2Sb;%et=DoEbhvSqb2{)OA><`2fHHW7_6>(#1|M zSl4*BWJX=6L9yMD%lIgN%(7T;2RDqCF|O?OoW8zVLaFj=V*C!375IE|Z0IC~f7N_@ z^<>_43togtk>8nySwZbaB<)~~+)GpX?jN>`jq}4&^dIfh}Y1Xac-$_Zn*kE*ptPFUM#$*jK&!-fbUzpYCG$lax$&(dyFb zK03sfS&0B+?^GH1!s*q3Z;YrplX zhfX%8czahGJAaM$@(8LvY!+f4rh#A8VPT(AX>|D@PZ!vrQrToLr#Th z(ep@w;jp18OFSE4XWrUOx@QcN$xXr3&FV)rI20Rp?-~>#tm$y!(x!h9pZvu|MJ0ls z6Dfy;A*;{xe|ws~4&lCZ98x^9DRxE$a-)uCZnQ1Kes%tjs)&R;_I=VdR2Z&FUCE4u z2eH+D&zQeGe1oRzpYFLIWN8rU_{KS(jG}LVkD(FMvPjZ|binAKjUZ~?XFftAe$RgASKJCPdV-5P3ayn-zF9X7L&m!_1>t7I?yrM9g22i`{xYPIP) zqLW>US^2q>d->3y#wtLpK)QC@Q+u=DOWV`oS?r?0T#RQ2-rn8J^^we@3*cwt9I_YDlWYeNC({M zWy>@>laMJ%3~$2}XK5Wh)k2RKbmx}qQn(?O;ktosBhP)kCemR_Sd+@|_8O?eNs|p$ zMijM}KVvOD7*Ao}#S(S$w*oE1ib#vLtGrZKdd@&^?)`xw78H| z`y9|Z!iUgTpBBnG2v=1r4wC5=BaX_uzNN2k+onhOGujQ&xQ4wx^#0?Fg``XKv+rAo z5-`aUbF>M?yrUEi2Y=@x*fE!-Yr6qUzMHnF03$LVu>|K=00^v7L9TU(vPR zW3P3s2vDUv&#i8%r$rvW@|T_!oY~eDH03h!hhR*p&Bl!d0HI!rvRblOA0ZH)P*V4g zG_+g{aC~xQ00Lb+hm~D5>-S>IRsH)!<@P^N)&2R{1I>+{D{`aB&t*sI?l*HP)~sY5 zItUKfj-8a2YxpFsx7V~C3Q5IJ)A;$vk!xdIRe?veTRf|$>Lnx<^j?+X_LEna#irSL zN`D&~<)G_MFerymXtuTS!|D=r`X!z^X>akg^drWWxK7<7|!@C$=Bx9wXxcpjKrsKb@eu}Csl!K&RT zhPh-ISqLM$7qT|X(hWH7L%D!B##RfN1+Oc8@Gkav4u zzxKpFE;@RAvX)vR%cyD`alYbdT^gHcohme8W^Z0(Q9=hHzQdS#_(uOL{8CLqd$ykY zfEbN3^Oc6S^u(vsGwWRw(#Q?vxOnnKM^6TuiYxR#5*hC5GUQ#9Jy9|9rTp^I8jsNt z)0LSonUCz8K0k83MkE`I5dv_yl|19}zrN|Dgtn3)Jtls9^Bb=ZVLmo=d*@S1f7oA| zt6us-hN2lem&NsfMj4GVz;G`?TLw{XP_MpsY8AX$c3)UQtF(77Ee_eW?(F-R`Z_^Q zw|Tz|3~Oz%4w_2z1(NV)@P>?=7g4p`B#P;lQ z)^8oc@aZQK4E8*;bl#X3&l2^{m#8dtR)-C{`K9h{kvbA;_?X@=iiAAVLQ&P?&)zUs zQdZ|F{TKee%E5bH_LDqWb!l;Dslf>`SJbH!>rdZ+!ya_h%AMhh0bb*1UA}g%ZD$*j z>&b`92bxo_lKY+pqjP4b9X-eXkWr&T@nKS24|eM2=meX#mocOpP3WxXx@`jMxUd=F zXHS)i!%6YSiH9szjRSaI0@N*)A2B@i)%knOHE2!|49fJFRk@NhO6emTaBmhzQ2gPe(G*>8M(X4|M#lRn}-N$g&=?p?1o zx5O??lG8~$9a$N81&9{eD)YtSfLm&cJ&BUt_p)WAUQbD5S&7p zyAgSZG${0~Y_AHEY;H1))9K$|Oj?bQ8rSkA9?NN83HF-%G!(AwvfFswAE;hU*eIf!l|w;5 zSKWP88_X8ap7!^N|HOLG-OExoE9;z~8(oH~HbAo*rf^awkq>mkFit%*Q#5i2=%D*} z=pHw~trh+DdiOr&6~>E|A=9DkPP3wDfp(seukYIQb%Eo8PlpQW1Lk_Jc}_<`Av{-H zLn@a;y5JiQa=^hjdDLF7zYmwv8q`=AIQPMBA#H$Xgl=L-*02YGI-B>3xZPHj1sb}z zt=V65>5k?ONxsdq?&SpF@`193(Yn&4KV5^@)F%I<$8YtmmE7=Z((5Fe=~C$miZVrz z{V>*x07?P-({t%!D?lMGdui5i$KIFu3p)v9G2#1n{T{kn4p8UPhfzO)WSmeFV_$Qf5IU#16_}1jW8Lv z?McKquk}Gw3_!6&rG0{PPDv1-jImQ|jN6bHSvNOm?^Y9~Ce3%Tf9QjeT7LfC8OC(F zl>QVW#-}0_<9U@7(AhosB)#yyZ|7rV)L33q%}#lhYePAnh-C9b2PEQ>Rt*^(_Uj3c_K z#rYad`N3L_Yn0#Vnvx`zLgv&tsInnNPx$^M@?so#7nh%fU04K6IZX{s3WxtXE4b=c^S!zu`ifPJcnYI8Z&H-9}l#= zhtbLrm2A3zVk7^DG4Bog)H}WsY~~$KPHjh+_=9IO+QNog$T2h&TdI1UE7}{au1+7h z{;;`?8nxw9WZwj2xpTd(Lg#XStms&k!u%ZkcInYTS$G?<_3M-tp2u)zOM$7$gljPO z_}_If{sO7wo+h}KoZv_a=W+%*J6XR4$_*dWF4+xm_^YhQYH!bLcT0bwcQ{ffzPC4@GBe=3HB_NnIyB_{Z{)=&E z9RttCw<`Psspgf&igdd->Zlu+P(e|@9p>tO9Co+86L)n`^-E}WsX)8=DJXiZN`EfR z$nTVro@xa+@Q?E7ny3vhmScT2jQTB%pLj+Tgiy507(uTU0@KA!b#|X|Sc=4w>>GTh z-H{(Or4+!F&C%95#Z~kb46^L`KSGJs{yr!tw(au$n;kd*5)){s$iiN33Lyx8T=wgq zq!wgt1qP9gA@#La62Jl-%rg_uc_E)J3+iq>@_l2Tum6a?>73;ycedb7R#q0)Yp&Xe z_>7|x&0=D`xYRh;%!uMWeJv|p@cm><4RocM)o10n5ZN;`jp!vVef(V=5uunCBZtZg zGppt}!{RV-VtFQhs$9CB=c`7G*QW(uQU<$WLqz-fDG5`0@_ellyUC*E;jop~E7%$O z_kS`zc%J#7DJ(z^)ebYnHy=_bJnEhOluDIf zZSETSZ4-kR?Zr*$$4$CD1yLvhH5yOk7een7v{hO7v2EoBsX%6X8dp#ez>h=#!6hJ| zsJ_36e=EIn^%`Qh=zz>Z2S0=VRMcmf+hF+52%8B1OLJ$-G2yXgdu^#WEA75ZW{qyC z4AooPKt3)|@~GXLf+vUDIyw~IDbj-O`#n!T|NffiQS-`=$q=>2p^q=woz7jJS--`u zOh`wS zK0P{^*a(rXwPo|FShd-U90sIK$wlm9Yc;*#WbWxF-zVrR6Dx9*sn{MyLl16Yv3q%{ z*b3#XKyz$d+91BG_#CDhUTA7PQs=ieo-J%77<0z4=A@~ezWk}~$S5inNT;}*Kc`5m zJxp$Kh+%Ggm(t^bT#pneol4oKeYb z@t0Nnq!ufpntmxl$j`fRqZTS5E{>*b5b+z7r0$opjeon8Km6tP(NitEY%<;wKPWsY z+Ove6HJZEEiHu(0nvpP_^G7{w6ESI^jVqUe#cbvK zMtf=tG-(&Xyq&^OK?w!3#aHEr6WHx0=#I7{)H=+`wEV*f;VsWEPN__JJ`+C9xR@yv z7fe+-hfD2SsV%lQ96OAaM@Af&o?e3y$eKD7%Cl__) zcJXp^0e;|m`N2K*EO}B;FSv8x~x(+>?(u&zhyowzd*%enm zIE`g^vm!3TM3hNe;OtZdpTAIq6=UB{1&m^fl(_oehPzEC(};%~L=0oZ%hIJsxJ&lz zjZ`Mzv{`ALny$SVq>5j!okA>_Wzfu9+jO6i_&KrJLtoYXRx=h60u;}po;b6Gvytom zgXd;n8PC|M)ZAN<-x7>wY)Z~V%@~TII+*7934evw>X*`&q9*~IpfVg;A@u- zN}mFC-fh?tb_+KxFlxS9xG5kua3o%J3xs&f$CGHn8K2C)B-Qpcr(;@3j$_dS(BB$j zryiUH4!AsbTWp61{+f~tsSGo9(QAH$pbGMwv$NC`1Nrobmi_=%C1;ieI(uX)t{!+s zF=`mD6IhGSVE)O1Sp9B literal 0 HcmV?d00001 From 0d06822e1b9aaefe2d42f3e3f531eadb927a0b2c Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Fri, 13 Jun 2025 09:29:06 +0000 Subject: [PATCH 168/299] Apply printer-linter format --- resources/definitions/hellbot_magna_SE.def.json | 2 +- resources/definitions/hellbot_magna_SE_Pro.def.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/hellbot_magna_SE.def.json b/resources/definitions/hellbot_magna_SE.def.json index 7f36c24525..0248b0caf2 100644 --- a/resources/definitions/hellbot_magna_SE.def.json +++ b/resources/definitions/hellbot_magna_SE.def.json @@ -24,4 +24,4 @@ "machine_name": { "default_value": "Hellbot Magna SE" }, "machine_width": { "default_value": 230 } } -} +} \ No newline at end of file diff --git a/resources/definitions/hellbot_magna_SE_Pro.def.json b/resources/definitions/hellbot_magna_SE_Pro.def.json index eb3120b9ed..cb13626121 100644 --- a/resources/definitions/hellbot_magna_SE_Pro.def.json +++ b/resources/definitions/hellbot_magna_SE_Pro.def.json @@ -24,4 +24,4 @@ "machine_name": { "default_value": "Hellbot Magna SE Pro" }, "machine_width": { "default_value": 230 } } -} +} \ No newline at end of file From 890db9da6efefa51f93a82eaa292b56ae4053b7a Mon Sep 17 00:00:00 2001 From: HellAholic Date: Fri, 13 Jun 2025 12:38:02 +0200 Subject: [PATCH 169/299] Update PurgeLinesAndUnload.py --- plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py b/plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py index 922aad902f..44c2b50f9e 100644 --- a/plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py +++ b/plugins/PostProcessingPlugin/scripts/PurgeLinesAndUnload.py @@ -35,9 +35,6 @@ class Position(tuple, Enum): class PurgeLinesAndUnload(Script): - def __init__(self): - super().__init__() - def initialize(self) -> None: super().initialize() # Get required values from the global stack and set default values for the script From d0947c5fb2634e9b7a046dfd18050bbaadfdacff Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 13 Jun 2025 16:17:58 +0200 Subject: [PATCH 170/299] Include new print feature type CURA-11978 --- cura/LayerPolygon.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index c4d57c07a0..cd4642d719 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -25,7 +25,8 @@ class LayerPolygon: PrimeTowerType = 11 MoveWhileRetractingType = 12 MoveWhileUnretractingType = 13 - __number_of_types = 14 + StationaryRetractUnretract = 14 + __number_of_types = 15 __jump_map = numpy.logical_or(numpy.logical_or(numpy.logical_or( numpy.arange(__number_of_types) == NoneType, @@ -281,6 +282,7 @@ class LayerPolygon: theme.getColor("layerview_prime_tower").getRgbF(), # PrimeTowerType theme.getColor("layerview_move_while_retracting").getRgbF(), # MoveWhileRetracting theme.getColor("layerview_move_while_unretracting").getRgbF(), # MoveWhileUnretracting + theme.getColor("layerview_move_retraction").getRgbF(), # StationaryRetractUnretract ]) return cls.__color_map From 2663d8eaceb1ac79a229da230c5857e4bee7c787 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Fri, 13 Jun 2025 16:32:40 +0200 Subject: [PATCH 171/299] capitalization .git ignores the capitalization on the repository so the assets rename did not update their capitalization. This fixes the unit tests --- resources/definitions/hellbot_magna_SE.def.json | 4 ++-- resources/definitions/hellbot_magna_SE_Pro.def.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/definitions/hellbot_magna_SE.def.json b/resources/definitions/hellbot_magna_SE.def.json index 0248b0caf2..a449a60f01 100644 --- a/resources/definitions/hellbot_magna_SE.def.json +++ b/resources/definitions/hellbot_magna_SE.def.json @@ -8,11 +8,11 @@ "author": "Hellbot Development Team", "manufacturer": "Hellbot", "file_formats": "text/x-gcode", - "platform": "Hellbot_Magna_SE.obj", + "platform": "hellbot_magna_SE.obj", "has_materials": true, "has_textured_buildplate": true, "machine_extruder_trains": { "0": "hellbot_magna_SE_extruder" }, - "platform_texture": "Hellbot_Magna_SE.png" + "platform_texture": "hellbot_magna_SE.png" }, "overrides": { diff --git a/resources/definitions/hellbot_magna_SE_Pro.def.json b/resources/definitions/hellbot_magna_SE_Pro.def.json index cb13626121..aa71aab37b 100644 --- a/resources/definitions/hellbot_magna_SE_Pro.def.json +++ b/resources/definitions/hellbot_magna_SE_Pro.def.json @@ -12,7 +12,7 @@ "has_materials": true, "has_textured_buildplate": true, "machine_extruder_trains": { "0": "hellbot_magna_SE_Pro_extruder" }, - "platform_texture": "Hellbot_Magna_SE_Pro.png" + "platform_texture": "Hellbot_magna_SE_Pro.png" }, "overrides": { From 9feb73dcf5e8da27c84ace46892b5e0b7045f402 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Sun, 15 Jun 2025 15:58:02 +0200 Subject: [PATCH 172/299] path->paths The correct keyword for filtering pull request triggers by file paths is paths (plural), not path (singular). --- .github/workflows/printer-linter-pr-diagnose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/printer-linter-pr-diagnose.yml b/.github/workflows/printer-linter-pr-diagnose.yml index 8feecdb3ee..64892e0db1 100644 --- a/.github/workflows/printer-linter-pr-diagnose.yml +++ b/.github/workflows/printer-linter-pr-diagnose.yml @@ -2,7 +2,7 @@ name: printer-linter-pr-diagnose on: pull_request: - path: + paths: - "resources/**" permissions: From 70476db7f2b2ac1725bd74b956a3414324af8b7a Mon Sep 17 00:00:00 2001 From: HellAholic Date: Sun, 15 Jun 2025 15:58:20 +0200 Subject: [PATCH 173/299] Indentation fix --- .github/workflows/update-translation.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/update-translation.yml b/.github/workflows/update-translation.yml index 189390410b..2134467ec9 100644 --- a/.github/workflows/update-translation.yml +++ b/.github/workflows/update-translation.yml @@ -11,5 +11,5 @@ on: jobs: update-translations: uses: ultimaker/cura-workflows/.github/workflows/update-translations.yml@main - with: - branch: ${{ inputs.branch }} + with: + branch: ${{ inputs.branch }} From c5bd7009615dcda52a24656df15874b651659974 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Sun, 15 Jun 2025 16:28:29 +0200 Subject: [PATCH 174/299] Create slicing-error-check.yml --- .github/workflows/slicing-error-check.yml | 67 +++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 .github/workflows/slicing-error-check.yml diff --git a/.github/workflows/slicing-error-check.yml b/.github/workflows/slicing-error-check.yml new file mode 100644 index 0000000000..7adf1a34f0 --- /dev/null +++ b/.github/workflows/slicing-error-check.yml @@ -0,0 +1,67 @@ +name: Slicing Error Check + +on: + issues: + types: [opened, edited] + +permissions: + issues: write + +jobs: + processSlicingError: + runs-on: ubuntu-latest + steps: + - name: Check for project file and set output + id: check_issue_details + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const issue = context.payload.issue; + const issueNumber = issue.number; + + console.log(`Processing issue #${issueNumber}: "${issue.title}"`); + + const hasSlicingErrorLabel = issue.labels.some(label => label.name === 'Slicing Error :collision:'); + const titleContainsSliceFailed = issue.title.toLowerCase().includes('slice failed'); + const bodyText = issue.body || ""; + const bodyContainsSliceFailed = bodyText.toLowerCase().includes('slice failed'); + let setNeedsInfoOutput = false; + + if (hasSlicingErrorLabel || titleContainsSliceFailed || bodyContainsSliceFailed) { + console.log(`Issue #${issueNumber} matches slicing error criteria.`); + + const zipRegex = /(\[[^\]]*?\]\(.*?\.zip\)|https?:\/\/[^\s]*?\.zip)/i; + let hasZipAttachment = zipRegex.test(bodyText); + + if (hasZipAttachment) { + console.log(`Issue #${issueNumber} appears to have a .zip file linked in the body.`); + } else { + console.log(`Issue #${issueNumber} does not appear to have a .zip file linked in the body. Flagging for further action.`); + setNeedsInfoOutput = true; + } + } else { + console.log(`Issue #${issueNumber} does not match slicing error criteria. No action needed.`); + } + core.setOutput('needs_info', setNeedsInfoOutput.toString()); + + - name: Add comment if project file is missing + if: steps.check_issue_details.outputs.needs_info == 'true' + uses: peter-evans/create-or-update-comment@v4 + with: + issue-number: ${{ github.event.issue.number }} + body: | + This issue is related to a slicing error, but it seems a project file (`.zip`) is missing. + Please attach a `.zip` file containing your project (including models and profiles) so we can reproduce the issue. + This will help us investigate and resolve the problem more effectively. + Have Cura open with your project that fails to slice, go to `Help` > `Export Package For Technical Support`, and save the package. + Then create a .zip file with the package, attach the `.zip` file to this issue. + If you have already attached a `.zip` file, please ensure it is correctly linked in the issue body. + + - name: Add Status Needs Info Label + if: steps.check_issue_details.outputs.needs_info == 'true' + uses: actions-ecosystem/action-add-labels@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + labels: | + Status: Needs Info From 18be62482e025d6dc04aa1cf5213824aaba67892 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Sun, 15 Jun 2025 19:25:09 +0200 Subject: [PATCH 175/299] Update slicing-error-check.yml --- .github/workflows/slicing-error-check.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/slicing-error-check.yml b/.github/workflows/slicing-error-check.yml index 7adf1a34f0..3e8faaeb7f 100644 --- a/.github/workflows/slicing-error-check.yml +++ b/.github/workflows/slicing-error-check.yml @@ -10,6 +10,8 @@ permissions: jobs: processSlicingError: runs-on: ubuntu-latest + outputs: + needs_info: ${{ steps.check_issue_details.outputs.needs_info }} steps: - name: Check for project file and set output id: check_issue_details @@ -22,7 +24,7 @@ jobs: console.log(`Processing issue #${issueNumber}: "${issue.title}"`); - const hasSlicingErrorLabel = issue.labels.some(label => label.name === 'Slicing Error :collision:'); + const hasSlicingErrorLabel = issue.labels.some(label => label.name.toLowerCase().includes('slicing error')); const titleContainsSliceFailed = issue.title.toLowerCase().includes('slice failed'); const bodyText = issue.body || ""; const bodyContainsSliceFailed = bodyText.toLowerCase().includes('slice failed'); @@ -43,10 +45,10 @@ jobs: } else { console.log(`Issue #${issueNumber} does not match slicing error criteria. No action needed.`); } - core.setOutput('needs_info', setNeedsInfoOutput.toString()); + console.log(`echo "needs_info=${setNeedsInfoOutput.toString()}" >> $GITHUB_OUTPUT`); - name: Add comment if project file is missing - if: steps.check_issue_details.outputs.needs_info == 'true' + if: ${{ steps.check_issue_details.outputs.needs_info == 'true' }} uses: peter-evans/create-or-update-comment@v4 with: issue-number: ${{ github.event.issue.number }} @@ -59,7 +61,7 @@ jobs: If you have already attached a `.zip` file, please ensure it is correctly linked in the issue body. - name: Add Status Needs Info Label - if: steps.check_issue_details.outputs.needs_info == 'true' + if: ${{ steps.check_issue_details.outputs.needs_info == 'true' }} uses: actions-ecosystem/action-add-labels@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} From 5849fd9c990f30a90e487af9df4bd13489048508 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Mon, 16 Jun 2025 10:22:40 +0200 Subject: [PATCH 176/299] Update CreateThumbnail.py --- plugins/PostProcessingPlugin/scripts/CreateThumbnail.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/CreateThumbnail.py b/plugins/PostProcessingPlugin/scripts/CreateThumbnail.py index 8f0c74ceee..1ee85bdc0b 100644 --- a/plugins/PostProcessingPlugin/scripts/CreateThumbnail.py +++ b/plugins/PostProcessingPlugin/scripts/CreateThumbnail.py @@ -94,8 +94,8 @@ class CreateThumbnail(Script): }, "use_star": { - "label": "xxx*yyy", - "description": "Use '*' instead of 'x' for size of image", + "label": "Use '*' for size of image", + "description": "Use '*' instead of 'x' for size of image as Width '*' Height", "type": "bool", "default_value": false } From 5db75acffbdc593bbb15efe0f1eca2b502631fce Mon Sep 17 00:00:00 2001 From: HellAholic Date: Mon, 16 Jun 2025 10:44:36 +0200 Subject: [PATCH 177/299] No need for type cast -> it returns a bool --- plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py b/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py index cec857a8af..d2a51a28fa 100644 --- a/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py +++ b/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py @@ -100,7 +100,7 @@ class InsertAtLayerChange(Script): if not bool(self.getSettingValueByKey("enabled")): return data #Initialize variables - mycode = self.getSettingValueByKey("gcode_to_add").upper() if bool(self.getSettingValueByKey("convert_to_upper")) else self.getSettingValueByKey("gcode_to_add") + mycode = self.getSettingValueByKey("gcode_to_add").upper() if self.getSettingValueByKey("convert_to_upper") else self.getSettingValueByKey("gcode_to_add") start_layer = int(self.getSettingValueByKey("start_layer")) end_layer = int(self.getSettingValueByKey("end_layer")) when_to_insert = self.getSettingValueByKey("insert_frequency") From 200119fe6a439c933853d10a9617c5610639a4b1 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Mon, 16 Jun 2025 11:00:11 +0200 Subject: [PATCH 178/299] use core instead of echo to set output --- .github/workflows/slicing-error-check.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/slicing-error-check.yml b/.github/workflows/slicing-error-check.yml index 3e8faaeb7f..6a3bb6d4c3 100644 --- a/.github/workflows/slicing-error-check.yml +++ b/.github/workflows/slicing-error-check.yml @@ -19,6 +19,7 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | + const core = require('@actions/core'); const issue = context.payload.issue; const issueNumber = issue.number; @@ -45,7 +46,7 @@ jobs: } else { console.log(`Issue #${issueNumber} does not match slicing error criteria. No action needed.`); } - console.log(`echo "needs_info=${setNeedsInfoOutput.toString()}" >> $GITHUB_OUTPUT`); + core.setOutput('needs_info', setNeedsInfoOutput.toString()); - name: Add comment if project file is missing if: ${{ steps.check_issue_details.outputs.needs_info == 'true' }} From 1803cb02a4998784bed4d70ce5498130591fd68c Mon Sep 17 00:00:00 2001 From: HellAholic Date: Mon, 16 Jun 2025 11:03:09 +0200 Subject: [PATCH 179/299] Apply review comments --- .github/workflows/slicing-error-check.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/slicing-error-check.yml b/.github/workflows/slicing-error-check.yml index 6a3bb6d4c3..4d1c215d3e 100644 --- a/.github/workflows/slicing-error-check.yml +++ b/.github/workflows/slicing-error-check.yml @@ -10,14 +10,11 @@ permissions: jobs: processSlicingError: runs-on: ubuntu-latest - outputs: - needs_info: ${{ steps.check_issue_details.outputs.needs_info }} steps: - name: Check for project file and set output id: check_issue_details uses: actions/github-script@v7 with: - github-token: ${{ secrets.GITHUB_TOKEN }} script: | const core = require('@actions/core'); const issue = context.payload.issue; From baf5b450e5a3e4a1c409944157102d9f1c8c6d0c Mon Sep 17 00:00:00 2001 From: HellAholic Date: Mon, 16 Jun 2025 11:14:09 +0200 Subject: [PATCH 180/299] go away token --- .github/workflows/slicing-error-check.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/slicing-error-check.yml b/.github/workflows/slicing-error-check.yml index 4d1c215d3e..ce22b6b81a 100644 --- a/.github/workflows/slicing-error-check.yml +++ b/.github/workflows/slicing-error-check.yml @@ -62,6 +62,5 @@ jobs: if: ${{ steps.check_issue_details.outputs.needs_info == 'true' }} uses: actions-ecosystem/action-add-labels@v1 with: - github_token: ${{ secrets.GITHUB_TOKEN }} labels: | Status: Needs Info From 43ee8fd92818b916b0c86a06161c51418c004532 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Mon, 16 Jun 2025 11:20:23 +0200 Subject: [PATCH 181/299] workflow update slicing error check core is already declared in actions/github-script@v7 so it's redundant --- .github/workflows/slicing-error-check.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/slicing-error-check.yml b/.github/workflows/slicing-error-check.yml index ce22b6b81a..9869ef9721 100644 --- a/.github/workflows/slicing-error-check.yml +++ b/.github/workflows/slicing-error-check.yml @@ -16,7 +16,6 @@ jobs: uses: actions/github-script@v7 with: script: | - const core = require('@actions/core'); const issue = context.payload.issue; const issueNumber = issue.number; From 429064f37b5260750725b3e8a1419463d28d3081 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Mon, 16 Jun 2025 15:31:05 +0200 Subject: [PATCH 182/299] Update nightly-stable.yml Set the workflow to be triggered on dispatch Prevents workflow run errors --- .github/workflows/nightly-stable.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nightly-stable.yml b/.github/workflows/nightly-stable.yml index 2790947ae8..badcef44e6 100644 --- a/.github/workflows/nightly-stable.yml +++ b/.github/workflows/nightly-stable.yml @@ -1,7 +1,8 @@ name: Nightly build - stable release run-name: Nightly build - stable release -# on: +on: + workflow_dispatch: # schedule: # # Daily at 5:15 CET # - cron: '15 4 * * *' From b3e9bc10868f6a06abe03130081315ad0925d974 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Mon, 16 Jun 2025 15:31:22 +0200 Subject: [PATCH 183/299] Update nightly-testing.yml Set the workflow to be triggered on dispatch Prevents workflow run errors --- .github/workflows/nightly-testing.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/nightly-testing.yml b/.github/workflows/nightly-testing.yml index 13f3670514..08d43570ec 100644 --- a/.github/workflows/nightly-testing.yml +++ b/.github/workflows/nightly-testing.yml @@ -1,10 +1,11 @@ name: Nightly build - dev release run-name: Nightly build - dev release -# on: +on: + workflow_dispatch: # schedule: -# # Daily at 4:15 CET -# - cron: '15 3 * * *' +# # Daily at 5:15 CET +# - cron: '15 4 * * *' jobs: build-nightly: From 89827ef4c1c8bf9da3fbca79164dfa977d250a4e Mon Sep 17 00:00:00 2001 From: Frederic Meeuwissen <13856291+Frederic98@users.noreply.github.com> Date: Mon, 16 Jun 2025 15:35:21 +0200 Subject: [PATCH 184/299] Revert "Remove unused global qualties" --- .../um_s8_global_High_Quality.inst.cfg | 15 +++++++++++++++ .../um_s8_global_Superdraft_Quality.inst.cfg | 15 +++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 resources/quality/ultimaker_s8/um_s8_global_High_Quality.inst.cfg create mode 100644 resources/quality/ultimaker_s8/um_s8_global_Superdraft_Quality.inst.cfg diff --git a/resources/quality/ultimaker_s8/um_s8_global_High_Quality.inst.cfg b/resources/quality/ultimaker_s8/um_s8_global_High_Quality.inst.cfg new file mode 100644 index 0000000000..d495da9f17 --- /dev/null +++ b/resources/quality/ultimaker_s8/um_s8_global_High_Quality.inst.cfg @@ -0,0 +1,15 @@ +[general] +definition = ultimaker_s8 +name = Extra Fine +version = 4 + +[metadata] +global_quality = True +quality_type = high +setting_version = 25 +type = quality +weight = 1 + +[values] +layer_height = =round(0.06 * material_shrinkage_percentage_z / 100, 5) + diff --git a/resources/quality/ultimaker_s8/um_s8_global_Superdraft_Quality.inst.cfg b/resources/quality/ultimaker_s8/um_s8_global_Superdraft_Quality.inst.cfg new file mode 100644 index 0000000000..026e5701de --- /dev/null +++ b/resources/quality/ultimaker_s8/um_s8_global_Superdraft_Quality.inst.cfg @@ -0,0 +1,15 @@ +[general] +definition = ultimaker_s8 +name = Sprint +version = 4 + +[metadata] +global_quality = True +quality_type = superdraft +setting_version = 25 +type = quality +weight = -4 + +[values] +layer_height = =round(0.4 * material_shrinkage_percentage_z / 100, 5) + From 2390067d694b425eb87a3830ce3647258f07fc1c Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 17 Jun 2025 09:20:59 +0200 Subject: [PATCH 185/299] Restore basic themes CURA-12544 Mistakenly commited after applying the daily rotated colors --- .../themes/cura-dark-colorblind/theme.json | 27 +- resources/themes/cura-dark/theme.json | 213 +++++- .../themes/cura-light-colorblind/theme.json | 30 +- resources/themes/cura-light/theme.json | 681 +++++++++++++++++- resources/themes/daily_test_colors.json | 16 + 5 files changed, 963 insertions(+), 4 deletions(-) create mode 100644 resources/themes/daily_test_colors.json diff --git a/resources/themes/cura-dark-colorblind/theme.json b/resources/themes/cura-dark-colorblind/theme.json index 4443111b60..4a006ee836 100644 --- a/resources/themes/cura-dark-colorblind/theme.json +++ b/resources/themes/cura-dark-colorblind/theme.json @@ -1 +1,26 @@ -{"metadata": {"name": "Colorblind Assist Dark", "inherits": "cura-dark"}, "colors": {"x_axis": [212, 0, 0, 255], "y_axis": [64, 64, 255, 255], "model_overhang": [200, 0, 255, 255], "xray": [26, 26, 62, 255], "xray_error": [255, 0, 0, 255], "layerview_inset_0": [255, 64, 0, 255], "layerview_inset_x": [0, 156, 128, 255], "layerview_skin": [255, 255, 86, 255], "layerview_support": [255, 255, 0, 255], "layerview_infill": [0, 255, 255, 255], "layerview_support_infill": [0, 200, 200, 255], "layerview_move_retraction": [0, 100, 255, 255], "main_window_header_background": [192, 199, 65, 255]}} \ No newline at end of file +{ + "metadata": { + "name": "Colorblind Assist Dark", + "inherits": "cura-dark" + }, + + "colors": { + "x_axis": [212, 0, 0, 255], + "y_axis": [64, 64, 255, 255], + + "model_overhang": [200, 0, 255, 255], + + "xray": [26, 26, 62, 255], + "xray_error": [255, 0, 0, 255], + + "layerview_inset_0": [255, 64, 0, 255], + "layerview_inset_x": [0, 156, 128, 255], + "layerview_skin": [255, 255, 86, 255], + "layerview_support": [255, 255, 0, 255], + + "layerview_infill": [0, 255, 255, 255], + "layerview_support_infill": [0, 200, 200, 255], + + "layerview_move_retraction": [0, 100, 255, 255] + } +} diff --git a/resources/themes/cura-dark/theme.json b/resources/themes/cura-dark/theme.json index 29be47e697..64c3e002a9 100644 --- a/resources/themes/cura-dark/theme.json +++ b/resources/themes/cura-dark/theme.json @@ -1 +1,212 @@ -{"metadata": {"name": "UltiMaker Dark", "inherits": "cura-light"}, "base_colors": {"background_1": [31, 31, 32, 255], "background_2": [57, 57, 58, 255], "background_3": [85, 85, 87, 255], "background_4": [23, 23, 23, 255], "accent_1": [25, 110, 240, 255], "accent_2": [16, 70, 156, 255], "border_main": [118, 118, 119, 255], "border_accent_1": [255, 255, 255, 255], "border_accent_2": [243, 243, 243, 255], "border_field": [57, 57, 58, 255], "text_default": [255, 255, 255, 255], "text_disabled": [118, 118, 118, 255], "text_primary_button": [255, 255, 255, 255], "text_secondary_button": [255, 255, 255, 255], "text_link_hover": [156, 195, 255, 255], "text_lighter": [243, 243, 243, 255], "um_green_1": [233, 245, 237, 255], "um_green_5": [36, 162, 73, 255], "um_green_9": [31, 44, 36, 255], "um_red_1": [251, 232, 233, 255], "um_red_5": [218, 30, 40, 255], "um_red_9": [59, 31, 33, 255], "um_orange_1": [255, 235, 221, 255], "um_orange_5": [252, 123, 30, 255], "um_orange_9": [64, 45, 32, 255], "um_yellow_1": [255, 248, 225, 255], "um_yellow_5": [253, 209, 58, 255], "um_yellow_9": [64, 58, 36, 255]}, "colors": {"main_background": "background_1", "detail_background": "background_2", "message_background": "background_1", "wide_lining": [31, 36, 39, 255], "thick_lining": [255, 255, 255, 60], "lining": "border_main", "viewport_overlay": "background_1", "primary_text": "text_default", "secondary": [95, 95, 95, 255], "expandable_active": "background_2", "expandable_hover": "background_2", "secondary_button": "background_1", "secondary_button_hover": "background_3", "secondary_button_text": "text_secondary_button", "icon": "text_default", "toolbar_background": "background_1", "toolbar_button_active": "background_3", "toolbar_button_hover": "background_3", "toolbar_button_active_hover": "background_3", "main_window_header_button_background_inactive": "background_4", "main_window_header_button_text_inactive": "text_primary_button", "main_window_header_button_text_active": "background_4", "main_window_header_background": [192, 199, 65, 255], "main_window_header_background_gradient": "background_4", "main_window_header_button_background_hovered": [46, 46, 46, 255], "account_sync_state_icon": [255, 255, 255, 204], "machine_selector_printer_icon": [204, 204, 204, 255], "text": "text_default", "text_detail": [255, 255, 255, 172], "text_link": "accent_1", "text_inactive": [118, 118, 118, 255], "text_hover": [255, 255, 255, 255], "text_scene": [250, 250, 250, 255], "text_scene_hover": [255, 255, 255, 255], "printer_type_label_background": [95, 95, 95, 255], "error": [212, 31, 53, 255], "disabled": [32, 32, 32, 255], "button": [39, 44, 48, 255], "button_hover": [39, 44, 48, 255], "button_text": "text_default", "button_disabled": [39, 44, 48, 255], "button_disabled_text": [255, 255, 255, 101], "small_button_text": [255, 255, 255, 197], "small_button_text_hover": [255, 255, 255, 255], "button_tooltip": [39, 44, 48, 255], "tab_checked": [39, 44, 48, 255], "tab_checked_border": [255, 255, 255, 30], "tab_checked_text": [255, 255, 255, 255], "tab_unchecked": [39, 44, 48, 255], "tab_unchecked_border": [255, 255, 255, 30], "tab_unchecked_text": [255, 255, 255, 101], "tab_hovered": [39, 44, 48, 255], "tab_hovered_border": [255, 255, 255, 30], "tab_hovered_text": [255, 255, 255, 255], "tab_active": [39, 44, 48, 255], "tab_active_border": [255, 255, 255, 30], "tab_active_text": [255, 255, 255, 255], "tab_background": [39, 44, 48, 255], "action_button": "background_1", "action_button_text": [255, 255, 255, 200], "action_button_border": "border_main", "action_button_hovered": [79, 85, 89, 255], "action_button_hovered_text": "text_default", "action_button_hovered_border": "border_main", "action_button_active": [39, 44, 48, 30], "action_button_active_text": "text_default", "action_button_active_border": [255, 255, 255, 100], "action_button_disabled": "background_3", "action_button_disabled_text": "text_disabled", "action_button_disabled_border": [255, 255, 255, 30], "scrollbar_background": [39, 44, 48, 0], "scrollbar_handle": [255, 255, 255, 105], "scrollbar_handle_hover": [255, 255, 255, 255], "scrollbar_handle_down": [255, 255, 255, 255], "setting_category_disabled": [75, 80, 83, 255], "setting_category_disabled_text": [255, 255, 255, 101], "setting_control": "background_2", "setting_control_selected": [34, 39, 42, 38], "setting_control_highlight": "background_3", "setting_control_border": [255, 255, 255, 38], "setting_control_border_highlight": [12, 169, 227, 255], "setting_control_text": "text_default", "setting_control_button": [255, 255, 255, 127], "setting_control_button_hover": [255, 255, 255, 204], "setting_control_disabled": [34, 39, 42, 255], "setting_control_disabled_text": [255, 255, 255, 101], "setting_control_disabled_border": [255, 255, 255, 101], "setting_unit": [255, 255, 255, 127], "setting_validation_error_background": "um_red_9", "setting_validation_warning_background": "um_yellow_9", "setting_validation_ok": "background_2", "progressbar_background": [255, 255, 255, 48], "progressbar_control": [255, 255, 255, 197], "slider_groove": [127, 127, 127, 255], "slider_groove_border": [127, 127, 127, 255], "slider_groove_fill": [245, 245, 245, 255], "slider_handle": [255, 255, 255, 255], "slider_handle_active": [68, 192, 255, 255], "category_background": "background_3", "tooltip": "background_2", "tooltip_text": "text_default", "tool_panel_background": "background_1", "viewport_background": "background_1", "volume_outline": [12, 169, 227, 128], "buildplate": [169, 169, 169, 255], "buildplate_grid_minor": [154, 154, 155, 255], "disallowed_area": [0, 0, 0, 52], "model_selection_outline": [12, 169, 227, 255], "material_compatibility_warning": [255, 255, 255, 255], "core_compatibility_warning": [255, 255, 255, 255], "quality_slider_available": [255, 255, 255, 255], "monitor_printer_family_tag": [86, 86, 106, 255], "monitor_text_disabled": [102, 102, 102, 255], "monitor_icon_primary": [229, 229, 229, 255], "monitor_icon_accent": [51, 53, 54, 255], "monitor_icon_disabled": [102, 102, 102, 255], "monitor_secondary_button_hover": [80, 80, 80, 255], "monitor_card_border": [102, 102, 102, 255], "monitor_card_background": [51, 53, 54, 255], "monitor_card_hover": [84, 89, 95, 255], "monitor_stage_background": "background_1", "monitor_stage_background_fade": "background_1", "monitor_progress_bar_deactive": [102, 102, 102, 255], "monitor_progress_bar_empty": [67, 67, 67, 255], "monitor_tooltip_text": [229, 229, 229, 255], "monitor_context_menu": [67, 67, 67, 255], "monitor_context_menu_hover": [30, 102, 215, 255], "monitor_skeleton_loading": [102, 102, 102, 255], "monitor_placeholder_image": [102, 102, 102, 255], "monitor_shadow": [4, 10, 13, 255], "monitor_carousel_dot": [119, 119, 119, 255], "monitor_carousel_dot_current": [216, 216, 216, 255]}} \ No newline at end of file +{ + "metadata": { + "name": "UltiMaker Dark", + "inherits": "cura-light" + }, + + "base_colors": + { + "background_1": [31, 31, 32, 255], + "background_2": [57, 57, 58, 255], + "background_3": [85, 85, 87, 255], + "background_4": [23, 23, 23, 255], + + "accent_1": [25, 110, 240, 255], + "accent_2": [16, 70, 156, 255], + "border_main": [118, 118, 119, 255], + "border_accent_1": [255, 255, 255, 255], + "border_accent_2": [243, 243, 243, 255], + "border_field": [57, 57, 58, 255], + + "text_default": [255, 255, 255, 255], + "text_disabled": [118, 118, 118, 255], + "text_primary_button": [255, 255, 255, 255], + "text_secondary_button": [255, 255, 255, 255], + "text_link_hover": [156, 195, 255, 255], + "text_lighter": [243, 243, 243, 255], + + "um_green_1": [233, 245, 237, 255], + "um_green_5": [36, 162, 73, 255], + "um_green_9": [31, 44, 36, 255], + "um_red_1": [251, 232, 233, 255], + "um_red_5": [218, 30, 40, 255], + "um_red_9": [59, 31, 33, 255], + "um_orange_1": [255, 235, 221, 255], + "um_orange_5": [252, 123, 30, 255], + "um_orange_9": [64, 45, 32, 255], + "um_yellow_1": [255, 248, 225, 255], + "um_yellow_5": [253, 209, 58, 255], + "um_yellow_9": [64, 58, 36, 255] + }, + + "colors": { + "main_background": "background_1", + "detail_background": "background_2", + "message_background": "background_1", + "wide_lining": [31, 36, 39, 255], + "thick_lining": [255, 255, 255, 60], + "lining": "border_main", + "viewport_overlay": "background_1", + + "primary_text": "text_default", + "secondary": [95, 95, 95, 255], + + "expandable_active": "background_2", + "expandable_hover": "background_2", + + "secondary_button": "background_1", + "secondary_button_hover": "background_3", + "secondary_button_text": [255, 255, 255, 255], + + "icon": "text_default", + "toolbar_background": "background_1", + "toolbar_button_active": "background_3", + "toolbar_button_hover": "background_3", + "toolbar_button_active_hover": "background_3", + + "main_window_header_button_background_inactive": "background_4", + "main_window_header_button_text_inactive": "text_primary_button", + "main_window_header_button_text_active": "background_4", + "main_window_header_background": "background_4", + "main_window_header_background_gradient": "background_4", + "main_window_header_button_background_hovered": [46, 46, 46, 255], + + "secondary_button_text": "text_secondary_button", + + "account_sync_state_icon": [255, 255, 255, 204], + + "machine_selector_printer_icon": [204, 204, 204, 255], + + "text": "text_default", + "text_detail": [255, 255, 255, 172], + "text_link": "accent_1", + "text_inactive": [118, 118, 118, 255], + "text_hover": [255, 255, 255, 255], + "text_scene": [250, 250, 250, 255], + "text_scene_hover": [255, 255, 255, 255], + + "printer_type_label_background": [95, 95, 95, 255], + + "error": [212, 31, 53, 255], + "disabled": [32, 32, 32, 255], + + "button": [39, 44, 48, 255], + "button_hover": [39, 44, 48, 255], + "button_text": "text_default", + "button_disabled": [39, 44, 48, 255], + "button_disabled_text": [255, 255, 255, 101], + + "small_button_text": [255, 255, 255, 197], + "small_button_text_hover": [255, 255, 255, 255], + + "button_tooltip": [39, 44, 48, 255], + + "tab_checked": [39, 44, 48, 255], + "tab_checked_border": [255, 255, 255, 30], + "tab_checked_text": [255, 255, 255, 255], + "tab_unchecked": [39, 44, 48, 255], + "tab_unchecked_border": [255, 255, 255, 30], + "tab_unchecked_text": [255, 255, 255, 101], + "tab_hovered": [39, 44, 48, 255], + "tab_hovered_border": [255, 255, 255, 30], + "tab_hovered_text": [255, 255, 255, 255], + "tab_active": [39, 44, 48, 255], + "tab_active_border": [255, 255, 255, 30], + "tab_active_text": [255, 255, 255, 255], + "tab_background": [39, 44, 48, 255], + + "action_button": "background_1", + "action_button_text": [255, 255, 255, 200], + "action_button_border": "border_main", + "action_button_hovered": [79, 85, 89, 255], + "action_button_hovered_text": "text_default", + "action_button_hovered_border": "border_main", + "action_button_active": [39, 44, 48, 30], + "action_button_active_text": "text_default", + "action_button_active_border": [255, 255, 255, 100], + "action_button_disabled": "background_3", + "action_button_disabled_text": "text_disabled", + "action_button_disabled_border": [255, 255, 255, 30], + + "scrollbar_background": [39, 44, 48, 0], + "scrollbar_handle": [255, 255, 255, 105], + "scrollbar_handle_hover": [255, 255, 255, 255], + "scrollbar_handle_down": [255, 255, 255, 255], + + "setting_category_disabled": [75, 80, 83, 255], + "setting_category_disabled_text": [255, 255, 255, 101], + + "setting_control": "background_2", + "setting_control_selected": [34, 39, 42, 38], + "setting_control_highlight": "background_3", + "setting_control_border": [255, 255, 255, 38], + "setting_control_border_highlight": [12, 169, 227, 255], + "setting_control_text": "text_default", + "setting_control_button": [255, 255, 255, 127], + "setting_control_button_hover": [255, 255, 255, 204], + "setting_control_disabled": [34, 39, 42, 255], + "setting_control_disabled_text": [255, 255, 255, 101], + "setting_control_disabled_border": [255, 255, 255, 101], + "setting_unit": [255, 255, 255, 127], + "setting_validation_error_background": "um_red_9", + "setting_validation_warning_background": "um_yellow_9", + "setting_validation_ok": "background_2", + + "progressbar_background": [255, 255, 255, 48], + "progressbar_control": [255, 255, 255, 197], + + "slider_groove": [127, 127, 127, 255], + "slider_groove_border": [127, 127, 127, 255], + "slider_groove_fill": [245, 245, 245, 255], + "slider_handle": [255, 255, 255, 255], + "slider_handle_active": [68, 192, 255, 255], + + "category_background": "background_3", + + "tooltip": "background_2", + "tooltip_text": "text_default", + + "tool_panel_background": "background_1", + + "viewport_background": "background_1", + "volume_outline": [12, 169, 227, 128], + "buildplate": [169, 169, 169, 255], + "buildplate_grid_minor": [154, 154, 155, 255], + + "disallowed_area": [0, 0, 0, 52], + + "model_selection_outline": [12, 169, 227, 255], + + "material_compatibility_warning": [255, 255, 255, 255], + + "quality_slider_available": [255, 255, 255, 255], + + "monitor_printer_family_tag": [86, 86, 106, 255], + "monitor_text_disabled": [102, 102, 102, 255], + "monitor_icon_primary": [229, 229, 229, 255], + "monitor_icon_accent": [51, 53, 54, 255], + "monitor_icon_disabled": [102, 102, 102, 255], + + "monitor_secondary_button_hover": [80, 80, 80, 255], + "monitor_card_border": [102, 102, 102, 255], + "monitor_card_background": [51, 53, 54, 255], + "monitor_card_hover": [84, 89, 95, 255], + + "monitor_stage_background": "background_1", + "monitor_stage_background_fade": "background_1", + + "monitor_progress_bar_deactive": [102, 102, 102, 255], + "monitor_progress_bar_empty": [67, 67, 67, 255], + + "monitor_tooltip_text": [229, 229, 229, 255], + "monitor_context_menu": [67, 67, 67, 255], + "monitor_context_menu_hover": [30, 102, 215, 255], + + "monitor_skeleton_loading": [102, 102, 102, 255], + "monitor_placeholder_image": [102, 102, 102, 255], + "monitor_shadow": [4, 10, 13, 255], + + "monitor_carousel_dot": [119, 119, 119, 255], + "monitor_carousel_dot_current": [216, 216, 216, 255] + } +} diff --git a/resources/themes/cura-light-colorblind/theme.json b/resources/themes/cura-light-colorblind/theme.json index cc7ed5dfba..740bf977b2 100644 --- a/resources/themes/cura-light-colorblind/theme.json +++ b/resources/themes/cura-light-colorblind/theme.json @@ -1 +1,29 @@ -{"metadata": {"name": "Colorblind Assist Light", "inherits": "cura-light"}, "colors": {"x_axis": [200, 0, 0, 255], "y_axis": [64, 64, 255, 255], "model_overhang": [200, 0, 255, 255], "model_selection_outline": [12, 169, 227, 255], "xray_error_dark": [255, 0, 0, 255], "xray_error_light": [255, 255, 0, 255], "xray": [26, 26, 62, 255], "xray_error": [255, 0, 0, 255], "layerview_inset_0": [255, 64, 0, 255], "layerview_inset_x": [0, 156, 128, 255], "layerview_skin": [255, 255, 86, 255], "layerview_support": [255, 255, 0, 255], "layerview_infill": [0, 255, 255, 255], "layerview_support_infill": [0, 200, 200, 255], "layerview_move_retraction": [0, 100, 255, 255], "main_window_header_background": [192, 199, 65, 255]}} \ No newline at end of file +{ + "metadata": { + "name": "Colorblind Assist Light", + "inherits": "cura-light" + }, + + "colors": { + + "x_axis": [200, 0, 0, 255], + "y_axis": [64, 64, 255, 255], + "model_overhang": [200, 0, 255, 255], + "model_selection_outline": [12, 169, 227, 255], + + "xray_error_dark": [255, 0, 0, 255], + "xray_error_light": [255, 255, 0, 255], + "xray": [26, 26, 62, 255], + "xray_error": [255, 0, 0, 255], + + "layerview_inset_0": [255, 64, 0, 255], + "layerview_inset_x": [0, 156, 128, 255], + "layerview_skin": [255, 255, 86, 255], + "layerview_support": [255, 255, 0, 255], + + "layerview_infill": [0, 255, 255, 255], + "layerview_support_infill": [0, 200, 200, 255], + + "layerview_move_retraction": [0, 100, 255, 255] + } +} diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 2362155944..8f3f9076c5 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -1 +1,680 @@ -{"metadata": {"name": "UltiMaker"}, "fonts": {"large": {"size": 1.35, "weight": 400, "family": "Noto Sans"}, "large_ja_JP": {"size": 1.35, "weight": 400, "family": "Noto Sans"}, "large_zh_CN": {"size": 1.35, "weight": 400, "family": "Noto Sans"}, "large_zh_TW": {"size": 1.35, "weight": 400, "family": "Noto Sans"}, "large_bold": {"size": 1.35, "weight": 600, "family": "Noto Sans"}, "huge": {"size": 1.8, "weight": 400, "family": "Noto Sans"}, "huge_bold": {"size": 1.8, "weight": 600, "family": "Noto Sans"}, "medium": {"size": 1.16, "weight": 400, "family": "Noto Sans"}, "medium_ja_JP": {"size": 1.16, "weight": 400, "family": "Noto Sans"}, "medium_zh_CN": {"size": 1.16, "weight": 400, "family": "Noto Sans"}, "medium_zh_TW": {"size": 1.16, "weight": 400, "family": "Noto Sans"}, "medium_bold": {"size": 1.16, "weight": 600, "family": "Noto Sans"}, "default": {"size": 0.95, "weight": 400, "family": "Noto Sans"}, "default_ja_JP": {"size": 1.0, "weight": 400, "family": "Noto Sans"}, "default_zh_CN": {"size": 1.0, "weight": 400, "family": "Noto Sans"}, "default_zh_TW": {"size": 1.0, "weight": 400, "family": "Noto Sans"}, "default_bold": {"size": 0.95, "weight": 600, "family": "Noto Sans"}, "default_bold_ja_JP": {"size": 1.0, "weight": 600, "family": "Noto Sans"}, "default_bold_zh_CN": {"size": 1.0, "weight": 600, "family": "Noto Sans"}, "default_bold_zh_TW": {"size": 1.0, "weight": 600, "family": "Noto Sans"}, "default_italic": {"size": 0.95, "weight": 400, "italic": true, "family": "Noto Sans"}, "medium_italic": {"size": 1.16, "weight": 400, "italic": true, "family": "Noto Sans"}, "default_italic_ja_JP": {"size": 1.0, "weight": 400, "italic": true, "family": "Noto Sans"}, "default_italic_zh_CN": {"size": 1.0, "weight": 400, "italic": true, "family": "Noto Sans"}, "default_italic_zh_TW": {"size": 1.0, "weight": 400, "italic": true, "family": "Noto Sans"}, "small": {"size": 0.9, "weight": 400, "family": "Noto Sans"}, "small_bold": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "small_ja_JP": {"size": 0.9, "weight": 400, "family": "Noto Sans"}, "small_zh_CN": {"size": 0.9, "weight": 400, "family": "Noto Sans"}, "small_zh_TW": {"size": 0.9, "weight": 400, "family": "Noto Sans"}, "small_emphasis": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "small_emphasis_ja_JP": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "small_emphasis_zh_CN": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "small_emphasis_zh_TW": {"size": 0.9, "weight": 700, "family": "Noto Sans"}, "tiny_emphasis": {"size": 0.7, "weight": 700, "family": "Noto Sans"}, "tiny_emphasis_ja_JP": {"size": 0.7, "weight": 700, "family": "Noto Sans"}, "tiny_emphasis_zh_CN": {"size": 0.7, "weight": 700, "family": "Noto Sans"}, "tiny_emphasis_zh_TW": {"size": 0.7, "weight": 700, "family": "Noto Sans"}}, "base_colors": {"background_1": [255, 255, 255, 255], "background_2": [243, 243, 243, 255], "background_3": [232, 240, 253, 255], "background_4": [3, 12, 66, 255], "accent_1": [25, 110, 240, 255], "accent_2": [16, 70, 156, 255], "border_main": [212, 212, 212, 255], "border_accent_1": [25, 110, 240, 255], "border_accent_2": [16, 70, 156, 255], "border_field": [180, 180, 180, 255], "text_default": [0, 14, 26, 255], "text_disabled": [180, 180, 180, 255], "text_primary_button": [255, 255, 255, 255], "text_secondary_button": [25, 110, 240, 255], "text_link_hover": [16, 70, 156, 255], "text_lighter": [108, 108, 108, 255], "um_green_1": [233, 245, 237, 255], "um_green_5": [36, 162, 73, 255], "um_green_9": [31, 44, 36, 255], "um_red_1": [251, 232, 233, 255], "um_red_5": [218, 30, 40, 255], "um_red_9": [59, 31, 33, 255], "um_orange_1": [255, 235, 221, 255], "um_orange_5": [252, 123, 30, 255], "um_orange_9": [64, 45, 32, 255], "um_yellow_1": [255, 248, 225, 255], "um_yellow_5": [253, 209, 58, 255], "um_yellow_9": [64, 58, 36, 255]}, "colors": {"main_background": "background_1", "detail_background": "background_2", "wide_lining": [245, 245, 245, 255], "thick_lining": [180, 180, 180, 255], "lining": [192, 193, 194, 255], "viewport_overlay": [246, 246, 246, 255], "primary": "accent_1", "primary_hover": [48, 182, 231, 255], "primary_text": [255, 255, 255, 255], "text_selection": [156, 195, 255, 127], "border": [127, 127, 127, 255], "border_field": [180, 180, 180, 255], "secondary": [240, 240, 240, 255], "expandable_active": [240, 240, 240, 255], "expandable_hover": [232, 242, 252, 255], "icon": [8, 7, 63, 255], "primary_button": "accent_1", "primary_button_hover": [16, 70, 156, 255], "primary_button_text": [255, 255, 255, 255], "secondary_button": "background_1", "secondary_button_shadow": [216, 216, 216, 255], "secondary_button_hover": [232, 240, 253, 255], "secondary_button_text": "accent_1", "main_window_header_background": [192, 199, 65, 255], "main_window_header_background_gradient": [25, 23, 91, 255], "main_window_header_button_text_active": [8, 7, 63, 255], "main_window_header_button_text_inactive": [255, 255, 255, 255], "main_window_header_button_text_hovered": [255, 255, 255, 255], "main_window_header_button_background_active": [255, 255, 255, 255], "main_window_header_button_background_inactive": [255, 255, 255, 0], "main_window_header_button_background_hovered": [117, 114, 159, 255], "account_widget_outline_active": [70, 66, 126, 255], "account_sync_state_icon": [25, 25, 25, 255], "machine_selector_printer_icon": [8, 7, 63, 255], "action_panel_secondary": "accent_1", "first_run_shadow": [50, 50, 50, 255], "toolbar_background": [255, 255, 255, 255], "notification_icon": [255, 0, 0, 255], "printer_type_label_background": [228, 228, 242, 255], "window_disabled_background": [0, 0, 0, 255], "text": [25, 25, 25, 255], "text_disabled": [180, 180, 180, 255], "text_detail": [174, 174, 174, 128], "text_link": "accent_1", "text_inactive": [174, 174, 174, 255], "text_medium": [128, 128, 128, 255], "text_scene": [102, 102, 102, 255], "text_scene_hover": [123, 123, 113, 255], "error": [218, 30, 40, 255], "warning": [253, 209, 58, 255], "success": [36, 162, 73, 255], "disabled": [229, 229, 229, 255], "toolbar_button_hover": [232, 242, 252, 255], "toolbar_button_active": [232, 242, 252, 255], "toolbar_button_active_hover": [232, 242, 252, 255], "button_text": [255, 255, 255, 255], "small_button_text": [102, 102, 102, 255], "small_button_text_hover": [8, 7, 63, 255], "button_tooltip": [31, 36, 39, 255], "extruder_disabled": [255, 255, 255, 102], "action_button": [255, 255, 255, 255], "action_button_hovered": [232, 242, 252, 255], "action_button_disabled": [245, 245, 245, 255], "action_button_disabled_text": [196, 196, 196, 255], "action_button_shadow": [223, 223, 223, 255], "scrollbar_background": [255, 255, 255, 255], "scrollbar_handle": [10, 8, 80, 255], "scrollbar_handle_hover": [50, 130, 255, 255], "scrollbar_handle_down": [50, 130, 255, 255], "setting_category": "background_1", "setting_category_disabled": [255, 255, 255, 255], "setting_category_hover": "background_2", "setting_category_text": "text_default", "setting_category_disabled_text": [24, 41, 77, 101], "setting_category_active_text": "text_default", "setting_control": "background_2", "setting_control_highlight": "background_3", "setting_control_border": [199, 199, 199, 255], "setting_control_border_highlight": [50, 130, 255, 255], "setting_control_text": [35, 35, 35, 255], "setting_control_button": [102, 102, 102, 255], "setting_control_button_hover": [8, 7, 63, 255], "setting_control_disabled": "background_2", "setting_control_disabled_text": [127, 127, 127, 255], "setting_control_disabled_border": [127, 127, 127, 255], "setting_unit": [127, 127, 127, 255], "setting_validation_error_background": "um_red_1", "setting_validation_error": "um_red_5", "setting_validation_warning_background": "um_yellow_1", "setting_validation_warning": "um_yellow_5", "setting_validation_ok": "background_2", "material_compatibility_warning": [243, 166, 59, 255], "core_compatibility_warning": [243, 166, 59, 255], "progressbar_background": [245, 245, 245, 255], "progressbar_control": [50, 130, 255, 255], "slider_groove": [223, 223, 223, 255], "slider_groove_fill": [8, 7, 63, 255], "slider_handle": [8, 7, 63, 255], "slider_handle_active": [50, 130, 255, 255], "slider_text_background": [255, 255, 255, 255], "quality_slider_unavailable": [179, 179, 179, 255], "quality_slider_available": [0, 0, 0, 255], "checkbox": "background_1", "checkbox_hover": "background_1", "checkbox_disabled": "background_2", "checkbox_border": [180, 180, 180, 255], "checkbox_border_hover": "border_main", "checkbox_border_disabled": "text_disabled", "checkbox_mark": "text_default", "checkbox_mark_disabled": "text_disabled", "checkbox_square": [180, 180, 180, 255], "checkbox_text": "text_default", "checkbox_text_disabled": "text_disabled", "switch": "background_1", "switch_state_checked": "accent_1", "switch_state_unchecked": "text_disabled", "radio": "background_1", "radio_disabled": "background_2", "radio_selected": "accent_1", "radio_selected_disabled": "text_disabled", "radio_border": [180, 180, 180, 255], "radio_border_hover": "border_main", "radio_border_disabled": "text_disabled", "radio_dot": "background_1", "radio_dot_disabled": "background_2", "radio_text": "text_default", "radio_text_disabled": "text_disabled", "text_field": "background_1", "text_field_border": [180, 180, 180, 255], "text_field_border_hovered": "border_main", "text_field_border_active": "border_accent_2", "text_field_border_disabled": "background_2", "text_field_text": "text_default", "text_field_text_disabled": "text_disabled", "category_background": "background_2", "tooltip": [25, 25, 25, 255], "tooltip_text": [255, 255, 255, 255], "message_background": [255, 255, 255, 255], "message_border": [192, 193, 194, 255], "message_close": [102, 102, 102, 255], "message_close_hover": [8, 7, 63, 255], "message_progressbar_background": [245, 245, 245, 255], "message_progressbar_control": [50, 130, 255, 255], "message_success_icon": [255, 255, 255, 255], "message_warning_icon": [0, 0, 0, 255], "message_error_icon": [255, 255, 255, 255], "tool_panel_background": [255, 255, 255, 255], "status_offline": [0, 0, 0, 255], "status_ready": [0, 205, 0, 255], "status_busy": [50, 130, 255, 255], "status_paused": [255, 140, 0, 255], "status_stopped": [236, 82, 80, 255], "disabled_axis": [127, 127, 127, 255], "x_axis": [218, 30, 40, 255], "y_axis": [25, 110, 240, 255], "z_axis": [36, 162, 73, 255], "all_axis": [255, 255, 255, 255], "viewport_background": [250, 250, 250, 255], "volume_outline": [50, 130, 255, 255], "buildplate": [244, 244, 244, 255], "buildplate_grid": [180, 180, 180, 255], "buildplate_grid_minor": [228, 228, 228, 255], "convex_hull": [35, 35, 35, 127], "disallowed_area": [0, 0, 0, 40], "error_area": [255, 0, 0, 127], "model_overhang": [255, 0, 0, 255], "model_unslicable": [122, 122, 122, 255], "model_unslicable_alt": [172, 172, 127, 255], "model_selection_outline": [50, 130, 255, 255], "model_non_printing": [122, 122, 122, 255], "xray": [26, 26, 62, 255], "layerview_ghost": [31, 31, 31, 95], "layerview_none": [255, 255, 255, 255], "layerview_inset_0": [230, 0, 0, 255], "layerview_inset_x": [0, 230, 0, 255], "layerview_skin": [230, 230, 0, 255], "layerview_support": [0, 230, 230, 127], "layerview_skirt": [0, 230, 230, 255], "layerview_infill": [230, 115, 0, 255], "layerview_support_infill": [0, 230, 230, 127], "layerview_move_combing": [0, 0, 255, 255], "layerview_move_retraction": [128, 127, 255, 255], "layerview_move_while_retracting": [127, 255, 255, 255], "layerview_move_while_unretracting": [255, 127, 255, 255], "layerview_support_interface": [63, 127, 255, 127], "layerview_prime_tower": [0, 255, 255, 255], "layerview_nozzle": [224, 192, 16, 64], "layerview_starts": [255, 255, 255, 255], "monitor_printer_family_tag": [228, 228, 242, 255], "monitor_text_disabled": [238, 238, 238, 255], "monitor_icon_primary": [10, 8, 80, 255], "monitor_icon_accent": [255, 255, 255, 255], "monitor_icon_disabled": [238, 238, 238, 255], "monitor_card_border": [192, 193, 194, 255], "monitor_card_background": [255, 255, 255, 255], "monitor_card_hover": [232, 242, 252, 255], "monitor_stage_background": [246, 246, 246, 255], "monitor_stage_background_fade": [246, 246, 246, 102], "monitor_tooltip": [25, 25, 25, 255], "monitor_tooltip_text": [255, 255, 255, 255], "monitor_context_menu": [255, 255, 255, 255], "monitor_context_menu_hover": [245, 245, 245, 255], "monitor_skeleton_loading": [238, 238, 238, 255], "monitor_placeholder_image": [230, 230, 230, 255], "monitor_image_overlay": [0, 0, 0, 255], "monitor_shadow": [200, 200, 200, 255], "monitor_carousel_dot": [216, 216, 216, 255], "monitor_carousel_dot_current": [119, 119, 119, 255], "cloud_unavailable": [153, 153, 153, 255], "connection_badge_background": [255, 255, 255, 255], "warning_badge_background": [0, 0, 0, 255], "error_badge_background": [255, 255, 255, 255], "border_field_light": [180, 180, 180, 255], "border_main_light": [212, 212, 212, 255]}, "sizes": {"window_minimum_size": [80, 48], "popup_dialog": [40, 36], "small_popup_dialog": [36, 12], "main_window_header": [0.0, 4.0], "stage_menu": [0.0, 4.0], "account_button": [12, 2.5], "print_setup_widget": [38.0, 30.0], "print_setup_extruder_box": [0.0, 6.0], "slider_widget_groove": [0.16, 0.16], "slider_widget_handle": [1.3, 1.3], "slider_widget_tickmarks": [0.5, 0.5], "print_setup_big_item": [28, 2.5], "print_setup_icon": [1.2, 1.2], "drag_icon": [1.416, 0.25], "application_switcher_item": [8, 9], "application_switcher_icon": [3.75, 3.75], "expandable_component_content_header": [0.0, 3.0], "configuration_selector": [35.0, 4.0], "action_panel_widget": [26.0, 0.0], "action_panel_information_widget": [20.0, 0.0], "machine_selector_widget": [20.0, 4.0], "machine_selector_widget_content": [25.0, 32.0], "machine_selector_icon": [2.5, 2.5], "views_selector": [16.0, 4.0], "printer_type_label": [3.5, 1.5], "default_radius": [0.25, 0.25], "wide_lining": [0.5, 0.5], "thick_lining": [0.2, 0.2], "default_lining": [0.08, 0.08], "default_arrow": [0.8, 0.8], "logo": [16, 2], "wide_margin": [2.0, 2.0], "thick_margin": [1.71, 1.43], "default_margin": [1.0, 1.0], "thin_margin": [0.71, 0.71], "narrow_margin": [0.5, 0.5], "extruder_icon": [2.5, 2.5], "section": [0.0, 2], "section_header": [0.0, 2.5], "section_control": [0, 1], "section_icon": [1.5, 1.5], "section_icon_column": [2.5, 2.5], "setting": [25.0, 1.8], "setting_control": [9.0, 2.0], "setting_control_radius": [0.15, 0.15], "setting_control_depth_margin": [1.4, 0.0], "setting_unit_margin": [0.5, 0.5], "standard_list_lineheight": [1.5, 1.5], "standard_arrow": [1.0, 1.0], "card": [25.0, 10], "card_icon": [6.0, 6.0], "card_tiny_icon": [1.5, 1.5], "button": [4, 4], "button_icon": [2.5, 2.5], "action_button": [15.0, 2.5], "action_button_icon": [1.5, 1.5], "action_button_icon_small": [1.0, 1.0], "action_button_radius": [0.15, 0.15], "radio_button": [1.3, 1.3], "small_button": [2, 2], "small_button_icon": [1.5, 1.5], "medium_button": [2.5, 2.5], "medium_button_icon": [2, 2], "large_button": [3.0, 3.0], "large_button_icon": [2.8, 2.8], "context_menu": [20, 2], "icon_indicator": [1, 1], "printer_status_icon": [1.0, 1.0], "button_tooltip": [1.0, 1.3], "button_tooltip_arrow": [0.25, 0.25], "progressbar": [26.0, 0.75], "progressbar_radius": [0.15, 0.15], "scrollbar": [0.75, 0.5], "slider_groove": [0.5, 0.5], "slider_groove_radius": [0.15, 0.15], "slider_handle": [1.5, 1.5], "slider_layerview_size": [1.0, 34.0], "layerview_menu_size": [16.0, 4.0], "layerview_legend_size": [1.0, 1.0], "layerview_row": [11.0, 1.5], "layerview_row_spacing": [0.0, 0.5], "checkbox": [1.33, 1.33], "checkbox_mark": [1, 1], "checkbox_radius": [0.25, 0.25], "spinbox": [6.0, 3.0], "combobox": [14, 2], "combobox_wide": [22, 2], "tooltip": [20.0, 10.0], "tooltip_margins": [1.0, 1.0], "tooltip_arrow_margins": [2.0, 2.0], "save_button_save_to_button": [0.3, 2.7], "save_button_specs_icons": [1.4, 1.4], "first_run_shadow_radius": [1.2, 1.2], "monitor_preheat_temperature_control": [4.5, 2.0], "welcome_wizard_window": [46, 50], "modal_window_minimum": [60.0, 50.0], "wizard_progress": [10.0, 0.0], "message": [30.0, 5.0], "message_close": [2, 2], "message_radius": [0.25, 0.25], "message_action_button": [0, 2.5], "message_image": [15.0, 10.0], "message_type_icon": [2, 2], "menu": [18, 2], "jobspecs_line": [2.0, 2.0], "objects_menu_size": [15, 15], "notification_icon": [1.5, 1.5], "avatar_image": [6.8, 6.8], "monitor_shadow_radius": [0.4, 0.4], "monitor_empty_state_offset": [5.6, 5.6], "monitor_empty_state_size": [35.0, 25.0], "monitor_column": [18.0, 1.0], "monitor_progress_bar": [16.5, 1.0], "table_row": [2.0, 2.0], "welcome_wizard_content_image_big": [18, 15], "welcome_wizard_cloud_content_image": [4, 4], "banner_icon_size": [2.0, 2.0], "marketplace_large_icon": [4.0, 4.0], "preferences_page_list_item": [8.0, 2.0], "recommended_button_icon": [1.7, 1.7], "recommended_section_setting_item": [14.0, 2.0], "reset_profile_icon": [1, 1]}} \ No newline at end of file +{ + "metadata": { + "name": "UltiMaker" + }, + + "fonts": { + "large": { + "size": 1.35, + "weight": 400, + "family": "Noto Sans" + }, + "large_ja_JP": { + "size": 1.35, + "weight": 400, + "family": "Noto Sans" + }, + "large_zh_CN": { + "size": 1.35, + "weight": 400, + "family": "Noto Sans" + }, + "large_zh_TW": { + "size": 1.35, + "weight": 400, + "family": "Noto Sans" + }, + "large_bold": { + "size": 1.35, + "weight": 600, + "family": "Noto Sans" + }, + "huge": { + "size": 1.8, + "weight": 400, + "family": "Noto Sans" + }, + "huge_bold": { + "size": 1.8, + "weight": 600, + "family": "Noto Sans" + }, + "medium": { + "size": 1.16, + "weight": 400, + "family": "Noto Sans" + }, + "medium_ja_JP": { + "size": 1.16, + "weight": 400, + "family": "Noto Sans" + }, + "medium_zh_CN": { + "size": 1.16, + "weight": 400, + "family": "Noto Sans" + }, + "medium_zh_TW": { + "size": 1.16, + "weight": 400, + "family": "Noto Sans" + }, + "medium_bold": { + "size": 1.16, + "weight": 600, + "family": "Noto Sans" + }, + "default": { + "size": 0.95, + "weight": 400, + "family": "Noto Sans" + }, + "default_ja_JP": { + "size": 1.0, + "weight": 400, + "family": "Noto Sans" + }, + "default_zh_CN": { + "size": 1.0, + "weight": 400, + "family": "Noto Sans" + }, + "default_zh_TW": { + "size": 1.0, + "weight": 400, + "family": "Noto Sans" + }, + "default_bold": { + "size": 0.95, + "weight": 600, + "family": "Noto Sans" + }, + "default_bold_ja_JP": { + "size": 1.0, + "weight": 600, + "family": "Noto Sans" + }, + "default_bold_zh_CN": { + "size": 1.0, + "weight": 600, + "family": "Noto Sans" + }, + "default_bold_zh_TW": { + "size": 1.0, + "weight": 600, + "family": "Noto Sans" + }, + "default_italic": { + "size": 0.95, + "weight": 400, + "italic": true, + "family": "Noto Sans" + }, + "default_italic_ja_JP": { + "size": 1.0, + "weight": 400, + "italic": true, + "family": "Noto Sans" + }, + "default_italic_zh_CN": { + "size": 1.0, + "weight": 400, + "italic": true, + "family": "Noto Sans" + }, + "default_italic_zh_TW": { + "size": 1.0, + "weight": 400, + "italic": true, + "family": "Noto Sans" + }, + "small": { + "size": 0.9, + "weight": 400, + "family": "Noto Sans" + }, + "small_bold": { + "size": 0.9, + "weight": 700, + "family": "Noto Sans" + }, + "small_ja_JP": { + "size": 0.9, + "weight": 400, + "family": "Noto Sans" + }, + "small_zh_CN": { + "size": 0.9, + "weight": 400, + "family": "Noto Sans" + }, + "small_zh_TW": { + "size": 0.9, + "weight": 400, + "family": "Noto Sans" + }, + "small_emphasis": { + "size": 0.9, + "weight": 700, + "family": "Noto Sans" + }, + "small_emphasis_ja_JP": { + "size": 0.9, + "weight": 700, + "family": "Noto Sans" + }, + "small_emphasis_zh_CN": { + "size": 0.9, + "weight": 700, + "family": "Noto Sans" + }, + "small_emphasis_zh_TW": { + "size": 0.9, + "weight": 700, + "family": "Noto Sans" + }, + "tiny_emphasis": { + "size": 0.7, + "weight": 700, + "family": "Noto Sans" + }, + "tiny_emphasis_ja_JP": { + "size": 0.7, + "weight": 700, + "family": "Noto Sans" + }, + "tiny_emphasis_zh_CN": { + "size": 0.7, + "weight": 700, + "family": "Noto Sans" + }, + "tiny_emphasis_zh_TW": { + "size": 0.7, + "weight": 700, + "family": "Noto Sans" + } + }, + + "base_colors": { + "background_1": [255, 255, 255, 255], + "background_2": [243, 243, 243, 255], + "background_3": [232, 240, 253, 255], + "background_4": [3, 12, 66, 255], + + "accent_1": [25, 110, 240, 255], + "accent_2": [16, 70, 156, 255], + "border_main": [212, 212, 212, 255], + "border_accent_1": [25, 110, 240, 255], + "border_accent_2": [16, 70, 156, 255], + "border_field": [180, 180, 180, 255], + + "text_default": [0, 14, 26, 255], + "text_disabled": [180, 180, 180, 255], + "text_primary_button": [255, 255, 255, 255], + "text_secondary_button": [25, 110, 240, 255], + "text_link_hover": [16, 70, 156, 255], + "text_lighter": [108, 108, 108, 255], + + "um_green_1": [233, 245, 237, 255], + "um_green_5": [36, 162, 73, 255], + "um_green_9": [31, 44, 36, 255], + "um_red_1": [251, 232, 233, 255], + "um_red_5": [218, 30, 40, 255], + "um_red_9": [59, 31, 33, 255], + "um_orange_1": [255, 235, 221, 255], + "um_orange_5": [252, 123, 30, 255], + "um_orange_9": [64, 45, 32, 255], + "um_yellow_1": [255, 248, 225, 255], + "um_yellow_5": [253, 209, 58, 255], + "um_yellow_9": [64, 58, 36, 255] + }, + + "colors": { + + "main_background": "background_1", + "detail_background": "background_2", + "wide_lining": [245, 245, 245, 255], + "thick_lining": [180, 180, 180, 255], + "lining": [192, 193, 194, 255], + "viewport_overlay": [246, 246, 246, 255], + + "primary": "accent_1", + "primary_hover": [48, 182, 231, 255], + "primary_text": [255, 255, 255, 255], + "text_selection": [156, 195, 255, 127], + "border": [127, 127, 127, 255], + "border_field": [180, 180, 180, 255], + "secondary": [240, 240, 240, 255], + + "expandable_active": [240, 240, 240, 255], + "expandable_hover": [232, 242, 252, 255], + + "icon": [8, 7, 63, 255], + + "primary_button": "accent_1", + "primary_button_hover": [16, 70, 156, 255], + "primary_button_text": [255, 255, 255, 255], + + "secondary_button": "background_1", + "secondary_button_shadow": [216, 216, 216, 255], + "secondary_button_hover": [232, 240, 253, 255], + "secondary_button_text": "accent_1", + + "main_window_header_background": [8, 7, 63, 255], + "main_window_header_background_gradient": [25, 23, 91, 255], + "main_window_header_button_text_active": [8, 7, 63, 255], + "main_window_header_button_text_inactive": [255, 255, 255, 255], + "main_window_header_button_text_hovered": [255, 255, 255, 255], + "main_window_header_button_background_active": [255, 255, 255, 255], + "main_window_header_button_background_inactive": [255, 255, 255, 0], + "main_window_header_button_background_hovered": [117, 114, 159, 255], + + "account_widget_outline_active": [70, 66, 126, 255], + "account_sync_state_icon": [25, 25, 25, 255], + + "machine_selector_printer_icon": [8, 7, 63, 255], + + "action_panel_secondary": "accent_1", + + "first_run_shadow": [50, 50, 50, 255], + + "toolbar_background": [255, 255, 255, 255], + + "notification_icon": [255, 0, 0, 255], + + "printer_type_label_background": [228, 228, 242, 255], + + "window_disabled_background": [0, 0, 0, 255], + + "text": [25, 25, 25, 255], + "text_disabled": [180, 180, 180, 255], + "text_detail": [174, 174, 174, 128], + "text_link": "accent_1", + "text_inactive": [174, 174, 174, 255], + "text_medium": [128, 128, 128, 255], + "text_scene": [102, 102, 102, 255], + "text_scene_hover": [123, 123, 113, 255], + + "error": [218, 30, 40, 255], + "warning": [253, 209, 58, 255], + "success": [36, 162, 73, 255], + "disabled": [229, 229, 229, 255], + + "toolbar_button_hover": [232, 242, 252, 255], + "toolbar_button_active": [232, 242, 252, 255], + "toolbar_button_active_hover": [232, 242, 252, 255], + + "button_text": [255, 255, 255, 255], + + "small_button_text": [102, 102, 102, 255], + "small_button_text_hover": [8, 7, 63, 255], + + "button_tooltip": [31, 36, 39, 255], + + "extruder_disabled": [255, 255, 255, 102], + + "action_button": [255, 255, 255, 255], + "action_button_hovered": [232, 242, 252, 255], + "action_button_disabled": [245, 245, 245, 255], + "action_button_disabled_text": [196, 196, 196, 255], + "action_button_shadow": [223, 223, 223, 255], + + "scrollbar_background": [255, 255, 255, 255], + "scrollbar_handle": [10, 8, 80, 255], + "scrollbar_handle_hover": [50, 130, 255, 255], + "scrollbar_handle_down": [50, 130, 255, 255], + + "setting_category": "background_1", + "setting_category_disabled": [255, 255, 255, 255], + "setting_category_hover": "background_2", + "setting_category_text": "text_default", + "setting_category_disabled_text": [24, 41, 77, 101], + "setting_category_active_text": "text_default", + + "setting_control": "background_2", + "setting_control_highlight": "background_3", + "setting_control_border": [199, 199, 199, 255], + "setting_control_border_highlight": [50, 130, 255, 255], + "setting_control_text": [35, 35, 35, 255], + "setting_control_button": [102, 102, 102, 255], + "setting_control_button_hover": [8, 7, 63, 255], + "setting_control_disabled": "background_2", + "setting_control_disabled_text": [127, 127, 127, 255], + "setting_control_disabled_border": [127, 127, 127, 255], + "setting_unit": [127, 127, 127, 255], + "setting_validation_error_background": "um_red_1", + "setting_validation_error": "um_red_5", + "setting_validation_warning_background": "um_yellow_1", + "setting_validation_warning": "um_yellow_5", + "setting_validation_ok": "background_2", + + "material_compatibility_warning": [243, 166, 59, 255], + + "progressbar_background": [245, 245, 245, 255], + "progressbar_control": [50, 130, 255, 255], + + "slider_groove": [223, 223, 223, 255], + "slider_groove_fill": [8, 7, 63, 255], + "slider_handle": [8, 7, 63, 255], + "slider_handle_active": [50, 130, 255, 255], + "slider_text_background": [255, 255, 255, 255], + + "quality_slider_unavailable": [179, 179, 179, 255], + "quality_slider_available": [0, 0, 0, 255], + + "checkbox": "background_1", + "checkbox_hover": "background_1", + "checkbox_disabled": "background_2", + "checkbox_border": [180, 180, 180, 255], + "checkbox_border_hover": "border_main", + "checkbox_border_disabled": "text_disabled", + "checkbox_mark": "text_default", + "checkbox_mark_disabled": "text_disabled", + "checkbox_square": [180, 180, 180, 255], + "checkbox_text": "text_default", + "checkbox_text_disabled": "text_disabled", + + "switch": "background_1", + "switch_state_checked": "accent_1", + "switch_state_unchecked": "text_disabled", + + "radio": "background_1", + "radio_disabled": "background_2", + "radio_selected": "accent_1", + "radio_selected_disabled": "text_disabled", + "radio_border": [180, 180, 180, 255], + "radio_border_hover": "border_main", + "radio_border_disabled": "text_disabled", + "radio_dot": "background_1", + "radio_dot_disabled": "background_2", + "radio_text": "text_default", + "radio_text_disabled": "text_disabled", + + "text_field": "background_1", + "text_field_border": [180, 180, 180, 255], + "text_field_border_hovered": "border_main", + "text_field_border_active": "border_accent_2", + "text_field_border_disabled": "background_2", + "text_field_text": "text_default", + "text_field_text_disabled": "text_disabled", + + "category_background": "background_2", + + "tooltip": [25, 25, 25, 255], + "tooltip_text": [255, 255, 255, 255], + + "message_background": [255, 255, 255, 255], + "message_border": [192, 193, 194, 255], + "message_close": [102, 102, 102, 255], + "message_close_hover": [8, 7, 63, 255], + "message_progressbar_background": [245, 245, 245, 255], + "message_progressbar_control": [50, 130, 255, 255], + "message_success_icon": [255, 255, 255, 255], + "message_warning_icon": [0, 0, 0, 255], + "message_error_icon": [255, 255, 255, 255], + + "tool_panel_background": [255, 255, 255, 255], + + "status_offline": [0, 0, 0, 255], + "status_ready": [0, 205, 0, 255], + "status_busy": [50, 130, 255, 255], + "status_paused": [255, 140, 0, 255], + "status_stopped": [236, 82, 80, 255], + + "disabled_axis": [127, 127, 127, 255], + "x_axis": [218, 30, 40, 255], + "y_axis": [25, 110, 240, 255], + "z_axis": [36, 162, 73, 255], + "all_axis": [255, 255, 255, 255], + + "viewport_background": [250, 250, 250, 255], + "volume_outline": [50, 130, 255, 255], + "buildplate": [244, 244, 244, 255], + "buildplate_grid": [180, 180, 180, 255], + "buildplate_grid_minor": [228, 228, 228, 255], + + "convex_hull": [35, 35, 35, 127], + "disallowed_area": [0, 0, 0, 40], + "error_area": [255, 0, 0, 127], + + "model_overhang": [255, 0, 0, 255], + "model_unslicable": [122, 122, 122, 255], + "model_unslicable_alt": [172, 172, 127, 255], + "model_selection_outline": [50, 130, 255, 255], + "model_non_printing": [122, 122, 122, 255], + + "xray": [26, 26, 62, 255], + + "layerview_ghost": [31, 31, 31, 95], + "layerview_none": [255, 255, 255, 255], + "layerview_inset_0": [230, 0, 0, 255], + "layerview_inset_x": [0, 230, 0, 255], + "layerview_skin": [230, 230, 0, 255], + "layerview_support": [0, 230, 230, 127], + "layerview_skirt": [0, 230, 230, 255], + "layerview_infill": [230, 115, 0, 255], + "layerview_support_infill": [0, 230, 230, 127], + "layerview_move_combing": [0, 0, 255, 255], + "layerview_move_retraction": [128, 127, 255, 255], + "layerview_support_interface": [63, 127, 255, 127], + "layerview_prime_tower": [0, 255, 255, 255], + "layerview_nozzle": [224, 192, 16, 64], + "layerview_starts": [255, 255, 255, 255], + + + "monitor_printer_family_tag": [228, 228, 242, 255], + "monitor_text_disabled": [238, 238, 238, 255], + "monitor_icon_primary": [10, 8, 80, 255], + "monitor_icon_accent": [255, 255, 255, 255], + "monitor_icon_disabled": [238, 238, 238, 255], + + "monitor_card_border": [192, 193, 194, 255], + "monitor_card_background": [255, 255, 255, 255], + "monitor_card_hover": [232, 242, 252, 255], + + "monitor_stage_background": [246, 246, 246, 255], + "monitor_stage_background_fade": [246, 246, 246, 102], + + "monitor_tooltip": [25, 25, 25, 255], + "monitor_tooltip_text": [255, 255, 255, 255], + "monitor_context_menu": [255, 255, 255, 255], + "monitor_context_menu_hover": [245, 245, 245, 255], + + "monitor_skeleton_loading": [238, 238, 238, 255], + "monitor_placeholder_image": [230, 230, 230, 255], + "monitor_image_overlay": [0, 0, 0, 255], + "monitor_shadow": [200, 200, 200, 255], + + "monitor_carousel_dot": [216, 216, 216, 255], + "monitor_carousel_dot_current": [119, 119, 119, 255], + + "cloud_unavailable": [153, 153, 153, 255], + "connection_badge_background": [255, 255, 255, 255], + "warning_badge_background": [0, 0, 0, 255], + "error_badge_background": [255, 255, 255, 255], + + "border_field_light": [180, 180, 180, 255], + "border_main_light": [212, 212, 212, 255] + }, + + "sizes": { + "window_minimum_size": [80, 48], + "popup_dialog": [40, 36], + "small_popup_dialog": [36, 12], + + "main_window_header": [0.0, 4.0], + + "stage_menu": [0.0, 4.0], + + "account_button": [12, 2.5], + + "print_setup_widget": [38.0, 30.0], + "print_setup_extruder_box": [0.0, 6.0], + "slider_widget_groove": [0.16, 0.16], + "slider_widget_handle": [1.3, 1.3], + "slider_widget_tickmarks": [0.5, 0.5], + "print_setup_big_item": [28, 2.5], + "print_setup_icon": [1.2, 1.2], + "drag_icon": [1.416, 0.25], + + "application_switcher_item": [8, 9], + "application_switcher_icon": [3.75, 3.75], + + "expandable_component_content_header": [0.0, 3.0], + + "configuration_selector": [35.0, 4.0], + + "action_panel_widget": [26.0, 0.0], + "action_panel_information_widget": [20.0, 0.0], + + "machine_selector_widget": [20.0, 4.0], + "machine_selector_widget_content": [25.0, 32.0], + "machine_selector_icon": [2.5, 2.5], + + "views_selector": [16.0, 4.0], + + "printer_type_label": [3.5, 1.5], + + "default_radius": [0.25, 0.25], + + "wide_lining": [0.5, 0.5], + "thick_lining": [0.2, 0.2], + "default_lining": [0.08, 0.08], + + "default_arrow": [0.8, 0.8], + "logo": [16, 2], + + "wide_margin": [2.0, 2.0], + "thick_margin": [1.71, 1.43], + "default_margin": [1.0, 1.0], + "thin_margin": [0.71, 0.71], + "narrow_margin": [0.5, 0.5], + + "extruder_icon": [2.5, 2.5], + + "section": [0.0, 2], + "section_header": [0.0, 2.5], + + "section_control": [0, 1], + "section_icon": [1.5, 1.5], + "section_icon_column": [2.5, 2.5], + + "setting": [25.0, 1.8], + "setting_control": [11.0, 2.0], + "setting_control_radius": [0.15, 0.15], + "setting_control_depth_margin": [1.4, 0.0], + "setting_unit_margin": [0.5, 0.5], + + "standard_list_lineheight": [1.5, 1.5], + "standard_arrow": [1.0, 1.0], + + "card": [25.0, 10], + "card_icon": [6.0, 6.0], + "card_tiny_icon": [1.5, 1.5], + + "button": [4, 4], + "button_icon": [2.5, 2.5], + + "action_button": [15.0, 2.5], + "action_button_icon": [1.5, 1.5], + "action_button_icon_small": [1.0, 1.0], + "action_button_radius": [0.15, 0.15], + + "radio_button": [1.3, 1.3], + + "small_button": [2, 2], + "small_button_icon": [1.5, 1.5], + + "medium_button": [2.5, 2.5], + "medium_button_icon": [2, 2], + + "large_button": [3.0, 3.0], + "large_button_icon": [2.8, 2.8], + + "context_menu": [20, 2], + + "icon_indicator": [1, 1], + + "printer_status_icon": [1.0, 1.0], + + "button_tooltip": [1.0, 1.3], + "button_tooltip_arrow": [0.25, 0.25], + + "progressbar": [26.0, 0.75], + "progressbar_radius": [0.15, 0.15], + + "scrollbar": [0.75, 0.5], + + "slider_groove": [0.5, 0.5], + "slider_groove_radius": [0.15, 0.15], + "slider_handle": [1.5, 1.5], + "slider_layerview_size": [1.0, 34.0], + + "layerview_menu_size": [16.0, 4.0], + "layerview_legend_size": [1.0, 1.0], + "layerview_row": [11.0, 1.5], + "layerview_row_spacing": [0.0, 0.5], + + "checkbox": [1.33, 1.33], + "checkbox_mark": [1, 1], + "checkbox_radius": [0.25, 0.25], + + "spinbox": [6.0, 3.0], + "combobox": [14, 2], + "combobox_wide": [22, 2], + + "tooltip": [20.0, 10.0], + "tooltip_margins": [1.0, 1.0], + "tooltip_arrow_margins": [2.0, 2.0], + + "save_button_save_to_button": [0.3, 2.7], + "save_button_specs_icons": [1.4, 1.4], + + "first_run_shadow_radius": [1.2, 1.2], + + "monitor_preheat_temperature_control": [4.5, 2.0], + + "welcome_wizard_window": [46, 50], + "modal_window_minimum": [60.0, 45], + "wizard_progress": [10.0, 0.0], + + "message": [30.0, 5.0], + "message_close": [1, 1], + "message_radius": [0.25, 0.25], + "message_action_button": [0, 2.5], + "message_image": [15.0, 10.0], + "message_type_icon": [2, 2], + "menu": [18, 2], + + "jobspecs_line": [2.0, 2.0], + + "objects_menu_size": [15, 15], + + "notification_icon": [1.5, 1.5], + + "avatar_image": [6.8, 6.8], + + "monitor_shadow_radius": [0.4, 0.4], + "monitor_empty_state_offset": [5.6, 5.6], + "monitor_empty_state_size": [35.0, 25.0], + "monitor_column": [18.0, 1.0], + "monitor_progress_bar": [16.5, 1.0], + + "table_row": [2.0, 2.0], + + "welcome_wizard_content_image_big": [18, 15], + "welcome_wizard_cloud_content_image": [4, 4], + + "banner_icon_size": [2.0, 2.0], + + "marketplace_large_icon": [4.0, 4.0], + + "preferences_page_list_item": [8.0, 2.0], + + "recommended_button_icon": [1.7, 1.7], + + "recommended_section_setting_item": [14.0, 2.0], + + "reset_profile_icon": [1, 1] + } +} diff --git a/resources/themes/daily_test_colors.json b/resources/themes/daily_test_colors.json new file mode 100644 index 0000000000..1cfa2baa74 --- /dev/null +++ b/resources/themes/daily_test_colors.json @@ -0,0 +1,16 @@ +[ + [ 62, 33, 55, 255], + [126, 196, 193, 255], + [126, 196, 193, 255], + [215, 155, 125, 255], + [228, 148, 58, 255], + [192, 199, 65, 255], + [157, 48, 59, 255], + [140, 143, 174, 255], + [ 23, 67, 75, 255], + [ 23, 67, 75, 255], + [154, 99, 72, 255], + [112, 55, 127, 255], + [100, 125, 52, 255], + [210, 100, 113, 255] +] From 851d472aafe6395c87c07e73e7cf6d2809ec0e8e Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 17 Jun 2025 10:12:52 +0200 Subject: [PATCH 186/299] Restore original themes --- resources/themes/cura-dark/theme.json | 8 ++++---- resources/themes/cura-light/theme.json | 13 ++++++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/resources/themes/cura-dark/theme.json b/resources/themes/cura-dark/theme.json index 64c3e002a9..1517b22eb9 100644 --- a/resources/themes/cura-dark/theme.json +++ b/resources/themes/cura-dark/theme.json @@ -56,7 +56,7 @@ "secondary_button": "background_1", "secondary_button_hover": "background_3", - "secondary_button_text": [255, 255, 255, 255], + "secondary_button_text": "text_secondary_button", "icon": "text_default", "toolbar_background": "background_1", @@ -69,9 +69,7 @@ "main_window_header_button_text_active": "background_4", "main_window_header_background": "background_4", "main_window_header_background_gradient": "background_4", - "main_window_header_button_background_hovered": [46, 46, 46, 255], - - "secondary_button_text": "text_secondary_button", + "main_window_header_button_background_hovered": [46, 46, 46, 255], "account_sync_state_icon": [255, 255, 255, 204], @@ -179,6 +177,8 @@ "material_compatibility_warning": [255, 255, 255, 255], + "core_compatibility_warning": [255, 255, 255, 255], + "quality_slider_available": [255, 255, 255, 255], "monitor_printer_family_tag": [86, 86, 106, 255], diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 8f3f9076c5..1ae316f96c 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -110,6 +110,12 @@ "italic": true, "family": "Noto Sans" }, + "medium_italic": { + "size": 1.16, + "weight": 400, + "italic": true, + "family": "Noto Sans" + }, "default_italic_ja_JP": { "size": 1.0, "weight": 400, @@ -349,6 +355,7 @@ "setting_validation_ok": "background_2", "material_compatibility_warning": [243, 166, 59, 255], + "core_compatibility_warning": [243, 166, 59, 255], "progressbar_background": [245, 245, 245, 255], "progressbar_control": [50, 130, 255, 255], @@ -560,7 +567,7 @@ "section_icon_column": [2.5, 2.5], "setting": [25.0, 1.8], - "setting_control": [11.0, 2.0], + "setting_control": [9.0, 2.0], "setting_control_radius": [0.15, 0.15], "setting_control_depth_margin": [1.4, 0.0], "setting_unit_margin": [0.5, 0.5], @@ -635,11 +642,11 @@ "monitor_preheat_temperature_control": [4.5, 2.0], "welcome_wizard_window": [46, 50], - "modal_window_minimum": [60.0, 45], + "modal_window_minimum": [60.0, 50.0], "wizard_progress": [10.0, 0.0], "message": [30.0, 5.0], - "message_close": [1, 1], + "message_close": [2, 2], "message_radius": [0.25, 0.25], "message_action_button": [0, 2.5], "message_image": [15.0, 10.0], From 6713ec3d7397bb22629ecfcd34ce0cf74403f6d4 Mon Sep 17 00:00:00 2001 From: Frederic Meeuwissen <13856291+Frederic98@users.noreply.github.com> Date: Tue, 17 Jun 2025 13:29:29 +0200 Subject: [PATCH 187/299] [PP-605] Add missing machine_nozzle_size to S6 BB04 --- resources/variants/ultimaker_s6_bb04.inst.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/variants/ultimaker_s6_bb04.inst.cfg b/resources/variants/ultimaker_s6_bb04.inst.cfg index 756d6fd1d4..e0c62d9596 100644 --- a/resources/variants/ultimaker_s6_bb04.inst.cfg +++ b/resources/variants/ultimaker_s6_bb04.inst.cfg @@ -11,6 +11,7 @@ type = variant [values] machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = BB 0.4 +machine_nozzle_size = 0.4 machine_nozzle_tip_outer_diameter = 1.0 retraction_amount = 4.5 support_bottom_height = =layer_height * 2 From 265599a52ded3724c4d0656276156841ed200daa Mon Sep 17 00:00:00 2001 From: Sam Bonnekamp Date: Wed, 18 Jun 2025 01:31:17 +0800 Subject: [PATCH 188/299] add Anycubic kobra 3 v2 (and ace pro) profiles --- .../definitions/anycubic_kobra3v2.def.json | 52 +++++++++++++ .../anycubic_kobra3v2_ACE_PRO.def.json | 69 ++++++++++++++++++ ...ycubic_kobra3v2_ACEPRO_extruder_0.def.json | 16 ++++ ...ycubic_kobra3v2_ACEPRO_extruder_1.def.json | 16 ++++ ...ycubic_kobra3v2_ACEPRO_extruder_2.def.json | 16 ++++ ...ycubic_kobra3v2_ACEPRO_extruder_3.def.json | 16 ++++ .../anycubic_kobra3v2_extruder_0.def.json | 16 ++++ .../meshes/anycubic_kobra3v2_buildplate.stl | Bin 0 -> 4284 bytes 8 files changed, 201 insertions(+) create mode 100644 resources/definitions/anycubic_kobra3v2.def.json create mode 100644 resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json create mode 100644 resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json create mode 100644 resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json create mode 100644 resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json create mode 100644 resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json create mode 100644 resources/extruders/anycubic_kobra3v2_extruder_0.def.json create mode 100644 resources/meshes/anycubic_kobra3v2_buildplate.stl diff --git a/resources/definitions/anycubic_kobra3v2.def.json b/resources/definitions/anycubic_kobra3v2.def.json new file mode 100644 index 0000000000..59afb1c660 --- /dev/null +++ b/resources/definitions/anycubic_kobra3v2.def.json @@ -0,0 +1,52 @@ +{ + "version": 2, + "name": "Anycubic Kobra 3 v2", + "inherits": "fdmprinter", + "metadata": + { + "visible": true, + "author": "Sam Bonnekamp", + "manufacturer": "Anycubic", + "file_formats": "text/x-gcode", + "platform": "anycubic_kobra3v2_buildplate.STL", + "machine_extruder_trains": { "0": "anycubic_kobra3v2_extruder_0" } + }, + "overrides": + { + "machine_height": { "default_value": 260 }, + "machine_width": { "default_value": 250 }, + "machine_depth": { "default_value": 250 }, + "machine_name": + { + "description": "Anycubic Kobra 3 v2", + "default_value": "Anycubic Kobra 3 v2" + }, + "machine_buildplate_type": { "default_value": "PEI Spring Steel" }, + "machine_heated_bed": { "default_value": true}, + "material_bed_temperature": + { + "default_value": 60, + "maximum_value": "110", + "maximum_value_warning": "90" + }, + "material_print_temp_wait": { "value": true }, + "machine_center_is_zero": { "default_value": false }, + "layer_height": { "default_value": 0.2 }, + "speed_slowdown_layers": { "value": 2 }, + "material_diameter": { "default_value": 1.75 }, + "material_initial_print_temperature": + { + "maximum_value_warning": 295, + "value": "material_print_temperature + 5" + }, + "material_print_temperature": { "maximum_value_warning": 250 }, + "material_print_temperature_layer_0": + { + "maximum_value_warning": 295, + "value": "material_print_temperature + 5" + }, + "material_print_temp_prep": { "default_value": false }, + "machine_start_gcode_first": { "default_value": true }, + "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\nTYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" } + } +} diff --git a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json new file mode 100644 index 0000000000..ab2f9a3b95 --- /dev/null +++ b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json @@ -0,0 +1,69 @@ +{ + "version": 2, + "name": "Anycubic Kobra 3 v2 ACE PRO", + "inherits": "fdmprinter", + "metadata": + { + "visible": true, + "author": "Sam Bonnekamp", + "manufacturer": "Anycubic", + "file_formats": "text/x-gcode", + "platform": "anycubic_kobra3v2_buildplate.STL", + "machine_extruder_trains": { + "0": "anycubic_kobra3v2_ACEPRO_extruder_0", + "1": "anycubic_kobra3v2_ACEPRO_extruder_1", + "2": "anycubic_kobra3v2_ACEPRO_extruder_2", + "3": "anycubic_kobra3v2_ACEPRO_extruder_3" + } + }, + "overrides": + { + "machine_height": { "default_value": 260 }, + "machine_width": { "default_value": 250 }, + "machine_depth": { "default_value": 250 }, + "machine_name": + { + "description": "Anycubic Kobra 3 v2", + "default_value": "Anycubic Kobra 3 v2" + }, + "machine_extruder_count": { "default_value": 4 }, + "machine_buildplate_type": { "default_value": "PEI Spring Steel" }, + "machine_heated_bed": { "default_value": true}, + "material_bed_temperature": + { + "default_value": 60, + "maximum_value": "110", + "maximum_value_warning": "90" + }, + "material_print_temp_wait": { "value": true }, + "machine_center_is_zero": { "default_value": false }, + "layer_height": { "default_value": 0.2 }, + "speed_slowdown_layers": { "value": 2 }, + "material_diameter": { "default_value": 1.75 }, + "material_initial_print_temperature": + { + "maximum_value_warning": 295, + "value": "material_print_temperature + 5" + }, + "default_material_print_temperature": + { + "maximum_value": 300, + "default_value": 200 + }, + "material_print_temperature": + { + "maximum_value": 300, + "default_value": 200 + }, + "material_standby_temperature" : {"default_value": "material_print_temperature"}, + "material_print_temperature_layer_0": + { + "maximum_value_warning": 295, + "value": "material_print_temperature + 5" + }, + "material_print_temp_prep": { "default_value": false }, + "machine_start_gcode_first": { "default_value": true }, + "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\nTYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, + "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\n;Retract the filament\nG92 E1\nG1 E-1 F300\nG27 P2 ;Park toolhead\nM84" } + } +} diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json new file mode 100644 index 0000000000..93c8618bf4 --- /dev/null +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "ACE Pro Colour 1", + "inherits": "fdmextruder", + "metadata": + { + "machine": "anycubic_kobra3v2_ACE_PRO", + "position": "0" + }, + "overrides": + { + "extruder_nr": { "default_value": 0 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json new file mode 100644 index 0000000000..ed41ca1946 --- /dev/null +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "ACE Pro Colour 2", + "inherits": "fdmextruder", + "metadata": + { + "machine": "anycubic_kobra3v2_ACE_PRO", + "position": "1" + }, + "overrides": + { + "extruder_nr": { "default_value": 1 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json new file mode 100644 index 0000000000..2fc2705ebb --- /dev/null +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "ACE Pro Colour 3", + "inherits": "fdmextruder", + "metadata": + { + "machine": "anycubic_kobra3v2_ACE_PRO", + "position": "1" + }, + "overrides": + { + "extruder_nr": { "default_value": 2 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json new file mode 100644 index 0000000000..f5ef25efc5 --- /dev/null +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "ACE Pro Colour 4", + "inherits": "fdmextruder", + "metadata": + { + "machine": "anycubic_kobra3v2_ACE_PRO", + "position": "3" + }, + "overrides": + { + "extruder_nr": { "default_value": 3 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} diff --git a/resources/extruders/anycubic_kobra3v2_extruder_0.def.json b/resources/extruders/anycubic_kobra3v2_extruder_0.def.json new file mode 100644 index 0000000000..dba5e6e559 --- /dev/null +++ b/resources/extruders/anycubic_kobra3v2_extruder_0.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": + { + "machine": "anycubic_kobra3v2", + "position": "0" + }, + "overrides": + { + "extruder_nr": { "default_value": 0 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} diff --git a/resources/meshes/anycubic_kobra3v2_buildplate.stl b/resources/meshes/anycubic_kobra3v2_buildplate.stl new file mode 100644 index 0000000000000000000000000000000000000000..9d526d0edada625da668ad41379a2d299965b68b GIT binary patch literal 4284 zcmbW4KWmgh5XKihvCvA;I-OXG1nl1P{03q#F|h~+Jx~j+_G{Qks^AAmeRqkCpFu$o zY;24m_$Q6d^Ugju&+gqT;=<+TotfXx&g|^ImnV<+c6TB#zWwbf}<$2iC)MBt!q!EMqVFDHY57x#m7U#p@&J*WudNx-56W$1k{k3-vU z#vqLt)YCumP>T|jL0C`COJCX3%wljqNFxUI!vri!P=?+I^FR)a!FdsbdiqBmYEgo+ z%wJ#-=iihwDDkKlBD<^>#v54G+=+`#49270z3?|T1ayqY7@#qJ*nWJqk3YRd{~UWB zoEHT3FAjzXSd^d)y$`Mm^D_qLMGWfcA9<)n3Ci{ScmlyaC(Rhp`{-AcT_%C2mcVm8 zKr;Gx@oN9WK;41@!J5>><(C&G*DsAq_tXS$nSSjP_SpN6S53yMppStVvCntj-CWK) zOsJ(LuD$+U$H>?dB_PvlI1jZbvGe)La)prvVkl92MGb30tE+_OG)&Z9QNxyCm!R%5 ztIfI|3#Q)>^Wsh^!FSY}9TY;nqTeEdpAoevq1_Wq-Mji$tNU1q+7k0>FD(7Duc~^J z+4*3tf?g6PU{z}2dkOX7`(w3MN~qUgc5uQ|RL{%z$7&3nOTD0HPDsE$Hh2bUQDRmT z4)nju*ws)mUP{rG#Z?Gq3l(eC%SXPd;#$6P7bhyEI3Fp+4z`3^TEfq~5ZN;CbnPyq z3K-1XpZFJqT39RCqYCuKcN;?qtw=B}pq#n1~Lze z5^*cJr@OaA?WGk73NgZ>gr0)%_ZUIcUjNd&Ns^O6kP@H~3lp$I-Q~ zuN7{%^~89gM9Ae%%(kLAmZfXgc%hG5v?t`2(ceBP1q}kfL%)|iB6@vCg?^YAFJdK1 zgZO0gpFQWlceSG0yP+Q@#tS7vF2uaV$huQ8uiotqA-BHg!OjR8gpKSSQs3tquU=Kp O^gX4-c%ekdi17zYNr Date: Wed, 18 Jun 2025 02:39:22 +0800 Subject: [PATCH 189/299] removed redudant fields --- .../definitions/anycubic_kobra3v2.def.json | 18 +++++++++++++----- .../anycubic_kobra3v2_ACE_PRO.def.json | 6 ++---- ...nycubic_kobra3v2_ACEPRO_extruder_2.def.json | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/resources/definitions/anycubic_kobra3v2.def.json b/resources/definitions/anycubic_kobra3v2.def.json index 59afb1c660..ec37f3174a 100644 --- a/resources/definitions/anycubic_kobra3v2.def.json +++ b/resources/definitions/anycubic_kobra3v2.def.json @@ -20,15 +20,24 @@ { "description": "Anycubic Kobra 3 v2", "default_value": "Anycubic Kobra 3 v2" - }, + }, "machine_buildplate_type": { "default_value": "PEI Spring Steel" }, "machine_heated_bed": { "default_value": true}, + "material_bed_temperature": - { - "default_value": 60, - "maximum_value": "110", + { "maximum_value": "110", "maximum_value_warning": "90" }, + "default_material_print_temperature": + { + "maximum_value": 300, + "default_value": 210 + }, + "material_print_temperature": + { + "maximum_value": 300, + "default_value": 210 + }, "material_print_temp_wait": { "value": true }, "machine_center_is_zero": { "default_value": false }, "layer_height": { "default_value": 0.2 }, @@ -45,7 +54,6 @@ "maximum_value_warning": 295, "value": "material_print_temperature + 5" }, - "material_print_temp_prep": { "default_value": false }, "machine_start_gcode_first": { "default_value": true }, "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\nTYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" } } diff --git a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json index ab2f9a3b95..a201ab32f4 100644 --- a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json +++ b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json @@ -31,7 +31,6 @@ "machine_heated_bed": { "default_value": true}, "material_bed_temperature": { - "default_value": 60, "maximum_value": "110", "maximum_value_warning": "90" }, @@ -48,12 +47,12 @@ "default_material_print_temperature": { "maximum_value": 300, - "default_value": 200 + "default_value": 210 }, "material_print_temperature": { "maximum_value": 300, - "default_value": 200 + "default_value": 210 }, "material_standby_temperature" : {"default_value": "material_print_temperature"}, "material_print_temperature_layer_0": @@ -61,7 +60,6 @@ "maximum_value_warning": 295, "value": "material_print_temperature + 5" }, - "material_print_temp_prep": { "default_value": false }, "machine_start_gcode_first": { "default_value": true }, "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\nTYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\n;Retract the filament\nG92 E1\nG1 E-1 F300\nG27 P2 ;Park toolhead\nM84" } diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json index 2fc2705ebb..2761e3d08e 100644 --- a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json @@ -5,7 +5,7 @@ "metadata": { "machine": "anycubic_kobra3v2_ACE_PRO", - "position": "1" + "position": "2" }, "overrides": { From c5550695d664678ab6cafb8f85f4423a147e2b9a Mon Sep 17 00:00:00 2001 From: Sam Bonnekamp Date: Wed, 18 Jun 2025 12:39:29 +0800 Subject: [PATCH 190/299] removed redundant directives, removed colonialism --- resources/definitions/anycubic_kobra3v2.def.json | 15 ++------------- .../anycubic_kobra3v2_ACE_PRO.def.json | 16 +++------------- .../anycubic_kobra3v2_ACEPRO_extruder_0.def.json | 4 ++-- .../anycubic_kobra3v2_ACEPRO_extruder_1.def.json | 4 ++-- .../anycubic_kobra3v2_ACEPRO_extruder_2.def.json | 2 +- .../anycubic_kobra3v2_ACEPRO_extruder_3.def.json | 4 ++-- .../anycubic_kobra3v2_extruder_0.def.json | 2 +- 7 files changed, 13 insertions(+), 34 deletions(-) diff --git a/resources/definitions/anycubic_kobra3v2.def.json b/resources/definitions/anycubic_kobra3v2.def.json index ec37f3174a..8c24b1391c 100644 --- a/resources/definitions/anycubic_kobra3v2.def.json +++ b/resources/definitions/anycubic_kobra3v2.def.json @@ -8,7 +8,7 @@ "author": "Sam Bonnekamp", "manufacturer": "Anycubic", "file_formats": "text/x-gcode", - "platform": "anycubic_kobra3v2_buildplate.STL", + "platform": "anycubic_kobra3v2_buildplate.stl", "machine_extruder_trains": { "0": "anycubic_kobra3v2_extruder_0" } }, "overrides": @@ -27,21 +27,10 @@ "material_bed_temperature": { "maximum_value": "110", "maximum_value_warning": "90" - }, - "default_material_print_temperature": - { - "maximum_value": 300, - "default_value": 210 }, - "material_print_temperature": - { - "maximum_value": 300, - "default_value": 210 - }, - "material_print_temp_wait": { "value": true }, + "material_print_temperature":{ "maximum_value": 300 }, "machine_center_is_zero": { "default_value": false }, "layer_height": { "default_value": 0.2 }, - "speed_slowdown_layers": { "value": 2 }, "material_diameter": { "default_value": 1.75 }, "material_initial_print_temperature": { diff --git a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json index a201ab32f4..6b9c65e59a 100644 --- a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json +++ b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json @@ -8,7 +8,7 @@ "author": "Sam Bonnekamp", "manufacturer": "Anycubic", "file_formats": "text/x-gcode", - "platform": "anycubic_kobra3v2_buildplate.STL", + "platform": "anycubic_kobra3v2_buildplate.stl", "machine_extruder_trains": { "0": "anycubic_kobra3v2_ACEPRO_extruder_0", "1": "anycubic_kobra3v2_ACEPRO_extruder_1", @@ -37,23 +37,13 @@ "material_print_temp_wait": { "value": true }, "machine_center_is_zero": { "default_value": false }, "layer_height": { "default_value": 0.2 }, - "speed_slowdown_layers": { "value": 2 }, "material_diameter": { "default_value": 1.75 }, "material_initial_print_temperature": { "maximum_value_warning": 295, "value": "material_print_temperature + 5" - }, - "default_material_print_temperature": - { - "maximum_value": 300, - "default_value": 210 - }, - "material_print_temperature": - { - "maximum_value": 300, - "default_value": 210 - }, + }, + "material_print_temperature": { "maximum_value": 300 }, "material_standby_temperature" : {"default_value": "material_print_temperature"}, "material_print_temperature_layer_0": { diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json index 93c8618bf4..104d6bb0f1 100644 --- a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json @@ -1,10 +1,10 @@ { "version": 2, - "name": "ACE Pro Colour 1", + "name": "ACE Pro Color 1", "inherits": "fdmextruder", "metadata": { - "machine": "anycubic_kobra3v2_ACE_PRO", + "machine": "kobra3v2_ACE_PRO", "position": "0" }, "overrides": diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json index ed41ca1946..2c3d072215 100644 --- a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json @@ -1,10 +1,10 @@ { "version": 2, - "name": "ACE Pro Colour 2", + "name": "ACE Pro Color 2", "inherits": "fdmextruder", "metadata": { - "machine": "anycubic_kobra3v2_ACE_PRO", + "machine": "kobra3v2_ACE_PRO", "position": "1" }, "overrides": diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json index 2761e3d08e..fb732d5fd4 100644 --- a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json @@ -1,6 +1,6 @@ { "version": 2, - "name": "ACE Pro Colour 3", + "name": "ACE Pro Color 3", "inherits": "fdmextruder", "metadata": { diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json index f5ef25efc5..fb64b590fc 100644 --- a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json @@ -1,10 +1,10 @@ { "version": 2, - "name": "ACE Pro Colour 4", + "name": "ACE Pro Color 4", "inherits": "fdmextruder", "metadata": { - "machine": "anycubic_kobra3v2_ACE_PRO", + "machine": "kobra3v2_ACE_PRO", "position": "3" }, "overrides": diff --git a/resources/extruders/anycubic_kobra3v2_extruder_0.def.json b/resources/extruders/anycubic_kobra3v2_extruder_0.def.json index dba5e6e559..d96e91ce07 100644 --- a/resources/extruders/anycubic_kobra3v2_extruder_0.def.json +++ b/resources/extruders/anycubic_kobra3v2_extruder_0.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "anycubic_kobra3v2", + "machine": "kobra3v2_ACE_PRO", "position": "0" }, "overrides": From bbe0b7f9f5a30adeb546f7501f5c2aba8e32ccc9 Mon Sep 17 00:00:00 2001 From: Sam Bonnekamp Date: Wed, 18 Jun 2025 13:14:53 +0800 Subject: [PATCH 191/299] missing comment semicolon --- resources/definitions/anycubic_kobra3v2.def.json | 2 +- resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/anycubic_kobra3v2.def.json b/resources/definitions/anycubic_kobra3v2.def.json index 8c24b1391c..8ca9800fde 100644 --- a/resources/definitions/anycubic_kobra3v2.def.json +++ b/resources/definitions/anycubic_kobra3v2.def.json @@ -44,6 +44,6 @@ "value": "material_print_temperature + 5" }, "machine_start_gcode_first": { "default_value": true }, - "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\nTYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" } + "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" } } } diff --git a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json index 6b9c65e59a..9686c4c192 100644 --- a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json +++ b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json @@ -51,7 +51,7 @@ "value": "material_print_temperature + 5" }, "machine_start_gcode_first": { "default_value": true }, - "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\nTYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, + "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\n;Retract the filament\nG92 E1\nG1 E-1 F300\nG27 P2 ;Park toolhead\nM84" } } } From bfbc6e4dc8269ca51e23e84af3072417f9e9015b Mon Sep 17 00:00:00 2001 From: Sam Bonnekamp Date: Wed, 18 Jun 2025 13:27:02 +0800 Subject: [PATCH 192/299] update printer names --- .../extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json | 2 +- .../extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json | 2 +- .../extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json | 2 +- resources/extruders/anycubic_kobra3v2_extruder_0.def.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json index 104d6bb0f1..ab4a7d1a68 100644 --- a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "kobra3v2_ACE_PRO", + "machine": "anycubic_kobra3v2_ACE_PRO", "position": "0" }, "overrides": diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json index 2c3d072215..029e7ad2bf 100644 --- a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "kobra3v2_ACE_PRO", + "machine": "anycubic_kobra3v2_ACE_PRO", "position": "1" }, "overrides": diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json index fb64b590fc..2f64b0532a 100644 --- a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "kobra3v2_ACE_PRO", + "machine": "anycubic_kobra3v2_ACE_PRO", "position": "3" }, "overrides": diff --git a/resources/extruders/anycubic_kobra3v2_extruder_0.def.json b/resources/extruders/anycubic_kobra3v2_extruder_0.def.json index d96e91ce07..dba5e6e559 100644 --- a/resources/extruders/anycubic_kobra3v2_extruder_0.def.json +++ b/resources/extruders/anycubic_kobra3v2_extruder_0.def.json @@ -4,7 +4,7 @@ "inherits": "fdmextruder", "metadata": { - "machine": "kobra3v2_ACE_PRO", + "machine": "anycubic_kobra3v2", "position": "0" }, "overrides": From 4f52a3d9389e192a7be2e32d19f1e5172b1e2580 Mon Sep 17 00:00:00 2001 From: Sam Bonnekamp Date: Wed, 18 Jun 2025 17:21:03 +0800 Subject: [PATCH 193/299] machine uses relative extrusion --- .../definitions/anycubic_kobra3v2.def.json | 21 ++++++++++++------- .../anycubic_kobra3v2_ACE_PRO.def.json | 19 ++++++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/resources/definitions/anycubic_kobra3v2.def.json b/resources/definitions/anycubic_kobra3v2.def.json index 8ca9800fde..a6d1c26d33 100644 --- a/resources/definitions/anycubic_kobra3v2.def.json +++ b/resources/definitions/anycubic_kobra3v2.def.json @@ -8,8 +8,9 @@ "author": "Sam Bonnekamp", "manufacturer": "Anycubic", "file_formats": "text/x-gcode", + "has_textured_buildplate": true, "platform": "anycubic_kobra3v2_buildplate.stl", - "machine_extruder_trains": { "0": "anycubic_kobra3v2_extruder_0" } + "machine_extruder_trains": { "0": "anycubic_kobra3v2_extruder_0" } }, "overrides": { @@ -20,17 +21,19 @@ { "description": "Anycubic Kobra 3 v2", "default_value": "Anycubic Kobra 3 v2" - }, + }, "machine_buildplate_type": { "default_value": "PEI Spring Steel" }, "machine_heated_bed": { "default_value": true}, - + "machine_center_is_zero": { "default_value": false }, + "machine_start_gcode_first": { "default_value": true }, + "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, + "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\n;Retract the filament\nG92 E1\nG1 E-1 F300\nG27 P2 ;Park toolhead\nM84" } + "material_bed_temperature": { "maximum_value": "110", - "maximum_value_warning": "90" + "maximum_value_warning": "90" }, "material_print_temperature":{ "maximum_value": 300 }, - "machine_center_is_zero": { "default_value": false }, - "layer_height": { "default_value": 0.2 }, "material_diameter": { "default_value": 1.75 }, "material_initial_print_temperature": { @@ -43,7 +46,9 @@ "maximum_value_warning": 295, "value": "material_print_temperature + 5" }, - "machine_start_gcode_first": { "default_value": true }, - "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" } + + "layer_height": { "default_value": 0.2 }, + "adhesion_type": { "value": "'skirt'" } + "relative_extrusion" : {"default_value": true} } } diff --git a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json index 9686c4c192..bc76df7a99 100644 --- a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json +++ b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json @@ -8,6 +8,7 @@ "author": "Sam Bonnekamp", "manufacturer": "Anycubic", "file_formats": "text/x-gcode", + "has_textured_buildplate": true, "platform": "anycubic_kobra3v2_buildplate.stl", "machine_extruder_trains": { "0": "anycubic_kobra3v2_ACEPRO_extruder_0", @@ -36,22 +37,26 @@ }, "material_print_temp_wait": { "value": true }, "machine_center_is_zero": { "default_value": false }, - "layer_height": { "default_value": 0.2 }, + "machine_start_gcode_first": { "default_value": true }, + "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, + "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\n;Retract the filament\nG92 E1\nG1 E-1 F300\nG27 P2 ;Park toolhead\nM84" } + "material_diameter": { "default_value": 1.75 }, "material_initial_print_temperature": - { + { "maximum_value_warning": 295, "value": "material_print_temperature + 5" - }, - "material_print_temperature": { "maximum_value": 300 }, + }, + "material_print_temperature": { "maximum_value": 300 }, "material_standby_temperature" : {"default_value": "material_print_temperature"}, "material_print_temperature_layer_0": { "maximum_value_warning": 295, "value": "material_print_temperature + 5" }, - "machine_start_gcode_first": { "default_value": true }, - "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, - "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\n;Retract the filament\nG92 E1\nG1 E-1 F300\nG27 P2 ;Park toolhead\nM84" } + + "layer_height": { "default_value": 0.2 }, + "adhesion_type": { "value": "'skirt'" }, + "relative_extrusion" : {"default_value": true} } } From 0ed4be3e94bf80effae215594558dd1bca35a84e Mon Sep 17 00:00:00 2001 From: Sam Bonnekamp Date: Wed, 18 Jun 2025 17:32:45 +0800 Subject: [PATCH 194/299] machine end gcode matches anycubic --- resources/definitions/anycubic_kobra3v2.def.json | 2 +- resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/anycubic_kobra3v2.def.json b/resources/definitions/anycubic_kobra3v2.def.json index a6d1c26d33..597c3578ed 100644 --- a/resources/definitions/anycubic_kobra3v2.def.json +++ b/resources/definitions/anycubic_kobra3v2.def.json @@ -27,7 +27,7 @@ "machine_center_is_zero": { "default_value": false }, "machine_start_gcode_first": { "default_value": true }, "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, - "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\n;Retract the filament\nG92 E1\nG1 E-1 F300\nG27 P2 ;Park toolhead\nM84" } + "machine_end_gcode": { "default_value": "G1 X5 Y{machine_depth*0.95} F{speed_travel*60} ; present print\nM140 S0 ; turn off heat bed\nM104 S0 ; turn off temperature\nM84; disable motors ; disable stepper motors" }, "material_bed_temperature": { "maximum_value": "110", diff --git a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json index bc76df7a99..c1738ddacd 100644 --- a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json +++ b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json @@ -39,7 +39,7 @@ "machine_center_is_zero": { "default_value": false }, "machine_start_gcode_first": { "default_value": true }, "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, - "machine_end_gcode": { "default_value": "M104 S0\nM140 S0\n;Retract the filament\nG92 E1\nG1 E-1 F300\nG27 P2 ;Park toolhead\nM84" } + "machine_end_gcode": { "default_value": "G1 X5 Y{machine_depth*0.95} F{speed_travel*60} ; present print\nM140 S0 ; turn off heat bed\nM104 S0 ; turn off temperature\nM84; disable motors ; disable stepper motors" }, "material_diameter": { "default_value": 1.75 }, "material_initial_print_temperature": From 350c95a110ee4074be8b80b9fe029bc58a7eb865 Mon Sep 17 00:00:00 2001 From: Sam Bonnekamp Date: Wed, 18 Jun 2025 17:36:32 +0800 Subject: [PATCH 195/299] missing semicolon --- resources/definitions/anycubic_kobra3v2.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/anycubic_kobra3v2.def.json b/resources/definitions/anycubic_kobra3v2.def.json index 597c3578ed..0f87ea130d 100644 --- a/resources/definitions/anycubic_kobra3v2.def.json +++ b/resources/definitions/anycubic_kobra3v2.def.json @@ -48,7 +48,7 @@ }, "layer_height": { "default_value": 0.2 }, - "adhesion_type": { "value": "'skirt'" } + "adhesion_type": { "value": "'skirt'" }, "relative_extrusion" : {"default_value": true} } } From 75946d8871b43a1e091ac36900d8c2cbfdd0ffd3 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 18 Jun 2025 11:56:08 +0200 Subject: [PATCH 196/299] Shape of brush is an enum now, not a string. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 14 ++++++++++---- plugins/PaintTool/PaintTool.qml | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index cbb0c97739..942ca67f17 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -1,6 +1,7 @@ # Copyright (c) 2025 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. +from enum import IntEnum import numpy from PyQt6.QtCore import Qt from PyQt6.QtGui import QImage, QPainter, QColor, QBrush, QPen @@ -20,6 +21,10 @@ from .PaintView import PaintView class PaintTool(Tool): """Provides the tool to paint meshes.""" + class BrushShape(IntEnum): + SQUARE = 0 + CIRCLE = 1 + def __init__(self) -> None: super().__init__() @@ -31,6 +36,7 @@ class PaintTool(Tool): self._mesh_transformed_cache = None self._cache_dirty: bool = True + # TODO: Colors will need to be replaced on a 'per type of painting' basis. self._color_str_to_rgba: Dict[str, List[int]] = { "A": [192, 0, 192, 255], "B": [232, 128, 0, 255], @@ -40,7 +46,7 @@ class PaintTool(Tool): self._brush_size: int = 10 self._brush_color: str = "A" - self._brush_shape: str = "A" + self._brush_shape: PaintTool.BrushShape = PaintTool.BrushShape.SQUARE self._brush_pen: QPen = self._createBrushPen() self._mouse_held: bool = False @@ -56,9 +62,9 @@ class PaintTool(Tool): color = self._color_str_to_rgba[self._brush_color] pen.setColor(QColor(color[0], color[1], color[2], color[3])) match self._brush_shape: - case "A": + case PaintTool.BrushShape.SQUARE: pen.setCapStyle(Qt.PenCapStyle.SquareCap) - case "B": + case PaintTool.BrushShape.CIRCLE: pen.setCapStyle(Qt.PenCapStyle.RoundCap) return pen @@ -98,7 +104,7 @@ class PaintTool(Tool): self._brush_color = brush_color self._brush_pen = self._createBrushPen() - def setBrushShape(self, brush_shape: str) -> None: + def setBrushShape(self, brush_shape: int) -> None: if brush_shape != self._brush_shape: self._brush_shape = brush_shape self._brush_pen = self._createBrushPen() diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index a1fac9c3a3..31aeb409d1 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -139,7 +139,7 @@ Item z: 2 - onClicked: UM.Controller.triggerActionWithData("setBrushShape", "A") + onClicked: UM.Controller.triggerActionWithData("setBrushShape", 0) } UM.ToolbarButton @@ -156,7 +156,7 @@ Item z: 2 - onClicked: UM.Controller.triggerActionWithData("setBrushShape", "B") + onClicked: UM.Controller.triggerActionWithData("setBrushShape", 1) } UM.Slider From 4fae9b231ab205b36c2297cb63d3801b097c4202 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 18 Jun 2025 12:06:04 +0200 Subject: [PATCH 197/299] Paint: Make calculation of Baricentric-coordinates a bit more robust. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 942ca67f17..86cc72e2b9 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -137,16 +137,25 @@ class PaintTool(Tool): # find unit direction vector for line C, which is perpendicular to lines A and B udir_res = numpy.cross(udir_b, udir_a) - udir_res /= numpy.linalg.norm(udir_res) + udir_res_len = numpy.linalg.norm(udir_res) + if udir_res_len == 0: + return 1.0 + udir_res /= udir_res_len # solve system of equations rhs = b - a lhs = numpy.array([udir_a, -udir_b, udir_res]).T - solved = numpy.linalg.solve(lhs, rhs) + try: + solved = numpy.linalg.solve(lhs, rhs) + except numpy.linalg.LinAlgError: + return 1.0 # get the ratio intersect = ((a + solved[0] * udir_a) + (b + solved[1] * udir_b)) * 0.5 - return numpy.linalg.norm(pt - intersect) / numpy.linalg.norm(a - intersect) + a_intersect_dist = numpy.linalg.norm(a - intersect) + if a_intersect_dist == 0: + return 1.0 + return numpy.linalg.norm(pt - intersect) / a_intersect_dist def _nodeTransformChanged(self, *args) -> None: self._cache_dirty = True @@ -167,6 +176,8 @@ class PaintTool(Tool): wb = PaintTool._get_intersect_ratio_via_pt(vb, pt, vc, va) wc = PaintTool._get_intersect_ratio_via_pt(vc, pt, va, vb) wt = wa + wb + wc + if wt == 0: + return face_id, None wa /= wt wb /= wt wc /= wt From 01c02e4479d4ca3fd1faf568ffc67bc63a2fa195 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 18 Jun 2025 12:42:45 +0200 Subject: [PATCH 198/299] Paint: Simplify and clarify input-event-code. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 38 ++++++++++------------------------ plugins/SolidView/SolidView.py | 1 - 2 files changed, 11 insertions(+), 28 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 86cc72e2b9..d596ea7289 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -4,7 +4,8 @@ from enum import IntEnum import numpy from PyQt6.QtCore import Qt -from PyQt6.QtGui import QImage, QPainter, QColor, QBrush, QPen +from PyQt6.QtGui import QImage, QPainter, QColor, QPen +from PyQt6 import QtWidgets from typing import cast, Dict, List, Optional, Tuple from UM.Application import Application @@ -50,8 +51,6 @@ class PaintTool(Tool): self._brush_pen: QPen = self._createBrushPen() self._mouse_held: bool = False - self._ctrl_held: bool = False - self._shift_held: bool = False self._last_text_coords: Optional[numpy.ndarray] = None self._last_face_id: Optional[int] = None @@ -209,27 +208,14 @@ class PaintTool(Tool): controller.setActiveView("SolidView") return True - if event.type == Event.KeyPressEvent: - evt = cast(KeyEvent, event) - if evt.key == KeyEvent.ControlKey: - self._ctrl_held = True - return True - if evt.key == KeyEvent.ShiftKey: - self._shift_held = True - return True - return False - if event.type == Event.KeyReleaseEvent: - evt = cast(KeyEvent, event) - if evt.key == KeyEvent.ControlKey: - self._ctrl_held = False - return True - if evt.key == KeyEvent.ShiftKey: - self._shift_held = False - return True - if evt.key == Qt.Key.Key_L and self._ctrl_held: + key_release = cast(KeyEvent, event) + modifiers = QtWidgets.QApplication.keyboardModifiers() + ctrl_held = modifiers & Qt.KeyboardModifier.ControlModifier != Qt.KeyboardModifier.NoModifier + if key_release.key == Qt.Key.Key_L and ctrl_held: # NOTE: Ctrl-L is used here instead of Ctrl-Z, as the latter is the application-wide one that takes precedence. - return self.undoStackAction(self._shift_held) + shift_held = modifiers & Qt.KeyboardModifier.ShiftModifier != Qt.KeyboardModifier.NoModifier + return self.undoStackAction(shift_held) return False if event.type == Event.MouseReleaseEvent and self._controller.getToolsEnabled(): @@ -246,9 +232,9 @@ class PaintTool(Tool): if is_moved and not self._mouse_held: return False - evt = cast(MouseEvent, event) + mouse_evt = cast(MouseEvent, event) if is_pressed: - if MouseEvent.LeftButton not in evt.buttons: + if MouseEvent.LeftButton not in mouse_evt.buttons: return False else: self._mouse_held = True @@ -276,15 +262,13 @@ class PaintTool(Tool): if not self._mesh_transformed_cache: return False - evt = cast(MouseEvent, event) - if not self._picking_pass: self._picking_pass = PickingPass(camera.getViewportWidth(), camera.getViewportHeight()) self._picking_pass.render() self._selection_pass.renderFacesMode() - face_id, texcoords = self._getTexCoordsFromClick(node, evt.x, evt.y) + face_id, texcoords = self._getTexCoordsFromClick(node, mouse_evt.x, mouse_evt.y) if texcoords is None: return False if self._last_text_coords is None: diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index e115267720..bffc3aa526 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -36,7 +36,6 @@ class SolidView(View): _show_xray_warning_preference = "view/show_xray_warning" _show_overhang_preference = "view/show_overhang" - _paint_active_preference = "view/paint_active" def __init__(self): super().__init__() From 56f669d1fd4440831481b238c28c38055427c468 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 18 Jun 2025 12:50:21 +0200 Subject: [PATCH 199/299] Paint: Replace undo-redo UI code with qml Action. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 10 ---------- plugins/PaintTool/PaintTool.qml | 19 +++++++++++++++++-- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index d596ea7289..e4dab412e7 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -208,16 +208,6 @@ class PaintTool(Tool): controller.setActiveView("SolidView") return True - if event.type == Event.KeyReleaseEvent: - key_release = cast(KeyEvent, event) - modifiers = QtWidgets.QApplication.keyboardModifiers() - ctrl_held = modifiers & Qt.KeyboardModifier.ControlModifier != Qt.KeyboardModifier.NoModifier - if key_release.key == Qt.Key.Key_L and ctrl_held: - # NOTE: Ctrl-L is used here instead of Ctrl-Z, as the latter is the application-wide one that takes precedence. - shift_held = modifiers & Qt.KeyboardModifier.ShiftModifier != Qt.KeyboardModifier.NoModifier - return self.undoStackAction(shift_held) - return False - if event.type == Event.MouseReleaseEvent and self._controller.getToolsEnabled(): if MouseEvent.LeftButton not in cast(MouseEvent, event).buttons: return False diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index 31aeb409d1..8bd02e00a3 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -2,6 +2,7 @@ // Cura is released under the terms of the LGPLv3 or higher. import QtQuick +import QtQuick.Controls import QtQuick.Layouts import UM 1.7 as UM @@ -13,6 +14,20 @@ Item height: childrenRect.height UM.I18nCatalog { id: catalog; name: "cura"} + Action + { + id: undoAction + shortcut: "Ctrl+L" + onTriggered: UM.Controller.triggerActionWithData("undoStackAction", false) + } + + Action + { + id: redoAction + shortcut: "Ctrl+Shift+L" + onTriggered: UM.Controller.triggerActionWithData("undoStackAction", true) + } + ColumnLayout { RowLayout @@ -192,7 +207,7 @@ Item z: 2 - onClicked: UM.Controller.triggerActionWithData("undoStackAction", false) + onClicked: undoAction.trigger() } UM.ToolbarButton @@ -208,7 +223,7 @@ Item z: 2 - onClicked: UM.Controller.triggerActionWithData("undoStackAction", true) + onClicked: redoAction.trigger() } } } From f7dc928d3283878e80ad8694ebc6d24a78cc9fea Mon Sep 17 00:00:00 2001 From: Sam Bonnekamp Date: Wed, 18 Jun 2025 19:03:55 +0800 Subject: [PATCH 200/299] fixed unecessary default --- resources/definitions/anycubic_kobra3v2.def.json | 2 +- resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/anycubic_kobra3v2.def.json b/resources/definitions/anycubic_kobra3v2.def.json index 0f87ea130d..0f32de2604 100644 --- a/resources/definitions/anycubic_kobra3v2.def.json +++ b/resources/definitions/anycubic_kobra3v2.def.json @@ -49,6 +49,6 @@ "layer_height": { "default_value": 0.2 }, "adhesion_type": { "value": "'skirt'" }, - "relative_extrusion" : {"default_value": true} + "relative_extrusion" : {"value": true} } } diff --git a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json index c1738ddacd..b85fb3c0ed 100644 --- a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json +++ b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json @@ -57,6 +57,6 @@ "layer_height": { "default_value": 0.2 }, "adhesion_type": { "value": "'skirt'" }, - "relative_extrusion" : {"default_value": true} + "relative_extrusion" : {"value": true} } } From d2ade67cad0a670ea82fd0cd4ada9fdc97c7f18b Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 18 Jun 2025 13:41:20 +0200 Subject: [PATCH 201/299] Paint: 'Substrokes per face' data-structure. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index e4dab412e7..db09bae410 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -53,6 +53,7 @@ class PaintTool(Tool): self._mouse_held: bool = False self._last_text_coords: Optional[numpy.ndarray] = None + self._last_mouse_coords: Optional[Tuple[int, int]] = None self._last_face_id: Optional[int] = None def _createBrushPen(self) -> QPen: @@ -213,6 +214,7 @@ class PaintTool(Tool): return False self._mouse_held = False self._last_text_coords = None + self._last_mouse_coords = None self._last_face_id = None return True @@ -263,26 +265,32 @@ class PaintTool(Tool): return False if self._last_text_coords is None: self._last_text_coords = texcoords + self._last_mouse_coords = (mouse_evt.x, mouse_evt.y) self._last_face_id = face_id - if face_id != self._last_face_id: - # TODO: draw two strokes in this case, for the two faces involved - # ... it's worse, for smaller faces we may genuinely require the patch -- and it may even go over _multiple_ patches if the user paints fast enough - # -> for now; make a lookup table for which faces are connected to which, don't split if they are connected, and solve the connection issue(s) later + substrokes_per_face = {} + if face_id == self._last_face_id: + substrokes_per_face[face_id] = (self._last_text_coords, texcoords) + else: + # TODO: In case the stroke doesn't begin and end within the same face: + # Iteratively get the face-id's and texture coordinates of mid-point between the previous-mouse position and this one, ... self._last_text_coords = texcoords + self._last_mouse_coords = (mouse_evt.x, mouse_evt.y) self._last_face_id = face_id return True w, h = paintview.getUvTexDimensions() - sub_image, (start_x, start_y) = self._createStrokeImage( - self._last_text_coords[0] * w, - self._last_text_coords[1] * h, - texcoords[0] * w, - texcoords[1] * h - ) - paintview.addStroke(sub_image, start_x, start_y) + for faceid, (start_coords, end_coords) in substrokes_per_face.items(): + sub_image, (start_x, start_y) = self._createStrokeImage( + start_coords[0] * w, + start_coords[1] * h, + end_coords[0] * w, + end_coords[1] * h + ) + paintview.addStroke(sub_image, start_x, start_y) self._last_text_coords = texcoords + self._last_mouse_coords = (mouse_evt.x, mouse_evt.y) self._last_face_id = face_id Application.getInstance().getController().getScene().sceneChanged.emit(node) return True From e27926a9685c0491902c5efd41b236b61bf18398 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 18 Jun 2025 15:02:06 +0200 Subject: [PATCH 202/299] Paint: Have a stroke properly propagate over the texture-triangles. part of CURA-12543 --- plugins/PaintTool/PaintTool.py | 47 ++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index db09bae410..bd3480161b 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -8,6 +8,8 @@ from PyQt6.QtGui import QImage, QPainter, QColor, QPen from PyQt6 import QtWidgets from typing import cast, Dict, List, Optional, Tuple +from numpy import ndarray + from UM.Application import Application from UM.Event import Event, MouseEvent, KeyEvent from UM.Logger import Logger @@ -160,7 +162,7 @@ class PaintTool(Tool): def _nodeTransformChanged(self, *args) -> None: self._cache_dirty = True - def _getTexCoordsFromClick(self, node: SceneNode, x: int, y: int) -> Tuple[int, Optional[numpy.ndarray]]: + def _getTexCoordsFromClick(self, node: SceneNode, x: float, y: float) -> Tuple[int, Optional[numpy.ndarray]]: face_id = self._selection_pass.getFaceIdAtPosition(x, y) if face_id < 0 or face_id >= node.getMeshData().getFaceCount(): return face_id, None @@ -184,6 +186,34 @@ class PaintTool(Tool): texcoords = wa * ta + wb * tb + wc * tc return face_id, texcoords + def _iteratateSplitSubstroke(self, node, substrokes, + info_a: Tuple[Tuple[float, float], Tuple[int, Optional[numpy.ndarray]]], + info_b: Tuple[Tuple[float, float], Tuple[int, Optional[numpy.ndarray]]]) -> None: + click_a, (face_a, texcoords_a) = info_a + click_b, (face_b, texcoords_b) = info_b + + if (abs(click_a[0] - click_b[0]) < 0.0001 and abs(click_a[1] - click_b[1]) < 0.0001) or (face_a < 0 and face_b < 0): + return + if face_b < 0 or face_a == face_b: + substrokes.append((self._last_text_coords, texcoords_a)) + return + if face_a < 0: + substrokes.append((self._last_text_coords, texcoords_b)) + return + + mouse_mid = (click_a[0] + click_b[0]) / 2.0, (click_a[1] + click_b[1]) / 2.0 + face_mid, texcoords_mid = self._getTexCoordsFromClick(node, mouse_mid[0], mouse_mid[1]) + mid_struct = (mouse_mid, (face_mid, texcoords_mid)) + if face_mid == face_a: + substrokes.append((texcoords_a, texcoords_mid)) + self._iteratateSplitSubstroke(node, substrokes, mid_struct, info_b) + elif face_mid == face_b: + substrokes.append((texcoords_mid, texcoords_b)) + self._iteratateSplitSubstroke(node, substrokes, info_a, mid_struct) + else: + self._iteratateSplitSubstroke(node, substrokes, mid_struct, info_b) + self._iteratateSplitSubstroke(node, substrokes, info_a, mid_struct) + def event(self, event: Event) -> bool: """Handle mouse and keyboard events. @@ -268,19 +298,16 @@ class PaintTool(Tool): self._last_mouse_coords = (mouse_evt.x, mouse_evt.y) self._last_face_id = face_id - substrokes_per_face = {} + substrokes = [] if face_id == self._last_face_id: - substrokes_per_face[face_id] = (self._last_text_coords, texcoords) + substrokes.append((self._last_text_coords, texcoords)) else: - # TODO: In case the stroke doesn't begin and end within the same face: - # Iteratively get the face-id's and texture coordinates of mid-point between the previous-mouse position and this one, ... - self._last_text_coords = texcoords - self._last_mouse_coords = (mouse_evt.x, mouse_evt.y) - self._last_face_id = face_id - return True + self._iteratateSplitSubstroke(node, substrokes, + (self._last_mouse_coords, (self._last_face_id, self._last_text_coords)), + ((mouse_evt.x, mouse_evt.y), (face_id, texcoords))) w, h = paintview.getUvTexDimensions() - for faceid, (start_coords, end_coords) in substrokes_per_face.items(): + for start_coords, end_coords in substrokes: sub_image, (start_x, start_y) = self._createStrokeImage( start_coords[0] * w, start_coords[1] * h, From 4caba52f0533611792cebd8253baf3b76230323f Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 18 Jun 2025 16:00:47 +0200 Subject: [PATCH 203/299] Basically working multipurpose painting CURA-12566 --- cura/Scene/SliceableObjectDecorator.py | 15 ++++- plugins/PaintTool/PaintTool.py | 62 +++++++++++-------- plugins/PaintTool/PaintView.py | 86 +++++++++++++++++++++++++- plugins/PaintTool/paint.shader | 31 ++++++---- resources/themes/cura-light/theme.json | 6 +- 5 files changed, 157 insertions(+), 43 deletions(-) diff --git a/cura/Scene/SliceableObjectDecorator.py b/cura/Scene/SliceableObjectDecorator.py index c26848ed1a..dee244b81c 100644 --- a/cura/Scene/SliceableObjectDecorator.py +++ b/cura/Scene/SliceableObjectDecorator.py @@ -1,6 +1,8 @@ import copy -from typing import Optional +from typing import Optional, Dict + +from PyQt6.QtGui import QImage import UM.View.GL.Texture from UM.Scene.SceneNodeDecorator import SceneNodeDecorator @@ -16,6 +18,7 @@ class SliceableObjectDecorator(SceneNodeDecorator): def __init__(self) -> None: super().__init__() self._paint_texture = None + self._texture_data_mapping: Dict[str, tuple[int, int]] = {} def isSliceable(self) -> bool: return True @@ -23,12 +26,22 @@ class SliceableObjectDecorator(SceneNodeDecorator): def getPaintTexture(self, create_if_required: bool = True) -> Optional[UM.View.GL.Texture.Texture]: if self._paint_texture is None and create_if_required: self._paint_texture = OpenGL.getInstance().createTexture(TEXTURE_WIDTH, TEXTURE_HEIGHT) + image = QImage(TEXTURE_WIDTH, TEXTURE_HEIGHT, QImage.Format.Format_RGB32) + image.fill(0) + self._paint_texture.setImage(image) return self._paint_texture def setPaintTexture(self, texture: UM.View.GL.Texture) -> None: self._paint_texture = texture + def getTextureDataMapping(self) -> Dict[str, tuple[int, int]]: + return self._texture_data_mapping + + def setTextureDataMapping(self, mapping: Dict[str, tuple[int, int]]) -> None: + self._texture_data_mapping = mapping + def __deepcopy__(self, memo) -> "SliceableObjectDecorator": copied_decorator = SliceableObjectDecorator() copied_decorator.setPaintTexture(copy.deepcopy(self.getPaintTexture())) + copied_decorator.setTextureDataMapping(copy.deepcopy(self.getTextureDataMapping())) return copied_decorator diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index cbb0c97739..deddff1a40 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -31,13 +31,6 @@ class PaintTool(Tool): self._mesh_transformed_cache = None self._cache_dirty: bool = True - self._color_str_to_rgba: Dict[str, List[int]] = { - "A": [192, 0, 192, 255], - "B": [232, 128, 0, 255], - "C": [0, 255, 0, 255], - "D": [255, 255, 255, 255], - } - self._brush_size: int = 10 self._brush_color: str = "A" self._brush_shape: str = "A" @@ -53,8 +46,8 @@ class PaintTool(Tool): def _createBrushPen(self) -> QPen: pen = QPen() pen.setWidth(self._brush_size) - color = self._color_str_to_rgba[self._brush_color] - pen.setColor(QColor(color[0], color[1], color[2], color[3])) + pen.setColor(Qt.GlobalColor.white) + match self._brush_shape: case "A": pen.setCapStyle(Qt.PenCapStyle.SquareCap) @@ -70,8 +63,8 @@ class PaintTool(Tool): start_x = int(min(x0, x1) - half_brush_size) start_y = int(min(y0, y1) - half_brush_size) - stroke_image = QImage(abs(xdiff) + self._brush_size, abs(ydiff) + self._brush_size, QImage.Format.Format_RGBA8888) - stroke_image.fill(QColor(0,0,0,0)) + stroke_image = QImage(abs(xdiff) + self._brush_size, abs(ydiff) + self._brush_size, QImage.Format.Format_RGB32) + stroke_image.fill(0) painter = QPainter(stroke_image) painter.setRenderHint(QPainter.RenderHint.Antialiasing, False) @@ -85,8 +78,14 @@ class PaintTool(Tool): return stroke_image, (start_x, start_y) def setPaintType(self, paint_type: str) -> None: - Logger.warning(f"TODO: Implement paint-types ({paint_type}).") - pass # FIXME: ... and also please call `self._brush_pen = self._createBrushPen()` (see other funcs). + paint_view = self._get_paint_view() + if paint_view is None: + return + + paint_view.setPaintType(paint_type) + + self._brush_pen = self._createBrushPen() + self._updateScene() def setBrushSize(self, brush_size: float) -> None: if brush_size != self._brush_size: @@ -94,9 +93,7 @@ class PaintTool(Tool): self._brush_pen = self._createBrushPen() def setBrushColor(self, brush_color: str) -> None: - if brush_color != self._brush_color: - self._brush_color = brush_color - self._brush_pen = self._createBrushPen() + self._brush_color = brush_color def setBrushShape(self, brush_shape: str) -> None: if brush_shape != self._brush_shape: @@ -104,19 +101,25 @@ class PaintTool(Tool): self._brush_pen = self._createBrushPen() def undoStackAction(self, redo_instead: bool) -> bool: - paintview = Application.getInstance().getController().getActiveView() - if paintview is None or paintview.getPluginId() != "PaintTool": + paint_view = self._get_paint_view() + if paint_view is None: return False - paintview = cast(PaintView, paintview) + if redo_instead: - paintview.redoStroke() + paint_view.redoStroke() else: - paintview.undoStroke() - node = Selection.getSelectedObject(0) - if node is not None: - Application.getInstance().getController().getScene().sceneChanged.emit(node) + paint_view.undoStroke() + + self._updateScene() return True + @staticmethod + def _get_paint_view() -> Optional[PaintView]: + paint_view = Application.getInstance().getController().getActiveView() + if paint_view is None or paint_view.getPluginId() != "PaintTool": + return None + return cast(PaintView, paint_view) + @staticmethod def _get_intersect_ratio_via_pt(a: numpy.ndarray, pt: numpy.ndarray, b: numpy.ndarray, c: numpy.ndarray) -> float: # compute the intersection of (param) A - pt with (param) B - (param) C @@ -289,11 +292,18 @@ class PaintTool(Tool): texcoords[0] * w, texcoords[1] * h ) - paintview.addStroke(sub_image, start_x, start_y) + paintview.addStroke(sub_image, start_x, start_y, self._brush_color) self._last_text_coords = texcoords self._last_face_id = face_id - Application.getInstance().getController().getScene().sceneChanged.emit(node) + self._updateScene(node) return True return False + + @staticmethod + def _updateScene(node: SceneNode = None): + if node is None: + node = Selection.getSelectedObject(0) + if node is not None: + Application.getInstance().getController().getScene().sceneChanged.emit(node) \ No newline at end of file diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 83f554dbed..71bf6cb014 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -2,10 +2,11 @@ # Cura is released under the terms of the LGPLv3 or higher. import os -from typing import Optional, List, Tuple +from typing import Optional, List, Tuple, Dict from PyQt6.QtGui import QImage, QColor, QPainter +from cura.CuraApplication import CuraApplication from UM.PluginRegistry import PluginRegistry from UM.View.GL.ShaderProgram import ShaderProgram from UM.View.GL.Texture import Texture @@ -13,6 +14,7 @@ from UM.View.View import View from UM.Scene.Selection import Selection from UM.View.GL.OpenGL import OpenGL from UM.i18n import i18nCatalog +from UM.Math.Color import Color catalog = i18nCatalog("cura") @@ -22,10 +24,24 @@ class PaintView(View): UNDO_STACK_SIZE = 1024 + class PaintType: + def __init__(self, icon: str, display_color: Color, value: int): + self.icon: str = icon + self.display_color: Color = display_color + self.value: int = value + + class PaintMode: + def __init__(self, icon: str, types: Dict[str, "PaintView.PaintType"]): + self.icon: str = icon + self.types = types + def __init__(self) -> None: super().__init__() self._paint_shader: Optional[ShaderProgram] = None self._current_paint_texture: Optional[Texture] = None + self._current_bits_ranges: tuple[int, int] = (0, 0) + self._current_paint_type = "" + self._paint_modes: Dict[str, PaintView.PaintMode] = {} self._stroke_undo_stack: List[Tuple[QImage, int, int]] = [] self._stroke_redo_stack: List[Tuple[QImage, int, int]] = [] @@ -33,6 +49,18 @@ class PaintView(View): self._force_opaque_mask = QImage(2, 2, QImage.Format.Format_Mono) self._force_opaque_mask.fill(1) + CuraApplication.getInstance().engineCreatedSignal.connect(self._makePaintModes) + + def _makePaintModes(self): + theme = CuraApplication.getInstance().getTheme() + usual_types = {"A": self.PaintType("Buildplate", Color(*theme.getColor("paint_normal_area").getRgb()), 0), + "B": self.PaintType("BlackMagic", Color(*theme.getColor("paint_preferred_area").getRgb()), 1), + "C": self.PaintType("Eye", Color(*theme.getColor("paint_avoid_area").getRgb()), 2)} + self._paint_modes = { + "A": self.PaintMode("MeshTypeNormal", usual_types), + "B": self.PaintMode("CircleOutline", usual_types), + } + def _checkSetup(self): if not self._paint_shader: shader_filename = os.path.join(PluginRegistry.getInstance().getPluginPath("PaintTool"), "paint.shader") @@ -49,10 +77,26 @@ class PaintView(View): res.setAlphaChannel(self._force_opaque_mask.scaled(image.width(), image.height())) return res - def addStroke(self, stroke_image: QImage, start_x: int, start_y: int) -> None: - if self._current_paint_texture is None: + def addStroke(self, stroke_image: QImage, start_x: int, start_y: int, brush_color: str) -> None: + if self._current_paint_texture is None or self._current_paint_texture.getImage() is None: return + actual_image = self._current_paint_texture.getImage() + + bit_range_start, bit_range_end = self._current_bits_ranges + set_value = self._paint_modes[self._current_paint_type].types[brush_color].value << self._current_bits_ranges[0] + clear_mask = 0xffffffff ^ (((0xffffffff << (32 - 1 - (bit_range_end - bit_range_start))) & 0xffffffff) >> (32 - 1 - bit_range_end)) + + for x in range(stroke_image.width()): + for y in range(stroke_image.height()): + stroke_pixel = stroke_image.pixel(x, y) + actual_pixel = actual_image.pixel(start_x + x, start_y + y) + if stroke_pixel != 0: + new_pixel = (actual_pixel & clear_mask) | set_value + else: + new_pixel = actual_pixel + stroke_image.setPixel(x, y, new_pixel) + self._stroke_redo_stack.clear() if len(self._stroke_undo_stack) >= PaintView.UNDO_STACK_SIZE: self._stroke_undo_stack.pop(0) @@ -83,6 +127,31 @@ class PaintView(View): return self._current_paint_texture.getWidth(), self._current_paint_texture.getHeight() return 0, 0 + def setPaintType(self, paint_type: str) -> None: + node = Selection.getAllSelectedObjects()[0] + if node is None: + return + + paint_data_mapping = node.callDecoration("getTextureDataMapping") + + if paint_type not in paint_data_mapping: + new_mapping = self._add_mapping(paint_data_mapping, len(self._paint_modes[paint_type].types)) + paint_data_mapping[paint_type] = new_mapping + node.callDecoration("setTextureDataMapping", paint_data_mapping) + + self._current_paint_type = paint_type + self._current_bits_ranges = paint_data_mapping[paint_type] + + @staticmethod + def _add_mapping(actual_mapping: Dict[str, tuple[int, int]], nb_storable_values: int) -> tuple[int, int]: + start_index = 0 + if actual_mapping: + start_index = max(end_index for _, end_index in actual_mapping.values()) + 1 + + end_index = start_index + int.bit_length(nb_storable_values - 1) - 1 + + return start_index, end_index + def beginRendering(self) -> None: renderer = self.getRenderer() self._checkSetup() @@ -93,6 +162,17 @@ class PaintView(View): if node is None: return + if self._current_paint_type == "": + self.setPaintType("A") + + self._paint_shader.setUniformValue("u_bitsRangesStart", self._current_bits_ranges[0]) + self._paint_shader.setUniformValue("u_bitsRangesEnd", self._current_bits_ranges[1]) + + colors = [paint_type_obj.display_color for paint_type_obj in self._paint_modes[self._current_paint_type].types.values()] + colors_values = [[int(color_part * 255) for color_part in [color.r, color.g, color.b]] for color in colors] + self._paint_shader.setUniformValueArray("u_renderColors", colors_values) + self._current_paint_texture = node.callDecoration("getPaintTexture") self._paint_shader.setTexture(0, self._current_paint_texture) + paint_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix()) diff --git a/plugins/PaintTool/paint.shader b/plugins/PaintTool/paint.shader index 83682c7222..bd769f5cb2 100644 --- a/plugins/PaintTool/paint.shader +++ b/plugins/PaintTool/paint.shader @@ -27,11 +27,13 @@ vertex = fragment = uniform mediump vec4 u_ambientColor; - uniform mediump vec4 u_diffuseColor; uniform highp vec3 u_lightPosition; uniform highp vec3 u_viewPosition; uniform mediump float u_opacity; uniform sampler2D u_texture; + uniform mediump int u_bitsRangesStart; + uniform mediump int u_bitsRangesEnd; + uniform mediump vec3 u_renderColors[16]; varying highp vec3 v_vertex; varying highp vec3 v_normal; @@ -48,15 +50,17 @@ fragment = highp vec3 light_dir = normalize(u_lightPosition - v_vertex); /* Diffuse Component */ + ivec4 texture = ivec4(texture(u_texture, v_uvs) * 255.0); + uint color_index = (texture.r << 16) | (texture.g << 8) | texture.b; + color_index = (color_index << (32 - 1 - u_bitsRangesEnd)) >> 32 - 1 - (u_bitsRangesEnd - u_bitsRangesStart); + + vec4 diffuse_color = vec4(u_renderColors[color_index] / 255.0, 1.0); highp float n_dot_l = clamp(dot(normal, light_dir), 0.0, 1.0); - final_color += (n_dot_l * u_diffuseColor); + final_color += (n_dot_l * diffuse_color); final_color.a = u_opacity; - lowp vec4 texture = texture2D(u_texture, v_uvs); - final_color = mix(final_color, texture, texture.a); - - gl_FragColor = final_color; + frag_color = final_color; } vertex41core = @@ -89,11 +93,13 @@ vertex41core = fragment41core = #version 410 uniform mediump vec4 u_ambientColor; - uniform mediump vec4 u_diffuseColor; uniform highp vec3 u_lightPosition; uniform highp vec3 u_viewPosition; uniform mediump float u_opacity; uniform sampler2D u_texture; + uniform mediump int u_bitsRangesStart; + uniform mediump int u_bitsRangesEnd; + uniform mediump vec3 u_renderColors[16]; in highp vec3 v_vertex; in highp vec3 v_normal; @@ -111,20 +117,21 @@ fragment41core = highp vec3 light_dir = normalize(u_lightPosition - v_vertex); /* Diffuse Component */ + ivec4 texture = ivec4(texture(u_texture, v_uvs) * 255.0); + uint color_index = (texture.r << 16) | (texture.g << 8) | texture.b; + color_index = (color_index << (32 - 1 - u_bitsRangesEnd)) >> 32 - 1 - (u_bitsRangesEnd - u_bitsRangesStart); + + vec4 diffuse_color = vec4(u_renderColors[color_index] / 255.0, 1.0); highp float n_dot_l = clamp(dot(normal, light_dir), 0.0, 1.0); - final_color += (n_dot_l * u_diffuseColor); + final_color += (n_dot_l * diffuse_color); final_color.a = u_opacity; - lowp vec4 texture = texture(u_texture, v_uvs); - final_color = mix(final_color, texture, texture.a); - frag_color = final_color; } [defaults] u_ambientColor = [0.3, 0.3, 0.3, 1.0] -u_diffuseColor = [1.0, 1.0, 1.0, 1.0] u_opacity = 0.5 u_texture = 0 diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 1ae316f96c..c5684a416b 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -501,7 +501,11 @@ "error_badge_background": [255, 255, 255, 255], "border_field_light": [180, 180, 180, 255], - "border_main_light": [212, 212, 212, 255] + "border_main_light": [212, 212, 212, 255], + + "paint_normal_area": "background_3", + "paint_preferred_area": "um_green_5", + "paint_avoid_area": "um_red_5" }, "sizes": { From 425a167391252c41b920955a77ecf38a6f94f4bd Mon Sep 17 00:00:00 2001 From: Sam Bonnekamp Date: Thu, 19 Jun 2025 15:28:49 +0800 Subject: [PATCH 204/299] added 32px cura thumbnail to start gcode --- resources/definitions/anycubic_kobra3v2.def.json | 2 +- resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/anycubic_kobra3v2.def.json b/resources/definitions/anycubic_kobra3v2.def.json index 0f32de2604..143d08b92b 100644 --- a/resources/definitions/anycubic_kobra3v2.def.json +++ b/resources/definitions/anycubic_kobra3v2.def.json @@ -26,7 +26,7 @@ "machine_heated_bed": { "default_value": true}, "machine_center_is_zero": { "default_value": false }, "machine_start_gcode_first": { "default_value": true }, - "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, + "machine_start_gcode": { "default_value": "; thumbnail begin 32x32\n; iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAX\n; NSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAARWSURBVHgB1Vc7bx1FFD5n/cC+YOQ4RBTXlg0STfIH\n; gM78h0SAhGgQjyqARO8eFEQFBaKhCHIoKagcOkJJQUWBI19XJLaJgp+5M8x5zZzdO+sg0ZCR1zM7u3\n; e+73znMbMAT0KLMVqPdKVhvuze+o2NjUafget7Gz4GeO3s7Ow29YiYiXSJ2TPft0BwEmZ2dpYnp+Ec\n; 8NPT09tpyOAhhF4CXSBPwhOvEZk+B/ynNFzd2QvwxlfHMEq9PqR//mVaWcegmqKCIf9FKGS2Px30Ey\n; A/Hh8fE/gWgRPomww+VkxVgYFoWcz3xXpUJo2QsXvEFu8qAQJvmobA13b3I1u+Q+AhQuRfB1kTBDS6\n; FUVmVBx5iwmqNIgNv9ONkUzg4ODgBQNn2b80yyNbCzFQqMsC4MCNg/eveSQGdQM6glhXYDAYbJHvRw\n; q+ux90dQ8eeBxacaD+5T5ZSdLbfIcT61hTgCZTuq1R/zqDjxMOva6SKzBdMQRoO1OsovcLZrpPkmOO\n; ytibCdPejOQCGJHl5l+zlEGNxBiuvjxI1zNwZTgDzw4a6LbV6/fTT8eqSGD/G3hVgTQRT05OOv6Nyl\n; zBwxgW5iN8/e4leOWlOTivESjAlNhvYJoEvTEA6gq7wIqMyZ76zevPw5XlWdi5/wi+2foLNu88hAeH\n; QQKQJG/ScjjFY1cUFD3mYKxmgeef+1z9AstO4KMEfu3zXdi594gXlHIj3hYFY6su5fVQU7OjgAvZNg\n; kpaDFn8jvrC9zf+GEvgZ+16HqX5QRVctl6FmAyXhq3TmHnROBhWuBysp7aj7/+rS+IWybKO8oPWTns\n; zFX2kxalEKTe+6pZXR9kx0X3olhXdmqJ+GIF6lyfC8ArUCnZ8PPvJ9xfXn4KLMCkuBlo306payJMWD\n; 9BoGspE9LrVop4ajfevgQrz82U5xkQyg7onyEWfpUzxSQBlUnjWRZM8t66cwi/jU5h5eIMbH40hKuv\n; LqS6UFwh7mhv1RL4AYojY9VQbqkQRWL34icPtQ5o6dXqR9fwQlLgrYuPLUSrH96TvZDigsg1UwxFc3\n; c/e5rfsRNRI/JFNNns8MBy8QKNvJYKzGgf4NoXf8LH3+5xTDw4jP0szH16ZvBlybdcitMhpJzrwKUB\n; jcmCiDkDvv/liK92qRWLeTdsZYSsQaPhhXOOZD44uLJhqXAIxYKIQUIaSqBGg+Di09CuBiUYxQ0E/t\n; 0Hc2bk9gQB26kiYJEK7a6kJyqdvL/bKSiKOmx9dGumfpnA35/jnsDH4/H6BAH7Qba3dobTTQYrOY0N\n; usOnbr9JieEiCPgSzzH4/Pz8dpVASw3T2OY0Y2V7FkBrdjDOarErkLPmpgNPkb/u5e8l4CqHG1IqhU\n; xEoQuZztlwuIRw8705WFma8uB3a0jcUhb05pQ/zdp+Ufso8R8hdLqygDs6OnptcXHxD+gx9V8R6H6a\n; dQ8WrSwq81XZ/1NToLztuY9T8D3U687/r/0D2siIlZoKRzIAAAAASUVORK5CYII=\n; thumbnail end\n; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, "machine_end_gcode": { "default_value": "G1 X5 Y{machine_depth*0.95} F{speed_travel*60} ; present print\nM140 S0 ; turn off heat bed\nM104 S0 ; turn off temperature\nM84; disable motors ; disable stepper motors" }, "material_bed_temperature": diff --git a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json index b85fb3c0ed..6e6fb31e2a 100644 --- a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json +++ b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json @@ -38,7 +38,7 @@ "material_print_temp_wait": { "value": true }, "machine_center_is_zero": { "default_value": false }, "machine_start_gcode_first": { "default_value": true }, - "machine_start_gcode": { "default_value": "; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, + "machine_start_gcode": { "default_value": "; thumbnail begin 32x32\n; iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAX\n; NSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAARWSURBVHgB1Vc7bx1FFD5n/cC+YOQ4RBTXlg0STfIH\n; gM78h0SAhGgQjyqARO8eFEQFBaKhCHIoKagcOkJJQUWBI19XJLaJgp+5M8x5zZzdO+sg0ZCR1zM7u3\n; e+73znMbMAT0KLMVqPdKVhvuze+o2NjUafget7Gz4GeO3s7Ow29YiYiXSJ2TPft0BwEmZ2dpYnp+Ec\n; 8NPT09tpyOAhhF4CXSBPwhOvEZk+B/ynNFzd2QvwxlfHMEq9PqR//mVaWcegmqKCIf9FKGS2Px30Ey\n; A/Hh8fE/gWgRPomww+VkxVgYFoWcz3xXpUJo2QsXvEFu8qAQJvmobA13b3I1u+Q+AhQuRfB1kTBDS6\n; FUVmVBx5iwmqNIgNv9ONkUzg4ODgBQNn2b80yyNbCzFQqMsC4MCNg/eveSQGdQM6glhXYDAYbJHvRw\n; q+ux90dQ8eeBxacaD+5T5ZSdLbfIcT61hTgCZTuq1R/zqDjxMOva6SKzBdMQRoO1OsovcLZrpPkmOO\n; ytibCdPejOQCGJHl5l+zlEGNxBiuvjxI1zNwZTgDzw4a6LbV6/fTT8eqSGD/G3hVgTQRT05OOv6Nyl\n; zBwxgW5iN8/e4leOWlOTivESjAlNhvYJoEvTEA6gq7wIqMyZ76zevPw5XlWdi5/wi+2foLNu88hAeH\n; QQKQJG/ScjjFY1cUFD3mYKxmgeef+1z9AstO4KMEfu3zXdi594gXlHIj3hYFY6su5fVQU7OjgAvZNg\n; kpaDFn8jvrC9zf+GEvgZ+16HqX5QRVctl6FmAyXhq3TmHnROBhWuBysp7aj7/+rS+IWybKO8oPWTns\n; zFX2kxalEKTe+6pZXR9kx0X3olhXdmqJ+GIF6lyfC8ArUCnZ8PPvJ9xfXn4KLMCkuBlo306payJMWD\n; 9BoGspE9LrVop4ajfevgQrz82U5xkQyg7onyEWfpUzxSQBlUnjWRZM8t66cwi/jU5h5eIMbH40hKuv\n; LqS6UFwh7mhv1RL4AYojY9VQbqkQRWL34icPtQ5o6dXqR9fwQlLgrYuPLUSrH96TvZDigsg1UwxFc3\n; c/e5rfsRNRI/JFNNns8MBy8QKNvJYKzGgf4NoXf8LH3+5xTDw4jP0szH16ZvBlybdcitMhpJzrwKUB\n; jcmCiDkDvv/liK92qRWLeTdsZYSsQaPhhXOOZD44uLJhqXAIxYKIQUIaSqBGg+Di09CuBiUYxQ0E/t\n; 0Hc2bk9gQB26kiYJEK7a6kJyqdvL/bKSiKOmx9dGumfpnA35/jnsDH4/H6BAH7Qba3dobTTQYrOY0N\n; usOnbr9JieEiCPgSzzH4/Pz8dpVASw3T2OY0Y2V7FkBrdjDOarErkLPmpgNPkb/u5e8l4CqHG1IqhU\n; xEoQuZztlwuIRw8705WFma8uB3a0jcUhb05pQ/zdp+Ufso8R8hdLqygDs6OnptcXHxD+gx9V8R6H6a\n; dQ8WrSwq81XZ/1NToLztuY9T8D3U687/r/0D2siIlZoKRzIAAAAASUVORK5CYII=\n; thumbnail end\n; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, "machine_end_gcode": { "default_value": "G1 X5 Y{machine_depth*0.95} F{speed_travel*60} ; present print\nM140 S0 ; turn off heat bed\nM104 S0 ; turn off temperature\nM84; disable motors ; disable stepper motors" }, "material_diameter": { "default_value": 1.75 }, From 960d2a231592930cf880cebff66fbd98dfef99b9 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 19 Jun 2025 10:15:37 +0200 Subject: [PATCH 205/299] Optimized application of stroke CURA-12566 --- plugins/PaintTool/PaintView.py | 36 +++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 71bf6cb014..32124872c4 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. import os +from PyQt6.QtCore import QRect from typing import Optional, List, Tuple, Dict from PyQt6.QtGui import QImage, QColor, QPainter @@ -85,22 +86,35 @@ class PaintView(View): bit_range_start, bit_range_end = self._current_bits_ranges set_value = self._paint_modes[self._current_paint_type].types[brush_color].value << self._current_bits_ranges[0] - clear_mask = 0xffffffff ^ (((0xffffffff << (32 - 1 - (bit_range_end - bit_range_start))) & 0xffffffff) >> (32 - 1 - bit_range_end)) + full_int32 = 0xffffffff + clear_mask = full_int32 ^ (((full_int32 << (32 - 1 - (bit_range_end - bit_range_start))) & full_int32) >> (32 - 1 - bit_range_end)) + image_rect = QRect(0, 0, stroke_image.width(), stroke_image.height()) - for x in range(stroke_image.width()): - for y in range(stroke_image.height()): - stroke_pixel = stroke_image.pixel(x, y) - actual_pixel = actual_image.pixel(start_x + x, start_y + y) - if stroke_pixel != 0: - new_pixel = (actual_pixel & clear_mask) | set_value - else: - new_pixel = actual_pixel - stroke_image.setPixel(x, y, new_pixel) + clear_bits_image = stroke_image.copy() + clear_bits_image.invertPixels() + painter = QPainter(clear_bits_image) + painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Lighten) + painter.fillRect(image_rect, clear_mask) + painter.end() + + set_value_image = stroke_image.copy() + painter = QPainter(set_value_image) + painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Multiply) + painter.fillRect(image_rect, set_value) + painter.end() + + stroked_image = actual_image.copy(start_x, start_y, stroke_image.width(), stroke_image.height()) + painter = QPainter(stroked_image) + painter.setCompositionMode(QPainter.CompositionMode.RasterOp_SourceAndDestination) + painter.drawImage(0, 0, clear_bits_image) + painter.setCompositionMode(QPainter.CompositionMode.RasterOp_SourceOrDestination) + painter.drawImage(0, 0, set_value_image) + painter.end() self._stroke_redo_stack.clear() if len(self._stroke_undo_stack) >= PaintView.UNDO_STACK_SIZE: self._stroke_undo_stack.pop(0) - undo_image = self._forceOpaqueDeepCopy(self._current_paint_texture.setSubImage(stroke_image, start_x, start_y)) + undo_image = self._forceOpaqueDeepCopy(self._current_paint_texture.setSubImage(stroked_image, start_x, start_y)) if undo_image is not None: self._stroke_undo_stack.append((undo_image, start_x, start_y)) From 3c04680c71b1f554c4504d9a939c9ff9ae5349cf Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 19 Jun 2025 15:57:07 +0200 Subject: [PATCH 206/299] Load and save texture data mapping in 3MF CURA-12566 --- plugins/3MFReader/ThreeMFReader.py | 23 ++++++++++++++++++++--- plugins/3MFWriter/ThreeMFWriter.py | 12 ++++++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 4275fbc7b5..aae6ea56ae 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -1,13 +1,14 @@ # Copyright (c) 2021-2022 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. - +import json import os.path import zipfile from typing import List, Optional, Union, TYPE_CHECKING, cast import pySavitar as Savitar import numpy -from PyQt6.QtGui import QImage +from PyQt6.QtCore import QBuffer +from PyQt6.QtGui import QImage, QImageReader from UM.Logger import Logger from UM.Math.Matrix import Matrix @@ -232,11 +233,27 @@ class ThreeMFReader(MeshReader): if texture_path != "" and archive is not None: texture_data = archive.open(texture_path).read() - texture_image = QImage.fromData(texture_data, "PNG") + texture_buffer = QBuffer() + texture_buffer.open(QBuffer.OpenModeFlag.ReadWrite) + texture_buffer.write(texture_data) + + image_reader = QImageReader(texture_buffer, b"png") + + texture_buffer.seek(0) + texture_image = image_reader.read() texture = Texture(OpenGL.getInstance()) texture.setImage(texture_image) sliceable_decorator.setPaintTexture(texture) + texture_buffer.seek(0) + data_mapping_desc = image_reader.text("Description") + if data_mapping_desc != "": + data_mapping = json.loads(data_mapping_desc) + for key, value in data_mapping.items(): + # Tuples are stored as lists in json, restore them back to tuples + data_mapping[key] = tuple(value) + sliceable_decorator.setTextureDataMapping(data_mapping) + return um_node def _read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]: diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 4cb7840841..9d35f88e6d 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -29,7 +29,7 @@ from cura.Scene.CuraSceneNode import CuraSceneNode from cura.Snapshot import Snapshot from PyQt6.QtCore import Qt, QBuffer -from PyQt6.QtGui import QImage, QPainter +from PyQt6.QtGui import QImage, QPainter, QImageWriter import pySavitar as Savitar from .UCPDialog import UCPDialog @@ -163,12 +163,16 @@ class ThreeMFWriter(MeshWriter): if texture is not None and archive is not None and uv_coordinates_array is not None and len(uv_coordinates_array) > 0: texture_image = texture.getImage() if texture_image is not None: - texture_path = f"{TEXTURES_PATH}/{id(um_node)}.png" - texture_buffer = QBuffer() texture_buffer.open(QBuffer.OpenModeFlag.ReadWrite) - texture_image.save(texture_buffer, "PNG") + image_writer = QImageWriter(texture_buffer, b"png") + texture_data_mapping = um_node.callDecoration("getTextureDataMapping") + if texture_data_mapping is not None: + image_writer.setText("Description", json.dumps(texture_data_mapping)) + image_writer.write(texture_image) + + texture_path = f"{TEXTURES_PATH}/{id(um_node)}.png" texture_file = zipfile.ZipInfo(texture_path) # Don't try to compress texture file, because the PNG is pretty much as compact as it will get archive.writestr(texture_file, texture_buffer.data()) From 8af5514200fb8c7c3b22ec62f2e5d732cb9162b8 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 19 Jun 2025 22:06:21 +0200 Subject: [PATCH 207/299] Update normal.inst.cfg Quality does not have any values The layer height defaults to 0.2 which makes it identical to other global quality profile for draft resources/quality/draft.inst.cfg --- resources/quality/normal.inst.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/quality/normal.inst.cfg b/resources/quality/normal.inst.cfg index 4ca290b0b5..71b9e92ae3 100644 --- a/resources/quality/normal.inst.cfg +++ b/resources/quality/normal.inst.cfg @@ -11,4 +11,4 @@ type = quality weight = 0 [values] - +layer_height = 0.1 From c10cedc0b9a019d5bf3a629f90bfc313ce715bc7 Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Thu, 19 Jun 2025 20:07:49 +0000 Subject: [PATCH 208/299] Apply printer-linter format --- resources/quality/normal.inst.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/quality/normal.inst.cfg b/resources/quality/normal.inst.cfg index 71b9e92ae3..5d82bf612c 100644 --- a/resources/quality/normal.inst.cfg +++ b/resources/quality/normal.inst.cfg @@ -12,3 +12,4 @@ weight = 0 [values] layer_height = 0.1 + From 95f35275be464edf537a4abb76bd16c04f95cd60 Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Fri, 20 Jun 2025 07:22:21 +0000 Subject: [PATCH 209/299] Apply printer-linter format --- .../definitions/anycubic_kobra3v2.def.json | 52 ++++++------- .../anycubic_kobra3v2_ACE_PRO.def.json | 77 +++++++++---------- ...ycubic_kobra3v2_ACEPRO_extruder_0.def.json | 2 +- ...ycubic_kobra3v2_ACEPRO_extruder_1.def.json | 2 +- ...ycubic_kobra3v2_ACEPRO_extruder_2.def.json | 2 +- ...ycubic_kobra3v2_ACEPRO_extruder_3.def.json | 2 +- .../anycubic_kobra3v2_extruder_0.def.json | 2 +- 7 files changed, 68 insertions(+), 71 deletions(-) diff --git a/resources/definitions/anycubic_kobra3v2.def.json b/resources/definitions/anycubic_kobra3v2.def.json index 143d08b92b..6b8df0cc4b 100644 --- a/resources/definitions/anycubic_kobra3v2.def.json +++ b/resources/definitions/anycubic_kobra3v2.def.json @@ -8,34 +8,35 @@ "author": "Sam Bonnekamp", "manufacturer": "Anycubic", "file_formats": "text/x-gcode", - "has_textured_buildplate": true, "platform": "anycubic_kobra3v2_buildplate.stl", - "machine_extruder_trains": { "0": "anycubic_kobra3v2_extruder_0" } + "has_textured_buildplate": true, + "machine_extruder_trains": { "0": "anycubic_kobra3v2_extruder_0" } }, "overrides": { + "adhesion_type": { "value": "'skirt'" }, + "layer_height": { "default_value": 0.2 }, + "machine_buildplate_type": { "default_value": "PEI Spring Steel" }, + "machine_center_is_zero": { "default_value": false }, + "machine_depth": { "default_value": 250 }, + "machine_end_gcode": { "default_value": "G1 X5 Y{machine_depth*0.95} F{speed_travel*60} ; present print\nM140 S0 ; turn off heat bed\nM104 S0 ; turn off temperature\nM84; disable motors ; disable stepper motors" }, + "machine_heated_bed": { "default_value": true }, "machine_height": { "default_value": 260 }, - "machine_width": { "default_value": 250 }, - "machine_depth": { "default_value": 250 }, - "machine_name": - { - "description": "Anycubic Kobra 3 v2", - "default_value": "Anycubic Kobra 3 v2" + "machine_name": + { + "default_value": "Anycubic Kobra 3 v2", + "description": "Anycubic Kobra 3 v2" }, - "machine_buildplate_type": { "default_value": "PEI Spring Steel" }, - "machine_heated_bed": { "default_value": true}, - "machine_center_is_zero": { "default_value": false }, - "machine_start_gcode_first": { "default_value": true }, - "machine_start_gcode": { "default_value": "; thumbnail begin 32x32\n; iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAX\n; NSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAARWSURBVHgB1Vc7bx1FFD5n/cC+YOQ4RBTXlg0STfIH\n; gM78h0SAhGgQjyqARO8eFEQFBaKhCHIoKagcOkJJQUWBI19XJLaJgp+5M8x5zZzdO+sg0ZCR1zM7u3\n; e+73znMbMAT0KLMVqPdKVhvuze+o2NjUafget7Gz4GeO3s7Ow29YiYiXSJ2TPft0BwEmZ2dpYnp+Ec\n; 8NPT09tpyOAhhF4CXSBPwhOvEZk+B/ynNFzd2QvwxlfHMEq9PqR//mVaWcegmqKCIf9FKGS2Px30Ey\n; A/Hh8fE/gWgRPomww+VkxVgYFoWcz3xXpUJo2QsXvEFu8qAQJvmobA13b3I1u+Q+AhQuRfB1kTBDS6\n; FUVmVBx5iwmqNIgNv9ONkUzg4ODgBQNn2b80yyNbCzFQqMsC4MCNg/eveSQGdQM6glhXYDAYbJHvRw\n; q+ux90dQ8eeBxacaD+5T5ZSdLbfIcT61hTgCZTuq1R/zqDjxMOva6SKzBdMQRoO1OsovcLZrpPkmOO\n; ytibCdPejOQCGJHl5l+zlEGNxBiuvjxI1zNwZTgDzw4a6LbV6/fTT8eqSGD/G3hVgTQRT05OOv6Nyl\n; zBwxgW5iN8/e4leOWlOTivESjAlNhvYJoEvTEA6gq7wIqMyZ76zevPw5XlWdi5/wi+2foLNu88hAeH\n; QQKQJG/ScjjFY1cUFD3mYKxmgeef+1z9AstO4KMEfu3zXdi594gXlHIj3hYFY6su5fVQU7OjgAvZNg\n; kpaDFn8jvrC9zf+GEvgZ+16HqX5QRVctl6FmAyXhq3TmHnROBhWuBysp7aj7/+rS+IWybKO8oPWTns\n; zFX2kxalEKTe+6pZXR9kx0X3olhXdmqJ+GIF6lyfC8ArUCnZ8PPvJ9xfXn4KLMCkuBlo306payJMWD\n; 9BoGspE9LrVop4ajfevgQrz82U5xkQyg7onyEWfpUzxSQBlUnjWRZM8t66cwi/jU5h5eIMbH40hKuv\n; LqS6UFwh7mhv1RL4AYojY9VQbqkQRWL34icPtQ5o6dXqR9fwQlLgrYuPLUSrH96TvZDigsg1UwxFc3\n; c/e5rfsRNRI/JFNNns8MBy8QKNvJYKzGgf4NoXf8LH3+5xTDw4jP0szH16ZvBlybdcitMhpJzrwKUB\n; jcmCiDkDvv/liK92qRWLeTdsZYSsQaPhhXOOZD44uLJhqXAIxYKIQUIaSqBGg+Di09CuBiUYxQ0E/t\n; 0Hc2bk9gQB26kiYJEK7a6kJyqdvL/bKSiKOmx9dGumfpnA35/jnsDH4/H6BAH7Qba3dobTTQYrOY0N\n; usOnbr9JieEiCPgSzzH4/Pz8dpVASw3T2OY0Y2V7FkBrdjDOarErkLPmpgNPkb/u5e8l4CqHG1IqhU\n; xEoQuZztlwuIRw8705WFma8uB3a0jcUhb05pQ/zdp+Ufso8R8hdLqygDs6OnptcXHxD+gx9V8R6H6a\n; dQ8WrSwq81XZ/1NToLztuY9T8D3U687/r/0D2siIlZoKRzIAAAAASUVORK5CYII=\n; thumbnail end\n; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, - "machine_end_gcode": { "default_value": "G1 X5 Y{machine_depth*0.95} F{speed_travel*60} ; present print\nM140 S0 ; turn off heat bed\nM104 S0 ; turn off temperature\nM84; disable motors ; disable stepper motors" }, - - "material_bed_temperature": - { "maximum_value": "110", - "maximum_value_warning": "90" - }, - "material_print_temperature":{ "maximum_value": 300 }, - "material_diameter": { "default_value": 1.75 }, - "material_initial_print_temperature": + "machine_start_gcode": { "default_value": "; thumbnail begin 32x32\n; iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAX\n; NSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAARWSURBVHgB1Vc7bx1FFD5n/cC+YOQ4RBTXlg0STfIH\n; gM78h0SAhGgQjyqARO8eFEQFBaKhCHIoKagcOkJJQUWBI19XJLaJgp+5M8x5zZzdO+sg0ZCR1zM7u3\n; e+73znMbMAT0KLMVqPdKVhvuze+o2NjUafget7Gz4GeO3s7Ow29YiYiXSJ2TPft0BwEmZ2dpYnp+Ec\n; 8NPT09tpyOAhhF4CXSBPwhOvEZk+B/ynNFzd2QvwxlfHMEq9PqR//mVaWcegmqKCIf9FKGS2Px30Ey\n; A/Hh8fE/gWgRPomww+VkxVgYFoWcz3xXpUJo2QsXvEFu8qAQJvmobA13b3I1u+Q+AhQuRfB1kTBDS6\n; FUVmVBx5iwmqNIgNv9ONkUzg4ODgBQNn2b80yyNbCzFQqMsC4MCNg/eveSQGdQM6glhXYDAYbJHvRw\n; q+ux90dQ8eeBxacaD+5T5ZSdLbfIcT61hTgCZTuq1R/zqDjxMOva6SKzBdMQRoO1OsovcLZrpPkmOO\n; ytibCdPejOQCGJHl5l+zlEGNxBiuvjxI1zNwZTgDzw4a6LbV6/fTT8eqSGD/G3hVgTQRT05OOv6Nyl\n; zBwxgW5iN8/e4leOWlOTivESjAlNhvYJoEvTEA6gq7wIqMyZ76zevPw5XlWdi5/wi+2foLNu88hAeH\n; QQKQJG/ScjjFY1cUFD3mYKxmgeef+1z9AstO4KMEfu3zXdi594gXlHIj3hYFY6su5fVQU7OjgAvZNg\n; kpaDFn8jvrC9zf+GEvgZ+16HqX5QRVctl6FmAyXhq3TmHnROBhWuBysp7aj7/+rS+IWybKO8oPWTns\n; zFX2kxalEKTe+6pZXR9kx0X3olhXdmqJ+GIF6lyfC8ArUCnZ8PPvJ9xfXn4KLMCkuBlo306payJMWD\n; 9BoGspE9LrVop4ajfevgQrz82U5xkQyg7onyEWfpUzxSQBlUnjWRZM8t66cwi/jU5h5eIMbH40hKuv\n; LqS6UFwh7mhv1RL4AYojY9VQbqkQRWL34icPtQ5o6dXqR9fwQlLgrYuPLUSrH96TvZDigsg1UwxFc3\n; c/e5rfsRNRI/JFNNns8MBy8QKNvJYKzGgf4NoXf8LH3+5xTDw4jP0szH16ZvBlybdcitMhpJzrwKUB\n; jcmCiDkDvv/liK92qRWLeTdsZYSsQaPhhXOOZD44uLJhqXAIxYKIQUIaSqBGg+Di09CuBiUYxQ0E/t\n; 0Hc2bk9gQB26kiYJEK7a6kJyqdvL/bKSiKOmx9dGumfpnA35/jnsDH4/H6BAH7Qba3dobTTQYrOY0N\n; usOnbr9JieEiCPgSzzH4/Pz8dpVASw3T2OY0Y2V7FkBrdjDOarErkLPmpgNPkb/u5e8l4CqHG1IqhU\n; xEoQuZztlwuIRw8705WFma8uB3a0jcUhb05pQ/zdp+Ufso8R8hdLqygDs6OnptcXHxD+gx9V8R6H6a\n; dQ8WrSwq81XZ/1NToLztuY9T8D3U687/r/0D2siIlZoKRzIAAAAASUVORK5CYII=\n; thumbnail end\n; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, + "machine_start_gcode_first": { "default_value": true }, + "machine_width": { "default_value": 250 }, + "material_bed_temperature": + { + "maximum_value": "110", + "maximum_value_warning": "90" + }, + "material_diameter": { "default_value": 1.75 }, + "material_initial_print_temperature": { "maximum_value_warning": 295, "value": "material_print_temperature + 5" @@ -46,9 +47,6 @@ "maximum_value_warning": 295, "value": "material_print_temperature + 5" }, - - "layer_height": { "default_value": 0.2 }, - "adhesion_type": { "value": "'skirt'" }, - "relative_extrusion" : {"value": true} + "relative_extrusion": { "value": true } } -} +} \ No newline at end of file diff --git a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json index 6e6fb31e2a..fc464c9eee 100644 --- a/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json +++ b/resources/definitions/anycubic_kobra3v2_ACE_PRO.def.json @@ -8,55 +8,54 @@ "author": "Sam Bonnekamp", "manufacturer": "Anycubic", "file_formats": "text/x-gcode", - "has_textured_buildplate": true, "platform": "anycubic_kobra3v2_buildplate.stl", - "machine_extruder_trains": { - "0": "anycubic_kobra3v2_ACEPRO_extruder_0", - "1": "anycubic_kobra3v2_ACEPRO_extruder_1", - "2": "anycubic_kobra3v2_ACEPRO_extruder_2", - "3": "anycubic_kobra3v2_ACEPRO_extruder_3" - } + "has_textured_buildplate": true, + "machine_extruder_trains": + { + "0": "anycubic_kobra3v2_ACEPRO_extruder_0", + "1": "anycubic_kobra3v2_ACEPRO_extruder_1", + "2": "anycubic_kobra3v2_ACEPRO_extruder_2", + "3": "anycubic_kobra3v2_ACEPRO_extruder_3" + } }, "overrides": { - "machine_height": { "default_value": 260 }, - "machine_width": { "default_value": 250 }, - "machine_depth": { "default_value": 250 }, - "machine_name": - { - "description": "Anycubic Kobra 3 v2", - "default_value": "Anycubic Kobra 3 v2" - }, + "adhesion_type": { "value": "'skirt'" }, + "layer_height": { "default_value": 0.2 }, + "machine_buildplate_type": { "default_value": "PEI Spring Steel" }, + "machine_center_is_zero": { "default_value": false }, + "machine_depth": { "default_value": 250 }, + "machine_end_gcode": { "default_value": "G1 X5 Y{machine_depth*0.95} F{speed_travel*60} ; present print\nM140 S0 ; turn off heat bed\nM104 S0 ; turn off temperature\nM84; disable motors ; disable stepper motors" }, "machine_extruder_count": { "default_value": 4 }, - "machine_buildplate_type": { "default_value": "PEI Spring Steel" }, - "machine_heated_bed": { "default_value": true}, - "material_bed_temperature": - { - "maximum_value": "110", - "maximum_value_warning": "90" - }, - "material_print_temp_wait": { "value": true }, - "machine_center_is_zero": { "default_value": false }, - "machine_start_gcode_first": { "default_value": true }, - "machine_start_gcode": { "default_value": "; thumbnail begin 32x32\n; iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAX\n; NSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAARWSURBVHgB1Vc7bx1FFD5n/cC+YOQ4RBTXlg0STfIH\n; gM78h0SAhGgQjyqARO8eFEQFBaKhCHIoKagcOkJJQUWBI19XJLaJgp+5M8x5zZzdO+sg0ZCR1zM7u3\n; e+73znMbMAT0KLMVqPdKVhvuze+o2NjUafget7Gz4GeO3s7Ow29YiYiXSJ2TPft0BwEmZ2dpYnp+Ec\n; 8NPT09tpyOAhhF4CXSBPwhOvEZk+B/ynNFzd2QvwxlfHMEq9PqR//mVaWcegmqKCIf9FKGS2Px30Ey\n; A/Hh8fE/gWgRPomww+VkxVgYFoWcz3xXpUJo2QsXvEFu8qAQJvmobA13b3I1u+Q+AhQuRfB1kTBDS6\n; FUVmVBx5iwmqNIgNv9ONkUzg4ODgBQNn2b80yyNbCzFQqMsC4MCNg/eveSQGdQM6glhXYDAYbJHvRw\n; q+ux90dQ8eeBxacaD+5T5ZSdLbfIcT61hTgCZTuq1R/zqDjxMOva6SKzBdMQRoO1OsovcLZrpPkmOO\n; ytibCdPejOQCGJHl5l+zlEGNxBiuvjxI1zNwZTgDzw4a6LbV6/fTT8eqSGD/G3hVgTQRT05OOv6Nyl\n; zBwxgW5iN8/e4leOWlOTivESjAlNhvYJoEvTEA6gq7wIqMyZ76zevPw5XlWdi5/wi+2foLNu88hAeH\n; QQKQJG/ScjjFY1cUFD3mYKxmgeef+1z9AstO4KMEfu3zXdi594gXlHIj3hYFY6su5fVQU7OjgAvZNg\n; kpaDFn8jvrC9zf+GEvgZ+16HqX5QRVctl6FmAyXhq3TmHnROBhWuBysp7aj7/+rS+IWybKO8oPWTns\n; zFX2kxalEKTe+6pZXR9kx0X3olhXdmqJ+GIF6lyfC8ArUCnZ8PPvJ9xfXn4KLMCkuBlo306payJMWD\n; 9BoGspE9LrVop4ajfevgQrz82U5xkQyg7onyEWfpUzxSQBlUnjWRZM8t66cwi/jU5h5eIMbH40hKuv\n; LqS6UFwh7mhv1RL4AYojY9VQbqkQRWL34icPtQ5o6dXqR9fwQlLgrYuPLUSrH96TvZDigsg1UwxFc3\n; c/e5rfsRNRI/JFNNns8MBy8QKNvJYKzGgf4NoXf8LH3+5xTDw4jP0szH16ZvBlybdcitMhpJzrwKUB\n; jcmCiDkDvv/liK92qRWLeTdsZYSsQaPhhXOOZD44uLJhqXAIxYKIQUIaSqBGg+Di09CuBiUYxQ0E/t\n; 0Hc2bk9gQB26kiYJEK7a6kJyqdvL/bKSiKOmx9dGumfpnA35/jnsDH4/H6BAH7Qba3dobTTQYrOY0N\n; usOnbr9JieEiCPgSzzH4/Pz8dpVASw3T2OY0Y2V7FkBrdjDOarErkLPmpgNPkb/u5e8l4CqHG1IqhU\n; xEoQuZztlwuIRw8705WFma8uB3a0jcUhb05pQ/zdp+Ufso8R8hdLqygDs6OnptcXHxD+gx9V8R6H6a\n; dQ8WrSwq81XZ/1NToLztuY9T8D3U687/r/0D2siIlZoKRzIAAAAASUVORK5CYII=\n; thumbnail end\n; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, - "machine_end_gcode": { "default_value": "G1 X5 Y{machine_depth*0.95} F{speed_travel*60} ; present print\nM140 S0 ; turn off heat bed\nM104 S0 ; turn off temperature\nM84; disable motors ; disable stepper motors" }, - - "material_diameter": { "default_value": 1.75 }, - "material_initial_print_temperature": - { + "machine_heated_bed": { "default_value": true }, + "machine_height": { "default_value": 260 }, + "machine_name": + { + "default_value": "Anycubic Kobra 3 v2", + "description": "Anycubic Kobra 3 v2" + }, + "machine_start_gcode": { "default_value": "; thumbnail begin 32x32\n; iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAX\n; NSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAARWSURBVHgB1Vc7bx1FFD5n/cC+YOQ4RBTXlg0STfIH\n; gM78h0SAhGgQjyqARO8eFEQFBaKhCHIoKagcOkJJQUWBI19XJLaJgp+5M8x5zZzdO+sg0ZCR1zM7u3\n; e+73znMbMAT0KLMVqPdKVhvuze+o2NjUafget7Gz4GeO3s7Ow29YiYiXSJ2TPft0BwEmZ2dpYnp+Ec\n; 8NPT09tpyOAhhF4CXSBPwhOvEZk+B/ynNFzd2QvwxlfHMEq9PqR//mVaWcegmqKCIf9FKGS2Px30Ey\n; A/Hh8fE/gWgRPomww+VkxVgYFoWcz3xXpUJo2QsXvEFu8qAQJvmobA13b3I1u+Q+AhQuRfB1kTBDS6\n; FUVmVBx5iwmqNIgNv9ONkUzg4ODgBQNn2b80yyNbCzFQqMsC4MCNg/eveSQGdQM6glhXYDAYbJHvRw\n; q+ux90dQ8eeBxacaD+5T5ZSdLbfIcT61hTgCZTuq1R/zqDjxMOva6SKzBdMQRoO1OsovcLZrpPkmOO\n; ytibCdPejOQCGJHl5l+zlEGNxBiuvjxI1zNwZTgDzw4a6LbV6/fTT8eqSGD/G3hVgTQRT05OOv6Nyl\n; zBwxgW5iN8/e4leOWlOTivESjAlNhvYJoEvTEA6gq7wIqMyZ76zevPw5XlWdi5/wi+2foLNu88hAeH\n; QQKQJG/ScjjFY1cUFD3mYKxmgeef+1z9AstO4KMEfu3zXdi594gXlHIj3hYFY6su5fVQU7OjgAvZNg\n; kpaDFn8jvrC9zf+GEvgZ+16HqX5QRVctl6FmAyXhq3TmHnROBhWuBysp7aj7/+rS+IWybKO8oPWTns\n; zFX2kxalEKTe+6pZXR9kx0X3olhXdmqJ+GIF6lyfC8ArUCnZ8PPvJ9xfXn4KLMCkuBlo306payJMWD\n; 9BoGspE9LrVop4ajfevgQrz82U5xkQyg7onyEWfpUzxSQBlUnjWRZM8t66cwi/jU5h5eIMbH40hKuv\n; LqS6UFwh7mhv1RL4AYojY9VQbqkQRWL34icPtQ5o6dXqR9fwQlLgrYuPLUSrH96TvZDigsg1UwxFc3\n; c/e5rfsRNRI/JFNNns8MBy8QKNvJYKzGgf4NoXf8LH3+5xTDw4jP0szH16ZvBlybdcitMhpJzrwKUB\n; jcmCiDkDvv/liK92qRWLeTdsZYSsQaPhhXOOZD44uLJhqXAIxYKIQUIaSqBGg+Di09CuBiUYxQ0E/t\n; 0Hc2bk9gQB26kiYJEK7a6kJyqdvL/bKSiKOmx9dGumfpnA35/jnsDH4/H6BAH7Qba3dobTTQYrOY0N\n; usOnbr9JieEiCPgSzzH4/Pz8dpVASw3T2OY0Y2V7FkBrdjDOarErkLPmpgNPkb/u5e8l4CqHG1IqhU\n; xEoQuZztlwuIRw8705WFma8uB3a0jcUhb05pQ/zdp+Ufso8R8hdLqygDs6OnptcXHxD+gx9V8R6H6a\n; dQ8WrSwq81XZ/1NToLztuY9T8D3U687/r/0D2siIlZoKRzIAAAAASUVORK5CYII=\n; thumbnail end\n; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.45mm\n; top infill extrusion width = 0.42mm\n; support material extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n;TYPE:Custom\nG9111 bedTemp={material_bed_temperature} extruderTemp={material_print_temperature}\nM117 ;display LCD message\nM900 K0.05 ;linear advance factor, ive only seen this set to k0.05\n;START HEADER\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nT0 ;set or report the current extruder or other tool\nM107 ; turn fan off" }, + "machine_start_gcode_first": { "default_value": true }, + "machine_width": { "default_value": 250 }, + "material_bed_temperature": + { + "maximum_value": "110", + "maximum_value_warning": "90" + }, + "material_diameter": { "default_value": 1.75 }, + "material_initial_print_temperature": + { "maximum_value_warning": 295, "value": "material_print_temperature + 5" - }, - "material_print_temperature": { "maximum_value": 300 }, - "material_standby_temperature" : {"default_value": "material_print_temperature"}, + }, + "material_print_temp_wait": { "value": true }, + "material_print_temperature": { "maximum_value": 300 }, "material_print_temperature_layer_0": { "maximum_value_warning": 295, "value": "material_print_temperature + 5" }, - - "layer_height": { "default_value": 0.2 }, - "adhesion_type": { "value": "'skirt'" }, - "relative_extrusion" : {"value": true} + "material_standby_temperature": { "default_value": "material_print_temperature" }, + "relative_extrusion": { "value": true } } -} +} \ No newline at end of file diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json index ab4a7d1a68..5537606b12 100644 --- a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_0.def.json @@ -13,4 +13,4 @@ "machine_nozzle_size": { "default_value": 0.4 }, "material_diameter": { "default_value": 1.75 } } -} +} \ No newline at end of file diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json index 029e7ad2bf..2370427eea 100644 --- a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_1.def.json @@ -13,4 +13,4 @@ "machine_nozzle_size": { "default_value": 0.4 }, "material_diameter": { "default_value": 1.75 } } -} +} \ No newline at end of file diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json index fb732d5fd4..ae860e5f7a 100644 --- a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_2.def.json @@ -13,4 +13,4 @@ "machine_nozzle_size": { "default_value": 0.4 }, "material_diameter": { "default_value": 1.75 } } -} +} \ No newline at end of file diff --git a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json index 2f64b0532a..fed2c1fc6b 100644 --- a/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json +++ b/resources/extruders/anycubic_kobra3v2_ACEPRO_extruder_3.def.json @@ -13,4 +13,4 @@ "machine_nozzle_size": { "default_value": 0.4 }, "material_diameter": { "default_value": 1.75 } } -} +} \ No newline at end of file diff --git a/resources/extruders/anycubic_kobra3v2_extruder_0.def.json b/resources/extruders/anycubic_kobra3v2_extruder_0.def.json index dba5e6e559..f5983cf3fb 100644 --- a/resources/extruders/anycubic_kobra3v2_extruder_0.def.json +++ b/resources/extruders/anycubic_kobra3v2_extruder_0.def.json @@ -13,4 +13,4 @@ "machine_nozzle_size": { "default_value": 0.4 }, "material_diameter": { "default_value": 1.75 } } -} +} \ No newline at end of file From be3d6201425e42cf44a710a52dbc200191b551b5 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Fri, 20 Jun 2025 12:28:51 +0200 Subject: [PATCH 210/299] typo fix --- plugins/DigitalLibrary/resources/qml/ProjectSummaryCard.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/DigitalLibrary/resources/qml/ProjectSummaryCard.qml b/plugins/DigitalLibrary/resources/qml/ProjectSummaryCard.qml index 133cc0edde..931a4fe9f0 100644 --- a/plugins/DigitalLibrary/resources/qml/ProjectSummaryCard.qml +++ b/plugins/DigitalLibrary/resources/qml/ProjectSummaryCard.qml @@ -14,7 +14,7 @@ Cura.RoundedRectangle border.color: enabled ? UM.Theme.getColor("lining") : UM.Theme.getColor("action_button_disabled_border") border.width: UM.Theme.getSize("default_lining").width radius: UM.Theme.getSize("default_radius").width - color: getBackgoundColor() + color: getBackgroundColor() signal clicked() property alias imageSource: projectImage.source property alias projectNameText: displayNameLabel.text @@ -106,4 +106,4 @@ Cura.RoundedRectangle return UM.Theme.getColor("action_button_disabled") } } -} \ No newline at end of file +} From 4001e23d913a84bece91bbd54976adb272627d2d Mon Sep 17 00:00:00 2001 From: HellAholic Date: Fri, 20 Jun 2025 14:08:09 +0200 Subject: [PATCH 211/299] Update Cura.proto Add the types missing --- plugins/CuraEngineBackend/Cura.proto | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto index 8018c9186f..cdbe463d81 100644 --- a/plugins/CuraEngineBackend/Cura.proto +++ b/plugins/CuraEngineBackend/Cura.proto @@ -78,10 +78,14 @@ message Polygon { SkirtType = 5; InfillType = 6; SupportInfillType = 7; - MoveUnretractedType = 8; - MoveRetractedType = 9; + MoveUnretracted = 8; + MoveRetracted = 9; SupportInterfaceType = 10; PrimeTowerType = 11; + MoveWhileRetracting = 12; + MoveWhileUnretracting = 13; + StationaryRetractUnretract = 14; + NumPrintFeatureTypes = 15; } Type type = 1; // Type of move bytes points = 2; // The points of the polygon, or two points if only a line segment (Currently only line segments are used) From 436d5a669d4fc2af5cd656795ef06508e971d676 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Fri, 20 Jun 2025 20:39:43 +0200 Subject: [PATCH 212/299] Create find-packages.yml --- .github/workflows/find-packages.yml | 118 ++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 .github/workflows/find-packages.yml diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml new file mode 100644 index 0000000000..693dff9ae8 --- /dev/null +++ b/.github/workflows/find-packages.yml @@ -0,0 +1,118 @@ +name: Conan Package Discovery by Jira Ticket + +on: + workflow_dispatch: + inputs: + jira_ticket_number: + description: 'Jira ticket number for Conan package discovery (e.g., cura_12345)' + required: true + type: string + +jobs: + discover_conan_packages: + runs-on: ubuntu-latest + steps: + - name: Checkout repository code + uses: actions/checkout@v4 + + - name: Validate Jira Ticket Number Format + id: validate_input + run: | + set -eou pipefail + JIRA_TICKET="${{ github.event.inputs.jira_ticket_number }}" + # Regex to validate the format: "cura_" followed by one or more digits. + # The '^' and '$' anchors ensure the entire string matches the pattern. + if [[ ! "$JIRA_TICKET" =~ ^cura_[0-9]+$ ]]; then + # Output an error message that will appear as an annotation in the GitHub Actions UI. + # This provides immediate and clear feedback to the user about the expected format. + echo "::error::Invalid Jira ticket number format. Expected format: cura_# (e.g., cura_12345)." + # Exit with a non-zero status code to fail the workflow immediately. + exit 1 + fi + echo "Jira ticket number '$JIRA_TICKET' is valid." + + - name: Setup Conan Client + uses: conan-io/setup-conan@v1 + + - name: Install jq for JSON parsing + run: sudo apt-get update && sudo apt-get install -y jq + + - name: Discover Conan Packages + id: conan_search + env: + CONAN_USERNAME: ${{ secrets.CONAN_USERNAME }} + CONAN_PASSWORD: ${{ secrets.CONAN_PASSWORD }} + run: | + set -eou pipefail + JIRA_TICKET="${{ github.event.inputs.jira_ticket_number }}" + # Construct the full Conan package reference dynamically. + # The format '5.11.0-alpha.0@ultimaker/cura_#' is based on the user's requirement. + CONAN_PACKAGE_REFERENCE="5.11.0-alpha.0@ultimaker/${JIRA_TICKET}" + echo "Searching for Conan packages matching tag: $CONAN_PACKAGE_REFERENCE" + + # Initialize an empty array to store discovered packages. + # This array will hold Markdown-formatted strings for the summary. + DISCOVERED_PACKAGES=() + + # Get a list of all configured Conan remotes in JSON format. + # Conan 2.x's 'conan remote list --format=json' provides structured output. + # This dynamic approach ensures the workflow adapts to any remote configuration changes. + REMOTES_JSON=$(conan remote list --format=json) + + # Parse the JSON to extract remote names. + # The 'jq -r..name' command extracts the 'name' field from each object in the JSON array. + REMOTE_NAMES=$(echo "$REMOTES_JSON" | jq -r '..name') + + # Iterate through each remote to perform a targeted search for binaries. + # For Conan 2.x, 'conan list' is used for detailed package information. + # To find specific binaries, iteration over individual remotes is necessary. + for REMOTE_NAME in $REMOTE_NAMES; do + echo "Searching remote: $REMOTE_NAME" + # Authenticate with the remote if credentials are provided as secrets. + # This is a security best practice for private remotes. + if [ -n "${CONAN_USERNAME:-}" ] && [ -n "${CONAN_PASSWORD:-}" ]; then + echo "Attempting to log in to remote '$REMOTE_NAME'..." + conan remote login "$REMOTE_NAME" -u "$CONAN_USERNAME" -p "$CONAN_PASSWORD" || echo "Login failed for remote $REMOTE_NAME, continuing without authentication for this remote." + fi + # Execute 'conan list' for the specific package reference on the current remote. + # The '--format=json' flag ensures machine-readable output. + # Redirect stderr to /dev/null to suppress non-critical error messages (e.g., remote not found). + SEARCH_RESULT=$(conan list "$CONAN_PACKAGE_REFERENCE" -r "$REMOTE_NAME" --format=json 2>/dev/null || true) + + # Check if any packages were found in this remote's search result. + # The '.results.items | select(.recipe.id == "$CONAN_PACKAGE_REFERENCE")' + # filters for the exact recipe ID. + # '.packages.id' extracts package IDs if binaries are present. + FOUND_ITEMS=$(echo "$SEARCH_RESULT" | jq -r --arg ref "$CONAN_PACKAGE_REFERENCE" \ + '.results.items | select(.recipe.id == $ref) |.packages.id' 2>/dev/null || true) + + if [ -n "$FOUND_ITEMS" ]; then + # If packages are found, add them to the DISCOVERED_PACKAGES array. + # Format: "- `package/version@user/channel#package_id` (Remote: `remote_name`)" + while IFS= read -r PACKAGE_ID; do + DISCOVERED_PACKAGES+=("- \`${CONAN_PACKAGE_REFERENCE}#${PACKAGE_ID}\` (Remote: \`${REMOTE_NAME}\`)") + done <<< "$FOUND_ITEMS" + else + echo "No packages found in $REMOTE_NAME matching $CONAN_PACKAGE_REFERENCE" + fi + done + + # Prepare the summary content for the GitHub Actions run summary. + # This content will be written to the GITHUB_STEP_SUMMARY file. + echo "### Conan Packages Found for Jira Ticket: ${JIRA_TICKET}" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" # Add a blank line for spacing + echo "The workflow searched for Conan packages tagged \`${CONAN_PACKAGE_REFERENCE}\` across all configured remotes." >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" # Add a blank line for spacing + echo "**Discovered Packages:**" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" # Add a blank line for spacing + + if [ ${#DISCOVERED_PACKAGES[@]} -eq 0 ]; then + echo "*No packages found matching the specified tag.*" >> "$GITHUB_STEP_SUMMARY" + else + # Iterate through the array of discovered packages and append each to the summary file. + for PACKAGE_ENTRY in "${DISCOVERED_PACKAGES[@]}"; do + echo "$PACKAGE_ENTRY" >> "$GITHUB_STEP_SUMMARY" + done + fi + echo "" >> "$GITHUB_STEP_SUMMARY" # Add a blank line for spacing + echo "---" >> "$GITHUB_STEP_SUMMARY" # Add a separator for cleanliness \ No newline at end of file From 4948adf03e199b46351073c893f3e1297e4821e7 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Fri, 20 Jun 2025 21:02:32 +0200 Subject: [PATCH 213/299] Update find-packages.yml --- .github/workflows/find-packages.yml | 113 ++-------------------------- 1 file changed, 6 insertions(+), 107 deletions(-) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index 693dff9ae8..e9c60a89b4 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -9,110 +9,9 @@ on: type: string jobs: - discover_conan_packages: - runs-on: ubuntu-latest - steps: - - name: Checkout repository code - uses: actions/checkout@v4 - - - name: Validate Jira Ticket Number Format - id: validate_input - run: | - set -eou pipefail - JIRA_TICKET="${{ github.event.inputs.jira_ticket_number }}" - # Regex to validate the format: "cura_" followed by one or more digits. - # The '^' and '$' anchors ensure the entire string matches the pattern. - if [[ ! "$JIRA_TICKET" =~ ^cura_[0-9]+$ ]]; then - # Output an error message that will appear as an annotation in the GitHub Actions UI. - # This provides immediate and clear feedback to the user about the expected format. - echo "::error::Invalid Jira ticket number format. Expected format: cura_# (e.g., cura_12345)." - # Exit with a non-zero status code to fail the workflow immediately. - exit 1 - fi - echo "Jira ticket number '$JIRA_TICKET' is valid." - - - name: Setup Conan Client - uses: conan-io/setup-conan@v1 - - - name: Install jq for JSON parsing - run: sudo apt-get update && sudo apt-get install -y jq - - - name: Discover Conan Packages - id: conan_search - env: - CONAN_USERNAME: ${{ secrets.CONAN_USERNAME }} - CONAN_PASSWORD: ${{ secrets.CONAN_PASSWORD }} - run: | - set -eou pipefail - JIRA_TICKET="${{ github.event.inputs.jira_ticket_number }}" - # Construct the full Conan package reference dynamically. - # The format '5.11.0-alpha.0@ultimaker/cura_#' is based on the user's requirement. - CONAN_PACKAGE_REFERENCE="5.11.0-alpha.0@ultimaker/${JIRA_TICKET}" - echo "Searching for Conan packages matching tag: $CONAN_PACKAGE_REFERENCE" - - # Initialize an empty array to store discovered packages. - # This array will hold Markdown-formatted strings for the summary. - DISCOVERED_PACKAGES=() - - # Get a list of all configured Conan remotes in JSON format. - # Conan 2.x's 'conan remote list --format=json' provides structured output. - # This dynamic approach ensures the workflow adapts to any remote configuration changes. - REMOTES_JSON=$(conan remote list --format=json) - - # Parse the JSON to extract remote names. - # The 'jq -r..name' command extracts the 'name' field from each object in the JSON array. - REMOTE_NAMES=$(echo "$REMOTES_JSON" | jq -r '..name') - - # Iterate through each remote to perform a targeted search for binaries. - # For Conan 2.x, 'conan list' is used for detailed package information. - # To find specific binaries, iteration over individual remotes is necessary. - for REMOTE_NAME in $REMOTE_NAMES; do - echo "Searching remote: $REMOTE_NAME" - # Authenticate with the remote if credentials are provided as secrets. - # This is a security best practice for private remotes. - if [ -n "${CONAN_USERNAME:-}" ] && [ -n "${CONAN_PASSWORD:-}" ]; then - echo "Attempting to log in to remote '$REMOTE_NAME'..." - conan remote login "$REMOTE_NAME" -u "$CONAN_USERNAME" -p "$CONAN_PASSWORD" || echo "Login failed for remote $REMOTE_NAME, continuing without authentication for this remote." - fi - # Execute 'conan list' for the specific package reference on the current remote. - # The '--format=json' flag ensures machine-readable output. - # Redirect stderr to /dev/null to suppress non-critical error messages (e.g., remote not found). - SEARCH_RESULT=$(conan list "$CONAN_PACKAGE_REFERENCE" -r "$REMOTE_NAME" --format=json 2>/dev/null || true) - - # Check if any packages were found in this remote's search result. - # The '.results.items | select(.recipe.id == "$CONAN_PACKAGE_REFERENCE")' - # filters for the exact recipe ID. - # '.packages.id' extracts package IDs if binaries are present. - FOUND_ITEMS=$(echo "$SEARCH_RESULT" | jq -r --arg ref "$CONAN_PACKAGE_REFERENCE" \ - '.results.items | select(.recipe.id == $ref) |.packages.id' 2>/dev/null || true) - - if [ -n "$FOUND_ITEMS" ]; then - # If packages are found, add them to the DISCOVERED_PACKAGES array. - # Format: "- `package/version@user/channel#package_id` (Remote: `remote_name`)" - while IFS= read -r PACKAGE_ID; do - DISCOVERED_PACKAGES+=("- \`${CONAN_PACKAGE_REFERENCE}#${PACKAGE_ID}\` (Remote: \`${REMOTE_NAME}\`)") - done <<< "$FOUND_ITEMS" - else - echo "No packages found in $REMOTE_NAME matching $CONAN_PACKAGE_REFERENCE" - fi - done - - # Prepare the summary content for the GitHub Actions run summary. - # This content will be written to the GITHUB_STEP_SUMMARY file. - echo "### Conan Packages Found for Jira Ticket: ${JIRA_TICKET}" >> "$GITHUB_STEP_SUMMARY" - echo "" >> "$GITHUB_STEP_SUMMARY" # Add a blank line for spacing - echo "The workflow searched for Conan packages tagged \`${CONAN_PACKAGE_REFERENCE}\` across all configured remotes." >> "$GITHUB_STEP_SUMMARY" - echo "" >> "$GITHUB_STEP_SUMMARY" # Add a blank line for spacing - echo "**Discovered Packages:**" >> "$GITHUB_STEP_SUMMARY" - echo "" >> "$GITHUB_STEP_SUMMARY" # Add a blank line for spacing - - if [ ${#DISCOVERED_PACKAGES[@]} -eq 0 ]; then - echo "*No packages found matching the specified tag.*" >> "$GITHUB_STEP_SUMMARY" - else - # Iterate through the array of discovered packages and append each to the summary file. - for PACKAGE_ENTRY in "${DISCOVERED_PACKAGES[@]}"; do - echo "$PACKAGE_ENTRY" >> "$GITHUB_STEP_SUMMARY" - done - fi - echo "" >> "$GITHUB_STEP_SUMMARY" # Add a blank line for spacing - echo "---" >> "$GITHUB_STEP_SUMMARY" # Add a separator for cleanliness \ No newline at end of file + find-packages: + name: Find packages for Jira ticket + uses: ultimaker/cura-workflows/.github/workflows/find_package_by_ticket.yml@jira_find_package + with: + jira_ticket_number: ${{ inputs.jira_ticket_number }} + secrets: inherit \ No newline at end of file From 2a45cf3274cd533b3a1cb406c9d54b56d0e6e6fc Mon Sep 17 00:00:00 2001 From: HellAholic Date: Sat, 21 Jun 2025 10:03:49 +0200 Subject: [PATCH 214/299] set_permission set high level permission to none --- .github/workflows/find-packages.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index e9c60a89b4..fdb3d8ebf4 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -8,10 +8,12 @@ on: required: true type: string +permissions: {} + jobs: find-packages: name: Find packages for Jira ticket uses: ultimaker/cura-workflows/.github/workflows/find_package_by_ticket.yml@jira_find_package with: jira_ticket_number: ${{ inputs.jira_ticket_number }} - secrets: inherit \ No newline at end of file + secrets: inherit From 1ca58824acfb1bf06fa170120520eb2d32345cbd Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sun, 4 Aug 2024 16:28:23 +0200 Subject: [PATCH 215/299] Add printer definitions for Sovol SV08. The SV08 (or SV-08; nomenclature is not completely consistent) is a relatively new printed based on Voron 2.4, running Klipper. This adds printer, extruder and material definitions for it, based on the voron2_base definitions (by copying, so as to stay independent of voron2_base is changed) plus Sovol's published profiles for Orca Slicer: https://drive.google.com/drive/folders/1KWjLxwpO_9_Xqi_f6qu84HRxZi26a_GN Unfortunately, the included STL model for the platform does not have texture coordinates, so we cannot use the platform texture (unless someone goes to add them manually or otherwise adjusts the model). The following settings were not carried over, mostly because I could not find any obvious equivalent in Cura: - Machine: "retract_before_wipe": [ "0%" ], "machine_max_acceleration_extruding": [ "20000" ], "machine_max_acceleration_retracting": [ "5000" ], "retract_length_toolchange": [ "2" ], "wipe_distance": [ "2" ], "retract_lift_below": [ "343" ], "thumbnails_format": "PNG", "before_layer_change_gcode": "TIMELAPSE_TAKE_FRAME\nG92 E0", - Filament (using ABS as an example; the exact values differ between the four material profiles): "nozzle_temperature_range_low": [ "190" ], "nozzle_temperature_range_high": [ "250" ], "overhang_fan_threshold": [ "25%" ], "temperature_vitrification": [ "60" ], # Only used for arranging. "close_fan_the_first_x_layers": [ "3" ], "full_fan_speed_layer": [ "0" ], # Inconsistent; effectively 4. # Enclosure fan (M106 P3 commands) "activate_air_filtration": [ "1" ], "complete_print_exhaust_fan_speed": [ "60" ], "during_print_exhaust_fan_speed": [ "100" ], - Process: A bunch (e.g. bridge_flow, elephant_foot_compensation, overhang_1_4_speed, etc. etc.), but it's unclear how many are printer-specific and how many are just Orca defaults where Cura wants to do things differently. The start and end G-code are mostly copied over verbatim, except that it leaves the printer in relative coordinate mode and Cura does not set this explicitly back to absolute, so we need an explicit G90 at the end. (Also, there seems to be a Klipper issue where G90 does not reset extrusion to absolute as well, so we need to send an explicit M82.) We give EXTRUDER_TEMP= and BED_TEMP= as parameters to the START_PRINT macro; the Sovol stock macros ignore these, but the popular mainline Klipper installation can use this to e.g. bed mesh at the correct temperature. We also use the new Cura 5.8 conditionals to reduce the extrusion amount for finer nozzles than 0.4mm, as we get Klipper errors otherwise. Unfortunately, Cura chooses SS_ as prefix instead of SV08_. I don't know if there is a way to override this; the other Sovol printers seem to have the same issue. I've tested this with the standard 0.4mm nozzle and ABS/PLA, using the Moonraker plugin. PETG and TPU are untested, in part because the current nozzle is said to be unsafe for PETG. The time estimates from Cura are not all that good, but klipper_estimator helps. (The Klipper object exclusion plugin is also recommended, as it allows the printer to bed mesh a smaller area.) Future work would include supporting the 0.2mm, 0.6mm and 0.8mm nozzles. There are separate profiles for them, with different layer height, support settings, print speeds, etc. -- and then there is a specific PLA/0.2mm profile with lower printing speed and higher fan settings. Also, it would be really good to support the enclosure fan (M106 P3, known as exhaust_fan in Orca) for printing ABS; it's possible that something could be done using the Cura fan control plugin, but it would be better to simply have it right in the filament settings. Similarly, the ABS/PETG profiles want to turn off the fan entirely the first three layers (to improve adhesion), but Cura can only ramp linearly starting from the first layer, not hold the first few layers constant. --- resources/definitions/sovol_sv08.def.json | 131 ++++++++++++++++++ .../extruders/sovol_sv08_extruder.def.json | 19 +++ .../meshes/sovol_sv08_buildplate_model.stl | Bin 0 -> 454884 bytes .../ABS/sovol_sv08_0.4_ABS_standard.inst.cfg | 26 ++++ .../sovol_sv08_0.4_PETG_standard.inst.cfg | 26 ++++ .../PLA/sovol_sv08_0.4_PLA_standard.inst.cfg | 26 ++++ .../TPU/sovol_sv08_0.4_TPU_standard.inst.cfg | 26 ++++ .../quality/sovol/sovol_sv08_global.inst.cfg | 30 ++++ .../variants/sovol/sovol_sv08_0.4.inst.cfg | 13 ++ 9 files changed, 297 insertions(+) create mode 100644 resources/definitions/sovol_sv08.def.json create mode 100644 resources/extruders/sovol_sv08_extruder.def.json create mode 100644 resources/meshes/sovol_sv08_buildplate_model.stl create mode 100644 resources/quality/sovol/ABS/sovol_sv08_0.4_ABS_standard.inst.cfg create mode 100644 resources/quality/sovol/PETG/sovol_sv08_0.4_PETG_standard.inst.cfg create mode 100644 resources/quality/sovol/PLA/sovol_sv08_0.4_PLA_standard.inst.cfg create mode 100644 resources/quality/sovol/TPU/sovol_sv08_0.4_TPU_standard.inst.cfg create mode 100644 resources/quality/sovol/sovol_sv08_global.inst.cfg create mode 100644 resources/variants/sovol/sovol_sv08_0.4.inst.cfg diff --git a/resources/definitions/sovol_sv08.def.json b/resources/definitions/sovol_sv08.def.json new file mode 100644 index 0000000000..52f5fb6138 --- /dev/null +++ b/resources/definitions/sovol_sv08.def.json @@ -0,0 +1,131 @@ +{ + "version": 2, + "name": "Sovol SV08", + "inherits": "fdmprinter", + "metadata": + { + "visible": true, + "author": "See voron2_base", + "manufacturer": "Sovol 3D", + "preferred_variant_name": "0.4mm Nozzle", + "quality_definition": "sovol_sv08", + "variants_name": "Nozzle Size", + "platform": "sovol_sv08_buildplate_model.stl", + "file_formats": "text/x-gcode", + "exclude_materials": [], + "first_start_actions": [ "MachineSettingsAction" ], + "has_machine_quality": true, + "has_materials": true, + "has_variants": true, + "machine_extruder_trains": { "0": "voron2_extruder_0" }, + "preferred_material": "generic_abs", + "preferred_quality_type": "fast" + }, + "overrides": + { + "machine_depth": { "default_value": 350 }, + "machine_width": { "default_value": 350 }, + "machine_height": { "default_value": 345 }, + "machine_name": { "default_value": "SV08" }, + "retraction_amount": { "default_value": 0.5 }, + "machine_max_acceleration_x": { "default_value": 40000 }, + "machine_max_acceleration_y": { "default_value": 40000 }, + "machine_max_acceleration_z": { "default_value": 500 }, + "machine_max_acceleration_e": { "default_value": 5000 }, + "machine_max_feedrate_x": { "default_value": 700 }, + "machine_max_feedrate_y": { "default_value": 700 }, + "machine_max_feedrate_z": { "default_value": 20 }, + "machine_max_feedrate_e": { "default_value": 50 }, + "machine_max_jerk_e": { "default_value": 5 }, + "machine_max_jerk_xy": { "default_value": 20 }, + "machine_max_jerk_z": { "default_value": 0.5 }, + "retraction_min_travel": { "default_value": 1 }, + "retraction_hop": { "default_value": 0.4 }, + "machine_start_gcode": { "default_value": "G28 ; Move to zero\nG90 ; Absolute positioning\nG1 X0 F9000\nG1 Y20\nG1 Z0.600 F600\nG1 Y0 F9000\nSTART_PRINT EXTRUDER_TEMP={material_print_temperature_layer_0} BED_TEMP={material_bed_temperature_layer_0}\nG90 ; Absolute positioning (START_PRINT might have changed it)\nG1 X0 F9000\nG1 Y20\nG1 Z0.600 F600\nG1 Y0 F9000\nM400\nG91 ; Relative positioning\nM83 ; Relative extrusion\nM140 S{material_bed_temperature_layer_0} ; Set bed temp\nM104 S{material_print_temperature_layer_0} ; Set extruder temp\nM190 S{material_bed_temperature_layer_0} ; Wait for bed temp\nM109 S{material_print_temperature_layer_0} ; Wait for extruder temp\n{if machine_nozzle_size >= 0.4}\n; Standard Sovol blob and purge line.\nG1 E25 F300 ; Purge blob\nG4 P1000 ; Wait a bit to let it finish\nG1 E-0.200 Z5 F600 ; Retract\nG1 X88.000 F9000 ; Move right and then down for purge line\nG1 Z-5.000 F600\nG1 X87.000 E20.88 F1800 ; Purge line right\nG1 X87.000 E13.92 F1800\nG1 Y1 E0.16 F1800 ; Small movement back for next line\nG1 X-87.000 E13.92 F1800 ; Purge line left\nG1 X-87.000 E20.88 F1800\nG1 Y1 E0.24 F1800 ; Small movement back for next line\nG1 X87.000 E20.88 F1800 ; Purge line right\nG1 X87.000 E13.92 F1800\nG1 E-0.200 Z1 F600\n{else}\n; The default start G-code uses too high flow for smaller nozzles,\n; which causes Klipper errors. Scale everything back by\n; (0.25/0.4)^2, i.e., for 0.25mm nozzle. This should be good\n; enough for 0.2mm as well.\nG1 E8 F300 ; Purge blob\nG4 P1000 ; Wait a bit to let it finish\nG1 E-0.078 Z5 F600 ; Retract\nG1 X88.000 F9000 ; Move right and then down for purge line\nG1 Z-5.000 F600\nG1 X87.000 E8.16 F1800 ; Purge line right\nG1 X87.000 E5.44 F1800\nG1 Y1 E0.063 F1800 ; Small movement back for next line\nG1 X-87.000 E5.44 F1800 ; Purge line left\nG1 X-87.000 E8.16 F1800\nG1 Y1 E0.094 F1800 ; Small movement back for next line\nG1 X87.000 E8.16 F1800 ; Purge line right\nG1 X87.000 E5.44 F1800\nG1 E-0.078 Z1 F600\n{endif}\nM400 ; Wait for moves to finish\nG90 ; Absolute positioning\nM82 ; Absolute extrusion mode\n" }, + "machine_end_gcode": { "default_value": "END_PRINT\n" }, + "acceleration_enabled": { "default_value": false }, + "acceleration_layer_0": { "value": 1800 }, + "acceleration_print": { "default_value": 2200 }, + "acceleration_roofing": { "value": 1800 }, + "acceleration_travel_layer_0": { "value": 1800 }, + "acceleration_wall_0": { "value": 1800 }, + "adhesion_type": { "default_value": "skirt" }, + "alternate_extra_perimeter": { "default_value": true }, + "bridge_fan_speed": { "default_value": 100 }, + "bridge_fan_speed_2": { "resolve": "max(cool_fan_speed, 50)" }, + "bridge_fan_speed_3": { "resolve": "max(cool_fan_speed, 20)" }, + "bridge_settings_enabled": { "default_value": true }, + "bridge_wall_coast": { "default_value": 10 }, + "cool_fan_full_at_height": { "value": "resolveOrValue('layer_height_0') + resolveOrValue('layer_height') * max(1, cool_fan_full_layer - 1)" }, + "cool_fan_full_layer": { "value": 4 }, + "cool_fan_speed_min": { "value": "cool_fan_speed" }, + "cool_min_layer_time": { "default_value": 15 }, + "cool_min_layer_time_fan_speed_max": { "default_value": 20 }, + "fill_outline_gaps": { "default_value": true }, + "gantry_height": { "value": 30 }, + "infill_before_walls": { "default_value": false }, + "infill_enable_travel_optimization": { "default_value": true }, + "jerk_enabled": { "default_value": false }, + "jerk_roofing": { "value": 10 }, + "jerk_wall_0": { "value": 10 }, + "layer_height_0": { "resolve": "max(0.2, min(extruderValues('layer_height')))" }, + "line_width": { "value": "machine_nozzle_size * 1.125" }, + "machine_acceleration": { "default_value": 1500 }, + "machine_endstop_positive_direction_x": { "default_value": true }, + "machine_endstop_positive_direction_y": { "default_value": true }, + "machine_endstop_positive_direction_z": { "default_value": false }, + "machine_feeder_wheel_diameter": { "default_value": 7.5 }, + "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, + "machine_head_with_fans_polygon": + { + "default_value": [ + [-35, 65], + [-35, -50], + [35, -50], + [35, 65] + ] + }, + "machine_heated_bed": { "default_value": true }, + "machine_steps_per_mm_x": { "default_value": 80 }, + "machine_steps_per_mm_y": { "default_value": 80 }, + "machine_steps_per_mm_z": { "default_value": 400 }, + "meshfix_maximum_resolution": { "default_value": 0.01 }, + "min_infill_area": { "default_value": 5.0 }, + "minimum_polygon_circumference": { "default_value": 0.2 }, + "optimize_wall_printing_order": { "default_value": true }, + "retraction_combing": { "value": "'noskin'" }, + "retraction_combing_max_distance": { "default_value": 10 }, + "retraction_hop_enabled": { "default_value": true }, + "retraction_prime_speed": + { + "maximum_value_warning": 130, + "value": "math.ceil(retraction_speed * 0.4)" + }, + "retraction_retract_speed": { "maximum_value_warning": 130 }, + "retraction_speed": + { + "default_value": 30, + "maximum_value_warning": 130 + }, + "roofing_layer_count": { "value": 1 }, + "skirt_brim_minimal_length": { "default_value": 550 }, + "speed_layer_0": { "value": "math.ceil(speed_print * 0.25)" }, + "speed_roofing": { "value": "math.ceil(speed_print * 0.33)" }, + "speed_slowdown_layers": { "default_value": 4 }, + "speed_topbottom": { "value": "math.ceil(speed_print * 0.33)" }, + "speed_travel": + { + "maximum_value_warning": 501, + "value": 300 + }, + "speed_travel_layer_0": { "value": "math.ceil(speed_travel * 0.4)" }, + "speed_wall": { "value": "math.ceil(speed_print * 0.33)" }, + "speed_wall_0": { "value": "math.ceil(speed_print * 0.33)" }, + "speed_wall_x": { "value": "math.ceil(speed_print * 0.66)" }, + "travel_avoid_other_parts": { "default_value": false }, + "wall_line_width": { "value": "machine_nozzle_size" }, + "wall_overhang_angle": { "default_value": 75 }, + "wall_overhang_speed_factor": { "default_value": 50 }, + "zig_zaggify_infill": { "value": true } + } +} diff --git a/resources/extruders/sovol_sv08_extruder.def.json b/resources/extruders/sovol_sv08_extruder.def.json new file mode 100644 index 0000000000..407c81de47 --- /dev/null +++ b/resources/extruders/sovol_sv08_extruder.def.json @@ -0,0 +1,19 @@ +{ + "version": 2, + "name": "Nozzle Size", + "inherits": "fdmextruder", + "metadata": + { + "machine": "sovol_sv08", + "position": "0" + }, + "overrides": + { + "extruder_nr": + { + "default_value": 0, + "maximum_value": 1 + }, + "material_diameter": { "default_value": 1.75 } + } +} diff --git a/resources/meshes/sovol_sv08_buildplate_model.stl b/resources/meshes/sovol_sv08_buildplate_model.stl new file mode 100644 index 0000000000000000000000000000000000000000..91acb50bd443f13d12c84d80a912e5d5b21ff1d8 GIT binary patch literal 454884 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

8}u(~qva{JL7O*{ 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 z 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

gqjqWHOjVDU%F#pu@`EC^N&2jaCG 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 literal 0 HcmV?d00001 diff --git a/resources/quality/sovol/ABS/sovol_sv08_0.4_ABS_standard.inst.cfg b/resources/quality/sovol/ABS/sovol_sv08_0.4_ABS_standard.inst.cfg new file mode 100644 index 0000000000..2fda8d1811 --- /dev/null +++ b/resources/quality/sovol/ABS/sovol_sv08_0.4_ABS_standard.inst.cfg @@ -0,0 +1,26 @@ +[general] +definition = sovol_sv08 +name = Standard Quality +version = 4 + +[metadata] +material = generic_abs +quality_type = standard +setting_version = 25 +type = quality +variant = 0.4mm Nozzle + +[values] +cool_fan_enabled = True +cool_fan_speed = 10 +cool_fan_speed_max = 30 +cool_min_layer_time_fan_speed_max = 30 +cool_min_layer_time = 4 +cool_min_speed = 10 +material_flow = 98 +material_max_flowrate = 21 +material_print_temperature = 270 +material_print_temperature_layer_0 = 280 +material_bed_temperature = 95 +bridge_settings_enabled = True +bridge_fan_speed = 30 diff --git a/resources/quality/sovol/PETG/sovol_sv08_0.4_PETG_standard.inst.cfg b/resources/quality/sovol/PETG/sovol_sv08_0.4_PETG_standard.inst.cfg new file mode 100644 index 0000000000..ba43c72c8b --- /dev/null +++ b/resources/quality/sovol/PETG/sovol_sv08_0.4_PETG_standard.inst.cfg @@ -0,0 +1,26 @@ +[general] +definition = sovol_sv08 +name = Standard Quality +version = 4 + +[metadata] +material = generic_petg +quality_type = standard +setting_version = 25 +type = quality +variant = 0.4mm Nozzle + +[values] +cool_fan_enabled = True +cool_fan_speed = 10 +cool_fan_speed_max = 30 +cool_min_layer_time_fan_speed_max = 30 +cool_min_layer_time = 5 +cool_min_speed = 10 +material_flow = 98 +material_max_flowrate = 17 +material_print_temperature = 235 +material_print_temperature_layer_0 = 250 +material_bed_temperature = 75 +bridge_settings_enabled = True +bridge_fan_speed = 70 diff --git a/resources/quality/sovol/PLA/sovol_sv08_0.4_PLA_standard.inst.cfg b/resources/quality/sovol/PLA/sovol_sv08_0.4_PLA_standard.inst.cfg new file mode 100644 index 0000000000..2a70b9415b --- /dev/null +++ b/resources/quality/sovol/PLA/sovol_sv08_0.4_PLA_standard.inst.cfg @@ -0,0 +1,26 @@ +[general] +definition = sovol_sv08 +name = Standard Quality +version = 4 + +[metadata] +material = generic_pla +quality_type = standard +setting_version = 25 +type = quality +variant = 0.4mm Nozzle + +[values] +cool_fan_enabled = True +cool_fan_speed = 50 +cool_fan_speed_max = 70 +cool_min_layer_time_fan_speed_max = 50 +cool_min_layer_time = 5 +cool_min_speed = 10 +material_flow = 98 +material_max_flowrate = 21 +material_print_temperature = 220 +material_print_temperature_layer_0 = 235 +material_bed_temperature = 65 +bridge_settings_enabled = True +bridge_fan_speed = 100 diff --git a/resources/quality/sovol/TPU/sovol_sv08_0.4_TPU_standard.inst.cfg b/resources/quality/sovol/TPU/sovol_sv08_0.4_TPU_standard.inst.cfg new file mode 100644 index 0000000000..1908bdb6b0 --- /dev/null +++ b/resources/quality/sovol/TPU/sovol_sv08_0.4_TPU_standard.inst.cfg @@ -0,0 +1,26 @@ +[general] +definition = sovol_sv08 +name = Standard Quality +version = 4 + +[metadata] +material = generic_tpu +quality_type = standard +setting_version = 25 +type = quality +variant = 0.4mm Nozzle + +[values] +cool_fan_enabled = True +cool_fan_speed = 80 +cool_fan_speed_max = 100 +cool_min_layer_time_fan_speed_max = 50 +cool_min_layer_time = 5 +cool_min_speed = 10 +material_flow = 98 +material_max_flowrate = 3.6 +material_print_temperature = 240 +material_print_temperature_layer_0 = 235 +material_bed_temperature = 65 +bridge_settings_enabled = True +bridge_fan_speed = 100 diff --git a/resources/quality/sovol/sovol_sv08_global.inst.cfg b/resources/quality/sovol/sovol_sv08_global.inst.cfg new file mode 100644 index 0000000000..2f2f0004ab --- /dev/null +++ b/resources/quality/sovol/sovol_sv08_global.inst.cfg @@ -0,0 +1,30 @@ +[general] +definition = sovol_sv08 +name = 0.20mm Standard +version = 4 + +[metadata] +global_quality = True +quality_type = standard +setting_version = 23 +type = quality + +[values] +layer_height = 0.2 +speed_print = 600 +speed_wall_x = 300 +speed_wall_0 = 200 +speed_infill = 200 +speed_travel = =speed_print +skirt_brim_speed = 80 +speed_ironing = 15 +speed_layer_0 = 30 +speed_slowdown_layers = 3 +acceleration_enabled = True +acceleration_print = 20000 +acceleration_wall_0 = 8000 +acceleration_wall_x = 12000 +acceleration_roofing = =acceleration_wall_0 +acceleration_topbottom = =acceleration_wall +acceleration_layer_0 = 3000 +acceleration_travel = 40000 diff --git a/resources/variants/sovol/sovol_sv08_0.4.inst.cfg b/resources/variants/sovol/sovol_sv08_0.4.inst.cfg new file mode 100644 index 0000000000..ce8ae1f23e --- /dev/null +++ b/resources/variants/sovol/sovol_sv08_0.4.inst.cfg @@ -0,0 +1,13 @@ +[general] +definition = sovol_sv08 +name = 0.4mm Nozzle +version = 4 + +[metadata] +hardware_type = nozzle +setting_version = 23 +type = variant + +[values] +machine_nozzle_size = 0.4 + From 694ef2a8c9486f37c86a66c95836d9f86b229c63 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 24 Jun 2025 12:16:05 +0200 Subject: [PATCH 216/299] Update find-packages workflow Add input to start builds Update the reference to the workflow name --- .github/workflows/find-packages.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index fdb3d8ebf4..43c4b6f17e 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -7,13 +7,18 @@ on: description: 'Jira ticket number for Conan package discovery (e.g., cura_12345)' required: true type: string + start_builds: + default: false + required: false + type: boolean permissions: {} jobs: find-packages: name: Find packages for Jira ticket - uses: ultimaker/cura-workflows/.github/workflows/find_package_by_ticket.yml@jira_find_package + uses: ultimaker/cura-workflows/.github/workflows/find-package-by-ticket.yml@jira_find_package with: jira_ticket_number: ${{ inputs.jira_ticket_number }} + start_builds: ${{ inputs.start_builds }} secrets: inherit From 94faa4cacfb64b6af8eb56d4a0060009cbad78b1 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 24 Jun 2025 12:38:09 +0200 Subject: [PATCH 217/299] Add read permission to allow for triggering builds --- .github/workflows/find-packages.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index 43c4b6f17e..ad8fb6271d 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -12,7 +12,8 @@ on: required: false type: boolean -permissions: {} +permissions: + contents: read jobs: find-packages: From 7dcc5cd4701d66abc5de9d5e4c8815be11802fbf Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 24 Jun 2025 13:11:00 +0200 Subject: [PATCH 218/299] Expose brush shape to QML CURA-12543 --- plugins/PaintTool/PaintTool.py | 16 +++++++++------- plugins/PaintTool/PaintTool.qml | 5 +++-- plugins/PaintTool/__init__.py | 3 +++ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index e030a789fa..0c3ac0d661 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -3,7 +3,7 @@ from enum import IntEnum import numpy -from PyQt6.QtCore import Qt +from PyQt6.QtCore import Qt, QObject, pyqtEnum from PyQt6.QtGui import QImage, QPainter, QColor, QPen from PyQt6 import QtWidgets from typing import cast, Dict, List, Optional, Tuple @@ -24,9 +24,11 @@ from .PaintView import PaintView class PaintTool(Tool): """Provides the tool to paint meshes.""" - class BrushShape(IntEnum): - SQUARE = 0 - CIRCLE = 1 + class Brush(QObject): + @pyqtEnum + class Shape(IntEnum): + SQUARE = 0 + CIRCLE = 1 def __init__(self) -> None: super().__init__() @@ -41,7 +43,7 @@ class PaintTool(Tool): self._brush_size: int = 10 self._brush_color: str = "A" - self._brush_shape: PaintTool.BrushShape = PaintTool.BrushShape.SQUARE + self._brush_shape: PaintTool.Brush.Shape = PaintTool.Brush.Shape.SQUARE self._brush_pen: QPen = self._createBrushPen() self._mouse_held: bool = False @@ -56,9 +58,9 @@ class PaintTool(Tool): pen.setColor(Qt.GlobalColor.white) match self._brush_shape: - case PaintTool.BrushShape.SQUARE: + case PaintTool.Brush.Shape.SQUARE: pen.setCapStyle(Qt.PenCapStyle.SquareCap) - case PaintTool.BrushShape.CIRCLE: + case PaintTool.Brush.Shape.CIRCLE: pen.setCapStyle(Qt.PenCapStyle.RoundCap) return pen diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index 8bd02e00a3..602805cba1 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -6,6 +6,7 @@ import QtQuick.Controls import QtQuick.Layouts import UM 1.7 as UM +import Cura 1.0 as Cura Item { @@ -154,7 +155,7 @@ Item z: 2 - onClicked: UM.Controller.triggerActionWithData("setBrushShape", 0) + onClicked: UM.Controller.triggerActionWithData("setBrushShape", Cura.PaintToolBrush.SQUARE) } UM.ToolbarButton @@ -171,7 +172,7 @@ Item z: 2 - onClicked: UM.Controller.triggerActionWithData("setBrushShape", 1) + onClicked: UM.Controller.triggerActionWithData("setBrushShape", Cura.PaintToolBrush.CIRCLE) } UM.Slider diff --git a/plugins/PaintTool/__init__.py b/plugins/PaintTool/__init__.py index 301bc49e0d..e92c169ee6 100644 --- a/plugins/PaintTool/__init__.py +++ b/plugins/PaintTool/__init__.py @@ -4,6 +4,8 @@ from . import PaintTool from . import PaintView +from PyQt6.QtQml import qmlRegisterUncreatableType + from UM.i18n import i18nCatalog i18n_catalog = i18nCatalog("cura") @@ -24,6 +26,7 @@ def getMetaData(): } def register(app): + qmlRegisterUncreatableType(PaintTool.PaintTool.Brush, "Cura", 1, 0, "This is an enumeration class", "PaintToolBrush") return { "tool": PaintTool.PaintTool(), "view": PaintView.PaintView() From be14fc7dd63e9c8e3137c0288104a4eae4f081a0 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 24 Jun 2025 13:36:49 +0200 Subject: [PATCH 219/299] Send texture data to the engine CURA-12574 --- cura/Scene/SliceableObjectDecorator.py | 20 +++++++++- plugins/3MFWriter/ThreeMFWriter.py | 43 ++++++++-------------- plugins/CuraEngineBackend/Cura.proto | 2 + plugins/CuraEngineBackend/StartSliceJob.py | 8 ++++ 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/cura/Scene/SliceableObjectDecorator.py b/cura/Scene/SliceableObjectDecorator.py index dee244b81c..4278705e2e 100644 --- a/cura/Scene/SliceableObjectDecorator.py +++ b/cura/Scene/SliceableObjectDecorator.py @@ -1,8 +1,10 @@ import copy +import json from typing import Optional, Dict -from PyQt6.QtGui import QImage +from PyQt6.QtCore import QBuffer +from PyQt6.QtGui import QImage, QImageWriter import UM.View.GL.Texture from UM.Scene.SceneNodeDecorator import SceneNodeDecorator @@ -40,6 +42,22 @@ class SliceableObjectDecorator(SceneNodeDecorator): def setTextureDataMapping(self, mapping: Dict[str, tuple[int, int]]) -> None: self._texture_data_mapping = mapping + def packTexture(self) -> Optional[bytearray]: + if self._paint_texture is None: + return None + + texture_image = self._paint_texture.getImage() + if texture_image is None: + return None + + texture_buffer = QBuffer() + texture_buffer.open(QBuffer.OpenModeFlag.ReadWrite) + image_writer = QImageWriter(texture_buffer, b"png") + image_writer.setText("Description", json.dumps(self._texture_data_mapping)) + image_writer.write(texture_image) + + return texture_buffer.data() + def __deepcopy__(self, memo) -> "SliceableObjectDecorator": copied_decorator = SliceableObjectDecorator() copied_decorator.setPaintTexture(copy.deepcopy(self.getPaintTexture())) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 9d35f88e6d..37345b16b0 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -29,7 +29,7 @@ from cura.Scene.CuraSceneNode import CuraSceneNode from cura.Snapshot import Snapshot from PyQt6.QtCore import Qt, QBuffer -from PyQt6.QtGui import QImage, QPainter, QImageWriter +from PyQt6.QtGui import QImage, QPainter import pySavitar as Savitar from .UCPDialog import UCPDialog @@ -158,36 +158,25 @@ class ThreeMFWriter(MeshWriter): else: savitar_node.getMeshData().setFacesFromBytes(numpy.arange(mesh_data.getVertices().size / 3, dtype=numpy.int32).tobytes()) - texture = um_node.callDecoration("getPaintTexture") + packed_texture = um_node.callDecoration("packTexture") uv_coordinates_array = mesh_data.getUVCoordinatesAsByteArray() - if texture is not None and archive is not None and uv_coordinates_array is not None and len(uv_coordinates_array) > 0: - texture_image = texture.getImage() - if texture_image is not None: - texture_buffer = QBuffer() - texture_buffer.open(QBuffer.OpenModeFlag.ReadWrite) + if packed_texture is not None and archive is not None and uv_coordinates_array is not None and len(uv_coordinates_array) > 0: + texture_path = f"{TEXTURES_PATH}/{id(um_node)}.png" + texture_file = zipfile.ZipInfo(texture_path) + # Don't try to compress texture file, because the PNG is pretty much as compact as it will get + archive.writestr(texture_file, packed_texture) - image_writer = QImageWriter(texture_buffer, b"png") - texture_data_mapping = um_node.callDecoration("getTextureDataMapping") - if texture_data_mapping is not None: - image_writer.setText("Description", json.dumps(texture_data_mapping)) - image_writer.write(texture_image) + savitar_node.getMeshData().setUVCoordinatesPerVertexAsBytes(uv_coordinates_array, texture_path, scene) - texture_path = f"{TEXTURES_PATH}/{id(um_node)}.png" - texture_file = zipfile.ZipInfo(texture_path) - # Don't try to compress texture file, because the PNG is pretty much as compact as it will get - archive.writestr(texture_file, texture_buffer.data()) + # Add texture relation to model relations file + if model_relations_element is not None: + ET.SubElement(model_relations_element, "Relationship", + Target=texture_path, Id=f"rel{len(model_relations_element)+1}", + Type="http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture") - savitar_node.getMeshData().setUVCoordinatesPerVertexAsBytes(uv_coordinates_array, texture_path, scene) - - # Add texture relation to model relations file - if model_relations_element is not None: - ET.SubElement(model_relations_element, "Relationship", - Target=texture_path, Id=f"rel{len(model_relations_element)+1}", - Type="http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture") - - if content_types_element is not None: - ET.SubElement(content_types_element, "Override", PartName=texture_path, - ContentType="application/vnd.ms-package.3dmanufacturing-3dmodeltexture") + if content_types_element is not None: + ET.SubElement(content_types_element, "Override", PartName=texture_path, + ContentType="application/vnd.ms-package.3dmanufacturing-3dmodeltexture") # Handle per object settings (if any) diff --git a/plugins/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto index 8018c9186f..f492718d03 100644 --- a/plugins/CuraEngineBackend/Cura.proto +++ b/plugins/CuraEngineBackend/Cura.proto @@ -53,6 +53,8 @@ message Object bytes indices = 4; //An array of ints. repeated Setting settings = 5; // Setting override per object, overruling the global settings. string name = 6; //Mesh name + bytes uv_coordinates = 7; //An array of 2 floats. + bytes texture = 8; //PNG-encoded texture data } message Progress diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index b276469d09..8b27a0319a 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -509,6 +509,14 @@ class StartSliceJob(Job): obj.vertices = flat_verts + uv_coordinates = mesh_data.getUVCoordinates() + if uv_coordinates is not None: + obj.uv_coordinates = uv_coordinates.flatten() + + packed_texture = object.callDecoration("packTexture") + if packed_texture is not None: + obj.texture = packed_texture + self._handlePerObjectSettings(cast(CuraSceneNode, object), obj) Job.yieldThread() From 6a230b3df5cc57c49550d4b6f262104d44293e54 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 24 Jun 2025 14:03:07 +0200 Subject: [PATCH 220/299] ClusterPrinterStatus: optional init args Prevents a cura crash if any of the args are not returned from api call --- .../src/Models/Http/ClusterPrinterStatus.py | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py index 925b4844c1..c7250d7c37 100644 --- a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py +++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py @@ -20,13 +20,14 @@ from ..BaseModel import BaseModel class ClusterPrinterStatus(BaseModel): """Class representing a cluster printer""" - def __init__(self, enabled: bool, firmware_version: str, friendly_name: str, ip_address: str, machine_variant: str, - status: str, unique_name: str, uuid: str, - configuration: List[Union[Dict[str, Any], ClusterPrintCoreConfiguration]], - reserved_by: Optional[str] = None, maintenance_required: Optional[bool] = None, + def __init__(self, enabled: Optional[bool] = True, friendly_name: Optional[str] = "", machine_variant: Optional[str] = "", + status: Optional[str] = "unknown", unique_name: Optional[str] = "", uuid: Optional[str] = "", + configuration: Optional[List[Union[Dict[str, Any], ClusterPrintCoreConfiguration]]] = None, + firmware_version: Optional[str] = None, ip_address: Optional[str] = None, + reserved_by: Optional[str] = None, maintenance_required: Optional[bool] = False, firmware_update_status: Optional[str] = None, latest_available_firmware: Optional[str] = None, - build_plate: Union[Dict[str, Any], ClusterBuildPlate] = None, - material_station: Union[Dict[str, Any], ClusterPrinterMaterialStation] = None, **kwargs) -> None: + build_plate: Optional[Union[Dict[str, Any], ClusterBuildPlate]] = None, + material_station: Optional[Union[Dict[str, Any], ClusterPrinterMaterialStation]] = None, **kwargs) -> None: """ Creates a new cluster printer status :param enabled: A printer can be disabled if it should not receive new jobs. By default, every printer is enabled. @@ -47,7 +48,7 @@ class ClusterPrinterStatus(BaseModel): :param material_station: The material station that is on the printer. """ - self.configuration = self.parseModels(ClusterPrintCoreConfiguration, configuration) + self.configuration = self.parseModels(ClusterPrintCoreConfiguration, configuration) if configuration else [] self.enabled = enabled self.firmware_version = firmware_version self.friendly_name = friendly_name @@ -70,7 +71,7 @@ class ClusterPrinterStatus(BaseModel): :param controller: - The controller of the model. """ - model = PrinterOutputModel(controller, len(self.configuration), firmware_version = self.firmware_version) + model = PrinterOutputModel(controller, len(self.configuration), firmware_version = self.firmware_version or "") self.updateOutputModel(model) return model @@ -80,13 +81,14 @@ class ClusterPrinterStatus(BaseModel): :param model: - The output model to update. """ - model.updateKey(self.uuid) - model.updateName(self.friendly_name) - model.updateUniqueName(self.unique_name) - model.updateType(self.machine_variant) + model.updateKey(self.uuid or "") + model.updateName(self.friendly_name or "") + model.updateUniqueName(self.unique_name or "") + model.updateType(self.machine_variant or "") model.updateState(self.status if self.enabled else "disabled") model.updateBuildplate(self.build_plate.type if self.build_plate else "glass") - model.setCameraUrl(QUrl("http://{}:8080/?action=stream".format(self.ip_address))) + if self.ip_address: + model.setCameraUrl(QUrl("http://{}:8080/?action=stream".format(self.ip_address))) if not model.printerConfiguration: # Prevent accessing printer configuration when not available. From 161f2707f6ce828396ad0f41c13fed2e46175dcb Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 24 Jun 2025 17:48:30 +0200 Subject: [PATCH 221/299] Update sovol_sv08.def.json - author name - change extruder name (no longer using voron2) --- resources/definitions/sovol_sv08.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/sovol_sv08.def.json b/resources/definitions/sovol_sv08.def.json index 52f5fb6138..e60e6edf91 100644 --- a/resources/definitions/sovol_sv08.def.json +++ b/resources/definitions/sovol_sv08.def.json @@ -5,7 +5,7 @@ "metadata": { "visible": true, - "author": "See voron2_base", + "author": "Steinar H. Gunderson", "manufacturer": "Sovol 3D", "preferred_variant_name": "0.4mm Nozzle", "quality_definition": "sovol_sv08", @@ -17,7 +17,7 @@ "has_machine_quality": true, "has_materials": true, "has_variants": true, - "machine_extruder_trains": { "0": "voron2_extruder_0" }, + "machine_extruder_trains": { "0": "sovol_sv08_extruder" }, "preferred_material": "generic_abs", "preferred_quality_type": "fast" }, From 2cfb063c9b3c03378ad47fd0f6f088605807ad10 Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Tue, 24 Jun 2025 15:49:28 +0000 Subject: [PATCH 222/299] Apply printer-linter format --- resources/definitions/sovol_sv08.def.json | 52 +++++++++++------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/resources/definitions/sovol_sv08.def.json b/resources/definitions/sovol_sv08.def.json index e60e6edf91..a0cda31889 100644 --- a/resources/definitions/sovol_sv08.def.json +++ b/resources/definitions/sovol_sv08.def.json @@ -7,11 +7,8 @@ "visible": true, "author": "Steinar H. Gunderson", "manufacturer": "Sovol 3D", - "preferred_variant_name": "0.4mm Nozzle", - "quality_definition": "sovol_sv08", - "variants_name": "Nozzle Size", - "platform": "sovol_sv08_buildplate_model.stl", "file_formats": "text/x-gcode", + "platform": "sovol_sv08_buildplate_model.stl", "exclude_materials": [], "first_start_actions": [ "MachineSettingsAction" ], "has_machine_quality": true, @@ -19,30 +16,13 @@ "has_variants": true, "machine_extruder_trains": { "0": "sovol_sv08_extruder" }, "preferred_material": "generic_abs", - "preferred_quality_type": "fast" + "preferred_quality_type": "fast", + "preferred_variant_name": "0.4mm Nozzle", + "quality_definition": "sovol_sv08", + "variants_name": "Nozzle Size" }, "overrides": { - "machine_depth": { "default_value": 350 }, - "machine_width": { "default_value": 350 }, - "machine_height": { "default_value": 345 }, - "machine_name": { "default_value": "SV08" }, - "retraction_amount": { "default_value": 0.5 }, - "machine_max_acceleration_x": { "default_value": 40000 }, - "machine_max_acceleration_y": { "default_value": 40000 }, - "machine_max_acceleration_z": { "default_value": 500 }, - "machine_max_acceleration_e": { "default_value": 5000 }, - "machine_max_feedrate_x": { "default_value": 700 }, - "machine_max_feedrate_y": { "default_value": 700 }, - "machine_max_feedrate_z": { "default_value": 20 }, - "machine_max_feedrate_e": { "default_value": 50 }, - "machine_max_jerk_e": { "default_value": 5 }, - "machine_max_jerk_xy": { "default_value": 20 }, - "machine_max_jerk_z": { "default_value": 0.5 }, - "retraction_min_travel": { "default_value": 1 }, - "retraction_hop": { "default_value": 0.4 }, - "machine_start_gcode": { "default_value": "G28 ; Move to zero\nG90 ; Absolute positioning\nG1 X0 F9000\nG1 Y20\nG1 Z0.600 F600\nG1 Y0 F9000\nSTART_PRINT EXTRUDER_TEMP={material_print_temperature_layer_0} BED_TEMP={material_bed_temperature_layer_0}\nG90 ; Absolute positioning (START_PRINT might have changed it)\nG1 X0 F9000\nG1 Y20\nG1 Z0.600 F600\nG1 Y0 F9000\nM400\nG91 ; Relative positioning\nM83 ; Relative extrusion\nM140 S{material_bed_temperature_layer_0} ; Set bed temp\nM104 S{material_print_temperature_layer_0} ; Set extruder temp\nM190 S{material_bed_temperature_layer_0} ; Wait for bed temp\nM109 S{material_print_temperature_layer_0} ; Wait for extruder temp\n{if machine_nozzle_size >= 0.4}\n; Standard Sovol blob and purge line.\nG1 E25 F300 ; Purge blob\nG4 P1000 ; Wait a bit to let it finish\nG1 E-0.200 Z5 F600 ; Retract\nG1 X88.000 F9000 ; Move right and then down for purge line\nG1 Z-5.000 F600\nG1 X87.000 E20.88 F1800 ; Purge line right\nG1 X87.000 E13.92 F1800\nG1 Y1 E0.16 F1800 ; Small movement back for next line\nG1 X-87.000 E13.92 F1800 ; Purge line left\nG1 X-87.000 E20.88 F1800\nG1 Y1 E0.24 F1800 ; Small movement back for next line\nG1 X87.000 E20.88 F1800 ; Purge line right\nG1 X87.000 E13.92 F1800\nG1 E-0.200 Z1 F600\n{else}\n; The default start G-code uses too high flow for smaller nozzles,\n; which causes Klipper errors. Scale everything back by\n; (0.25/0.4)^2, i.e., for 0.25mm nozzle. This should be good\n; enough for 0.2mm as well.\nG1 E8 F300 ; Purge blob\nG4 P1000 ; Wait a bit to let it finish\nG1 E-0.078 Z5 F600 ; Retract\nG1 X88.000 F9000 ; Move right and then down for purge line\nG1 Z-5.000 F600\nG1 X87.000 E8.16 F1800 ; Purge line right\nG1 X87.000 E5.44 F1800\nG1 Y1 E0.063 F1800 ; Small movement back for next line\nG1 X-87.000 E5.44 F1800 ; Purge line left\nG1 X-87.000 E8.16 F1800\nG1 Y1 E0.094 F1800 ; Small movement back for next line\nG1 X87.000 E8.16 F1800 ; Purge line right\nG1 X87.000 E5.44 F1800\nG1 E-0.078 Z1 F600\n{endif}\nM400 ; Wait for moves to finish\nG90 ; Absolute positioning\nM82 ; Absolute extrusion mode\n" }, - "machine_end_gcode": { "default_value": "END_PRINT\n" }, "acceleration_enabled": { "default_value": false }, "acceleration_layer_0": { "value": 1800 }, "acceleration_print": { "default_value": 2200 }, @@ -71,6 +51,8 @@ "layer_height_0": { "resolve": "max(0.2, min(extruderValues('layer_height')))" }, "line_width": { "value": "machine_nozzle_size * 1.125" }, "machine_acceleration": { "default_value": 1500 }, + "machine_depth": { "default_value": 350 }, + "machine_end_gcode": { "default_value": "END_PRINT\n" }, "machine_endstop_positive_direction_x": { "default_value": true }, "machine_endstop_positive_direction_y": { "default_value": true }, "machine_endstop_positive_direction_z": { "default_value": false }, @@ -86,16 +68,34 @@ ] }, "machine_heated_bed": { "default_value": true }, + "machine_height": { "default_value": 345 }, + "machine_max_acceleration_e": { "default_value": 5000 }, + "machine_max_acceleration_x": { "default_value": 40000 }, + "machine_max_acceleration_y": { "default_value": 40000 }, + "machine_max_acceleration_z": { "default_value": 500 }, + "machine_max_feedrate_e": { "default_value": 50 }, + "machine_max_feedrate_x": { "default_value": 700 }, + "machine_max_feedrate_y": { "default_value": 700 }, + "machine_max_feedrate_z": { "default_value": 20 }, + "machine_max_jerk_e": { "default_value": 5 }, + "machine_max_jerk_xy": { "default_value": 20 }, + "machine_max_jerk_z": { "default_value": 0.5 }, + "machine_name": { "default_value": "SV08" }, + "machine_start_gcode": { "default_value": "G28 ; Move to zero\nG90 ; Absolute positioning\nG1 X0 F9000\nG1 Y20\nG1 Z0.600 F600\nG1 Y0 F9000\nSTART_PRINT EXTRUDER_TEMP={material_print_temperature_layer_0} BED_TEMP={material_bed_temperature_layer_0}\nG90 ; Absolute positioning (START_PRINT might have changed it)\nG1 X0 F9000\nG1 Y20\nG1 Z0.600 F600\nG1 Y0 F9000\nM400\nG91 ; Relative positioning\nM83 ; Relative extrusion\nM140 S{material_bed_temperature_layer_0} ; Set bed temp\nM104 S{material_print_temperature_layer_0} ; Set extruder temp\nM190 S{material_bed_temperature_layer_0} ; Wait for bed temp\nM109 S{material_print_temperature_layer_0} ; Wait for extruder temp\n{if machine_nozzle_size >= 0.4}\n; Standard Sovol blob and purge line.\nG1 E25 F300 ; Purge blob\nG4 P1000 ; Wait a bit to let it finish\nG1 E-0.200 Z5 F600 ; Retract\nG1 X88.000 F9000 ; Move right and then down for purge line\nG1 Z-5.000 F600\nG1 X87.000 E20.88 F1800 ; Purge line right\nG1 X87.000 E13.92 F1800\nG1 Y1 E0.16 F1800 ; Small movement back for next line\nG1 X-87.000 E13.92 F1800 ; Purge line left\nG1 X-87.000 E20.88 F1800\nG1 Y1 E0.24 F1800 ; Small movement back for next line\nG1 X87.000 E20.88 F1800 ; Purge line right\nG1 X87.000 E13.92 F1800\nG1 E-0.200 Z1 F600\n{else}\n; The default start G-code uses too high flow for smaller nozzles,\n; which causes Klipper errors. Scale everything back by\n; (0.25/0.4)^2, i.e., for 0.25mm nozzle. This should be good\n; enough for 0.2mm as well.\nG1 E8 F300 ; Purge blob\nG4 P1000 ; Wait a bit to let it finish\nG1 E-0.078 Z5 F600 ; Retract\nG1 X88.000 F9000 ; Move right and then down for purge line\nG1 Z-5.000 F600\nG1 X87.000 E8.16 F1800 ; Purge line right\nG1 X87.000 E5.44 F1800\nG1 Y1 E0.063 F1800 ; Small movement back for next line\nG1 X-87.000 E5.44 F1800 ; Purge line left\nG1 X-87.000 E8.16 F1800\nG1 Y1 E0.094 F1800 ; Small movement back for next line\nG1 X87.000 E8.16 F1800 ; Purge line right\nG1 X87.000 E5.44 F1800\nG1 E-0.078 Z1 F600\n{endif}\nM400 ; Wait for moves to finish\nG90 ; Absolute positioning\nM82 ; Absolute extrusion mode\n" }, "machine_steps_per_mm_x": { "default_value": 80 }, "machine_steps_per_mm_y": { "default_value": 80 }, "machine_steps_per_mm_z": { "default_value": 400 }, + "machine_width": { "default_value": 350 }, "meshfix_maximum_resolution": { "default_value": 0.01 }, "min_infill_area": { "default_value": 5.0 }, "minimum_polygon_circumference": { "default_value": 0.2 }, "optimize_wall_printing_order": { "default_value": true }, + "retraction_amount": { "default_value": 0.5 }, "retraction_combing": { "value": "'noskin'" }, "retraction_combing_max_distance": { "default_value": 10 }, + "retraction_hop": { "default_value": 0.4 }, "retraction_hop_enabled": { "default_value": true }, + "retraction_min_travel": { "default_value": 1 }, "retraction_prime_speed": { "maximum_value_warning": 130, @@ -128,4 +128,4 @@ "wall_overhang_speed_factor": { "default_value": 50 }, "zig_zaggify_infill": { "value": true } } -} +} \ No newline at end of file From 594ad121ddd0c1218fbbe88ab440e264deb95587 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 24 Jun 2025 17:49:44 +0200 Subject: [PATCH 223/299] bump setting version to 25 --- resources/variants/sovol/sovol_sv08_0.4.inst.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/variants/sovol/sovol_sv08_0.4.inst.cfg b/resources/variants/sovol/sovol_sv08_0.4.inst.cfg index ce8ae1f23e..b5c72e92d3 100644 --- a/resources/variants/sovol/sovol_sv08_0.4.inst.cfg +++ b/resources/variants/sovol/sovol_sv08_0.4.inst.cfg @@ -5,7 +5,7 @@ version = 4 [metadata] hardware_type = nozzle -setting_version = 23 +setting_version = 25 type = variant [values] From 08d14c39b4ad7bd70ec336b65acb2fd65bb15146 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 24 Jun 2025 17:50:07 +0200 Subject: [PATCH 224/299] bump setting version to 25 --- resources/quality/sovol/sovol_sv08_global.inst.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/quality/sovol/sovol_sv08_global.inst.cfg b/resources/quality/sovol/sovol_sv08_global.inst.cfg index 2f2f0004ab..bebbc3acb1 100644 --- a/resources/quality/sovol/sovol_sv08_global.inst.cfg +++ b/resources/quality/sovol/sovol_sv08_global.inst.cfg @@ -6,7 +6,7 @@ version = 4 [metadata] global_quality = True quality_type = standard -setting_version = 23 +setting_version = 25 type = quality [values] From 75a719ec6031e7300848f10c672cacef99626fde Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Tue, 24 Jun 2025 15:51:48 +0000 Subject: [PATCH 225/299] Apply printer-linter format --- .../quality/sovol/sovol_sv08_global.inst.cfg | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/resources/quality/sovol/sovol_sv08_global.inst.cfg b/resources/quality/sovol/sovol_sv08_global.inst.cfg index bebbc3acb1..4030ec9441 100644 --- a/resources/quality/sovol/sovol_sv08_global.inst.cfg +++ b/resources/quality/sovol/sovol_sv08_global.inst.cfg @@ -10,21 +10,22 @@ setting_version = 25 type = quality [values] -layer_height = 0.2 -speed_print = 600 -speed_wall_x = 300 -speed_wall_0 = 200 -speed_infill = 200 -speed_travel = =speed_print -skirt_brim_speed = 80 -speed_ironing = 15 -speed_layer_0 = 30 -speed_slowdown_layers = 3 acceleration_enabled = True +acceleration_layer_0 = 3000 acceleration_print = 20000 -acceleration_wall_0 = 8000 -acceleration_wall_x = 12000 acceleration_roofing = =acceleration_wall_0 acceleration_topbottom = =acceleration_wall -acceleration_layer_0 = 3000 acceleration_travel = 40000 +acceleration_wall_0 = 8000 +acceleration_wall_x = 12000 +layer_height = 0.2 +skirt_brim_speed = 80 +speed_infill = 200 +speed_ironing = 15 +speed_layer_0 = 30 +speed_print = 600 +speed_slowdown_layers = 3 +speed_travel = =speed_print +speed_wall_0 = 200 +speed_wall_x = 300 + From 9cf75648ab527579f2e0c1e5a051b56581c2c5e9 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Wed, 25 Jun 2025 13:54:56 +0200 Subject: [PATCH 226/299] Review comment - Set default to `""` for `Optional[str]` to remove the `or ""` -The FW version can be returned as None which requires the fallback `or ""` --- .../src/Models/Http/ClusterPrinterStatus.py | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py index c7250d7c37..260d276427 100644 --- a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py +++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py @@ -20,14 +20,23 @@ from ..BaseModel import BaseModel class ClusterPrinterStatus(BaseModel): """Class representing a cluster printer""" - def __init__(self, enabled: Optional[bool] = True, friendly_name: Optional[str] = "", machine_variant: Optional[str] = "", - status: Optional[str] = "unknown", unique_name: Optional[str] = "", uuid: Optional[str] = "", + def __init__(self, + enabled: Optional[bool] = True, + friendly_name: Optional[str] = "", + machine_variant: Optional[str] = "", + status: Optional[str] = "unknown", + unique_name: Optional[str] = "", + uuid: Optional[str] = "", configuration: Optional[List[Union[Dict[str, Any], ClusterPrintCoreConfiguration]]] = None, - firmware_version: Optional[str] = None, ip_address: Optional[str] = None, - reserved_by: Optional[str] = None, maintenance_required: Optional[bool] = False, - firmware_update_status: Optional[str] = None, latest_available_firmware: Optional[str] = None, + firmware_version: Optional[str] = None, + ip_address: Optional[str] = None, + reserved_by: Optional[str] = "", + maintenance_required: Optional[bool] = False, + firmware_update_status: Optional[str] = "", + latest_available_firmware: Optional[str] = "", build_plate: Optional[Union[Dict[str, Any], ClusterBuildPlate]] = None, - material_station: Optional[Union[Dict[str, Any], ClusterPrinterMaterialStation]] = None, **kwargs) -> None: + material_station: Optional[Union[Dict[str, Any], ClusterPrinterMaterialStation]] = None, + **kwargs) -> None: """ Creates a new cluster printer status :param enabled: A printer can be disabled if it should not receive new jobs. By default, every printer is enabled. @@ -81,10 +90,10 @@ class ClusterPrinterStatus(BaseModel): :param model: - The output model to update. """ - model.updateKey(self.uuid or "") - model.updateName(self.friendly_name or "") - model.updateUniqueName(self.unique_name or "") - model.updateType(self.machine_variant or "") + model.updateKey(self.uuid) + model.updateName(self.friendly_name) + model.updateUniqueName(self.unique_name) + model.updateType(self.machine_variant) model.updateState(self.status if self.enabled else "disabled") model.updateBuildplate(self.build_plate.type if self.build_plate else "glass") if self.ip_address: From 90170c694ccb09ec4e7d62ad5ebbe6ca735805b5 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 26 Jun 2025 09:23:20 +0200 Subject: [PATCH 227/299] Unlink the reusable workflows and add build args --- .github/workflows/find-packages.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index ad8fb6271d..671121904a 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -11,6 +11,18 @@ on: default: false required: false type: boolean + conan_args: + description: 'Conan args' + default: '' + type: string + enterprise: + description: 'Build Cura as an Enterprise edition' + default: false + type: boolean + staging: + description: 'Use staging API' + default: false + type: boolean permissions: contents: read @@ -23,3 +35,17 @@ jobs: jira_ticket_number: ${{ inputs.jira_ticket_number }} start_builds: ${{ inputs.start_builds }} secrets: inherit + + installers: + name: Create installers + needs: find-packages + if: ${{ inputs.start_builds == true && needs.find-packages.outputs.cura_conan_version != '' }} + uses: ultimaker/cura-workflows/.github/workflows/cura-installers.yml@main + with: + cura_conan_version: ${{ needs.find-packages.outputs.cura_conan_version }} + package_overrides: ${{ needs.find-packages.outputs.package_overrides }} + conan_args: ${{ inputs.conan_args }} + enterprise: ${{ inputs.enterprise }} + staging: ${{ inputs.staging }} + secrets: inherit + From 06cf1151e5e7e63285b11de8c3ddedb28c334ddd Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 26 Jun 2025 09:26:46 +0200 Subject: [PATCH 228/299] remove input for starting build from workflow - installers job is moved to this workflow so the trigger to start build is handled locally and should not be sent to reusable workflow --- .github/workflows/find-packages.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index 671121904a..60f87c8688 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -33,7 +33,6 @@ jobs: uses: ultimaker/cura-workflows/.github/workflows/find-package-by-ticket.yml@jira_find_package with: jira_ticket_number: ${{ inputs.jira_ticket_number }} - start_builds: ${{ inputs.start_builds }} secrets: inherit installers: From 9cc61d7db092427cb077aa8371a5e0f00970ba85 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 26 Jun 2025 09:44:01 +0200 Subject: [PATCH 229/299] workflow input/output name correction --- .github/workflows/find-packages.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index 60f87c8688..fa2dfe2d39 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -38,10 +38,10 @@ jobs: installers: name: Create installers needs: find-packages - if: ${{ inputs.start_builds == true && needs.find-packages.outputs.cura_conan_version != '' }} + if: ${{ inputs.start_builds == true && needs.find-packages.outputs.discovered_packages != '' }} uses: ultimaker/cura-workflows/.github/workflows/cura-installers.yml@main with: - cura_conan_version: ${{ needs.find-packages.outputs.cura_conan_version }} + cura_conan_version: ${{ needs.find-packages.outputs.cura_package }} package_overrides: ${{ needs.find-packages.outputs.package_overrides }} conan_args: ${{ inputs.conan_args }} enterprise: ${{ inputs.enterprise }} From 300d776f1a1a96e3d278ffd5db0db07ee77ede89 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 26 Jun 2025 09:48:46 +0200 Subject: [PATCH 230/299] adjust to access the workflow_dispatch input inputs.start_builds is only available at the top-level workflow, not inside a job's if condition. --- .github/workflows/find-packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index fa2dfe2d39..4e584844d6 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -38,7 +38,7 @@ jobs: installers: name: Create installers needs: find-packages - if: ${{ inputs.start_builds == true && needs.find-packages.outputs.discovered_packages != '' }} + if: ${{ github.event.inputs.start_builds == 'true' && needs.find-packages.outputs.discovered_packages != '' }} uses: ultimaker/cura-workflows/.github/workflows/cura-installers.yml@main with: cura_conan_version: ${{ needs.find-packages.outputs.cura_package }} From a6bb69566665c99e210e2d7045110a3dcc699f69 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 26 Jun 2025 10:04:28 +0200 Subject: [PATCH 231/299] debug - remove the input check --- .github/workflows/find-packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index 4e584844d6..283e59286e 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -38,7 +38,7 @@ jobs: installers: name: Create installers needs: find-packages - if: ${{ github.event.inputs.start_builds == 'true' && needs.find-packages.outputs.discovered_packages != '' }} + if: ${{ needs.find-packages.outputs.discovered_packages != '' }} uses: ultimaker/cura-workflows/.github/workflows/cura-installers.yml@main with: cura_conan_version: ${{ needs.find-packages.outputs.cura_package }} From 7637bbe3ca8abeccf4fd7d5842712e743e9dd6db Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 26 Jun 2025 10:07:03 +0200 Subject: [PATCH 232/299] debug output --- .github/workflows/find-packages.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index 283e59286e..d9772dd782 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -35,6 +35,16 @@ jobs: jira_ticket_number: ${{ inputs.jira_ticket_number }} secrets: inherit + debug-outputs: + name: Debug Outputs + needs: find-packages + runs-on: ubuntu-latest + steps: + - run: | + echo "discovered_packages: '${{ needs.find-packages.outputs.discovered_packages }}'" + echo "cura_package: '${{ needs.find-packages.outputs.cura_package }}'" + echo "package_overrides: '${{ needs.find-packages.outputs.package_overrides }}'" + installers: name: Create installers needs: find-packages From f2c754ef7a3c3f41c73279724bf7a09ebea9e1fa Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 26 Jun 2025 10:16:13 +0200 Subject: [PATCH 233/299] Remove debug and set the start_builds condition back --- .github/workflows/find-packages.yml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index d9772dd782..fa2dfe2d39 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -35,20 +35,10 @@ jobs: jira_ticket_number: ${{ inputs.jira_ticket_number }} secrets: inherit - debug-outputs: - name: Debug Outputs - needs: find-packages - runs-on: ubuntu-latest - steps: - - run: | - echo "discovered_packages: '${{ needs.find-packages.outputs.discovered_packages }}'" - echo "cura_package: '${{ needs.find-packages.outputs.cura_package }}'" - echo "package_overrides: '${{ needs.find-packages.outputs.package_overrides }}'" - installers: name: Create installers needs: find-packages - if: ${{ needs.find-packages.outputs.discovered_packages != '' }} + if: ${{ inputs.start_builds == true && needs.find-packages.outputs.discovered_packages != '' }} uses: ultimaker/cura-workflows/.github/workflows/cura-installers.yml@main with: cura_conan_version: ${{ needs.find-packages.outputs.cura_package }} From f506fe570949559a5da33c49d43c264626b98322 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 26 Jun 2025 10:22:22 +0200 Subject: [PATCH 234/299] Update find-packages.yml --- .github/workflows/find-packages.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index fa2dfe2d39..81f68857e5 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -1,4 +1,4 @@ -name: Conan Package Discovery by Jira Ticket +name: Find packages for Jira ticket and create installers on: workflow_dispatch: @@ -30,7 +30,7 @@ permissions: jobs: find-packages: name: Find packages for Jira ticket - uses: ultimaker/cura-workflows/.github/workflows/find-package-by-ticket.yml@jira_find_package + uses: ultimaker/cura-workflows/.github/workflows/find-package-by-ticket.yml@main with: jira_ticket_number: ${{ inputs.jira_ticket_number }} secrets: inherit @@ -47,4 +47,3 @@ jobs: enterprise: ${{ inputs.enterprise }} staging: ${{ inputs.staging }} secrets: inherit - From 21764d3db00a573aa3635fe1635d995ec85b034d Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 26 Jun 2025 10:38:48 +0200 Subject: [PATCH 235/299] Remove redundant override The value is overwritten with the formula in fdmprinter, so setting the default_value does not have any effect in this case. --- resources/definitions/sovol_sv08.def.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/definitions/sovol_sv08.def.json b/resources/definitions/sovol_sv08.def.json index a0cda31889..e64cca8a06 100644 --- a/resources/definitions/sovol_sv08.def.json +++ b/resources/definitions/sovol_sv08.def.json @@ -95,7 +95,6 @@ "retraction_combing_max_distance": { "default_value": 10 }, "retraction_hop": { "default_value": 0.4 }, "retraction_hop_enabled": { "default_value": true }, - "retraction_min_travel": { "default_value": 1 }, "retraction_prime_speed": { "maximum_value_warning": 130, @@ -128,4 +127,4 @@ "wall_overhang_speed_factor": { "default_value": 50 }, "zig_zaggify_infill": { "value": true } } -} \ No newline at end of file +} From 445ea884ffc5837610801a32dbf73ab7da434f69 Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Thu, 26 Jun 2025 08:39:47 +0000 Subject: [PATCH 236/299] Apply printer-linter format --- resources/definitions/sovol_sv08.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/sovol_sv08.def.json b/resources/definitions/sovol_sv08.def.json index e64cca8a06..a0b7125a9e 100644 --- a/resources/definitions/sovol_sv08.def.json +++ b/resources/definitions/sovol_sv08.def.json @@ -127,4 +127,4 @@ "wall_overhang_speed_factor": { "default_value": 50 }, "zig_zaggify_infill": { "value": true } } -} +} \ No newline at end of file From 8bfd3047548c41432fa374f7dcc4c1f87258704e Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 26 Jun 2025 14:26:51 +0200 Subject: [PATCH 237/299] definition fix wall_overhang_speed_factor: Int should be wall_overhang_speed_factors: List --- resources/definitions/sovol_sv08.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/sovol_sv08.def.json b/resources/definitions/sovol_sv08.def.json index a0b7125a9e..c3896304fe 100644 --- a/resources/definitions/sovol_sv08.def.json +++ b/resources/definitions/sovol_sv08.def.json @@ -124,7 +124,7 @@ "travel_avoid_other_parts": { "default_value": false }, "wall_line_width": { "value": "machine_nozzle_size" }, "wall_overhang_angle": { "default_value": 75 }, - "wall_overhang_speed_factor": { "default_value": 50 }, + "wall_overhang_speed_factors": { "default_value": [50] }, "zig_zaggify_infill": { "value": true } } } \ No newline at end of file From ccea5bcfee63e8ccea0615f7e02f7ad7bf035949 Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Thu, 26 Jun 2025 12:27:49 +0000 Subject: [PATCH 238/299] Apply printer-linter format --- resources/definitions/sovol_sv08.def.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/resources/definitions/sovol_sv08.def.json b/resources/definitions/sovol_sv08.def.json index c3896304fe..95a03f6e99 100644 --- a/resources/definitions/sovol_sv08.def.json +++ b/resources/definitions/sovol_sv08.def.json @@ -124,7 +124,12 @@ "travel_avoid_other_parts": { "default_value": false }, "wall_line_width": { "value": "machine_nozzle_size" }, "wall_overhang_angle": { "default_value": 75 }, - "wall_overhang_speed_factors": { "default_value": [50] }, + "wall_overhang_speed_factors": + { + "default_value": [ + 50 + ] + }, "zig_zaggify_infill": { "value": true } } } \ No newline at end of file From dd12c8152c14dde1495ea7012baabcf4e8a89a04 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 26 Jun 2025 14:47:21 +0200 Subject: [PATCH 239/299] overhang speed factors update to string(list) --- resources/definitions/sovol_sv08.def.json | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/resources/definitions/sovol_sv08.def.json b/resources/definitions/sovol_sv08.def.json index 95a03f6e99..147b839fbf 100644 --- a/resources/definitions/sovol_sv08.def.json +++ b/resources/definitions/sovol_sv08.def.json @@ -124,12 +124,7 @@ "travel_avoid_other_parts": { "default_value": false }, "wall_line_width": { "value": "machine_nozzle_size" }, "wall_overhang_angle": { "default_value": 75 }, - "wall_overhang_speed_factors": - { - "default_value": [ - 50 - ] - }, + "wall_overhang_speed_factors": { "default_value": "[50]" }, "zig_zaggify_infill": { "value": true } } -} \ No newline at end of file +} From b73c5091ac6f8cdcb27f255473218d50c2d047bd Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Thu, 26 Jun 2025 12:48:18 +0000 Subject: [PATCH 240/299] Apply printer-linter format --- resources/definitions/sovol_sv08.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/sovol_sv08.def.json b/resources/definitions/sovol_sv08.def.json index 147b839fbf..a662b19618 100644 --- a/resources/definitions/sovol_sv08.def.json +++ b/resources/definitions/sovol_sv08.def.json @@ -127,4 +127,4 @@ "wall_overhang_speed_factors": { "default_value": "[50]" }, "zig_zaggify_infill": { "value": true } } -} +} \ No newline at end of file From 39c791ba470d42d56c221cebf71d4fd07928cbb7 Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Thu, 26 Jun 2025 15:01:17 +0000 Subject: [PATCH 241/299] Apply printer-linter format --- resources/extruders/sovol_sv08_extruder.def.json | 2 +- .../sovol/ABS/sovol_sv08_0.4_ABS_standard.inst.cfg | 9 +++++---- .../sovol/PETG/sovol_sv08_0.4_PETG_standard.inst.cfg | 9 +++++---- .../sovol/PLA/sovol_sv08_0.4_PLA_standard.inst.cfg | 9 +++++---- .../sovol/TPU/sovol_sv08_0.4_TPU_standard.inst.cfg | 9 +++++---- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/resources/extruders/sovol_sv08_extruder.def.json b/resources/extruders/sovol_sv08_extruder.def.json index 407c81de47..d0ccdee1de 100644 --- a/resources/extruders/sovol_sv08_extruder.def.json +++ b/resources/extruders/sovol_sv08_extruder.def.json @@ -16,4 +16,4 @@ }, "material_diameter": { "default_value": 1.75 } } -} +} \ No newline at end of file diff --git a/resources/quality/sovol/ABS/sovol_sv08_0.4_ABS_standard.inst.cfg b/resources/quality/sovol/ABS/sovol_sv08_0.4_ABS_standard.inst.cfg index 2fda8d1811..4fdd35f5ba 100644 --- a/resources/quality/sovol/ABS/sovol_sv08_0.4_ABS_standard.inst.cfg +++ b/resources/quality/sovol/ABS/sovol_sv08_0.4_ABS_standard.inst.cfg @@ -11,16 +11,17 @@ type = quality variant = 0.4mm Nozzle [values] +bridge_fan_speed = 30 +bridge_settings_enabled = True cool_fan_enabled = True cool_fan_speed = 10 cool_fan_speed_max = 30 -cool_min_layer_time_fan_speed_max = 30 cool_min_layer_time = 4 +cool_min_layer_time_fan_speed_max = 30 cool_min_speed = 10 +material_bed_temperature = 95 material_flow = 98 material_max_flowrate = 21 material_print_temperature = 270 material_print_temperature_layer_0 = 280 -material_bed_temperature = 95 -bridge_settings_enabled = True -bridge_fan_speed = 30 + diff --git a/resources/quality/sovol/PETG/sovol_sv08_0.4_PETG_standard.inst.cfg b/resources/quality/sovol/PETG/sovol_sv08_0.4_PETG_standard.inst.cfg index ba43c72c8b..3cf9d68d04 100644 --- a/resources/quality/sovol/PETG/sovol_sv08_0.4_PETG_standard.inst.cfg +++ b/resources/quality/sovol/PETG/sovol_sv08_0.4_PETG_standard.inst.cfg @@ -11,16 +11,17 @@ type = quality variant = 0.4mm Nozzle [values] +bridge_fan_speed = 70 +bridge_settings_enabled = True cool_fan_enabled = True cool_fan_speed = 10 cool_fan_speed_max = 30 -cool_min_layer_time_fan_speed_max = 30 cool_min_layer_time = 5 +cool_min_layer_time_fan_speed_max = 30 cool_min_speed = 10 +material_bed_temperature = 75 material_flow = 98 material_max_flowrate = 17 material_print_temperature = 235 material_print_temperature_layer_0 = 250 -material_bed_temperature = 75 -bridge_settings_enabled = True -bridge_fan_speed = 70 + diff --git a/resources/quality/sovol/PLA/sovol_sv08_0.4_PLA_standard.inst.cfg b/resources/quality/sovol/PLA/sovol_sv08_0.4_PLA_standard.inst.cfg index 2a70b9415b..daca9ebd94 100644 --- a/resources/quality/sovol/PLA/sovol_sv08_0.4_PLA_standard.inst.cfg +++ b/resources/quality/sovol/PLA/sovol_sv08_0.4_PLA_standard.inst.cfg @@ -11,16 +11,17 @@ type = quality variant = 0.4mm Nozzle [values] +bridge_fan_speed = 100 +bridge_settings_enabled = True cool_fan_enabled = True cool_fan_speed = 50 cool_fan_speed_max = 70 -cool_min_layer_time_fan_speed_max = 50 cool_min_layer_time = 5 +cool_min_layer_time_fan_speed_max = 50 cool_min_speed = 10 +material_bed_temperature = 65 material_flow = 98 material_max_flowrate = 21 material_print_temperature = 220 material_print_temperature_layer_0 = 235 -material_bed_temperature = 65 -bridge_settings_enabled = True -bridge_fan_speed = 100 + diff --git a/resources/quality/sovol/TPU/sovol_sv08_0.4_TPU_standard.inst.cfg b/resources/quality/sovol/TPU/sovol_sv08_0.4_TPU_standard.inst.cfg index 1908bdb6b0..c1b44b46b0 100644 --- a/resources/quality/sovol/TPU/sovol_sv08_0.4_TPU_standard.inst.cfg +++ b/resources/quality/sovol/TPU/sovol_sv08_0.4_TPU_standard.inst.cfg @@ -11,16 +11,17 @@ type = quality variant = 0.4mm Nozzle [values] +bridge_fan_speed = 100 +bridge_settings_enabled = True cool_fan_enabled = True cool_fan_speed = 80 cool_fan_speed_max = 100 -cool_min_layer_time_fan_speed_max = 50 cool_min_layer_time = 5 +cool_min_layer_time_fan_speed_max = 50 cool_min_speed = 10 +material_bed_temperature = 65 material_flow = 98 material_max_flowrate = 3.6 material_print_temperature = 240 material_print_temperature_layer_0 = 235 -material_bed_temperature = 65 -bridge_settings_enabled = True -bridge_fan_speed = 100 + From ae2a189c14dbab873b197b9235e8382847a7cf7e Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 30 Jun 2025 09:53:54 +0200 Subject: [PATCH 242/299] Replace "cloudActive" property by generic "active" CURA-12557 --- .../NetworkedPrinterOutputDevice.py | 4 ++-- cura/PrinterOutput/PrinterOutputDevice.py | 21 ++++++++++++++++++- cura/Settings/MachineManager.py | 11 ++++------ .../src/Cloud/CloudOutputDevice.py | 16 +++----------- .../UltimakerNetworkedPrinterOutputDevice.py | 4 ++-- .../qml/PrinterSelector/MachineSelector.qml | 4 ++-- 6 files changed, 33 insertions(+), 27 deletions(-) diff --git a/cura/PrinterOutput/NetworkedPrinterOutputDevice.py b/cura/PrinterOutput/NetworkedPrinterOutputDevice.py index 3dc245d468..1d0be1389e 100644 --- a/cura/PrinterOutput/NetworkedPrinterOutputDevice.py +++ b/cura/PrinterOutput/NetworkedPrinterOutputDevice.py @@ -33,8 +33,8 @@ class AuthState(IntEnum): class NetworkedPrinterOutputDevice(PrinterOutputDevice): authenticationStateChanged = pyqtSignal() - def __init__(self, device_id, address: str, properties: Dict[bytes, bytes], connection_type: ConnectionType = ConnectionType.NetworkConnection, parent: QObject = None) -> None: - super().__init__(device_id = device_id, connection_type = connection_type, parent = parent) + def __init__(self, device_id, address: str, properties: Dict[bytes, bytes], connection_type: ConnectionType = ConnectionType.NetworkConnection, parent: QObject = None, active: bool = True) -> None: + super().__init__(device_id = device_id, connection_type = connection_type, parent = parent, active = active) self._manager = None # type: Optional[QNetworkAccessManager] self._timeout_time = 10 # After how many seconds of no response should a timeout occur? diff --git a/cura/PrinterOutput/PrinterOutputDevice.py b/cura/PrinterOutput/PrinterOutputDevice.py index 9c1727f569..b369fc1129 100644 --- a/cura/PrinterOutput/PrinterOutputDevice.py +++ b/cura/PrinterOutput/PrinterOutputDevice.py @@ -72,7 +72,10 @@ class PrinterOutputDevice(QObject, OutputDevice): # Signal to indicate that the configuration of one of the printers has changed. uniqueConfigurationsChanged = pyqtSignal() - def __init__(self, device_id: str, connection_type: "ConnectionType" = ConnectionType.NotConnected, parent: QObject = None) -> None: + # Signal to indicate that the printer has become active or inactive + activeChanged = pyqtSignal() + + def __init__(self, device_id: str, connection_type: "ConnectionType" = ConnectionType.NotConnected, parent: QObject = None, active: bool = True) -> None: super().__init__(device_id = device_id, parent = parent) # type: ignore # MyPy complains with the multiple inheritance self._printers = [] # type: List[PrinterOutputModel] @@ -88,6 +91,8 @@ class PrinterOutputDevice(QObject, OutputDevice): self._accepts_commands = False # type: bool + self._active: bool = active + self._update_timer = QTimer() # type: QTimer self._update_timer.setInterval(2000) # TODO; Add preference for update interval self._update_timer.setSingleShot(False) @@ -295,3 +300,17 @@ class PrinterOutputDevice(QObject, OutputDevice): return self._firmware_updater.updateFirmware(firmware_file) + + @pyqtProperty(bool, notify = activeChanged) + def active(self) -> bool: + """ + Indicates whether the printer is active, which is not the same as "being the active printer". In this case, + active means that the printer can be used. An example of an inactive printer is one that cannot be used because + the user doesn't have enough seats on Digital Factory. + """ + return self._active + + def _setActive(self, active: bool) -> None: + if active != self._active: + self._active = active + self.activeChanged.emit() diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 1bdb32f4ac..3a2201449d 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -184,15 +184,13 @@ class MachineManager(QObject): def _onOutputDevicesChanged(self) -> None: for printer_output_device in self._printer_output_devices: - if hasattr(printer_output_device, "cloudActiveChanged"): - printer_output_device.cloudActiveChanged.disconnect(self.printerConnectedStatusChanged) + printer_output_device.activeChanged.disconnect(self.printerConnectedStatusChanged) self._printer_output_devices = [] for printer_output_device in self._application.getOutputDeviceManager().getOutputDevices(): if isinstance(printer_output_device, PrinterOutputDevice): self._printer_output_devices.append(printer_output_device) - if hasattr(printer_output_device, "cloudActiveChanged"): - printer_output_device.cloudActiveChanged.connect(self.printerConnectedStatusChanged) + printer_output_device.activeChanged.connect(self.printerConnectedStatusChanged) self.outputDevicesChanged.emit() @@ -576,12 +574,11 @@ class MachineManager(QObject): return self.activeMachineHasCloudConnection and not self.activeMachineHasNetworkConnection @pyqtProperty(bool, notify = printerConnectedStatusChanged) - def activeMachineIsCloudActive(self) -> bool: + def activeMachineIsActive(self) -> bool: if not self._printer_output_devices: return True - first_printer = self._printer_output_devices[0] - return True if not hasattr(first_printer, 'cloudActive') else first_printer.cloudActive + return self._printer_output_devices[0].active def activeMachineNetworkKey(self) -> str: if self._global_container_stack: diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py index 020cafacd8..010ef93fbd 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py @@ -65,8 +65,6 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): # Therefore, we create a private signal used to trigger the printersChanged signal. _cloudClusterPrintersChanged = pyqtSignal() - cloudActiveChanged = pyqtSignal() - def __init__(self, api_client: CloudApiClient, cluster: CloudClusterResponse, parent: QObject = None) -> None: """Creates a new cloud output device @@ -91,7 +89,8 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): address="", connection_type=ConnectionType.CloudConnection, properties=properties, - parent=parent + parent=parent, + active=cluster.display_status != "inactive" ) self._api = api_client @@ -115,9 +114,6 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): self._pre_upload_print_job = None # type: Optional[CloudPrintJobResponse] self._uploaded_print_job = None # type: Optional[CloudPrintJobResponse] - # Whether the printer is active, i.e. authorized for use i.r.t to workspace limitations - self._active = cluster.display_status != "inactive" - CuraApplication.getInstance().getBackend().backendDone.connect(self._resetPrintJob) CuraApplication.getInstance().getController().getScene().sceneChanged.connect(self._onSceneChanged) @@ -197,9 +193,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): self._received_print_jobs = status.print_jobs self._updatePrintJobs(status.print_jobs) - if status.active != self._active: - self._active = status.active - self.cloudActiveChanged.emit() + self._setActive(status.active) def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False, file_handler: Optional[FileHandler] = None, filter_by_machine: bool = False, **kwargs) -> None: @@ -445,10 +439,6 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): root_url_prefix = "-staging" if self._account.is_staging else "" return f"https://digitalfactory{root_url_prefix}.ultimaker.com/app/jobs/{self.clusterData.cluster_id}" - @pyqtProperty(bool, notify = cloudActiveChanged) - def cloudActive(self) -> bool: - return self._active - def __del__(self): CuraApplication.getInstance().getBackend().backendDone.disconnect(self._resetPrintJob) CuraApplication.getInstance().getController().getScene().sceneChanged.disconnect(self._onSceneChanged) diff --git a/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterOutputDevice.py index 8f25df37db..3ac5ccc7e7 100644 --- a/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterOutputDevice.py @@ -46,10 +46,10 @@ class UltimakerNetworkedPrinterOutputDevice(NetworkedPrinterOutputDevice): QUEUED_PRINT_JOBS_STATES = {"queued", "error"} def __init__(self, device_id: str, address: str, properties: Dict[bytes, bytes], connection_type: ConnectionType, - parent=None) -> None: + parent=None, active: bool = True) -> None: super().__init__(device_id=device_id, address=address, properties=properties, connection_type=connection_type, - parent=parent) + parent=parent, active=active) # Trigger the printersChanged signal when the private signal is triggered. self.printersChanged.connect(self._clusterPrintersChanged) diff --git a/resources/qml/PrinterSelector/MachineSelector.qml b/resources/qml/PrinterSelector/MachineSelector.qml index 7acdd9573b..e8ee98fe8f 100644 --- a/resources/qml/PrinterSelector/MachineSelector.qml +++ b/resources/qml/PrinterSelector/MachineSelector.qml @@ -16,7 +16,7 @@ Cura.ExpandablePopup property bool isConnectedCloudPrinter: machineManager.activeMachineHasCloudConnection property bool isCloudRegistered: machineManager.activeMachineHasCloudRegistration property bool isGroup: machineManager.activeMachineIsGroup - property bool isCloudActive: machineManager.activeMachineIsCloudActive + property bool isActive: machineManager.activeMachineIsActive property string machineName: { if (isNetworkPrinter && machineManager.activeMachineNetworkGroupName != "") { @@ -41,7 +41,7 @@ Cura.ExpandablePopup } else if (isConnectedCloudPrinter && Cura.API.connectionStatus.isInternetReachable) { - if (isCloudActive) + if (isActive) { return "printer_cloud_connected" } From 3ad2c1b5788466412e17f23840deb9197ba9e19e Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Mon, 30 Jun 2025 21:39:03 -0400 Subject: [PATCH 243/299] Update DisplayInfoOnLCD.py Add "Electricity Cost" to the statistics added to the gcode. Update DisplayInfoOnLCD.py Formatting changes for layer heights --- .../scripts/DisplayInfoOnLCD.py | 45 ++++++++++++++++--- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 89c76769c9..ddf292fb85 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -29,6 +29,7 @@ Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It uses the Time Fudge Factor. The user may enter a print start time. +Date: June 30, 2025 Cost of electricity added to the other print statistics in '_add_stats'. """ from ..Script import Script @@ -37,6 +38,7 @@ from UM.Qt.Duration import DurationFormat import time import datetime import math +from UM.Preferences import Preferences from UM.Message import Message class DisplayInfoOnLCD(Script): @@ -234,7 +236,26 @@ class DisplayInfoOnLCD(Script): "default_value": "", "unit": "hrs ", "enabled": "enable_end_message" + }, + "electricity_cost": + { + "label": "Electricity Cost per kWh", + "description": "Cost of electricity per kilowatt-hour. This should be on your electric utility bill.", + "type": "float", + "default_value": 0.151, + "minimum_value": 0, + "unit": "€/kWh " + }, + "printer_power_usage": + { + "label": "Printer Power Usage", + "description": "Average power usage of the 3D printer in Watts. The actual wattage has many variables. 50% of the power supply rating would be a ballpark figure.", + "type": "float", + "default_value": 175, + "minimum_value": 0, + "unit": "Watts " } + } }""" @@ -249,6 +270,11 @@ class DisplayInfoOnLCD(Script): self.add_m73_time = self.getSettingValueByKey("add_m73_time") self.add_m73_percent = self.getSettingValueByKey("add_m73_percent") self.m73_str = "" + para_1 = data[0].split("\n") + for line in para_1: + if line.startswith(";TIME:"): + self.time_total = int(line.split(":")[1]) + break if display_option == "filename_layer": data = self._display_filename_layer(data) else: @@ -337,7 +363,6 @@ class DisplayInfoOnLCD(Script): data[len(data)-1] += "M77\n" # Initialize some variables first_layer_index = 0 - time_total = int(data[0].split(";TIME:")[1].split("\n")[0]) number_of_layers = 0 time_elapsed = 0 @@ -418,8 +443,6 @@ class DisplayInfoOnLCD(Script): for lay in range(2,len(data)-1,1): if ";LAYER:" in data[lay]: number_of_layers += 1 - elif line.startswith(";TIME:"): - time_total = int(line.split(":")[1]) # for all layers... current_layer = 0 for layer_counter in range(len(data)-2): @@ -438,7 +461,7 @@ class DisplayInfoOnLCD(Script): # if display_remaining_time is checked, it is calculated in this loop if display_remaining_time: time_remaining_display = " | ET " # initialize the time display - m = (time_total - time_elapsed) // 60 # estimated time in minutes + m = (self.time_total - time_elapsed) // 60 # estimated time in minutes m *= speed_factor # correct for printing time m = int(m) h, m = divmod(m, 60) # convert to hours and minutes @@ -640,7 +663,8 @@ class DisplayInfoOnLCD(Script): model_list.append(model_name) # Filament stats extruder_count = global_stack.getProperty("machine_extruder_count", "value") - init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) + layheight_0 = global_stack.getProperty("layer_height_0", "value") + init_layer_hgt_line = ";Initial Layer Height: " + f"{layheight_0:.2f}".format(layheight_0) filament_line_t0 = ";Extruder 1 (T0)\n" filament_amount = Application.getInstance().getPrintInformation().materialLengths filament_line_t0 += f"; Filament used: {filament_amount[0]}m\n" @@ -659,16 +683,23 @@ class DisplayInfoOnLCD(Script): filament_line_t1 += f"; Filament Dia.: {global_stack.extruderList[1].getProperty("material_diameter", "value")}mm\n" filament_line_t1 += f"; Nozzle Size : {global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")}mm\n" filament_line_t1 += f"; Print Temp. : {global_stack.extruderList[1].getProperty("material_print_temperature", "value")}°" - + + # Calculate the cost of electricity for the print + electricity_cost = self.getSettingValueByKey("electricity_cost") + printer_power_usage = self.getSettingValueByKey("printer_power_usage") + currency_unit = Application.getInstance().getPreferences().getValue("cura/currency") + total_cost_electricity = (printer_power_usage / 1000) * (self.time_total / 3600) * electricity_cost + # Add the stats to the gcode file lines = data[0].split("\n") for index, line in enumerate(lines): if line.startswith(";Layer height:"): + lines[index] = ";Layer height: " + f"{float(line.split(":")[1]):.2f}".format(float(line.split(":")[1])) lines[index] += f"\n{init_layer_hgt_line}" lines[index] += f"\n;Base Quality Name : '{global_stack.quality.getMetaDataEntry("name", "")}'" lines[index] += f"\n;Custom Quality Name: '{global_stack.qualityChanges.getMetaDataEntry("name")}'" if line.startswith(";Filament used"): - lines[index] = filament_line_t0 + filament_line_t1 + lines[index] = filament_line_t0 + filament_line_t1 + f"\n;Electric Cost: {currency_unit}{total_cost_electricity:.2f}".format(total_cost_electricity) # The target machine "machine_name" is actually the printer model. This adds the user defined printer name to the "TARGET_MACHINE" line. if line.startswith(";TARGET_MACHINE"): machine_model = str(global_stack.getProperty("machine_name", "value")) From bbddcab4e9520af04e390dc7c9ffe739488ddef1 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 2 Jul 2025 14:04:41 +0200 Subject: [PATCH 244/299] Proper paint-on-seam UI CURA-12578 --- plugins/PaintTool/BrushColorButton.qml | 25 ++ plugins/PaintTool/BrushShapeButton.qml | 25 ++ plugins/PaintTool/PaintModeButton.qml | 24 ++ plugins/PaintTool/PaintTool.py | 19 +- plugins/PaintTool/PaintTool.qml | 264 +++++++++--------- plugins/PaintTool/PaintView.py | 38 ++- ...ectorButton.qml => ModeSelectorButton.qml} | 13 +- .../RecommendedQualityProfileSelector.qml | 5 +- .../cura-light/icons/default/Circle.svg | 5 + .../cura-light/icons/default/Eraser.svg | 5 + .../themes/cura-light/icons/default/Seam.svg | 6 + .../cura-light/icons/low/CancelBadge.svg | 5 + .../cura-light/icons/low/CheckBadge.svg | 5 + 13 files changed, 274 insertions(+), 165 deletions(-) create mode 100644 plugins/PaintTool/BrushColorButton.qml create mode 100644 plugins/PaintTool/BrushShapeButton.qml create mode 100644 plugins/PaintTool/PaintModeButton.qml rename resources/qml/{PrintSetupSelector/Recommended/RecommendedQualityProfileSelectorButton.qml => ModeSelectorButton.qml} (91%) create mode 100644 resources/themes/cura-light/icons/default/Circle.svg create mode 100644 resources/themes/cura-light/icons/default/Eraser.svg create mode 100644 resources/themes/cura-light/icons/default/Seam.svg create mode 100644 resources/themes/cura-light/icons/low/CancelBadge.svg create mode 100644 resources/themes/cura-light/icons/low/CheckBadge.svg diff --git a/plugins/PaintTool/BrushColorButton.qml b/plugins/PaintTool/BrushColorButton.qml new file mode 100644 index 0000000000..71556f2681 --- /dev/null +++ b/plugins/PaintTool/BrushColorButton.qml @@ -0,0 +1,25 @@ +// Copyright (c) 2025 UltiMaker +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick + +import UM 1.7 as UM +import Cura 1.0 as Cura + + +UM.ToolbarButton +{ + id: buttonBrushColor + + property string color + + checked: base.selectedColor === buttonBrushColor.color + + onClicked: setColor() + + function setColor() + { + base.selectedColor = buttonBrushColor.color + UM.Controller.triggerActionWithData("setBrushColor", buttonBrushColor.color) + } +} diff --git a/plugins/PaintTool/BrushShapeButton.qml b/plugins/PaintTool/BrushShapeButton.qml new file mode 100644 index 0000000000..5c290e4a13 --- /dev/null +++ b/plugins/PaintTool/BrushShapeButton.qml @@ -0,0 +1,25 @@ +// Copyright (c) 2025 UltiMaker +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick + +import UM 1.7 as UM +import Cura 1.0 as Cura + + +UM.ToolbarButton +{ + id: buttonBrushShape + + property int shape + + checked: base.selectedShape === buttonBrushShape.shape + + onClicked: setShape() + + function setShape() + { + base.selectedShape = buttonBrushShape.shape + UM.Controller.triggerActionWithData("setBrushShape", buttonBrushShape.shape) + } +} diff --git a/plugins/PaintTool/PaintModeButton.qml b/plugins/PaintTool/PaintModeButton.qml new file mode 100644 index 0000000000..473996e04b --- /dev/null +++ b/plugins/PaintTool/PaintModeButton.qml @@ -0,0 +1,24 @@ +// Copyright (c) 2025 UltiMaker +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick + +import UM 1.7 as UM +import Cura 1.0 as Cura + +Cura.ModeSelectorButton +{ + id: modeSelectorButton + + property string mode + + selected: base.selectedMode === modeSelectorButton.mode + + onClicked: setMode() + + function setMode() + { + base.selectedMode = modeSelectorButton.mode + UM.Controller.triggerActionWithData("setPaintType", modeSelectorButton.mode) + } +} diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 0c3ac0d661..524011af9d 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -42,7 +42,7 @@ class PaintTool(Tool): self._cache_dirty: bool = True self._brush_size: int = 10 - self._brush_color: str = "A" + self._brush_color: str = "" self._brush_shape: PaintTool.Brush.Shape = PaintTool.Brush.Shape.SQUARE self._brush_pen: QPen = self._createBrushPen() @@ -122,6 +122,18 @@ class PaintTool(Tool): self._updateScene() return True + def clear(self) -> None: + paintview = self._get_paint_view() + if paintview is None: + return + + width, height = paintview.getUvTexDimensions() + clear_image = QImage(width, height, QImage.Format.Format_RGB32) + clear_image.fill(Qt.GlobalColor.white) + paintview.addStroke(clear_image, 0, 0, "none") + + self._updateScene() + @staticmethod def _get_paint_view() -> Optional[PaintView]: paint_view = Application.getInstance().getController().getActiveView() @@ -265,10 +277,9 @@ class PaintTool(Tool): else: self._mouse_held = True - paintview = controller.getActiveView() - if paintview is None or paintview.getPluginId() != "PaintTool": + paintview = self._get_paint_view() + if paintview is None: return False - paintview = cast(PaintView, paintview) if not self._selection_pass: return False diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index 602805cba1..4cbe9d4ade 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -15,6 +15,10 @@ Item height: childrenRect.height UM.I18nCatalog { id: catalog; name: "cura"} + property string selectedMode: "" + property string selectedColor: "" + property int selectedShape: 0 + Action { id: undoAction @@ -29,170 +33,158 @@ Item onTriggered: UM.Controller.triggerActionWithData("undoStackAction", true) } - ColumnLayout + Column { + id: mainColumn + spacing: UM.Theme.getSize("default_margin").height + RowLayout { - UM.ToolbarButton + id: rowPaintMode + width: parent.width + + PaintModeButton { - id: paintTypeA - - text: catalog.i18nc("@action:button", "Paint Type A") - toolItem: UM.ColorImage - { - source: UM.Theme.getIcon("Buildplate") - color: UM.Theme.getColor("icon") - } - property bool needBorder: true - - z: 2 - - onClicked: UM.Controller.triggerActionWithData("setPaintType", "A") + text: catalog.i18nc("@action:button", "Seam") + icon: "Seam" + tooltipText: catalog.i18nc("@tooltip", "Refine seam placement by defining preferred/avoidance areas") + mode: "seam" } - UM.ToolbarButton + PaintModeButton { - id: paintTypeB + text: catalog.i18nc("@action:button", "Support") + icon: "Support" + tooltipText: catalog.i18nc("@tooltip", "Refine support placement by defining preferred/avoidance areas") + mode: "support" + } + } - text: catalog.i18nc("@action:button", "Paint Type B") + //Line between the sections. + Rectangle + { + width: parent.width + height: UM.Theme.getSize("default_lining").height + color: UM.Theme.getColor("lining") + } + + RowLayout + { + id: rowBrushColor + + UM.Label + { + text: catalog.i18nc("@label", "Mark as") + } + + BrushColorButton + { + id: buttonPreferredArea + color: "preferred" + + text: catalog.i18nc("@action:button", "Preferred") toolItem: UM.ColorImage { - source: UM.Theme.getIcon("BlackMagic") + source: UM.Theme.getIcon("CheckBadge", "low") + color: UM.Theme.getColor("paint_preferred_area") + } + } + + BrushColorButton + { + id: buttonAvoidArea + color: "avoid" + + text: catalog.i18nc("@action:button", "Avoid") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("CancelBadge", "low") + color: UM.Theme.getColor("paint_avoid_area") + } + } + + BrushColorButton + { + id: buttonEraseArea + color: "none" + + text: catalog.i18nc("@action:button", "Erase") + toolItem: UM.ColorImage + { + source: UM.Theme.getIcon("Eraser") color: UM.Theme.getColor("icon") } - property bool needBorder: true - - z: 2 - - onClicked: UM.Controller.triggerActionWithData("setPaintType", "B") } } RowLayout { - UM.ToolbarButton + id: rowBrushShape + + UM.Label { - id: colorButtonA - - text: catalog.i18nc("@action:button", "Color A") - toolItem: UM.ColorImage - { - source: UM.Theme.getIcon("Eye") - color: "purple" - } - property bool needBorder: true - - z: 2 - - onClicked: UM.Controller.triggerActionWithData("setBrushColor", "A") + text: catalog.i18nc("@label", "Brush Shape") } - UM.ToolbarButton + BrushShapeButton { - id: colorButtonB + id: buttonBrushCircle + shape: Cura.PaintToolBrush.CIRCLE - text: catalog.i18nc("@action:button", "Color B") + text: catalog.i18nc("@action:button", "Circle") toolItem: UM.ColorImage { - source: UM.Theme.getIcon("Eye") - color: "orange" + source: UM.Theme.getIcon("Circle") + color: UM.Theme.getColor("icon") } - property bool needBorder: true - - z: 2 - - onClicked: UM.Controller.triggerActionWithData("setBrushColor", "B") } - UM.ToolbarButton + BrushShapeButton { - id: colorButtonC + id: buttonBrushSquare + shape: Cura.PaintToolBrush.SQUARE - text: catalog.i18nc("@action:button", "Color C") - toolItem: UM.ColorImage - { - source: UM.Theme.getIcon("Eye") - color: "green" - } - property bool needBorder: true - - z: 2 - - onClicked: UM.Controller.triggerActionWithData("setBrushColor", "C") - } - - UM.ToolbarButton - { - id: colorButtonD - - text: catalog.i18nc("@action:button", "Color D") - toolItem: UM.ColorImage - { - source: UM.Theme.getIcon("Eye") - color: "ghostwhite" - } - property bool needBorder: true - - z: 2 - - onClicked: UM.Controller.triggerActionWithData("setBrushColor", "D") - } - } - - RowLayout - { - UM.ToolbarButton - { - id: shapeSquareButton - - text: catalog.i18nc("@action:button", "Square Brush") + text: catalog.i18nc("@action:button", "Square") toolItem: UM.ColorImage { source: UM.Theme.getIcon("MeshTypeNormal") color: UM.Theme.getColor("icon") } - property bool needBorder: true - - z: 2 - - onClicked: UM.Controller.triggerActionWithData("setBrushShape", Cura.PaintToolBrush.SQUARE) } + } - UM.ToolbarButton + UM.Label + { + text: catalog.i18nc("@label", "Brush Size") + } + + UM.Slider + { + id: shapeSizeSlider + width: parent.width + indicatorVisible: false + + from: 1 + to: 40 + value: 10 + + onPressedChanged: function(pressed) { - id: shapeCircleButton - - text: catalog.i18nc("@action:button", "Round Brush") - toolItem: UM.ColorImage + if(! pressed) { - source: UM.Theme.getIcon("CircleOutline") - color: UM.Theme.getColor("icon") - } - property bool needBorder: true - - z: 2 - - onClicked: UM.Controller.triggerActionWithData("setBrushShape", Cura.PaintToolBrush.CIRCLE) - } - - UM.Slider - { - id: shapeSizeSlider - - from: 1 - to: 40 - value: 10 - - onPressedChanged: function(pressed) - { - if(! pressed) - { - UM.Controller.triggerActionWithData("setBrushSize", shapeSizeSlider.value) - } + UM.Controller.triggerActionWithData("setBrushSize", shapeSizeSlider.value) } } } + //Line between the sections. + Rectangle + { + width: parent.width + height: UM.Theme.getSize("default_lining").height + color: UM.Theme.getColor("lining") + } + RowLayout { UM.ToolbarButton @@ -203,10 +195,8 @@ Item toolItem: UM.ColorImage { source: UM.Theme.getIcon("ArrowReset") + color: UM.Theme.getColor("icon") } - property bool needBorder: true - - z: 2 onClicked: undoAction.trigger() } @@ -218,14 +208,30 @@ Item text: catalog.i18nc("@action:button", "Redo Stroke") toolItem: UM.ColorImage { - source: UM.Theme.getIcon("ArrowDoubleCircleRight") + source: UM.Theme.getIcon("ArrowReset") + color: UM.Theme.getColor("icon") + transform: [ + Scale { xScale: -1; origin.x: width/2 } + ] } - property bool needBorder: true - - z: 2 onClicked: redoAction.trigger() } + + Cura.SecondaryButton + { + id: clearButton + text: catalog.i18nc("@button", "Clear all") + onClicked: UM.Controller.triggerAction("clear") + } } } + + Component.onCompleted: + { + // Force first types for consistency, otherwise UI may become different from controller + rowPaintMode.children[0].setMode() + rowBrushColor.children[1].setColor() + rowBrushShape.children[1].setShape() + } } diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 32124872c4..22eb8c55f6 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -26,23 +26,17 @@ class PaintView(View): UNDO_STACK_SIZE = 1024 class PaintType: - def __init__(self, icon: str, display_color: Color, value: int): - self.icon: str = icon + def __init__(self, display_color: Color, value: int): self.display_color: Color = display_color self.value: int = value - class PaintMode: - def __init__(self, icon: str, types: Dict[str, "PaintView.PaintType"]): - self.icon: str = icon - self.types = types - def __init__(self) -> None: super().__init__() self._paint_shader: Optional[ShaderProgram] = None self._current_paint_texture: Optional[Texture] = None self._current_bits_ranges: tuple[int, int] = (0, 0) self._current_paint_type = "" - self._paint_modes: Dict[str, PaintView.PaintMode] = {} + self._paint_modes: Dict[str, Dict[str, "PaintView.PaintType"]] = {} self._stroke_undo_stack: List[Tuple[QImage, int, int]] = [] self._stroke_redo_stack: List[Tuple[QImage, int, int]] = [] @@ -54,12 +48,12 @@ class PaintView(View): def _makePaintModes(self): theme = CuraApplication.getInstance().getTheme() - usual_types = {"A": self.PaintType("Buildplate", Color(*theme.getColor("paint_normal_area").getRgb()), 0), - "B": self.PaintType("BlackMagic", Color(*theme.getColor("paint_preferred_area").getRgb()), 1), - "C": self.PaintType("Eye", Color(*theme.getColor("paint_avoid_area").getRgb()), 2)} + usual_types = {"none": self.PaintType(Color(*theme.getColor("paint_normal_area").getRgb()), 0), + "preferred": self.PaintType(Color(*theme.getColor("paint_preferred_area").getRgb()), 1), + "avoid": self.PaintType(Color(*theme.getColor("paint_avoid_area").getRgb()), 2)} self._paint_modes = { - "A": self.PaintMode("MeshTypeNormal", usual_types), - "B": self.PaintMode("CircleOutline", usual_types), + "seam": usual_types, + "support": usual_types, } def _checkSetup(self): @@ -78,32 +72,32 @@ class PaintView(View): res.setAlphaChannel(self._force_opaque_mask.scaled(image.width(), image.height())) return res - def addStroke(self, stroke_image: QImage, start_x: int, start_y: int, brush_color: str) -> None: + def addStroke(self, stroke_mask: QImage, start_x: int, start_y: int, brush_color: str) -> None: if self._current_paint_texture is None or self._current_paint_texture.getImage() is None: return actual_image = self._current_paint_texture.getImage() bit_range_start, bit_range_end = self._current_bits_ranges - set_value = self._paint_modes[self._current_paint_type].types[brush_color].value << self._current_bits_ranges[0] + set_value = self._paint_modes[self._current_paint_type][brush_color].value << self._current_bits_ranges[0] full_int32 = 0xffffffff clear_mask = full_int32 ^ (((full_int32 << (32 - 1 - (bit_range_end - bit_range_start))) & full_int32) >> (32 - 1 - bit_range_end)) - image_rect = QRect(0, 0, stroke_image.width(), stroke_image.height()) + image_rect = QRect(0, 0, stroke_mask.width(), stroke_mask.height()) - clear_bits_image = stroke_image.copy() + clear_bits_image = stroke_mask.copy() clear_bits_image.invertPixels() painter = QPainter(clear_bits_image) painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Lighten) painter.fillRect(image_rect, clear_mask) painter.end() - set_value_image = stroke_image.copy() + set_value_image = stroke_mask.copy() painter = QPainter(set_value_image) painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Multiply) painter.fillRect(image_rect, set_value) painter.end() - stroked_image = actual_image.copy(start_x, start_y, stroke_image.width(), stroke_image.height()) + stroked_image = actual_image.copy(start_x, start_y, stroke_mask.width(), stroke_mask.height()) painter = QPainter(stroked_image) painter.setCompositionMode(QPainter.CompositionMode.RasterOp_SourceAndDestination) painter.drawImage(0, 0, clear_bits_image) @@ -149,7 +143,7 @@ class PaintView(View): paint_data_mapping = node.callDecoration("getTextureDataMapping") if paint_type not in paint_data_mapping: - new_mapping = self._add_mapping(paint_data_mapping, len(self._paint_modes[paint_type].types)) + new_mapping = self._add_mapping(paint_data_mapping, len(self._paint_modes[paint_type])) paint_data_mapping[paint_type] = new_mapping node.callDecoration("setTextureDataMapping", paint_data_mapping) @@ -177,12 +171,12 @@ class PaintView(View): return if self._current_paint_type == "": - self.setPaintType("A") + return self._paint_shader.setUniformValue("u_bitsRangesStart", self._current_bits_ranges[0]) self._paint_shader.setUniformValue("u_bitsRangesEnd", self._current_bits_ranges[1]) - colors = [paint_type_obj.display_color for paint_type_obj in self._paint_modes[self._current_paint_type].types.values()] + colors = [paint_type_obj.display_color for paint_type_obj in self._paint_modes[self._current_paint_type].values()] colors_values = [[int(color_part * 255) for color_part in [color.r, color.g, color.b]] for color in colors] self._paint_shader.setUniformValueArray("u_renderColors", colors_values) diff --git a/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelectorButton.qml b/resources/qml/ModeSelectorButton.qml similarity index 91% rename from resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelectorButton.qml rename to resources/qml/ModeSelectorButton.qml index 1bbc726b9d..65a6ee4a75 100644 --- a/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelectorButton.qml +++ b/resources/qml/ModeSelectorButton.qml @@ -17,7 +17,7 @@ Rectangle color: mouseArea.containsMouse || selected ? UM.Theme.getColor("background_3") : UM.Theme.getColor("background_1") property bool selected: false - property string profileName: "" + property alias text: mainLabel.text property string icon: "" property string custom_icon: "" property alias tooltipText: tooltip.text @@ -42,18 +42,18 @@ Rectangle Item { - width: intentIcon.width + width: mainIcon.width anchors { top: parent.top - bottom: qualityLabel.top + bottom: mainLabel.top horizontalCenter: parent.horizontalCenter topMargin: UM.Theme.getSize("narrow_margin").height } Item { - id: intentIcon + id: mainIcon width: UM.Theme.getSize("recommended_button_icon").width height: UM.Theme.getSize("recommended_button_icon").height @@ -90,7 +90,7 @@ Rectangle { id: initialLabel anchors.centerIn: parent - text: profileName.charAt(0).toUpperCase() + text: base.text.charAt(0).toUpperCase() font: UM.Theme.getFont("small_bold") horizontalAlignment: Text.AlignHCenter } @@ -102,8 +102,7 @@ Rectangle UM.Label { - id: qualityLabel - text: profileName + id: mainLabel anchors { bottom: parent.bottom diff --git a/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml b/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml index 19c57e5130..1559f6cec3 100644 --- a/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml +++ b/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml @@ -7,7 +7,6 @@ import QtQuick.Layouts 2.10 import UM 1.5 as UM import Cura 1.7 as Cura -import ".." Item { @@ -28,9 +27,9 @@ Item id: intentSelectionRepeater model: Cura.IntentSelectionModel {} - RecommendedQualityProfileSelectorButton + Cura.ModeSelectorButton { - profileName: model.name + text: model.name icon: model.icon ? model.icon : "" custom_icon: model.custom_icon ? model.custom_icon : "" tooltipText: model.description ? model.description : "" diff --git a/resources/themes/cura-light/icons/default/Circle.svg b/resources/themes/cura-light/icons/default/Circle.svg new file mode 100644 index 0000000000..c69b5a4e31 --- /dev/null +++ b/resources/themes/cura-light/icons/default/Circle.svg @@ -0,0 +1,5 @@ + + + + diff --git a/resources/themes/cura-light/icons/default/Eraser.svg b/resources/themes/cura-light/icons/default/Eraser.svg new file mode 100644 index 0000000000..fbe5103993 --- /dev/null +++ b/resources/themes/cura-light/icons/default/Eraser.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/themes/cura-light/icons/default/Seam.svg b/resources/themes/cura-light/icons/default/Seam.svg new file mode 100644 index 0000000000..a9615832d6 --- /dev/null +++ b/resources/themes/cura-light/icons/default/Seam.svg @@ -0,0 +1,6 @@ + + + + diff --git a/resources/themes/cura-light/icons/low/CancelBadge.svg b/resources/themes/cura-light/icons/low/CancelBadge.svg new file mode 100644 index 0000000000..25c4198083 --- /dev/null +++ b/resources/themes/cura-light/icons/low/CancelBadge.svg @@ -0,0 +1,5 @@ + + + + diff --git a/resources/themes/cura-light/icons/low/CheckBadge.svg b/resources/themes/cura-light/icons/low/CheckBadge.svg new file mode 100644 index 0000000000..a10a92c6af --- /dev/null +++ b/resources/themes/cura-light/icons/low/CheckBadge.svg @@ -0,0 +1,5 @@ + + + + From 4aea5807cfe17dc8c0910be9d6e265e21b4d7644 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 4 Jul 2025 17:25:49 +0200 Subject: [PATCH 245/299] Fix SliceableObjectDecorator deep copy CURA-12543 --- cura/Scene/SliceableObjectDecorator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Scene/SliceableObjectDecorator.py b/cura/Scene/SliceableObjectDecorator.py index 4278705e2e..cc611b17af 100644 --- a/cura/Scene/SliceableObjectDecorator.py +++ b/cura/Scene/SliceableObjectDecorator.py @@ -60,6 +60,6 @@ class SliceableObjectDecorator(SceneNodeDecorator): def __deepcopy__(self, memo) -> "SliceableObjectDecorator": copied_decorator = SliceableObjectDecorator() - copied_decorator.setPaintTexture(copy.deepcopy(self.getPaintTexture())) + copied_decorator.setPaintTexture(copy.deepcopy(self.getPaintTexture(create_if_required = False))) copied_decorator.setTextureDataMapping(copy.deepcopy(self.getTextureDataMapping())) return copied_decorator From 2debe37e7236f42ab3457c94c7789103c70516de Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 7 Jul 2025 09:18:22 +0200 Subject: [PATCH 246/299] Use specific config folder for alpha versions CURA-12408 --- conandata.yml | 1 + conanfile.py | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/conandata.yml b/conandata.yml index 3181d601e5..b9a8b99eb1 100644 --- a/conandata.yml +++ b/conandata.yml @@ -1,4 +1,5 @@ version: "5.11.0-alpha.0" +commit: "unknown" requirements: - "cura_resources/5.11.0-alpha.0@ultimaker/testing" - "uranium/5.11.0-alpha.0@ultimaker/testing" diff --git a/conanfile.py b/conanfile.py index 28f45e7c24..652f151fc3 100644 --- a/conanfile.py +++ b/conanfile.py @@ -16,7 +16,7 @@ from conan import ConanFile from conan.tools.files import copy, rmdir, save, mkdir, rm, update_conandata from conan.tools.microsoft import unix_path from conan.tools.env import VirtualRunEnv, Environment, VirtualBuildEnv -from conan.tools.scm import Version +from conan.tools.scm import Version, Git from conan.errors import ConanInvalidConfiguration, ConanException required_conan_version = ">=2.7.0" # When changing the version, also change the one in conandata.yml/extra_dependencies @@ -329,10 +329,16 @@ class CuraConan(ConanFile): # If you want a specific Cura version to show up on the splash screen add the user configuration `user.cura:version=VERSION` # the global.conf, profile, package_info (of dependency) or via the cmd line `-c user.cura:version=VERSION` cura_version = Version(self.conf.get("user.cura:version", default = self.version, check_type = str)) - pre_tag = f"-{cura_version.pre}" if cura_version.pre else "" - build_tag = f"+{cura_version.build}" if cura_version.build else "" - internal_tag = f"+internal" if self.options.internal else "" - cura_version = f"{cura_version.major}.{cura_version.minor}.{cura_version.patch}{pre_tag}{build_tag}{internal_tag}" + extra_build_identifiers = [] + + if self.options.internal: + extra_build_identifiers.append("internal") + if cura_version.pre.startswith("alpha") and self.conan_data["commmit"] != "unknown": + extra_build_identifiers.append(self.conan_data["commmit"]) + + if extra_build_identifiers: + separator = "+" if not cura_version.build else "." + cura_version = Version(f"{cura_version}{separator}{".".join(extra_build_identifiers)}") self.output.info(f"Write CuraVersion.py to {self.recipe_folder}") @@ -340,7 +346,7 @@ class CuraConan(ConanFile): f.write(cura_version_py.render( cura_app_name = self.name, cura_app_display_name = self._app_name, - cura_version = cura_version, + cura_version = str(cura_version), cura_version_full = self.version, cura_build_type = "Enterprise" if self.options.enterprise else "", cura_debug_mode = self.options.cura_debug_mode, @@ -527,7 +533,7 @@ class CuraConan(ConanFile): )) def export(self): - update_conandata(self, {"version": self.version}) + update_conandata(self, {"version": self.version, "commit": Git(self).get_commit()}) def export_sources(self): copy(self, "*", os.path.join(self.recipe_folder, "plugins"), os.path.join(self.export_sources_folder, "plugins")) From 87eb3b47053959c4b70e004dc54afbe453cefaed Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 7 Jul 2025 09:25:39 +0200 Subject: [PATCH 247/299] Fix string comparison CURA-12408 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 652f151fc3..82f039f9b9 100644 --- a/conanfile.py +++ b/conanfile.py @@ -333,7 +333,7 @@ class CuraConan(ConanFile): if self.options.internal: extra_build_identifiers.append("internal") - if cura_version.pre.startswith("alpha") and self.conan_data["commmit"] != "unknown": + if str(cura_version.pre).startswith("alpha") and self.conan_data["commmit"] != "unknown": extra_build_identifiers.append(self.conan_data["commmit"]) if extra_build_identifiers: From b617f2c27e60e7b33f0fc307cb1b89290b2cd975 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 7 Jul 2025 09:29:30 +0200 Subject: [PATCH 248/299] Fix commit key (too many MMMMMs) CURA-12408 --- conanfile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conanfile.py b/conanfile.py index 82f039f9b9..362861ae41 100644 --- a/conanfile.py +++ b/conanfile.py @@ -333,8 +333,8 @@ class CuraConan(ConanFile): if self.options.internal: extra_build_identifiers.append("internal") - if str(cura_version.pre).startswith("alpha") and self.conan_data["commmit"] != "unknown": - extra_build_identifiers.append(self.conan_data["commmit"]) + if str(cura_version.pre).startswith("alpha") and self.conan_data["commit"] != "unknown": + extra_build_identifiers.append(self.conan_data["commit"]) if extra_build_identifiers: separator = "+" if not cura_version.build else "." From 581d8e3a1299a0b75ba61332c019649c9e07fd0c Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 7 Jul 2025 09:55:37 +0200 Subject: [PATCH 249/299] Use shorter commit reference CURA-12408 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 362861ae41..89b2da35d6 100644 --- a/conanfile.py +++ b/conanfile.py @@ -334,7 +334,7 @@ class CuraConan(ConanFile): if self.options.internal: extra_build_identifiers.append("internal") if str(cura_version.pre).startswith("alpha") and self.conan_data["commit"] != "unknown": - extra_build_identifiers.append(self.conan_data["commit"]) + extra_build_identifiers.append(self.conan_data["commit"][:6]) if extra_build_identifiers: separator = "+" if not cura_version.build else "." From 55ee4ec6e1c32f57e64f719e630cefa86e01559a Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 8 Jul 2025 15:47:46 +0200 Subject: [PATCH 250/299] Calculate and apply UV coordinates CURA-12528 --- cura/Scene/SliceableObjectDecorator.py | 22 ++++++++++------------ plugins/3MFReader/ThreeMFReader.py | 2 -- plugins/PaintTool/PaintTool.qml | 14 ++++++++++---- plugins/PaintTool/PaintView.py | 8 ++++++++ 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/cura/Scene/SliceableObjectDecorator.py b/cura/Scene/SliceableObjectDecorator.py index cc611b17af..7ee77795e7 100644 --- a/cura/Scene/SliceableObjectDecorator.py +++ b/cura/Scene/SliceableObjectDecorator.py @@ -12,10 +12,6 @@ from UM.View.GL.OpenGL import OpenGL from UM.View.GL.Texture import Texture -# FIXME: When the texture UV-unwrapping is done, these two values will need to be set to a proper value (suggest 4096 for both). -TEXTURE_WIDTH = 512 -TEXTURE_HEIGHT = 512 - class SliceableObjectDecorator(SceneNodeDecorator): def __init__(self) -> None: super().__init__() @@ -25,15 +21,10 @@ class SliceableObjectDecorator(SceneNodeDecorator): def isSliceable(self) -> bool: return True - def getPaintTexture(self, create_if_required: bool = True) -> Optional[UM.View.GL.Texture.Texture]: - if self._paint_texture is None and create_if_required: - self._paint_texture = OpenGL.getInstance().createTexture(TEXTURE_WIDTH, TEXTURE_HEIGHT) - image = QImage(TEXTURE_WIDTH, TEXTURE_HEIGHT, QImage.Format.Format_RGB32) - image.fill(0) - self._paint_texture.setImage(image) + def getPaintTexture(self) -> Optional[Texture]: return self._paint_texture - def setPaintTexture(self, texture: UM.View.GL.Texture) -> None: + def setPaintTexture(self, texture: Texture) -> None: self._paint_texture = texture def getTextureDataMapping(self) -> Dict[str, tuple[int, int]]: @@ -42,6 +33,13 @@ class SliceableObjectDecorator(SceneNodeDecorator): def setTextureDataMapping(self, mapping: Dict[str, tuple[int, int]]) -> None: self._texture_data_mapping = mapping + def prepareTexture(self, width: int, height: int) -> None: + if self._paint_texture is None: + self._paint_texture = OpenGL.getInstance().createTexture(width, height) + image = QImage(width, height, QImage.Format.Format_RGB32) + image.fill(0) + self._paint_texture.setImage(image) + def packTexture(self) -> Optional[bytearray]: if self._paint_texture is None: return None @@ -60,6 +58,6 @@ class SliceableObjectDecorator(SceneNodeDecorator): def __deepcopy__(self, memo) -> "SliceableObjectDecorator": copied_decorator = SliceableObjectDecorator() - copied_decorator.setPaintTexture(copy.deepcopy(self.getPaintTexture(create_if_required = False))) + copied_decorator.setPaintTexture(copy.deepcopy(self.getPaintTexture())) copied_decorator.setTextureDataMapping(copy.deepcopy(self.getTextureDataMapping())) return copied_decorator diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 730acf4af6..09143dde64 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -153,8 +153,6 @@ class ThreeMFReader(MeshReader): # It is only set for the root node of the 3mf file mesh_builder.setFileName(file_name) - mesh_builder.unwrapNewUvs() - mesh_data = mesh_builder.build() if len(mesh_data.getVertices()): diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index 4cbe9d4ade..ef1ac35628 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -164,17 +164,22 @@ Item width: parent.width indicatorVisible: false - from: 1 - to: 40 - value: 10 + from: 10 + to: 1000 + value: 200 onPressedChanged: function(pressed) { if(! pressed) { - UM.Controller.triggerActionWithData("setBrushSize", shapeSizeSlider.value) + setBrushSize() } } + + function setBrushSize() + { + UM.Controller.triggerActionWithData("setBrushSize", shapeSizeSlider.value) + } } //Line between the sections. @@ -233,5 +238,6 @@ Item rowPaintMode.children[0].setMode() rowBrushColor.children[1].setColor() rowBrushShape.children[1].setShape() + shapeSizeSlider.setBrushSize() } } diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 22eb8c55f6..2b0181be70 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -147,6 +147,14 @@ class PaintView(View): paint_data_mapping[paint_type] = new_mapping node.callDecoration("setTextureDataMapping", paint_data_mapping) + mesh = node.getMeshData() + if not mesh.hasUVCoordinates(): + texture_width, texture_height = mesh.calculateUnwrappedUVCoordinates(4096) + node.callDecoration("prepareTexture", texture_width, texture_height) + if hasattr(mesh, OpenGL.VertexBufferProperty): + # Force clear OpenGL buffer so that new UV coordinates will be sent + delattr(mesh, OpenGL.VertexBufferProperty) + self._current_paint_type = paint_type self._current_bits_ranges = paint_data_mapping[paint_type] From 20a2664294d0028ba4924bfe02186fbbacd1f18d Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 14 Jul 2025 13:36:48 +0200 Subject: [PATCH 251/299] Remove the desired texture definition CURA-12528 --- plugins/PaintTool/PaintView.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 2b0181be70..c2562fa36a 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -149,7 +149,7 @@ class PaintView(View): mesh = node.getMeshData() if not mesh.hasUVCoordinates(): - texture_width, texture_height = mesh.calculateUnwrappedUVCoordinates(4096) + texture_width, texture_height = mesh.calculateUnwrappedUVCoordinates() node.callDecoration("prepareTexture", texture_width, texture_height) if hasattr(mesh, OpenGL.VertexBufferProperty): # Force clear OpenGL buffer so that new UV coordinates will be sent From b3552d8b20c66c7d0b51c5f2ca8567a8e171fd53 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 16 Jul 2025 11:27:49 +0200 Subject: [PATCH 252/299] Basic warning on unused extruder. Since the bed-temp (for example) might be unfluenced by unused but (probably accidentally) enabled extruders, we want to be able to warn the user of such. part of CURA-12622 --- .../CuraEngineBackend/CuraEngineBackend.py | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index e3e15f5381..eb65cafb68 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. import argparse #To run the engine in debug mode if the front-end is in debug mode. +from cmath import isnan from collections import defaultdict import os from PyQt6.QtCore import QObject, QTimer, QUrl, pyqtSlot @@ -960,8 +961,26 @@ class CuraEngineBackend(QObject, Backend): """ material_amounts = [] + no_use_warnings = [] for index in range(message.repeatedMessageCount("materialEstimates")): - material_amounts.append(message.getRepeatedMessage("materialEstimates", index).material_amount) + material_use_for_tool = message.getRepeatedMessage("materialEstimates", index).material_amount + if isnan(material_use_for_tool): + material_amounts.append(0.0) + if self._global_container_stack.extruderList[int(index)].isEnabled: + no_use_warnings.append(index) + else: + material_amounts.append(material_use_for_tool) + + if no_use_warnings: + extruder_names = [self._global_container_stack.extruderList[int(idx)].definition.getName() for idx in no_use_warnings] + Message( + text=catalog.i18nc("@message", "At least one extruder that wasn't disabled, remains unused in this print (preview). " + f"Unused extruders: '{", ".join(extruder_names)}'. This can sometimes become a problem " + "(for example when the bed-temperature is adjusted by the material-profile present in the unused extruder). " + "It therefore might be desirable to disable these unused extruders manually, depending on the situation. "), + title=catalog.i18nc("@message:title", "Unused Non-Disabled Extruder"), + message_type=Message.MessageType.WARNING + ).show() times = self._parseMessagePrintTimes(message) self.printDurationMessage.emit(self._start_slice_job_build_plate, times, material_amounts) From b1676c66fdc7ceea2a82e964219c1059fdced9bf Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 17 Jul 2025 09:15:00 +0200 Subject: [PATCH 253/299] Add run-name Identify the build's origin by looking at the workflow --- .github/workflows/find-packages.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index 81f68857e5..788ec4021d 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -1,4 +1,5 @@ name: Find packages for Jira ticket and create installers +run-name: ${{ inputs.jira_ticket_number }} by @${{ github.actor }} on: workflow_dispatch: From c7b86ae1c43480c946fe4bd2885ec0e2db5f2d7f Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 21 Jul 2025 12:00:05 +0200 Subject: [PATCH 254/299] Refine automagic installers workflow --- .github/workflows/find-packages.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/find-packages.yml b/.github/workflows/find-packages.yml index 788ec4021d..93a5bdde2b 100644 --- a/.github/workflows/find-packages.yml +++ b/.github/workflows/find-packages.yml @@ -1,15 +1,16 @@ -name: Find packages for Jira ticket and create installers +name: All installers (based on Jira ticket) run-name: ${{ inputs.jira_ticket_number }} by @${{ github.actor }} on: workflow_dispatch: inputs: jira_ticket_number: - description: 'Jira ticket number for Conan package discovery (e.g., cura_12345)' + description: 'Jira ticket number (e.g. CURA-15432 or cura_12345)' required: true type: string start_builds: - default: false + description: 'Start installers build based on found packages' + default: true required: false type: boolean conan_args: From 5fbf6af420e4978aff66a9661a3b9f84e9422078 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 22 Jul 2025 15:48:33 +0200 Subject: [PATCH 255/299] Do not use default xz compression Because it is not supported by the appimage toolkit --- packaging/AppImage-builder/AppImageBuilder.yml.jinja | 1 + 1 file changed, 1 insertion(+) diff --git a/packaging/AppImage-builder/AppImageBuilder.yml.jinja b/packaging/AppImage-builder/AppImageBuilder.yml.jinja index c6e7a7123a..fe191fdc54 100644 --- a/packaging/AppImage-builder/AppImageBuilder.yml.jinja +++ b/packaging/AppImage-builder/AppImageBuilder.yml.jinja @@ -77,3 +77,4 @@ AppImage: arch: {{ arch }} file_name: {{ file_name }} update-information: guess + comp: zlib From 51ff682556498d754526676c6252d03db0a84065 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 22 Jul 2025 15:59:13 +0200 Subject: [PATCH 256/299] Give the proper compressor name --- packaging/AppImage-builder/AppImageBuilder.yml.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/AppImage-builder/AppImageBuilder.yml.jinja b/packaging/AppImage-builder/AppImageBuilder.yml.jinja index fe191fdc54..29144b0e77 100644 --- a/packaging/AppImage-builder/AppImageBuilder.yml.jinja +++ b/packaging/AppImage-builder/AppImageBuilder.yml.jinja @@ -77,4 +77,4 @@ AppImage: arch: {{ arch }} file_name: {{ file_name }} update-information: guess - comp: zlib + comp: gzip From d61c87b9fe5012007ab99ba5ae2d1a6dba437426 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 22 Jul 2025 16:13:21 +0200 Subject: [PATCH 257/299] Try more efficient compression ratio --- packaging/AppImage-builder/AppImageBuilder.yml.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/AppImage-builder/AppImageBuilder.yml.jinja b/packaging/AppImage-builder/AppImageBuilder.yml.jinja index 29144b0e77..601189bb28 100644 --- a/packaging/AppImage-builder/AppImageBuilder.yml.jinja +++ b/packaging/AppImage-builder/AppImageBuilder.yml.jinja @@ -77,4 +77,4 @@ AppImage: arch: {{ arch }} file_name: {{ file_name }} update-information: guess - comp: gzip + comp: lzma From ef116edafe38a9d079cc33d447d8dccaa928ba24 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 22 Jul 2025 16:35:34 +0200 Subject: [PATCH 258/299] Revert "Try more efficient compression ratio" This reverts commit d61c87b9fe5012007ab99ba5ae2d1a6dba437426. --- packaging/AppImage-builder/AppImageBuilder.yml.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/AppImage-builder/AppImageBuilder.yml.jinja b/packaging/AppImage-builder/AppImageBuilder.yml.jinja index 601189bb28..29144b0e77 100644 --- a/packaging/AppImage-builder/AppImageBuilder.yml.jinja +++ b/packaging/AppImage-builder/AppImageBuilder.yml.jinja @@ -77,4 +77,4 @@ AppImage: arch: {{ arch }} file_name: {{ file_name }} update-information: guess - comp: lzma + comp: gzip From a39f6c94fa0f139ecb5fa50e1d2e9bee3d3865e0 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 24 Jul 2025 10:50:31 +0200 Subject: [PATCH 259/299] Make the warning message more concise CURA-12622 The purpose being to make the message as short as possible so that people are not too much discouraged to read it --- plugins/CuraEngineBackend/CuraEngineBackend.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index eb65cafb68..bea5de1bce 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -973,12 +973,13 @@ class CuraEngineBackend(QObject, Backend): if no_use_warnings: extruder_names = [self._global_container_stack.extruderList[int(idx)].definition.getName() for idx in no_use_warnings] + unused_extruders = [f"

  • {extruder_name}
  • " for extruder_name in extruder_names] Message( - text=catalog.i18nc("@message", "At least one extruder that wasn't disabled, remains unused in this print (preview). " - f"Unused extruders: '{", ".join(extruder_names)}'. This can sometimes become a problem " - "(for example when the bed-temperature is adjusted by the material-profile present in the unused extruder). " - "It therefore might be desirable to disable these unused extruders manually, depending on the situation. "), - title=catalog.i18nc("@message:title", "Unused Non-Disabled Extruder"), + text=catalog.i18nc("@message", "At least one extruder remains unused in this print:" + f"
      {"".join(unused_extruders)}

    This can sometimes become a problem, " + "for example when the bed-temperature is adjusted by the material-profile present in the unused extruder. " + "It might be desirable to disable these unused extruders."), + title=catalog.i18nc("@message:title", "Unused Extruder"), message_type=Message.MessageType.WARNING ).show() From e8423755a48f628b841f9701300adf24716e33d3 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 24 Jul 2025 11:14:36 +0200 Subject: [PATCH 260/299] Add button to auto-disable unused extruders CURA-12622 --- .../CuraEngineBackend/CuraEngineBackend.py | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index bea5de1bce..f8736d69b8 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -159,6 +159,7 @@ class CuraEngineBackend(QObject, Backend): self._backend_log_max_lines: int = 20000 # Maximum number of lines to buffer self._error_message: Optional[Message] = None # Pop-up message that shows errors. + self._unused_extruders: list[int] = [] # Extruder numbers of found unused extruders # Count number of objects to see if there is something changed self._last_num_objects: Dict[int, int] = defaultdict(int) @@ -961,31 +962,44 @@ class CuraEngineBackend(QObject, Backend): """ material_amounts = [] - no_use_warnings = [] + self._unused_extruders = [] for index in range(message.repeatedMessageCount("materialEstimates")): material_use_for_tool = message.getRepeatedMessage("materialEstimates", index).material_amount if isnan(material_use_for_tool): material_amounts.append(0.0) if self._global_container_stack.extruderList[int(index)].isEnabled: - no_use_warnings.append(index) + self._unused_extruders.append(index) else: material_amounts.append(material_use_for_tool) - if no_use_warnings: - extruder_names = [self._global_container_stack.extruderList[int(idx)].definition.getName() for idx in no_use_warnings] + if self._unused_extruders: + extruder_names = [self._global_container_stack.extruderList[int(idx)].definition.getName() for idx in self._unused_extruders] unused_extruders = [f"
  • {extruder_name}
  • " for extruder_name in extruder_names] - Message( + warning_message = Message( text=catalog.i18nc("@message", "At least one extruder remains unused in this print:" f"
      {"".join(unused_extruders)}

    This can sometimes become a problem, " - "for example when the bed-temperature is adjusted by the material-profile present in the unused extruder. " + "for example when the bed temperature is adjusted for the material present in the unused extruder. " "It might be desirable to disable these unused extruders."), - title=catalog.i18nc("@message:title", "Unused Extruder"), + title=catalog.i18nc("@message:title", "Unused Extruder(s)"), message_type=Message.MessageType.WARNING - ).show() + ) + warning_message.addAction("disable_extruders", + name=catalog.i18nc("@button", "Disable unused extruder(s)"), + icon="", + description=catalog.i18nc("@label", "Automatically disable the unused extruder(s)") + ) + warning_message.actionTriggered.connect(self._onMessageActionTriggered) + warning_message.show() times = self._parseMessagePrintTimes(message) self.printDurationMessage.emit(self._start_slice_job_build_plate, times, material_amounts) + def _onMessageActionTriggered(self, message: Message, message_action: str) -> None: + if message_action == "disable_extruders": + message.hide() + for unused_extruder in self._unused_extruders: + CuraApplication.getInstance().getMachineManager().setExtruderEnabled(unused_extruder, False) + def _parseMessagePrintTimes(self, message: Arcus.PythonMessage) -> Dict[str, float]: """Called for parsing message to retrieve estimated time per feature From 890543b7de78a5a6f879c14d159b77482b287d13 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 25 Jul 2025 11:02:37 +0200 Subject: [PATCH 261/299] Change Marketplace dialog creation and destruction CURA-11810 This will hopefully fix some display issues we have, especially on Mac platforms --- plugins/Marketplace/Marketplace.py | 29 +- .../Marketplace/resources/qml/Marketplace.qml | 440 +++++++++--------- 2 files changed, 229 insertions(+), 240 deletions(-) diff --git a/plugins/Marketplace/Marketplace.py b/plugins/Marketplace/Marketplace.py index 86910f8f4a..fc287b5877 100644 --- a/plugins/Marketplace/Marketplace.py +++ b/plugins/Marketplace/Marketplace.py @@ -21,7 +21,6 @@ class Marketplace(Extension, QObject): def __init__(self, parent: Optional[QObject] = None) -> None: QObject.__init__(self, parent) Extension.__init__(self) - self._window: Optional["QObject"] = None # If the window has been loaded yet, it'll be cached in here. self._package_manager = CuraApplication.getInstance().getPackageManager() self._material_package_list: Optional[RemotePackageList] = None @@ -79,20 +78,17 @@ class Marketplace(Extension, QObject): If the window hadn't been loaded yet into Qt, it will be created lazily. """ - if self._window is None: - plugin_registry = PluginRegistry.getInstance() - plugin_registry.pluginsEnabledOrDisabledChanged.connect(self.checkIfRestartNeeded) - plugin_path = plugin_registry.getPluginPath(self.getPluginId()) - if plugin_path is None: - plugin_path = os.path.dirname(__file__) - path = os.path.join(plugin_path, "resources", "qml", "Marketplace.qml") - self._window = CuraApplication.getInstance().createQmlComponent(path, {"manager": self}) - if self._window is None: # Still None? Failed to load the QML then. - return - if not self._window.isVisible(): - self.setTabShown(0) - self._window.show() - self._window.requestActivate() # Bring window into focus, if it was already open in the background. + + plugin_registry = PluginRegistry.getInstance() + plugin_registry.pluginsEnabledOrDisabledChanged.connect(self.checkIfRestartNeeded) + plugin_path = plugin_registry.getPluginPath(self.getPluginId()) + if plugin_path is None: + plugin_path = os.path.dirname(__file__) + path = os.path.join(plugin_path, "resources", "qml", "Marketplace.qml") + window = CuraApplication.getInstance().createQmlSubWindow(path, {"manager": self}) + + if window is not None: # Still None? Failed to load the QML then. + window.show() @pyqtSlot() def setVisibleTabToMaterials(self) -> None: @@ -103,9 +99,6 @@ class Marketplace(Extension, QObject): self.setTabShown(1) def checkIfRestartNeeded(self) -> None: - if self._window is None: - return - if self._package_manager.hasPackagesToRemoveOrInstall or \ PluginRegistry.getInstance().getCurrentSessionActivationChangedPlugins(): self._restart_needed = True diff --git a/plugins/Marketplace/resources/qml/Marketplace.qml b/plugins/Marketplace/resources/qml/Marketplace.qml index 8028b89e02..c858297ac9 100644 --- a/plugins/Marketplace/resources/qml/Marketplace.qml +++ b/plugins/Marketplace/resources/qml/Marketplace.qml @@ -9,7 +9,7 @@ import QtQuick.Window 2.2 import UM 1.5 as UM import Cura 1.6 as Cura -Window +UM.Dialog { id: marketplaceDialog property variant catalog: UM.I18nCatalog { name: "cura" } @@ -25,293 +25,289 @@ Window width: minimumWidth height: minimumHeight - onVisibleChanged: - { - while(contextStack.depth > 1) - { - contextStack.pop(); //Do NOT use the StackView.Immediate transition here, since it causes the window to stay empty. Seemingly a Qt bug: https://bugreports.qt.io/browse/QTBUG-60670? - } - } - - Connections - { - target: Cura.API.account - function onLoginStateChanged() - { - close(); - } - } - title: "Marketplace" //Seen by Ultimaker as a brand name, so this doesn't get translated. - modality: Qt.NonModal // Background color Rectangle { anchors.fill: parent color: UM.Theme.getColor("main_background") - } - //The Marketplace can have a page in front of everything with package details. The stack view controls its visibility. - StackView - { - id: contextStack - anchors.fill: parent - initialItem: packageBrowse - - ColumnLayout + //The Marketplace can have a page in front of everything with package details. The stack view controls its visibility. + StackView { - id: packageBrowse + id: contextStack + anchors.fill: parent - spacing: UM.Theme.getSize("narrow_margin").height + initialItem: packageBrowse - // Page title. - Item + ColumnLayout { - Layout.preferredWidth: parent.width - Layout.preferredHeight: childrenRect.height + UM.Theme.getSize("default_margin").height + id: packageBrowse - UM.Label + spacing: UM.Theme.getSize("narrow_margin").height + + // Page title. + Item { - id: pageTitle - anchors - { - left: parent.left - leftMargin: UM.Theme.getSize("default_margin").width - right: parent.right - rightMargin: UM.Theme.getSize("default_margin").width - bottom: parent.bottom - } + Layout.preferredWidth: parent.width + Layout.preferredHeight: childrenRect.height + UM.Theme.getSize("default_margin").height - font: UM.Theme.getFont("large") - text: content.item ? content.item.pageTitle: catalog.i18nc("@title", "Loading...") + UM.Label + { + id: pageTitle + anchors + { + left: parent.left + leftMargin: UM.Theme.getSize("default_margin").width + right: parent.right + rightMargin: UM.Theme.getSize("default_margin").width + bottom: parent.bottom + } + + font: UM.Theme.getFont("large") + text: content.item ? content.item.pageTitle : catalog.i18nc("@title", "Loading...") + } } - } - OnboardBanner - { - id: onBoardBanner - visible: content.item && content.item.bannerVisible - text: content.item && content.item.bannerText - icon: content.item && content.item.bannerIcon - onRemove: content.item && content.item.onRemoveBanner - readMoreUrl: content.item && content.item.bannerReadMoreUrl - - Layout.fillWidth: true - Layout.leftMargin: UM.Theme.getSize("default_margin").width - Layout.rightMargin: UM.Theme.getSize("default_margin").width - } - - // Search & Top-Level Tabs - Item - { - id: searchHeader - implicitHeight: childrenRect.height - implicitWidth: parent.width - 2 * UM.Theme.getSize("default_margin").width - Layout.alignment: Qt.AlignHCenter - RowLayout + OnboardBanner { - width: parent.width - height: UM.Theme.getSize("button_icon").height + UM.Theme.getSize("default_margin").height - spacing: UM.Theme.getSize("thin_margin").width + id: onBoardBanner + visible: content.item && content.item.bannerVisible + text: content.item && content.item.bannerText + icon: content.item && content.item.bannerIcon + onRemove: content.item && content.item.onRemoveBanner + readMoreUrl: content.item && content.item.bannerReadMoreUrl - Cura.SearchBar + Layout.fillWidth: true + Layout.leftMargin: UM.Theme.getSize("default_margin").width + Layout.rightMargin: UM.Theme.getSize("default_margin").width + } + + // Search & Top-Level Tabs + Item + { + id: searchHeader + implicitHeight: childrenRect.height + implicitWidth: parent.width - 2 * UM.Theme.getSize("default_margin").width + Layout.alignment: Qt.AlignHCenter + RowLayout { - id: searchBar - implicitHeight: UM.Theme.getSize("button_icon").height - Layout.fillWidth: true - onTextEdited: searchStringChanged(text) - } + width: parent.width + height: UM.Theme.getSize("button_icon").height + UM.Theme.getSize("default_margin").height + spacing: UM.Theme.getSize("thin_margin").width - // Page selection. - TabBar - { - id: pageSelectionTabBar - Layout.alignment: Qt.AlignRight - height: UM.Theme.getSize("button_icon").height - spacing: 0 - background: Rectangle { color: "transparent" } - currentIndex: manager.tabShown - - onCurrentIndexChanged: + Cura.SearchBar { - manager.tabShown = currentIndex - searchBar.text = ""; - searchBar.visible = currentItem.hasSearch; - content.source = currentItem.sourcePage; + id: searchBar + implicitHeight: UM.Theme.getSize("button_icon").height + Layout.fillWidth: true + onTextEdited: searchStringChanged(text) } - PackageTypeTab + // Page selection. + TabBar { - id: pluginTabText - width: implicitWidth - text: catalog.i18nc("@button", "Plugins") - property string sourcePage: "Plugins.qml" - property bool hasSearch: true - } - PackageTypeTab - { - id: materialsTabText - width: implicitWidth - text: catalog.i18nc("@button", "Materials") - property string sourcePage: "Materials.qml" - property bool hasSearch: true - } - ManagePackagesButton - { - property string sourcePage: "ManagedPackages.qml" - property bool hasSearch: false + id: pageSelectionTabBar + Layout.alignment: Qt.AlignRight + height: UM.Theme.getSize("button_icon").height + spacing: 0 + background: Rectangle { + color: "transparent" + } + currentIndex: manager.tabShown - Cura.NotificationIcon + onCurrentIndexChanged: { - anchors - { - horizontalCenter: parent.right - verticalCenter: parent.top - } - visible: CuraApplication.getPackageManager().packagesWithUpdate.length > 0 + manager.tabShown = currentIndex + searchBar.text = ""; + searchBar.visible = currentItem.hasSearch; + content.source = currentItem.sourcePage; + } - labelText: + PackageTypeTab + { + id: pluginTabText + width: implicitWidth + text: catalog.i18nc("@button", "Plugins") + property string sourcePage: "Plugins.qml" + property bool hasSearch: true + } + PackageTypeTab + { + id: materialsTabText + width: implicitWidth + text: catalog.i18nc("@button", "Materials") + property string sourcePage: "Materials.qml" + property bool hasSearch: true + } + ManagePackagesButton + { + property string sourcePage: "ManagedPackages.qml" + property bool hasSearch: false + + Cura.NotificationIcon { - const itemCount = CuraApplication.getPackageManager().packagesWithUpdate.length - return itemCount > 9 ? "9+" : itemCount + anchors + { + horizontalCenter: parent.right + verticalCenter: parent.top + } + visible: CuraApplication.getPackageManager().packagesWithUpdate.length > 0 + + labelText: + { + const itemCount = CuraApplication.getPackageManager().packagesWithUpdate.length + return itemCount > 9 ? "9+" : itemCount + } } } } } } - } - FontMetrics - { - id: fontMetrics - font: UM.Theme.getFont("default") - } + FontMetrics + { + id: fontMetrics + font: UM.Theme.getFont("default") + } - Cura.TertiaryButton - { - text: catalog.i18nc("@info", "Search in the browser") - iconSource: UM.Theme.getIcon("LinkExternal") - visible: pageSelectionTabBar.currentItem.hasSearch && searchHeader.visible - isIconOnRightSide: true - height: fontMetrics.height - textFont: fontMetrics.font - textColor: UM.Theme.getColor("text") + Cura.TertiaryButton + { + text: catalog.i18nc("@info", "Search in the browser") + iconSource: UM.Theme.getIcon("LinkExternal") + visible: pageSelectionTabBar.currentItem.hasSearch && searchHeader.visible + isIconOnRightSide: true + height: fontMetrics.height + textFont: fontMetrics.font + textColor: UM.Theme.getColor("text") - onClicked: content.item && Qt.openUrlExternally(content.item.searchInBrowserUrl) - } - - // Page contents. - Rectangle - { - Layout.preferredWidth: parent.width - Layout.fillHeight: true - color: UM.Theme.getColor("detail_background") + onClicked: content.item && Qt.openUrlExternally(content.item.searchInBrowserUrl) + } // Page contents. - Loader + Rectangle { - id: content - anchors.fill: parent - anchors.margins: UM.Theme.getSize("default_margin").width - source: "Plugins.qml" + Layout.preferredWidth: parent.width + Layout.fillHeight: true + color: UM.Theme.getColor("detail_background") - Connections + // Page contents. + Loader { - target: content - function onLoaded() + id: content + anchors.fill: parent + anchors.margins: UM.Theme.getSize("default_margin").width + source: "Plugins.qml" + + Connections { - pageTitle.text = content.item.pageTitle - searchStringChanged.connect(handleSearchStringChanged) - } - function handleSearchStringChanged(new_search) - { - content.item.model.searchString = new_search + target: content + + function onLoaded() + { + pageTitle.text = content.item.pageTitle + searchStringChanged.connect(handleSearchStringChanged) + } + + function handleSearchStringChanged(new_search) + { + content.item.model.searchString = new_search + } } } } } } - } - Rectangle - { - height: quitButton.height + 2 * UM.Theme.getSize("default_margin").width - color: UM.Theme.getColor("primary") - visible: manager.showRestartNotification - anchors - { - left: parent.left - right: parent.right - bottom: parent.bottom - } - - RowLayout + Rectangle { + height: quitButton.height + 2 * UM.Theme.getSize("default_margin").width + color: UM.Theme.getColor("primary") + visible: manager.showRestartNotification anchors { left: parent.left right: parent.right - verticalCenter: parent.verticalCenter - margins: UM.Theme.getSize("default_margin").width + bottom: parent.bottom } - spacing: UM.Theme.getSize("default_margin").width - UM.ColorImage - { - id: bannerIcon - source: UM.Theme.getIcon("Plugin") - color: UM.Theme.getColor("primary_button_text") - implicitWidth: UM.Theme.getSize("banner_icon_size").width - implicitHeight: UM.Theme.getSize("banner_icon_size").height - } - Text + RowLayout { - color: UM.Theme.getColor("primary_button_text") - text: catalog.i18nc("@button", "In order to use the package you will need to restart Cura") - font: UM.Theme.getFont("default") - renderType: Text.NativeRendering - Layout.fillWidth: true - } - Cura.SecondaryButton - { - id: quitButton - text: catalog.i18nc("@info:button, %1 is the application name", "Quit %1").arg(CuraApplication.applicationDisplayName) - onClicked: + anchors { - marketplaceDialog.hide(); - CuraApplication.checkAndExitApplication(); + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + margins: UM.Theme.getSize("default_margin").width + } + spacing: UM.Theme.getSize("default_margin").width + UM.ColorImage + { + id: bannerIcon + source: UM.Theme.getIcon("Plugin") + + color: UM.Theme.getColor("primary_button_text") + implicitWidth: UM.Theme.getSize("banner_icon_size").width + implicitHeight: UM.Theme.getSize("banner_icon_size").height + } + Text + { + color: UM.Theme.getColor("primary_button_text") + text: catalog.i18nc("@button", "In order to use the package you will need to restart Cura") + font: UM.Theme.getFont("default") + renderType: Text.NativeRendering + Layout.fillWidth: true + } + Cura.SecondaryButton + { + id: quitButton + text: catalog.i18nc("@info:button, %1 is the application name", "Quit %1").arg(CuraApplication.applicationDisplayName) + onClicked: + { + marketplaceDialog.hide(); + CuraApplication.checkAndExitApplication(); + } } } } - } - Rectangle - { - color: UM.Theme.getColor("main_background") - anchors.fill: parent - visible: !Cura.API.account.isLoggedIn && CuraApplication.isEnterprise - - UM.Label + Rectangle { - id: signInLabel - anchors.centerIn: parent - width: Math.round(UM.Theme.getSize("modal_window_minimum").width / 2.5) - text: catalog.i18nc("@description","Please sign in to get verified plugins and materials for UltiMaker Cura Enterprise") - horizontalAlignment: Text.AlignHCenter + color: UM.Theme.getColor("main_background") + anchors.fill: parent + visible: !Cura.API.account.isLoggedIn && CuraApplication.isEnterprise + + UM.Label + { + id: signInLabel + anchors.centerIn: parent + width: Math.round(UM.Theme.getSize("modal_window_minimum").width / 2.5) + text: catalog.i18nc("@description", "Please sign in to get verified plugins and materials for UltiMaker Cura Enterprise") + horizontalAlignment: Text.AlignHCenter + } + + Cura.PrimaryButton + { + id: loginButton + width: UM.Theme.getSize("account_button").width + height: UM.Theme.getSize("account_button").height + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: signInLabel.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height * 2 + text: catalog.i18nc("@button", "Sign in") + fixedWidthMode: true + onClicked: Cura.API.account.login() + } } - Cura.PrimaryButton + Connections { - id: loginButton - width: UM.Theme.getSize("account_button").width - height: UM.Theme.getSize("account_button").height - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: signInLabel.bottom - anchors.topMargin: UM.Theme.getSize("default_margin").height * 2 - text: catalog.i18nc("@button", "Sign in") - fixedWidthMode: true - onClicked: Cura.API.account.login() + target: Cura.API.account + function onLoginStateChanged() + { + reject(); + } } } } From 376d18c7ee7d7abdf151b75ee79213d51c0d679f Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 25 Jul 2025 13:21:06 +0200 Subject: [PATCH 262/299] Change Preferences dialog creation and destruction CURA-11810 --- resources/qml/Cura.qml | 55 +++---- .../qml/Preferences/PreferencesDialog.qml | 136 ++++++++++++++++++ resources/qml/qmldir | 4 + 3 files changed, 161 insertions(+), 34 deletions(-) create mode 100644 resources/qml/Preferences/PreferencesDialog.qml diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 77efc45fe8..bc5cc6a044 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -456,45 +456,32 @@ UM.MainWindow } } - UM.PreferencesDialog + Component { - id: preferences - - Component.onCompleted: + id: preferencesDialogComponent + Cura.PreferencesDialog { - //; Remove & re-add the general page as we want to use our own instead of uranium standard. - removePage(0); - insertPage(0, catalog.i18nc("@title:tab","General"), Qt.resolvedUrl("Preferences/GeneralPage.qml")); - - removePage(1); - insertPage(1, catalog.i18nc("@title:tab","Settings"), Qt.resolvedUrl("Preferences/SettingVisibilityPage.qml")); - - insertPage(2, catalog.i18nc("@title:tab", "Printers"), Qt.resolvedUrl("Preferences/MachinesPage.qml")); - - insertPage(3, catalog.i18nc("@title:tab", "Materials"), Qt.resolvedUrl("Preferences/Materials/MaterialsPage.qml")); - - insertPage(4, catalog.i18nc("@title:tab", "Profiles"), Qt.resolvedUrl("Preferences/ProfilesPage.qml")); - currentPage = 0; + selfDestroy: true } + } - onVisibleChanged: - { - // When the dialog closes, switch to the General page. - // This prevents us from having a heavy page like Setting Visibility active in the background. - setPage(0); - } + function showPreferencesDialog() + { + var dialog = preferencesDialogComponent.createObject(base) + dialog.show() + return dialog } Connections { target: Cura.Actions.preferences - function onTriggered() { preferences.visible = true } + function onTriggered() { showPreferencesDialog() } } Connections { target: CuraApplication - function onShowPreferencesWindow() { preferences.visible = true } + function onShowPreferencesWindow() { showPreferencesDialog() } } Connections @@ -511,8 +498,8 @@ UM.MainWindow target: Cura.Actions.configureMachines function onTriggered() { - preferences.visible = true; - preferences.setPage(2); + var dialog = showPreferencesDialog() + dialog.currentPage = 2; } } @@ -521,8 +508,8 @@ UM.MainWindow target: Cura.Actions.manageProfiles function onTriggered() { - preferences.visible = true; - preferences.setPage(4); + var dialog = showPreferencesDialog() + dialog.currentPage = 4; } } @@ -531,8 +518,8 @@ UM.MainWindow target: Cura.Actions.manageMaterials function onTriggered() { - preferences.visible = true; - preferences.setPage(3) + var dialog = showPreferencesDialog() + dialog.currentPage = 3; } } @@ -541,11 +528,11 @@ UM.MainWindow target: Cura.Actions.configureSettingVisibility function onTriggered(source) { - preferences.visible = true; - preferences.setPage(1); + var dialog = showPreferencesDialog() + dialog.currentPage = 1; if(source && source.key) { - preferences.getCurrentItem().scrollToSection(source.key); + dialog.currentItem.scrollToSection(source.key); } } } diff --git a/resources/qml/Preferences/PreferencesDialog.qml b/resources/qml/Preferences/PreferencesDialog.qml new file mode 100644 index 0000000000..0d46cd6b42 --- /dev/null +++ b/resources/qml/Preferences/PreferencesDialog.qml @@ -0,0 +1,136 @@ +// Copyright (c) 2022 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.1 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.1 +import QtQuick.Window 2.1 + +import ".." + +import UM 1.6 as UM + +UM.Dialog +{ + id: base + + title: catalog.i18nc("@title:window", "Preferences") + minimumWidth: UM.Theme.getSize("modal_window_minimum").width + minimumHeight: UM.Theme.getSize("modal_window_minimum").height + width: minimumWidth + height: minimumHeight + + property alias currentPage: pagesList.currentIndex + property alias currentItem: pagesList.currentItem + + Rectangle + { + anchors.fill: parent + color: UM.Theme.getColor("background_2") + } + + Item + { + id: test + anchors.fill: parent + anchors.margins: UM.Theme.getSize("default_margin").width + + ListView + { + id: pagesList + width: UM.Theme.getSize("preferences_page_list_item").width + anchors.top: parent.top + anchors.bottom: parent.bottom + + ScrollBar.vertical: UM.ScrollBar {} + clip: true + model: [ + { + name: catalog.i18nc("@title:tab","General"), + item: Qt.resolvedUrl("GeneralPage.qml") + }, + { + name: catalog.i18nc("@title:tab","Settings"), + item: Qt.resolvedUrl("SettingVisibilityPage.qml") + }, + { + name: catalog.i18nc("@title:tab","Printers"), + item: Qt.resolvedUrl("MachinesPage.qml") + }, + { + name: catalog.i18nc("@title:tab","Materials"), + item: Qt.resolvedUrl("Materials/MaterialsPage.qml") + }, + { + name: catalog.i18nc("@title:tab","Profiles"), + item: Qt.resolvedUrl("ProfilesPage.qml") + } + ] + + delegate: Rectangle + { + width: parent ? parent.width : 0 + height: pageLabel.height + + color: ListView.isCurrentItem ? UM.Theme.getColor("background_3") : UM.Theme.getColor("main_background") + + UM.Label + { + id: pageLabel + anchors.centerIn: parent + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + width: parent.width + height: UM.Theme.getSize("preferences_page_list_item").height + color: UM.Theme.getColor("text_default") + text: modelData.name + } + MouseArea + { + anchors.fill: parent + onClicked: pagesList.currentIndex = index + } + } + + onCurrentIndexChanged: stackView.replace(model[currentIndex].item) + } + + StackView + { + id: stackView + anchors + { + left: pagesList.right + leftMargin: UM.Theme.getSize("narrow_margin").width + top: parent.top + bottom: parent.bottom + right: parent.right + } + + initialItem: Item { property bool resetEnabled: false } + + replaceEnter: Transition + { + NumberAnimation + { + properties: "opacity" + from: 0 + to: 1 + duration: 100 + } + } + replaceExit: Transition + { + NumberAnimation + { + properties: "opacity" + from: 1 + to: 0 + duration: 100 + } + } + } + + UM.I18nCatalog { id: catalog; name: "uranium"; } + } +} diff --git a/resources/qml/qmldir b/resources/qml/qmldir index 8fce82c858..98140608c6 100644 --- a/resources/qml/qmldir +++ b/resources/qml/qmldir @@ -52,3 +52,7 @@ NumericTextFieldWithUnit 1.0 NumericTextFieldWithUnit.qml PrintHeadMinMaxTextField 1.0 PrintHeadMinMaxTextField.qml SimpleCheckBox 1.0 SimpleCheckBox.qml RenameDialog 1.0 RenameDialog.qml + +# Cura/Preferences + +PreferencesDialog 1.0 PreferencesDialog.qml From d00a9b8715fb9eaa8f0c4b6b605de2f684bb69d4 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 25 Jul 2025 14:15:55 +0200 Subject: [PATCH 263/299] Fix double margin in Preferences dialog CURA-11810 --- .../qml/Preferences/PreferencesDialog.qml | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/resources/qml/Preferences/PreferencesDialog.qml b/resources/qml/Preferences/PreferencesDialog.qml index 0d46cd6b42..f175370205 100644 --- a/resources/qml/Preferences/PreferencesDialog.qml +++ b/resources/qml/Preferences/PreferencesDialog.qml @@ -19,21 +19,15 @@ UM.Dialog minimumHeight: UM.Theme.getSize("modal_window_minimum").height width: minimumWidth height: minimumHeight + backgroundColor: UM.Theme.getColor("background_2") property alias currentPage: pagesList.currentIndex property alias currentItem: pagesList.currentItem - Rectangle - { - anchors.fill: parent - color: UM.Theme.getColor("background_2") - } - Item { id: test anchors.fill: parent - anchors.margins: UM.Theme.getSize("default_margin").width ListView { @@ -46,23 +40,23 @@ UM.Dialog clip: true model: [ { - name: catalog.i18nc("@title:tab","General"), + name: catalog.i18nc("@title:tab", "General"), item: Qt.resolvedUrl("GeneralPage.qml") }, { - name: catalog.i18nc("@title:tab","Settings"), + name: catalog.i18nc("@title:tab", "Settings"), item: Qt.resolvedUrl("SettingVisibilityPage.qml") }, { - name: catalog.i18nc("@title:tab","Printers"), + name: catalog.i18nc("@title:tab", "Printers"), item: Qt.resolvedUrl("MachinesPage.qml") }, { - name: catalog.i18nc("@title:tab","Materials"), + name: catalog.i18nc("@title:tab", "Materials"), item: Qt.resolvedUrl("Materials/MaterialsPage.qml") }, { - name: catalog.i18nc("@title:tab","Profiles"), + name: catalog.i18nc("@title:tab", "Profiles"), item: Qt.resolvedUrl("ProfilesPage.qml") } ] From f8810c463ac6d02cf0a79e11f7592fd9d600a7a9 Mon Sep 17 00:00:00 2001 From: Wouter Symons Date: Sun, 27 Jul 2025 15:30:32 +0200 Subject: [PATCH 264/299] conanfile.py: correct quotes in f-string --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 89b2da35d6..dbe524b2f1 100644 --- a/conanfile.py +++ b/conanfile.py @@ -338,7 +338,7 @@ class CuraConan(ConanFile): if extra_build_identifiers: separator = "+" if not cura_version.build else "." - cura_version = Version(f"{cura_version}{separator}{".".join(extra_build_identifiers)}") + cura_version = Version(f"{cura_version}{separator}{'.'.join(extra_build_identifiers)}") self.output.info(f"Write CuraVersion.py to {self.recipe_folder}") From 5426f80c57e687f3e1da75f0917bde4b70f7b0a6 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 29 Jul 2025 07:54:30 +0200 Subject: [PATCH 265/299] Update action version --- .github/workflows/printer-linter-pr-diagnose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/printer-linter-pr-diagnose.yml b/.github/workflows/printer-linter-pr-diagnose.yml index 64892e0db1..666383c8f9 100644 --- a/.github/workflows/printer-linter-pr-diagnose.yml +++ b/.github/workflows/printer-linter-pr-diagnose.yml @@ -47,7 +47,7 @@ jobs: path: printer-linter-result/ - name: Run clang-tidy-pr-comments action - uses: platisd/clang-tidy-pr-comments@bc0bb7da034a8317d54e7fe1e819159002f4cc40 + uses: platisd/clang-tidy-pr-comments@v1.8.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} clang_tidy_fixes: result.yml From 92ff625a52e8dd46b720cecbc623650dca6cef09 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 29 Jul 2025 19:18:39 +0200 Subject: [PATCH 266/299] Add UV-unwrap lib to 'hidden imports'. This is probably what it needs for the builds to start working on Windows. part of CURA-12528 --- conandata.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/conandata.yml b/conandata.yml index 3181d601e5..537c8bc72c 100644 --- a/conandata.yml +++ b/conandata.yml @@ -99,6 +99,7 @@ pyinstaller: - "pyArcus" - "pyDulcificum" - "pynest2d" + - "pyUvula" - "PyQt6" - "PyQt6.QtNetwork" - "PyQt6.sip" From 5d2aca4e31fbf57c19fbff58ae0e884f670fe334 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 30 Jul 2025 12:10:40 +0200 Subject: [PATCH 267/299] Avoid crash when UV coordinates not loaded/generated CURA-12664 --- plugins/PaintTool/PaintTool.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 524011af9d..fa6436f10d 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -186,7 +186,11 @@ class PaintTool(Tool): pt = self._picking_pass.getPickedPosition(x, y).getData() va, vb, vc = self._mesh_transformed_cache.getFaceNodes(face_id) - ta, tb, tc = node.getMeshData().getFaceUvCoords(face_id) + + face_uv_coordinates = node.getMeshData().getFaceUvCoords(face_id) + if face_uv_coordinates is None: + return face_id, None + ta, tb, tc = face_uv_coordinates # 'Weight' of each vertex that would produce point pt, so we can generate the texture coordinates from the uv ones of the vertices. # See (also) https://mathworld.wolfram.com/BarycentricCoordinates.html From 8af8283d2c00c2c1b968f934c4a18df6c5b310ac Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 30 Jul 2025 14:02:56 +0200 Subject: [PATCH 268/299] Use newly exposed 'reloadNodes' so we can use Uraniums version of that. This caused issues where the code deleted in this ticket was almost the same as in Uranium, except it was slightly buggy (but it also did slightly more, hence the new 'on_done' parametrer). part of CURA-12630 --- cura/CuraApplication.py | 58 +++-------------------------------------- 1 file changed, 3 insertions(+), 55 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 8af98c2d0e..491d68630e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -9,7 +9,6 @@ import time import platform from pathlib import Path from typing import cast, TYPE_CHECKING, Optional, Callable, List, Any, Dict -import requests import numpy from PyQt6.QtCore import QObject, QTimer, QUrl, QUrlQuery, pyqtSignal, pyqtProperty, QEvent, pyqtEnum, QCoreApplication, \ @@ -1645,14 +1644,10 @@ class CuraApplication(QtApplication): Logger.log("w", "Unable to reload data because we don't have a filename.") for file_name, nodes in objects_in_filename.items(): - file_path = os.path.normpath(os.path.dirname(file_name)) - job = ReadMeshJob(file_name, - add_to_recent_files=file_path != tempfile.gettempdir()) # Don't add temp files to the recent files list - job._nodes = nodes # type: ignore - job.finished.connect(self._reloadMeshFinished) + on_done = None if has_merged_nodes: - job.finished.connect(self.updateOriginOfMergedMeshes) - job.start() + on_done = self.updateOriginOfMergedMeshes + self.getController().getScene().reloadNodes(nodes, file_name, on_done) @pyqtSlot("QStringList") def setExpandedCategories(self, categories: List[str]) -> None: @@ -1835,53 +1830,6 @@ class CuraApplication(QtApplication): fileLoaded = pyqtSignal(str) fileCompleted = pyqtSignal(str) - def _reloadMeshFinished(self, job) -> None: - """ - Function called when ReadMeshJob finishes reloading a file in the background, then update node objects in the - scene from its source file. The function gets all the nodes that exist in the file through the job result, and - then finds the scene nodes that need to be refreshed by their name. Each job refreshes all nodes of a file. - Nodes that are not present in the updated file are kept in the scene. - - :param job: The :py:class:`Uranium.UM.ReadMeshJob.ReadMeshJob` running in the background that reads all the - meshes in a file - """ - - job_result = job.getResult() # nodes that exist inside the file read by this job - if len(job_result) == 0: - Logger.log("e", "Reloading the mesh failed.") - return - renamed_nodes = {} # type: Dict[str, int] - # Find the node to be refreshed based on its id - for job_result_node in job_result: - mesh_data = job_result_node.getMeshData() - if not mesh_data: - Logger.log("w", "Could not find a mesh in reloaded node.") - continue - - # Solves issues with object naming - result_node_name = job_result_node.getName() - if not result_node_name: - result_node_name = os.path.basename(mesh_data.getFileName()) - if result_node_name in renamed_nodes: # objects may get renamed by ObjectsModel._renameNodes() when loaded - renamed_nodes[result_node_name] += 1 - result_node_name = "{0}({1})".format(result_node_name, renamed_nodes[result_node_name]) - else: - renamed_nodes[job_result_node.getName()] = 0 - - # Find the matching scene node to replace - scene_node = None - for replaced_node in job._nodes: - if replaced_node.getName() == result_node_name: - scene_node = replaced_node - break - - if scene_node: - scene_node.setMeshData(mesh_data) - else: - # Current node is a new one in the file, or it's name has changed - # TODO: Load this mesh into the scene. Also alter the "_reloadJobFinished" action in UM.Scene - Logger.log("w", "Could not find matching node for object '{0}' in the scene.".format(result_node_name)) - def _openFile(self, filename): self.readLocalFile(QUrl.fromLocalFile(filename)) From 37c364e8a5692bc3b7fd950a586a8918589132da Mon Sep 17 00:00:00 2001 From: THeijmans Date: Wed, 30 Jul 2025 14:11:57 +0200 Subject: [PATCH 269/299] PP-650-High-speed-profile-improvements-S6S8 --- resources/definitions/ultimaker_s8.def.json | 61 +++++++++++-------- ...um_s8_aa_plus_0.4_abs_0.2mm_quick.inst.cfg | 22 +++++++ ...m_s8_aa_plus_0.4_petg_0.2mm_quick.inst.cfg | 22 +++++++ ...um_s8_aa_plus_0.4_pla_0.2mm_quick.inst.cfg | 22 +++++++ ...aa_plus_0.4_tough-pla_0.2mm_quick.inst.cfg | 22 +++++++ .../um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg | 5 +- .../um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg | 4 +- .../um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg | 4 ++ .../um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg | 4 ++ .../um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg | 4 ++ ...m_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg | 4 ++ ...um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg | 4 ++ ...um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg | 4 ++ 13 files changed, 156 insertions(+), 26 deletions(-) create mode 100644 resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm_quick.inst.cfg create mode 100644 resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm_quick.inst.cfg create mode 100644 resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm_quick.inst.cfg create mode 100644 resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm_quick.inst.cfg diff --git a/resources/definitions/ultimaker_s8.def.json b/resources/definitions/ultimaker_s8.def.json index b7de27722d..cbd6e255f8 100644 --- a/resources/definitions/ultimaker_s8.def.json +++ b/resources/definitions/ultimaker_s8.def.json @@ -98,7 +98,7 @@ { "maximum_value": "machine_max_acceleration_x", "maximum_value_warning": "machine_max_acceleration_x*0.8", - "value": "acceleration_wall_0" + "value": "acceleration_topbottom / 2" }, "acceleration_skirt_brim": { @@ -199,15 +199,19 @@ }, "adhesion_type": { "value": "'brim' if support_enable and support_structure=='tree' else 'skirt'" }, "bottom_thickness": { "value": "3*layer_height if top_layers==4 and not support_enable else top_bottom_thickness" }, - "bridge_skin_material_flow": { "value": 200 }, + "bridge_enable_more_layers": { "value": true }, + "bridge_skin_density": { "value": 70 }, + "bridge_skin_material_flow": { "value": 150 }, + "bridge_skin_material_flow_2": { "value": 70 }, "bridge_skin_speed": { "unit": "mm/s", - "value": "bridge_wall_speed" + "value": 35 }, + "bridge_skin_speed_2": { "value": "speed_print*2/3" }, "bridge_sparse_infill_max_density": { "value": 50 }, - "bridge_wall_material_flow": { "value": "bridge_skin_material_flow" }, - "bridge_wall_min_length": { "value": 10 }, + "bridge_wall_material_flow": { "value": 200 }, + "bridge_wall_min_length": { "value": 2 }, "bridge_wall_speed": { "unit": "mm/s", @@ -221,13 +225,13 @@ ] }, "cool_during_extruder_switch": { "value": "'all_fans'" }, - "cool_min_layer_time": { "value": 5 }, - "cool_min_layer_time_overhang": { "value": 9 }, - "cool_min_layer_time_overhang_min_segment_length": { "value": 2 }, + "cool_min_layer_time": { "value": 6 }, + "cool_min_layer_time_overhang": { "value": 11 }, + "cool_min_layer_time_overhang_min_segment_length": { "value": 1.5 }, "cool_min_speed": { "value": 6 }, "cool_min_temperature": { - "minimum_value_warning": "material_print_temperature-15", + "minimum_value_warning": "material_print_temperature-20", "value": "material_print_temperature-15" }, "default_material_print_temperature": { "maximum_value_warning": 320 }, @@ -235,9 +239,9 @@ "flooring_layer_count": { "value": 1 }, "gradual_flow_enabled": { "value": false }, "hole_xy_offset": { "value": 0.075 }, - "infill_material_flow": { "value": "material_flow" }, + "infill_material_flow": { "value": "material_flow if infill_sparse_density < 95 else 95" }, "infill_overlap": { "value": 10 }, - "infill_pattern": { "value": "'zigzag' if infill_sparse_density > 80 else 'grid'" }, + "infill_pattern": { "value": "'zigzag' if infill_sparse_density > 50 else 'grid'" }, "infill_sparse_density": { "value": 15 }, "infill_wall_line_count": { "value": "1 if infill_sparse_density > 80 else 0" }, "initial_bottom_layers": { "value": 2 }, @@ -281,7 +285,7 @@ { "maximum_value_warning": "machine_max_jerk_xy / 2", "unit": "m/s\u00b3", - "value": "jerk_wall_0" + "value": "jerk_print" }, "jerk_skirt_brim": { @@ -438,10 +442,11 @@ "retraction_hop": { "value": 1 }, "retraction_hop_after_extruder_switch_height": { "value": 2 }, "retraction_hop_enabled": { "value": true }, - "retraction_min_travel": { "value": "5 if support_enable and support_structure=='tree' else line_width * 2.5" }, + "retraction_min_travel": { "value": "2.5 if support_enable and support_structure=='tree' else line_width * 2.5" }, "retraction_prime_speed": { "value": 15 }, "skin_edge_support_thickness": { "value": 0 }, - "skin_material_flow": { "value": 95 }, + "skin_material_flow": { "value": 93 }, + "skin_outline_count": { "value": 0 }, "skin_overlap": { "value": 0 }, "skin_preshrink": { "value": 0 }, "skirt_brim_minimal_length": { "value": 1000 }, @@ -571,38 +576,46 @@ "value": "speed_wall" }, "support_angle": { "value": 60 }, - "support_bottom_distance": { "maximum_value_warning": "3*layer_height" }, + "support_bottom_distance": + { + "maximum_value_warning": "3*layer_height", + "value": "support_z_distance" + }, "support_bottom_offset": { "value": 0 }, "support_brim_width": { "value": 10 }, "support_interface_enable": { "value": true }, "support_interface_offset": { "value": "support_offset" }, "support_line_width": { "value": "1.25*line_width" }, - "support_offset": { "value": "1.2 if support_structure == 'tree' else 0.8" }, + "support_offset": { "value": 0.8 }, "support_pattern": { "value": "'gyroid' if support_structure == 'tree' else 'lines'" }, "support_roof_height": { "minimum_value_warning": 0 }, "support_structure": { "value": "'normal'" }, "support_top_distance": { "maximum_value_warning": "3*layer_height" }, "support_tree_angle": { "value": 50 }, "support_tree_angle_slow": { "value": 35 }, - "support_tree_bp_diameter": { "value": 15 }, - "support_tree_branch_diameter": { "value": 8 }, - "support_tree_tip_diameter": { "value": 1.0 }, - "support_tree_top_rate": { "value": 20 }, - "support_xy_distance_overhang": { "value": "machine_nozzle_size" }, - "support_z_distance": { "value": "0.4*material_shrinkage_percentage_z/100.0" }, - "top_bottom_thickness": { "value": "round(4*layer_height, 2)" }, + "support_tree_bp_diameter": { "value": 20 }, + "support_tree_branch_diameter": { "value": 5 }, + "support_tree_branch_diameter_angle": { "value": 5 }, + "support_tree_max_diameter": { "value": 15 }, + "support_tree_tip_diameter": { "value": 2.0 }, + "support_tree_top_rate": { "value": 10 }, + "support_xy_distance": { "value": 1.2 }, + "support_xy_distance_overhang": { "value": "1.5*machine_nozzle_size" }, + "support_z_distance": { "value": "2*layer_height" }, + "top_bottom_thickness": { "value": "wall_thickness" }, "travel_avoid_other_parts": { "value": true }, "travel_avoid_supports": { "value": true }, "wall_0_acceleration": { "value": 1000 }, "wall_0_deceleration": { "value": 1000 }, "wall_0_end_speed_ratio": { "value": 100 }, + "wall_0_inset": { "value": 0.05 }, "wall_0_speed_split_distance": { "value": 0.2 }, "wall_0_start_speed_ratio": { "value": 100 }, "wall_0_wipe_dist": { "value": 0 }, "wall_material_flow": { "value": 95 }, "wall_overhang_angle": { "value": 45 }, "wall_x_material_flow": { "value": 100 }, - "xy_offset": { "value": 0.05 }, + "xy_offset": { "value": 0.075 }, "z_seam_corner": { "value": "'z_seam_corner_weighted'" }, "z_seam_position": { "value": "'backright'" }, "z_seam_type": { "value": "'sharpest_corner'" } diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm_quick.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm_quick.inst.cfg new file mode 100644 index 0000000000..9889424797 --- /dev/null +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm_quick.inst.cfg @@ -0,0 +1,22 @@ +[general] +definition = ultimaker_s8 +name = Quick +version = 4 + +[metadata] +intent_category = quick +material = generic_abs +quality_type = draft +setting_version = 25 +type = intent +variant = AA+ 0.4 + +[values] +cool_min_layer_time = 5 +cool_min_layer_time_overhang = 9 +cool_min_speed = 6 +cool_min_temperature = =material_print_temperature - 15 +speed_wall_x = =speed_print +speed_wall_x_roofing = =speed_wall +wall_line_width_x = =wall_line_width + diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm_quick.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm_quick.inst.cfg new file mode 100644 index 0000000000..ae38c02395 --- /dev/null +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm_quick.inst.cfg @@ -0,0 +1,22 @@ +[general] +definition = ultimaker_s8 +name = Quick +version = 4 + +[metadata] +intent_category = quick +material = generic_petg +quality_type = draft +setting_version = 25 +type = intent +variant = AA+ 0.4 + +[values] +cool_min_layer_time = 5 +cool_min_layer_time_overhang = 9 +cool_min_speed = 6 +cool_min_temperature = =material_print_temperature - 15 +speed_wall_x = =speed_print +speed_wall_x_roofing = =speed_wall +wall_line_width_x = =wall_line_width + diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm_quick.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm_quick.inst.cfg new file mode 100644 index 0000000000..4509317076 --- /dev/null +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm_quick.inst.cfg @@ -0,0 +1,22 @@ +[general] +definition = ultimaker_s8 +name = Quick +version = 4 + +[metadata] +intent_category = quick +material = generic_pla +quality_type = draft +setting_version = 25 +type = intent +variant = AA+ 0.4 + +[values] +cool_min_layer_time = 5 +cool_min_layer_time_overhang = 9 +cool_min_speed = 6 +cool_min_temperature = =material_print_temperature - 15 +speed_wall_x = =speed_print +speed_wall_x_roofing = =speed_wall +wall_line_width_x = =wall_line_width + diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm_quick.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm_quick.inst.cfg new file mode 100644 index 0000000000..4f75b631df --- /dev/null +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm_quick.inst.cfg @@ -0,0 +1,22 @@ +[general] +definition = ultimaker_s8 +name = Quick +version = 4 + +[metadata] +intent_category = quick +material = generic_tough_pla +quality_type = draft +setting_version = 25 +type = intent +variant = AA+ 0.4 + +[values] +cool_min_layer_time = 5 +cool_min_layer_time_overhang = 9 +cool_min_speed = 6 +cool_min_temperature = =material_print_temperature - 15 +speed_wall_x = =speed_print +speed_wall_x_roofing = =speed_wall +wall_line_width_x = =wall_line_width + diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg index 37767673aa..cc5e850220 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg @@ -14,7 +14,10 @@ weight = -2 [values] cool_min_layer_time = 4 cool_min_layer_time_fan_speed_max = 9 -cool_min_temperature = =material_print_temperature - 10 +cool_min_temperature = =material_print_temperature - 20 retraction_prime_speed = 15 +speed_wall_x = =speed_wall +speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree +wall_line_width_x = =wall_line_width * 1.25 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg index a22e4fbeec..9abcd5ddd2 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg @@ -15,5 +15,7 @@ weight = -2 cool_min_layer_time = 4 material_print_temperature = =default_material_print_temperature + 5 retraction_prime_speed = 15 -support_structure = tree +speed_wall_x = =speed_wall +speed_wall_x_roofing = =speed_wall * 0.8 +wall_line_width_x = =wall_line_width * 1.25 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg index 6c445180f8..9feab61e0e 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg @@ -12,8 +12,12 @@ variant = AA+ 0.4 weight = -1 [values] +cool_min_temperature = =material_print_temperature - 20 material_final_print_temperature = =material_print_temperature - 15 material_initial_print_temperature = =material_print_temperature - 15 retraction_prime_speed = =retraction_speed +speed_wall_x = =speed_wall +speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree +wall_line_width_x = =wall_line_width * 1.25 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg index d3d99eec9e..8431bb9c43 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg @@ -12,9 +12,13 @@ variant = AA+ 0.4 weight = 0 [values] +cool_min_temperature = =material_print_temperature - 20 material_final_print_temperature = =material_print_temperature - 15 material_initial_print_temperature = =material_print_temperature - 15 retraction_prime_speed = =retraction_speed +speed_wall_x = =speed_wall +speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree top_bottom_thickness = =round(6*layer_height,3) +wall_line_width_x = =wall_line_width * 1.25 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg index 2e015f8a88..7a5d19dc2c 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg @@ -12,8 +12,12 @@ variant = AA+ 0.4 weight = -2 [values] +cool_min_temperature = =material_print_temperature - 20 material_final_print_temperature = =material_print_temperature - 15 material_initial_print_temperature = =material_print_temperature - 15 retraction_prime_speed = =retraction_speed +speed_wall_x = =speed_wall +speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree +wall_line_width_x = =wall_line_width * 1.25 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg index e3477c1e7d..f17d3fde40 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg @@ -12,7 +12,11 @@ variant = AA+ 0.4 weight = -1 [values] +cool_min_temperature = =material_print_temperature - 20 retraction_prime_speed = =retraction_speed retraction_speed = 25 +speed_wall_x = =speed_wall +speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree +wall_line_width_x = =wall_line_width * 1.25 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg index 6ccc0da6dd..672eae3e4a 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg @@ -12,7 +12,11 @@ variant = AA+ 0.4 weight = 0 [values] +cool_min_temperature = =material_print_temperature - 20 retraction_prime_speed = =retraction_speed +speed_wall_x = =speed_wall +speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree top_bottom_thickness = =round(6*layer_height,3) +wall_line_width_x = =wall_line_width * 1.25 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg index bb629e0758..716765aac5 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg @@ -12,6 +12,10 @@ variant = AA+ 0.4 weight = -2 [values] +cool_min_temperature = =material_print_temperature - 20 retraction_prime_speed = =retraction_speed +speed_wall_x = =speed_wall +speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree +wall_line_width_x = =wall_line_width * 1.25 From 5040e7f230b031ece60ccbee3cf6224a0567cf74 Mon Sep 17 00:00:00 2001 From: Timur Seitosmanov Date: Wed, 3 Jul 2024 12:10:43 +0200 Subject: [PATCH 270/299] Trigger machine error checking during startup. Otherwise slicing will keep failing until selected printer is changed. --- cura/Machines/MachineErrorChecker.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/Machines/MachineErrorChecker.py b/cura/Machines/MachineErrorChecker.py index 5edee0778f..87d50e46d4 100644 --- a/cura/Machines/MachineErrorChecker.py +++ b/cura/Machines/MachineErrorChecker.py @@ -61,6 +61,7 @@ class MachineErrorChecker(QObject): self._machine_manager.globalContainerChanged.connect(self.startErrorCheck) self._onMachineChanged() + self.startErrorCheck() def _setCheckTimer(self) -> None: """A QTimer to regulate error check frequency From da0509cda35f66df6f03bb1046ff6170a7ab5c4a Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 30 Jul 2025 15:58:26 +0200 Subject: [PATCH 271/299] Fix painting through an invisible object CURA-12660 --- cura/PickingPass.py | 6 ++++-- plugins/PaintTool/PaintTool.py | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cura/PickingPass.py b/cura/PickingPass.py index 4d6ef671df..dd91659afe 100644 --- a/cura/PickingPass.py +++ b/cura/PickingPass.py @@ -7,6 +7,7 @@ from UM.Qt.QtApplication import QtApplication from UM.Logger import Logger from UM.Math.Vector import Vector from UM.Resources import Resources +from UM.Scene.Selection import Selection from UM.View.RenderPass import RenderPass from UM.View.GL.OpenGL import OpenGL @@ -27,13 +28,14 @@ class PickingPass(RenderPass): .. note:: that in order to increase precision, the 24 bit depth value is encoded into all three of the R,G & B channels """ - def __init__(self, width: int, height: int) -> None: + def __init__(self, width: int, height: int, only_selected_objects: bool = False) -> None: super().__init__("picking", width, height) self._renderer = QtApplication.getInstance().getRenderer() self._shader = None #type: Optional[ShaderProgram] self._scene = QtApplication.getInstance().getController().getScene() + self._only_selected_objects = only_selected_objects def render(self) -> None: if not self._shader: @@ -53,7 +55,7 @@ class PickingPass(RenderPass): # Fill up the batch with objects that can be sliced. ` for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax. - if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible(): + if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible() and (not self._only_selected_objects or Selection.isSelected(node)): batch.addItem(node.getWorldTransformation(copy = False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix()) self.bind() diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 524011af9d..fcc5c9a3a0 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -300,7 +300,9 @@ class PaintTool(Tool): return False if not self._picking_pass: - self._picking_pass = PickingPass(camera.getViewportWidth(), camera.getViewportHeight()) + self._picking_pass = PickingPass(camera.getViewportWidth(), + camera.getViewportHeight(), + only_selected_objects = True) self._picking_pass.render() self._selection_pass.renderFacesMode() From 73f5b817b438df0b03b943b3993d2dea656cdffe Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 30 Jul 2025 15:59:30 +0200 Subject: [PATCH 272/299] Display build plate in paint mode CURA-12660 --- plugins/PaintTool/PaintView.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 22eb8c55f6..18dc067c5a 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -8,10 +8,13 @@ from typing import Optional, List, Tuple, Dict from PyQt6.QtGui import QImage, QColor, QPainter from cura.CuraApplication import CuraApplication +from cura.BuildVolume import BuildVolume from UM.PluginRegistry import PluginRegistry from UM.View.GL.ShaderProgram import ShaderProgram from UM.View.GL.Texture import Texture from UM.View.View import View +from UM.View.SelectionPass import SelectionPass +from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.Selection import Selection from UM.View.GL.OpenGL import OpenGL from UM.i18n import i18nCatalog @@ -163,6 +166,11 @@ class PaintView(View): def beginRendering(self) -> None: renderer = self.getRenderer() self._checkSetup() + + for node in DepthFirstIterator(self._scene.getRoot()): + if isinstance(node, BuildVolume): + node.render(renderer) + paint_batch = renderer.createRenderBatch(shader=self._paint_shader) renderer.addRenderBatch(paint_batch) From 6bf9a8a0aeba3b7157ae4bdd695e9ffa50396bca Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 30 Jul 2025 16:00:13 +0200 Subject: [PATCH 273/299] Ignore invisible object for selection in paint mode CURA-12660 --- plugins/PaintTool/PaintView.py | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 18dc067c5a..c37afd178d 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -3,7 +3,7 @@ import os from PyQt6.QtCore import QRect -from typing import Optional, List, Tuple, Dict +from typing import Optional, List, Tuple, Dict, cast from PyQt6.QtGui import QImage, QColor, QPainter @@ -47,7 +47,9 @@ class PaintView(View): self._force_opaque_mask = QImage(2, 2, QImage.Format.Format_Mono) self._force_opaque_mask.fill(1) - CuraApplication.getInstance().engineCreatedSignal.connect(self._makePaintModes) + application = CuraApplication.getInstance() + application.engineCreatedSignal.connect(self._makePaintModes) + self._scene = application.getController().getScene() def _makePaintModes(self): theme = CuraApplication.getInstance().getTheme() @@ -164,6 +166,9 @@ class PaintView(View): return start_index, end_index def beginRendering(self) -> None: + if self._current_paint_type == "": + return + renderer = self.getRenderer() self._checkSetup() @@ -174,12 +179,20 @@ class PaintView(View): paint_batch = renderer.createRenderBatch(shader=self._paint_shader) renderer.addRenderBatch(paint_batch) - node = Selection.getSelectedObject(0) - if node is None: - return + display_objects = Selection.getAllSelectedObjects().copy() + if display_objects: + selection_pass = cast(SelectionPass, renderer.getRenderPass("selection")) + if selection_pass is not None: + selection_pass.setIgnoreUnselectedObjectsDuringNextRender() + else: + for node in DepthFirstIterator(self._scene.getRoot()): + if node.callDecoration("isSliceable"): + display_objects.append(node) - if self._current_paint_type == "": - return + for node in display_objects: + paint_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix()) + self._current_paint_texture = node.callDecoration("getPaintTexture") + self._paint_shader.setTexture(0, self._current_paint_texture) self._paint_shader.setUniformValue("u_bitsRangesStart", self._current_bits_ranges[0]) self._paint_shader.setUniformValue("u_bitsRangesEnd", self._current_bits_ranges[1]) @@ -187,8 +200,3 @@ class PaintView(View): colors = [paint_type_obj.display_color for paint_type_obj in self._paint_modes[self._current_paint_type].values()] colors_values = [[int(color_part * 255) for color_part in [color.r, color.g, color.b]] for color in colors] self._paint_shader.setUniformValueArray("u_renderColors", colors_values) - - self._current_paint_texture = node.callDecoration("getPaintTexture") - self._paint_shader.setTexture(0, self._current_paint_texture) - - paint_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix()) From 6896c0ed4bfb23475fb52d50d76900ec6a85906e Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 30 Jul 2025 16:53:41 +0200 Subject: [PATCH 274/299] Display classic view when there is no selection CURA-12660 --- plugins/PaintTool/PaintView.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index c37afd178d..60656086ff 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -9,10 +9,10 @@ from PyQt6.QtGui import QImage, QColor, QPainter from cura.CuraApplication import CuraApplication from cura.BuildVolume import BuildVolume +from plugins.SolidView.SolidView import SolidView from UM.PluginRegistry import PluginRegistry from UM.View.GL.ShaderProgram import ShaderProgram from UM.View.GL.Texture import Texture -from UM.View.View import View from UM.View.SelectionPass import SelectionPass from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.Selection import Selection @@ -23,7 +23,7 @@ from UM.Math.Color import Color catalog = i18nCatalog("cura") -class PaintView(View): +class PaintView(SolidView): """View for model-painting.""" UNDO_STACK_SIZE = 1024 @@ -62,6 +62,8 @@ class PaintView(View): } def _checkSetup(self): + super()._checkSetup() + if not self._paint_shader: shader_filename = os.path.join(PluginRegistry.getInstance().getPluginPath("PaintTool"), "paint.shader") self._paint_shader = OpenGL.getInstance().createShaderProgram(shader_filename) @@ -169,8 +171,14 @@ class PaintView(View): if self._current_paint_type == "": return - renderer = self.getRenderer() + display_objects = Selection.getAllSelectedObjects().copy() + if not display_objects: + # Display the classic view until an object is selected + super().beginRendering() + return + self._checkSetup() + renderer = self.getRenderer() for node in DepthFirstIterator(self._scene.getRoot()): if isinstance(node, BuildVolume): @@ -179,15 +187,9 @@ class PaintView(View): paint_batch = renderer.createRenderBatch(shader=self._paint_shader) renderer.addRenderBatch(paint_batch) - display_objects = Selection.getAllSelectedObjects().copy() - if display_objects: - selection_pass = cast(SelectionPass, renderer.getRenderPass("selection")) - if selection_pass is not None: - selection_pass.setIgnoreUnselectedObjectsDuringNextRender() - else: - for node in DepthFirstIterator(self._scene.getRoot()): - if node.callDecoration("isSliceable"): - display_objects.append(node) + selection_pass = cast(SelectionPass, renderer.getRenderPass("selection")) + if selection_pass is not None: + selection_pass.setIgnoreUnselectedObjectsDuringNextRender() for node in display_objects: paint_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix()) From 91e986697d229f85fd0375424d43e57e32ce5685 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 30 Jul 2025 16:54:05 +0200 Subject: [PATCH 275/299] Fix painting after changing the selected object CURA-12660 --- plugins/PaintTool/PaintTool.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index fcc5c9a3a0..2099a59691 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -293,6 +293,7 @@ class PaintTool(Tool): self._node_cache.transformationChanged.disconnect(self._nodeTransformChanged) self._node_cache = node self._node_cache.transformationChanged.connect(self._nodeTransformChanged) + self._cache_dirty = True if self._cache_dirty: self._cache_dirty = False self._mesh_transformed_cache = self._node_cache.getMeshDataTransformed() From 6292f5b133f6423bd758bf1d56c738f8517d050d Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 30 Jul 2025 16:57:29 +0200 Subject: [PATCH 276/299] Hide paint-on-support option until it is implemented CURA-12660 --- plugins/PaintTool/PaintTool.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index 4cbe9d4ade..e3f244dd4c 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -57,6 +57,7 @@ Item icon: "Support" tooltipText: catalog.i18nc("@tooltip", "Refine support placement by defining preferred/avoidance areas") mode: "support" + visible: false } } From ef7bde87fa4469174fd01c5cfca8cca59c545129 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 31 Jul 2025 11:24:36 +0200 Subject: [PATCH 277/299] Allow painting only when 1 object is selected CURA-12660 --- plugins/PaintTool/PaintView.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 60656086ff..61a6d0079c 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -172,8 +172,8 @@ class PaintView(SolidView): return display_objects = Selection.getAllSelectedObjects().copy() - if not display_objects: - # Display the classic view until an object is selected + if len(display_objects) != 1: + # Display the classic view until a single object is selected super().beginRendering() return From 3cb7eb3c873ed195ae998b0dd8ed15cea884a162 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 31 Jul 2025 11:47:41 +0200 Subject: [PATCH 278/299] Avoid too dark or too light areas while painting CURA-12660 This avoid having parts of the model where you cannot see the painted areas anymore --- plugins/PaintTool/paint.shader | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/PaintTool/paint.shader b/plugins/PaintTool/paint.shader index bd769f5cb2..f2af66ffe6 100644 --- a/plugins/PaintTool/paint.shader +++ b/plugins/PaintTool/paint.shader @@ -55,7 +55,7 @@ fragment = color_index = (color_index << (32 - 1 - u_bitsRangesEnd)) >> 32 - 1 - (u_bitsRangesEnd - u_bitsRangesStart); vec4 diffuse_color = vec4(u_renderColors[color_index] / 255.0, 1.0); - highp float n_dot_l = clamp(dot(normal, light_dir), 0.0, 1.0); + highp float n_dot_l = mix(0.3, 0.7, dot(normal, light_dir)); final_color += (n_dot_l * diffuse_color); final_color.a = u_opacity; @@ -122,7 +122,7 @@ fragment41core = color_index = (color_index << (32 - 1 - u_bitsRangesEnd)) >> 32 - 1 - (u_bitsRangesEnd - u_bitsRangesStart); vec4 diffuse_color = vec4(u_renderColors[color_index] / 255.0, 1.0); - highp float n_dot_l = clamp(dot(normal, light_dir), 0.0, 1.0); + highp float n_dot_l = mix(0.3, 0.7, dot(normal, light_dir)); final_color += (n_dot_l * diffuse_color); final_color.a = u_opacity; From ab58dec5d141c12a0cde128fb702126ec39914cd Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 1 Aug 2025 13:10:03 +0200 Subject: [PATCH 279/299] Fix unability to paint with visible message box CURA-12660 When a message box is displayed, some offscreen rendering passes (face selection) render an unpredictable result and we are unable to start painting. This went through a refactoring of the rendering passes. Since doing the offscreen rendering outside the Qt rendering loop caused some troubles, we now use the rendering passes only inside the Qt rendering loop, so that they work properly. Tools also have the ability to indicate which extra passes they require, so that we don't run all the passes when they are not required. Since this issue also concerns the support blockers placement and rotation by face selection, they have been updated so that they now also always work. The face selection mechanism using the Selection class was partially working and used only by the rotation, so now it has been deprecated in favor of the new mechanism. --- cura/CuraApplication.py | 4 +++ cura/CuraRenderer.py | 46 ++++++++++++++++++++++++++ cura/PickingPass.py | 2 +- plugins/PaintTool/PaintTool.py | 40 +++++++++++++++------- plugins/PaintTool/PaintView.py | 5 --- plugins/SupportEraser/SupportEraser.py | 17 +++++++--- 6 files changed, 91 insertions(+), 23 deletions(-) create mode 100644 cura/CuraRenderer.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 8af98c2d0e..660f312468 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -60,6 +60,7 @@ from cura import ApplicationMetadata from cura.API import CuraAPI from cura.API.Account import Account from cura.Arranging.ArrangeObjectsJob import ArrangeObjectsJob +from cura.CuraRenderer import CuraRenderer from cura.Machines.MachineErrorChecker import MachineErrorChecker from cura.Machines.Models.BuildPlateModel import BuildPlateModel from cura.Machines.Models.CustomQualityProfilesDropDownMenuModel import CustomQualityProfilesDropDownMenuModel @@ -362,6 +363,9 @@ class CuraApplication(QtApplication): self._machine_action_manager = MachineActionManager(self) self._machine_action_manager.initialize() + def makeRenderer(self) -> CuraRenderer: + return CuraRenderer(self) + def __sendCommandToSingleInstance(self): self._single_instance = SingleInstance(self, self._files_to_open, self._urls_to_open) diff --git a/cura/CuraRenderer.py b/cura/CuraRenderer.py new file mode 100644 index 0000000000..77030b3fe8 --- /dev/null +++ b/cura/CuraRenderer.py @@ -0,0 +1,46 @@ +# Copyright (c) 2025 UltiMaker +# Uranium is released under the terms of the LGPLv3 or higher. + + +from typing import TYPE_CHECKING + +from cura.PickingPass import PickingPass +from UM.Qt.QtRenderer import QtRenderer +from UM.View.RenderPass import RenderPass +from UM.View.SelectionPass import SelectionPass + +if TYPE_CHECKING: + from cura.CuraApplication import CuraApplication + + +class CuraRenderer(QtRenderer): + """An overridden Renderer implementation that adds some behaviors specific to Cura.""" + + def __init__(self, application: "CuraApplication") -> None: + super().__init__() + + self._controller = application.getController() + self._controller.activeToolChanged.connect(self._onActiveToolChanged) + self._extra_rendering_passes: list[RenderPass] = [] + + def _onActiveToolChanged(self) -> None: + tool_extra_rendering_passes = [] + + active_tool = self._controller.getActiveTool() + if active_tool is not None: + tool_extra_rendering_passes = active_tool.getRequiredExtraRenderingPasses() + + for extra_rendering_pass in self._extra_rendering_passes: + extra_rendering_pass.setEnabled(extra_rendering_pass.getName() in tool_extra_rendering_passes) + + def _makeRenderPasses(self) -> list[RenderPass]: + self._extra_rendering_passes = [ + SelectionPass(self._viewport_width, self._viewport_height, SelectionPass.SelectionMode.FACES), + PickingPass(self._viewport_width, self._viewport_height, only_selected_objects=True), + PickingPass(self._viewport_width, self._viewport_height, only_selected_objects=False) + ] + + for extra_rendering_pass in self._extra_rendering_passes: + extra_rendering_pass.setEnabled(False) + + return super()._makeRenderPasses() + self._extra_rendering_passes diff --git a/cura/PickingPass.py b/cura/PickingPass.py index dd91659afe..e585e72269 100644 --- a/cura/PickingPass.py +++ b/cura/PickingPass.py @@ -29,7 +29,7 @@ class PickingPass(RenderPass): """ def __init__(self, width: int, height: int, only_selected_objects: bool = False) -> None: - super().__init__("picking", width, height) + super().__init__("picking" if not only_selected_objects else "picking_selected", width, height) self._renderer = QtApplication.getInstance().getRenderer() diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 2099a59691..e57c6d5a11 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -17,7 +17,9 @@ from UM.Scene.SceneNode import SceneNode from UM.Scene.Selection import Selection from UM.Tool import Tool +from cura.CuraApplication import CuraApplication from cura.PickingPass import PickingPass +from UM.View.SelectionPass import SelectionPass from .PaintView import PaintView @@ -34,6 +36,7 @@ class PaintTool(Tool): super().__init__() self._picking_pass: Optional[PickingPass] = None + self._faces_selection_pass: Optional[SelectionPass] = None self._shortcut_key: Qt.Key = Qt.Key.Key_P @@ -52,6 +55,8 @@ class PaintTool(Tool): self._last_mouse_coords: Optional[Tuple[int, int]] = None self._last_face_id: Optional[int] = None + Selection.selectionChanged.connect(self._updateIgnoreUnselectedObjects) + def _createBrushPen(self) -> QPen: pen = QPen() pen.setWidth(self._brush_size) @@ -179,7 +184,7 @@ class PaintTool(Tool): self._cache_dirty = True def _getTexCoordsFromClick(self, node: SceneNode, x: float, y: float) -> Tuple[int, Optional[numpy.ndarray]]: - face_id = self._selection_pass.getFaceIdAtPosition(x, y) + face_id = self._faces_selection_pass.getFaceIdAtPosition(x, y) if face_id < 0 or face_id >= node.getMeshData().getFaceCount(): return face_id, None @@ -248,11 +253,14 @@ class PaintTool(Tool): if event.type == Event.ToolActivateEvent: controller.setActiveStage("PrepareStage") controller.setActiveView("PaintTool") # Because that's the plugin-name, and the view is registered to it. + self._updateIgnoreUnselectedObjects() return True if event.type == Event.ToolDeactivateEvent: controller.setActiveStage("PrepareStage") controller.setActiveView("SolidView") + CuraApplication.getInstance().getRenderer().getRenderPass("selection").setIgnoreUnselectedObjects(False) + CuraApplication.getInstance().getRenderer().getRenderPass("selection_faces").setIgnoreUnselectedObjects(False) return True if event.type == Event.MouseReleaseEvent and self._controller.getToolsEnabled(): @@ -281,8 +289,15 @@ class PaintTool(Tool): if paintview is None: return False - if not self._selection_pass: - return False + if not self._faces_selection_pass: + self._faces_selection_pass = CuraApplication.getInstance().getRenderer().getRenderPass("selection_faces") + if not self._faces_selection_pass: + return False + + if not self._picking_pass: + self._picking_pass = CuraApplication.getInstance().getRenderer().getRenderPass("picking_selected") + if not self._picking_pass: + return False camera = self._controller.getScene().getActiveCamera() if not camera: @@ -300,14 +315,6 @@ class PaintTool(Tool): if not self._mesh_transformed_cache: return False - if not self._picking_pass: - self._picking_pass = PickingPass(camera.getViewportWidth(), - camera.getViewportHeight(), - only_selected_objects = True) - self._picking_pass.render() - - self._selection_pass.renderFacesMode() - face_id, texcoords = self._getTexCoordsFromClick(node, mouse_evt.x, mouse_evt.y) if texcoords is None: return False @@ -347,4 +354,13 @@ class PaintTool(Tool): if node is None: node = Selection.getSelectedObject(0) if node is not None: - Application.getInstance().getController().getScene().sceneChanged.emit(node) \ No newline at end of file + Application.getInstance().getController().getScene().sceneChanged.emit(node) + + def getRequiredExtraRenderingPasses(self) -> list[str]: + return ["selection_faces", "picking_selected"] + + def _updateIgnoreUnselectedObjects(self): + if self._controller.getActiveTool() is self: + ignore_unselected_objects = len(Selection.getAllSelectedObjects()) == 1 + CuraApplication.getInstance().getRenderer().getRenderPass("selection").setIgnoreUnselectedObjects(ignore_unselected_objects) + CuraApplication.getInstance().getRenderer().getRenderPass("selection_faces").setIgnoreUnselectedObjects(ignore_unselected_objects) \ No newline at end of file diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 61a6d0079c..a3d4b36315 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -13,7 +13,6 @@ from plugins.SolidView.SolidView import SolidView from UM.PluginRegistry import PluginRegistry from UM.View.GL.ShaderProgram import ShaderProgram from UM.View.GL.Texture import Texture -from UM.View.SelectionPass import SelectionPass from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.Selection import Selection from UM.View.GL.OpenGL import OpenGL @@ -187,10 +186,6 @@ class PaintView(SolidView): paint_batch = renderer.createRenderBatch(shader=self._paint_shader) renderer.addRenderBatch(paint_batch) - selection_pass = cast(SelectionPass, renderer.getRenderPass("selection")) - if selection_pass is not None: - selection_pass.setIgnoreUnselectedObjectsDuringNextRender() - for node in display_objects: paint_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix()) self._current_paint_texture = node.callDecoration("getPaintTexture") diff --git a/plugins/SupportEraser/SupportEraser.py b/plugins/SupportEraser/SupportEraser.py index 0a714396aa..afdad6a4d0 100644 --- a/plugins/SupportEraser/SupportEraser.py +++ b/plugins/SupportEraser/SupportEraser.py @@ -1,6 +1,8 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +from typing import Optional + from PyQt6.QtCore import Qt, QTimer from PyQt6.QtWidgets import QApplication @@ -35,6 +37,7 @@ class SupportEraser(Tool): self._controller = self.getController() self._selection_pass = None + self._picking_pass: Optional[PickingPass] = None CuraApplication.getInstance().globalContainerStackChanged.connect(self._updateEnabled) # Note: if the selection is cleared with this tool active, there is no way to switch to @@ -84,12 +87,13 @@ class SupportEraser(Tool): # Only "normal" meshes can have anti_overhang_meshes added to them return - # Create a pass for picking a world-space location from the mouse location - active_camera = self._controller.getScene().getActiveCamera() - picking_pass = PickingPass(active_camera.getViewportWidth(), active_camera.getViewportHeight()) - picking_pass.render() + # Get the pass for picking a world-space location from the mouse location + if self._picking_pass is None: + self._picking_pass = Application.getInstance().getRenderer().getRenderPass("picking_selected") + if not self._picking_pass: + return - picked_position = picking_pass.getPickedPosition(event.x, event.y) + picked_position = self._picking_pass.getPickedPosition(event.x, event.y) # Add the anti_overhang_mesh cube at the picked location self._createEraserMesh(picked_node, picked_position) @@ -189,3 +193,6 @@ class SupportEraser(Tool): mesh.calculateNormals() return mesh + + def getRequiredExtraRenderingPasses(self) -> list[str]: + return ["picking_selected"] \ No newline at end of file From ea488f02029563c587abdc45bcb30d56377a1ef4 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 1 Aug 2025 14:23:02 +0200 Subject: [PATCH 280/299] Fix wrongly displayed error message CURA-12660 --- cura/XRayPass.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/XRayPass.py b/cura/XRayPass.py index 965294ba89..20fe38741e 100644 --- a/cura/XRayPass.py +++ b/cura/XRayPass.py @@ -16,7 +16,7 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator class XRayPass(RenderPass): def __init__(self, width, height): - super().__init__("xray", width, height) + super().__init__("xray", width, height, -100) self._shader = None self._gl = OpenGL.getInstance().getBindingsObject() From 78daa94ebff6a76b5fa91e59483c6541a9c80a18 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 1 Aug 2025 17:08:53 +0200 Subject: [PATCH 281/299] Save and restore painting tool settings CURA-12660 --- plugins/PaintTool/BrushColorButton.qml | 22 ++++++++++--- plugins/PaintTool/BrushShapeButton.qml | 22 ++++++++++--- plugins/PaintTool/PaintModeButton.qml | 23 +++++++++++--- plugins/PaintTool/PaintTool.py | 43 ++++++++++++++++++++------ plugins/PaintTool/PaintTool.qml | 20 ++++-------- plugins/PaintTool/PaintView.py | 22 +++++++++---- plugins/SolidView/SolidView.py | 5 +-- 7 files changed, 113 insertions(+), 44 deletions(-) diff --git a/plugins/PaintTool/BrushColorButton.qml b/plugins/PaintTool/BrushColorButton.qml index 71556f2681..ae4ab6243f 100644 --- a/plugins/PaintTool/BrushColorButton.qml +++ b/plugins/PaintTool/BrushColorButton.qml @@ -13,13 +13,27 @@ UM.ToolbarButton property string color - checked: base.selectedColor === buttonBrushColor.color - onClicked: setColor() function setColor() { - base.selectedColor = buttonBrushColor.color - UM.Controller.triggerActionWithData("setBrushColor", buttonBrushColor.color) + UM.Controller.setProperty("BrushColor", buttonBrushColor.color); + } + + function isChecked() + { + return UM.Controller.properties.getValue("BrushColor") === buttonBrushColor.color; + } + + Component.onCompleted: + { + buttonBrushColor.checked = isChecked(); + } + + Binding + { + target: buttonBrushColor + property: "checked" + value: isChecked() } } diff --git a/plugins/PaintTool/BrushShapeButton.qml b/plugins/PaintTool/BrushShapeButton.qml index 5c290e4a13..ef4256792a 100644 --- a/plugins/PaintTool/BrushShapeButton.qml +++ b/plugins/PaintTool/BrushShapeButton.qml @@ -13,13 +13,27 @@ UM.ToolbarButton property int shape - checked: base.selectedShape === buttonBrushShape.shape - onClicked: setShape() function setShape() { - base.selectedShape = buttonBrushShape.shape - UM.Controller.triggerActionWithData("setBrushShape", buttonBrushShape.shape) + UM.Controller.setProperty("BrushShape", buttonBrushShape.shape) + } + + function isChecked() + { + return UM.Controller.properties.getValue("BrushShape") === buttonBrushShape.shape; + } + + Component.onCompleted: + { + buttonBrushShape.checked = isChecked(); + } + + Binding + { + target: buttonBrushShape + property: "checked" + value: isChecked() } } diff --git a/plugins/PaintTool/PaintModeButton.qml b/plugins/PaintTool/PaintModeButton.qml index 473996e04b..eb294f7ad6 100644 --- a/plugins/PaintTool/PaintModeButton.qml +++ b/plugins/PaintTool/PaintModeButton.qml @@ -6,19 +6,34 @@ import QtQuick import UM 1.7 as UM import Cura 1.0 as Cura + Cura.ModeSelectorButton { id: modeSelectorButton property string mode - selected: base.selectedMode === modeSelectorButton.mode - onClicked: setMode() function setMode() { - base.selectedMode = modeSelectorButton.mode - UM.Controller.triggerActionWithData("setPaintType", modeSelectorButton.mode) + UM.Controller.setProperty("PaintType", modeSelectorButton.mode); + } + + function isSelected() + { + return UM.Controller.properties.getValue("PaintType") === modeSelectorButton.mode; + } + + Component.onCompleted: + { + modeSelectorButton.selected = isSelected(); + } + + Binding + { + target: modeSelectorButton + property: "selected" + value: isSelected() } } diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index e57c6d5a11..a1812a5766 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -45,8 +45,8 @@ class PaintTool(Tool): self._cache_dirty: bool = True self._brush_size: int = 10 - self._brush_color: str = "" - self._brush_shape: PaintTool.Brush.Shape = PaintTool.Brush.Shape.SQUARE + self._brush_color: str = "preferred" + self._brush_shape: PaintTool.Brush.Shape = PaintTool.Brush.Shape.CIRCLE self._brush_pen: QPen = self._createBrushPen() self._mouse_held: bool = False @@ -55,6 +55,8 @@ class PaintTool(Tool): self._last_mouse_coords: Optional[Tuple[int, int]] = None self._last_face_id: Optional[int] = None + self.setExposedProperties("PaintType", "BrushSize", "BrushColor", "BrushShape") + Selection.selectionChanged.connect(self._updateIgnoreUnselectedObjects) def _createBrushPen(self) -> QPen: @@ -91,28 +93,51 @@ class PaintTool(Tool): return stroke_image, (start_x, start_y) + def getPaintType(self) -> str: + paint_view = self._get_paint_view() + if paint_view is None: + return "" + + return paint_view.getPaintType() + def setPaintType(self, paint_type: str) -> None: paint_view = self._get_paint_view() if paint_view is None: return - paint_view.setPaintType(paint_type) + if paint_type != self.getPaintType(): + paint_view.setPaintType(paint_type) - self._brush_pen = self._createBrushPen() - self._updateScene() + self._brush_pen = self._createBrushPen() + self._updateScene() + self.propertyChanged.emit() + + def getBrushSize(self) -> int: + return self._brush_size def setBrushSize(self, brush_size: float) -> None: - if brush_size != self._brush_size: - self._brush_size = int(brush_size) + brush_size_int = int(brush_size) + if brush_size_int != self._brush_size: + self._brush_size = brush_size_int self._brush_pen = self._createBrushPen() + self.propertyChanged.emit() + + def getBrushColor(self) -> str: + return self._brush_color def setBrushColor(self, brush_color: str) -> None: - self._brush_color = brush_color + if brush_color != self._brush_color: + self._brush_color = brush_color + self.propertyChanged.emit() + + def getBrushShape(self) -> int: + return self._brush_shape def setBrushShape(self, brush_shape: int) -> None: if brush_shape != self._brush_shape: self._brush_shape = brush_shape self._brush_pen = self._createBrushPen() + self.propertyChanged.emit() def undoStackAction(self, redo_instead: bool) -> bool: paint_view = self._get_paint_view() @@ -251,13 +276,11 @@ class PaintTool(Tool): # Make sure the displayed values are updated if the bounding box of the selected mesh(es) changes if event.type == Event.ToolActivateEvent: - controller.setActiveStage("PrepareStage") controller.setActiveView("PaintTool") # Because that's the plugin-name, and the view is registered to it. self._updateIgnoreUnselectedObjects() return True if event.type == Event.ToolDeactivateEvent: - controller.setActiveStage("PrepareStage") controller.setActiveView("SolidView") CuraApplication.getInstance().getRenderer().getRenderPass("selection").setIgnoreUnselectedObjects(False) CuraApplication.getInstance().getRenderer().getRenderPass("selection_faces").setIgnoreUnselectedObjects(False) diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index e3f244dd4c..94642b1f66 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -15,10 +15,6 @@ Item height: childrenRect.height UM.I18nCatalog { id: catalog; name: "cura"} - property string selectedMode: "" - property string selectedColor: "" - property int selectedShape: 0 - Action { id: undoAction @@ -167,15 +163,19 @@ Item from: 1 to: 40 - value: 10 onPressedChanged: function(pressed) { if(! pressed) { - UM.Controller.triggerActionWithData("setBrushSize", shapeSizeSlider.value) + UM.Controller.setProperty("BrushSize", shapeSizeSlider.value); } } + + Component.onCompleted: + { + shapeSizeSlider.value = UM.Controller.properties.getValue("BrushSize"); + } } //Line between the sections. @@ -227,12 +227,4 @@ Item } } } - - Component.onCompleted: - { - // Force first types for consistency, otherwise UI may become different from controller - rowPaintMode.children[0].setMode() - rowBrushColor.children[1].setColor() - rowBrushShape.children[1].setShape() - } } diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index a3d4b36315..c723f4321d 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -60,6 +60,8 @@ class PaintView(SolidView): "support": usual_types, } + self._current_paint_type = "seam" + def _checkSetup(self): super()._checkSetup() @@ -82,6 +84,8 @@ class PaintView(SolidView): if self._current_paint_texture is None or self._current_paint_texture.getImage() is None: return + self._prepareDataMapping() + actual_image = self._current_paint_texture.getImage() bit_range_start, bit_range_end = self._current_bits_ranges @@ -141,20 +145,26 @@ class PaintView(SolidView): return self._current_paint_texture.getWidth(), self._current_paint_texture.getHeight() return 0, 0 + def getPaintType(self) -> str: + return self._current_paint_type + def setPaintType(self, paint_type: str) -> None: + self._current_paint_type = paint_type + self._prepareDataMapping() + + def _prepareDataMapping(self): node = Selection.getAllSelectedObjects()[0] if node is None: return paint_data_mapping = node.callDecoration("getTextureDataMapping") - if paint_type not in paint_data_mapping: - new_mapping = self._add_mapping(paint_data_mapping, len(self._paint_modes[paint_type])) - paint_data_mapping[paint_type] = new_mapping + if self._current_paint_type not in paint_data_mapping: + new_mapping = self._add_mapping(paint_data_mapping, len(self._paint_modes[self._current_paint_type])) + paint_data_mapping[self._current_paint_type] = new_mapping node.callDecoration("setTextureDataMapping", paint_data_mapping) - self._current_paint_type = paint_type - self._current_bits_ranges = paint_data_mapping[paint_type] + self._current_bits_ranges = paint_data_mapping[self._current_paint_type] @staticmethod def _add_mapping(actual_mapping: Dict[str, tuple[int, int]], nb_storable_values: int) -> tuple[int, int]: @@ -167,7 +177,7 @@ class PaintView(SolidView): return start_index, end_index def beginRendering(self) -> None: - if self._current_paint_type == "": + if self._current_paint_type not in self._paint_modes: return display_objects = Selection.getAllSelectedObjects().copy() diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index bffc3aa526..e25273cb13 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -289,8 +289,9 @@ class SolidView(View): def endRendering(self): # check whether the xray overlay is showing badness - if time.time() > self._next_xray_checking_time\ - and Application.getInstance().getPreferences().getValue(self._show_xray_warning_preference): + if (time.time() > self._next_xray_checking_time + and Application.getInstance().getPreferences().getValue(self._show_xray_warning_preference) + and self._xray_pass is not None): self._next_xray_checking_time = time.time() + self._xray_checking_update_time xray_img = self._xray_pass.getOutput() From f6486bdffcf06984ea613fce22c3fac31be3bc79 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Fri, 1 Aug 2025 14:28:38 -0400 Subject: [PATCH 282/299] Update DisplayInfoOnLCD.py If the printer was a UM then the statistics and model list weren't being added. This is the fix. --- plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index ddf292fb85..a7578e3565 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -40,6 +40,7 @@ import datetime import math from UM.Preferences import Preferences from UM.Message import Message +from UM.Logger import Logger class DisplayInfoOnLCD(Script): @@ -272,7 +273,7 @@ class DisplayInfoOnLCD(Script): self.m73_str = "" para_1 = data[0].split("\n") for line in para_1: - if line.startswith(";TIME:"): + if line.startswith(";TIME:") or line.startswith(";PRINT.TIME:"): self.time_total = int(line.split(":")[1]) break if display_option == "filename_layer": @@ -693,8 +694,8 @@ class DisplayInfoOnLCD(Script): # Add the stats to the gcode file lines = data[0].split("\n") for index, line in enumerate(lines): - if line.startswith(";Layer height:"): - lines[index] = ";Layer height: " + f"{float(line.split(":")[1]):.2f}".format(float(line.split(":")[1])) + if line.startswith(";Layer height:") or line.startswith(";TARGET_MACHINE.NAME:"): + lines[index] = ";Layer height: " + f"{global_stack.getProperty("layer_height", "value")}" lines[index] += f"\n{init_layer_hgt_line}" lines[index] += f"\n;Base Quality Name : '{global_stack.quality.getMetaDataEntry("name", "")}'" lines[index] += f"\n;Custom Quality Name: '{global_stack.qualityChanges.getMetaDataEntry("name")}'" From 8c3c36b241819a662f4fc97346f62990cd3ed047 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 2 Aug 2025 14:04:29 -0400 Subject: [PATCH 283/299] Update DisplayInfoOnLCD.py Changes per Reviewer request. --- plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index a7578e3565..edfa9d8632 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -38,9 +38,7 @@ from UM.Qt.Duration import DurationFormat import time import datetime import math -from UM.Preferences import Preferences from UM.Message import Message -from UM.Logger import Logger class DisplayInfoOnLCD(Script): @@ -286,6 +284,7 @@ class DisplayInfoOnLCD(Script): def _display_filename_layer(self, data: str) -> str: data[0] = self._add_stats(data) max_layer = 0 + format_option = self.getSettingValueByKey("format_option") lcd_text = "M117 " octo_text = "M118 " if self.getSettingValueByKey("file_name") != "": @@ -295,7 +294,7 @@ class DisplayInfoOnLCD(Script): if self.getSettingValueByKey("addPrefixPrinting"): lcd_text += "Printing " octo_text += "Printing " - if not self.getSettingValueByKey("scroll"): + if not format_option: lcd_text += "Lay " octo_text += "Layer " else: @@ -317,11 +316,11 @@ class DisplayInfoOnLCD(Script): if self.getSettingValueByKey("maxlayer"): display_text += "/" + max_layer self.m118_text += "/" + max_layer - if not self.getSettingValueByKey("scroll"): + if not format_option: display_text += "|" + file_name self.m118_text += " | " + file_name else: - if not self.getSettingValueByKey("scroll"): + if not format_option: display_text += "|" + file_name + "!" self.m118_text += " | " + file_name + "!" else: From 8353d55ce2b2d5e090ebf6a5922af5dffd2875dc Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 2 Aug 2025 14:32:00 -0400 Subject: [PATCH 284/299] Create AnnealingOrDrying.py A new script. The user can hold the build plate and chamber temepratures to "anneal" a print. Optionally the heated be can be used to attempt to dry filament rolls. --- .../scripts/AnnealingOrDrying.py | 513 ++++++++++++++++++ 1 file changed, 513 insertions(+) create mode 100644 plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py diff --git a/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py b/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py new file mode 100644 index 0000000000..6d6775c6ea --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py @@ -0,0 +1,513 @@ +""" +Copyright (c) 2025 GregValiant (Greg Foresi) + + When Annealing: + The user may elect to hold the build plate at a temperature for a period of time. When the hold expires, the 'Timed Cooldown' will begin. + If there is no 'Hold Time' then the 'Annealing' cooldown will begin when the print ends. In 'Annealing' cooldown the bed temperature drops in 3° increments across the time span. + G4 commands are used for the cooldown steps. + If there is a 'Heated Chamber' then the chamber will start to cool when the bed temperature reaches the chamber temperature. + + When drying filament: + The bed must be empty because the printer will auto-home before raising the Z to 'machine_height minus 20mm' and then park the head in the XY. + The bed will heat up to the set point. + G4 commands are used to keep the machine from turning the bed off until the Drying Time has expired. + If you happen to have an enclosure with a fan, the fan can be set up to run during the drying or annealing. + + NOTE: This script uses the G4 Dwell command as a timer. It cannot be canceled from the LCD. If you wish to ;excape' from G4 you might have to cancel the print from the LCD or cycle the printer on and off to reset. +""" + +from UM.Application import Application +from ..Script import Script +from UM.Message import Message + +class AnnealingOrDrying(Script): + + def initialize(self) -> None: + super().initialize() + # Get the Bed Temperature from Cura + bed_temp = str(Application.getInstance().getGlobalContainerStack().getProperty("material_bed_temperature", "value")) + self._instance.setProperty("startout_temp", "value", bed_temp) + # Get the Build Volume temperature if there is one + heated_build_volume = bool(Application.getInstance().getGlobalContainerStack().getProperty("machine_heated_build_volume", "value")) + curaApp = Application.getInstance().getGlobalContainerStack() + chamber_fan_nr = curaApp.getProperty("build_volume_fan_nr", "value") + extruder_count = curaApp.getProperty("machine_extruder_count", "value") + if heated_build_volume: + chamber_temp = curaApp.getProperty("build_volume_temperature", "value") + self._instance.setProperty("has_build_volume_heater", "value", heated_build_volume) + self._instance.setProperty("build_volume_temp", "value", chamber_temp) + try: + if chamber_fan_nr > 0: + self._instance.setProperty("enable_chamber_fan_setting", "value", True) + except: + pass + + def getSettingDataString(self): + return """{ + "name": "Annealing CoolDown or Filament Drying", + "key": "AnnealingOrDrying", + "metadata": {}, + "version": 2, + "settings": + { + "enable_annealing": + { + "label": "Enable the Script", + "description": "If it isn't enabled it doesn't run.", + "type": "bool", + "default_value": true, + "enabled": true + }, + "cycle_type": + { + "label": "Anneal Print or Dry Filament", + "description": "Whether to Anneal the Print (by keeping the bed hot for a period of time), or to use the bed as a Filament Dryer. If drying; you will still need to slice a model, but it will not print. The gcode will consist only of a short script to heat the bed, wait for a while, then turn the bed off. The 'Z' will move to the max height and XY park position so the filament can be covered. The 'Hold Time', 'Bed Start Temp' and (if applicable) the 'Chamber Temp' come from these settings rather than from the Cura settings. When annealing; the Timed Cooldown will commence when the print ends.", + "type": "enum", + "options": + { + + "anneal_cycle": "Anneal Print", + "dry_cycle": "Dry Filament"}, + "default_value": "anneal_cycle", + "enabled": true, + "enabled": "enable_annealing" + }, + "bed_and_chamber": + { + "label": "Hold the Temp for the:", + "description": "Select the 'Bed' for just the bed, or 'Bed and Chamber' if you want to include your 'Heated Build Volume'.", + "type": "enum", + "options": + { + "bed_only": "Bed", + "bed_chamber": "Bed and Chamber"}, + "default_value": "bed_only", + "enabled": "enable_annealing" + }, + "wait_time": + { + "label": "Hold Time at Temp(s)", + "description": "Hold the bed temp at the 'Bed Start Out Temperature' for this amount of time (in decimal hours). When this time expires then the Annealing cool down will start. This is also the 'Drying Time' used when 'Drying Filament'.", + "type": "float", + "default_value": 0.0, + "unit": "Decimal Hrs ", + "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + }, + "dry_time": + { + "label": "Drying Time", + "description": "Hold the bed temp at the 'Bed Start Out Temperature' for this amount of time (in decimal hours). When this time expires the bed will shut off.", + "type": "float", + "default_value": 4.0, + "unit": "Decimal Hrs ", + "enabled": "enable_annealing and cycle_type == 'dry_cycle'" + }, + "pause_cmd": + { + "label": "Pause Cmd for Auto-Home", + "description": "Not required when you are paying attention and the bed is empty; ELSE; Enter the pause command to use prior to the Auto-Home command. The pause insures that the user IS paying attention and clears the build plate for Auto-Home. If you leave the box empty then there won't be a pause.", + "type": "str", + "default_value": "", + "enabled": "enable_annealing and cycle_type == 'dry_cycle'" + }, + "startout_temp": + { + "label": "Bed Start Out Temperature:", + "description": "Enter the temperature to start at. This is typically the bed temperature during the print but can be changed here. This is also the temperature used when drying filament.", + "type": "int", + "value": 30, + "unit": "Degrees ", + "minimum_value": 30, + "maximum_value": 110, + "maximum_value_warning": 100, + "enabled": "enable_annealing" + }, + "lowest_temp": + { + "label": "Shut-Off Temp:", + "description": "Enter the lowest temperature to control the cool down. This is the shut-off temperature for the build plate and (when applicable) the Heated Chamber. The minimum value is 30", + "type": "int", + "default_value": 30, + "unit": "Degrees ", + "minimum_value": 30, + "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + }, + "build_volume_temp": + { + "label": "Build Volume Temperature:", + "description": "Enter the temperature for the Build Volume (Heated Chamber). This is typically the temperature during the print but can be changed here.", + "type": "int", + "value": 24, + "unit": "Degrees ", + "minimum_value": 0, + "maximum_value": 90, + "maximum_value_warning": 75, + "enabled": "enable_annealing and has_build_volume_heater and bed_and_chamber == 'bed_chamber'" + }, + "enable_chamber_fan_setting": + { + "label": "Hidden Setting", + "description": "Enables chamber fan and speed.", + "type": "bool", + "default_value": false, + "enabled": false + }, + "chamber_fan_speed": + { + "label": "Chamber Fan Speed", + "description": "Set to % fan speed. Set to 0 to turn it off.", + "type": "int", + "default_value": 0, + "minimum_value": 0, + "maximum_value": 100, + "enabled": "enable_annealing and enable_chamber_fan_setting" + }, + "time_span": + { + "label": "Cool Down Time Span:", + "description": "The total amount of time (in decimal hours) to control the cool down. The build plate temperature will be dropped in 3° increments across this time span. 'Cool Down Time' starts at the end of the 'Hold Time' if you entered one.", + "type": "float", + "default_value": 1.0, + "unit": "Decimal Hrs ", + "minimum_value_warning": 0.25, + "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + }, + "park_head": + { + "label": "Park at MaxX and MaxY", + "description": "When unchecked, the park position is X0 Y0. Enable this setting to move the nozzle to the Max X and Max Y to allow access to the print.", + "type": "bool", + "default_value": false, + "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + }, + "park_max_z": + { + "label": "Move to MaxZ", + "description": "Enable this setting to move the nozzle to 'Machine_Height - 20' to allow the print to be covered.", + "type": "bool", + "default_value": false, + "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + }, + "beep_when_done": + { + "label": "Beep when done", + "description": "Add an annoying noise when the Cool Down completes.", + "type": "bool", + "default_value": true, + "enabled": "enable_annealing" + }, + "beep_duration": + { + "label": "Beep Duration", + "description": "The length of the buzzer sound. Units are in milliseconds so 1000ms = 1 second.", + "type": "int", + "unit": "milliseconds ", + "default_value": 1000, + "enabled": "beep_when_done and enable_annealing" + }, + "add_messages": + { + "label": "Include M117 and M118 messages", + "description": "Add messages to the LCD and any print server.", + "type": "bool", + "default_value": false, + "enabled": "enable_annealing" + }, + "has_build_volume_heater": + { + "label": "Hidden setting", + "description": "Hidden. This setting enables the build volume settings.", + "type": "bool", + "default_value": false, + "enabled": false + } + } + }""" + + def execute(self, data): + # Exit if there is no heated bed. + if not bool(Application.getInstance().getGlobalContainerStack().getProperty("machine_heated_bed", "value")): + Message(title = "[Anneal or Dry Filament]", text = "The script did not run because Heated Bed is disabled in Machine Settings.").show() + return data + # Enter a message in the gcode if the script is not enabled. + if not bool(self.getSettingValueByKey("enable_annealing")): + data[0] += "; [Anneal or Dry Filament] was not enabled\n" + return data + lowest_temp = int(self.getSettingValueByKey("lowest_temp")) + + # If the shutoff temp is under 30° then exit as a safety precaution so the bed doesn't stay on. + if lowest_temp < 30: + data[0] += "; Anneal or Dry Filament did not run. Shutoff Temp < 30\n" + Message(title = "[Anneal or Dry Filament]", text = "The script did not run because the Shutoff Temp is less than 30°.").show() + return data + self.global_stack = Application.getInstance().getGlobalContainerStack() + extruder = self.global_stack.extruderList + bed_temperature = int(self.getSettingValueByKey("startout_temp")) + heated_chamber = bool(Application.getInstance().getGlobalContainerStack().getProperty("machine_heated_build_volume", "value")) + anneal_type = self.getSettingValueByKey("bed_and_chamber") + + # Get the heated chamber temperature or set to 0 if no chamber + if heated_chamber: + chamber_temp = str(self.getSettingValueByKey("build_volume_temp")) + else: + anneal_type = "bed_only" + chamber_temp = "0" + + # For compatibility with earlier Cura versions + if self.global_stack.getProperty("build_volume_fan_nr", "value") is not None: + has_bv_fan = bool(self.global_stack.getProperty("build_volume_fan_nr", "value")) + bv_fan_nr = int(self.global_stack.getProperty("build_volume_fan_nr", "value")) + if bv_fan_nr > 0: + speed_bv_fan = int(self.getSettingValueByKey("chamber_fan_speed")) + else: + speed_bv_fan = 0 + + if bool(extruder[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) and has_bv_fan: + speed_bv_fan = round(speed_bv_fan * .01) + else: + speed_bv_fan = round(speed_bv_fan * 2.55) + + if has_bv_fan and speed_bv_fan > 0: + self.bv_fan_on_str = f"M106 S{speed_bv_fan} P{bv_fan_nr} ; Build Chamber Fan On\n" + self.bv_fan_off_str = f"M106 S0 P{bv_fan_nr} ; Build Chamber Fan Off\n" + else: + self.bv_fan_on_str = "" + self.bv_fan_off_str = "" + else: + has_bv_fan = False + bv_fan_nr = 0 + speed_bv_fan = 0 + self.bv_fan_on_str = "" + self.bv_fan_off_str = "" + + # Park Head + max_y = str(self.global_stack.getProperty("machine_depth", "value")) + max_x = str(self.global_stack.getProperty("machine_width", "value")) + # Max_z is limited to 'machine_height - 20' just so the print head doesn't smack into anything. + max_z = str(int(self.global_stack.getProperty("machine_height", "value")) - 20) + speed_travel = str(round(extruder[0].getProperty("speed_travel", "value")*60)) + park_xy = bool(self.getSettingValueByKey("park_head")) + park_z = bool(self.getSettingValueByKey("park_max_z")) + cycle_type = self.getSettingValueByKey("cycle_type") + add_messages = bool(self.getSettingValueByKey("add_messages")) + + if cycle_type == "anneal_cycle": + data = self._anneal_print(data, park_xy, park_z, bed_temperature, lowest_temp, heated_chamber, chamber_temp, max_y, max_x, max_z, speed_travel, add_messages, anneal_type) + elif cycle_type == "dry_cycle": + data = self._dry_filament_only(data, anneal_type, heated_chamber, chamber_temp, bed_temperature, max_z, max_y, speed_travel) + return data + + def _anneal_print(self, anneal_data: str, park_xy: bool, park_z: bool, bed_temperature:int, lowest_temp: int, heated_chamber: bool, chamber_temp: str, max_x: str, max_y: str, max_z: str, speed_travel: str, add_messages: bool, anneal_type: str): + """ + The procedure disables the M140 (and M141) lines at the end of the print, and adds additional bed (and chamber) temperature commands to the end of the G-Code file. The bed is allowed to cool down over a period of time. + """ + # Put the head parking string together + time_minutes = 1 + time_span = int(float(self.getSettingValueByKey("time_span")) * 3600) + park_string = "" + if park_xy and not park_z: + park_string = f"G0 F{speed_travel} X{max_x} Y{max_y} ; Park XY\nM84 X Y E ; Disable steppers except Z\n" + elif park_xy and park_z: + park_string = f"G0 F{speed_travel} X{max_x} Y{max_y} ; Park XY\nG0 Z{max_z} ; Raise Z to 'ZMax - 20'\nM84 X Y E ; Disable steppers except Z\n" + elif not park_xy and park_z: + park_string = f"G0 F{speed_travel} Z{max_z} ; Raise Z to 'ZMax - 20'\nM84 X Y E ; Disable steppers except Z\n" + elif not park_xy and not park_z: + park_string = f"G91 ; Relative movement\nG0 F{speed_travel} Z5 ; Raise Z\nG90 ; Absolute movement\nG0 X0 Y0 ; Park\nM84 X Y E ; Disable steppers except Z\n" + + # Calculate the temperature differential + hysteresis = bed_temperature - lowest_temp + + # if the bed temp is below the shutoff temp then exit + if hysteresis <= 0: + anneal_data[0] += "; Anneal or Dry Filament did not run. Bed Temp < Shutoff Temp\n" + Message(title = "Anneal or Dry Filament", text = "Did not run because the Bed Temp < Shutoff Temp.").show() + return anneal_data + + # Drop the bed temperature in 3° increments. + num_steps = int(hysteresis / 3) + step_index = 2 + deg_per_step = int(hysteresis / num_steps) + time_per_step = int(time_span / num_steps) + step_down = bed_temperature + wait_time = int(float(self.getSettingValueByKey("wait_time")) * 3600) + + # Put the first lines of the anneal string together + anneal_string = ";\n;TYPE:CUSTOM ---------------- Anneal Print\n" + if add_messages: + anneal_string += "M117 Cool Down for " + str(round((wait_time + time_span)/3600,2)) + "hr\n" + anneal_string += "M118 Cool Down for " + str(round((wait_time + time_span)/3600,2)) + "hr\n" + anneal_string += self.bv_fan_on_str + if wait_time > 0: + # Move the head before the M190 + anneal_string += park_string + if anneal_type == "bed_only": + anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\n" + if anneal_type == "bed_chamber": + anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\nM141 S{chamber_temp} ; Set the chamber temp\n" + anneal_string += f"G4 S{wait_time} ; Hold for {round(wait_time / 3600,2)} hrs\n" + else: + # Move the head after the M140 + anneal_string += f"M140 S{step_down} ; Set bed temp\n" + anneal_string += park_string + anneal_string += f"G4 S{time_per_step} ; wait time in seconds\n" + step_down -= deg_per_step + + time_remaining = round(time_span/3600,2) + # Step the bed/chamber temps down and add each step to the anneal string. The chamber remains at it's temperature until the bed gets down to that temperature. + for num in range(bed_temperature, lowest_temp, -3): + anneal_string += f"M140 S{step_down} ; Step down bed\n" + if anneal_type == "bed_chamber" and int(step_down) < int(chamber_temp): + anneal_string += f"M141 S{step_down} ; Step down chamber\n" + anneal_string += f"G4 S{time_per_step} ; Wait\n" + #time_remaining = round((time_span-(step_index*time_per_step))/3600,2) + if time_remaining >= 1.00: + if add_messages: + anneal_string += f"M117 CoolDown - {round(time_remaining,1)}hr\n" + anneal_string += f"M118 CoolDown - {round(time_remaining,1)}hr\n" + elif time_minutes > 0: + time_minutes = round(time_remaining * 60,1) + if add_messages: + anneal_string += f"M117 CoolDown - {time_minutes}min\n" + anneal_string += f"M118 CoolDown - {time_minutes}min\n" + time_remaining = round((time_span-(step_index*time_per_step))/3600,2) + step_down -= deg_per_step + step_index += 1 + if step_down <= lowest_temp: + break + + # Beep line + if bool(self.getSettingValueByKey("beep_when_done")): + beep_string = "M300 S440 P" + str(self.getSettingValueByKey("beep_duration")) + " ; Beep\n" + else: + beep_string = "" + + # Close out the anneal string + anneal_string += "M140 S0 ; Shut off the bed heater" + "\n" + if anneal_type == "bed_chamber": + anneal_string += "M141 S0 ; Shut off the chamber heater\n" + anneal_string += self.bv_fan_off_str + anneal_string += beep_string + if add_messages: + anneal_string += "M117 CoolDown Complete\n" + anneal_string += "M118 CoolDown Complete\n" + anneal_string += ";TYPE:CUSTOM ---------------- End of Anneal\n;" + + # Format + anneal_lines = anneal_string.split("\n") + for index, line in enumerate(anneal_lines): + if not line.startswith(";") and ";" in line: + front_txt = anneal_lines[index].split(";")[0] + back_txt = anneal_lines[index].split(";")[1] + anneal_lines[index] = front_txt + str(" " * (30 - len(front_txt))) +";" + back_txt + anneal_string = "\n".join(anneal_lines) + "\n" + + layer = anneal_data[len(anneal_data)-1] + lines = layer.split("\n") + + # Comment out the M140 S0 line in the ending gcode. + for num in range(len(lines)-1,-1,-1): + if lines[num].startswith("M140 S0"): + lines[num] = ";M140 S0 ; Shutoff Overide - Anneal or Dry Filament" + anneal_data[len(anneal_data)-1] = "\n".join(lines) + + # If there is a Heated Chamber and it's included then comment out the M141 S0 line + if anneal_type == "bed_chamber" and heated_chamber: + for num in range(0,len(lines)-1,1): + if lines[num].startswith("M141 S0"): + lines[num] = ";M141 S0 ; Shutoff Overide - Anneal or Dry Filament" + anneal_data[len(anneal_data)-1] = "\n".join(lines) + + # If park head is enabled then dont let the steppers disable until the head is parked + disable_string = "" + for num in range(0,len(lines)-1,1): + if lines[num][:3] in ("M84", "M18"): + disable_string = lines[num] + "\n" + stepper_timeout = int(wait_time + time_span) + if stepper_timeout > 14400: stepper_timeout = 14400 + lines[num] = ";" + lines[num] + " ; Overide - Anneal or Dry Filament" + lines.insert(num, "M84 S" + str(stepper_timeout) + " ; Increase stepper timeout - Anneal or Dry Filament") + anneal_data[len(anneal_data)-1] = "\n".join(lines) + break + + # The Anneal string is the new end of the gcode so move the 'End of Gcode' comment line in case there are other scripts running + anneal_data[len(anneal_data)-1] = anneal_data[len(anneal_data)-1].replace(";End of Gcode", anneal_string + disable_string + ";End of Gcode") + return anneal_data + + def _dry_filament_only(self, drydata: str, anneal_type: str, heated_chamber: bool, chamber_temp: int, bed_temperature: int, max_z:str, max_y:str, speed_travel: str) -> str: + """ + This procedure turns the bed on, homes the printer, parks the head. After the time period the bed is turned off. There is no actual print in the generated gcode, just a couple of moves to get the nozzle out of the way, and the bed heat (and possibly chamber heat) control. It allows a user to use the bed to warm up and hopefully dry a filament roll. + """ + for num in range(2, len(drydata)): + drydata[num] = "" + drydata[0] = drydata[0].split("\n")[0] + "\n" + add_messages = bool(self.getSettingValueByKey("add_messages")) + pause_cmd = self.getSettingValueByKey("pause_cmd").upper() + if pause_cmd != "": + pause_cmd = "M300 ; Beep\n" + pause_cmd + dry_time = self.getSettingValueByKey("dry_time") * 3600 + lines = drydata[1].split("\n") + drying_string = lines[0] + "\n" + ";............TYPE:CUSTOM: Dry Filament\n" + if add_messages: + drying_string += f"M117 Cool Down for {round(dry_time/3600,2)} hr ; Message\n" + drying_string += f"M118 Cool Down for {round(dry_time/3600,2)} hr ; Message\n" + # M113 sends messages to a print server as a 'Keep Alive' and can generate a lot of traffic over the USB + drying_string += "M113 S0 ; No echo\n" + drying_string += f"M84 S{round(dry_time)} ; Set stepper timeout\n" + drying_string += f"M140 S{bed_temperature} ; Heat bed\n" + drying_string += self.bv_fan_on_str + if heated_chamber and anneal_type == "bed_chamber": + drying_string += f"M141 S{chamber_temp} ; Chamber temp\n" + if pause_cmd == "M0": + pause_cmd = "M0 Clear bed and click...; Pause" + if pause_cmd != "": + drying_string += pause_cmd + " ; Pause\n" + drying_string += "G28 ; Auto-Home\n" + drying_string += f"G0 F{speed_travel} Z{max_z} ; Raise Z to 'ZMax - 20'\n" + drying_string += f"G0 F{speed_travel} X0 Y{max_y} ; Park print head\n" + if dry_time <= 3600: + if add_messages: + drying_string += f"M117 {dry_time/3600} hr remaining ; Message\n" + drying_string += f"M118 {dry_time/3600} hr remaining ; Message\n" + drying_string += f"G4 S{dry_time} ; Dry time\n" + elif dry_time > 3600: + temp_time = dry_time + while temp_time > 3600: + if add_messages: + drying_string += f"M117 {temp_time/3600} hr remaining ; Message\n" + drying_string += f"M118 {temp_time/3600} hr remaining ; Message\n" + drying_string += f"G4 S3600 ; Dry time split\n" + if temp_time > 3600: + temp_time -= 3600 + if temp_time > 0: + if add_messages: + drying_string += f"M117 {temp_time/3600} hr remaining ; Message\n" + drying_string += f"M118 {temp_time/3600} hr remaining ; Message\n" + drying_string += f"G4 S{temp_time} ; Dry time\n" + if heated_chamber and anneal_type == "bed_chamber": + drying_string += f"M141 S0 ; Shut off chamber\n" + drying_string += "M140 S0 ; Shut off bed\n" + drying_string += self.bv_fan_off_str + if self.getSettingValueByKey("beep_when_done"): + beep_duration = self.getSettingValueByKey("beep_duration") + drying_string += f"M300 P{beep_duration} ; Beep\n" + if add_messages: + drying_string += "M117 End of drying cycle ; Message\n" + drying_string += "M118 End of drying cycle ; Message\n" + drying_string += "M84 X Y E ; Disable steppers except Z\n" + drying_string += ";End of Gcode" + + # Format + lines = drying_string.split("\n") + for index, line in enumerate(lines): + if not line.startswith(";") and ";" in line: + front_txt = lines[index].split(";")[0] + back_txt = lines[index].split(";")[1] + lines[index] = front_txt + str(" " * (30 - len(front_txt))) +";" + back_txt + drydata[1] = "\n".join(lines) + "\n" + dry_txt = "; Drying time ...................... " + str(self.getSettingValueByKey("dry_time")) + " hrs\n" + dry_txt += "; Drying temperature ........ " + str(bed_temperature) + "°\n" + if heated_chamber and anneal_type == "bed_chamber": + dry_txt += "; Chamber temperature ... " + str(chamber_temp) + "°\n" + Message(title = "[Dry Filament]", text = dry_txt).show() + drydata[0] = "; <<< This is a filament drying file only. There is no actual print. >>>\n;\n" + dry_txt + ";\n" + return drydata \ No newline at end of file From e742ca81f384925473fd219c14f093fd32c86db9 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 4 Aug 2025 10:24:29 +0200 Subject: [PATCH 285/299] Fixed more possible crashes CURA-12528 --- plugins/PaintTool/PaintView.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index c2562fa36a..749fa463e4 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -150,7 +150,9 @@ class PaintView(View): mesh = node.getMeshData() if not mesh.hasUVCoordinates(): texture_width, texture_height = mesh.calculateUnwrappedUVCoordinates() - node.callDecoration("prepareTexture", texture_width, texture_height) + if texture_width > 0 and texture_height > 0: + node.callDecoration("prepareTexture", texture_width, texture_height) + if hasattr(mesh, OpenGL.VertexBufferProperty): # Force clear OpenGL buffer so that new UV coordinates will be sent delattr(mesh, OpenGL.VertexBufferProperty) From 44d6c0a9694d6cb5ddbf78da25735e37a0e8c7e2 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 4 Aug 2025 11:28:31 +0200 Subject: [PATCH 286/299] Call SolidView dynamically instead of by inheritance CURA-12660 The previous method actually doesn't work when Cura is packaged because the plugins paths change. This method is much safer, and uses the actual SolidView instance. --- plugins/PaintTool/PaintView.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index c723f4321d..e4a8b3c493 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -9,8 +9,8 @@ from PyQt6.QtGui import QImage, QColor, QPainter from cura.CuraApplication import CuraApplication from cura.BuildVolume import BuildVolume -from plugins.SolidView.SolidView import SolidView from UM.PluginRegistry import PluginRegistry +from UM.View.View import View from UM.View.GL.ShaderProgram import ShaderProgram from UM.View.GL.Texture import Texture from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator @@ -22,7 +22,7 @@ from UM.Math.Color import Color catalog = i18nCatalog("cura") -class PaintView(SolidView): +class PaintView(View): """View for model-painting.""" UNDO_STACK_SIZE = 1024 @@ -50,6 +50,8 @@ class PaintView(SolidView): application.engineCreatedSignal.connect(self._makePaintModes) self._scene = application.getController().getScene() + self._solid_view = None + def _makePaintModes(self): theme = CuraApplication.getInstance().getTheme() usual_types = {"none": self.PaintType(Color(*theme.getColor("paint_normal_area").getRgb()), 0), @@ -63,8 +65,6 @@ class PaintView(SolidView): self._current_paint_type = "seam" def _checkSetup(self): - super()._checkSetup() - if not self._paint_shader: shader_filename = os.path.join(PluginRegistry.getInstance().getPluginPath("PaintTool"), "paint.shader") self._paint_shader = OpenGL.getInstance().createShaderProgram(shader_filename) @@ -180,10 +180,16 @@ class PaintView(SolidView): if self._current_paint_type not in self._paint_modes: return + if self._solid_view is None: + plugin_registry = PluginRegistry.getInstance() + solid_view = plugin_registry.getPluginObject("SolidView") + if isinstance(solid_view, View): + self._solid_view = solid_view + display_objects = Selection.getAllSelectedObjects().copy() - if len(display_objects) != 1: + if len(display_objects) != 1 and self._solid_view is not None: # Display the classic view until a single object is selected - super().beginRendering() + self._solid_view.beginRendering() return self._checkSetup() From 47ad02bcf1baf4278e15a8879408641f23055fba Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 2 Aug 2025 23:05:32 -0400 Subject: [PATCH 287/299] Update AnnealingOrDrying.py Changed some verbiage. Update AnnealingOrDrying.py Changes per the review, bug fixes, cleanup my code. Add more beeps. Update AnnealingOrDrying.py Fixed a typo --- .../scripts/AnnealingOrDrying.py | 170 +++++++++--------- 1 file changed, 88 insertions(+), 82 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py b/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py index 6d6775c6ea..496fc1cb42 100644 --- a/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py +++ b/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py @@ -3,7 +3,7 @@ Copyright (c) 2025 GregValiant (Greg Foresi) When Annealing: The user may elect to hold the build plate at a temperature for a period of time. When the hold expires, the 'Timed Cooldown' will begin. - If there is no 'Hold Time' then the 'Annealing' cooldown will begin when the print ends. In 'Annealing' cooldown the bed temperature drops in 3° increments across the time span. + If there is no 'Hold Time' then the 'Annealing' cooldown will begin when the print ends. In 'Annealing' the bed temperature drops in 3° increments across the time span. G4 commands are used for the cooldown steps. If there is a 'Heated Chamber' then the chamber will start to cool when the bed temperature reaches the chamber temperature. @@ -12,8 +12,8 @@ Copyright (c) 2025 GregValiant (Greg Foresi) The bed will heat up to the set point. G4 commands are used to keep the machine from turning the bed off until the Drying Time has expired. If you happen to have an enclosure with a fan, the fan can be set up to run during the drying or annealing. - - NOTE: This script uses the G4 Dwell command as a timer. It cannot be canceled from the LCD. If you wish to ;excape' from G4 you might have to cancel the print from the LCD or cycle the printer on and off to reset. + + NOTE: This script uses the G4 Dwell command as a timer. It cannot be canceled from the LCD. If you wish to 'escape' from G4 you might have to cancel the print from the LCD or cycle the printer on and off to reset. """ from UM.Application import Application @@ -25,15 +25,15 @@ class AnnealingOrDrying(Script): def initialize(self) -> None: super().initialize() # Get the Bed Temperature from Cura - bed_temp = str(Application.getInstance().getGlobalContainerStack().getProperty("material_bed_temperature", "value")) - self._instance.setProperty("startout_temp", "value", bed_temp) + self.global_stack = Application.getInstance().getGlobalContainerStack() + bed_temp_during_print = str(self.global_stack.getProperty("material_bed_temperature", "value")) + self._instance.setProperty("startout_temp", "value", bed_temp_during_print) # Get the Build Volume temperature if there is one - heated_build_volume = bool(Application.getInstance().getGlobalContainerStack().getProperty("machine_heated_build_volume", "value")) - curaApp = Application.getInstance().getGlobalContainerStack() - chamber_fan_nr = curaApp.getProperty("build_volume_fan_nr", "value") - extruder_count = curaApp.getProperty("machine_extruder_count", "value") + heated_build_volume = bool(self.global_stack.getProperty("machine_heated_build_volume", "value")) + chamber_fan_nr = self.global_stack.getProperty("build_volume_fan_nr", "value") + extruder_count = self.global_stack.getProperty("machine_extruder_count", "value") if heated_build_volume: - chamber_temp = curaApp.getProperty("build_volume_temperature", "value") + chamber_temp = self.global_stack.getProperty("build_volume_temperature", "value") self._instance.setProperty("has_build_volume_heater", "value", heated_build_volume) self._instance.setProperty("build_volume_temp", "value", chamber_temp) try: @@ -50,7 +50,7 @@ class AnnealingOrDrying(Script): "version": 2, "settings": { - "enable_annealing": + "enable_script": { "label": "Enable the Script", "description": "If it isn't enabled it doesn't run.", @@ -65,14 +65,14 @@ class AnnealingOrDrying(Script): "type": "enum", "options": { - "anneal_cycle": "Anneal Print", - "dry_cycle": "Dry Filament"}, + "dry_cycle": "Dry Filament" + }, "default_value": "anneal_cycle", "enabled": true, - "enabled": "enable_annealing" + "enabled": "enable_script" }, - "bed_and_chamber": + "heating_zone_selection": { "label": "Hold the Temp for the:", "description": "Select the 'Bed' for just the bed, or 'Bed and Chamber' if you want to include your 'Heated Build Volume'.", @@ -82,7 +82,7 @@ class AnnealingOrDrying(Script): "bed_only": "Bed", "bed_chamber": "Bed and Chamber"}, "default_value": "bed_only", - "enabled": "enable_annealing" + "enabled": "enable_script" }, "wait_time": { @@ -91,7 +91,7 @@ class AnnealingOrDrying(Script): "type": "float", "default_value": 0.0, "unit": "Decimal Hrs ", - "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + "enabled": "enable_script and cycle_type == 'anneal_cycle'" }, "dry_time": { @@ -100,7 +100,7 @@ class AnnealingOrDrying(Script): "type": "float", "default_value": 4.0, "unit": "Decimal Hrs ", - "enabled": "enable_annealing and cycle_type == 'dry_cycle'" + "enabled": "enable_script and cycle_type == 'dry_cycle'" }, "pause_cmd": { @@ -108,7 +108,7 @@ class AnnealingOrDrying(Script): "description": "Not required when you are paying attention and the bed is empty; ELSE; Enter the pause command to use prior to the Auto-Home command. The pause insures that the user IS paying attention and clears the build plate for Auto-Home. If you leave the box empty then there won't be a pause.", "type": "str", "default_value": "", - "enabled": "enable_annealing and cycle_type == 'dry_cycle'" + "enabled": "enable_script and cycle_type == 'dry_cycle'" }, "startout_temp": { @@ -120,7 +120,7 @@ class AnnealingOrDrying(Script): "minimum_value": 30, "maximum_value": 110, "maximum_value_warning": 100, - "enabled": "enable_annealing" + "enabled": "enable_script" }, "lowest_temp": { @@ -130,7 +130,7 @@ class AnnealingOrDrying(Script): "default_value": 30, "unit": "Degrees ", "minimum_value": 30, - "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + "enabled": "enable_script and cycle_type == 'anneal_cycle'" }, "build_volume_temp": { @@ -142,7 +142,7 @@ class AnnealingOrDrying(Script): "minimum_value": 0, "maximum_value": 90, "maximum_value_warning": 75, - "enabled": "enable_annealing and has_build_volume_heater and bed_and_chamber == 'bed_chamber'" + "enabled": "enable_script and has_build_volume_heater and heating_zone_selection == 'bed_chamber'" }, "enable_chamber_fan_setting": { @@ -160,7 +160,8 @@ class AnnealingOrDrying(Script): "default_value": 0, "minimum_value": 0, "maximum_value": 100, - "enabled": "enable_annealing and enable_chamber_fan_setting" + "unit": "% ", + "enabled": "enable_script and enable_chamber_fan_setting" }, "time_span": { @@ -170,7 +171,7 @@ class AnnealingOrDrying(Script): "default_value": 1.0, "unit": "Decimal Hrs ", "minimum_value_warning": 0.25, - "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + "enabled": "enable_script and cycle_type == 'anneal_cycle'" }, "park_head": { @@ -178,7 +179,7 @@ class AnnealingOrDrying(Script): "description": "When unchecked, the park position is X0 Y0. Enable this setting to move the nozzle to the Max X and Max Y to allow access to the print.", "type": "bool", "default_value": false, - "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + "enabled": "enable_script and cycle_type == 'anneal_cycle'" }, "park_max_z": { @@ -186,7 +187,7 @@ class AnnealingOrDrying(Script): "description": "Enable this setting to move the nozzle to 'Machine_Height - 20' to allow the print to be covered.", "type": "bool", "default_value": false, - "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + "enabled": "enable_script and cycle_type == 'anneal_cycle'" }, "beep_when_done": { @@ -194,7 +195,7 @@ class AnnealingOrDrying(Script): "description": "Add an annoying noise when the Cool Down completes.", "type": "bool", "default_value": true, - "enabled": "enable_annealing" + "enabled": "enable_script" }, "beep_duration": { @@ -203,7 +204,7 @@ class AnnealingOrDrying(Script): "type": "int", "unit": "milliseconds ", "default_value": 1000, - "enabled": "beep_when_done and enable_annealing" + "enabled": "beep_when_done and enable_script" }, "add_messages": { @@ -211,7 +212,7 @@ class AnnealingOrDrying(Script): "description": "Add messages to the LCD and any print server.", "type": "bool", "default_value": false, - "enabled": "enable_annealing" + "enabled": "enable_script" }, "has_build_volume_heater": { @@ -226,11 +227,11 @@ class AnnealingOrDrying(Script): def execute(self, data): # Exit if there is no heated bed. - if not bool(Application.getInstance().getGlobalContainerStack().getProperty("machine_heated_bed", "value")): + if not bool(self.global_stack.getProperty("machine_heated_bed", "value")): Message(title = "[Anneal or Dry Filament]", text = "The script did not run because Heated Bed is disabled in Machine Settings.").show() return data # Enter a message in the gcode if the script is not enabled. - if not bool(self.getSettingValueByKey("enable_annealing")): + if not bool(self.getSettingValueByKey("enable_script")): data[0] += "; [Anneal or Dry Filament] was not enabled\n" return data lowest_temp = int(self.getSettingValueByKey("lowest_temp")) @@ -240,11 +241,10 @@ class AnnealingOrDrying(Script): data[0] += "; Anneal or Dry Filament did not run. Shutoff Temp < 30\n" Message(title = "[Anneal or Dry Filament]", text = "The script did not run because the Shutoff Temp is less than 30°.").show() return data - self.global_stack = Application.getInstance().getGlobalContainerStack() - extruder = self.global_stack.extruderList + extruders = self.global_stack.extruderList bed_temperature = int(self.getSettingValueByKey("startout_temp")) - heated_chamber = bool(Application.getInstance().getGlobalContainerStack().getProperty("machine_heated_build_volume", "value")) - anneal_type = self.getSettingValueByKey("bed_and_chamber") + heated_chamber = bool(self.global_stack.getProperty("machine_heated_build_volume", "value")) + anneal_type = self.getSettingValueByKey("heating_zone_selection") # Get the heated chamber temperature or set to 0 if no chamber if heated_chamber: @@ -253,6 +253,13 @@ class AnnealingOrDrying(Script): anneal_type = "bed_only" chamber_temp = "0" + # Beep line + if bool(self.getSettingValueByKey("beep_when_done")): + beep_duration = self.getSettingValueByKey("beep_duration") + self.beep_string = f"M300 S440 P{beep_duration} ; Beep\n" + else: + self.beep_string = "" + # For compatibility with earlier Cura versions if self.global_stack.getProperty("build_volume_fan_nr", "value") is not None: has_bv_fan = bool(self.global_stack.getProperty("build_volume_fan_nr", "value")) @@ -262,7 +269,7 @@ class AnnealingOrDrying(Script): else: speed_bv_fan = 0 - if bool(extruder[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) and has_bv_fan: + if bool(extruders[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) and has_bv_fan: speed_bv_fan = round(speed_bv_fan * .01) else: speed_bv_fan = round(speed_bv_fan * 2.55) @@ -283,9 +290,10 @@ class AnnealingOrDrying(Script): # Park Head max_y = str(self.global_stack.getProperty("machine_depth", "value")) max_x = str(self.global_stack.getProperty("machine_width", "value")) + # Max_z is limited to 'machine_height - 20' just so the print head doesn't smack into anything. max_z = str(int(self.global_stack.getProperty("machine_height", "value")) - 20) - speed_travel = str(round(extruder[0].getProperty("speed_travel", "value")*60)) + speed_travel = str(round(extruders[0].getProperty("speed_travel", "value")*60)) park_xy = bool(self.getSettingValueByKey("park_head")) park_z = bool(self.getSettingValueByKey("park_max_z")) cycle_type = self.getSettingValueByKey("cycle_type") @@ -295,6 +303,7 @@ class AnnealingOrDrying(Script): data = self._anneal_print(data, park_xy, park_z, bed_temperature, lowest_temp, heated_chamber, chamber_temp, max_y, max_x, max_z, speed_travel, add_messages, anneal_type) elif cycle_type == "dry_cycle": data = self._dry_filament_only(data, anneal_type, heated_chamber, chamber_temp, bed_temperature, max_z, max_y, speed_travel) + return data def _anneal_print(self, anneal_data: str, park_xy: bool, park_z: bool, bed_temperature:int, lowest_temp: int, heated_chamber: bool, chamber_temp: str, max_x: str, max_y: str, max_z: str, speed_travel: str, add_messages: bool, anneal_type: str): @@ -302,17 +311,17 @@ class AnnealingOrDrying(Script): The procedure disables the M140 (and M141) lines at the end of the print, and adds additional bed (and chamber) temperature commands to the end of the G-Code file. The bed is allowed to cool down over a period of time. """ # Put the head parking string together + bed_temp_during_print = int(self.global_stack.getProperty("material_bed_temperature", "value")) time_minutes = 1 time_span = int(float(self.getSettingValueByKey("time_span")) * 3600) park_string = "" - if park_xy and not park_z: - park_string = f"G0 F{speed_travel} X{max_x} Y{max_y} ; Park XY\nM84 X Y E ; Disable steppers except Z\n" - elif park_xy and park_z: - park_string = f"G0 F{speed_travel} X{max_x} Y{max_y} ; Park XY\nG0 Z{max_z} ; Raise Z to 'ZMax - 20'\nM84 X Y E ; Disable steppers except Z\n" - elif not park_xy and park_z: - park_string = f"G0 F{speed_travel} Z{max_z} ; Raise Z to 'ZMax - 20'\nM84 X Y E ; Disable steppers except Z\n" - elif not park_xy and not park_z: - park_string = f"G91 ; Relative movement\nG0 F{speed_travel} Z5 ; Raise Z\nG90 ; Absolute movement\nG0 X0 Y0 ; Park\nM84 X Y E ; Disable steppers except Z\n" + if park_xy: + park_string += f"G0 F{speed_travel} X{max_x} Y{max_y} ; Park XY\n" + if park_z: + park_string += f"G0 Z{max_z} ; Raise Z to 'ZMax - 20'\n" + if not park_xy and not park_z: + park_string += f"G91 ; Relative movement\nG0 F{speed_travel} Z5 ; Raise Z\nG90 ; Absolute movement\nG0 X0 Y0 ; Park\n" + park_string += "M84 X Y E ; Disable steppers except Z\n" # Calculate the temperature differential hysteresis = bed_temperature - lowest_temp @@ -333,33 +342,35 @@ class AnnealingOrDrying(Script): # Put the first lines of the anneal string together anneal_string = ";\n;TYPE:CUSTOM ---------------- Anneal Print\n" + if bed_temperature == bed_temp_during_print: + anneal_string += self.beep_string if add_messages: anneal_string += "M117 Cool Down for " + str(round((wait_time + time_span)/3600,2)) + "hr\n" anneal_string += "M118 Cool Down for " + str(round((wait_time + time_span)/3600,2)) + "hr\n" anneal_string += self.bv_fan_on_str if wait_time > 0: - # Move the head before the M190 + # Add the parking string BEFORE the M190 anneal_string += park_string if anneal_type == "bed_only": - anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\n" + anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\n{self.beep_string}" if anneal_type == "bed_chamber": - anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\nM141 S{chamber_temp} ; Set the chamber temp\n" + anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\nM141 S{chamber_temp} ; Set the chamber temp\n{self.beep_string}" anneal_string += f"G4 S{wait_time} ; Hold for {round(wait_time / 3600,2)} hrs\n" else: - # Move the head after the M140 + # Add the parking string AFTER the M140 anneal_string += f"M140 S{step_down} ; Set bed temp\n" anneal_string += park_string anneal_string += f"G4 S{time_per_step} ; wait time in seconds\n" - step_down -= deg_per_step + step_down -= deg_per_step time_remaining = round(time_span/3600,2) + # Step the bed/chamber temps down and add each step to the anneal string. The chamber remains at it's temperature until the bed gets down to that temperature. for num in range(bed_temperature, lowest_temp, -3): anneal_string += f"M140 S{step_down} ; Step down bed\n" if anneal_type == "bed_chamber" and int(step_down) < int(chamber_temp): anneal_string += f"M141 S{step_down} ; Step down chamber\n" anneal_string += f"G4 S{time_per_step} ; Wait\n" - #time_remaining = round((time_span-(step_index*time_per_step))/3600,2) if time_remaining >= 1.00: if add_messages: anneal_string += f"M117 CoolDown - {round(time_remaining,1)}hr\n" @@ -375,24 +386,18 @@ class AnnealingOrDrying(Script): if step_down <= lowest_temp: break - # Beep line - if bool(self.getSettingValueByKey("beep_when_done")): - beep_string = "M300 S440 P" + str(self.getSettingValueByKey("beep_duration")) + " ; Beep\n" - else: - beep_string = "" - # Close out the anneal string anneal_string += "M140 S0 ; Shut off the bed heater" + "\n" if anneal_type == "bed_chamber": anneal_string += "M141 S0 ; Shut off the chamber heater\n" anneal_string += self.bv_fan_off_str - anneal_string += beep_string + anneal_string += self.beep_string if add_messages: anneal_string += "M117 CoolDown Complete\n" anneal_string += "M118 CoolDown Complete\n" anneal_string += ";TYPE:CUSTOM ---------------- End of Anneal\n;" - # Format + # Format the inserted lines. anneal_lines = anneal_string.split("\n") for index, line in enumerate(anneal_lines): if not line.startswith(";") and ";" in line: @@ -401,36 +406,36 @@ class AnnealingOrDrying(Script): anneal_lines[index] = front_txt + str(" " * (30 - len(front_txt))) +";" + back_txt anneal_string = "\n".join(anneal_lines) + "\n" - layer = anneal_data[len(anneal_data)-1] - lines = layer.split("\n") + end_gcode = anneal_data[-1] + end_lines = end_gcode.split("\n") - # Comment out the M140 S0 line in the ending gcode. - for num in range(len(lines)-1,-1,-1): - if lines[num].startswith("M140 S0"): - lines[num] = ";M140 S0 ; Shutoff Overide - Anneal or Dry Filament" - anneal_data[len(anneal_data)-1] = "\n".join(lines) + # Comment out the existing M140 S0 lines in the ending gcode. + for num in range(len(end_lines)-1,-1,-1): + if end_lines[num].startswith("M140 S0"): + end_lines[num] = ";M140 S0 ; Shutoff Overide - Anneal or Dry Filament" + anneal_data[-1] = "\n".join(end_lines) # If there is a Heated Chamber and it's included then comment out the M141 S0 line if anneal_type == "bed_chamber" and heated_chamber: - for num in range(0,len(lines)-1,1): - if lines[num].startswith("M141 S0"): - lines[num] = ";M141 S0 ; Shutoff Overide - Anneal or Dry Filament" - anneal_data[len(anneal_data)-1] = "\n".join(lines) + for num in range(0,len(end_lines)-1): + if end_lines[num].startswith("M141 S0"): + end_lines[num] = ";M141 S0 ; Shutoff Overide - Anneal or Dry Filament" + anneal_data[-1] = "\n".join(end_lines) # If park head is enabled then dont let the steppers disable until the head is parked disable_string = "" - for num in range(0,len(lines)-1,1): - if lines[num][:3] in ("M84", "M18"): - disable_string = lines[num] + "\n" + for num in range(0,len(end_lines)-1): + if end_lines[num][:3] in ("M84", "M18"): + disable_string = end_lines[num] + "\n" stepper_timeout = int(wait_time + time_span) if stepper_timeout > 14400: stepper_timeout = 14400 - lines[num] = ";" + lines[num] + " ; Overide - Anneal or Dry Filament" - lines.insert(num, "M84 S" + str(stepper_timeout) + " ; Increase stepper timeout - Anneal or Dry Filament") - anneal_data[len(anneal_data)-1] = "\n".join(lines) + end_lines[num] = ";" + end_lines[num] + " ; Overide - Anneal or Dry Filament" + end_lines.insert(num, "M84 S" + str(stepper_timeout) + " ; Increase stepper timeout - Anneal or Dry Filament") + anneal_data[-1] = "\n".join(end_lines) break # The Anneal string is the new end of the gcode so move the 'End of Gcode' comment line in case there are other scripts running - anneal_data[len(anneal_data)-1] = anneal_data[len(anneal_data)-1].replace(";End of Gcode", anneal_string + disable_string + ";End of Gcode") + anneal_data[-1] = anneal_data[-1].replace(";End of Gcode", anneal_string + disable_string + ";End of Gcode") return anneal_data def _dry_filament_only(self, drydata: str, anneal_type: str, heated_chamber: bool, chamber_temp: int, bed_temperature: int, max_z:str, max_y:str, speed_travel: str) -> str: @@ -441,15 +446,16 @@ class AnnealingOrDrying(Script): drydata[num] = "" drydata[0] = drydata[0].split("\n")[0] + "\n" add_messages = bool(self.getSettingValueByKey("add_messages")) - pause_cmd = self.getSettingValueByKey("pause_cmd").upper() + pause_cmd = self.getSettingValueByKey("pause_cmd") if pause_cmd != "": - pause_cmd = "M300 ; Beep\n" + pause_cmd + pause_cmd = self.beep_string + pause_cmd dry_time = self.getSettingValueByKey("dry_time") * 3600 lines = drydata[1].split("\n") - drying_string = lines[0] + "\n" + ";............TYPE:CUSTOM: Dry Filament\n" + drying_string = lines[0] + f"\n;............TYPE:CUSTOM: Dry Filament\n{self.beep_string}" if add_messages: drying_string += f"M117 Cool Down for {round(dry_time/3600,2)} hr ; Message\n" drying_string += f"M118 Cool Down for {round(dry_time/3600,2)} hr ; Message\n" + # M113 sends messages to a print server as a 'Keep Alive' and can generate a lot of traffic over the USB drying_string += "M113 S0 ; No echo\n" drying_string += f"M84 S{round(dry_time)} ; Set stepper timeout\n" @@ -489,14 +495,14 @@ class AnnealingOrDrying(Script): drying_string += self.bv_fan_off_str if self.getSettingValueByKey("beep_when_done"): beep_duration = self.getSettingValueByKey("beep_duration") - drying_string += f"M300 P{beep_duration} ; Beep\n" + drying_string += self.beep_string if add_messages: drying_string += "M117 End of drying cycle ; Message\n" drying_string += "M118 End of drying cycle ; Message\n" drying_string += "M84 X Y E ; Disable steppers except Z\n" drying_string += ";End of Gcode" - # Format + # Format the lines lines = drying_string.split("\n") for index, line in enumerate(lines): if not line.startswith(";") and ";" in line: From 968576472121c88735e0ebc5252336719738fac2 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 4 Aug 2025 15:19:04 +0200 Subject: [PATCH 288/299] Implement undo-redo by full stroke CURA-12661 --- plugins/PaintTool/PaintTool.py | 4 +- plugins/PaintTool/PaintUndoCommand.py | 104 ++++++++++++++++++++++++++ plugins/PaintTool/PaintView.py | 95 ++++++++--------------- 3 files changed, 136 insertions(+), 67 deletions(-) create mode 100644 plugins/PaintTool/PaintUndoCommand.py diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index fa6436f10d..4f6516ffd7 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -130,7 +130,7 @@ class PaintTool(Tool): width, height = paintview.getUvTexDimensions() clear_image = QImage(width, height, QImage.Format.Format_RGB32) clear_image.fill(Qt.GlobalColor.white) - paintview.addStroke(clear_image, 0, 0, "none") + paintview.addStroke(clear_image, 0, 0, "none", False) self._updateScene() @@ -333,7 +333,7 @@ class PaintTool(Tool): end_coords[0] * w, end_coords[1] * h ) - paintview.addStroke(sub_image, start_x, start_y, self._brush_color) + paintview.addStroke(sub_image, start_x, start_y, self._brush_color, is_moved) self._last_text_coords = texcoords self._last_mouse_coords = (mouse_evt.x, mouse_evt.y) diff --git a/plugins/PaintTool/PaintUndoCommand.py b/plugins/PaintTool/PaintUndoCommand.py new file mode 100644 index 0000000000..c100780c7f --- /dev/null +++ b/plugins/PaintTool/PaintUndoCommand.py @@ -0,0 +1,104 @@ +# Copyright (c) 2025 UltiMaker +# Cura is released under the terms of the LGPLv3 or higher. + +from typing import cast, Optional + +from PyQt6.QtCore import QRect, QPoint +from PyQt6.QtGui import QUndoCommand, QImage, QPainter + +from UM.View.GL.Texture import Texture + + +class PaintUndoCommand(QUndoCommand): + """Provides the command that does the actual painting on objects with undo/redo mechanisms""" + + def __init__(self, + texture: Texture, + stroke_mask: QImage, + x: int, + y: int, + set_value: int, + bit_range: tuple[int, int], + mergeable: bool) -> None: + super().__init__() + + self._original_texture_image: Optional[QImage] = texture.getImage().copy() if not mergeable else None + self._texture: Texture = texture + self._stroke_mask: QImage = stroke_mask + self._x: int = x + self._y: int = y + self._set_value: int = set_value + self._bit_range: tuple[int, int] = bit_range + self._mergeable: bool = mergeable + + def id(self) -> int: + # Since the undo stack will contain only commands of this type, we can use a fixed ID + return 0 + + def redo(self) -> None: + actual_image = self._texture.getImage() + + bit_range_start, bit_range_end = self._bit_range + full_int32 = 0xffffffff + clear_mask = full_int32 ^ (((full_int32 << (32 - 1 - (bit_range_end - bit_range_start))) & full_int32) >> ( + 32 - 1 - bit_range_end)) + image_rect = QRect(0, 0, self._stroke_mask.width(), self._stroke_mask.height()) + + clear_bits_image = self._stroke_mask.copy() + clear_bits_image.invertPixels() + painter = QPainter(clear_bits_image) + painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Lighten) + painter.fillRect(image_rect, clear_mask) + painter.end() + + set_value_image = self._stroke_mask.copy() + painter = QPainter(set_value_image) + painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Multiply) + painter.fillRect(image_rect, self._set_value) + painter.end() + + stroked_image = actual_image.copy(self._x, self._y, self._stroke_mask.width(), self._stroke_mask.height()) + painter = QPainter(stroked_image) + painter.setCompositionMode(QPainter.CompositionMode.RasterOp_SourceAndDestination) + painter.drawImage(0, 0, clear_bits_image) + painter.setCompositionMode(QPainter.CompositionMode.RasterOp_SourceOrDestination) + painter.drawImage(0, 0, set_value_image) + painter.end() + + self._texture.setSubImage(stroked_image, self._x, self._y) + + def undo(self) -> None: + if self._original_texture_image is not None: + self._texture.setSubImage(self._original_texture_image.copy(self._x, + self._y, + self._stroke_mask.width(), + self._stroke_mask.height()), + self._x, + self._y) + + def mergeWith(self, command: QUndoCommand) -> bool: + if not isinstance(command, PaintUndoCommand): + return False + paint_undo_command = cast(PaintUndoCommand, command) + + if not paint_undo_command._mergeable: + return False + + self_rect = QRect(QPoint(self._x, self._y), self._stroke_mask.size()) + command_rect = QRect(QPoint(paint_undo_command._x, paint_undo_command._y), paint_undo_command._stroke_mask.size()) + bounding_rect = self_rect.united(command_rect) + + merged_mask = QImage(bounding_rect.width(), bounding_rect.height(), self._stroke_mask.format()) + merged_mask.fill(0) + + painter = QPainter(merged_mask) + painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Lighten) + painter.drawImage(self._x - bounding_rect.x(), self._y - bounding_rect.y(), self._stroke_mask) + painter.drawImage(paint_undo_command._x - bounding_rect.x(), paint_undo_command._y - bounding_rect.y(), paint_undo_command._stroke_mask) + painter.end() + + self._x = bounding_rect.x() + self._y = bounding_rect.y() + self._stroke_mask = merged_mask + + return True diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 749fa463e4..da00e16c2a 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -5,7 +5,7 @@ import os from PyQt6.QtCore import QRect from typing import Optional, List, Tuple, Dict -from PyQt6.QtGui import QImage, QColor, QPainter +from PyQt6.QtGui import QImage, QColor, QPainter, QUndoStack from cura.CuraApplication import CuraApplication from UM.PluginRegistry import PluginRegistry @@ -17,14 +17,14 @@ from UM.View.GL.OpenGL import OpenGL from UM.i18n import i18nCatalog from UM.Math.Color import Color +from .PaintUndoCommand import PaintUndoCommand + catalog = i18nCatalog("cura") class PaintView(View): """View for model-painting.""" - UNDO_STACK_SIZE = 1024 - class PaintType: def __init__(self, display_color: Color, value: int): self.display_color: Color = display_color @@ -38,8 +38,8 @@ class PaintView(View): self._current_paint_type = "" self._paint_modes: Dict[str, Dict[str, "PaintView.PaintType"]] = {} - self._stroke_undo_stack: List[Tuple[QImage, int, int]] = [] - self._stroke_redo_stack: List[Tuple[QImage, int, int]] = [] + self._paint_undo_stack: QUndoStack = QUndoStack() + self._paint_undo_stack.setUndoLimit(32) # Set a quite low amount since every command copies the full texture self._force_opaque_mask = QImage(2, 2, QImage.Format.Format_Mono) self._force_opaque_mask.fill(1) @@ -61,74 +61,39 @@ class PaintView(View): shader_filename = os.path.join(PluginRegistry.getInstance().getPluginPath("PaintTool"), "paint.shader") self._paint_shader = OpenGL.getInstance().createShaderProgram(shader_filename) - def _forceOpaqueDeepCopy(self, image: QImage): - res = QImage(image.width(), image.height(), QImage.Format.Format_RGBA8888) - res.fill(QColor(255, 255, 255, 255)) - painter = QPainter(res) - painter.setRenderHint(QPainter.RenderHint.Antialiasing, False) - painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceOver) - painter.drawImage(0, 0, image) - painter.end() - res.setAlphaChannel(self._force_opaque_mask.scaled(image.width(), image.height())) - return res - - def addStroke(self, stroke_mask: QImage, start_x: int, start_y: int, brush_color: str) -> None: + def addStroke(self, stroke_mask: QImage, start_x: int, start_y: int, brush_color: str, merge_with_previous: bool) -> None: if self._current_paint_texture is None or self._current_paint_texture.getImage() is None: return - actual_image = self._current_paint_texture.getImage() + current_image = self._current_paint_texture.getImage() + texture_rect = QRect(0, 0, current_image.width(), current_image.height()) + stroke_rect = QRect(start_x, start_y, stroke_mask.width(), stroke_mask.height()) + intersect_rect = texture_rect.intersected(stroke_rect) + if intersect_rect != stroke_rect: + # Stroke doesn't fully fit into the image, we have to crop it + stroke_mask = stroke_mask.copy(intersect_rect.x() - start_x, + intersect_rect.y() - start_y, + intersect_rect.width(), + intersect_rect.height()) + start_x = intersect_rect.x() + start_y = intersect_rect.y() bit_range_start, bit_range_end = self._current_bits_ranges - set_value = self._paint_modes[self._current_paint_type][brush_color].value << self._current_bits_ranges[0] - full_int32 = 0xffffffff - clear_mask = full_int32 ^ (((full_int32 << (32 - 1 - (bit_range_end - bit_range_start))) & full_int32) >> (32 - 1 - bit_range_end)) - image_rect = QRect(0, 0, stroke_mask.width(), stroke_mask.height()) + set_value = self._paint_modes[self._current_paint_type][brush_color].value << bit_range_start - clear_bits_image = stroke_mask.copy() - clear_bits_image.invertPixels() - painter = QPainter(clear_bits_image) - painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Lighten) - painter.fillRect(image_rect, clear_mask) - painter.end() + self._paint_undo_stack.push(PaintUndoCommand(self._current_paint_texture, + stroke_mask, + start_x, + start_y, + set_value, + (bit_range_start, bit_range_end), + merge_with_previous)) - set_value_image = stroke_mask.copy() - painter = QPainter(set_value_image) - painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Multiply) - painter.fillRect(image_rect, set_value) - painter.end() + def undoStroke(self) -> None: + self._paint_undo_stack.undo() - stroked_image = actual_image.copy(start_x, start_y, stroke_mask.width(), stroke_mask.height()) - painter = QPainter(stroked_image) - painter.setCompositionMode(QPainter.CompositionMode.RasterOp_SourceAndDestination) - painter.drawImage(0, 0, clear_bits_image) - painter.setCompositionMode(QPainter.CompositionMode.RasterOp_SourceOrDestination) - painter.drawImage(0, 0, set_value_image) - painter.end() - - self._stroke_redo_stack.clear() - if len(self._stroke_undo_stack) >= PaintView.UNDO_STACK_SIZE: - self._stroke_undo_stack.pop(0) - undo_image = self._forceOpaqueDeepCopy(self._current_paint_texture.setSubImage(stroked_image, start_x, start_y)) - if undo_image is not None: - self._stroke_undo_stack.append((undo_image, start_x, start_y)) - - def _applyUndoStacksAction(self, from_stack: List[Tuple[QImage, int, int]], to_stack: List[Tuple[QImage, int, int]]) -> bool: - if len(from_stack) <= 0 or self._current_paint_texture is None: - return False - from_image, x, y = from_stack.pop() - to_image = self._forceOpaqueDeepCopy(self._current_paint_texture.setSubImage(from_image, x, y)) - if to_image is None: - return False - if len(to_stack) >= PaintView.UNDO_STACK_SIZE: - to_stack.pop(0) - to_stack.append((to_image, x, y)) - return True - - def undoStroke(self) -> bool: - return self._applyUndoStacksAction(self._stroke_undo_stack, self._stroke_redo_stack) - - def redoStroke(self) -> bool: - return self._applyUndoStacksAction(self._stroke_redo_stack, self._stroke_undo_stack) + def redoStroke(self) -> None: + self._paint_undo_stack.redo() def getUvTexDimensions(self): if self._current_paint_texture is not None: From 586c2939a60dd2750c44bdad383e5d66e3a82d0a Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 4 Aug 2025 15:46:51 +0200 Subject: [PATCH 289/299] Enable undo/redo buttons when appropriate CURA-12661 --- plugins/PaintTool/PaintTool.py | 68 ++++++++++++++------------------- plugins/PaintTool/PaintTool.qml | 20 +++++++++- plugins/PaintTool/PaintView.py | 20 +++++++--- plugins/PaintTool/__init__.py | 7 +++- 4 files changed, 65 insertions(+), 50 deletions(-) diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index b9f7a5e95b..293c069786 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -33,9 +33,13 @@ class PaintTool(Tool): SQUARE = 0 CIRCLE = 1 - def __init__(self) -> None: + def __init__(self, view: PaintView) -> None: super().__init__() + self._view: PaintView = view + self._view.canUndoChanged.connect(self._onCanUndoChanged) + self._view.canRedoChanged.connect(self._onCanRedoChanged) + self._picking_pass: Optional[PickingPass] = None self._faces_selection_pass: Optional[SelectionPass] = None @@ -56,7 +60,7 @@ class PaintTool(Tool): self._last_mouse_coords: Optional[Tuple[int, int]] = None self._last_face_id: Optional[int] = None - self.setExposedProperties("PaintType", "BrushSize", "BrushColor", "BrushShape") + self.setExposedProperties("PaintType", "BrushSize", "BrushColor", "BrushShape", "CanUndo", "CanRedo") Selection.selectionChanged.connect(self._updateIgnoreUnselectedObjects) @@ -95,19 +99,11 @@ class PaintTool(Tool): return stroke_image, (start_x, start_y) def getPaintType(self) -> str: - paint_view = self._get_paint_view() - if paint_view is None: - return "" - - return paint_view.getPaintType() + return self._view.getPaintType() def setPaintType(self, paint_type: str) -> None: - paint_view = self._get_paint_view() - if paint_view is None: - return - if paint_type != self.getPaintType(): - paint_view.setPaintType(paint_type) + self._view.setPaintType(paint_type) self._brush_pen = self._createBrushPen() self._updateScene() @@ -140,38 +136,34 @@ class PaintTool(Tool): self._brush_pen = self._createBrushPen() self.propertyChanged.emit() - def undoStackAction(self, redo_instead: bool) -> bool: - paint_view = self._get_paint_view() - if paint_view is None: - return False + def getCanUndo(self) -> bool: + return self._view.canUndo() - if redo_instead: - paint_view.redoStroke() - else: - paint_view.undoStroke() + def _onCanUndoChanged(self): + self.propertyChanged.emit() + def getCanRedo(self) -> bool: + return self._view.canRedo() + + def _onCanRedoChanged(self): + self.propertyChanged.emit() + + def undoStackAction(self) -> None: + self._view.undoStroke() + self._updateScene() + + def redoStackAction(self) -> None: + self._view.redoStroke() self._updateScene() - return True def clear(self) -> None: - paintview = self._get_paint_view() - if paintview is None: - return - - width, height = paintview.getUvTexDimensions() + width, height = self._view.getUvTexDimensions() clear_image = QImage(width, height, QImage.Format.Format_RGB32) clear_image.fill(Qt.GlobalColor.white) - paintview.addStroke(clear_image, 0, 0, "none", False) + self._view.addStroke(clear_image, 0, 0, "none", False) self._updateScene() - @staticmethod - def _get_paint_view() -> Optional[PaintView]: - paint_view = Application.getInstance().getController().getActiveView() - if paint_view is None or paint_view.getPluginId() != "PaintTool": - return None - return cast(PaintView, paint_view) - @staticmethod def _get_intersect_ratio_via_pt(a: numpy.ndarray, pt: numpy.ndarray, b: numpy.ndarray, c: numpy.ndarray) -> float: # compute the intersection of (param) A - pt with (param) B - (param) C @@ -330,10 +322,6 @@ class PaintTool(Tool): else: self._mouse_held = True - paintview = self._get_paint_view() - if paintview is None: - return False - if not self._faces_selection_pass: self._faces_selection_pass = CuraApplication.getInstance().getRenderer().getRenderPass("selection_faces") if not self._faces_selection_pass: @@ -379,7 +367,7 @@ class PaintTool(Tool): (self._last_mouse_coords, (self._last_face_id, self._last_text_coords)), ((mouse_evt.x, mouse_evt.y), (face_id, texcoords))) - w, h = paintview.getUvTexDimensions() + w, h = self._view.getUvTexDimensions() for start_coords, end_coords in substrokes: sub_image, (start_x, start_y) = self._createStrokeImage( start_coords[0] * w, @@ -387,7 +375,7 @@ class PaintTool(Tool): end_coords[0] * w, end_coords[1] * h ) - paintview.addStroke(sub_image, start_x, start_y, self._brush_color, is_moved) + self._view.addStroke(sub_image, start_x, start_y, self._brush_color, is_moved) self._last_text_coords = texcoords self._last_mouse_coords = (mouse_evt.x, mouse_evt.y) diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index 2bb3106dd5..c448835bc5 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -19,14 +19,14 @@ Item { id: undoAction shortcut: "Ctrl+L" - onTriggered: UM.Controller.triggerActionWithData("undoStackAction", false) + onTriggered: UM.Controller.triggerAction("undoStackAction") } Action { id: redoAction shortcut: "Ctrl+Shift+L" - onTriggered: UM.Controller.triggerActionWithData("undoStackAction", true) + onTriggered: UM.Controller.triggerAction("redoStackAction") } Column @@ -192,6 +192,7 @@ Item { id: undoButton + enabled: undoAction.enabled text: catalog.i18nc("@action:button", "Undo Stroke") toolItem: UM.ColorImage { @@ -206,6 +207,7 @@ Item { id: redoButton + enabled: redoAction.enabled text: catalog.i18nc("@action:button", "Redo Stroke") toolItem: UM.ColorImage { @@ -227,4 +229,18 @@ Item } } } + + Binding + { + target: undoAction + property: "enabled" + value: UM.Controller.properties.getValue("CanUndo") + } + + Binding + { + target: redoAction + property: "enabled" + value: UM.Controller.properties.getValue("CanRedo") + } } diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index ed06da17d4..b5cd44772d 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -2,10 +2,10 @@ # Cura is released under the terms of the LGPLv3 or higher. import os -from PyQt6.QtCore import QRect -from typing import Optional, List, Tuple, Dict, cast +from PyQt6.QtCore import QRect, pyqtSignal +from typing import Optional, Dict -from PyQt6.QtGui import QImage, QColor, QPainter, QUndoStack +from PyQt6.QtGui import QImage, QUndoStack from cura.CuraApplication import CuraApplication from cura.BuildVolume import BuildVolume @@ -42,9 +42,8 @@ class PaintView(View): self._paint_undo_stack: QUndoStack = QUndoStack() self._paint_undo_stack.setUndoLimit(32) # Set a quite low amount since every command copies the full texture - - self._force_opaque_mask = QImage(2, 2, QImage.Format.Format_Mono) - self._force_opaque_mask.fill(1) + self._paint_undo_stack.canUndoChanged.connect(self.canUndoChanged) + self._paint_undo_stack.canRedoChanged.connect(self.canRedoChanged) application = CuraApplication.getInstance() application.engineCreatedSignal.connect(self._makePaintModes) @@ -52,6 +51,15 @@ class PaintView(View): self._solid_view = None + canUndoChanged = pyqtSignal(bool) + canRedoChanged = pyqtSignal(bool) + + def canUndo(self): + return self._paint_undo_stack.canUndo() + + def canRedo(self): + return self._paint_undo_stack.canRedo() + def _makePaintModes(self): theme = CuraApplication.getInstance().getTheme() usual_types = {"none": self.PaintType(Color(*theme.getColor("paint_normal_area").getRgb()), 0), diff --git a/plugins/PaintTool/__init__.py b/plugins/PaintTool/__init__.py index e92c169ee6..637e0b00f2 100644 --- a/plugins/PaintTool/__init__.py +++ b/plugins/PaintTool/__init__.py @@ -27,7 +27,10 @@ def getMetaData(): def register(app): qmlRegisterUncreatableType(PaintTool.PaintTool.Brush, "Cura", 1, 0, "This is an enumeration class", "PaintToolBrush") + + view = PaintView.PaintView() + return { - "tool": PaintTool.PaintTool(), - "view": PaintView.PaintView() + "tool": PaintTool.PaintTool(view), + "view": view } From 8f9a17d49e7ee40a28849ccdfc41671c198dbe27 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 4 Aug 2025 16:03:09 +0200 Subject: [PATCH 290/299] Simplify QML code CURA-12661 --- plugins/PaintTool/BrushColorButton.qml | 25 ++----------------------- plugins/PaintTool/BrushShapeButton.qml | 25 ++----------------------- plugins/PaintTool/PaintModeButton.qml | 25 ++----------------------- plugins/PaintTool/PaintTool.qml | 24 ++++-------------------- 4 files changed, 10 insertions(+), 89 deletions(-) diff --git a/plugins/PaintTool/BrushColorButton.qml b/plugins/PaintTool/BrushColorButton.qml index ae4ab6243f..b62ab09e92 100644 --- a/plugins/PaintTool/BrushColorButton.qml +++ b/plugins/PaintTool/BrushColorButton.qml @@ -13,27 +13,6 @@ UM.ToolbarButton property string color - onClicked: setColor() - - function setColor() - { - UM.Controller.setProperty("BrushColor", buttonBrushColor.color); - } - - function isChecked() - { - return UM.Controller.properties.getValue("BrushColor") === buttonBrushColor.color; - } - - Component.onCompleted: - { - buttonBrushColor.checked = isChecked(); - } - - Binding - { - target: buttonBrushColor - property: "checked" - value: isChecked() - } + checked: UM.Controller.properties.getValue("BrushColor") === buttonBrushColor.color + onClicked: UM.Controller.setProperty("BrushColor", buttonBrushColor.color) } diff --git a/plugins/PaintTool/BrushShapeButton.qml b/plugins/PaintTool/BrushShapeButton.qml index ef4256792a..e05cd206f3 100644 --- a/plugins/PaintTool/BrushShapeButton.qml +++ b/plugins/PaintTool/BrushShapeButton.qml @@ -13,27 +13,6 @@ UM.ToolbarButton property int shape - onClicked: setShape() - - function setShape() - { - UM.Controller.setProperty("BrushShape", buttonBrushShape.shape) - } - - function isChecked() - { - return UM.Controller.properties.getValue("BrushShape") === buttonBrushShape.shape; - } - - Component.onCompleted: - { - buttonBrushShape.checked = isChecked(); - } - - Binding - { - target: buttonBrushShape - property: "checked" - value: isChecked() - } + checked: UM.Controller.properties.getValue("BrushShape") === buttonBrushShape.shape + onClicked: UM.Controller.setProperty("BrushShape", buttonBrushShape.shape) } diff --git a/plugins/PaintTool/PaintModeButton.qml b/plugins/PaintTool/PaintModeButton.qml index eb294f7ad6..833a009551 100644 --- a/plugins/PaintTool/PaintModeButton.qml +++ b/plugins/PaintTool/PaintModeButton.qml @@ -13,27 +13,6 @@ Cura.ModeSelectorButton property string mode - onClicked: setMode() - - function setMode() - { - UM.Controller.setProperty("PaintType", modeSelectorButton.mode); - } - - function isSelected() - { - return UM.Controller.properties.getValue("PaintType") === modeSelectorButton.mode; - } - - Component.onCompleted: - { - modeSelectorButton.selected = isSelected(); - } - - Binding - { - target: modeSelectorButton - property: "selected" - value: isSelected() - } + selected: UM.Controller.properties.getValue("PaintType") === modeSelectorButton.mode + onClicked: UM.Controller.setProperty("PaintType", modeSelectorButton.mode) } diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index c448835bc5..01d866967a 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -19,6 +19,7 @@ Item { id: undoAction shortcut: "Ctrl+L" + enabled: UM.Controller.properties.getValue("CanUndo") onTriggered: UM.Controller.triggerAction("undoStackAction") } @@ -26,6 +27,7 @@ Item { id: redoAction shortcut: "Ctrl+Shift+L" + enabled: UM.Controller.properties.getValue("CanRedo") onTriggered: UM.Controller.triggerAction("redoStackAction") } @@ -53,7 +55,7 @@ Item icon: "Support" tooltipText: catalog.i18nc("@tooltip", "Refine support placement by defining preferred/avoidance areas") mode: "support" - visible: false + // visible: false } } @@ -163,6 +165,7 @@ Item from: 10 to: 1000 + value: UM.Controller.properties.getValue("BrushSize") onPressedChanged: function(pressed) { @@ -171,11 +174,6 @@ Item UM.Controller.setProperty("BrushSize", shapeSizeSlider.value); } } - - Component.onCompleted: - { - shapeSizeSlider.value = UM.Controller.properties.getValue("BrushSize"); - } } //Line between the sections. @@ -229,18 +227,4 @@ Item } } } - - Binding - { - target: undoAction - property: "enabled" - value: UM.Controller.properties.getValue("CanUndo") - } - - Binding - { - target: redoAction - property: "enabled" - value: UM.Controller.properties.getValue("CanRedo") - } } From b5e2ce6168240406169fbb1b764ff5dce030fc81 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 4 Aug 2025 16:07:49 +0200 Subject: [PATCH 291/299] Restore disabled support painting CURA-12661 --- plugins/PaintTool/PaintTool.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index 01d866967a..0d1129eb60 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -55,7 +55,7 @@ Item icon: "Support" tooltipText: catalog.i18nc("@tooltip", "Refine support placement by defining preferred/avoidance areas") mode: "support" - // visible: false + visible: false } } From 4006272fee2f6b90af4ac78cbf7e071aa39f7746 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 5 Aug 2025 00:45:48 +0200 Subject: [PATCH 292/299] Some housekeeping - anneal_type -> heating_zone: lines up the variable name with intent. - Sort the variable inputs of the functions (annealing / drying) - Add description for parameters in both functions (annealing / drying) --- .../scripts/AnnealingOrDrying.py | 94 ++++++++++++++----- 1 file changed, 73 insertions(+), 21 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py b/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py index 496fc1cb42..1841a8b62b 100644 --- a/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py +++ b/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py @@ -67,7 +67,7 @@ class AnnealingOrDrying(Script): { "anneal_cycle": "Anneal Print", "dry_cycle": "Dry Filament" - }, + }, "default_value": "anneal_cycle", "enabled": true, "enabled": "enable_script" @@ -80,7 +80,8 @@ class AnnealingOrDrying(Script): "options": { "bed_only": "Bed", - "bed_chamber": "Bed and Chamber"}, + "bed_chamber": "Bed and Chamber" + }, "default_value": "bed_only", "enabled": "enable_script" }, @@ -244,13 +245,13 @@ class AnnealingOrDrying(Script): extruders = self.global_stack.extruderList bed_temperature = int(self.getSettingValueByKey("startout_temp")) heated_chamber = bool(self.global_stack.getProperty("machine_heated_build_volume", "value")) - anneal_type = self.getSettingValueByKey("heating_zone_selection") + heating_zone = self.getSettingValueByKey("heating_zone_selection") # Get the heated chamber temperature or set to 0 if no chamber if heated_chamber: chamber_temp = str(self.getSettingValueByKey("build_volume_temp")) else: - anneal_type = "bed_only" + heating_zone = "bed_only" chamber_temp = "0" # Beep line @@ -270,7 +271,7 @@ class AnnealingOrDrying(Script): speed_bv_fan = 0 if bool(extruders[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) and has_bv_fan: - speed_bv_fan = round(speed_bv_fan * .01) + speed_bv_fan = round(speed_bv_fan * 0.01) else: speed_bv_fan = round(speed_bv_fan * 2.55) @@ -300,15 +301,45 @@ class AnnealingOrDrying(Script): add_messages = bool(self.getSettingValueByKey("add_messages")) if cycle_type == "anneal_cycle": - data = self._anneal_print(data, park_xy, park_z, bed_temperature, lowest_temp, heated_chamber, chamber_temp, max_y, max_x, max_z, speed_travel, add_messages, anneal_type) + data = self._anneal_print(add_messages, data, bed_temperature, chamber_temp, heated_chamber, heating_zone, lowest_temp, max_x, max_y, max_z, park_xy, park_z, speed_travel) elif cycle_type == "dry_cycle": - data = self._dry_filament_only(data, anneal_type, heated_chamber, chamber_temp, bed_temperature, max_z, max_y, speed_travel) + data = self._dry_filament_only(data, bed_temperature, chamber_temp, heated_chamber, heating_zone, max_y, max_z, speed_travel) return data - def _anneal_print(self, anneal_data: str, park_xy: bool, park_z: bool, bed_temperature:int, lowest_temp: int, heated_chamber: bool, chamber_temp: str, max_x: str, max_y: str, max_z: str, speed_travel: str, add_messages: bool, anneal_type: str): + def _anneal_print( + self, + add_messages: bool, + anneal_data: str, + bed_temperature: int, + chamber_temp: str, + heated_chamber: bool, + heating_zone: str, + lowest_temp: int, + max_x: str, + max_y: str, + max_z: str, + park_xy: bool, + park_z: bool, + speed_travel: str) -> str: """ - The procedure disables the M140 (and M141) lines at the end of the print, and adds additional bed (and chamber) temperature commands to the end of the G-Code file. The bed is allowed to cool down over a period of time. + The procedure disables the M140 (and M141) lines at the end of the print, and adds additional bed (and chamber) temperature commands to the end of the G-Code file. + The bed is allowed to cool down over a period of time. + + :param add_messages: Whether to include M117 and M118 messages for LCD and print server + :param anneal_data: The G-code data to be modified with annealing commands + :param bed_temperature: Starting bed temperature in degrees Celsius + :param chamber_temp: Chamber/build volume temperature in degrees Celsius as string + :param heated_chamber: Whether the printer has a heated build volume/chamber + :param heating_zone: Zone selection - "bed_only" or "bed_chamber" + :param lowest_temp: Final shutdown temperature in degrees Celsius + :param max_x: Maximum X axis position for parking as string + :param max_y: Maximum Y axis position for parking as string + :param max_z: Maximum Z axis position (machine height - 20mm) as string + :param park_xy: Whether to park the print head at max X and Y positions + :param park_z: Whether to raise Z to maximum safe height + :param speed_travel: Travel speed for positioning moves in mm/min as string + :return: Modified G-code data with annealing cooldown sequence """ # Put the head parking string together bed_temp_during_print = int(self.global_stack.getProperty("material_bed_temperature", "value")) @@ -326,7 +357,7 @@ class AnnealingOrDrying(Script): # Calculate the temperature differential hysteresis = bed_temperature - lowest_temp - # if the bed temp is below the shutoff temp then exit + # Exit if the bed temp is below the shutoff temp if hysteresis <= 0: anneal_data[0] += "; Anneal or Dry Filament did not run. Bed Temp < Shutoff Temp\n" Message(title = "Anneal or Dry Filament", text = "Did not run because the Bed Temp < Shutoff Temp.").show() @@ -351,9 +382,9 @@ class AnnealingOrDrying(Script): if wait_time > 0: # Add the parking string BEFORE the M190 anneal_string += park_string - if anneal_type == "bed_only": + if heating_zone == "bed_only": anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\n{self.beep_string}" - if anneal_type == "bed_chamber": + if heating_zone == "bed_chamber": anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\nM141 S{chamber_temp} ; Set the chamber temp\n{self.beep_string}" anneal_string += f"G4 S{wait_time} ; Hold for {round(wait_time / 3600,2)} hrs\n" else: @@ -368,7 +399,7 @@ class AnnealingOrDrying(Script): # Step the bed/chamber temps down and add each step to the anneal string. The chamber remains at it's temperature until the bed gets down to that temperature. for num in range(bed_temperature, lowest_temp, -3): anneal_string += f"M140 S{step_down} ; Step down bed\n" - if anneal_type == "bed_chamber" and int(step_down) < int(chamber_temp): + if heating_zone == "bed_chamber" and int(step_down) < int(chamber_temp): anneal_string += f"M141 S{step_down} ; Step down chamber\n" anneal_string += f"G4 S{time_per_step} ; Wait\n" if time_remaining >= 1.00: @@ -388,7 +419,7 @@ class AnnealingOrDrying(Script): # Close out the anneal string anneal_string += "M140 S0 ; Shut off the bed heater" + "\n" - if anneal_type == "bed_chamber": + if heating_zone == "bed_chamber": anneal_string += "M141 S0 ; Shut off the chamber heater\n" anneal_string += self.bv_fan_off_str anneal_string += self.beep_string @@ -416,7 +447,7 @@ class AnnealingOrDrying(Script): anneal_data[-1] = "\n".join(end_lines) # If there is a Heated Chamber and it's included then comment out the M141 S0 line - if anneal_type == "bed_chamber" and heated_chamber: + if heating_zone == "bed_chamber" and heated_chamber: for num in range(0,len(end_lines)-1): if end_lines[num].startswith("M141 S0"): end_lines[num] = ";M141 S0 ; Shutoff Overide - Anneal or Dry Filament" @@ -438,9 +469,30 @@ class AnnealingOrDrying(Script): anneal_data[-1] = anneal_data[-1].replace(";End of Gcode", anneal_string + disable_string + ";End of Gcode") return anneal_data - def _dry_filament_only(self, drydata: str, anneal_type: str, heated_chamber: bool, chamber_temp: int, bed_temperature: int, max_z:str, max_y:str, speed_travel: str) -> str: + def _dry_filament_only( + self, + bed_temperature: int, + chamber_temp: int, + drydata: str, + heated_chamber: bool, + heating_zone: str, + max_y: str, + max_z: str, + speed_travel: str) -> str: """ - This procedure turns the bed on, homes the printer, parks the head. After the time period the bed is turned off. There is no actual print in the generated gcode, just a couple of moves to get the nozzle out of the way, and the bed heat (and possibly chamber heat) control. It allows a user to use the bed to warm up and hopefully dry a filament roll. + This procedure turns the bed on, homes the printer, parks the head. After the time period the bed is turned off. + There is no actual print in the generated gcode, just a couple of moves to get the nozzle out of the way, and the bed heat (and possibly chamber heat) control. + It allows a user to use the bed to warm up and hopefully dry a filament roll. + + :param bed_temperature: Bed temperature for drying in degrees Celsius + :param chamber_temp: Chamber/build volume temperature for drying in degrees Celsius + :param drydata: The G-code data to be replaced with filament drying commands + :param heated_chamber: Whether the printer has a heated build volume/chamber + :param heating_zone: Zone selection - "bed_only" or "bed_chamber" + :param max_y: Maximum Y axis position for parking as string + :param max_z: Maximum Z axis position (machine height - 20mm) as string + :param speed_travel: Travel speed for positioning moves in mm/min as string + :return: Modified G-code data containing only filament drying sequence """ for num in range(2, len(drydata)): drydata[num] = "" @@ -461,7 +513,7 @@ class AnnealingOrDrying(Script): drying_string += f"M84 S{round(dry_time)} ; Set stepper timeout\n" drying_string += f"M140 S{bed_temperature} ; Heat bed\n" drying_string += self.bv_fan_on_str - if heated_chamber and anneal_type == "bed_chamber": + if heated_chamber and heating_zone == "bed_chamber": drying_string += f"M141 S{chamber_temp} ; Chamber temp\n" if pause_cmd == "M0": pause_cmd = "M0 Clear bed and click...; Pause" @@ -489,7 +541,7 @@ class AnnealingOrDrying(Script): drying_string += f"M117 {temp_time/3600} hr remaining ; Message\n" drying_string += f"M118 {temp_time/3600} hr remaining ; Message\n" drying_string += f"G4 S{temp_time} ; Dry time\n" - if heated_chamber and anneal_type == "bed_chamber": + if heated_chamber and heating_zone == "bed_chamber": drying_string += f"M141 S0 ; Shut off chamber\n" drying_string += "M140 S0 ; Shut off bed\n" drying_string += self.bv_fan_off_str @@ -512,8 +564,8 @@ class AnnealingOrDrying(Script): drydata[1] = "\n".join(lines) + "\n" dry_txt = "; Drying time ...................... " + str(self.getSettingValueByKey("dry_time")) + " hrs\n" dry_txt += "; Drying temperature ........ " + str(bed_temperature) + "°\n" - if heated_chamber and anneal_type == "bed_chamber": + if heated_chamber and heating_zone == "bed_chamber": dry_txt += "; Chamber temperature ... " + str(chamber_temp) + "°\n" Message(title = "[Dry Filament]", text = dry_txt).show() drydata[0] = "; <<< This is a filament drying file only. There is no actual print. >>>\n;\n" + dry_txt + ";\n" - return drydata \ No newline at end of file + return drydata From 9d97eb7d594208bde9891b515d59aa6673cf6362 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 5 Aug 2025 14:07:44 +0200 Subject: [PATCH 293/299] Fix sometimes wrong painting color display CURA-12660 --- plugins/PaintTool/paint.shader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PaintTool/paint.shader b/plugins/PaintTool/paint.shader index f2af66ffe6..c1b90b376b 100644 --- a/plugins/PaintTool/paint.shader +++ b/plugins/PaintTool/paint.shader @@ -132,7 +132,7 @@ fragment41core = [defaults] u_ambientColor = [0.3, 0.3, 0.3, 1.0] -u_opacity = 0.5 +u_opacity = 1.0 u_texture = 0 [bindings] From cf24ed91e9650dcde09f87d4d53524b878889b7d Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 5 Aug 2025 15:55:23 +0200 Subject: [PATCH 294/299] Improve fix for opacity issues CURA-12660 Previous fix caused issues when moving to preview --- plugins/PaintTool/paint.shader | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/plugins/PaintTool/paint.shader b/plugins/PaintTool/paint.shader index c1b90b376b..1982724910 100644 --- a/plugins/PaintTool/paint.shader +++ b/plugins/PaintTool/paint.shader @@ -29,7 +29,6 @@ fragment = uniform mediump vec4 u_ambientColor; uniform highp vec3 u_lightPosition; uniform highp vec3 u_viewPosition; - uniform mediump float u_opacity; uniform sampler2D u_texture; uniform mediump int u_bitsRangesStart; uniform mediump int u_bitsRangesEnd; @@ -58,7 +57,7 @@ fragment = highp float n_dot_l = mix(0.3, 0.7, dot(normal, light_dir)); final_color += (n_dot_l * diffuse_color); - final_color.a = u_opacity; + final_color.a = 1.0; frag_color = final_color; } @@ -95,7 +94,6 @@ fragment41core = uniform mediump vec4 u_ambientColor; uniform highp vec3 u_lightPosition; uniform highp vec3 u_viewPosition; - uniform mediump float u_opacity; uniform sampler2D u_texture; uniform mediump int u_bitsRangesStart; uniform mediump int u_bitsRangesEnd; @@ -125,14 +123,13 @@ fragment41core = highp float n_dot_l = mix(0.3, 0.7, dot(normal, light_dir)); final_color += (n_dot_l * diffuse_color); - final_color.a = u_opacity; + final_color.a = 1.0; frag_color = final_color; } [defaults] u_ambientColor = [0.3, 0.3, 0.3, 1.0] -u_opacity = 1.0 u_texture = 0 [bindings] From e69a4369423aa57cd00d81a4b459fb6f4888c30b Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 6 Aug 2025 16:15:05 +0200 Subject: [PATCH 295/299] Fix sometimes wrongly displayed view CURA-12660 This required a refactoring of the management of the active view. The previous behavior was that anyone could set the active view, depending on certain conditions. But now we also have a view that is set by a tool, so sometimes the actually set view would be incorrect. Now each Stage requests an active view, and each tool CAN also request an active view. Then the Controller decides which view should actually be active depending on the active stage and tool. --- cura/CuraApplication.py | 5 +---- cura/Stages/CuraStage.py | 6 ++++-- plugins/PaintTool/PaintTool.py | 22 ++++++++++------------ plugins/PaintTool/PaintView.py | 22 ++++------------------ plugins/PreviewStage/PreviewStage.py | 19 ------------------- plugins/SimulationView/SimulationView.py | 16 +++++++++++++--- resources/qml/ViewsSelector.qml | 4 ++-- 7 files changed, 34 insertions(+), 60 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 5ce358080c..57d4773cb3 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1038,7 +1038,6 @@ class CuraApplication(QtApplication): # Initialize UI state controller.setActiveStage("PrepareStage") - controller.setActiveView("SolidView") controller.setCameraTool("CameraTool") controller.setSelectionTool("SelectionTool") @@ -2089,9 +2088,7 @@ class CuraApplication(QtApplication): is_non_sliceable = "." + file_extension in self._non_sliceable_extensions if is_non_sliceable: - # Need to switch first to the preview stage and then to layer view - self.callLater(lambda: (self.getController().setActiveStage("PreviewStage"), - self.getController().setActiveView("SimulationView"))) + self.callLater(lambda: (self.getController().setActiveStage("PreviewStage"))) block_slicing_decorator = BlockSlicingDecorator() node.addDecorator(block_slicing_decorator) diff --git a/cura/Stages/CuraStage.py b/cura/Stages/CuraStage.py index 869ed309dc..8c207db8ad 100644 --- a/cura/Stages/CuraStage.py +++ b/cura/Stages/CuraStage.py @@ -1,6 +1,8 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +from typing import Optional + from PyQt6.QtCore import pyqtProperty, QUrl from UM.Stage import Stage @@ -13,8 +15,8 @@ from UM.Stage import Stage # * The MainComponent is the component that will be drawn starting from the bottom of the stageBar and fills the rest # of the screen. class CuraStage(Stage): - def __init__(self, parent = None) -> None: - super().__init__(parent) + def __init__(self, parent = None, active_view: Optional[str] = "SolidView") -> None: + super().__init__(parent, active_view = active_view) @pyqtProperty(str, constant = True) def stageId(self) -> str: diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index eaeb2dc69b..7a1b25f331 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -58,7 +58,8 @@ class PaintTool(Tool): self.setExposedProperties("PaintType", "BrushSize", "BrushColor", "BrushShape") - Selection.selectionChanged.connect(self._updateIgnoreUnselectedObjects) + Selection.selectionChanged.connect(self._updateActiveView) + self._controller.activeViewChanged.connect(self._updateIgnoreUnselectedObjects) def _createBrushPen(self) -> QPen: pen = QPen() @@ -298,14 +299,9 @@ class PaintTool(Tool): # Make sure the displayed values are updated if the bounding box of the selected mesh(es) changes if event.type == Event.ToolActivateEvent: - controller.setActiveView("PaintTool") # Because that's the plugin-name, and the view is registered to it. - self._updateIgnoreUnselectedObjects() return True if event.type == Event.ToolDeactivateEvent: - controller.setActiveView("SolidView") - CuraApplication.getInstance().getRenderer().getRenderPass("selection").setIgnoreUnselectedObjects(False) - CuraApplication.getInstance().getRenderer().getRenderPass("selection_faces").setIgnoreUnselectedObjects(False) return True if event.type == Event.MouseReleaseEvent and self._controller.getToolsEnabled(): @@ -397,6 +393,9 @@ class PaintTool(Tool): return False + def getRequiredExtraRenderingPasses(self) -> list[str]: + return ["selection_faces", "picking_selected"] + @staticmethod def _updateScene(node: SceneNode = None): if node is None: @@ -404,11 +403,10 @@ class PaintTool(Tool): if node is not None: Application.getInstance().getController().getScene().sceneChanged.emit(node) - def getRequiredExtraRenderingPasses(self) -> list[str]: - return ["selection_faces", "picking_selected"] + def _updateActiveView(self): + self.setActiveView("PaintTool" if len(Selection.getAllSelectedObjects()) == 1 else None) def _updateIgnoreUnselectedObjects(self): - if self._controller.getActiveTool() is self: - ignore_unselected_objects = len(Selection.getAllSelectedObjects()) == 1 - CuraApplication.getInstance().getRenderer().getRenderPass("selection").setIgnoreUnselectedObjects(ignore_unselected_objects) - CuraApplication.getInstance().getRenderer().getRenderPass("selection_faces").setIgnoreUnselectedObjects(ignore_unselected_objects) \ No newline at end of file + ignore_unselected_objects = self._controller.getActiveView().name == "PaintTool" + CuraApplication.getInstance().getRenderer().getRenderPass("selection").setIgnoreUnselectedObjects(ignore_unselected_objects) + CuraApplication.getInstance().getRenderer().getRenderPass("selection_faces").setIgnoreUnselectedObjects(ignore_unselected_objects) \ No newline at end of file diff --git a/plugins/PaintTool/PaintView.py b/plugins/PaintTool/PaintView.py index 73e8a511a6..22629e340c 100644 --- a/plugins/PaintTool/PaintView.py +++ b/plugins/PaintTool/PaintView.py @@ -9,8 +9,8 @@ from PyQt6.QtGui import QImage, QColor, QPainter from cura.CuraApplication import CuraApplication from cura.BuildVolume import BuildVolume +from cura.CuraView import CuraView from UM.PluginRegistry import PluginRegistry -from UM.View.View import View from UM.View.GL.ShaderProgram import ShaderProgram from UM.View.GL.Texture import Texture from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator @@ -22,7 +22,7 @@ from UM.Math.Color import Color catalog = i18nCatalog("cura") -class PaintView(View): +class PaintView(CuraView): """View for model-painting.""" UNDO_STACK_SIZE = 1024 @@ -33,7 +33,7 @@ class PaintView(View): self.value: int = value def __init__(self) -> None: - super().__init__() + super().__init__(use_empty_menu_placeholder = True) self._paint_shader: Optional[ShaderProgram] = None self._current_paint_texture: Optional[Texture] = None self._current_bits_ranges: tuple[int, int] = (0, 0) @@ -50,8 +50,6 @@ class PaintView(View): application.engineCreatedSignal.connect(self._makePaintModes) self._scene = application.getController().getScene() - self._solid_view = None - def _makePaintModes(self): theme = CuraApplication.getInstance().getTheme() usual_types = {"none": self.PaintType(Color(*theme.getColor("paint_normal_area").getRgb()), 0), @@ -179,18 +177,6 @@ class PaintView(View): if self._current_paint_type not in self._paint_modes: return - if self._solid_view is None: - plugin_registry = PluginRegistry.getInstance() - solid_view = plugin_registry.getPluginObject("SolidView") - if isinstance(solid_view, View): - self._solid_view = solid_view - - display_objects = Selection.getAllSelectedObjects().copy() - if len(display_objects) != 1 and self._solid_view is not None: - # Display the classic view until a single object is selected - self._solid_view.beginRendering() - return - self._checkSetup() renderer = self.getRenderer() @@ -201,7 +187,7 @@ class PaintView(View): paint_batch = renderer.createRenderBatch(shader=self._paint_shader) renderer.addRenderBatch(paint_batch) - for node in display_objects: + for node in Selection.getAllSelectedObjects(): paint_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData(), normal_transformation=node.getCachedNormalMatrix()) self._current_paint_texture = node.callDecoration("getPaintTexture") self._paint_shader.setTexture(0, self._current_paint_texture) diff --git a/plugins/PreviewStage/PreviewStage.py b/plugins/PreviewStage/PreviewStage.py index 88f432ef9b..3f1a4423b2 100644 --- a/plugins/PreviewStage/PreviewStage.py +++ b/plugins/PreviewStage/PreviewStage.py @@ -24,25 +24,6 @@ class PreviewStage(CuraStage): super().__init__(parent) self._application = application self._application.engineCreatedSignal.connect(self._engineCreated) - self._previously_active_view = None # type: Optional[View] - - def onStageSelected(self) -> None: - """When selecting the stage, remember which was the previous view so that - - we can revert to that view when we go out of the stage later. - """ - self._previously_active_view = self._application.getController().getActiveView() - - def onStageDeselected(self) -> None: - """Called when going to a different stage (away from the Preview Stage). - - When going to a different stage, the view should be reverted to what it - was before. Normally, that just reverts it to solid view. - """ - - if self._previously_active_view is not None: - self._application.getController().setActiveView(self._previously_active_view.getPluginId()) - self._previously_active_view = None def _engineCreated(self) -> None: """Delayed load of the QML files. diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py index 083fc73bf1..5d339e7f74 100644 --- a/plugins/SimulationView/SimulationView.py +++ b/plugins/SimulationView/SimulationView.py @@ -172,13 +172,20 @@ class SimulationView(CuraView): self._updateSliceWarningVisibility() self.activityChanged.emit() - def getSimulationPass(self) -> SimulationPass: + def getSimulationPass(self) -> Optional[SimulationPass]: if not self._layer_pass: + renderer = self.getRenderer() + if renderer is None: + return None + # Currently the RenderPass constructor requires a size > 0 # This should be fixed in RenderPass's constructor. self._layer_pass = SimulationPass(1, 1) self._compatibility_mode = self._evaluateCompatibilityMode() self._layer_pass.setSimulationView(self) + self._layer_pass.setEnabled(False) + renderer.addRenderPass(self._layer_pass) + return self._layer_pass def getCurrentLayer(self) -> int: @@ -734,11 +741,14 @@ class SimulationView(CuraView): # Make sure the SimulationPass is created layer_pass = self.getSimulationPass() + if layer_pass is None: + return False + renderer = self.getRenderer() if renderer is None: return False - renderer.addRenderPass(layer_pass) + layer_pass.setEnabled(True) # Make sure the NozzleNode is add to the root nozzle = self.getNozzleNode() @@ -778,7 +788,7 @@ class SimulationView(CuraView): return False if self._layer_pass is not None: - renderer.removeRenderPass(self._layer_pass) + self._layer_pass.setEnabled(False) if self._composite_pass: self._composite_pass.setLayerBindings(cast(List[str], self._old_layer_bindings)) self._composite_pass.setCompositeShader(cast(ShaderProgram, self._old_composite_shader)) diff --git a/resources/qml/ViewsSelector.qml b/resources/qml/ViewsSelector.qml index e76e5dbb67..b0e31ac532 100644 --- a/resources/qml/ViewsSelector.qml +++ b/resources/qml/ViewsSelector.qml @@ -38,7 +38,7 @@ Cura.ExpandablePopup { if (activeView == null) { - UM.Controller.setActiveView(viewModel.getItem(0).id) + UM.Controller.activeStage.setActiveView(viewModel.getItem(0).id) } } @@ -110,7 +110,7 @@ Cura.ExpandablePopup onClicked: { toggleContent() - UM.Controller.setActiveView(id) + UM.Controller.activeStage.setActiveView(id) } } } From db514f0be77dd585092ca77a1da977837b912b83 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 7 Aug 2025 11:03:51 +0200 Subject: [PATCH 296/299] Properly prepare the model for painting CURA-12660 The UV-unwrapping is now done in a background job, and the UI displays a waiting state. This fixes the issue where the user would start painting but the model was not ready yet, and the first stroke would be missing. --- plugins/PaintTool/PaintTool.py | 70 ++++++++++++++++--------- plugins/PaintTool/PaintTool.qml | 71 ++++++++++++++++++++++++++ plugins/PaintTool/PrepareTextureJob.py | 33 ++++++++++++ plugins/PaintTool/__init__.py | 1 + 4 files changed, 152 insertions(+), 23 deletions(-) create mode 100644 plugins/PaintTool/PrepareTextureJob.py diff --git a/plugins/PaintTool/PaintTool.py b/plugins/PaintTool/PaintTool.py index 7a1b25f331..82361e80ec 100644 --- a/plugins/PaintTool/PaintTool.py +++ b/plugins/PaintTool/PaintTool.py @@ -12,6 +12,7 @@ from numpy import ndarray from UM.Application import Application from UM.Event import Event, MouseEvent, KeyEvent +from UM.Job import Job from UM.Logger import Logger from UM.Scene.SceneNode import SceneNode from UM.Scene.Selection import Selection @@ -22,6 +23,7 @@ from cura.CuraApplication import CuraApplication from cura.PickingPass import PickingPass from UM.View.SelectionPass import SelectionPass from .PaintView import PaintView +from .PrepareTextureJob import PrepareTextureJob class PaintTool(Tool): @@ -33,6 +35,13 @@ class PaintTool(Tool): SQUARE = 0 CIRCLE = 1 + class Paint(QObject): + @pyqtEnum + class State(IntEnum): + MULTIPLE_SELECTION = 0 # Multiple objects are selected, wait until there is only one + PREPARING_MODEL = 1 # Model is being prepared (UV-unwrapping, texture generation) + READY = 2 # Ready to paint ! + def __init__(self) -> None: super().__init__() @@ -56,10 +65,13 @@ class PaintTool(Tool): self._last_mouse_coords: Optional[Tuple[int, int]] = None self._last_face_id: Optional[int] = None - self.setExposedProperties("PaintType", "BrushSize", "BrushColor", "BrushShape") + self._state: PaintTool.Paint.State = PaintTool.Paint.State.MULTIPLE_SELECTION + self._prepare_texture_job: Optional[PrepareTextureJob] = None + + self.setExposedProperties("PaintType", "BrushSize", "BrushColor", "BrushShape", "State") - Selection.selectionChanged.connect(self._updateActiveView) self._controller.activeViewChanged.connect(self._updateIgnoreUnselectedObjects) + self._controller.activeToolChanged.connect(self._updateState) def _createBrushPen(self) -> QPen: pen = QPen() @@ -141,6 +153,9 @@ class PaintTool(Tool): self._brush_pen = self._createBrushPen() self.propertyChanged.emit() + def getState(self) -> int: + return self._state + def undoStackAction(self, redo_instead: bool) -> bool: paint_view = self._get_paint_view() if paint_view is None: @@ -266,23 +281,6 @@ class PaintTool(Tool): self._iteratateSplitSubstroke(node, substrokes, mid_struct, info_b) self._iteratateSplitSubstroke(node, substrokes, info_a, mid_struct) - def _setupNodeForPainting(self, node: SceneNode) -> bool: - mesh = node.getMeshData() - if mesh.hasUVCoordinates(): - return True - - texture_width, texture_height = mesh.calculateUnwrappedUVCoordinates() - if texture_width <= 0 or texture_height <= 0: - return False - - node.callDecoration("prepareTexture", texture_width, texture_height) - - if hasattr(mesh, OpenGL.VertexBufferProperty): - # Force clear OpenGL buffer so that new UV coordinates will be sent - delattr(mesh, OpenGL.VertexBufferProperty) - - return True - def event(self, event: Event) -> bool: """Handle mouse and keyboard events. @@ -304,6 +302,9 @@ class PaintTool(Tool): if event.type == Event.ToolDeactivateEvent: return True + if self._state != PaintTool.Paint.State.READY: + return False + if event.type == Event.MouseReleaseEvent and self._controller.getToolsEnabled(): if MouseEvent.LeftButton not in cast(MouseEvent, event).buttons: return False @@ -356,9 +357,6 @@ class PaintTool(Tool): if not self._mesh_transformed_cache: return False - if not self._setupNodeForPainting(node): - return False - face_id, texcoords = self._getTexCoordsFromClick(node, mouse_evt.x, mouse_evt.y) if texcoords is None: return False @@ -403,8 +401,34 @@ class PaintTool(Tool): if node is not None: Application.getInstance().getController().getScene().sceneChanged.emit(node) - def _updateActiveView(self): + def _onSelectionChanged(self): + super()._onSelectionChanged() + self.setActiveView("PaintTool" if len(Selection.getAllSelectedObjects()) == 1 else None) + self._updateState() + + def _updateState(self): + if len(Selection.getAllSelectedObjects()) == 1 and self._controller.getActiveTool() == self: + selected_object = Selection.getSelectedObject(0) + if selected_object.callDecoration("getPaintTexture") is not None: + new_state = PaintTool.Paint.State.READY + else: + new_state = PaintTool.Paint.State.PREPARING_MODEL + self._prepare_texture_job = PrepareTextureJob(selected_object) + self._prepare_texture_job.finished.connect(self._onPrepareTextureFinished) + self._prepare_texture_job.start() + else: + new_state = PaintTool.Paint.State.MULTIPLE_SELECTION + + if new_state != self._state: + self._state = new_state + self.propertyChanged.emit() + + def _onPrepareTextureFinished(self, job: Job): + if job == self._prepare_texture_job: + self._prepare_texture_job = None + self._state = PaintTool.Paint.State.READY + self.propertyChanged.emit() def _updateIgnoreUnselectedObjects(self): ignore_unselected_objects = self._controller.getActiveView().name == "PaintTool" diff --git a/plugins/PaintTool/PaintTool.qml b/plugins/PaintTool/PaintTool.qml index 2bb3106dd5..7b04f9e58d 100644 --- a/plugins/PaintTool/PaintTool.qml +++ b/plugins/PaintTool/PaintTool.qml @@ -227,4 +227,75 @@ Item } } } + + Rectangle + { + id: waitPrepareItem + anchors.fill: parent + color: UM.Theme.getColor("main_background") + visible: UM.Controller.properties.getValue("State") === Cura.PaintToolState.PREPARING_MODEL + + ColumnLayout + { + anchors.fill: parent + + UM.Label + { + Layout.fillWidth: true + Layout.fillHeight: true + Layout.verticalStretchFactor: 2 + + text: catalog.i18nc("@label", "Preparing model for painting...") + verticalAlignment: Text.AlignBottom + horizontalAlignment: Text.AlignHCenter + } + + Item + { + Layout.preferredWidth: loadingIndicator.width + Layout.alignment: Qt.AlignHCenter + Layout.fillHeight: true + Layout.verticalStretchFactor: 1 + + UM.ColorImage + { + id: loadingIndicator + + anchors.top: parent.top + anchors.left: parent.left + width: UM.Theme.getSize("card_icon").width + height: UM.Theme.getSize("card_icon").height + source: UM.Theme.getIcon("ArrowDoubleCircleRight") + color: UM.Theme.getColor("text_default") + + RotationAnimator + { + target: loadingIndicator + from: 0 + to: 360 + duration: 2000 + loops: Animation.Infinite + running: true + alwaysRunToEnd: true + } + } + } + } + } + + Rectangle + { + id: selectSingleMessageItem + anchors.fill: parent + color: UM.Theme.getColor("main_background") + visible: UM.Controller.properties.getValue("State") === Cura.PaintToolState.MULTIPLE_SELECTION + + UM.Label + { + anchors.fill: parent + text: catalog.i18nc("@label", "Select a single model to start painting") + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } } diff --git a/plugins/PaintTool/PrepareTextureJob.py b/plugins/PaintTool/PrepareTextureJob.py new file mode 100644 index 0000000000..6c5e61c009 --- /dev/null +++ b/plugins/PaintTool/PrepareTextureJob.py @@ -0,0 +1,33 @@ +# Copyright (c) 2025 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from UM.Job import Job +from UM.Scene.SceneNode import SceneNode +from UM.View.GL.OpenGL import OpenGL + + +class PrepareTextureJob(Job): + """ + Background job to prepare a model for painting, i.e. do the UV-unwrapping and create the appropriate texture image, + which can last a few seconds + """ + + def __init__(self, node: SceneNode): + super().__init__() + self._node: SceneNode = node + + def run(self) -> None: + # If the model has already-provided UV coordinates, we can only assume that the associated texture + # should be a square + texture_width = texture_height = 4096 + + mesh = self._node.getMeshData() + if not mesh.hasUVCoordinates(): + texture_width, texture_height = mesh.calculateUnwrappedUVCoordinates() + + self._node.callDecoration("prepareTexture", texture_width, texture_height) + + if hasattr(mesh, OpenGL.VertexBufferProperty): + # Force clear OpenGL buffer so that new UV coordinates will be sent + delattr(mesh, OpenGL.VertexBufferProperty) + diff --git a/plugins/PaintTool/__init__.py b/plugins/PaintTool/__init__.py index e92c169ee6..93b47c7266 100644 --- a/plugins/PaintTool/__init__.py +++ b/plugins/PaintTool/__init__.py @@ -27,6 +27,7 @@ def getMetaData(): def register(app): qmlRegisterUncreatableType(PaintTool.PaintTool.Brush, "Cura", 1, 0, "This is an enumeration class", "PaintToolBrush") + qmlRegisterUncreatableType(PaintTool.PaintTool.Paint, "Cura", 1, 0, "This is an enumeration class", "PaintToolState") return { "tool": PaintTool.PaintTool(), "view": PaintView.PaintView() From 3da366f31633a93fc42c44d845aa2fcb4ee0ef06 Mon Sep 17 00:00:00 2001 From: HellAholic <28710690+HellAholic@users.noreply.github.com> Date: Mon, 11 Aug 2025 10:58:51 +0000 Subject: [PATCH 297/299] Apply printer-linter format --- resources/definitions/fdmprinter.def.json | 2 +- resources/definitions/ultimaker.def.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index d4813429ef..68852d805f 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -9603,4 +9603,4 @@ } } } -} +} \ No newline at end of file diff --git a/resources/definitions/ultimaker.def.json b/resources/definitions/ultimaker.def.json index 2995562e59..c5f441479b 100644 --- a/resources/definitions/ultimaker.def.json +++ b/resources/definitions/ultimaker.def.json @@ -227,4 +227,4 @@ "z_seam_relative": { "value": "True" }, "zig_zaggify_support": { "value": true } } -} +} \ No newline at end of file From d372c68bd7f03b069379780cb25445aaf84f3146 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 12 Aug 2025 11:58:41 +0000 Subject: [PATCH 298/299] Set conan package version 5.10.3 --- conandata.yml | 14 +++++++------- resources/conandata.yml | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/conandata.yml b/conandata.yml index 9d709096f4..da5149f15c 100644 --- a/conandata.yml +++ b/conandata.yml @@ -1,15 +1,15 @@ -version: "5.10.2" +version: "5.10.3" requirements: - - "cura_resources/5.10.2" - - "uranium/5.10.2" - - "curaengine/5.10.2" - - "cura_binary_data/5.10.2" - - "fdm_materials/5.10.2" + - "cura_resources/5.10.3" + - "uranium/5.10.3" + - "curaengine/5.10.3" + - "cura_binary_data/5.10.3" + - "fdm_materials/5.10.3" - "dulcificum/5.10.0" - "pysavitar/5.10.0" - "pynest2d/5.10.0" requirements_internal: - - "fdm_materials/5.10.2" + - "fdm_materials/5.10.3" - "cura_private_data/5.10.0-alpha.0@internal/testing" requirements_enterprise: - "native_cad_plugin/2.0.0" diff --git a/resources/conandata.yml b/resources/conandata.yml index c4418d4f57..71d63a5684 100644 --- a/resources/conandata.yml +++ b/resources/conandata.yml @@ -1 +1 @@ -version: "5.10.2" +version: "5.10.3" From a55cca73f405d1d2b5029379425068532668b320 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 26 Aug 2025 13:05:56 +0200 Subject: [PATCH 299/299] Apply Review clear_mask -> clear_texture_bit_mask --- plugins/PaintTool/PaintUndoCommand.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/PaintTool/PaintUndoCommand.py b/plugins/PaintTool/PaintUndoCommand.py index c100780c7f..50bfb787b7 100644 --- a/plugins/PaintTool/PaintUndoCommand.py +++ b/plugins/PaintTool/PaintUndoCommand.py @@ -40,7 +40,7 @@ class PaintUndoCommand(QUndoCommand): bit_range_start, bit_range_end = self._bit_range full_int32 = 0xffffffff - clear_mask = full_int32 ^ (((full_int32 << (32 - 1 - (bit_range_end - bit_range_start))) & full_int32) >> ( + clear_texture_bit_mask = full_int32 ^ (((full_int32 << (32 - 1 - (bit_range_end - bit_range_start))) & full_int32) >> ( 32 - 1 - bit_range_end)) image_rect = QRect(0, 0, self._stroke_mask.width(), self._stroke_mask.height()) @@ -48,7 +48,7 @@ class PaintUndoCommand(QUndoCommand): clear_bits_image.invertPixels() painter = QPainter(clear_bits_image) painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Lighten) - painter.fillRect(image_rect, clear_mask) + painter.fillRect(image_rect, clear_texture_bit_mask) painter.end() set_value_image = self._stroke_mask.copy()