11 from Cura.util import profile
13 def getEngineFilename():
14 if platform.system() == 'Windows':
15 if os.path.exists('C:/Software/Cura_SteamEngine/_bin/Release/Cura_SteamEngine.exe'):
16 return 'C:/Software/Cura_SteamEngine/_bin/Release/Cura_SteamEngine.exe'
17 return os.path.abspath(os.path.join(os.path.dirname(__file__), '../..', 'SteamEngine.exe'))
18 if hasattr(sys, 'frozen'):
19 return os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../../..', 'SteamEngine'))
20 return os.path.abspath(os.path.join(os.path.dirname(__file__), '../..', 'SteamEngine'))
22 def getTempFilename():
23 warnings.simplefilter('ignore')
24 ret = os.tempnam(None, "Cura_Tmp")
25 warnings.simplefilter('default')
29 def __init__(self, progressCallback):
32 self._callback = progressCallback
33 self._binaryStorageFilename = getTempFilename()
34 self._exportFilename = getTempFilename()
35 self._progressSteps = ['inset', 'skin', 'export']
42 os.remove(self._binaryStorageFilename)
46 os.remove(self._exportFilename)
50 def abortSlicer(self):
51 if self._process is not None:
53 self._process.terminate()
58 def getGCodeFilename(self):
59 return self._exportFilename
61 def getSliceLog(self):
64 def runSlicer(self, scene):
66 self._callback(0.0, False)
68 commandList = [getEngineFilename(), '-vv']
69 for k, v in self._engineSettings().iteritems():
70 commandList += ['-s', '%s=%s' % (k, str(v))]
71 commandList += ['-o', self._exportFilename]
72 commandList += ['-b', self._binaryStorageFilename]
74 with open(self._binaryStorageFilename, "wb") as f:
75 order = scene.printOrder()
77 pos = numpy.array([profile.getPreferenceFloat('machine_width') * 1000 / 2, profile.getPreferenceFloat('machine_depth') * 1000 / 2])
78 commandList += ['-s', 'posx=%d' % int(pos[0]), '-s', 'posy=%d' % int(pos[1])]
81 for obj in scene.objects():
82 if scene.checkPlatform(obj):
83 for mesh in obj._meshList:
84 vertexTotal += mesh.vertexCount
86 f.write(numpy.array([vertexTotal], numpy.int32).tostring())
87 for obj in scene.objects():
88 if scene.checkPlatform(obj):
89 for mesh in obj._meshList:
90 vertexes = (numpy.matrix(mesh.vertexes, copy = False) * numpy.matrix(obj._matrix, numpy.float32)).getA()
91 vertexes -= obj._drawOffset
92 vertexes += numpy.array([obj.getPosition()[0], obj.getPosition()[1], 0.0])
93 f.write(vertexes.tostring())
99 obj = scene.objects()[n]
100 for mesh in obj._meshList:
101 f.write(numpy.array([mesh.vertexCount], numpy.int32).tostring())
102 f.write(mesh.vertexes.tostring())
103 pos = obj.getPosition() * 1000
104 pos += numpy.array([profile.getPreferenceFloat('machine_width') * 1000 / 2, profile.getPreferenceFloat('machine_depth') * 1000 / 2])
105 commandList += ['-m', ','.join(map(str, obj._matrix.getA().flatten()))]
106 commandList += ['-s', 'posx=%d' % int(pos[0]), '-s', 'posy=%d' % int(pos[1])]
107 commandList += ['#' * len(obj._meshList)]
109 if self._objCount > 0:
111 self._process = self._runSliceProcess(commandList)
112 self._thread = threading.Thread(target=self._watchProcess)
113 self._thread.daemon = True
116 traceback.print_exc()
118 def _watchProcess(self):
119 self._callback(0.0, False)
121 line = self._process.stdout.readline()
125 if line.startswith('Progress:'):
126 line = line.split(':')
127 if line[1] == 'process':
129 elif line[1] in self._progressSteps:
130 progressValue = float(line[2]) / float(line[3])
131 progressValue /= len(self._progressSteps)
132 progressValue += 1.0 / len(self._progressSteps) * self._progressSteps.index(line[1])
134 progressValue /= self._objCount
135 progressValue += 1.0 / self._objCount * objectNr
137 self._callback(progressValue, False)
141 self._sliceLog.append(line.strip())
142 line = self._process.stdout.readline()
143 for line in self._process.stderr:
144 self._sliceLog.append(line.strip())
145 returnCode = self._process.wait()
148 self._callback(1.0, True)
150 self._callback(0.0, False)
155 def _engineSettings(self):
157 'layerThickness': int(profile.getProfileSettingFloat('layer_height') * 1000),
158 'initialLayerThickness': int(profile.getProfileSettingFloat('bottom_thickness') * 1000),
159 'filamentDiameter': int(profile.getProfileSettingFloat('filament_diameter') * 1000),
160 'extrusionWidth': int(profile.calculateEdgeWidth() * 1000),
161 'insetCount': int(profile.calculateLineCount()),
162 'downSkinCount': int(profile.calculateSolidLayerCount()) if profile.getProfileSetting('solid_bottom') == 'True' else 0,
163 'upSkinCount': int(profile.calculateSolidLayerCount()) if profile.getProfileSetting('solid_top') == 'True' else 0,
164 'sparseInfillLineDistance': int(100 * profile.calculateEdgeWidth() * 1000 / profile.getProfileSettingFloat('fill_density')) if profile.getProfileSettingFloat('fill_density') > 0 else 9999999999,
165 'skirtDistance': int(profile.getProfileSettingFloat('skirt_gap') * 1000),
166 'skirtLineCount': int(profile.getProfileSettingFloat('skirt_line_count')),
167 'initialSpeedupLayers': int(4),
168 'initialLayerSpeed': int(profile.getProfileSettingFloat('bottom_layer_speed')),
169 'printSpeed': int(profile.getProfileSettingFloat('print_speed')),
170 'moveSpeed': int(profile.getProfileSettingFloat('travel_speed')),
171 'fanOnLayerNr': int(profile.getProfileSettingFloat('fan_layer')),
172 'supportAngle': int(-1) if profile.getProfileSetting('support') == 'None' else int(60),
173 'supportEverywhere': int(1) if profile.getProfileSetting('support') == 'Everywhere' else int(0),
174 'retractionAmount': int(profile.getProfileSettingFloat('retraction_amount') * 1000),
175 'retractionSpeed': int(profile.getProfileSettingFloat('retraction_speed')),
176 'objectSink': int(profile.getProfileSettingFloat('object_sink') * 1000),
177 'minimalLayerTime': int(profile.getProfileSettingFloat('cool_min_layer_time')),
178 'minimalFeedrate': int(profile.getProfileSettingFloat('cool_min_feedrate')),
179 'coolHeadLift': 1 if profile.getProfileSetting('cool_head_lift') == 'True' else 0,
180 'startCode': profile.getAlterationFileContents('start.gcode'),
181 'endCode': profile.getAlterationFileContents('end.gcode'),
184 def _runSliceProcess(self, cmdList):
186 if subprocess.mswindows:
187 su = subprocess.STARTUPINFO()
188 su.dwFlags |= subprocess.STARTF_USESHOWWINDOW
189 su.wShowWindow = subprocess.SW_HIDE
190 kwargs['startupinfo'] = su
191 kwargs['creationflags'] = 0x00004000 #BELOW_NORMAL_PRIORITY_CLASS
192 return subprocess.Popen(cmdList, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)