FilamentChange.py 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # The PostProcessingPlugin is released 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