2 Slice engine communication.
3 This module handles all communication with the slicing engine.
5 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
23 from Cura.util.bigDataStorage import BigDataStorage
24 from Cura.util import profile
25 from Cura.util import pluginInfo
26 from Cura.util import version
27 from Cura.util import gcodeInterpreter
29 def getEngineFilename():
31 Finds and returns the path to the current engine executable. This is OS depended.
32 :return: The full path to the engine executable.
34 if platform.system() == 'Windows':
35 if version.isDevVersion() and os.path.exists('C:/Software/Cura_SteamEngine/_bin/Release/Cura_SteamEngine.exe'):
36 return 'C:/Software/Cura_SteamEngine/_bin/Release/Cura_SteamEngine.exe'
37 if version.isDevVersion() and os.path.exists('C:/Program Files (x86)/Cura_14.09/CuraEngine.exe'):
38 return 'C:/Program Files (x86)/Cura_14.09/CuraEngine.exe'
39 return os.path.abspath(os.path.join(os.path.dirname(__file__), '../..', 'CuraEngine.exe'))
40 if hasattr(sys, 'frozen'):
41 return os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../../..', 'CuraEngine'))
42 if os.path.isfile('/usr/bin/CuraEngine'):
43 return '/usr/bin/CuraEngine'
44 if os.path.isfile('/usr/local/bin/CuraEngine'):
45 return '/usr/local/bin/CuraEngine'
46 tempPath = os.path.abspath(os.path.join(os.path.dirname(__file__), '../..', 'CuraEngine'))
47 if os.path.isdir(tempPath):
48 tempPath = os.path.join(tempPath,'CuraEngine')
51 class EngineResult(object):
53 Result from running the CuraEngine.
54 Contains the engine log, polygons retrieved from the engine, the GCode and some meta-data.
58 self._gcodeData = BigDataStorage()
60 self._replaceInfo = {}
62 self._printTimeSeconds = None
63 self._filamentMM = [0.0] * 4
64 self._modelHash = None
65 self._profileString = profile.getProfileString()
66 self._preferencesString = profile.getPreferencesString()
67 self._gcodeInterpreter = gcodeInterpreter.gcode()
68 self._gcodeLoadThread = None
69 self._finished = False
71 def getFilamentWeight(self, e=0):
72 #Calculates the weight of the filament in kg
73 radius = float(profile.getProfileSetting('filament_diameter')) / 2
74 volumeM3 = (self._filamentMM[e] * (math.pi * radius * radius)) / (1000*1000*1000)
75 return volumeM3 * profile.getPreferenceFloat('filament_physical_density')
77 def getFilamentCost(self, e=0):
78 cost_kg = profile.getPreferenceFloat('filament_cost_kg')
79 cost_meter = profile.getPreferenceFloat('filament_cost_meter')
80 if cost_kg > 0.0 and cost_meter > 0.0:
81 return "%.2f / %.2f" % (self.getFilamentWeight(e) * cost_kg, self._filamentMM[e] / 1000.0 * cost_meter)
83 return "%.2f" % (self.getFilamentWeight(e) * cost_kg)
84 elif cost_meter > 0.0:
85 return "%.2f" % (self._filamentMM[e] / 1000.0 * cost_meter)
88 def getPrintTime(self):
89 if self._printTimeSeconds is None:
91 if int(self._printTimeSeconds / 60 / 60) < 1:
92 return _('%d minutes') % (int(self._printTimeSeconds / 60) % 60)
93 if int(self._printTimeSeconds / 60 / 60) == 1:
94 return _('%d hour %d minutes') % (int(self._printTimeSeconds / 60 / 60), int(self._printTimeSeconds / 60) % 60)
95 return _('%d hours %d minutes') % (int(self._printTimeSeconds / 60 / 60), int(self._printTimeSeconds / 60) % 60)
97 def getFilamentAmount(self, e=0):
98 if self._filamentMM[e] == 0.0:
100 return _('%0.2f meter %0.0f gram') % (float(self._filamentMM[e]) / 1000.0, self.getFilamentWeight(e) * 1000.0)
103 return self._engineLog
106 self._gcodeData.seekStart()
107 return self._gcodeData
109 def setGCode(self, gcode):
110 self._gcodeData = BigDataStorage()
111 self._gcodeData.write(gcode)
112 self._replaceInfo = {}
114 def addLog(self, line):
115 self._engineLog.append(line)
117 def setHash(self, hash):
118 self._modelHash = hash
120 def setFinished(self, result):
122 for k, v in self._replaceInfo.items():
123 self._gcodeData.replaceAtStart(k, v)
124 self._finished = result
126 def isFinished(self):
127 return self._finished
129 def getGCodeLayers(self, loadCallback):
130 if not self._finished:
132 if self._gcodeInterpreter.layerList is None and self._gcodeLoadThread is None:
133 self._gcodeInterpreter.progressCallback = self._gcodeInterpreterCallback
134 self._gcodeLoadThread = threading.Thread(target=lambda : self._gcodeInterpreter.load(self._gcodeData.clone()))
135 self._gcodeLoadCallback = loadCallback
136 self._gcodeLoadThread.daemon = True
137 self._gcodeLoadThread.start()
138 return self._gcodeInterpreter.layerList
140 def _gcodeInterpreterCallback(self, progress):
141 if len(self._gcodeInterpreter.layerList) % 5 == 0:
143 return self._gcodeLoadCallback(self, progress)
145 def submitInfoOnline(self):
146 if profile.getPreference('submit_slice_information') != 'True':
148 if version.isDevVersion():
151 'processor': platform.processor(),
152 'machine': platform.machine(),
153 'platform': platform.platform(),
154 'profile': self._profileString,
155 'preferences': self._preferencesString,
156 'modelhash': self._modelHash,
157 'version': version.getVersion(),
160 f = urllib2.urlopen("https://www.youmagine.com/curastats/", data = urllib.urlencode(data), timeout = 1)
165 traceback.print_exc()
167 class Engine(object):
169 Class used to communicate with the CuraEngine.
170 The CuraEngine is ran as a 2nd process and reports back information trough stderr.
171 GCode trough stdout and has a socket connection for polygon information and loading the 3D model into the engine.
173 GUI_CMD_REQUEST_MESH = 0x01
174 GUI_CMD_SEND_POLYGONS = 0x02
175 GUI_CMD_FINISH_OBJECT = 0x03
177 def __init__(self, progressCallback):
180 self._callback = progressCallback
181 self._progressSteps = ['inset', 'skin', 'export']
185 self._serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
186 self._serverPortNr = 0xC20A
187 for potential_port in xrange(0xC20A, 0xFFFF):
188 self._serverPortNr = potential_port
190 self._serversocket.bind(('127.0.0.1', self._serverPortNr))
193 print("Failed to listen on port: %d" % (self._serverPortNr))
195 print("Failed to listen on any port, this is a fatal error")
197 thread = threading.Thread(target=self._socketListenThread)
201 def _socketListenThread(self):
202 self._serversocket.listen(1)
203 print 'Listening for engine communications on %d' % (self._serverPortNr)
206 sock, _ = self._serversocket.accept()
207 thread = threading.Thread(target=self._socketConnectionThread, args=(sock,))
210 except socket.error, e:
211 if e.errno != errno.EINTR:
214 def _socketConnectionThread(self, sock):
224 cmd = struct.unpack('@i', data)[0]
225 if cmd == self.GUI_CMD_REQUEST_MESH:
226 meshInfo = self._modelData[0]
227 self._modelData = self._modelData[1:]
228 sock.sendall(struct.pack('@i', meshInfo[0]))
229 sock.sendall(meshInfo[1].tostring())
230 elif cmd == self.GUI_CMD_SEND_POLYGONS:
231 cnt = struct.unpack('@i', sock.recv(4))[0]
232 layerNr = struct.unpack('@i', sock.recv(4))[0]
233 layerNr += layerNrOffset
234 z = struct.unpack('@i', sock.recv(4))[0]
235 z = float(z) / 1000.0
236 typeNameLen = struct.unpack('@i', sock.recv(4))[0]
237 typeName = sock.recv(typeNameLen)
238 while len(self._result._polygons) < layerNr + 1:
239 self._result._polygons.append({})
240 polygons = self._result._polygons[layerNr]
241 if typeName not in polygons:
242 polygons[typeName] = []
243 for n in xrange(0, cnt):
244 length = struct.unpack('@i', sock.recv(4))[0]
246 while len(data) < length * 8 * 2:
247 recvData = sock.recv(length * 8 * 2 - len(data))
248 if len(recvData) < 1:
251 polygon2d = numpy.array(numpy.fromstring(data, numpy.int64), numpy.float32) / 1000.0
252 polygon2d = polygon2d.reshape((len(polygon2d) / 2, 2))
253 polygon = numpy.empty((len(polygon2d), 3), numpy.float32)
254 polygon[:,:-1] = polygon2d
256 polygons[typeName].append(polygon)
257 elif cmd == self.GUI_CMD_FINISH_OBJECT:
258 layerNrOffset = len(self._result._polygons)
260 print "Unknown command on socket: %x" % (cmd)
264 self._serversocket.close()
266 def abortEngine(self):
267 if self._process is not None:
269 self._process.terminate()
272 if self._thread is not None:
277 if self._thread is not None:
283 def runEngine(self, scene):
284 if len(scene.objects()) < 1:
287 for obj in scene.objects():
288 if scene.checkPlatform(obj):
289 extruderCount = max(extruderCount, len(obj._meshList))
291 extruderCount = max(extruderCount, profile.minimalExtruderCount())
293 commandList = [getEngineFilename(), '-v', '-p']
294 for k, v in self._engineSettings(extruderCount).iteritems():
295 commandList += ['-s', '%s=%s' % (k, str(v))]
296 commandList += ['-g', '%d' % (self._serverPortNr)]
299 hash = hashlib.sha512()
300 order = scene.printOrder()
302 pos = numpy.array(profile.getMachineCenterCoords()) * 1000
305 for obj in scene.objects():
306 if scene.checkPlatform(obj):
307 oMin = obj.getMinimum()[0:2] + obj.getPosition()
308 oMax = obj.getMaximum()[0:2] + obj.getPosition()
313 objMin[0] = min(oMin[0], objMin[0])
314 objMin[1] = min(oMin[1], objMin[1])
315 objMax[0] = max(oMax[0], objMax[0])
316 objMax[1] = max(oMax[1], objMax[1])
319 pos += (objMin + objMax) / 2.0 * 1000
320 commandList += ['-s', 'posx=%d' % int(pos[0]), '-s', 'posy=%d' % int(pos[1])]
322 vertexTotal = [0] * 4
324 for obj in scene.objects():
325 if scene.checkPlatform(obj):
326 meshMax = max(meshMax, len(obj._meshList))
327 for n in xrange(0, len(obj._meshList)):
328 vertexTotal[n] += obj._meshList[n].vertexCount
330 for n in xrange(0, meshMax):
331 verts = numpy.zeros((0, 3), numpy.float32)
332 for obj in scene.objects():
333 if scene.checkPlatform(obj):
334 if n < len(obj._meshList):
335 vertexes = (numpy.matrix(obj._meshList[n].vertexes, copy = False) * numpy.matrix(obj._matrix, numpy.float32)).getA()
336 vertexes -= obj._drawOffset
337 vertexes += numpy.array([obj.getPosition()[0], obj.getPosition()[1], 0.0])
338 verts = numpy.concatenate((verts, vertexes))
339 hash.update(obj._meshList[n].vertexes.tostring())
340 engineModelData.append((vertexTotal[n], verts))
342 commandList += ['$' * meshMax]
346 obj = scene.objects()[n]
347 for mesh in obj._meshList:
348 engineModelData.append((mesh.vertexCount, mesh.vertexes))
349 hash.update(mesh.vertexes.tostring())
350 pos = obj.getPosition() * 1000
351 pos += numpy.array(profile.getMachineCenterCoords()) * 1000
352 commandList += ['-m', ','.join(map(str, obj._matrix.getA().flatten()))]
353 commandList += ['-s', 'posx=%d' % int(pos[0]), '-s', 'posy=%d' % int(pos[1])]
354 commandList += ['$' * len(obj._meshList)]
356 modelHash = hash.hexdigest()
357 if self._objCount > 0:
358 self._thread = threading.Thread(target=self._watchProcess, args=(commandList, self._thread, engineModelData, modelHash))
359 self._thread.daemon = True
362 def _watchProcess(self, commandList, oldThread, engineModelData, modelHash):
363 if oldThread is not None:
364 if self._process is not None:
365 self._process.terminate()
368 self._modelData = engineModelData
370 self._process = self._runEngineProcess(commandList)
372 traceback.print_exc()
374 if self._thread != threading.currentThread():
375 self._process.terminate()
377 self._result = EngineResult()
378 self._result.addLog('Running: %s' % (' '.join(commandList)))
379 self._result.setHash(modelHash)
382 logThread = threading.Thread(target=self._watchStderr, args=(self._process.stderr,))
383 logThread.daemon = True
386 data = self._process.stdout.read(4096)
388 self._result._gcodeData.write(data)
389 data = self._process.stdout.read(4096)
391 returnCode = self._process.wait()
394 pluginError = pluginInfo.runPostProcessingPlugins(self._result)
395 if pluginError is not None:
397 self._result.addLog(pluginError)
398 self._result.setFinished(True)
401 for line in self._result.getLog():
406 def _watchStderr(self, stderr):
408 line = stderr.readline()
411 if line.startswith('Progress:'):
412 line = line.split(':')
413 if line[1] == 'process':
415 elif line[1] in self._progressSteps:
416 progressValue = float(line[2]) / float(line[3])
417 progressValue /= len(self._progressSteps)
418 progressValue += 1.0 / len(self._progressSteps) * self._progressSteps.index(line[1])
420 progressValue /= self._objCount
421 progressValue += 1.0 / self._objCount * objectNr
423 self._callback(progressValue)
426 elif line.startswith('Print time:'):
427 self._result._printTimeSeconds = int(line.split(':')[1].strip())
428 elif line.startswith('Filament:'):
429 self._result._filamentMM[0] = int(line.split(':')[1].strip())
430 if profile.getMachineSetting('gcode_flavor') == 'UltiGCode':
431 radius = profile.getProfileSettingFloat('filament_diameter') / 2.0
432 self._result._filamentMM[0] /= (math.pi * radius * radius)
433 elif line.startswith('Filament2:'):
434 self._result._filamentMM[1] = int(line.split(':')[1].strip())
435 if profile.getMachineSetting('gcode_flavor') == 'UltiGCode':
436 radius = profile.getProfileSettingFloat('filament_diameter') / 2.0
437 self._result._filamentMM[1] /= (math.pi * radius * radius)
438 elif line.startswith('Replace:'):
439 self._result._replaceInfo[line.split(':')[1].strip()] = line.split(':')[2].strip()
441 self._result.addLog(line)
442 line = stderr.readline()
444 def _engineSettings(self, extruderCount):
446 'layerThickness': int(profile.getProfileSettingFloat('layer_height') * 1000),
447 'initialLayerThickness': int(profile.getProfileSettingFloat('bottom_thickness') * 1000) if profile.getProfileSettingFloat('bottom_thickness') > 0.0 else int(profile.getProfileSettingFloat('layer_height') * 1000),
448 'filamentDiameter': int(profile.getProfileSettingFloat('filament_diameter') * 1000),
449 'filamentFlow': int(profile.getProfileSettingFloat('filament_flow')),
450 'extrusionWidth': int(profile.calculateEdgeWidth() * 1000),
451 'layer0extrusionWidth': int(profile.calculateEdgeWidth() * profile.getProfileSettingFloat('layer0_width_factor') / 100 * 1000),
452 'insetCount': int(profile.calculateLineCount()),
453 'downSkinCount': int(profile.calculateSolidLayerCount()) if profile.getProfileSetting('solid_bottom') == 'True' else 0,
454 'upSkinCount': int(profile.calculateSolidLayerCount()) if profile.getProfileSetting('solid_top') == 'True' else 0,
455 'infillOverlap': int(profile.getProfileSettingFloat('fill_overlap')),
456 'initialSpeedupLayers': int(4),
457 'initialLayerSpeed': int(profile.getProfileSettingFloat('bottom_layer_speed')),
458 'printSpeed': int(profile.getProfileSettingFloat('print_speed')),
459 'infillSpeed': int(profile.getProfileSettingFloat('infill_speed')) if int(profile.getProfileSettingFloat('infill_speed')) > 0 else int(profile.getProfileSettingFloat('print_speed')),
460 'inset0Speed': int(profile.getProfileSettingFloat('inset0_speed')) if int(profile.getProfileSettingFloat('inset0_speed')) > 0 else int(profile.getProfileSettingFloat('print_speed')),
461 'insetXSpeed': int(profile.getProfileSettingFloat('insetx_speed')) if int(profile.getProfileSettingFloat('insetx_speed')) > 0 else int(profile.getProfileSettingFloat('print_speed')),
462 'moveSpeed': int(profile.getProfileSettingFloat('travel_speed')),
463 'fanSpeedMin': int(profile.getProfileSettingFloat('fan_speed')) if profile.getProfileSetting('fan_enabled') == 'True' else 0,
464 'fanSpeedMax': int(profile.getProfileSettingFloat('fan_speed_max')) if profile.getProfileSetting('fan_enabled') == 'True' else 0,
465 'supportAngle': int(-1) if profile.getProfileSetting('support') == 'None' else int(profile.getProfileSettingFloat('support_angle')),
466 'supportEverywhere': int(1) if profile.getProfileSetting('support') == 'Everywhere' else int(0),
467 'supportLineDistance': int(100 * profile.calculateEdgeWidth() * 1000 / profile.getProfileSettingFloat('support_fill_rate')) if profile.getProfileSettingFloat('support_fill_rate') > 0 else -1,
468 'supportXYDistance': int(1000 * profile.getProfileSettingFloat('support_xy_distance')),
469 'supportZDistance': int(1000 * profile.getProfileSettingFloat('support_z_distance')),
470 'supportExtruder': 0 if profile.getProfileSetting('support_dual_extrusion') == 'First extruder' else (1 if profile.getProfileSetting('support_dual_extrusion') == 'Second extruder' and profile.minimalExtruderCount() > 1 else -1),
471 'retractionAmount': int(profile.getProfileSettingFloat('retraction_amount') * 1000) if profile.getProfileSetting('retraction_enable') == 'True' else 0,
472 'retractionSpeed': int(profile.getProfileSettingFloat('retraction_speed')),
473 'retractionMinimalDistance': int(profile.getProfileSettingFloat('retraction_min_travel') * 1000),
474 'retractionAmountExtruderSwitch': int(profile.getProfileSettingFloat('retraction_dual_amount') * 1000),
475 'retractionZHop': int(profile.getProfileSettingFloat('retraction_hop') * 1000),
476 'minimalExtrusionBeforeRetraction': int(profile.getProfileSettingFloat('retraction_minimal_extrusion') * 1000),
477 'enableCombing': 1 if profile.getProfileSetting('retraction_combing') == 'True' else 0,
478 'multiVolumeOverlap': int(profile.getProfileSettingFloat('overlap_dual') * 1000),
479 'objectSink': max(0, int(profile.getProfileSettingFloat('object_sink') * 1000)),
480 'minimalLayerTime': int(profile.getProfileSettingFloat('cool_min_layer_time')),
481 'minimalFeedrate': int(profile.getProfileSettingFloat('cool_min_feedrate')),
482 'coolHeadLift': 1 if profile.getProfileSetting('cool_head_lift') == 'True' else 0,
483 'startCode': profile.getAlterationFileContents('start.gcode', extruderCount),
484 'endCode': profile.getAlterationFileContents('end.gcode', extruderCount),
485 'preSwitchExtruderCode': profile.getAlterationFileContents('preSwitchExtruder.gcode', extruderCount),
486 'postSwitchExtruderCode': profile.getAlterationFileContents('postSwitchExtruder.gcode', extruderCount),
488 'extruderOffset[1].X': int(profile.getMachineSettingFloat('extruder_offset_x1') * 1000),
489 'extruderOffset[1].Y': int(profile.getMachineSettingFloat('extruder_offset_y1') * 1000),
490 'extruderOffset[2].X': int(profile.getMachineSettingFloat('extruder_offset_x2') * 1000),
491 'extruderOffset[2].Y': int(profile.getMachineSettingFloat('extruder_offset_y2') * 1000),
492 'extruderOffset[3].X': int(profile.getMachineSettingFloat('extruder_offset_x3') * 1000),
493 'extruderOffset[3].Y': int(profile.getMachineSettingFloat('extruder_offset_y3') * 1000),
496 fanFullHeight = int(profile.getProfileSettingFloat('fan_full_height') * 1000)
497 settings['fanFullOnLayerNr'] = (fanFullHeight - settings['initialLayerThickness'] - 1) / settings['layerThickness'] + 1
498 if settings['fanFullOnLayerNr'] < 0:
499 settings['fanFullOnLayerNr'] = 0
500 if profile.getProfileSetting('support_type') == 'Lines':
501 settings['supportType'] = 1
503 if profile.getProfileSettingFloat('fill_density') == 0:
504 settings['sparseInfillLineDistance'] = -1
505 elif profile.getProfileSettingFloat('fill_density') == 100:
506 settings['sparseInfillLineDistance'] = settings['extrusionWidth']
507 #Set the up/down skins height to 10000 if we want a 100% filled object.
508 # This gives better results then normal 100% infill as the sparse and up/down skin have some overlap.
509 settings['downSkinCount'] = 10000
510 settings['upSkinCount'] = 10000
512 settings['sparseInfillLineDistance'] = int(100 * profile.calculateEdgeWidth() * 1000 / profile.getProfileSettingFloat('fill_density'))
513 if profile.getProfileSetting('platform_adhesion') == 'Brim':
514 settings['skirtDistance'] = 0
515 settings['skirtLineCount'] = int(profile.getProfileSettingFloat('brim_line_count'))
516 elif profile.getProfileSetting('platform_adhesion') == 'Raft':
517 settings['skirtDistance'] = 0
518 settings['skirtLineCount'] = 0
519 settings['raftMargin'] = int(profile.getProfileSettingFloat('raft_margin') * 1000)
520 settings['raftLineSpacing'] = int(profile.getProfileSettingFloat('raft_line_spacing') * 1000)
521 settings['raftBaseThickness'] = int(profile.getProfileSettingFloat('raft_base_thickness') * 1000)
522 settings['raftBaseLinewidth'] = int(profile.getProfileSettingFloat('raft_base_linewidth') * 1000)
523 settings['raftInterfaceThickness'] = int(profile.getProfileSettingFloat('raft_interface_thickness') * 1000)
524 settings['raftInterfaceLinewidth'] = int(profile.getProfileSettingFloat('raft_interface_linewidth') * 1000)
525 settings['raftInterfaceLineSpacing'] = int(profile.getProfileSettingFloat('raft_interface_linewidth') * 1000 * 2.0)
526 settings['raftAirGapLayer0'] = int(profile.getProfileSettingFloat('raft_airgap') * 1000 + profile.getProfileSettingFloat('raft_airgap_all') * 1000)
527 settings['raftAirGap'] = int(profile.getProfileSettingFloat('raft_airgap_all') * 1000)
528 settings['raftBaseSpeed'] = int(profile.getProfileSettingFloat('bottom_layer_speed'))
529 settings['raftFanSpeed'] = 100
530 settings['raftSurfaceThickness'] = settings['raftInterfaceThickness']
531 settings['raftSurfaceLinewidth'] = int(profile.calculateEdgeWidth() * 1000)
532 settings['raftSurfaceLineSpacing'] = int(profile.calculateEdgeWidth() * 1000 * 0.9)
533 settings['raftSurfaceLayers'] = int(profile.getProfileSettingFloat('raft_surface_layers'))
534 settings['raftSurfaceSpeed'] = int(profile.getProfileSettingFloat('bottom_layer_speed'))
536 settings['skirtDistance'] = int(profile.getProfileSettingFloat('skirt_gap') * 1000)
537 settings['skirtLineCount'] = int(profile.getProfileSettingFloat('skirt_line_count'))
538 settings['skirtMinLength'] = int(profile.getProfileSettingFloat('skirt_minimal_length') * 1000)
540 if profile.getProfileSetting('fix_horrible_union_all_type_a') == 'True':
541 settings['fixHorrible'] |= 0x01
542 if profile.getProfileSetting('fix_horrible_union_all_type_b') == 'True':
543 settings['fixHorrible'] |= 0x02
544 if profile.getProfileSetting('fix_horrible_use_open_bits') == 'True':
545 settings['fixHorrible'] |= 0x10
546 if profile.getProfileSetting('fix_horrible_extensive_stitching') == 'True':
547 settings['fixHorrible'] |= 0x04
549 if settings['layerThickness'] <= 0:
550 settings['layerThickness'] = 1000
551 if profile.getMachineSetting('gcode_flavor') == 'UltiGCode':
552 settings['gcodeFlavor'] = 1
553 elif profile.getMachineSetting('gcode_flavor') == 'MakerBot':
554 settings['gcodeFlavor'] = 2
555 elif profile.getMachineSetting('gcode_flavor') == 'BFB':
556 settings['gcodeFlavor'] = 3
557 elif profile.getMachineSetting('gcode_flavor') == 'Mach3':
558 settings['gcodeFlavor'] = 4
559 elif profile.getMachineSetting('gcode_flavor') == 'RepRap (Volumetric)':
560 settings['gcodeFlavor'] = 5
561 if profile.getProfileSetting('spiralize') == 'True':
562 settings['spiralizeMode'] = 1
563 if profile.getProfileSetting('simple_mode') == 'True':
564 settings['simpleMode'] = 1
565 if profile.getProfileSetting('wipe_tower') == 'True' and extruderCount > 1:
566 settings['wipeTowerSize'] = int(math.sqrt(profile.getProfileSettingFloat('wipe_tower_volume') * 1000 * 1000 * 1000 / settings['layerThickness']))
567 if profile.getProfileSetting('ooze_shield') == 'True':
568 settings['enableOozeShield'] = 1
571 def _runEngineProcess(self, cmdList):
573 if subprocess.mswindows:
574 su = subprocess.STARTUPINFO()
575 su.dwFlags |= subprocess.STARTF_USESHOWWINDOW
576 su.wShowWindow = subprocess.SW_HIDE
577 kwargs['startupinfo'] = su
578 kwargs['creationflags'] = 0x00004000 #BELOW_NORMAL_PRIORITY_CLASS
579 return subprocess.Popen(cmdList, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)