From 15fe5a60c6d6cfef2cc9880e37d4b8462ebaaf1a Mon Sep 17 00:00:00 2001 From: Daid Date: Sun, 6 May 2012 22:34:15 +0200 Subject: [PATCH 01/10] Fixed #93 - Oh noes, only 1 change this weekend. What has the world come to? --- Cura/gui/mainWindow.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index 34d2f965..e760f738 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -236,21 +236,19 @@ class mainWindow(configBase.configWindowBase): self.Show(True) def OnLoadProfile(self, e): - dlg=wx.FileDialog(self, "Select profile file to load", self.lastPath, style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) + dlg=wx.FileDialog(self, "Select profile file to load", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) dlg.SetWildcard("ini files (*.ini)|*.ini") if dlg.ShowModal() == wx.ID_OK: profileFile = dlg.GetPath() - self.lastPath = os.path.split(profileFile)[0] profile.loadGlobalProfile(profileFile) self.updateProfileToControls() dlg.Destroy() def OnSaveProfile(self, e): - dlg=wx.FileDialog(self, "Select profile file to save", self.lastPath, style=wx.FD_SAVE) + dlg=wx.FileDialog(self, "Select profile file to save", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE) dlg.SetWildcard("ini files (*.ini)|*.ini") if dlg.ShowModal() == wx.ID_OK: profileFile = dlg.GetPath() - self.lastPath = os.path.split(profileFile)[0] profile.saveGlobalProfile(profileFile) dlg.Destroy() @@ -268,7 +266,7 @@ class mainWindow(configBase.configWindowBase): machineCom.InstallFirmware(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../firmware/default.hex")) def OnCustomFirmware(self, e): - dlg=wx.FileDialog(self, "Open firmware to upload", self.lastPath, style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) + dlg=wx.FileDialog(self, "Open firmware to upload", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) dlg.SetWildcard("HEX file (*.hex)|*.hex;*.HEX") if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath() From 58b4a4816253f75483074b0001d398042b6ca351 Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 7 May 2012 13:24:26 +0200 Subject: [PATCH 02/10] Updated gcode interperter and GCode preview. Fixed #77 --- Cura/gui/opengl.py | 92 +++++++++++++++++++++++++++++++++++ Cura/gui/preview3d.py | 76 +---------------------------- Cura/util/gcodeInterpreter.py | 16 +++--- 3 files changed, 104 insertions(+), 80 deletions(-) diff --git a/Cura/gui/opengl.py b/Cura/gui/opengl.py index 92ffcdea..0507f566 100644 --- a/Cura/gui/opengl.py +++ b/Cura/gui/opengl.py @@ -1,3 +1,7 @@ +import math + +from util import util3d +from util import profile try: import OpenGL @@ -215,3 +219,91 @@ def DrawSTL(mesh): glVertex3f(v3.x, v3.y, v3.z) glVertex3f(v2.x, v2.y, v2.z) glEnd() + +def DrawGCodeLayer(layer): + filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2 + filamentArea = math.pi * filamentRadius * filamentRadius + lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10 + + fillCycle = 0 + fillColorCycle = [[0.5,0.5,0.0],[0.0,0.5,0.5],[0.5,0.0,0.5]] + + glDisable(GL_CULL_FACE) + for path in layer: + if path.type == 'move': + glColor3f(0,0,1) + if path.type == 'extrude': + if path.pathType == 'FILL': + glColor3fv(fillColorCycle[fillCycle]) + fillCycle = (fillCycle + 1) % len(fillColorCycle) + elif path.pathType == 'WALL-INNER': + glColor3fv([0,1,0]) + elif path.pathType == 'SUPPORT': + glColor3fv([0,1,1]) + elif path.pathType == 'SKIRT': + glColor3fv([0,0.5,0.5]) + else: + glColor3fv([1,0,0]) + if path.type == 'retract': + glColor3fv([0,1,1]) + if path.type == 'extrude': + drawLength = 0.0 + prevNormal = None + for i in xrange(0, len(path.list)-1): + v0 = path.list[i] + v1 = path.list[i+1] + + # Calculate line width from ePerDistance (needs layer thickness and filament diameter) + dist = (v0 - v1).vsize() + if dist > 0 and path.layerThickness > 0: + extrusionMMperDist = (v1.e - v0.e) / dist + lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 + + drawLength += (v0 - v1).vsize() + normal = (v0 - v1).cross(util3d.Vector3(0,0,1)) + normal.normalize() + + vv2 = v0 + normal * lineWidth + vv3 = v1 + normal * lineWidth + vv0 = v0 - normal * lineWidth + vv1 = v1 - normal * lineWidth + + glBegin(GL_QUADS) + glVertex3f(vv0.x, vv0.y, vv0.z - 0.01) + glVertex3f(vv1.x, vv1.y, vv1.z - 0.01) + glVertex3f(vv3.x, vv3.y, vv3.z - 0.01) + glVertex3f(vv2.x, vv2.y, vv2.z - 0.01) + glEnd() + if prevNormal != None: + n = (normal + prevNormal) + n.normalize() + vv4 = v0 + n * lineWidth + vv5 = v0 - n * lineWidth + glBegin(GL_QUADS) + glVertex3f(vv2.x, vv2.y, vv2.z) + glVertex3f(vv4.x, vv4.y, vv4.z) + glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z) + glVertex3f(v0.x, v0.y, v0.z) + + glVertex3f(vv0.x, vv0.y, vv0.z) + glVertex3f(vv5.x, vv5.y, vv5.z) + glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z) + glVertex3f(v0.x, v0.y, v0.z) + glEnd() + + prevNormal = normal + prevVv1 = vv1 + prevVv3 = vv3 + + #for v in path.list: + # glBegin(GL_TRIANGLE_FAN) + # glVertex3f(v.x, v.y, v.z - 0.001) + # for i in xrange(0, 16+1): + # glVertex3f(v.x + math.cos(math.pi*2/16*i) * lineWidth, v.y + math.sin(math.pi*2/16*i) * lineWidth, v.z - 0.01) + # glEnd() + else: + glBegin(GL_LINE_STRIP) + for v in path.list: + glVertex3f(v.x, v.y, v.z) + glEnd() + glEnable(GL_CULL_FACE) diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index 52665936..71a2638b 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -446,85 +446,13 @@ class PreviewGLCanvas(glcanvas.GLCanvas): self.gcodeDisplayList = glGenLists(len(self.parent.gcode.layerList)); self.gcodeDisplayListCount = len(self.parent.gcode.layerList) self.parent.gcodeDirty = False - prevLayerZ = 0.0 - curLayerZ = 0.0 - - layerThickness = 0.0 - filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2 - filamentArea = math.pi * filamentRadius * filamentRadius - lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10 curLayerNum = 0 for layer in self.parent.gcode.layerList: glNewList(self.gcodeDisplayList + curLayerNum, GL_COMPILE) - glDisable(GL_CULL_FACE) - curLayerZ = layer[0].list[1].z - layerThickness = curLayerZ - prevLayerZ - prevLayerZ = layer[-1].list[-1].z - for path in layer: - if path.type == 'move': - glColor3f(0,0,1) - if path.type == 'extrude': - if path.pathType == 'FILL': - glColor3f(0.5,0.5,0) - elif path.pathType == 'WALL-INNER': - glColor3f(0,1,0) - elif path.pathType == 'SUPPORT': - glColor3f(0,1,1) - elif path.pathType == 'SKIRT': - glColor3f(0,0.5,0.5) - else: - glColor3f(1,0,0) - if path.type == 'retract': - glColor3f(0,1,1) - if path.type == 'extrude': - for i in xrange(0, len(path.list)-1): - v0 = path.list[i] - v1 = path.list[i+1] - - # Calculate line width from ePerDistance (needs layer thickness and filament diameter) - dist = (v0 - v1).vsize() - if dist > 0 and layerThickness > 0: - extrusionMMperDist = (v1.e - v0.e) / dist - lineWidth = extrusionMMperDist * filamentArea / layerThickness / 2 - - normal = (v0 - v1).cross(util3d.Vector3(0,0,1)) - normal.normalize() - v2 = v0 + normal * lineWidth - v3 = v1 + normal * lineWidth - v0 = v0 - normal * lineWidth - v1 = v1 - normal * lineWidth - - glBegin(GL_QUADS) - if path.pathType == 'FILL': #Remove depth buffer fighting on infill/wall overlap - glVertex3f(v0.x, v0.y, v0.z - 0.02) - glVertex3f(v1.x, v1.y, v1.z - 0.02) - glVertex3f(v3.x, v3.y, v3.z - 0.02) - glVertex3f(v2.x, v2.y, v2.z - 0.02) - else: - glVertex3f(v0.x, v0.y, v0.z - 0.01) - glVertex3f(v1.x, v1.y, v1.z - 0.01) - glVertex3f(v3.x, v3.y, v3.z - 0.01) - glVertex3f(v2.x, v2.y, v2.z - 0.01) - glEnd() - - #for v in path['list']: - # glBegin(GL_TRIANGLE_FAN) - # glVertex3f(v.x, v.y, v.z - 0.001) - # for i in xrange(0, 16+1): - # if path['pathType'] == 'FILL': #Remove depth buffer fighting on infill/wall overlap - # glVertex3f(v.x + math.cos(math.pi*2/16*i) * lineWidth, v.y + math.sin(math.pi*2/16*i) * lineWidth, v.z - 0.02) - # else: - # glVertex3f(v.x + math.cos(math.pi*2/16*i) * lineWidth, v.y + math.sin(math.pi*2/16*i) * lineWidth, v.z - 0.01) - # glEnd() - else: - glBegin(GL_LINE_STRIP) - for v in path.list: - glVertex3f(v.x, v.y, v.z) - glEnd() - curLayerNum += 1 - glEnable(GL_CULL_FACE) + opengl.DrawGCodeLayer(layer) glEndList() + curLayerNum += 1 if self.parent.gcode != None and (self.viewMode == "GCode" or self.viewMode == "Mixed"): glEnable(GL_COLOR_MATERIAL) diff --git a/Cura/util/gcodeInterpreter.py b/Cura/util/gcodeInterpreter.py index 5714972c..08586178 100644 --- a/Cura/util/gcodeInterpreter.py +++ b/Cura/util/gcodeInterpreter.py @@ -10,9 +10,10 @@ from util import util3d from util import profile class gcodePath(object): - def __init__(self, newType, pathType, startPoint): + def __init__(self, newType, pathType, layerThickness, startPoint): self.type = newType self.pathType = pathType + self.layerThickness = layerThickness self.list = [startPoint] class gcode(object): @@ -61,10 +62,11 @@ class gcode(object): scale = 1.0 posAbs = True feedRate = 3600 + layerThickness = 0.1 pathType = 'CUSTOM'; startCodeDone = False currentLayer = [] - currentPath = gcodePath('move', pathType, pos.copy()) + currentPath = gcodePath('move', pathType, layerThickness, pos.copy()) currentPath.list[0].e = totalExtrusion currentLayer.append(currentPath) for line in gcodeFile: @@ -88,6 +90,9 @@ class gcode(object): pathType = 'WALL-INNER' elif comment == 'skirt': pathType = 'SKIRT' + if comment.startswith('LAYER:'): + self.layerList.append(currentLayer) + currentLayer = [] if pathType != "CUSTOM": startCodeDone = True line = line[0:line.find(';')] @@ -126,9 +131,8 @@ class gcode(object): else: pos.z += z * scale #Check if we have a new layer. - if oldPos.z < pos.z and startCodeDone and len(currentLayer) > 0: - self.layerList.append(currentLayer) - currentLayer = [] + if oldPos.z != pos.z: + layerThickness = abs(oldPos.z - pos.z) if f is not None: feedRate = f if x is not None or y is not None or z is not None: @@ -152,7 +156,7 @@ class gcode(object): if totalExtrusion > maxExtrusion: maxExtrusion = totalExtrusion if currentPath.type != moveType or currentPath.pathType != pathType: - currentPath = gcodePath(moveType, pathType, currentPath.list[-1]) + currentPath = gcodePath(moveType, pathType, layerThickness, currentPath.list[-1]) currentLayer.append(currentPath) newPos = pos.copy() newPos.e = totalExtrusion From 8a495554d8c8f28a94835aa5eb1259be2a2208fc Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 7 May 2012 13:51:28 +0200 Subject: [PATCH 03/10] Generate 1 GCode layer per draw cycle, this keeps the UI responsive during the generation of display lists with huge GCode files. --- Cura/gui/opengl.py | 7 ------- Cura/gui/preview3d.py | 22 +++++++++++++++++----- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Cura/gui/opengl.py b/Cura/gui/opengl.py index 0507f566..e5204cff 100644 --- a/Cura/gui/opengl.py +++ b/Cura/gui/opengl.py @@ -294,13 +294,6 @@ def DrawGCodeLayer(layer): prevNormal = normal prevVv1 = vv1 prevVv3 = vv3 - - #for v in path.list: - # glBegin(GL_TRIANGLE_FAN) - # glVertex3f(v.x, v.y, v.z - 0.001) - # for i in xrange(0, 16+1): - # glVertex3f(v.x + math.cos(math.pi*2/16*i) * lineWidth, v.y + math.sin(math.pi*2/16*i) * lineWidth, v.z - 0.01) - # glEnd() else: glBegin(GL_LINE_STRIP) for v in path.list: diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index 71a2638b..190cbb09 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -372,6 +372,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas): self.offsetY = 0 self.view3D = True self.gcodeDisplayList = None + self.gcodeDisplayListMade = None self.gcodeDisplayListCount = 0 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]] @@ -446,13 +447,23 @@ class PreviewGLCanvas(glcanvas.GLCanvas): self.gcodeDisplayList = glGenLists(len(self.parent.gcode.layerList)); self.gcodeDisplayListCount = len(self.parent.gcode.layerList) self.parent.gcodeDirty = False - + self.gcodeDisplayListMade = [] + for idx in xrange(0, len(self.parent.gcode.layerList)): + self.gcodeDisplayListMade.append(False) + + if self.gcodeDisplayListMade != None: curLayerNum = 0 for layer in self.parent.gcode.layerList: - glNewList(self.gcodeDisplayList + curLayerNum, GL_COMPILE) - opengl.DrawGCodeLayer(layer) - glEndList() + if not self.gcodeDisplayListMade[curLayerNum]: + glNewList(self.gcodeDisplayList + curLayerNum, GL_COMPILE) + opengl.DrawGCodeLayer(layer) + glEndList() + self.gcodeDisplayListMade[curLayerNum] = True + self.Refresh() + break curLayerNum += 1 + if curLayerNum == len(self.parent.gcode.layerList): + self.gcodeDisplayListMade = None if self.parent.gcode != None and (self.viewMode == "GCode" or self.viewMode == "Mixed"): glEnable(GL_COLOR_MATERIAL) @@ -467,7 +478,8 @@ class PreviewGLCanvas(glcanvas.GLCanvas): c = 0.1 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0,0,0,0]) glLightfv(GL_LIGHT0, GL_AMBIENT, [c,c,c,c]) - glCallList(self.gcodeDisplayList + i) + if self.gcodeDisplayListMade == None or self.gcodeDisplayListMade[i]: + glCallList(self.gcodeDisplayList + i) glDisable(GL_LIGHTING) glDisable(GL_COLOR_MATERIAL) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, [0.2, 0.2, 0.2, 1.0]); From c04c09a437da1ee944b6eac96c55a0f05e135a7b Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 7 May 2012 16:03:42 +0200 Subject: [PATCH 04/10] Added preferences to project planner to configure head size --- Cura/gui/projectPlanner.py | 44 ++++++++++++++++++++++++++++++++++++ Cura/images/preferences.png | Bin 0 -> 690 bytes 2 files changed, 44 insertions(+) create mode 100644 Cura/images/preferences.png diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index b24721e5..67317627 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -19,6 +19,8 @@ except: from gui import opengl from gui import toolbarUtil from gui import icon +from gui import configBase +from gui import validators from util import profile from util import util3d from util import stl @@ -159,6 +161,8 @@ class projectPlanner(wx.Frame): toolbarUtil.RadioButton(self.toolbar, group, 'object-top-on.png', 'object-top-off.png', 'Topdown view', callback=self.OnTopClick).SetValue(True) self.toolbar.AddSeparator() toolbarUtil.NormalButton(self.toolbar, self.OnQuit, 'exit.png', 'Close project planner') + self.toolbar.AddSeparator() + toolbarUtil.NormalButton(self.toolbar, self.OnPreferences, 'preferences.png', 'Project planner preferences') self.toolbar.Realize() @@ -228,6 +232,11 @@ class projectPlanner(wx.Frame): def OnQuit(self, e): self.Close() + def OnPreferences(self, e): + prefDialog = preferencesDialog(self) + prefDialog.Centre() + prefDialog.Show(True) + def OnSaveProject(self, e): dlg=wx.FileDialog(self, "Save project file", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE) dlg.SetWildcard("Project files (*.curaproject)|*.curaproject") @@ -821,6 +830,41 @@ class ProjectSliceProgressWindow(wx.Frame): wx.CallAfter(self.abortButton.SetLabel, 'Close') +class preferencesDialog(configBase.configWindowBase): + def __init__(self, parent): + super(preferencesDialog, self).__init__(title="Project Planner Preferences") + + self.parent = parent + wx.EVT_CLOSE(self, self.OnClose) + + extruderAmount = int(profile.getPreference('extruder_amount')) + + left, right, main = self.CreateConfigPanel(self) + configBase.TitleRow(left, 'Machine head size') + c = configBase.SettingRow(left, 'Head size - X towards home (mm)', 'extruder_head_size_min_x', '0', 'Size of your printer head in the X direction, on the Ultimaker your fan is in this direction.', type = 'preference') + validators.validFloat(c, 0.1) + c = configBase.SettingRow(left, 'Head size - X towards end (mm)', 'extruder_head_size_max_x', '0', 'Size of your printer head in the X direction.', type = 'preference') + validators.validFloat(c, 0.1) + c = configBase.SettingRow(left, 'Head size - Y towards home (mm)', 'extruder_head_size_min_y', '0', 'Size of your printer head in the Y direction.', type = 'preference') + validators.validFloat(c, 0.1) + c = configBase.SettingRow(left, 'Head size - Y towards end (mm)', 'extruder_head_size_max_y', '0', 'Size of your printer head in the Y direction.', type = 'preference') + validators.validFloat(c, 0.1) + + self.okButton = wx.Button(left, -1, 'Ok') + left.GetSizer().Add(self.okButton, (left.GetSizer().GetRows(), 1)) + self.okButton.Bind(wx.EVT_BUTTON, self.OnClose) + + self.MakeModal(True) + main.Fit() + self.Fit() + + def OnClose(self, e): + self.parent.headSizeMin = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0) + self.parent.headSizeMax = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0) + + self.MakeModal(False) + self.Destroy() + def main(): app = wx.App(False) projectPlanner().Show(True) diff --git a/Cura/images/preferences.png b/Cura/images/preferences.png new file mode 100644 index 0000000000000000000000000000000000000000..dab6b5190b33040e2c8a1b67132958ba99163574 GIT binary patch literal 690 zcmV;j0!{siP)Td47@B2I*7DcFFp@Cs$ z{>=Pm=6MGGQ*+^yp}C188q=Pf5>6y&)y_masBZO|83d{^H|52o6+KT#f#U zwE;*;HCWS{qIerlpRDtGy=UuBH8?wOb;PA522t^=TZ?OJYqj;5(e`ZcDgJ?e6ovl$ zy!>%g{dL?h&iMBGoc@-cF!tT0{p3$5XD2e0F)BJnF+V3_ubJ1<7=~Sz1_N z>fIFO`^u3LK75+PG)*QZ#-sv$I>1WYc|1Qahl1?|%+Ag*8<^o<&qHdeju4m+P*%1V zha;7x#U+M^he>xiafBx=_sU4O_Mj=F#OralhV&A>?a~#B3U?3+28pdlnVg&?)8irh zBf`?c7yN!dyHn?>udXCzEntK`PAn?D&1o&=mCYTw8N#MWBkBK-s9C%j=z5{+s-rq* zr_ZLR=Yp_6CR7Rwq?w4f;2XZvhyau-Jxysc>9$+Mo{~;{eKm23J;fqfNRT3tBmeToQmVS$aUWLs Y4dyl&fhWT Date: Mon, 7 May 2012 16:26:29 +0200 Subject: [PATCH 05/10] Bring simple mode window up to speed with the rest --- Cura/gui/mainWindow.py | 12 ++++++------ Cura/gui/simpleMode.py | 35 +++++++++++++++++------------------ 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index e760f738..d4b8f55f 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -41,7 +41,7 @@ class mainWindow(configBase.configWindowBase): menubar = wx.MenuBar() fileMenu = wx.Menu() i = fileMenu.Append(-1, 'Load model file...') - self.Bind(wx.EVT_MENU, self.OnLoadModel, i) + self.Bind(wx.EVT_MENU, lambda e: self._showModelLoadDialog(1), i) fileMenu.AppendSeparator() i = fileMenu.Append(-1, 'Open Profile...') self.Bind(wx.EVT_MENU, self.OnLoadProfile, i) @@ -189,23 +189,23 @@ class mainWindow(configBase.configWindowBase): loadButton = wx.Button(self, -1, 'Load Model') sliceButton = wx.Button(self, -1, 'Slice to GCode') printButton = wx.Button(self, -1, 'Print GCode') - self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton) + self.Bind(wx.EVT_BUTTON, lambda e: self._showModelLoadDialog(1), loadButton) self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton) 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) + self.Bind(wx.EVT_BUTTON, lambda e: self._showModelLoadDialog(2), loadButton2) if extruderCount > 2: loadButton3 = wx.Button(self, -1, 'Load Tripple') - self.Bind(wx.EVT_BUTTON, self.OnLoadModel3, loadButton3) + self.Bind(wx.EVT_BUTTON, lambda e: self._showModelLoadDialog(3), loadButton3) if extruderCount > 2: loadButton4 = wx.Button(self, -1, 'Load Quad') - self.Bind(wx.EVT_BUTTON, self.OnLoadModel4, loadButton4) + self.Bind(wx.EVT_BUTTON, lambda e: self._showModelLoadDialog(4), loadButton4) #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, lambda e: self._showModelLoadDialog(1), self.preview3d.glCanvas) #Main sizer, to position the preview window, buttons and tab control sizer = wx.GridBagSizer() diff --git a/Cura/gui/simpleMode.py b/Cura/gui/simpleMode.py index 4f38ca95..63928fd3 100644 --- a/Cura/gui/simpleMode.py +++ b/Cura/gui/simpleMode.py @@ -51,8 +51,11 @@ class simpleModeWindow(configBase.configWindowBase): menubar.Append(helpMenu, 'Help') self.SetMenuBar(menubar) - self.lastPath = "" - self.filename = profile.getPreference('lastFile') + if profile.getPreference('lastFile') != '': + self.filelist = profile.getPreference('lastFile').split(';') + self.SetTitle(self.filelist[-1] + ' - Cura - ' + version.getVersion()) + else: + self.filelist = [] self.progressPanelList = [] #Preview window @@ -116,9 +119,8 @@ class simpleModeWindow(configBase.configWindowBase): sizer.Add(printButton, (1,3), flag=wx.RIGHT, border=5) self.sizer = sizer - if self.filename != "None": - self.preview3d.loadModelFiles([self.filename]) - self.lastPath = os.path.split(self.filename)[0] + if len(self.filelist) > 0: + self.preview3d.loadModelFiles(self.filelist) self.updateProfileToControls() @@ -136,7 +138,7 @@ class simpleModeWindow(configBase.configWindowBase): machineCom.InstallFirmware(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../firmware/default.hex")) def OnCustomFirmware(self, e): - dlg=wx.FileDialog(self, "Open firmware to upload", self.lastPath, style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) + dlg=wx.FileDialog(self, "Open firmware to upload", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) dlg.SetWildcard("HEX file (*.hex)|*.hex;*.HEX") if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath() @@ -150,20 +152,17 @@ class simpleModeWindow(configBase.configWindowBase): self.updateProfileToControls() def OnLoadModel(self, e): - dlg=wx.FileDialog(self, "Open file to print", self.lastPath, style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) + dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL") if dlg.ShowModal() == wx.ID_OK: - self.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.loadModelFiles([self.filename]) + self.filelist = [dlg.GetPath()] + profile.putPreference('lastFile', ';'.join(self.filelist)) + self.preview3d.loadModelFiles(self.filelist) self.preview3d.setViewMode("Normal") dlg.Destroy() 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) return #save the current profile so we can put it back latter @@ -262,7 +261,7 @@ class simpleModeWindow(configBase.configWindowBase): put('bottom_thickness', '0.0') #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.Layout() newSize = self.GetSize(); @@ -274,13 +273,13 @@ class simpleModeWindow(configBase.configWindowBase): profile.loadGlobalProfileFromString(oldProfile) 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) 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) return - printWindow.printFile(self.filename[: self.filename.rfind('.')] + "_export.gcode") + printWindow.printFile(self.filelist[0][: self.filelist[0].rfind('.')] + "_export.gcode") def OnNormalSwitch(self, e): from gui import mainWindow From 7abad9e98b66ffd8527a6fb2d7de02c161b059ad Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 7 May 2012 16:42:15 +0200 Subject: [PATCH 06/10] Add 3 seconds delay in config wizard for the SD card init to timeout. --- Cura/gui/configWizard.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Cura/gui/configWizard.py b/Cura/gui/configWizard.py index 8edaf410..812b073f 100644 --- a/Cura/gui/configWizard.py +++ b/Cura/gui/configWizard.py @@ -180,11 +180,13 @@ class UltimakerCheckupPage(InfoPage): wx.CallAfter(self.AddProgressText, "Error: Missing start message.") self.comm.close() return - + + #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found. + time.sleep(3) + wx.CallAfter(self.AddProgressText, "Disabling step motors...") if self.DoCommCommandWithTimeout('M84') == False: wx.CallAfter(self.AddProgressText, "Error: Missing reply to Deactivate steppers (M84).") - wx.CallAfter(self.AddProgressText, "Possible cause: Temperature MIN/MAX.\nCheck temperature sensor connections.") self.comm.close() return @@ -289,6 +291,7 @@ class UltimakerCheckupPage(InfoPage): if line == '': self.comm.close() return False + print line if line.startswith(replyStart): break t.cancel() @@ -372,6 +375,9 @@ class UltimakerCalibrateStepsPerEPage(InfoPage): return if line.startswith('start'): break + #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found. + time.sleep(3) + self.sendGCommand('M302') #Disable cold extrusion protection self.sendGCommand("M92 E%f" % (currentEValue)); self.sendGCommand("G92 E0"); @@ -392,6 +398,9 @@ class UltimakerCalibrateStepsPerEPage(InfoPage): return if line.startswith('start'): break + #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found. + time.sleep(3) + self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out. wx.MessageBox('Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)', 'Machine heatup', wx.OK | wx.ICON_INFORMATION) self.sendGCommand('M104 S0') From f64298d58366eb50939f8c8a0598aa708231b627 Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 7 May 2012 17:26:40 +0200 Subject: [PATCH 07/10] The new GCode text editor with syntax highlight is very cool, but is causing problems on MacOS, so fall back to a simple textarea in that case. --- Cura/gui/configBase.py | 2 +- Cura/gui/gcodeTextArea.py | 194 ++++++++++++++++++++------------------ Cura/gui/toolbarUtil.py | 2 +- 3 files changed, 103 insertions(+), 95 deletions(-) diff --git a/Cura/gui/configBase.py b/Cura/gui/configBase.py index 40026d1e..79a7d248 100644 --- a/Cura/gui/configBase.py +++ b/Cura/gui/configBase.py @@ -64,7 +64,7 @@ class configWindowBase(wx.Frame): self.popup.text.SetLabel(setting.helpText) self.popup.text.Wrap(350) self.popup.Fit() - if os.name == 'darwin': + if sys.platform == 'darwin': x, y = self.ClientToScreenXY(0, 0) sx, sy = self.GetClientSizeTuple() else: diff --git a/Cura/gui/gcodeTextArea.py b/Cura/gui/gcodeTextArea.py index 68d05249..5487241f 100644 --- a/Cura/gui/gcodeTextArea.py +++ b/Cura/gui/gcodeTextArea.py @@ -3,101 +3,109 @@ import sys,math,os from util import profile -class GcodeTextArea(wx.stc.StyledTextCtrl): - def __init__(self, parent): - super(GcodeTextArea, self).__init__(parent) - - self.SetLexer(wx.stc.STC_LEX_CONTAINER) - self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyle) - - fontSize = wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize() - fontName = wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL).GetFaceName() - self.SetStyleBits(5) - self.StyleSetSpec(0, "face:%s,size:%d" % (fontName, fontSize)) - self.StyleSetSpec(1, "fore:#006000,face:%s,size:%d" % (fontName, fontSize)) - self.IndicatorSetStyle(0, wx.stc.STC_INDIC_TT) - self.IndicatorSetForeground(0, "#0000FF") - self.IndicatorSetStyle(1, wx.stc.STC_INDIC_SQUIGGLE) - self.IndicatorSetForeground(1, "#FF0000") - self.SetWrapMode(wx.stc.STC_WRAP_NONE) - self.SetScrollWidth(1000) - - #GCodes and MCodes as supported by Marlin - #GCode 21 is not really supported by Marlin, but we still do not report it as error as it's often used. - self.supportedGCodes = [0,1,2,3,4,21,28,90,91,92] - self.supportedMCodes = [17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,42,80,81,82,83,84,85,92,104,105,106,107,109,114,115,117,119,140,190,201,202,203,204,205,206,220,221,240,301,302,303,400,500,501,502,503,999] - - def OnStyle(self, e): - lineNr = self.LineFromPosition(self.GetEndStyled()) - while self.PositionFromLine(lineNr) > -1: - line = self.GetLine(lineNr) - start = self.PositionFromLine(lineNr) - length = self.LineLength(lineNr) - self.StartStyling(start, 255) - self.SetStyling(length, 0) - if ';' in line: - pos = line.index(';') - self.StartStyling(start + pos, 31) - self.SetStyling(length - pos, 1) - length = pos +if sys.platform == 'darwin': + class GcodeTextArea(wx.TextCtrl): + def __init__(self, parent): + super(GcodeTextArea, self).__init__(parent, style=wx.TE_MULTILINE|wx.TE_DONTWRAP|wx.TE_PROCESS_TAB) - pos = 0 - while pos < length: - if line[pos] in " \t\n\r": - while pos < length and line[pos] in " \t\n\r": - pos += 1 - else: - end = pos - while end < length and not line[end] in " \t\n\r": - end += 1 - if self.checkGCodePart(line[pos:end], start + pos): - self.StartStyling(start + pos, 0x20) - self.SetStyling(end - pos, 0x20) - pos = end - lineNr += 1 + self.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) - def checkGCodePart(self, part, pos): - if len(part) < 2: - self.StartStyling(pos, 0x40) - self.SetStyling(1, 0x40) - return True - if not part[0] in "GMXYZFESTBPIDCJ": - self.StartStyling(pos, 0x40) - self.SetStyling(1, 0x40) - return True - if part[1] == '{': - if part[-1] != '}': - return True - tag = part[2:-1] - if not profile.isProfileSetting(tag) and not profile.isPreference(tag): - self.StartStyling(pos + 2, 0x40) - self.SetStyling(len(tag), 0x40) - return True - elif part[0] in "GM": - try: - code = int(part[1:]) - except (ValueError): - self.StartStyling(pos + 1, 0x40) - self.SetStyling(len(part) - 1, 0x40) - return True - if part[0] == 'G': - if not code in self.supportedGCodes: - return True - if part[0] == 'M': - if not code in self.supportedMCodes: - return True - else: - try: - float(part[1:]) - except (ValueError): - self.StartStyling(pos + 1, 0x40) - self.SetStyling(len(part) - 1, 0x40) - return True - return False +else: + class GcodeTextArea(wx.stc.StyledTextCtrl): + def __init__(self, parent): + super(GcodeTextArea, self).__init__(parent) - def GetValue(self): - return self.GetText() + self.SetLexer(wx.stc.STC_LEX_CONTAINER) + self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyle) + + fontSize = wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize() + fontName = wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL).GetFaceName() + self.SetStyleBits(5) + self.StyleSetSpec(0, "face:%s,size:%d" % (fontName, fontSize)) + self.StyleSetSpec(1, "fore:#006000,face:%s,size:%d" % (fontName, fontSize)) + self.IndicatorSetStyle(0, wx.stc.STC_INDIC_TT) + self.IndicatorSetForeground(0, "#0000FF") + self.IndicatorSetStyle(1, wx.stc.STC_INDIC_SQUIGGLE) + self.IndicatorSetForeground(1, "#FF0000") + self.SetWrapMode(wx.stc.STC_WRAP_NONE) + self.SetScrollWidth(1000) + + #GCodes and MCodes as supported by Marlin + #GCode 21 is not really supported by Marlin, but we still do not report it as error as it's often used. + self.supportedGCodes = [0,1,2,3,4,21,28,90,91,92] + self.supportedMCodes = [17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,42,80,81,82,83,84,85,92,104,105,106,107,109,114,115,117,119,140,190,201,202,203,204,205,206,220,221,240,301,302,303,400,500,501,502,503,999] + + def OnStyle(self, e): + lineNr = self.LineFromPosition(self.GetEndStyled()) + while self.PositionFromLine(lineNr) > -1: + line = self.GetLine(lineNr) + start = self.PositionFromLine(lineNr) + length = self.LineLength(lineNr) + self.StartStyling(start, 255) + self.SetStyling(length, 0) + if ';' in line: + pos = line.index(';') + self.StartStyling(start + pos, 31) + self.SetStyling(length - pos, 1) + length = pos + + pos = 0 + while pos < length: + if line[pos] in " \t\n\r": + while pos < length and line[pos] in " \t\n\r": + pos += 1 + else: + end = pos + while end < length and not line[end] in " \t\n\r": + end += 1 + if self.checkGCodePart(line[pos:end], start + pos): + self.StartStyling(start + pos, 0x20) + self.SetStyling(end - pos, 0x20) + pos = end + lineNr += 1 + + def checkGCodePart(self, part, pos): + if len(part) < 2: + self.StartStyling(pos, 0x40) + self.SetStyling(1, 0x40) + return True + if not part[0] in "GMXYZFESTBPIDCJ": + self.StartStyling(pos, 0x40) + self.SetStyling(1, 0x40) + return True + if part[1] == '{': + if part[-1] != '}': + return True + tag = part[2:-1] + if not profile.isProfileSetting(tag) and not profile.isPreference(tag): + self.StartStyling(pos + 2, 0x40) + self.SetStyling(len(tag), 0x40) + return True + elif part[0] in "GM": + try: + code = int(part[1:]) + except (ValueError): + self.StartStyling(pos + 1, 0x40) + self.SetStyling(len(part) - 1, 0x40) + return True + if part[0] == 'G': + if not code in self.supportedGCodes: + return True + if part[0] == 'M': + if not code in self.supportedMCodes: + return True + else: + try: + float(part[1:]) + except (ValueError): + self.StartStyling(pos + 1, 0x40) + self.SetStyling(len(part) - 1, 0x40) + return True + return False + + def GetValue(self): + return self.GetText() - def SetValue(self, s): - self.SetText(s) + def SetValue(self, s): + self.SetText(s) diff --git a/Cura/gui/toolbarUtil.py b/Cura/gui/toolbarUtil.py index 1ec088ef..5914a308 100644 --- a/Cura/gui/toolbarUtil.py +++ b/Cura/gui/toolbarUtil.py @@ -41,7 +41,7 @@ class Toolbar(wx.ToolBar): popup.text.SetLabel(control.helpText) popup.text.Wrap(350) popup.Fit(); - if os.name == 'darwin': + if sys.platform == 'darwin': x, y = self.GetParent().ClientToScreenXY(0, 0) sx, sy = self.GetParent().GetClientSizeTuple() else: From fb935e49fe50135d6d291e964dfdc1d0bb881d67 Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 7 May 2012 17:36:41 +0200 Subject: [PATCH 08/10] Keep the objects on the printer bed after autoplacing in project planner. Fixed #92 --- Cura/gui/projectPlanner.py | 30 ++++++++++++++++++------------ Cura/gui/toolbarUtil.py | 2 +- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index 67317627..4b5b1ec0 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -31,11 +31,12 @@ class Action(object): pass class ProjectObject(stl.stlModel): - def __init__(self, filename): + def __init__(self, parent, filename): super(ProjectObject, self).__init__() self.load(filename) + self.parent = parent self.filename = filename self.scale = 1.0 self.rotate = 0.0 @@ -110,7 +111,7 @@ class ProjectObject(stl.stlModel): self.modelDirty = True def clone(self): - p = ProjectObject(self.filename) + p = ProjectObject(self.parent, self.filename) p.centerX = self.centerX + 5 p.centerY = self.centerY + 5 @@ -128,6 +129,16 @@ class ProjectObject(stl.stlModel): p.updateModelTransform() return p + + def clampXY(self): + if self.centerX < -self.getMinimum().x * self.scale + self.parent.extruderOffset[self.extruder].x: + self.centerX = -self.getMinimum().x * self.scale + self.parent.extruderOffset[self.extruder].x + if self.centerY < -self.getMinimum().y * self.scale + self.parent.extruderOffset[self.extruder].y: + self.centerY = -self.getMinimum().y * self.scale + self.parent.extruderOffset[self.extruder].y + if self.centerX > self.parent.machineSize.x + self.parent.extruderOffset[self.extruder].x - self.getMaximum().x * self.scale: + self.centerX = self.parent.machineSize.x + self.parent.extruderOffset[self.extruder].x - self.getMaximum().x * self.scale + if self.centerY > self.parent.machineSize.y + self.parent.extruderOffset[self.extruder].y - self.getMaximum().y * self.scale: + self.centerY = self.parent.machineSize.y + self.parent.extruderOffset[self.extruder].y - self.getMaximum().y * self.scale class projectPlanner(wx.Frame): "Main user interface window" @@ -273,7 +284,7 @@ class projectPlanner(wx.Frame): while cp.has_section('model_%d' % (i)): section = 'model_%d' % (i) - item = ProjectObject(unicode(cp.get(section, 'filename'), "utf-8")) + item = ProjectObject(self, unicode(cp.get(section, 'filename'), "utf-8")) item.centerX = float(cp.get(section, 'centerX')) item.centerY = float(cp.get(section, 'centerY')) item.scale = float(cp.get(section, 'scale')) @@ -326,7 +337,7 @@ class projectPlanner(wx.Frame): dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL") if dlg.ShowModal() == wx.ID_OK: for filename in dlg.GetPaths(): - item = ProjectObject(filename) + item = ProjectObject(self, filename) profile.putPreference('lastFile', item.filename) self.list.append(item) self.selection = item @@ -396,6 +407,8 @@ class projectPlanner(wx.Frame): bestAllowedSize = i bestArea = area self._doAutoPlace(bestAllowedSize) + for item in self.list: + item.clampXY() self.preview.Refresh() def _doAutoPlace(self, allowedSizeY): @@ -546,14 +559,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas): if item != None: item.centerX += float(e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2 item.centerY -= float(e.GetY() - self.oldY) * self.zoom / self.GetSize().GetHeight() * 2 - if item.centerX < -item.getMinimum().x * item.scale + self.parent.extruderOffset[item.extruder].x: - item.centerX = -item.getMinimum().x * item.scale + self.parent.extruderOffset[item.extruder].x - if item.centerY < -item.getMinimum().y * item.scale + self.parent.extruderOffset[item.extruder].y: - item.centerY = -item.getMinimum().y * item.scale + self.parent.extruderOffset[item.extruder].y - if item.centerX > self.parent.machineSize.x + self.parent.extruderOffset[item.extruder].x - item.getMaximum().x * item.scale: - item.centerX = self.parent.machineSize.x + self.parent.extruderOffset[item.extruder].x - item.getMaximum().x * item.scale - if item.centerY > self.parent.machineSize.y + self.parent.extruderOffset[item.extruder].y - item.getMaximum().y * item.scale: - item.centerY = self.parent.machineSize.y + self.parent.extruderOffset[item.extruder].y - item.getMaximum().y * item.scale + item.clampXY() self.Refresh() else: self.allowDrag = False diff --git a/Cura/gui/toolbarUtil.py b/Cura/gui/toolbarUtil.py index 5914a308..a609aa6e 100644 --- a/Cura/gui/toolbarUtil.py +++ b/Cura/gui/toolbarUtil.py @@ -1,6 +1,6 @@ from __future__ import division -import os +import os, sys import wx from wx.lib import buttons From 7f576692809f229f204006ef79dfd6dfd4cc55f0 Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 7 May 2012 17:42:46 +0200 Subject: [PATCH 09/10] Move extruder switching GCode to profile instead of hardcoded. --- Cura/gui/alterationPanel.py | 2 ++ Cura/gui/sliceProgessPanel.py | 9 ++++----- Cura/util/profile.py | 7 +++++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Cura/gui/alterationPanel.py b/Cura/gui/alterationPanel.py index 5f5098d6..144f3d94 100644 --- a/Cura/gui/alterationPanel.py +++ b/Cura/gui/alterationPanel.py @@ -9,6 +9,8 @@ class alterationPanel(wx.Panel): wx.Panel.__init__(self, parent,-1) self.alterationFileList = ['start.gcode', 'end.gcode', 'support_start.gcode', 'support_end.gcode', 'nextobject.gcode', 'replace.csv'] + if int(profile.getPreference('extruder_amount')) > 1: + self.alterationFileList.append('switchExtruder.gcode') self.currentFile = None #self.textArea = wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_DONTWRAP|wx.TE_PROCESS_TAB) diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index 9e49e5b3..d2240a56 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -190,11 +190,10 @@ class WorkerThread(threading.Thread): resultFile.write(';LAYER:%d\n' % (layerNr)) resultFile.write(';EXTRUDER:%d\n' % (nextExtruder)) if nextExtruder != currentExtruder: - resultFile.write("G1 E-5 F5000\n") - resultFile.write("G92 E0\n") - resultFile.write("T%d\n" % (nextExtruder)) - resultFile.write("G1 E5 F5000\n") - resultFile.write("G92 E0\n") + resultFile.write(';TYPE:CUSTOM\n') + profile.setTempOverride('extruder', nextExtruder) + resultFile.write(profile.getAlterationFileContents('switchExtruder.gcode')) + profile.resetTempOverride() currentExtruder = nextExtruder layerHasLine = True resultFile.write(line) diff --git a/Cura/util/profile.py b/Cura/util/profile.py index 5e6f67ef..22d30fb0 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -122,6 +122,13 @@ G92 E0 G1 Z0 F{max_z_speed} """, ####################################################################################### + 'switchExtruder.gcode': """;Switch between the current extruder and the next extruder, when printing with multiple extruders. +G1 E-5 F5000 +G92 E0 +T{extruder} +G1 E5 F5000 +G92 E0 +""", } preferencesDefaultSettings = { 'wizardDone': 'False', From 666bbbb6b048f23bd30cd8d95267bd970a2fc4b4 Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 7 May 2012 18:12:26 +0200 Subject: [PATCH 10/10] What was I smoking? This code is much simpler this way. --- Cura/cura_sf/fabmetheus_utilities/settings.py | 2 +- Cura/gui/preview3d.py | 31 +++++++------------ 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/Cura/cura_sf/fabmetheus_utilities/settings.py b/Cura/cura_sf/fabmetheus_utilities/settings.py index fa79a29c..f5d76296 100644 --- a/Cura/cura_sf/fabmetheus_utilities/settings.py +++ b/Cura/cura_sf/fabmetheus_utilities/settings.py @@ -138,7 +138,7 @@ def getProfileInformation(): 'Widen_Width_over_Edge_Width_ratio': DEFSET, },'inset': { 'Add_Custom_Code_for_Temperature_Reading': "False", - 'Infill_in_Direction_of_Bridge': "True", + 'Infill_in_Direction_of_Bridge': ifSettingAboveZero('fill_density'), 'Infill_Width': storedSettingFloat("nozzle_size"), 'Loop_Order_Choice': DEFSET, 'Overlap_Removal_Width_over_Perimeter_Width_ratio': DEFSET, diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index 190cbb09..372ec4e3 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -447,39 +447,30 @@ class PreviewGLCanvas(glcanvas.GLCanvas): self.gcodeDisplayList = glGenLists(len(self.parent.gcode.layerList)); self.gcodeDisplayListCount = len(self.parent.gcode.layerList) self.parent.gcodeDirty = False - self.gcodeDisplayListMade = [] - for idx in xrange(0, len(self.parent.gcode.layerList)): - self.gcodeDisplayListMade.append(False) + self.gcodeDisplayListMade = 0 - if self.gcodeDisplayListMade != None: - curLayerNum = 0 - for layer in self.parent.gcode.layerList: - if not self.gcodeDisplayListMade[curLayerNum]: - glNewList(self.gcodeDisplayList + curLayerNum, GL_COMPILE) - opengl.DrawGCodeLayer(layer) - glEndList() - self.gcodeDisplayListMade[curLayerNum] = True - self.Refresh() - break - curLayerNum += 1 - if curLayerNum == len(self.parent.gcode.layerList): - self.gcodeDisplayListMade = None + if self.parent.gcode != None and self.gcodeDisplayListMade < len(self.parent.gcode.layerList): + glNewList(self.gcodeDisplayList + self.gcodeDisplayListMade, GL_COMPILE) + opengl.DrawGCodeLayer(self.parent.gcode.layerList[self.gcodeDisplayListMade]) + glEndList() + self.gcodeDisplayListMade += 1 + self.Refresh() if self.parent.gcode != None and (self.viewMode == "GCode" or self.viewMode == "Mixed"): glEnable(GL_COLOR_MATERIAL) glEnable(GL_LIGHTING) - for i in xrange(0, self.parent.layerSpin.GetValue() + 1): + drawUpToLayer = min(self.gcodeDisplayListMade, self.parent.layerSpin.GetValue() + 1) + for i in xrange(0, drawUpToLayer): c = 1.0 if i < self.parent.layerSpin.GetValue(): - c = 0.9 - (self.parent.layerSpin.GetValue() - i) * 0.1 + c = 0.9 - (drawUpToLayer - i) * 0.1 if c < 0.4: c = (0.4 + c) / 2 if c < 0.1: c = 0.1 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0,0,0,0]) glLightfv(GL_LIGHT0, GL_AMBIENT, [c,c,c,c]) - if self.gcodeDisplayListMade == None or self.gcodeDisplayListMade[i]: - glCallList(self.gcodeDisplayList + i) + glCallList(self.gcodeDisplayList + i) glDisable(GL_LIGHTING) glDisable(GL_COLOR_MATERIAL) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, [0.2, 0.2, 0.2, 1.0]);