10 from Cura.util import profile
12 def getEngineFilename():
13 if platform.system() == 'Windows':
14 if os.path.exists('C:/Software/Cura_SteamEngine/_bin/Release/Cura_SteamEngine.exe'):
15 return 'C:/Software/Cura_SteamEngine/_bin/Release/Cura_SteamEngine.exe'
16 return os.path.abspath(os.path.join(os.path.dirname(__file__), '../..', 'SteamEngine.exe'))
17 return os.path.abspath(os.path.join(os.path.dirname(__file__), '../..', 'SteamEngine'))
19 def getTempFilename():
20 warnings.simplefilter('ignore')
21 ret = os.tempnam(None, "Cura_Tmp")
22 warnings.simplefilter('default')
26 def __init__(self, progressCallback):
29 self._callback = progressCallback
30 self._binaryStorageFilename = getTempFilename()
31 self._exportFilename = getTempFilename()
32 self._progressSteps = ['inset', 'skin', 'export']
37 os.remove(self._binaryStorageFilename)
38 os.remove(self._exportFilename)
40 def abortSlicer(self):
41 if self._process is not None:
43 self._process.terminate()
48 def getGCodeFilename(self):
49 return self._exportFilename
51 def runSlicer(self, scene):
53 self._callback(0.0, False)
55 commandList = [getEngineFilename(), '-vv']
56 for k, v in self._engineSettings().iteritems():
57 commandList += ['-s', '%s=%s' % (k, str(v))]
58 commandList += ['-o', self._exportFilename]
59 commandList += ['-b', self._binaryStorageFilename]
61 with open(self._binaryStorageFilename, "wb") as f:
62 for n in scene.printOrder():
63 obj = scene.objects()[n]
64 for mesh in obj._meshList:
65 n = numpy.array([mesh.vertexCount], numpy.int32)
67 f.write(mesh.vertexes.tostring())
68 pos = obj.getPosition() * 1000
69 pos += numpy.array([profile.getPreferenceFloat('machine_width') * 1000 / 2, profile.getPreferenceFloat('machine_depth') * 1000 / 2])
70 commandList += ['-m', ','.join(map(str, obj._matrix.getA().flatten()))]
71 commandList += ['-s', 'posx=%d' % int(pos[0]), '-s', 'posy=%d' % int(pos[1])]
72 commandList += ['#' * len(obj._meshList)]
74 if self._objCount > 0:
75 print ' '.join(commandList)
77 self._process = self._runSliceProcess(commandList)
78 self._thread = threading.Thread(target=self._watchProcess)
79 self._thread.daemon = True
84 def _watchProcess(self):
85 self._callback(0.0, False)
86 line = self._process.stdout.readline()
90 if line.startswith('Progress:'):
91 line = line.split(':')
92 if line[1] == 'process':
94 elif line[1] in self._progressSteps:
95 progressValue = float(line[2]) / float(line[3])
96 progressValue /= len(self._progressSteps)
97 progressValue += 1.0 / len(self._progressSteps) * self._progressSteps.index(line[1])
99 progressValue /= self._objCount
100 progressValue += 1.0 / self._objCount * objectNr
102 self._callback(progressValue, False)
106 #print '#', line.strip()
108 line = self._process.stdout.readline()
109 for line in self._process.stderr:
111 returnCode = self._process.wait()
115 self._callback(1.0, True)
117 self._callback(0.0, False)
122 def _engineSettings(self):
124 'layerThickness': int(profile.getProfileSettingFloat('layer_height') * 1000),
125 'initialLayerThickness': int(profile.getProfileSettingFloat('bottom_thickness') * 1000),
126 'filamentDiameter': int(profile.getProfileSettingFloat('filament_diameter') * 1000),
127 'extrusionWidth': int(profile.calculateEdgeWidth() * 1000),
128 'insetCount': int(profile.calculateLineCount()),
129 'downSkinCount': int(profile.calculateSolidLayerCount()),
130 'upSkinCount': int(profile.calculateSolidLayerCount()),
131 'sparseInfillLineDistance': int(100 * profile.calculateEdgeWidth() * 1000 / profile.getProfileSettingFloat('fill_density')) if profile.getProfileSettingFloat('fill_density') > 0 else 9999999999,
132 'skirtDistance': int(profile.getProfileSettingFloat('skirt_gap') * 1000),
133 'skirtLineCount': int(profile.getProfileSettingFloat('skirt_line_count')),
134 'initialSpeedupLayers': int(4),
135 'initialLayerSpeed': int(profile.getProfileSettingFloat('bottom_layer_speed')),
136 'printSpeed': int(profile.getProfileSettingFloat('print_speed')),
137 'moveSpeed': int(profile.getProfileSettingFloat('travel_speed')),
138 'fanOnLayerNr': int(profile.getProfileSettingFloat('fan_layer')),
139 'supportAngle': int(-1) if profile.getProfileSetting('support') == 'None' else int(60),
140 'supportEverywhere': int(1) if profile.getProfileSetting('support') == 'Everywhere' else int(0),
141 'retractionAmount': int(profile.getProfileSettingFloat('retraction_amount') * 1000),
142 'retractionSpeed': int(profile.getProfileSettingFloat('retraction_speed')),
143 'objectSink': int(profile.getProfileSettingFloat('object_sink') * 1000),
146 def _runSliceProcess(self, cmdList):
148 if subprocess.mswindows:
149 su = subprocess.STARTUPINFO()
150 su.dwFlags |= subprocess.STARTF_USESHOWWINDOW
151 su.wShowWindow = subprocess.SW_HIDE
152 kwargs['startupinfo'] = su
153 kwargs['creationflags'] = 0x00004000 #BELOW_NORMAL_PRIORITY_CLASS
154 return subprocess.Popen(cmdList, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)