'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,
wx.Panel.__init__(self, parent,-1)\r
\r
self.alterationFileList = ['start.gcode', 'end.gcode', 'support_start.gcode', 'support_end.gcode', 'nextobject.gcode', 'replace.csv']\r
+ if int(profile.getPreference('extruder_amount')) > 1:\r
+ self.alterationFileList.append('switchExtruder.gcode')\r
self.currentFile = None\r
\r
#self.textArea = wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_DONTWRAP|wx.TE_PROCESS_TAB)\r
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:
wx.CallAfter(self.AddProgressText, "Error: Missing start message.")\r
self.comm.close()\r
return\r
- \r
+ \r
+ #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.\r
+ time.sleep(3)\r
+ \r
wx.CallAfter(self.AddProgressText, "Disabling step motors...")\r
if self.DoCommCommandWithTimeout('M84') == False:\r
wx.CallAfter(self.AddProgressText, "Error: Missing reply to Deactivate steppers (M84).")\r
- wx.CallAfter(self.AddProgressText, "Possible cause: Temperature MIN/MAX.\nCheck temperature sensor connections.")\r
self.comm.close()\r
return\r
\r
if line == '':\r
self.comm.close()\r
return False\r
+ print line\r
if line.startswith(replyStart):\r
break\r
t.cancel()\r
return\r
if line.startswith('start'):\r
break\r
+ #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.\r
+ time.sleep(3)\r
+ \r
self.sendGCommand('M302') #Disable cold extrusion protection\r
self.sendGCommand("M92 E%f" % (currentEValue));\r
self.sendGCommand("G92 E0");\r
return\r
if line.startswith('start'):\r
break\r
+ #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.\r
+ time.sleep(3)\r
+ \r
self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.\r
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)\r
self.sendGCommand('M104 S0')\r
from util import profile
-class GcodeTextArea(wx.stc.StyledTextCtrl):
- def __init__(self, parent):
- super(GcodeTextArea, self).__init__(parent)
+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)
+
+ self.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
+
+else:
+ 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)
+ 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)
+ 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]
+ #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
+ 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
+ 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)
+ def checkGCodePart(self, part, pos):
+ if len(part) < 2:
+ self.StartStyling(pos, 0x40)
+ self.SetStyling(1, 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)
+ if not part[0] in "GMXYZFESTBPIDCJ":
+ self.StartStyling(pos, 0x40)
+ self.SetStyling(1, 0x40)
return True
- if part[0] == 'G':
- if not code in self.supportedGCodes:
+ if part[1] == '{':
+ if part[-1] != '}':
return True
- if part[0] == 'M':
- if not code in self.supportedMCodes:
+ 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
- else:
- try:
- float(part[1:])
- except (ValueError):
- self.StartStyling(pos + 1, 0x40)
- self.SetStyling(len(part) - 1, 0x40)
- return True
- return False
+ 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 GetValue(self):
+ return self.GetText()
- def SetValue(self, s):
- self.SetText(s)
+ def SetValue(self, s):
+ self.SetText(s)
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)
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()
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()
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()
+import math\r
+\r
+from util import util3d\r
+from util import profile\r
\r
try:\r
import OpenGL\r
glVertex3f(v3.x, v3.y, v3.z)\r
glVertex3f(v2.x, v2.y, v2.z)\r
glEnd()\r
+\r
+def DrawGCodeLayer(layer):\r
+ filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2\r
+ filamentArea = math.pi * filamentRadius * filamentRadius\r
+ lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10\r
+ \r
+ fillCycle = 0\r
+ fillColorCycle = [[0.5,0.5,0.0],[0.0,0.5,0.5],[0.5,0.0,0.5]]\r
+ \r
+ glDisable(GL_CULL_FACE)\r
+ for path in layer:\r
+ if path.type == 'move':\r
+ glColor3f(0,0,1)\r
+ if path.type == 'extrude':\r
+ if path.pathType == 'FILL':\r
+ glColor3fv(fillColorCycle[fillCycle])\r
+ fillCycle = (fillCycle + 1) % len(fillColorCycle)\r
+ elif path.pathType == 'WALL-INNER':\r
+ glColor3fv([0,1,0])\r
+ elif path.pathType == 'SUPPORT':\r
+ glColor3fv([0,1,1])\r
+ elif path.pathType == 'SKIRT':\r
+ glColor3fv([0,0.5,0.5])\r
+ else:\r
+ glColor3fv([1,0,0])\r
+ if path.type == 'retract':\r
+ glColor3fv([0,1,1])\r
+ if path.type == 'extrude':\r
+ drawLength = 0.0\r
+ prevNormal = None\r
+ for i in xrange(0, len(path.list)-1):\r
+ v0 = path.list[i]\r
+ v1 = path.list[i+1]\r
+\r
+ # Calculate line width from ePerDistance (needs layer thickness and filament diameter)\r
+ dist = (v0 - v1).vsize()\r
+ if dist > 0 and path.layerThickness > 0:\r
+ extrusionMMperDist = (v1.e - v0.e) / dist\r
+ lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2\r
+\r
+ drawLength += (v0 - v1).vsize()\r
+ normal = (v0 - v1).cross(util3d.Vector3(0,0,1))\r
+ normal.normalize()\r
+\r
+ vv2 = v0 + normal * lineWidth\r
+ vv3 = v1 + normal * lineWidth\r
+ vv0 = v0 - normal * lineWidth\r
+ vv1 = v1 - normal * lineWidth\r
+\r
+ glBegin(GL_QUADS)\r
+ glVertex3f(vv0.x, vv0.y, vv0.z - 0.01)\r
+ glVertex3f(vv1.x, vv1.y, vv1.z - 0.01)\r
+ glVertex3f(vv3.x, vv3.y, vv3.z - 0.01)\r
+ glVertex3f(vv2.x, vv2.y, vv2.z - 0.01)\r
+ glEnd()\r
+ if prevNormal != None:\r
+ n = (normal + prevNormal)\r
+ n.normalize()\r
+ vv4 = v0 + n * lineWidth\r
+ vv5 = v0 - n * lineWidth\r
+ glBegin(GL_QUADS)\r
+ glVertex3f(vv2.x, vv2.y, vv2.z)\r
+ glVertex3f(vv4.x, vv4.y, vv4.z)\r
+ glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z)\r
+ glVertex3f(v0.x, v0.y, v0.z)\r
+ \r
+ glVertex3f(vv0.x, vv0.y, vv0.z)\r
+ glVertex3f(vv5.x, vv5.y, vv5.z)\r
+ glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z)\r
+ glVertex3f(v0.x, v0.y, v0.z)\r
+ glEnd()\r
+ \r
+ prevNormal = normal\r
+ prevVv1 = vv1\r
+ prevVv3 = vv3\r
+ else:\r
+ glBegin(GL_LINE_STRIP)\r
+ for v in path.list:\r
+ glVertex3f(v.x, v.y, v.z)\r
+ glEnd()\r
+ glEnable(GL_CULL_FACE)\r
self.offsetY = 0\r
self.view3D = True\r
self.gcodeDisplayList = None\r
+ self.gcodeDisplayListMade = None\r
self.gcodeDisplayListCount = 0\r
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]]\r
\r
self.gcodeDisplayList = glGenLists(len(self.parent.gcode.layerList));\r
self.gcodeDisplayListCount = len(self.parent.gcode.layerList)\r
self.parent.gcodeDirty = False\r
- prevLayerZ = 0.0\r
- curLayerZ = 0.0\r
- \r
- layerThickness = 0.0\r
- filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2\r
- filamentArea = math.pi * filamentRadius * filamentRadius\r
- lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10\r
- \r
- curLayerNum = 0\r
- for layer in self.parent.gcode.layerList:\r
- glNewList(self.gcodeDisplayList + curLayerNum, GL_COMPILE)\r
- glDisable(GL_CULL_FACE)\r
- curLayerZ = layer[0].list[1].z\r
- layerThickness = curLayerZ - prevLayerZ\r
- prevLayerZ = layer[-1].list[-1].z\r
- for path in layer:\r
- if path.type == 'move':\r
- glColor3f(0,0,1)\r
- if path.type == 'extrude':\r
- if path.pathType == 'FILL':\r
- glColor3f(0.5,0.5,0)\r
- elif path.pathType == 'WALL-INNER':\r
- glColor3f(0,1,0)\r
- elif path.pathType == 'SUPPORT':\r
- glColor3f(0,1,1)\r
- elif path.pathType == 'SKIRT':\r
- glColor3f(0,0.5,0.5)\r
- else:\r
- glColor3f(1,0,0)\r
- if path.type == 'retract':\r
- glColor3f(0,1,1)\r
- if path.type == 'extrude':\r
- for i in xrange(0, len(path.list)-1):\r
- v0 = path.list[i]\r
- v1 = path.list[i+1]\r
-\r
- # Calculate line width from ePerDistance (needs layer thickness and filament diameter)\r
- dist = (v0 - v1).vsize()\r
- if dist > 0 and layerThickness > 0:\r
- extrusionMMperDist = (v1.e - v0.e) / dist\r
- lineWidth = extrusionMMperDist * filamentArea / layerThickness / 2\r
-\r
- normal = (v0 - v1).cross(util3d.Vector3(0,0,1))\r
- normal.normalize()\r
- v2 = v0 + normal * lineWidth\r
- v3 = v1 + normal * lineWidth\r
- v0 = v0 - normal * lineWidth\r
- v1 = v1 - normal * lineWidth\r
-\r
- glBegin(GL_QUADS)\r
- if path.pathType == 'FILL': #Remove depth buffer fighting on infill/wall overlap\r
- glVertex3f(v0.x, v0.y, v0.z - 0.02)\r
- glVertex3f(v1.x, v1.y, v1.z - 0.02)\r
- glVertex3f(v3.x, v3.y, v3.z - 0.02)\r
- glVertex3f(v2.x, v2.y, v2.z - 0.02)\r
- else:\r
- glVertex3f(v0.x, v0.y, v0.z - 0.01)\r
- glVertex3f(v1.x, v1.y, v1.z - 0.01)\r
- glVertex3f(v3.x, v3.y, v3.z - 0.01)\r
- glVertex3f(v2.x, v2.y, v2.z - 0.01)\r
- glEnd()\r
- \r
- #for v in path['list']:\r
- # glBegin(GL_TRIANGLE_FAN)\r
- # glVertex3f(v.x, v.y, v.z - 0.001)\r
- # for i in xrange(0, 16+1):\r
- # if path['pathType'] == 'FILL': #Remove depth buffer fighting on infill/wall overlap\r
- # 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)\r
- # else:\r
- # 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)\r
- # glEnd()\r
- else:\r
- glBegin(GL_LINE_STRIP)\r
- for v in path.list:\r
- glVertex3f(v.x, v.y, v.z)\r
- glEnd()\r
- curLayerNum += 1\r
- glEnable(GL_CULL_FACE)\r
- glEndList()\r
+ self.gcodeDisplayListMade = 0\r
+ \r
+ if self.parent.gcode != None and self.gcodeDisplayListMade < len(self.parent.gcode.layerList):\r
+ glNewList(self.gcodeDisplayList + self.gcodeDisplayListMade, GL_COMPILE)\r
+ opengl.DrawGCodeLayer(self.parent.gcode.layerList[self.gcodeDisplayListMade])\r
+ glEndList()\r
+ self.gcodeDisplayListMade += 1\r
+ self.Refresh()\r
\r
if self.parent.gcode != None and (self.viewMode == "GCode" or self.viewMode == "Mixed"):\r
glEnable(GL_COLOR_MATERIAL)\r
glEnable(GL_LIGHTING)\r
- for i in xrange(0, self.parent.layerSpin.GetValue() + 1):\r
+ drawUpToLayer = min(self.gcodeDisplayListMade, self.parent.layerSpin.GetValue() + 1)\r
+ for i in xrange(0, drawUpToLayer):\r
c = 1.0\r
if i < self.parent.layerSpin.GetValue():\r
- c = 0.9 - (self.parent.layerSpin.GetValue() - i) * 0.1\r
+ c = 0.9 - (drawUpToLayer - i) * 0.1\r
if c < 0.4:\r
c = (0.4 + c) / 2\r
if c < 0.1:\r
from gui import opengl\r
from gui import toolbarUtil\r
from gui import icon\r
+from gui import configBase\r
+from gui import validators\r
from util import profile\r
from util import util3d\r
from util import stl\r
pass\r
\r
class ProjectObject(stl.stlModel):\r
- def __init__(self, filename):\r
+ def __init__(self, parent, filename):\r
super(ProjectObject, self).__init__()\r
\r
self.load(filename)\r
\r
+ self.parent = parent\r
self.filename = filename\r
self.scale = 1.0\r
self.rotate = 0.0\r
self.modelDirty = True\r
\r
def clone(self):\r
- p = ProjectObject(self.filename)\r
+ p = ProjectObject(self.parent, self.filename)\r
\r
p.centerX = self.centerX + 5\r
p.centerY = self.centerY + 5\r
p.updateModelTransform()\r
\r
return p\r
+ \r
+ def clampXY(self):\r
+ if self.centerX < -self.getMinimum().x * self.scale + self.parent.extruderOffset[self.extruder].x:\r
+ self.centerX = -self.getMinimum().x * self.scale + self.parent.extruderOffset[self.extruder].x\r
+ if self.centerY < -self.getMinimum().y * self.scale + self.parent.extruderOffset[self.extruder].y:\r
+ self.centerY = -self.getMinimum().y * self.scale + self.parent.extruderOffset[self.extruder].y\r
+ if self.centerX > self.parent.machineSize.x + self.parent.extruderOffset[self.extruder].x - self.getMaximum().x * self.scale:\r
+ self.centerX = self.parent.machineSize.x + self.parent.extruderOffset[self.extruder].x - self.getMaximum().x * self.scale\r
+ if self.centerY > self.parent.machineSize.y + self.parent.extruderOffset[self.extruder].y - self.getMaximum().y * self.scale:\r
+ self.centerY = self.parent.machineSize.y + self.parent.extruderOffset[self.extruder].y - self.getMaximum().y * self.scale\r
\r
class projectPlanner(wx.Frame):\r
"Main user interface window"\r
toolbarUtil.RadioButton(self.toolbar, group, 'object-top-on.png', 'object-top-off.png', 'Topdown view', callback=self.OnTopClick).SetValue(True)\r
self.toolbar.AddSeparator()\r
toolbarUtil.NormalButton(self.toolbar, self.OnQuit, 'exit.png', 'Close project planner')\r
+ self.toolbar.AddSeparator()\r
+ toolbarUtil.NormalButton(self.toolbar, self.OnPreferences, 'preferences.png', 'Project planner preferences')\r
\r
self.toolbar.Realize()\r
\r
def OnQuit(self, e):\r
self.Close()\r
\r
+ def OnPreferences(self, e):\r
+ prefDialog = preferencesDialog(self)\r
+ prefDialog.Centre()\r
+ prefDialog.Show(True)\r
+ \r
def OnSaveProject(self, e):\r
dlg=wx.FileDialog(self, "Save project file", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE)\r
dlg.SetWildcard("Project files (*.curaproject)|*.curaproject")\r
while cp.has_section('model_%d' % (i)):\r
section = 'model_%d' % (i)\r
\r
- item = ProjectObject(unicode(cp.get(section, 'filename'), "utf-8"))\r
+ item = ProjectObject(self, unicode(cp.get(section, 'filename'), "utf-8"))\r
item.centerX = float(cp.get(section, 'centerX'))\r
item.centerY = float(cp.get(section, 'centerY'))\r
item.scale = float(cp.get(section, 'scale'))\r
dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL")\r
if dlg.ShowModal() == wx.ID_OK:\r
for filename in dlg.GetPaths():\r
- item = ProjectObject(filename)\r
+ item = ProjectObject(self, filename)\r
profile.putPreference('lastFile', item.filename)\r
self.list.append(item)\r
self.selection = item\r
bestAllowedSize = i\r
bestArea = area\r
self._doAutoPlace(bestAllowedSize)\r
+ for item in self.list:\r
+ item.clampXY()\r
self.preview.Refresh()\r
\r
def _doAutoPlace(self, allowedSizeY):\r
if item != None:\r
item.centerX += float(e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2\r
item.centerY -= float(e.GetY() - self.oldY) * self.zoom / self.GetSize().GetHeight() * 2\r
- if item.centerX < -item.getMinimum().x * item.scale + self.parent.extruderOffset[item.extruder].x:\r
- item.centerX = -item.getMinimum().x * item.scale + self.parent.extruderOffset[item.extruder].x\r
- if item.centerY < -item.getMinimum().y * item.scale + self.parent.extruderOffset[item.extruder].y:\r
- item.centerY = -item.getMinimum().y * item.scale + self.parent.extruderOffset[item.extruder].y\r
- if item.centerX > self.parent.machineSize.x + self.parent.extruderOffset[item.extruder].x - item.getMaximum().x * item.scale:\r
- item.centerX = self.parent.machineSize.x + self.parent.extruderOffset[item.extruder].x - item.getMaximum().x * item.scale\r
- if item.centerY > self.parent.machineSize.y + self.parent.extruderOffset[item.extruder].y - item.getMaximum().y * item.scale:\r
- item.centerY = self.parent.machineSize.y + self.parent.extruderOffset[item.extruder].y - item.getMaximum().y * item.scale\r
+ item.clampXY()\r
self.Refresh()\r
else:\r
self.allowDrag = False\r
\r
wx.CallAfter(self.abortButton.SetLabel, 'Close')\r
\r
+class preferencesDialog(configBase.configWindowBase):\r
+ def __init__(self, parent):\r
+ super(preferencesDialog, self).__init__(title="Project Planner Preferences")\r
+ \r
+ self.parent = parent\r
+ wx.EVT_CLOSE(self, self.OnClose)\r
+ \r
+ extruderAmount = int(profile.getPreference('extruder_amount'))\r
+ \r
+ left, right, main = self.CreateConfigPanel(self)\r
+ configBase.TitleRow(left, 'Machine head size')\r
+ 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')\r
+ validators.validFloat(c, 0.1)\r
+ 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')\r
+ validators.validFloat(c, 0.1)\r
+ 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')\r
+ validators.validFloat(c, 0.1)\r
+ 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')\r
+ validators.validFloat(c, 0.1)\r
+ \r
+ self.okButton = wx.Button(left, -1, 'Ok')\r
+ left.GetSizer().Add(self.okButton, (left.GetSizer().GetRows(), 1))\r
+ self.okButton.Bind(wx.EVT_BUTTON, self.OnClose)\r
+ \r
+ self.MakeModal(True)\r
+ main.Fit()\r
+ self.Fit()\r
+\r
+ def OnClose(self, e):\r
+ self.parent.headSizeMin = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0)\r
+ self.parent.headSizeMax = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0)\r
+\r
+ self.MakeModal(False)\r
+ self.Destroy()\r
+\r
def main():\r
app = wx.App(False)\r
projectPlanner().Show(True)\r
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
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()
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()
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
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();
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
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)
from __future__ import division
-import os
+import os, sys
import wx
from wx.lib import buttons
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 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):
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:
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(';')]
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:
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
G1 Z0 F{max_z_speed}\r
""",\r
#######################################################################################\r
+ 'switchExtruder.gcode': """;Switch between the current extruder and the next extruder, when printing with multiple extruders.\r
+G1 E-5 F5000\r
+G92 E0\r
+T{extruder}\r
+G1 E5 F5000\r
+G92 E0\r
+""",\r
}\r
preferencesDefaultSettings = {\r
'wizardDone': 'False',\r