mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-04-22 05:39:37 +08:00
191 lines
7.5 KiB
Python
191 lines
7.5 KiB
Python
# 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
|
|
|
|
## Uses -
|
|
## M163 - Set Mix Factor
|
|
## M164 - Save Mix - saves to T3 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",
|
|
"key":"ColorMix 2-1",
|
|
"metadata": {},
|
|
"version": 2,
|
|
"settings":
|
|
{
|
|
"measurement_units":
|
|
{
|
|
"label": "Units of measurement",
|
|
"description": "Input value as mm or layer number.",
|
|
"type": "enum",
|
|
"options": {"mm":"mm","layer":"Layer"},
|
|
"default_value": "layer"
|
|
},
|
|
"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": "0.1",
|
|
"enabled": "c_behavior == 'blend_value'"
|
|
},
|
|
"mix_start_ratio":
|
|
{
|
|
"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_ratio":
|
|
{
|
|
"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": "c_behavior == 'blend_value'"
|
|
},
|
|
"notes":
|
|
{
|
|
"label": "Notes",
|
|
"description": "A spot to put a note",
|
|
"type": "str",
|
|
"default_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):
|
|
#get user variables
|
|
firstHeight = 0.0
|
|
secondHeight = 0.0
|
|
firstMix = 0.0
|
|
SecondMix = 0.0
|
|
|
|
firstHeight = self.getSettingValueByKey("start_height")
|
|
secondHeight = self.getSettingValueByKey("finish_height")
|
|
firstMix = self.getSettingValueByKey("mix_start_ratio")
|
|
SecondMix = self.getSettingValueByKey("mix_finish_ratio")
|
|
|
|
#locals
|
|
layer = 0
|
|
|
|
#get layer height
|
|
layerHeight = .2
|
|
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
|
|
#get layers to use
|
|
startLayer = 0
|
|
endLayer = 0
|
|
if self.getSettingValueByKey("measurement_units") == "mm":
|
|
if firstHeight == 0:
|
|
startLayer = 0
|
|
else:
|
|
startLayer = firstHeight / layerHeight
|
|
if secondHeight == 0:
|
|
endLayer = 0
|
|
else:
|
|
endLayer = secondHeight / layerHeight
|
|
else: #layer height
|
|
startLayer = firstHeight
|
|
endLayer = secondHeight
|
|
#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
|
|
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)
|
|
if (layer >= startLayer) and (layer <= endLayer): #find layers of interest
|
|
if lines[lineIndex + 4] == "T2": #check if needing to delete old data
|
|
del lines[(lineIndex + 1):(lineIndex + 5)]
|
|
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
|