forked from gargansa/MELT
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ColorShift.py
307 lines (276 loc) · 13.6 KB
/
ColorShift.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
from ..Script import Script
# current problems...
# running two sets of post processing fails the second post process
# possibly need an option for shift every 4 layers and shift about 100 times per print to be more clear with choices
# need description of project
# Recent fixed problems
# Reduced size of clamp function
# Reduced size of adjust_extruder_rate function
# simplified verifying input isn't backwards for layer_no and percentage
# simplified initiate_extruder function
# Math is correct between starting layer shift and ending layer shift so that ratio starts at 0:1 and ends at 1:0 instead of ending at 0.994:0.006 for example
# potential updates
# possible initial option choices
# easy mode (shift approx 100 times from top to bottom)
# Clamp Percentage (shift every n layers between start percentage and end percentage)
# clamp layer (shift every n layers between defined start and stop layers)
# possible secondary option (type of shifts)
# normal shift
# reverse shift
# logarithmic shift
# exponential shift
# fibonacci shift (1+1+2+3+5+8)
# heartbeat shift (pulse to set degree and frequency)
# wood shift (randomize up to degree of change and length of ring)
# Credits
# gargansa, bass4aj
# convenience function for coding familiarity
def clamp(value, minimum, maximum):
return max(minimum, min(value, maximum))
# function to compile the initial setup into a string
def initiate_extruder(existing_gcode,*ext):
qty_ext = len(ext)
setup_line = ""
setup_line += ";Modified by ColorShift" + "\n"
setup_line += existing_gcode + " Modified:\n"
#define tool
for i in range(0, qty_ext):
if i == 0:
setup_line += "M563 P0 D" + str(i)
else:
setup_line += ":" + str(i)
setup_line += " H1 ;Define tool 0" + "\n"
#position tool
for i in range(0, qty_ext):
setup_line += "M563 P2 D" + str(i) + " H" + str(i+1)
setup_line += " ;Position " + str(i+1) + " tool" + "\n"
#set axis offsets
setup_line += "G10 P0 X0 Y0 Z0 ;Set tool 0 axis offsets" + "\n"
#activate tool
setup_line += "G10 P2 R120 S220 ;Set initial tool 0 active" + "\n"
#set initial extrusion rate
setup_line += adjust_extruder_rate(";Initial Extruder Rate", *ext)
#initiate the tool
setup_line += "M568 P0 S1 ;Turn on tool mixing for the extruder" + "\n"
return setup_line
# function to compile extruder info into a string
def adjust_extruder_rate(existing_gcode, *ext):
i = 0
for item in ext:
if i == 0:
setup_line = existing_gcode + " ;Modified: \nM567 P0 E" + str(item)
else:
setup_line += ":" + str(item) + "\n"
i += 1
return setup_line
class ColorShift(Script):
version = "1.0.0"
def __init__(self):
super().__init__()
def getSettingDataString(self):
return """{
"name":"ColorShift",
"key":"ColorShift",
"metadata": {},
"version": 2,
"settings":
{
"a_trigger":
{
"label": "Shifting Clamp Type",
"description": "Begin and end shifting at percentage or layer.",
"type": "enum",
"options": {"percent":"Percentage","layer_no":"Layer No."},
"default_value": "percent"
},
"percent_change_start":
{
"label": "Extrusion % Start",
"description": "Percentage of layer height to start shifting extruder percentage.",
"unit": "%",
"type": "float",
"default_value": 0,
"minimum_value": "0",
"maximum_value": "100",
"minimum_value_warning": "0",
"maximum_value_warning": "99",
"enabled": "a_trigger == 'percent'"
},
"percent_change_end":
{
"label": "Extrusion % End",
"description": "Percentage of layer height to stop shifting extruder percentage.",
"unit": "%",
"type": "float",
"default_value": 100,
"minimum_value": "0",
"maximum_value": "100",
"minimum_value_warning": "1",
"maximum_value_warning": "100",
"enabled": "a_trigger == 'percent'"
},
"layer_change_start":
{
"label": "Extrusion # Start",
"description": "Layer to start shifting extruder percentage.",
"unit": "#",
"type": "int",
"default_value": 0,
"minimum_value": "0",
"enabled": "a_trigger == 'layer_no'"
},
"layer_change_end":
{
"label": "Extrusion # End",
"description": "Layer to stop changing extruder percentage. If layer is more then total layers the max layer will be chosen.",
"unit": "#",
"type": "int",
"default_value": 100000,
"minimum_value": "0",
"enabled": "a_trigger == 'layer_no'"
},
"b_trigger":
{
"label": "Direction of Shift",
"description": "Allows the shift to run the opposite direction without swapping filaments.",
"type": "enum",
"options": {"normal":"Normal","reversed":"Reversed"},
"default_value": "normal"
},
"e1_trigger":
{
"label": "Expert Controls",
"description": "Enable more controls. Some of which are for debugging purposes and may change or be removed later",
"type": "bool",
"default_value": false
},
"adjustments":
{
"label": "Adjustments",
"description": "To grant an even shift adjustments are calculated based on this formula affected_layers/adjustments = change rate. The affected_layers are the total layers within the clamp set by percentages or layer numbers chosen. Adjustments are set here. The resulting change_rate is rounded down and the print will shift every count of change_rate.",
"unit": "# of changes",
"type": "int",
"default_value": 100,
"minimum_value": "1",
"maximum_value": "400",
"minimum_value_warning": "1",
"maximum_value_warning": "200",
"enabled": "e1_trigger"
},
"flow_one_adjust":
{
"label": "Ext One Flow Adjust",
"description": "This compensates for under or over extrusion due to variances in filament",
"unit": "% + -",
"type": "float",
"default_value": 0,
"minimum_value": "-20",
"maximum_value": "20",
"minimum_value_warning": "-5",
"maximum_value_warning": "5",
"enabled": "e1_trigger"
},
"flow_two_adjust":
{
"label": "Ext Two Flow Adjust",
"description": "This compensates for under or over extrusion due to variances in filament",
"unit": "% + -",
"type": "float",
"default_value": 0,
"minimum_value": "-20",
"maximum_value": "20",
"minimum_value_warning": "-5",
"maximum_value_warning": "5",
"enabled": "e1_trigger"
},
"flow_min":
{
"label": "Minimum Flow Allowed",
"description": "Clamp to keep both extruders flowing a small amount to prevent clogs",
"unit": "%",
"type": "float",
"default_value": 1,
"minimum_value": "0",
"maximum_value": "10",
"minimum_value_warning": "1",
"maximum_value_warning": "5",
"enabled": "e1_trigger"
}
}
}"""
def execute(self, data: list): # used to be data: list
# Set user settings from cura
choice = self.getSettingValueByKey("a_trigger")
direction = self.getSettingValueByKey("b_trigger")
adjustments = int(clamp(self.getSettingValueByKey("adjustments"), 0, 999)) # clamp within understandable range
flow_one_adjust = float((self.getSettingValueByKey("flow_one_adjust"))/100)+1 # convert user input into multi
flow_two_adjust = float((self.getSettingValueByKey("flow_two_adjust"))/100)+1 # convert user input into multi
flow_min = float(self.getSettingValueByKey("flow_min")/100)
flow_clamp_adjust = float(1-(flow_min*2))
# Make sure user settings are in order after loading
percent_start = float(self.getSettingValueByKey("percent_change_start")/100)
percent_end = float(self.getSettingValueByKey("percent_change_end")/100)
if percent_end < percent_start:
percent_start, percent_end = percent_end, percent_start
# Make sure user settings are in order after loading
layer_start = int(self.getSettingValueByKey("layer_change_start"))
layer_end = int(self.getSettingValueByKey("layer_change_end"))
if layer_end < layer_start:
layer_start, layer_end = layer_end, layer_start
# Initialize things that affect decisions
current_position = 0
index = 0
# Iterate through the layers
for active_layer in data:
# Remove the whitespace and split the gcode into lines
lines = active_layer.strip().split("\n")
modified_gcode = ""
for line in lines:
# Find where to add the initial setup info
if ";LAYER_COUNT:" in line:
# Find the actual total layers in the gcode
total_layers = float(line[(line.index(':') + 1): len(line)])
# Calculate positions based on total_layers
if choice == 'percent':
start_position = int(int(total_layers) * float(percent_start)) # find where to start
current_position = start_position
end_position = int(int(total_layers) * float(percent_end)) # find where to end
if choice == 'layer_no':
start_position = int(clamp(layer_start, 0, total_layers))
current_position = start_position
end_position = int(clamp(layer_end, 0, total_layers))
# Find the layers that are actually affected or the ones within the clamp set by user
adjusted_layers = end_position - current_position
# Make sure that the set adjustments are less then the actual affected layers since you can only adjust once per layer
adjustments = clamp(int(adjustments), 0, adjusted_layers)
# Find how often to adjust the rate
change_rate = int(int(adjusted_layers) / int(adjustments))
# Math to determine extruder percentage based on layer location without flow clamp and adjustments
location = (current_position-start_position)/(adjusted_layers-change_rate)
# Adjust extruder percentages by user set flow and clamp adjustments
extruder_one = format(location * flow_one_adjust * flow_clamp_adjust + flow_min, '.3f')
extruder_two = format((1-location) * flow_two_adjust * flow_clamp_adjust + flow_min, '.3f')
# Send extruder percentages to be compiled into a string based on direction set by user
if direction == 'normal':
modified_gcode = initiate_extruder(line, extruder_one, extruder_two)
else:
modified_gcode = initiate_extruder(line, extruder_two, extruder_one)
# Find where to add for affected layers
elif ";LAYER:" + str(current_position) in line and int(current_position) < int(end_position):
# Same thing we did above
location = (current_position-start_position)/(adjusted_layers-change_rate)
extruder_one = format(location*flow_one_adjust * flow_clamp_adjust + flow_min, '.3f')
extruder_two = format((1-location)*flow_two_adjust * flow_clamp_adjust + flow_min, '.3f')
if direction == 'normal':
modified_gcode = adjust_extruder_rate(line, extruder_one, extruder_two)
else:
modified_gcode = adjust_extruder_rate(line, extruder_two, extruder_one)
# Increase the position for the next line to find it on the next loop
current_position += int(change_rate)
# If no conditions apply leave the code alone
else:
modified_gcode += line + "\n"
# Replace the data
data[index] = modified_gcode
index += 1
return data