123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- # ColorMix script - 2-1 extruder color mix and blending
- # This script is specific for the Geeetech A10M dual extruder but should work with other Marlin printers.
- # It runs with the PostProcessingPlugin which is released under the terms of the AGPLv3 or higher.
- # This script is licensed under the Creative Commons - Attribution - Share Alike (CC BY-SA) terms
- #Authors of the 2-1 ColorMix plug-in / script:
- # Written by John Hryb - john.hryb.4@gmail.com
- #history / change-log:
- #V1.0.0 - Initial
- #V1.1.0 -
- # additions:
- #Object number - To select individual models or all when using "one at a time" print sequence
- #V1.2.0
- # fixed layer heights Cura starts at 1 while G-code starts at 0
- # removed notes
- # changed Units of measurement to Units
- #V1.2.1
- # Fixed mm bug when not in multiples of layer height
- # Uses -
- # M163 - Set Mix Factor
- # M164 - Save Mix - saves to T2 as a unique mix
- import re #To perform the search and replace.
- from ..Script import Script
- class ColorMix(Script):
- def __init__(self):
- super().__init__()
- def getSettingDataString(self):
- return """{
- "name":"ColorMix 2-1 V1.2.1",
- "key":"ColorMix 2-1",
- "metadata": {},
- "version": 2,
- "settings":
- {
- "units_of_measurement":
- {
- "label": "Units",
- "description": "Input value as mm or layer number.",
- "type": "enum",
- "options": {"mm":"mm","layer":"Layer"},
- "default_value": "layer"
- },
- "object_number":
- {
- "label": "Object Number",
- "description": "Select model to apply to for print one at a time print sequence. 0 = everything",
- "type": "int",
- "default_value": 0,
- "minimum_value": "0"
- },
- "start_height":
- {
- "label": "Start Height",
- "description": "Value to start at (mm or layer)",
- "type": "float",
- "default_value": 0,
- "minimum_value": "0"
- },
- "behavior":
- {
- "label": "Fixed or blend",
- "description": "Select Fixed (set new mixture) or Blend mode (dynamic mix)",
- "type": "enum",
- "options": {"fixed_value":"Fixed","blend_value":"Blend"},
- "default_value": "fixed_value"
- },
- "finish_height":
- {
- "label": "Finish Height",
- "description": "Value to stop at (mm or layer)",
- "type": "float",
- "default_value": 0,
- "minimum_value": "0",
- "minimum_value_warning": "start_height",
- "enabled": "behavior == 'blend_value'"
- },
- "mix_start":
- {
- "label": "Start mix ratio",
- "description": "First extruder percentage 0-100",
- "type": "float",
- "default_value": 100,
- "minimum_value": "0",
- "minimum_value_warning": "0",
- "maximum_value_warning": "100"
- },
- "mix_finish":
- {
- "label": "End mix ratio",
- "description": "First extruder percentage 0-100 to finish blend",
- "type": "float",
- "default_value": 0,
- "minimum_value": "0",
- "minimum_value_warning": "0",
- "maximum_value_warning": "100",
- "enabled": "behavior == 'blend_value'"
- }
- }
- }"""
- def getValue(self, line, key, default = None): #replace default getvalue due to comment-reading feature
- if not key in line or (";" in line and line.find(key) > line.find(";") and
- not ";ChangeAtZ" in key and not ";LAYER:" in key):
- return default
- subPart = line[line.find(key) + len(key):] #allows for string lengths larger than 1
- if ";ChangeAtZ" in key:
- m = re.search("^[0-4]", subPart)
- elif ";LAYER:" in key:
- m = re.search("^[+-]?[0-9]*", subPart)
- else:
- #the minus at the beginning allows for negative values, e.g. for delta printers
- m = re.search("^[-]?[0-9]*\.?[0-9]*", subPart)
- if m == None:
- return default
- try:
- return float(m.group(0))
- except:
- return default
- def execute(self, data):
- firstHeight = self.getSettingValueByKey("start_height")
- secondHeight = self.getSettingValueByKey("finish_height")
- firstMix = self.getSettingValueByKey("mix_start")
- secondMix = self.getSettingValueByKey("mix_finish")
- modelOfInterest = self.getSettingValueByKey("object_number")
- #get layer height
- layerHeight = 0
- for active_layer in data:
- lines = active_layer.split("\n")
- for line in lines:
- if ";Layer height: " in line:
- layerHeight = self.getValue(line, ";Layer height: ", layerHeight)
- break
- if layerHeight != 0:
- break
- #default layerHeight if not found
- if layerHeight == 0:
- layerHeight = .2
- #get layers to use
- startLayer = 0
- endLayer = 0
- if self.getSettingValueByKey("units_of_measurement") == "mm":
- startLayer = round(firstHeight / layerHeight)
- endLayer = round(secondHeight / layerHeight)
- else: #layer height shifts down by one for g-code
- if firstHeight <= 0:
- firstHeight = 1
- if secondHeight <= 0:
- secondHeight = 1
- startLayer = firstHeight - 1
- endLayer = secondHeight - 1
- #see if one-shot
- if self.getSettingValueByKey("behavior") == "fixed_value":
- endLayer = startLayer
- firstExtruderIncrements = 0
- else: #blend
- firstExtruderIncrements = (secondMix - firstMix) / (endLayer - startLayer)
- firstExtruderValue = 0
- index = 0
- #start scanning
- layer = -1
- modelNumber = 0
- for active_layer in data:
- modified_gcode = ""
- lineIndex = 0
- lines = active_layer.split("\n")
- for line in lines:
- #dont leave blanks
- if line != "":
- modified_gcode += line + "\n"
- # find current layer
- if ";LAYER:" in line:
- layer = self.getValue(line, ";LAYER:", layer)
- #get model number by layer 0 repeats
- if layer == 0:
- modelNumber = modelNumber + 1
- #search for layers to manipulate
- if (layer >= startLayer) and (layer <= endLayer):
- #make sure correct model is selected
- if (modelOfInterest == 0) or (modelOfInterest == modelNumber):
- #Delete old data if required
- if lines[lineIndex + 4] == "T2":
- del lines[(lineIndex + 1):(lineIndex + 5)]
- #add mixing commands
- firstExtruderValue = int(((layer - startLayer) * firstExtruderIncrements) + firstMix)
- if firstExtruderValue == 100:
- modified_gcode += "M163 S0 P1\n"
- modified_gcode += "M163 S1 P0\n"
- elif firstExtruderValue == 0:
- modified_gcode += "M163 S0 P0\n"
- modified_gcode += "M163 S1 P1\n"
- else:
- modified_gcode += "M163 S0 P0.{:02d}\n".format(firstExtruderValue)
- modified_gcode += "M163 S1 P0.{:02d}\n".format(100 - firstExtruderValue)
- modified_gcode += "M164 S2\n"
- modified_gcode += "T2\n"
- lineIndex += 1 #for deleting index
- data[index] = modified_gcode
- index += 1
- return data
|