Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
a4ba5afb67
9 changed files with 270 additions and 145 deletions
|
@ -84,8 +84,10 @@ class mainWindow(configBase.configWindowBase):
|
||||||
menubar.Append(helpMenu, 'Help')
|
menubar.Append(helpMenu, 'Help')
|
||||||
self.SetMenuBar(menubar)
|
self.SetMenuBar(menubar)
|
||||||
|
|
||||||
self.lastPath = ""
|
if profile.getPreference('lastFile') != '':
|
||||||
self.filename = profile.getPreference('lastFile')
|
self.filelist = profile.getPreference('lastFile').split(';')
|
||||||
|
else:
|
||||||
|
self.filelist = []
|
||||||
self.progressPanelList = []
|
self.progressPanelList = []
|
||||||
|
|
||||||
#Preview window
|
#Preview window
|
||||||
|
@ -189,6 +191,18 @@ class mainWindow(configBase.configWindowBase):
|
||||||
self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
|
self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
|
||||||
self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
|
self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
|
||||||
self.Bind(wx.EVT_BUTTON, self.OnPrint, printButton)
|
self.Bind(wx.EVT_BUTTON, self.OnPrint, printButton)
|
||||||
|
|
||||||
|
extruderCount = int(profile.getPreference('extruder_amount'))
|
||||||
|
if extruderCount > 1:
|
||||||
|
loadButton2 = wx.Button(self, -1, 'Load Dual')
|
||||||
|
self.Bind(wx.EVT_BUTTON, self.OnLoadModel2, loadButton2)
|
||||||
|
if extruderCount > 2:
|
||||||
|
loadButton3 = wx.Button(self, -1, 'Load Tripple')
|
||||||
|
self.Bind(wx.EVT_BUTTON, self.OnLoadModel3, loadButton3)
|
||||||
|
if extruderCount > 2:
|
||||||
|
loadButton4 = wx.Button(self, -1, 'Load Quad')
|
||||||
|
self.Bind(wx.EVT_BUTTON, self.OnLoadModel4, loadButton4)
|
||||||
|
|
||||||
#Also bind double clicking the 3D preview to load an STL file.
|
#Also bind double clicking the 3D preview to load an STL file.
|
||||||
self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLoadModel, self.preview3d.glCanvas)
|
self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLoadModel, self.preview3d.glCanvas)
|
||||||
|
|
||||||
|
@ -196,17 +210,22 @@ class mainWindow(configBase.configWindowBase):
|
||||||
sizer = wx.GridBagSizer()
|
sizer = wx.GridBagSizer()
|
||||||
self.SetSizer(sizer)
|
self.SetSizer(sizer)
|
||||||
sizer.Add(nb, (0,0), span=(1,1), flag=wx.EXPAND)
|
sizer.Add(nb, (0,0), span=(1,1), flag=wx.EXPAND)
|
||||||
sizer.Add(self.preview3d, (0,1), span=(1,3), flag=wx.EXPAND)
|
sizer.Add(self.preview3d, (0,1), span=(1,2+extruderCount), flag=wx.EXPAND)
|
||||||
sizer.AddGrowableCol(2)
|
sizer.AddGrowableCol(2 + extruderCount)
|
||||||
sizer.AddGrowableRow(0)
|
sizer.AddGrowableRow(0)
|
||||||
sizer.Add(loadButton, (1,1), flag=wx.RIGHT, border=5)
|
sizer.Add(loadButton, (1,1), flag=wx.RIGHT, border=5)
|
||||||
sizer.Add(sliceButton, (1,2), flag=wx.RIGHT, border=5)
|
if extruderCount > 1:
|
||||||
sizer.Add(printButton, (1,3), flag=wx.RIGHT, border=5)
|
sizer.Add(loadButton2, (1,2), flag=wx.RIGHT, border=5)
|
||||||
|
if extruderCount > 2:
|
||||||
|
sizer.Add(loadButton3, (1,3), flag=wx.RIGHT, border=5)
|
||||||
|
if extruderCount > 3:
|
||||||
|
sizer.Add(loadButton4, (1,4), flag=wx.RIGHT, border=5)
|
||||||
|
sizer.Add(sliceButton, (1,1+extruderCount), flag=wx.RIGHT, border=5)
|
||||||
|
sizer.Add(printButton, (1,2+extruderCount), flag=wx.RIGHT, border=5)
|
||||||
self.sizer = sizer
|
self.sizer = sizer
|
||||||
|
|
||||||
if self.filename != "None":
|
if len(self.filelist) > 0:
|
||||||
self.preview3d.loadModelFile(self.filename)
|
self.preview3d.loadModelFiles(self.filelist)
|
||||||
self.lastPath = os.path.split(self.filename)[0]
|
|
||||||
|
|
||||||
self.updateProfileToControls()
|
self.updateProfileToControls()
|
||||||
|
|
||||||
|
@ -261,25 +280,48 @@ class mainWindow(configBase.configWindowBase):
|
||||||
configWizard.configWizard()
|
configWizard.configWizard()
|
||||||
self.updateProfileToControls()
|
self.updateProfileToControls()
|
||||||
|
|
||||||
def OnLoadModel(self, e):
|
def _showOpenDialog(self, title, wildcard = "STL files (*.stl)|*.stl;*.STL"):
|
||||||
dlg=wx.FileDialog(self, "Open file to print", self.lastPath, style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
|
dlg=wx.FileDialog(self, title, os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
|
||||||
dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL")
|
dlg.SetWildcard(wildcard)
|
||||||
if dlg.ShowModal() == wx.ID_OK:
|
if dlg.ShowModal() == wx.ID_OK:
|
||||||
self.filename=dlg.GetPath()
|
filename = dlg.GetPath()
|
||||||
profile.putPreference('lastFile', self.filename)
|
|
||||||
if not(os.path.exists(self.filename)):
|
|
||||||
return
|
|
||||||
self.lastPath = os.path.split(self.filename)[0]
|
|
||||||
self.preview3d.loadModelFile(self.filename)
|
|
||||||
self.preview3d.setViewMode("Normal")
|
|
||||||
dlg.Destroy()
|
dlg.Destroy()
|
||||||
|
if not(os.path.exists(filename)):
|
||||||
|
return False
|
||||||
|
profile.putPreference('lastFile', filename)
|
||||||
|
return filename
|
||||||
|
dlg.Destroy()
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _showModelLoadDialog(self, amount):
|
||||||
|
filelist = []
|
||||||
|
for i in xrange(0, amount):
|
||||||
|
filelist.append(self._showOpenDialog("Open file to print"))
|
||||||
|
if filelist[-1] == False:
|
||||||
|
return
|
||||||
|
self.filelist = filelist
|
||||||
|
profile.putPreference('lastFile', ';'.join(self.filelist))
|
||||||
|
self.preview3d.loadModelFiles(self.filelist)
|
||||||
|
self.preview3d.setViewMode("Normal")
|
||||||
|
|
||||||
|
def OnLoadModel(self, e):
|
||||||
|
self._showModelLoadDialog(1)
|
||||||
|
|
||||||
|
def OnLoadModel2(self, e):
|
||||||
|
self._showModelLoadDialog(2)
|
||||||
|
|
||||||
|
def OnLoadModel3(self, e):
|
||||||
|
self._showModelLoadDialog(3)
|
||||||
|
|
||||||
|
def OnLoadModel4(self, e):
|
||||||
|
self._showModelLoadDialog(4)
|
||||||
|
|
||||||
def OnSlice(self, e):
|
def OnSlice(self, e):
|
||||||
if self.filename == None:
|
if len(self.filelist) < 1:
|
||||||
wx.MessageBox('You need to load a file before you can slice it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
|
wx.MessageBox('You need to load a file before you can slice it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
|
||||||
return
|
return
|
||||||
#Create a progress panel and add it to the window. The progress panel will start the Skein operation.
|
#Create a progress panel and add it to the window. The progress panel will start the Skein operation.
|
||||||
spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filename)
|
spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filelist)
|
||||||
self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
|
self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
|
||||||
self.sizer.Layout()
|
self.sizer.Layout()
|
||||||
newSize = self.GetSize();
|
newSize = self.GetSize();
|
||||||
|
@ -288,13 +330,13 @@ class mainWindow(configBase.configWindowBase):
|
||||||
self.progressPanelList.append(spp)
|
self.progressPanelList.append(spp)
|
||||||
|
|
||||||
def OnPrint(self, e):
|
def OnPrint(self, e):
|
||||||
if self.filename == None:
|
if len(self.filelist) < 1:
|
||||||
wx.MessageBox('You need to load a file and slice it before you can print it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
|
wx.MessageBox('You need to load a file and slice it before you can print it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
|
||||||
return
|
return
|
||||||
if not os.path.exists(self.filename[: self.filename.rfind('.')] + "_export.gcode"):
|
if not os.path.exists(self.filelist[0][: self.filelist[0].rfind('.')] + "_export.gcode"):
|
||||||
wx.MessageBox('You need to slice the file to GCode before you can print it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
|
wx.MessageBox('You need to slice the file to GCode before you can print it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
|
||||||
return
|
return
|
||||||
printWindow.printFile(self.filename[: self.filename.rfind('.')] + "_export.gcode")
|
printWindow.printFile(self.filelist[0][: self.filelist[0].rfind('.')] + "_export.gcode")
|
||||||
|
|
||||||
def OnExpertOpen(self, e):
|
def OnExpertOpen(self, e):
|
||||||
ecw = expertConfig.expertConfigWindow()
|
ecw = expertConfig.expertConfigWindow()
|
||||||
|
|
|
@ -24,6 +24,7 @@ class preferencesDialog(configBase.configWindowBase):
|
||||||
validators.validFloat(c, 10.0)
|
validators.validFloat(c, 10.0)
|
||||||
c = configBase.SettingRow(left, 'Machine height (mm)', 'machine_height', '200', 'Size of the machine in mm', type = 'preference')
|
c = configBase.SettingRow(left, 'Machine height (mm)', 'machine_height', '200', 'Size of the machine in mm', type = 'preference')
|
||||||
validators.validFloat(c, 10.0)
|
validators.validFloat(c, 10.0)
|
||||||
|
c = configBase.SettingRow(left, 'Extruder count', 'extruder_amount', ['1', '2', '3', '4'], 'Amount of extruders in your machine.', type = 'preference')
|
||||||
|
|
||||||
configBase.TitleRow(left, 'Filament settings')
|
configBase.TitleRow(left, 'Filament settings')
|
||||||
c = configBase.SettingRow(left, 'Filament density (kg/m3)', 'filament_density', '1300', 'Weight of the filament per m3. Around 1300 for PLA. And around 1040 for ABS. This value is used to estimate the weight if the filament used for the print.', type = 'preference')
|
c = configBase.SettingRow(left, 'Filament density (kg/m3)', 'filament_density', '1300', 'Weight of the filament per m3. Around 1300 for PLA. And around 1040 for ABS. This value is used to estimate the weight if the filament used for the print.', type = 'preference')
|
||||||
|
@ -38,7 +39,7 @@ class preferencesDialog(configBase.configWindowBase):
|
||||||
c = configBase.SettingRow(left, 'Baudrate', 'serial_baud', '250000', 'Speed of the serial port communication\nNeeds to match your firmware settings\nCommon values are 250000, 115200, 57600', type = 'preference')
|
c = configBase.SettingRow(left, 'Baudrate', 'serial_baud', '250000', 'Speed of the serial port communication\nNeeds to match your firmware settings\nCommon values are 250000, 115200, 57600', type = 'preference')
|
||||||
|
|
||||||
configBase.TitleRow(left, 'Slicer settings')
|
configBase.TitleRow(left, 'Slicer settings')
|
||||||
c = configBase.SettingRow(left, 'Slicer selection', 'slicer', ['Cura (Skeinforge based)', 'Slic3r'], 'Which slicer to use to slice objects. Usually the Cura engine produces the best results. But Slic3r is developing fast and is faster with slicing.', type = 'preference')
|
#c = configBase.SettingRow(left, 'Slicer selection', 'slicer', ['Cura (Skeinforge based)', 'Slic3r'], 'Which slicer to use to slice objects. Usually the Cura engine produces the best results. But Slic3r is developing fast and is faster with slicing.', type = 'preference')
|
||||||
c = configBase.SettingRow(left, 'Save profile on slice', 'save_profile', False, 'When slicing save the profile as [stl_file]_profile.ini next to the model.', type = 'preference')
|
c = configBase.SettingRow(left, 'Save profile on slice', 'save_profile', False, 'When slicing save the profile as [stl_file]_profile.ini next to the model.', type = 'preference')
|
||||||
|
|
||||||
self.MakeModal(True)
|
self.MakeModal(True)
|
||||||
|
|
|
@ -27,6 +27,13 @@ from util import gcodeInterpreter
|
||||||
from util import stl
|
from util import stl
|
||||||
from util import util3d
|
from util import util3d
|
||||||
|
|
||||||
|
class previewObject():
|
||||||
|
def __init__(self):
|
||||||
|
self.mesh = None
|
||||||
|
self.filename = None
|
||||||
|
self.displayList = None
|
||||||
|
self.dirty = False
|
||||||
|
|
||||||
class previewPanel(wx.Panel):
|
class previewPanel(wx.Panel):
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
super(previewPanel, self).__init__(parent,-1)
|
super(previewPanel, self).__init__(parent,-1)
|
||||||
|
@ -35,11 +42,10 @@ class previewPanel(wx.Panel):
|
||||||
self.SetMinSize((440,320))
|
self.SetMinSize((440,320))
|
||||||
|
|
||||||
self.glCanvas = PreviewGLCanvas(self)
|
self.glCanvas = PreviewGLCanvas(self)
|
||||||
self.init = 0
|
self.objectList = []
|
||||||
self.triangleMesh = None
|
|
||||||
self.gcode = None
|
self.gcode = None
|
||||||
self.modelFilename = None
|
self.objectsMinV = None
|
||||||
self.loadingProgressAmount = 0
|
self.objectsMaxV = None
|
||||||
self.loadThread = None
|
self.loadThread = None
|
||||||
self.machineSize = util3d.Vector3(float(profile.getPreference('machine_width')), float(profile.getPreference('machine_depth')), float(profile.getPreference('machine_height')))
|
self.machineSize = util3d.Vector3(float(profile.getPreference('machine_width')), float(profile.getPreference('machine_depth')), float(profile.getPreference('machine_height')))
|
||||||
self.machineCenter = util3d.Vector3(float(profile.getProfileSetting('machine_center_x')), float(profile.getProfileSetting('machine_center_y')), 0)
|
self.machineCenter = util3d.Vector3(float(profile.getProfileSetting('machine_center_x')), float(profile.getProfileSetting('machine_center_y')), 0)
|
||||||
|
@ -138,10 +144,10 @@ class previewPanel(wx.Panel):
|
||||||
self.glCanvas.Refresh()
|
self.glCanvas.Refresh()
|
||||||
|
|
||||||
def OnScaleMax(self, e):
|
def OnScaleMax(self, e):
|
||||||
if self.triangleMesh == None:
|
if self.objectsMinV == None:
|
||||||
return
|
return
|
||||||
vMin = self.triangleMesh.getMinimum()
|
vMin = self.objectsMinV
|
||||||
vMax = self.triangleMesh.getMaximum()
|
vMax = self.objectsMaxV
|
||||||
scaleX1 = (self.machineSize.x - self.machineCenter.x) / ((vMax.x - vMin.x) / 2)
|
scaleX1 = (self.machineSize.x - self.machineCenter.x) / ((vMax.x - vMin.x) / 2)
|
||||||
scaleY1 = (self.machineSize.y - self.machineCenter.y) / ((vMax.y - vMin.y) / 2)
|
scaleY1 = (self.machineSize.y - self.machineCenter.y) / ((vMax.y - vMin.y) / 2)
|
||||||
scaleX2 = (self.machineCenter.x) / ((vMax.x - vMin.x) / 2)
|
scaleX2 = (self.machineCenter.x) / ((vMax.x - vMin.x) / 2)
|
||||||
|
@ -194,15 +200,21 @@ class previewPanel(wx.Panel):
|
||||||
self.glCanvas.viewMode = mode
|
self.glCanvas.viewMode = mode
|
||||||
wx.CallAfter(self.glCanvas.Refresh)
|
wx.CallAfter(self.glCanvas.Refresh)
|
||||||
|
|
||||||
def loadModelFile(self, filename):
|
def loadModelFiles(self, filelist):
|
||||||
if self.modelFilename != filename:
|
while len(filelist) > len(self.objectList):
|
||||||
self.modelFileTime = None
|
self.objectList.append(previewObject())
|
||||||
|
for idx in xrange(len(self.objectList), len(filelist)):
|
||||||
|
self.objectList[idx].mesh = None
|
||||||
|
for idx in xrange(0, len(filelist)):
|
||||||
|
obj = self.objectList[idx]
|
||||||
|
if obj.filename != filelist[idx]:
|
||||||
|
obj.fileTime = None
|
||||||
self.gcodeFileTime = None
|
self.gcodeFileTime = None
|
||||||
self.logFileTime = None
|
self.logFileTime = None
|
||||||
|
obj.filename = filelist[idx]
|
||||||
|
|
||||||
self.modelFilename = filename
|
self.gcodeFilename = filelist[0][: filelist[0].rfind('.')] + "_export.gcode"
|
||||||
self.gcodeFilename = filename[: filename.rfind('.')] + "_export.gcode"
|
self.logFilename = filelist[0][: filelist[0].rfind('.')] + "_export.log"
|
||||||
self.logFilename = filename[: filename.rfind('.')] + "_export.log"
|
|
||||||
#Do the STL file loading in a background thread so we don't block the UI.
|
#Do the STL file loading in a background thread so we don't block the UI.
|
||||||
if self.loadThread != None and self.loadThread.isAlive():
|
if self.loadThread != None and self.loadThread.isAlive():
|
||||||
self.loadThread.join()
|
self.loadThread.join()
|
||||||
|
@ -210,25 +222,23 @@ class previewPanel(wx.Panel):
|
||||||
self.loadThread.daemon = True
|
self.loadThread.daemon = True
|
||||||
self.loadThread.start()
|
self.loadThread.start()
|
||||||
|
|
||||||
def loadReModelFile(self, filename):
|
def loadReModelFiles(self, filelist):
|
||||||
#Only load this again if the filename matches the file we have already loaded (for auto loading GCode after slicing)
|
#Only load this again if the filename matches the file we have already loaded (for auto loading GCode after slicing)
|
||||||
if self.modelFilename != filename:
|
for idx in xrange(0, len(filelist)):
|
||||||
|
if self.objectList[idx].filename != filelist[idx]:
|
||||||
return False
|
return False
|
||||||
self.loadModelFile(filename)
|
self.loadModelFiles(filelist)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def doFileLoadThread(self):
|
def doFileLoadThread(self):
|
||||||
if os.path.isfile(self.modelFilename) and self.modelFileTime != os.stat(self.modelFilename).st_mtime:
|
for obj in self.objectList:
|
||||||
self.modelFileTime = os.stat(self.modelFilename).st_mtime
|
if os.path.isfile(obj.filename) and obj.fileTime != os.stat(obj.filename).st_mtime:
|
||||||
triangleMesh = stl.stlModel()
|
obj.ileTime = os.stat(obj.filename).st_mtime
|
||||||
triangleMesh.load(self.modelFilename)
|
mesh = stl.stlModel()
|
||||||
triangleMesh.origonalVertexes = list(triangleMesh.vertexes)
|
mesh.load(obj.filename)
|
||||||
for i in xrange(0, len(triangleMesh.origonalVertexes)):
|
obj.dirty = False
|
||||||
triangleMesh.origonalVertexes[i] = triangleMesh.origonalVertexes[i].copy()
|
obj.errorList = []
|
||||||
triangleMesh.getMinimumZ()
|
obj.mesh = mesh
|
||||||
self.modelDirty = False
|
|
||||||
self.errorList = []
|
|
||||||
self.triangleMesh = triangleMesh
|
|
||||||
self.updateModelTransform()
|
self.updateModelTransform()
|
||||||
wx.CallAfter(self.updateToolbar)
|
wx.CallAfter(self.updateToolbar)
|
||||||
wx.CallAfter(self.glCanvas.Refresh)
|
wx.CallAfter(self.glCanvas.Refresh)
|
||||||
|
@ -238,7 +248,6 @@ class previewPanel(wx.Panel):
|
||||||
gcode = gcodeInterpreter.gcode()
|
gcode = gcodeInterpreter.gcode()
|
||||||
gcode.progressCallback = self.loadProgress
|
gcode.progressCallback = self.loadProgress
|
||||||
gcode.load(self.gcodeFilename)
|
gcode.load(self.gcodeFilename)
|
||||||
self.loadingProgressAmount = 0
|
|
||||||
self.gcodeDirty = False
|
self.gcodeDirty = False
|
||||||
self.errorList = []
|
self.errorList = []
|
||||||
self.gcode = gcode
|
self.gcode = gcode
|
||||||
|
@ -260,8 +269,7 @@ class previewPanel(wx.Panel):
|
||||||
wx.CallAfter(self.glCanvas.Refresh)
|
wx.CallAfter(self.glCanvas.Refresh)
|
||||||
|
|
||||||
def loadProgress(self, progress):
|
def loadProgress(self, progress):
|
||||||
self.loadingProgressAmount = progress
|
pass
|
||||||
wx.CallAfter(self.glCanvas.Refresh)
|
|
||||||
|
|
||||||
def updateToolbar(self):
|
def updateToolbar(self):
|
||||||
self.layerSpin.Show(self.gcode != None)
|
self.layerSpin.Show(self.gcode != None)
|
||||||
|
@ -283,8 +291,6 @@ class previewPanel(wx.Panel):
|
||||||
self.glCanvas.Refresh()
|
self.glCanvas.Refresh()
|
||||||
|
|
||||||
def updateModelTransform(self, f=0):
|
def updateModelTransform(self, f=0):
|
||||||
if self.triangleMesh == None:
|
|
||||||
return
|
|
||||||
rotate = profile.getProfileSettingFloat('model_rotate_base') / 180.0 * math.pi
|
rotate = profile.getProfileSettingFloat('model_rotate_base') / 180.0 * math.pi
|
||||||
scaleX = 1.0
|
scaleX = 1.0
|
||||||
scaleY = 1.0
|
scaleY = 1.0
|
||||||
|
@ -302,34 +308,54 @@ class previewPanel(wx.Panel):
|
||||||
mat10 = math.sin(rotate) * scaleX
|
mat10 = math.sin(rotate) * scaleX
|
||||||
mat11 = math.cos(rotate) * scaleY
|
mat11 = math.cos(rotate) * scaleY
|
||||||
|
|
||||||
for i in xrange(0, len(self.triangleMesh.origonalVertexes)):
|
if len(self.objectList) < 1 or self.objectList[0].mesh == None:
|
||||||
x = self.triangleMesh.origonalVertexes[i].x
|
return
|
||||||
y = self.triangleMesh.origonalVertexes[i].y
|
|
||||||
z = self.triangleMesh.origonalVertexes[i].z
|
for obj in self.objectList:
|
||||||
|
if obj.mesh == None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for i in xrange(0, len(obj.mesh.origonalVertexes)):
|
||||||
|
x = obj.mesh.origonalVertexes[i].x
|
||||||
|
y = obj.mesh.origonalVertexes[i].y
|
||||||
|
z = obj.mesh.origonalVertexes[i].z
|
||||||
if swapXZ:
|
if swapXZ:
|
||||||
x, z = z, x
|
x, z = z, x
|
||||||
if swapYZ:
|
if swapYZ:
|
||||||
y, z = z, y
|
y, z = z, y
|
||||||
self.triangleMesh.vertexes[i].x = x * mat00 + y * mat01
|
obj.mesh.vertexes[i].x = x * mat00 + y * mat01
|
||||||
self.triangleMesh.vertexes[i].y = x * mat10 + y * mat11
|
obj.mesh.vertexes[i].y = x * mat10 + y * mat11
|
||||||
self.triangleMesh.vertexes[i].z = z * scaleZ
|
obj.mesh.vertexes[i].z = z * scaleZ
|
||||||
|
|
||||||
for face in self.triangleMesh.faces:
|
for face in obj.mesh.faces:
|
||||||
v1 = face.v[0]
|
v1 = face.v[0]
|
||||||
v2 = face.v[1]
|
v2 = face.v[1]
|
||||||
v3 = face.v[2]
|
v3 = face.v[2]
|
||||||
face.normal = (v2 - v1).cross(v3 - v1)
|
face.normal = (v2 - v1).cross(v3 - v1)
|
||||||
face.normal.normalize()
|
face.normal.normalize()
|
||||||
|
|
||||||
minZ = self.triangleMesh.getMinimumZ()
|
minV = self.objectList[0].mesh.getMinimum()
|
||||||
min = self.triangleMesh.getMinimum()
|
maxV = self.objectList[0].mesh.getMaximum()
|
||||||
max = self.triangleMesh.getMaximum()
|
for obj in self.objectList:
|
||||||
for v in self.triangleMesh.vertexes:
|
if obj.mesh == None:
|
||||||
v.z -= minZ
|
continue
|
||||||
v.x -= min.x + (max.x - min.x) / 2
|
|
||||||
v.y -= min.y + (max.y - min.y) / 2
|
obj.mesh.getMinimumZ()
|
||||||
self.triangleMesh.getMinimumZ()
|
minV = minV.min(obj.mesh.getMinimum())
|
||||||
self.modelDirty = True
|
maxV = maxV.max(obj.mesh.getMaximum())
|
||||||
|
|
||||||
|
self.objectsMaxV = maxV
|
||||||
|
self.objectsMinV = minV
|
||||||
|
for obj in self.objectList:
|
||||||
|
if obj.mesh == None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for v in obj.mesh.vertexes:
|
||||||
|
v.z -= minV.z
|
||||||
|
v.x -= minV.x + (maxV.x - minV.x) / 2
|
||||||
|
v.y -= minV.y + (maxV.y - minV.y) / 2
|
||||||
|
obj.mesh.getMinimumZ()
|
||||||
|
obj.dirty = True
|
||||||
self.glCanvas.Refresh()
|
self.glCanvas.Refresh()
|
||||||
|
|
||||||
class PreviewGLCanvas(glcanvas.GLCanvas):
|
class PreviewGLCanvas(glcanvas.GLCanvas):
|
||||||
|
@ -349,8 +375,8 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
|
||||||
self.offsetX = 0
|
self.offsetX = 0
|
||||||
self.offsetY = 0
|
self.offsetY = 0
|
||||||
self.view3D = True
|
self.view3D = True
|
||||||
self.modelDisplayList = None
|
|
||||||
self.gcodeDisplayList = None
|
self.gcodeDisplayList = None
|
||||||
|
self.objColor = [[1.0, 0.8, 0.6, 1.0], [0.2, 1.0, 0.1, 1.0], [1.0, 0.2, 0.1, 1.0], [0.1, 0.2, 1.0, 1.0]]
|
||||||
|
|
||||||
def OnMouseMotion(self,e):
|
def OnMouseMotion(self,e):
|
||||||
if e.Dragging() and e.LeftIsDown():
|
if e.Dragging() and e.LeftIsDown():
|
||||||
|
@ -398,8 +424,8 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
|
||||||
glTranslate(0,0,-self.zoom)
|
glTranslate(0,0,-self.zoom)
|
||||||
glRotate(-self.pitch, 1,0,0)
|
glRotate(-self.pitch, 1,0,0)
|
||||||
glRotate(self.yaw, 0,0,1)
|
glRotate(self.yaw, 0,0,1)
|
||||||
if self.parent.triangleMesh != None:
|
if self.parent.objectsMaxV != None:
|
||||||
glTranslate(0,0,-self.parent.triangleMesh.getMaximum().z * profile.getProfileSettingFloat('model_scale') / 2)
|
glTranslate(0,0,-self.parent.objectsMaxV.z * profile.getProfileSettingFloat('model_scale') / 2)
|
||||||
else:
|
else:
|
||||||
glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)
|
glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)
|
||||||
glTranslate(self.offsetX, self.offsetY, 0.0)
|
glTranslate(self.offsetX, self.offsetY, 0.0)
|
||||||
|
@ -505,26 +531,28 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
|
||||||
if self.viewMode == "GCode" or self.viewMode == "Mixed":
|
if self.viewMode == "GCode" or self.viewMode == "Mixed":
|
||||||
glCallList(self.gcodeDisplayList)
|
glCallList(self.gcodeDisplayList)
|
||||||
|
|
||||||
if self.parent.triangleMesh != None:
|
glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0)
|
||||||
if self.modelDisplayList == None:
|
for obj in self.parent.objectList:
|
||||||
self.modelDisplayList = glGenLists(1);
|
if obj.mesh == None:
|
||||||
if self.parent.modelDirty:
|
continue
|
||||||
self.parent.modelDirty = False
|
if obj.displayList == None:
|
||||||
glNewList(self.modelDisplayList, GL_COMPILE)
|
obj.displayList = glGenLists(1);
|
||||||
opengl.DrawSTL(self.parent.triangleMesh)
|
if obj.dirty:
|
||||||
|
obj.dirty = False
|
||||||
|
glNewList(obj.displayList, GL_COMPILE)
|
||||||
|
opengl.DrawSTL(obj.mesh)
|
||||||
glEndList()
|
glEndList()
|
||||||
|
|
||||||
glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0)
|
|
||||||
glEnable(GL_NORMALIZE)
|
glEnable(GL_NORMALIZE)
|
||||||
if self.viewMode == "Transparent" or self.viewMode == "Mixed":
|
if self.viewMode == "Transparent" or self.viewMode == "Mixed":
|
||||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.5, 0.4, 0.3, 1.0])
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, map(lambda x: x / 2, self.objColor[self.parent.objectList.index(obj)]))
|
||||||
glLightfv(GL_LIGHT0, GL_AMBIENT, [0.1, 0.1, 0.1, 0.0])
|
glLightfv(GL_LIGHT0, GL_AMBIENT, map(lambda x: x / 10, self.objColor[self.parent.objectList.index(obj)]))
|
||||||
#If we want transparent, then first render a solid black model to remove the printer size lines.
|
#If we want transparent, then first render a solid black model to remove the printer size lines.
|
||||||
if self.viewMode != "Mixed":
|
if self.viewMode != "Mixed":
|
||||||
glDisable(GL_BLEND)
|
glDisable(GL_BLEND)
|
||||||
glDisable(GL_LIGHTING)
|
glDisable(GL_LIGHTING)
|
||||||
glColor3f(0,0,0)
|
glColor3f(0,0,0)
|
||||||
self.drawModel()
|
self.drawModel(obj)
|
||||||
glColor3f(1,1,1)
|
glColor3f(1,1,1)
|
||||||
#After the black model is rendered, render the model again but now with lighting and no depth testing.
|
#After the black model is rendered, render the model again but now with lighting and no depth testing.
|
||||||
glDisable(GL_DEPTH_TEST)
|
glDisable(GL_DEPTH_TEST)
|
||||||
|
@ -532,23 +560,23 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
|
||||||
glEnable(GL_BLEND)
|
glEnable(GL_BLEND)
|
||||||
glBlendFunc(GL_ONE, GL_ONE)
|
glBlendFunc(GL_ONE, GL_ONE)
|
||||||
glEnable(GL_LIGHTING)
|
glEnable(GL_LIGHTING)
|
||||||
self.drawModel()
|
self.drawModel(obj)
|
||||||
elif self.viewMode == "X-Ray":
|
elif self.viewMode == "X-Ray":
|
||||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)
|
||||||
glDisable(GL_DEPTH_TEST)
|
glDisable(GL_DEPTH_TEST)
|
||||||
glEnable(GL_STENCIL_TEST);
|
glEnable(GL_STENCIL_TEST);
|
||||||
glStencilFunc(GL_ALWAYS, 1, 1)
|
glStencilFunc(GL_ALWAYS, 1, 1)
|
||||||
glStencilOp(GL_INCR, GL_INCR, GL_INCR)
|
glStencilOp(GL_INCR, GL_INCR, GL_INCR)
|
||||||
self.drawModel()
|
self.drawModel(obj)
|
||||||
glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
|
glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
|
||||||
|
|
||||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)
|
||||||
glStencilFunc(GL_EQUAL, 0, 1);
|
glStencilFunc(GL_EQUAL, 0, 1);
|
||||||
glColor(1, 1, 1)
|
glColor(1, 1, 1)
|
||||||
self.drawModel()
|
self.drawModel(obj)
|
||||||
glStencilFunc(GL_EQUAL, 1, 1);
|
glStencilFunc(GL_EQUAL, 1, 1);
|
||||||
glColor(1, 0, 0)
|
glColor(1, 0, 0)
|
||||||
self.drawModel()
|
self.drawModel(obj)
|
||||||
|
|
||||||
glPushMatrix()
|
glPushMatrix()
|
||||||
glLoadIdentity()
|
glLoadIdentity()
|
||||||
|
@ -575,28 +603,29 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
glEnable(GL_DEPTH_TEST)
|
glEnable(GL_DEPTH_TEST)
|
||||||
elif self.viewMode == "Normal":
|
elif self.viewMode == "Normal":
|
||||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, [1.0, 0.8, 0.6, 1.0])
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, self.objColor[self.parent.objectList.index(obj)])
|
||||||
glLightfv(GL_LIGHT0, GL_AMBIENT, [0.2, 0.2, 0.2, 0.0])
|
glLightfv(GL_LIGHT0, GL_AMBIENT, map(lambda x: x / 5, self.objColor[self.parent.objectList.index(obj)]))
|
||||||
glEnable(GL_LIGHTING)
|
glEnable(GL_LIGHTING)
|
||||||
self.drawModel()
|
self.drawModel(obj)
|
||||||
|
|
||||||
if self.viewMode == "Normal" or self.viewMode == "Transparent" or self.viewMode == "X-Ray":
|
if self.viewMode == "Normal" or self.viewMode == "Transparent" or self.viewMode == "X-Ray":
|
||||||
glDisable(GL_LIGHTING)
|
glDisable(GL_LIGHTING)
|
||||||
glDisable(GL_DEPTH_TEST)
|
glDisable(GL_DEPTH_TEST)
|
||||||
glDisable(GL_BLEND)
|
glDisable(GL_BLEND)
|
||||||
glColor3f(1,0,0)
|
glColor3f(1,0,0)
|
||||||
glBegin(GL_LINES)
|
#glBegin(GL_LINES)
|
||||||
for err in self.parent.errorList:
|
#for err in self.parent.errorList:
|
||||||
glVertex3f(err[0].x, err[0].y, err[0].z)
|
# glVertex3f(err[0].x, err[0].y, err[0].z)
|
||||||
glVertex3f(err[1].x, err[1].y, err[1].z)
|
# glVertex3f(err[1].x, err[1].y, err[1].z)
|
||||||
glEnd()
|
#glEnd()
|
||||||
|
glEnable(GL_DEPTH_TEST)
|
||||||
glFlush()
|
glFlush()
|
||||||
|
|
||||||
def drawModel(self):
|
def drawModel(self, obj):
|
||||||
multiX = int(profile.getProfileSetting('model_multiply_x'))
|
multiX = int(profile.getProfileSetting('model_multiply_x'))
|
||||||
multiY = int(profile.getProfileSetting('model_multiply_y'))
|
multiY = int(profile.getProfileSetting('model_multiply_y'))
|
||||||
modelScale = profile.getProfileSettingFloat('model_scale')
|
modelScale = profile.getProfileSettingFloat('model_scale')
|
||||||
modelSize = (self.parent.triangleMesh.getMaximum() - self.parent.triangleMesh.getMinimum()) * modelScale
|
modelSize = (obj.mesh.getMaximum() - obj.mesh.getMinimum()) * modelScale
|
||||||
glPushMatrix()
|
glPushMatrix()
|
||||||
glTranslate(-(modelSize.x+10)*(multiX-1)/2,-(modelSize.y+10)*(multiY-1)/2, 0)
|
glTranslate(-(modelSize.x+10)*(multiX-1)/2,-(modelSize.y+10)*(multiY-1)/2, 0)
|
||||||
for mx in xrange(0, multiX):
|
for mx in xrange(0, multiX):
|
||||||
|
@ -604,7 +633,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
|
||||||
glPushMatrix()
|
glPushMatrix()
|
||||||
glTranslate((modelSize.x+10)*mx,(modelSize.y+10)*my, 0)
|
glTranslate((modelSize.x+10)*mx,(modelSize.y+10)*my, 0)
|
||||||
glScalef(modelScale, modelScale, modelScale)
|
glScalef(modelScale, modelScale, modelScale)
|
||||||
glCallList(self.modelDisplayList)
|
glCallList(obj.displayList)
|
||||||
glPopMatrix()
|
glPopMatrix()
|
||||||
glPopMatrix()
|
glPopMatrix()
|
||||||
|
|
||||||
|
|
|
@ -707,11 +707,11 @@ class ProjectSliceProgressWindow(wx.Frame):
|
||||||
|
|
||||||
if action == self.actionList[0]:
|
if action == self.actionList[0]:
|
||||||
resultFile.write(';TYPE:CUSTOM\n')
|
resultFile.write(';TYPE:CUSTOM\n')
|
||||||
resultFile.write(profile.getAlterationFileContents('start.gcode'))
|
resultFile.write(profile.getAlterationFileContents('start.gcode').encode('utf-8')
|
||||||
else:
|
else:
|
||||||
#reset the extrusion length, and move to the next object center.
|
#reset the extrusion length, and move to the next object center.
|
||||||
resultFile.write(';TYPE:CUSTOM\n')
|
resultFile.write(';TYPE:CUSTOM\n')
|
||||||
resultFile.write(profile.getAlterationFileContents('nextobject.gcode'))
|
resultFile.write(profile.getAlterationFileContents('nextobject.gcode').encode('utf-8')
|
||||||
resultFile.write(';PRINTNR:%d\n' % self.actionList.index(action))
|
resultFile.write(';PRINTNR:%d\n' % self.actionList.index(action))
|
||||||
profile.loadGlobalProfileFromString(oldProfile)
|
profile.loadGlobalProfileFromString(oldProfile)
|
||||||
|
|
||||||
|
@ -727,7 +727,7 @@ class ProjectSliceProgressWindow(wx.Frame):
|
||||||
wx.CallAfter(self.progressGauge2.SetValue, self.actionList.index(action) + 1)
|
wx.CallAfter(self.progressGauge2.SetValue, self.actionList.index(action) + 1)
|
||||||
|
|
||||||
resultFile.write(';TYPE:CUSTOM\n')
|
resultFile.write(';TYPE:CUSTOM\n')
|
||||||
resultFile.write(profile.getAlterationFileContents('end.gcode'))
|
resultFile.write(profile.getAlterationFileContents('end.gcode').encode('utf-8')
|
||||||
resultFile.close()
|
resultFile.close()
|
||||||
self.abort = True
|
self.abort = True
|
||||||
wx.CallAfter(self.abortButton.SetLabel, 'Close')
|
wx.CallAfter(self.abortButton.SetLabel, 'Close')
|
||||||
|
|
|
@ -1,22 +1,17 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
import __init__
|
import __init__
|
||||||
|
|
||||||
import wx
|
import wx, sys, os, math, threading, subprocess, time
|
||||||
import sys
|
|
||||||
import math
|
|
||||||
import threading
|
|
||||||
import subprocess
|
|
||||||
import time
|
|
||||||
|
|
||||||
from util import profile
|
from util import profile
|
||||||
from util import sliceRun
|
from util import sliceRun
|
||||||
from util import exporer
|
from util import exporer
|
||||||
|
|
||||||
class sliceProgessPanel(wx.Panel):
|
class sliceProgessPanel(wx.Panel):
|
||||||
def __init__(self, mainWindow, parent, filename):
|
def __init__(self, mainWindow, parent, filelist):
|
||||||
wx.Panel.__init__(self, parent, -1)
|
wx.Panel.__init__(self, parent, -1)
|
||||||
self.mainWindow = mainWindow
|
self.mainWindow = mainWindow
|
||||||
self.filename = filename
|
self.filelist = filelist
|
||||||
self.abort = False
|
self.abort = False
|
||||||
|
|
||||||
#How long does each step take compared to the others. This is used to make a better scaled progress bar, and guess time left.
|
#How long does each step take compared to the others. This is used to make a better scaled progress bar, and guess time left.
|
||||||
|
@ -40,7 +35,7 @@ class sliceProgessPanel(wx.Panel):
|
||||||
for v in self.sliceStepTimeFactor.itervalues():
|
for v in self.sliceStepTimeFactor.itervalues():
|
||||||
self.totalRunTimeFactor += v
|
self.totalRunTimeFactor += v
|
||||||
|
|
||||||
box = wx.StaticBox(self, -1, filename)
|
box = wx.StaticBox(self, -1, filelist[0])
|
||||||
self.sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
|
self.sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
|
||||||
|
|
||||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
@ -61,9 +56,18 @@ class sliceProgessPanel(wx.Panel):
|
||||||
self.totalDoneFactor = 0.0
|
self.totalDoneFactor = 0.0
|
||||||
self.startTime = time.time()
|
self.startTime = time.time()
|
||||||
if profile.getPreference('save_profile') == 'True':
|
if profile.getPreference('save_profile') == 'True':
|
||||||
profile.saveGlobalProfile(self.filename[: self.filename.rfind('.')] + "_profile.ini")
|
profile.saveGlobalProfile(self.filelist[0][: self.filelist[0].rfind('.')] + "_profile.ini")
|
||||||
p = subprocess.Popen(sliceRun.getSliceCommand(self.filename), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
cmdList = []
|
||||||
self.thread = WorkerThread(self, filename, p)
|
oldProfile = profile.getGlobalProfileString()
|
||||||
|
for filename in self.filelist:
|
||||||
|
if self.filelist.index(filename) > 0:
|
||||||
|
profile.putProfileSetting('fan_enabled', 'False')
|
||||||
|
if len(self.filelist) > 1:
|
||||||
|
profile.putProfileSetting('add_start_end_gcode', 'False')
|
||||||
|
profile.putProfileSetting('gcode_extension', 'multi_extrude_tmp')
|
||||||
|
cmdList.append(sliceRun.getSliceCommand(filename))
|
||||||
|
profile.loadGlobalProfileFromString(oldProfile)
|
||||||
|
self.thread = WorkerThread(self, filelist, cmdList)
|
||||||
|
|
||||||
def OnAbort(self, e):
|
def OnAbort(self, e):
|
||||||
if self.abort:
|
if self.abort:
|
||||||
|
@ -72,14 +76,14 @@ class sliceProgessPanel(wx.Panel):
|
||||||
self.abort = True
|
self.abort = True
|
||||||
|
|
||||||
def OnShowGCode(self, e):
|
def OnShowGCode(self, e):
|
||||||
self.mainWindow.preview3d.loadModelFile(self.filename)
|
self.mainWindow.preview3d.loadModelFiles(self.filelist)
|
||||||
self.mainWindow.preview3d.setViewMode("GCode")
|
self.mainWindow.preview3d.setViewMode("GCode")
|
||||||
|
|
||||||
def OnShowLog(self, e):
|
def OnShowLog(self, e):
|
||||||
LogWindow('\n'.join(self.progressLog))
|
LogWindow('\n'.join(self.progressLog))
|
||||||
|
|
||||||
def OnOpenFileLocation(self, e):
|
def OnOpenFileLocation(self, e):
|
||||||
exporer.openExporer(self.filename[: self.filename.rfind('.')] + "_export.gcode")
|
exporer.openExporer(self.filelist[0][: self.filelist[0].rfind('.')] + "_export.gcode")
|
||||||
|
|
||||||
def OnSliceDone(self, result):
|
def OnSliceDone(self, result):
|
||||||
self.progressGauge.Destroy()
|
self.progressGauge.Destroy()
|
||||||
|
@ -105,7 +109,7 @@ class sliceProgessPanel(wx.Panel):
|
||||||
self.sizer.Layout()
|
self.sizer.Layout()
|
||||||
self.Layout()
|
self.Layout()
|
||||||
self.abort = True
|
self.abort = True
|
||||||
if self.mainWindow.preview3d.loadReModelFile(self.filename):
|
if self.mainWindow.preview3d.loadReModelFiles(self.filelist):
|
||||||
self.mainWindow.preview3d.setViewMode("GCode")
|
self.mainWindow.preview3d.setViewMode("GCode")
|
||||||
|
|
||||||
def SetProgress(self, stepName, layer, maxLayer):
|
def SetProgress(self, stepName, layer, maxLayer):
|
||||||
|
@ -121,18 +125,19 @@ class sliceProgessPanel(wx.Panel):
|
||||||
self.statusText.SetLabel(stepName + " [" + str(layer) + "/" + str(maxLayer) + "]")
|
self.statusText.SetLabel(stepName + " [" + str(layer) + "/" + str(maxLayer) + "]")
|
||||||
|
|
||||||
class WorkerThread(threading.Thread):
|
class WorkerThread(threading.Thread):
|
||||||
def __init__(self, notifyWindow, filename, process):
|
def __init__(self, notifyWindow, filelist, cmdList):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.filename = filename
|
self.filelist = filelist
|
||||||
self.notifyWindow = notifyWindow
|
self.notifyWindow = notifyWindow
|
||||||
self.process = process
|
self.cmdList = cmdList
|
||||||
|
self.fileIdx = 0
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
p = self.process
|
p = subprocess.Popen(self.cmdList[self.fileIdx], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
line = p.stdout.readline()
|
line = p.stdout.readline()
|
||||||
maxValue = 1
|
|
||||||
self.progressLog = []
|
self.progressLog = []
|
||||||
|
maxValue = 1
|
||||||
while(len(line) > 0):
|
while(len(line) > 0):
|
||||||
line = line.rstrip()
|
line = line.rstrip()
|
||||||
if line[0:9] == "Progress[" and line[-1:] == "]":
|
if line[0:9] == "Progress[" and line[-1:] == "]":
|
||||||
|
@ -150,12 +155,43 @@ class WorkerThread(threading.Thread):
|
||||||
return
|
return
|
||||||
line = p.stdout.readline()
|
line = p.stdout.readline()
|
||||||
self.returnCode = p.wait()
|
self.returnCode = p.wait()
|
||||||
logfile = open(self.filename[: self.filename.rfind('.')] + "_export.log", "w")
|
logfile = open(self.filelist[self.fileIdx][: self.filelist[self.fileIdx].rfind('.')] + "_export.log", "w")
|
||||||
for logLine in self.progressLog:
|
for logLine in self.progressLog:
|
||||||
logfile.write(logLine)
|
logfile.write(logLine)
|
||||||
logfile.write('\n')
|
logfile.write('\n')
|
||||||
logfile.close()
|
logfile.close()
|
||||||
|
self.fileIdx += 1
|
||||||
|
if self.fileIdx == len(self.cmdList):
|
||||||
|
if len(self.filelist) > 1:
|
||||||
|
self._stitchMultiExtruder()
|
||||||
wx.CallAfter(self.notifyWindow.OnSliceDone, self)
|
wx.CallAfter(self.notifyWindow.OnSliceDone, self)
|
||||||
|
else:
|
||||||
|
self.run()
|
||||||
|
|
||||||
|
def _stitchMultiExtruder(self):
|
||||||
|
files = []
|
||||||
|
resultFile = open(self.filelist[0][:self.filelist[0].rfind('.')]+'_export.gcode', "w")
|
||||||
|
resultFile.write(';TYPE:CUSTOM\n')
|
||||||
|
resultFile.write(unicode(profile.getAlterationFileContents('start.gcode')).encode('utf-8'))
|
||||||
|
for filename in self.filelist:
|
||||||
|
files.append(open(filename[:filename.rfind('.')]+'_export.multi_extrude_tmp', "r"))
|
||||||
|
|
||||||
|
hasLine = True
|
||||||
|
while hasLine:
|
||||||
|
hasLine = False
|
||||||
|
for f in files:
|
||||||
|
for line in f:
|
||||||
|
resultFile.write(line)
|
||||||
|
hasLine = True
|
||||||
|
if line.startswith(';LAYER:'):
|
||||||
|
break
|
||||||
|
for f in files:
|
||||||
|
f.close()
|
||||||
|
for filename in self.filelist:
|
||||||
|
os.remove(filename[:filename.rfind('.')]+'_export.multi_extrude_tmp')
|
||||||
|
resultFile.write(';TYPE:CUSTOM\n')
|
||||||
|
resultFile.write(unicode(profile.getAlterationFileContents('end.gcode')).encode('utf-8'))
|
||||||
|
resultFile.close()
|
||||||
|
|
||||||
class LogWindow(wx.Frame):
|
class LogWindow(wx.Frame):
|
||||||
def __init__(self, logText):
|
def __init__(self, logText):
|
||||||
|
|
|
@ -123,10 +123,11 @@ G1 Z0 F{max_z_speed}
|
||||||
preferencesDefaultSettings = {
|
preferencesDefaultSettings = {
|
||||||
'wizardDone': 'False',
|
'wizardDone': 'False',
|
||||||
'startMode': 'Simple',
|
'startMode': 'Simple',
|
||||||
'lastFile': 'None',
|
'lastFile': '',
|
||||||
'machine_width': '205',
|
'machine_width': '205',
|
||||||
'machine_depth': '205',
|
'machine_depth': '205',
|
||||||
'machine_height': '200',
|
'machine_height': '200',
|
||||||
|
'extruder_amount': '1',
|
||||||
'filament_density': '1300',
|
'filament_density': '1300',
|
||||||
'steps_per_e': '0',
|
'steps_per_e': '0',
|
||||||
'serial_port': 'AUTO',
|
'serial_port': 'AUTO',
|
||||||
|
|
|
@ -116,5 +116,7 @@ def getSliceCommand(filename):
|
||||||
pypyExe = getPyPyExe()
|
pypyExe = getPyPyExe()
|
||||||
if pypyExe == False:
|
if pypyExe == False:
|
||||||
pypyExe = sys.executable
|
pypyExe = sys.executable
|
||||||
return [pypyExe, os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", os.path.split(sys.argv[0])[1])), '-p', profile.getGlobalProfileString(), filename]
|
cmd = [pypyExe, os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", os.path.split(sys.argv[0])[1])), '-p', profile.getGlobalProfileString()]
|
||||||
|
cmd.append(filename)
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,8 @@ class stlModel():
|
||||||
self._loadBinary(f)
|
self._loadBinary(f)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
self._createOrigonalVertexCopy()
|
||||||
|
|
||||||
def _loadAscii(self, f):
|
def _loadAscii(self, f):
|
||||||
cnt = 0
|
cnt = 0
|
||||||
for line in f:
|
for line in f:
|
||||||
|
@ -62,6 +64,12 @@ class stlModel():
|
||||||
self.vertexes.append(v1)
|
self.vertexes.append(v1)
|
||||||
self.vertexes.append(v2)
|
self.vertexes.append(v2)
|
||||||
|
|
||||||
|
def _createOrigonalVertexCopy(self):
|
||||||
|
self.origonalVertexes = list(self.vertexes)
|
||||||
|
for i in xrange(0, len(self.origonalVertexes)):
|
||||||
|
self.origonalVertexes[i] = self.origonalVertexes[i].copy()
|
||||||
|
self.getMinimumZ()
|
||||||
|
|
||||||
def getMinimumZ(self):
|
def getMinimumZ(self):
|
||||||
minv = self.vertexes[0].copy()
|
minv = self.vertexes[0].copy()
|
||||||
maxv = self.vertexes[0].copy()
|
maxv = self.vertexes[0].copy()
|
||||||
|
|
|
@ -69,3 +69,9 @@ class Vector3():
|
||||||
self.y /= f
|
self.y /= f
|
||||||
self.z /= f
|
self.z /= f
|
||||||
|
|
||||||
|
def min(self, v):
|
||||||
|
return Vector3(min(self.x, v.x), min(self.y, v.y), min(self.z, v.z))
|
||||||
|
|
||||||
|
def max(self, v):
|
||||||
|
return Vector3(max(self.x, v.x), max(self.y, v.y), max(self.z, v.z))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue