FilamentChange.py 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. # This PostProcessing Plugin script is released
  2. # under the terms of the AGPLv3 or higher
  3. from typing import Optional, Tuple
  4. from UM.Logger import Logger
  5. from ..Script import Script
  6. class FilamentChange(Script):
  7. _layer_keyword = ";LAYER:"
  8. def __init__(self):
  9. super().__init__()
  10. def getSettingDataString(self):
  11. return """{
  12. "name":"Filament Change",
  13. "key": "FilamentChange",
  14. "metadata": {},
  15. "version": 2,
  16. "settings":
  17. {
  18. "layer_number":
  19. {
  20. "label": "Layer",
  21. "description": "At what layer should color change occur. This will be before the layer starts printing. Specify multiple color changes with a comma.",
  22. "unit": "",
  23. "type": "str",
  24. "default_value": "1"
  25. },
  26. "initial_retract":
  27. {
  28. "label": "Initial Retraction",
  29. "description": "Initial filament retraction distance. The filament will be retracted with this amount before moving the nozzle away from the ongoing print.",
  30. "unit": "mm",
  31. "type": "float",
  32. "default_value": 30.0
  33. },
  34. "later_retract":
  35. {
  36. "label": "Later Retraction Distance",
  37. "description": "Later filament retraction distance for removal. The filament will be retracted all the way out of the printer so that you can change the filament.",
  38. "unit": "mm",
  39. "type": "float",
  40. "default_value": 300.0
  41. }
  42. }
  43. }"""
  44. def execute(self, data: list):
  45. """data is a list. Each index contains a layer"""
  46. layer_nums = self.getSettingValueByKey("layer_number")
  47. initial_retract = self.getSettingValueByKey("initial_retract")
  48. later_retract = self.getSettingValueByKey("later_retract")
  49. color_change = "M600"
  50. if initial_retract is not None and initial_retract > 0.:
  51. color_change = color_change + (" E%.2f" % initial_retract)
  52. if later_retract is not None and later_retract > 0.:
  53. color_change = color_change + (" L%.2f" % later_retract)
  54. color_change = color_change + " ; Generated by FilamentChange plugin"
  55. layer_targets = layer_nums.split(",")
  56. if len(layer_targets) > 0:
  57. for layer_num in layer_targets:
  58. layer_num = int(layer_num.strip())
  59. if layer_num <= len(data):
  60. index, layer_data = self._searchLayerData(data, layer_num - 1)
  61. if layer_data is None:
  62. Logger.log("e", "Could not found the layer")
  63. continue
  64. lines = layer_data.split("\n")
  65. lines.insert(2, color_change)
  66. final_line = "\n".join(lines)
  67. data[index] = final_line
  68. return data
  69. ## This method returns the data corresponding with the indicated layer number, looking in the gcode for
  70. # the occurrence of this layer number.
  71. def _searchLayerData(self, data: list, layer_num: int) -> Tuple[int, Optional[str]]:
  72. for index, layer_data in enumerate(data):
  73. first_line = layer_data.split("\n")[0]
  74. # The first line should contain the layer number at the beginning.
  75. if first_line[:len(self._layer_keyword)] == self._layer_keyword:
  76. # If found the layer that we are looking for, then return the data
  77. if first_line[len(self._layer_keyword):] == str(layer_num):
  78. return index, layer_data
  79. return 0, None