def loadModelFiles(self, filelist, showWarning = False): while len(filelist) > len(self.objectList): self.objectList.append(previewObject()) for idx in xrange(len(filelist), len(self.objectList)): self.objectList[idx].mesh = None self.objectList[idx].filename = None for idx in xrange(0, len(filelist)): obj = self.objectList[idx] if obj.filename != filelist[idx]: obj.fileTime = None self.gcodeFileTime = None self.logFileTime = None obj.filename = filelist[idx] self.gcodeFilename = sliceRun.getExportFilename(filelist[0]) #Do the STL file loading in a background thread so we don't block the UI. if self.loadThread != None and self.loadThread.isAlive(): self.loadThread.join() self.loadThread = threading.Thread(target=self.doFileLoadThread) self.loadThread.daemon = True self.loadThread.start() if showWarning: if profile.getProfileSettingFloat('model_scale') != 1.0 or profile.getProfileSettingFloat('model_rotate_base') != 0 or profile.getProfileSetting('flip_x') != 'False' or profile.getProfileSetting('flip_y') != 'False' or profile.getProfileSetting('flip_z') != 'False' or profile.getProfileSetting('swap_xz') != 'False' or profile.getProfileSetting('swap_yz') != 'False': self.warningPopup.Show(True) self.warningPopup.timer.Start(5000)
def calcLayerSkip(setting): bottomThickness = profile.getProfileSettingFloat('bottom_thickness') layerThickness = profile.getProfileSettingFloat('layer_height') if bottomThickness < layerThickness: return 0 return int( math.ceil((bottomThickness - layerThickness) / layerThickness + 0.0001) - 1)
def _doAutoPlace(self, allowedSizeY): extraSizeMin = self.headSizeMin extraSizeMax = self.headSizeMax if profile.getProfileSettingFloat('skirt_line_count') > 0: skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap') extraSizeMin = extraSizeMin + util3d.Vector3(skirtSize, skirtSize, 0) extraSizeMax = extraSizeMax + util3d.Vector3(skirtSize, skirtSize, 0) if profile.getProfileSetting('support') != 'None': extraSizeMin = extraSizeMin + util3d.Vector3(3.0, 0, 0) extraSizeMax = extraSizeMax + util3d.Vector3(3.0, 0, 0) if self.printMode == 1: extraSizeMin = util3d.Vector3(6.0, 6.0, 0) extraSizeMax = util3d.Vector3(6.0, 6.0, 0) if extraSizeMin.x > extraSizeMax.x: posX = self.machineSize.x dirX = -1 else: posX = 0 dirX = 1 posY = 0 dirY = 1 minX = self.machineSize.x minY = self.machineSize.y maxX = 0 maxY = 0 for item in self.list: item.centerX = posX + item.getMaximum().x * item.scale * dirX item.centerY = posY + item.getMaximum().y * item.scale * dirY if item.centerY + item.getSize().y >= allowedSizeY: if dirX < 0: posX = minX - extraSizeMax.x - 1 else: posX = maxX + extraSizeMin.x + 1 posY = 0 item.centerX = posX + item.getMaximum().x * item.scale * dirX item.centerY = posY + item.getMaximum().y * item.scale * dirY posY += item.getSize().y * item.scale * dirY + extraSizeMin.y + 1 minX = min(minX, item.centerX - item.getSize().x * item.scale / 2) minY = min(minY, item.centerY - item.getSize().y * item.scale / 2) maxX = max(maxX, item.centerX + item.getSize().x * item.scale / 2) maxY = max(maxY, item.centerY + item.getSize().y * item.scale / 2) for item in self.list: if dirX < 0: item.centerX -= minX / 2 else: item.centerX += (self.machineSize.x - maxX) / 2 item.centerY += (self.machineSize.y - maxY) / 2 if minX < 0 or maxX > self.machineSize.x: return ((maxX - minX) + (maxY - minY)) * 100 return (maxX - minX) + (maxY - minY)
def __init__(self, mainWindow, parent, filelist): wx.Panel.__init__(self, parent, -1) self.mainWindow = mainWindow self.filelist = filelist self.abort = False box = wx.StaticBox(self, -1, filelist[0]) self.sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(self.sizer, 0, flag=wx.EXPAND) self.statusText = wx.StaticText(self, -1, "Starting...") self.progressGauge = wx.Gauge(self, -1) self.progressGauge.SetRange(10000 * len(filelist)) self.abortButton = wx.Button(self, -1, "X", style=wx.BU_EXACTFIT) self.sizer.Add(self.statusText, 2, flag=wx.ALIGN_CENTER) self.sizer.Add(self.progressGauge, 2) self.sizer.Add(self.abortButton, 0) self.Bind(wx.EVT_BUTTON, self.OnAbort, self.abortButton) self.SetSizer(mainSizer) self.prevStep = 'start' self.totalDoneFactor = 0.0 self.startTime = time.time() if profile.getPreference('save_profile') == 'True': profile.saveGlobalProfile( self.filelist[0][:self.filelist[0].rfind('.')] + "_profile.ini") cmdList = [] for filename in self.filelist: idx = self.filelist.index(filename) #print filename, idx if idx > 0: profile.setTempOverride('fan_enabled', 'False') profile.setTempOverride('skirt_line_count', '0') profile.setTempOverride( 'machine_center_x', profile.getProfileSettingFloat('machine_center_x') - profile.getPreferenceFloat('extruder_offset_x%d' % (idx))) profile.setTempOverride( 'machine_center_y', profile.getProfileSettingFloat('machine_center_y') - profile.getPreferenceFloat('extruder_offset_y%d' % (idx))) profile.setTempOverride('alternative_center', self.filelist[0]) if len(self.filelist) > 1: profile.setTempOverride('add_start_end_gcode', 'False') profile.setTempOverride('gcode_extension', 'multi_extrude_tmp') cmdList.append(sliceRun.getSliceCommand(filename)) profile.resetTempOverride() self.thread = WorkerThread(self, filelist, cmdList)
def OnOpenSVG(self, e): dlg = wx.FileDialog(self, "Open SVG file", os.path.split( profile.getPreference('lastFile'))[0], style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) dlg.SetWildcard("SVG files (*.svg)|*.svg;*.SVG") if dlg.ShowModal() == wx.ID_OK: self.filename = dlg.GetPath() self.svg = svg.SVG(self.filename) self.svg.center( complex(profile.getProfileSettingFloat('machine_center_x'), profile.getProfileSettingFloat('machine_center_y'))) self.preview.Refresh() dlg.Destroy()
def OnPaint(self,e): dc = wx.PaintDC(self) if not hasOpenGLlibs: dc.Clear() dc.DrawText("No PyOpenGL installation found.\nNo preview window available.", 10, 10) return self.SetCurrent(self.context) opengl.InitGL(self, self.view3D, self.zoom) if self.view3D: glTranslate(0,0,-self.zoom) glRotate(-self.pitch, 1,0,0) glRotate(self.yaw, 0,0,1) if self.viewMode == "GCode" or self.viewMode == "Mixed": if self.parent.gcode != None and len(self.parent.gcode.layerList) > self.parent.layerSpin.GetValue() and len(self.parent.gcode.layerList[self.parent.layerSpin.GetValue()]) > 0: glTranslate(0,0,-self.parent.gcode.layerList[self.parent.layerSpin.GetValue()][0].list[-1].z) else: if self.parent.objectsMaxV != None: glTranslate(0,0,-(self.parent.objectsMaxV[2]-self.parent.objectsMinV[2]) * profile.getProfileSettingFloat('model_scale') / 2) else: glScale(1.0/self.zoom, 1.0/self.zoom, 1.0) glTranslate(self.offsetX, self.offsetY, 0.0) self.viewport = glGetIntegerv(GL_VIEWPORT); self.modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX); self.projMatrix = glGetDoublev(GL_PROJECTION_MATRIX); glTranslate(-self.parent.machineCenter.x, -self.parent.machineCenter.y, 0) self.OnDraw() self.SwapBuffers()
def StoreData(self): profile.putPreference('machine_width', self.machineWidth.GetValue()) profile.putPreference('machine_depth', self.machineDepth.GetValue()) profile.putPreference('machine_height', self.machineHeight.GetValue()) profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue()) profile.putProfileSetting('machine_center_x', profile.getPreferenceFloat('machine_width') / 2) profile.putProfileSetting('machine_center_y', profile.getPreferenceFloat('machine_depth') / 2) profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2) profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
def OnMouseMotion(self,e): if self.parent.objectsMaxV != None: size = (self.parent.objectsMaxV - self.parent.objectsMinV) sizeXY = math.sqrt((size[0] * size[0]) + (size[1] * size[1])) p0 = numpy.array(gluUnProject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 0, self.modelMatrix, self.projMatrix, self.viewport)) p1 = numpy.array(gluUnProject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 1, self.modelMatrix, self.projMatrix, self.viewport)) cursorZ0 = p0 - (p1 - p0) * (p0[2] / (p1[2] - p0[2])) cursorXY = math.sqrt((cursorZ0[0] * cursorZ0[0]) + (cursorZ0[1] * cursorZ0[1])) if cursorXY >= sizeXY * 0.7 and cursorXY <= sizeXY * 0.7 + 3: self.SetCursor(wx.StockCursor(wx.CURSOR_SIZING)) else: self.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) if e.Dragging() and e.LeftIsDown(): if self.dragType == '': #Define the drag type depending on the cursor position. if cursorXY >= sizeXY * 0.7 and cursorXY <= sizeXY * 0.7 + 3: self.dragType = 'modelRotate' self.dragStart = math.atan2(cursorZ0[0], cursorZ0[1]) else: self.dragType = 'viewRotate' if self.dragType == 'viewRotate': if self.view3D: self.yaw += e.GetX() - self.oldX self.pitch -= e.GetY() - self.oldY if self.pitch > 170: self.pitch = 170 if self.pitch < 10: self.pitch = 10 else: self.offsetX += float(e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2 self.offsetY -= float(e.GetY() - self.oldY) * self.zoom / self.GetSize().GetHeight() * 2 elif self.dragType == 'modelRotate': angle = math.atan2(cursorZ0[0], cursorZ0[1]) diff = self.dragStart - angle self.tempRotate = diff * 180 / math.pi #Workaround for buggy ATI cards. size = self.GetSizeTuple() self.SetSize((size[0]+1, size[1])) self.SetSize((size[0], size[1])) self.Refresh() else: if self.tempRotate != 0: profile.putProfileSetting('model_rotate_base', profile.getProfileSettingFloat('model_rotate_base') + self.tempRotate) self.parent.updateModelTransform() self.tempRotate = 0 self.dragType = '' if e.Dragging() and e.RightIsDown(): self.zoom += e.GetY() - self.oldY if self.zoom < 1: self.zoom = 1 self.Refresh() self.oldX = e.GetX() self.oldY = e.GetY()
def updateProfileToControls(self): self.scale.SetValue(profile.getProfileSetting('model_scale')) self.rotate.SetValue(profile.getProfileSettingFloat('model_rotate_base')) self.mirrorX.SetValue(profile.getProfileSetting('flip_x') == 'True') self.mirrorY.SetValue(profile.getProfileSetting('flip_y') == 'True') self.mirrorZ.SetValue(profile.getProfileSetting('flip_z') == 'True') self.swapXZ.SetValue(profile.getProfileSetting('swap_xz') == 'True') self.swapYZ.SetValue(profile.getProfileSetting('swap_yz') == 'True') self.updateModelTransform()
def validate(self): try: nozzleSize = profile.getProfileSettingFloat('nozzle_size') layerHeight = profile.getProfileSettingFloat('layer_height') printSpeed = profile.getProfileSettingFloat('print_speed') printVolumePerMM = layerHeight * nozzleSize printVolumePerSecond = printVolumePerMM * printSpeed #Using 10mm3 per second with a 0.4mm nozzle (normal max according to Joergen Geerds) maxPrintVolumePerSecond = 10 / (math.pi*(0.2*0.2)) * (math.pi*(nozzleSize/2*nozzleSize/2)) if printVolumePerSecond > maxPrintVolumePerSecond: return WARNING, 'You are trying to print more then %.1fmm^3 of filament per second. This might cause filament slipping. (You are printing at %0.1fmm^3 per second)' % (maxPrintVolumePerSecond, printVolumePerSecond) return SUCCESS, '' except ValueError: #We already have an error by the int/float validator in this case. return SUCCESS, ''
def __init__(self, mainWindow, parent, filelist): wx.Panel.__init__(self, parent, -1) self.mainWindow = mainWindow self.filelist = filelist self.abort = False box = wx.StaticBox(self, -1, filelist[0]) self.sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(self.sizer, 0, flag=wx.EXPAND) self.statusText = wx.StaticText(self, -1, "Starting...") self.progressGauge = wx.Gauge(self, -1) self.progressGauge.SetRange(10000 * len(filelist)) self.abortButton = wx.Button(self, -1, "X", style=wx.BU_EXACTFIT) self.sizer.Add(self.statusText, 2, flag=wx.ALIGN_CENTER ) self.sizer.Add(self.progressGauge, 2) self.sizer.Add(self.abortButton, 0) self.Bind(wx.EVT_BUTTON, self.OnAbort, self.abortButton) self.SetSizer(mainSizer) self.prevStep = 'start' self.totalDoneFactor = 0.0 self.startTime = time.time() if profile.getPreference('save_profile') == 'True': profile.saveGlobalProfile(self.filelist[0][: self.filelist[0].rfind('.')] + "_profile.ini") cmdList = [] for filename in self.filelist: idx = self.filelist.index(filename) #print filename, idx if idx > 0: profile.setTempOverride('fan_enabled', 'False') profile.setTempOverride('skirt_line_count', '0') profile.setTempOverride('machine_center_x', profile.getProfileSettingFloat('machine_center_x') - profile.getPreferenceFloat('extruder_offset_x%d' % (idx))) profile.setTempOverride('machine_center_y', profile.getProfileSettingFloat('machine_center_y') - profile.getPreferenceFloat('extruder_offset_y%d' % (idx))) profile.setTempOverride('alternative_center', self.filelist[0]) if len(self.filelist) > 1: profile.setTempOverride('add_start_end_gcode', 'False') profile.setTempOverride('gcode_extension', 'multi_extrude_tmp') cmdList.append(sliceRun.getSliceCommand(filename)) profile.resetTempOverride() self.thread = WorkerThread(self, filelist, cmdList)
def OnOpenSVG(self, e): dlg = wx.FileDialog( self, "Open SVG file", os.path.split(profile.getPreference("lastFile"))[0], style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST, ) dlg.SetWildcard("SVG files (*.svg)|*.svg;*.SVG") if dlg.ShowModal() == wx.ID_OK: self.filename = dlg.GetPath() self.svg = svg.SVG(self.filename) self.svg.center( complex( profile.getProfileSettingFloat("machine_center_x"), profile.getProfileSettingFloat("machine_center_y"), ) ) self.preview.Refresh() dlg.Destroy()
def updateProfileToControls(self): self.scale.SetValue(profile.getProfileSetting('model_scale')) self.rotate.SetValue( profile.getProfileSettingFloat('model_rotate_base')) self.mirrorX.SetValue(profile.getProfileSetting('flip_x') == 'True') self.mirrorY.SetValue(profile.getProfileSetting('flip_y') == 'True') self.mirrorZ.SetValue(profile.getProfileSetting('flip_z') == 'True') self.swapXZ.SetValue(profile.getProfileSetting('swap_xz') == 'True') self.swapYZ.SetValue(profile.getProfileSetting('swap_yz') == 'True') self.updateModelTransform() self.glCanvas.updateProfileToControls()
def validate(self): try: wallThickness = profile.getProfileSettingFloat('wall_thickness') nozzleSize = profile.getProfileSettingFloat('nozzle_size') if wallThickness <= nozzleSize * 0.5: return ERROR, 'Trying to print walls thinner then the half of your nozzle size, this will not produce anything usable' if wallThickness <= nozzleSize * 0.85: return WARNING, 'Trying to print walls thinner then the 0.8 * nozzle size. Small chance that this will produce usable results' if wallThickness < nozzleSize: return SUCCESS, '' lineCount = int(wallThickness / nozzleSize) lineWidth = wallThickness / lineCount lineWidthAlt = wallThickness / (lineCount + 1) if lineWidth >= nozzleSize * 1.5 and lineWidthAlt <= nozzleSize * 0.85: return WARNING, 'Current selected wall thickness results in a line thickness of ' + str(lineWidthAlt) + 'mm which is not recommended with your nozzle of ' + str(nozzleSize) + 'mm' return SUCCESS, '' except ValueError: #We already have an error by the int/float validator in this case. return SUCCESS, ''
def getExtraHeadSize(self): extraSizeMin = self.headSizeMin extraSizeMax = self.headSizeMax if profile.getProfileSettingFloat('skirt_line_count') > 0: skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap') extraSizeMin = extraSizeMin + numpy.array([skirtSize, skirtSize, 0]) extraSizeMax = extraSizeMax + numpy.array([skirtSize, skirtSize, 0]) if profile.getProfileSetting('enable_raft') != 'False': raftSize = profile.getProfileSettingFloat('raft_margin') * 2 extraSizeMin = extraSizeMin + numpy.array([raftSize, raftSize, 0]) extraSizeMax = extraSizeMax + numpy.array([raftSize, raftSize, 0]) if profile.getProfileSetting('support') != 'None': extraSizeMin = extraSizeMin + numpy.array([3.0, 0, 0]) extraSizeMax = extraSizeMax + numpy.array([3.0, 0, 0]) if self.printMode == 1: extraSizeMin = numpy.array([6.0, 6.0, 0]) extraSizeMax = numpy.array([6.0, 6.0, 0]) return extraSizeMin, extraSizeMax
def doFileLoadThread(self): for obj in self.objectList: if obj.filename != None and os.path.isfile( obj.filename) and obj.fileTime != os.stat( obj.filename).st_mtime: obj.ileTime = os.stat(obj.filename).st_mtime mesh = meshLoader.loadMesh(obj.filename) obj.dirty = False obj.mesh = mesh self.updateModelTransform() scale = profile.getProfileSettingFloat('model_scale') size = (self.objectsMaxV - self.objectsMinV) * scale if size[0] > self.machineSize.x or size[ 1] > self.machineSize.y or size[2] > self.machineSize.z: self.OnScaleMax(None) self.glCanvas.zoom = numpy.max(size) * 2.5 self.errorList = [] wx.CallAfter(self.updateToolbar) wx.CallAfter(self.glCanvas.Refresh) if os.path.isfile( self.gcodeFilename) and self.gcodeFileTime != os.stat( self.gcodeFilename).st_mtime: self.gcodeFileTime = os.stat(self.gcodeFilename).st_mtime gcode = gcodeInterpreter.gcode() gcode.progressCallback = self.loadProgress gcode.load(self.gcodeFilename) self.gcodeDirty = False self.gcode = gcode self.gcodeDirty = True errorList = [] for line in open(self.gcodeFilename, "rt"): res = re.search( ';Model error\(([a-z ]*)\): \(([0-9\.\-e]*), ([0-9\.\-e]*), ([0-9\.\-e]*)\) \(([0-9\.\-e]*), ([0-9\.\-e]*), ([0-9\.\-e]*)\)', line) if res != None: v1 = util3d.Vector3(float(res.group(2)), float(res.group(3)), float(res.group(4))) v2 = util3d.Vector3(float(res.group(5)), float(res.group(6)), float(res.group(7))) errorList.append([v1, v2]) self.errorList = errorList wx.CallAfter(self.updateToolbar) wx.CallAfter(self.glCanvas.Refresh) elif not os.path.isfile(self.gcodeFilename): self.gcode = None
def StoreData(self): profile.putPreference('machine_width', self.machineWidth.GetValue()) profile.putPreference('machine_depth', self.machineDepth.GetValue()) profile.putPreference('machine_height', self.machineHeight.GetValue()) profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue()) profile.putProfileSetting( 'machine_center_x', profile.getPreferenceFloat('machine_width') / 2) profile.putProfileSetting( 'machine_center_y', profile.getPreferenceFloat('machine_depth') / 2) profile.putProfileSetting( 'wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2) profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
def drawModel(self, obj): multiX = 1 #int(profile.getProfileSetting('model_multiply_x')) multiY = 1 #int(profile.getProfileSetting('model_multiply_y')) modelScale = profile.getProfileSettingFloat('model_scale') modelSize = (obj.mesh.getMaximum() - obj.mesh.getMinimum()) * modelScale glPushMatrix() glTranslate(-(modelSize.x+10)*(multiX-1)/2,-(modelSize.y+10)*(multiY-1)/2, 0) for mx in xrange(0, multiX): for my in xrange(0, multiY): glPushMatrix() glTranslate((modelSize.x+10)*mx,(modelSize.y+10)*my, 0) glScalef(modelScale, modelScale, modelScale) glCallList(obj.displayList) glPopMatrix() glPopMatrix()
def loadModelFiles(self, filelist, showWarning=False): while len(filelist) > len(self.objectList): self.objectList.append(previewObject()) for idx in xrange(len(filelist), len(self.objectList)): self.objectList[idx].mesh = None self.objectList[idx].filename = None for idx in xrange(0, len(filelist)): obj = self.objectList[idx] if obj.filename != filelist[idx]: obj.fileTime = None self.gcodeFileTime = None self.logFileTime = None obj.filename = filelist[idx] self.gcodeFilename = sliceRun.getExportFilename(filelist[0]) #Do the STL file loading in a background thread so we don't block the UI. if self.loadThread != None and self.loadThread.isAlive(): self.loadThread.join() self.loadThread = threading.Thread(target=self.doFileLoadThread) self.loadThread.daemon = True self.loadThread.start() if showWarning: if profile.getProfileSettingFloat( 'model_scale') != 1.0 or profile.getProfileSettingFloat( 'model_rotate_base') != 0 or profile.getProfileSetting( 'flip_x') != 'False' or profile.getProfileSetting( 'flip_y' ) != 'False' or profile.getProfileSetting( 'flip_z' ) != 'False' or profile.getProfileSetting( 'swap_xz' ) != 'False' or profile.getProfileSetting( 'swap_yz') != 'False': self.warningPopup.Show(True) self.warningPopup.timer.Start(5000)
def drawModel(self, obj): multiX = 1 #int(profile.getProfileSetting('model_multiply_x')) multiY = 1 #int(profile.getProfileSetting('model_multiply_y')) modelScale = profile.getProfileSettingFloat('model_scale') modelSize = (obj.mesh.getMaximum() - obj.mesh.getMinimum()) * modelScale glPushMatrix() glTranslate(-(modelSize.x + 10) * (multiX - 1) / 2, -(modelSize.y + 10) * (multiY - 1) / 2, 0) for mx in xrange(0, multiX): for my in xrange(0, multiY): glPushMatrix() glTranslate((modelSize.x + 10) * mx, (modelSize.y + 10) * my, 0) glScalef(modelScale, modelScale, modelScale) glCallList(obj.displayList) glPopMatrix() glPopMatrix()
def updateModelTransform(self, f=0): if len(self.objectList) < 1 or self.objectList[0].mesh == None: return rotate = profile.getProfileSettingFloat('model_rotate_base') mirrorX = profile.getProfileSetting('flip_x') == 'True' mirrorY = profile.getProfileSetting('flip_y') == 'True' mirrorZ = profile.getProfileSetting('flip_z') == 'True' swapXZ = profile.getProfileSetting('swap_xz') == 'True' swapYZ = profile.getProfileSetting('swap_yz') == 'True' for obj in self.objectList: if obj.mesh == None: continue obj.mesh.setRotateMirror(rotate, mirrorX, mirrorY, mirrorZ, swapXZ, swapYZ) minV = self.objectList[0].mesh.getMinimum() maxV = self.objectList[0].mesh.getMaximum() for obj in self.objectList: if obj.mesh == None: continue obj.mesh.getMinimumZ() minV = numpy.minimum(minV, obj.mesh.getMinimum()) maxV = numpy.maximum(maxV, obj.mesh.getMaximum()) self.objectsMaxV = maxV self.objectsMinV = minV for obj in self.objectList: if obj.mesh == None: continue obj.mesh.vertexes -= numpy.array([ minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minV[2] ]) #for v in obj.mesh.vertexes: # v[2] -= minV[2] # v[0] -= minV[0] + (maxV[0] - minV[0]) / 2 # v[1] -= minV[1] + (maxV[1] - minV[1]) / 2 obj.mesh.getMinimumZ() obj.dirty = True self.glCanvas.Refresh()
def OnPaint(self, e): dc = wx.PaintDC(self) if not hasOpenGLlibs: dc.Clear() dc.DrawText( "No PyOpenGL installation found.\nNo preview window available.", 10, 10) return self.SetCurrent(self.context) opengl.InitGL(self, self.view3D, self.zoom) if self.view3D: glTranslate(0, 0, -self.zoom) glRotate(-self.pitch, 1, 0, 0) glRotate(self.yaw, 0, 0, 1) if self.viewMode == "GCode" or self.viewMode == "Mixed": if self.parent.gcode != None and len( self.parent.gcode.layerList ) > self.parent.layerSpin.GetValue() and len( self.parent.gcode.layerList[ self.parent.layerSpin.GetValue()]) > 0: glTranslate( 0, 0, -self.parent.gcode.layerList[ self.parent.layerSpin.GetValue()][0].list[-1].z) else: if self.parent.objectsMaxV != None: glTranslate( 0, 0, -(self.parent.objectsMaxV[2] - self.parent.objectsMinV[2]) * profile.getProfileSettingFloat('model_scale') / 2) else: glScale(1.0 / self.zoom, 1.0 / self.zoom, 1.0) glTranslate(self.offsetX, self.offsetY, 0.0) self.viewport = glGetIntegerv(GL_VIEWPORT) self.modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX) self.projMatrix = glGetDoublev(GL_PROJECTION_MATRIX) glTranslate(-self.parent.machineCenter.x, -self.parent.machineCenter.y, 0) self.OnDraw() self.SwapBuffers()
def updateModelTransform(self, f=0): if len(self.objectList) < 1 or self.objectList[0].mesh == None: return rotate = profile.getProfileSettingFloat('model_rotate_base') mirrorX = profile.getProfileSetting('flip_x') == 'True' mirrorY = profile.getProfileSetting('flip_y') == 'True' mirrorZ = profile.getProfileSetting('flip_z') == 'True' swapXZ = profile.getProfileSetting('swap_xz') == 'True' swapYZ = profile.getProfileSetting('swap_yz') == 'True' for obj in self.objectList: if obj.mesh == None: continue obj.mesh.setRotateMirror(rotate, mirrorX, mirrorY, mirrorZ, swapXZ, swapYZ) minV = self.objectList[0].mesh.getMinimum() maxV = self.objectList[0].mesh.getMaximum() for obj in self.objectList: if obj.mesh == None: continue obj.mesh.getMinimumZ() minV = minV.min(obj.mesh.getMinimum()) 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()
def updateModelTransform(self, f=0): if len(self.objectList) < 1 or self.objectList[0].mesh == None: return rotate = profile.getProfileSettingFloat('model_rotate_base') mirrorX = profile.getProfileSetting('flip_x') == 'True' mirrorY = profile.getProfileSetting('flip_y') == 'True' mirrorZ = profile.getProfileSetting('flip_z') == 'True' swapXZ = profile.getProfileSetting('swap_xz') == 'True' swapYZ = profile.getProfileSetting('swap_yz') == 'True' for obj in self.objectList: if obj.mesh == None: continue obj.mesh.setRotateMirror(rotate, mirrorX, mirrorY, mirrorZ, swapXZ, swapYZ) minV = self.objectList[0].mesh.getMinimum() maxV = self.objectList[0].mesh.getMaximum() for obj in self.objectList: if obj.mesh == None: continue obj.mesh.getMinimumZ() minV = numpy.minimum(minV, obj.mesh.getMinimum()) maxV = numpy.maximum(maxV, obj.mesh.getMaximum()) self.objectsMaxV = maxV self.objectsMinV = minV for obj in self.objectList: if obj.mesh == None: continue obj.mesh.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minV[2]]) #for v in obj.mesh.vertexes: # v[2] -= minV[2] # v[0] -= minV[0] + (maxV[0] - minV[0]) / 2 # v[1] -= minV[1] + (maxV[1] - minV[1]) / 2 obj.mesh.getMinimumZ() obj.dirty = True self.glCanvas.Refresh()
def doFileLoadThread(self): for obj in self.objectList: if obj.filename != None and os.path.isfile(obj.filename) and obj.fileTime != os.stat(obj.filename).st_mtime: obj.ileTime = os.stat(obj.filename).st_mtime mesh = meshLoader.loadMesh(obj.filename) obj.dirty = False obj.mesh = mesh self.updateModelTransform() scale = profile.getProfileSettingFloat('model_scale') size = (self.objectsMaxV - self.objectsMinV) * scale if size[0] > self.machineSize.x or size[1] > self.machineSize.y or size[2] > self.machineSize.z: self.OnScaleMax(None) self.glCanvas.zoom = numpy.max(size) * 2.5 self.errorList = [] wx.CallAfter(self.updateToolbar) wx.CallAfter(self.glCanvas.Refresh) if os.path.isfile(self.gcodeFilename) and self.gcodeFileTime != os.stat(self.gcodeFilename).st_mtime: self.gcodeFileTime = os.stat(self.gcodeFilename).st_mtime gcode = gcodeInterpreter.gcode() gcode.progressCallback = self.loadProgress gcode.load(self.gcodeFilename) self.gcodeDirty = False self.gcode = gcode self.gcodeDirty = True errorList = [] for line in open(self.gcodeFilename, "rt"): res = re.search(';Model error\(([a-z ]*)\): \(([0-9\.\-e]*), ([0-9\.\-e]*), ([0-9\.\-e]*)\) \(([0-9\.\-e]*), ([0-9\.\-e]*), ([0-9\.\-e]*)\)', line) if res != None: v1 = util3d.Vector3(float(res.group(2)), float(res.group(3)), float(res.group(4))) v2 = util3d.Vector3(float(res.group(5)), float(res.group(6)), float(res.group(7))) errorList.append([v1, v2]) self.errorList = errorList wx.CallAfter(self.updateToolbar) wx.CallAfter(self.glCanvas.Refresh) elif not os.path.isfile(self.gcodeFilename): self.gcode = None
def updateCenterY(self): self.machineCenter.y = profile.getProfileSettingFloat( 'machine_center_y') self.glCanvas.Refresh()
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]] moveColor = [0, 0, 1] retractColor = [1, 0, 0.5] supportColor = [0, 1, 1] extrudeColor = [1, 0, 0] innerWallColor = [0, 1, 0] skirtColor = [0, 0.5, 0.5] prevPathWasRetract = False glDisable(GL_CULL_FACE) for path in layer: if path.type == 'move': if prevPathWasRetract: c = retractColor else: c = moveColor zOffset = 0.01 if path.type == 'extrude': if path.pathType == 'FILL': c = fillColorCycle[fillCycle] fillCycle = (fillCycle + 1) % len(fillColorCycle) elif path.pathType == 'WALL-INNER': c = innerWallColor zOffset = 0.02 elif path.pathType == 'SUPPORT': c = supportColor elif path.pathType == 'SKIRT': c = skirtColor else: c = extrudeColor if path.type == 'retract': c = [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) glColor3fv(c) glVertex3f(vv0.x, vv0.y, vv0.z - zOffset) glVertex3f(vv1.x, vv1.y, vv1.z - zOffset) glVertex3f(vv3.x, vv3.y, vv3.z - zOffset) glVertex3f(vv2.x, vv2.y, vv2.z - zOffset) glEnd() if prevNormal != None: n = (normal + prevNormal) n.normalize() vv4 = v0 + n * lineWidth vv5 = v0 - n * lineWidth glBegin(GL_QUADS) glColor3fv(c) glVertex3f(vv2.x, vv2.y, vv2.z - zOffset) glVertex3f(vv4.x, vv4.y, vv4.z - zOffset) glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset) glVertex3f(v0.x, v0.y, v0.z - zOffset) glVertex3f(vv0.x, vv0.y, vv0.z - zOffset) glVertex3f(vv5.x, vv5.y, vv5.z - zOffset) glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset) glVertex3f(v0.x, v0.y, v0.z - zOffset) glEnd() prevNormal = normal prevVv1 = vv1 prevVv3 = vv3 else: glBegin(GL_LINE_STRIP) glColor3fv(c) for v in path.list: glVertex3f(v.x, v.y, v.z) glEnd() if not path.type == 'move': prevPathWasRetract = False if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]): prevPathWasRetract = True glEnable(GL_CULL_FACE)
def calculateShellsBase(setting): edgeWidth = profile.calculateEdgeWidth() extraWall = profile.getProfileSettingFloat('extra_base_wall_thickness') return profile.calculateLineCount() - 1 + int(extraWall / edgeWidth + 0.0001)
def updateCenterY(self): self.machineCenter.y = profile.getProfileSettingFloat('machine_center_y') self.glCanvas.Refresh()
def OnRun(self): resultFile = open(self.resultFilename, "w") put = profile.setTempOverride self.progressLog = [] for action in self.actionList: wx.CallAfter(self.SetTitle, "Building: [%d/%d]" % (self.actionList.index(action) + 1, len(self.actionList))) if not action.usePreviousSlice: p = subprocess.Popen(action.sliceCmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) line = p.stdout.readline() maxValue = 1 while(len(line) > 0): line = line.rstrip() if line[0:9] == "Progress[" and line[-1:] == "]": progress = line[9:-1].split(":") if len(progress) > 2: maxValue = int(progress[2]) wx.CallAfter(self.SetProgress, progress[0], int(progress[1]), maxValue) else: print line self.progressLog.append(line) wx.CallAfter(self.statusText.SetLabel, line) if self.abort: p.terminate() wx.CallAfter(self.statusText.SetLabel, "Aborted by user.") resultFile.close() return line = p.stdout.readline() self.returnCode = p.wait() put('machine_center_x', action.centerX - self.extruderOffset[action.extruder][0]) put('machine_center_y', action.centerY - self.extruderOffset[action.extruder][1]) put('clear_z', action.clearZ) put('extruder', action.extruder) put('print_temperature', action.temperature) if action == self.actionList[0]: resultFile.write(';TYPE:CUSTOM\n') resultFile.write('T%d\n' % (action.extruder)) currentExtruder = action.extruder prevTemp = action.temperature resultFile.write(profile.getAlterationFileContents('start.gcode')) else: #reset the extrusion length, and move to the next object center. resultFile.write(';TYPE:CUSTOM\n') if prevTemp != action.temperature: resultFile.write('M104 S%d\n' % (int(action.temperature))) prevTemp = action.temperature resultFile.write(profile.getAlterationFileContents('nextobject.gcode')) resultFile.write(';PRINTNR:%d\n' % self.actionList.index(action)) profile.resetTempOverride() if not action.usePreviousSlice: f = open(sliceRun.getExportFilename(action.filename, "project_tmp"), "r") data = f.read(4096) while data != '': resultFile.write(data) data = f.read(4096) f.close() savedCenterX = action.centerX savedCenterY = action.centerY else: f = open(sliceRun.getExportFilename(action.filename, "project_tmp"), "r") for line in f: if line[0] != ';': if 'X' in line: line = self._adjustNumberInLine(line, 'X', action.centerX - savedCenterX) if 'Y' in line: line = self._adjustNumberInLine(line, 'Y', action.centerY - savedCenterY) resultFile.write(line) f.close() if not action.leaveResultForNextSlice: os.remove(sliceRun.getExportFilename(action.filename, "project_tmp")) wx.CallAfter(self.progressGauge.SetValue, 10000) self.totalDoneFactor = 0.0 wx.CallAfter(self.progressGauge2.SetValue, self.actionList.index(action) + 1) resultFile.write(';TYPE:CUSTOM\n') resultFile.write('G1 Z%f F%f\n' % (self.actionList[-1].clearZ, profile.getProfileSettingFloat('max_z_speed') * 60)) resultFile.write(profile.getAlterationFileContents('end.gcode')) resultFile.close() gcode = gcodeInterpreter.gcode() gcode.load(self.resultFilename) self.abort = True sliceTime = time.time() - self.sliceStartTime status = "Build: %s" % (self.resultFilename) status += "\nSlicing took: %02d:%02d" % (sliceTime / 60, sliceTime % 60) status += "\nFilament: %.2fm %.2fg" % (gcode.extrusionAmount / 1000, gcode.calculateWeight() * 1000) status += "\nPrint time: %02d:%02d" % (int(gcode.totalMoveTimeMinute / 60), int(gcode.totalMoveTimeMinute % 60)) cost = gcode.calculateCost() if cost != False: status += "\nCost: %s" % (cost) profile.replaceGCodeTags(self.resultFilename, gcode) wx.CallAfter(self.statusText.SetLabel, status) wx.CallAfter(self.OnSliceDone)
def storedSettingInt(name): return lambda setting: int(profile.getProfileSettingFloat(name))
def calcSupportDistanceRatio(setting): edgeWidth = calculateEdgeWidth(setting) distance = profile.getProfileSettingFloat('support_distance') return distance / edgeWidth
def _engineSettings(self, extruderCount): settings = { 'layerThickness': int(profile.getProfileSettingFloat('layer_height') * 1000), 'initialLayerThickness': int(profile.getProfileSettingFloat('bottom_thickness') * 1000) if profile.getProfileSettingFloat('bottom_thickness') > 0.0 else int( profile.getProfileSettingFloat('layer_height') * 1000), 'filamentDiameter': int(profile.getProfileSettingFloat('filament_diameter') * 1000), 'filamentFlow': int(profile.getProfileSettingFloat('filament_flow')), 'extrusionWidth': int(profile.calculateEdgeWidth() * 1000), 'insetCount': int(profile.calculateLineCount()), 'downSkinCount': int(profile.calculateSolidLayerCount()) if profile.getProfileSetting('solid_bottom') == 'True' else 0, 'upSkinCount': int(profile.calculateSolidLayerCount()) if profile.getProfileSetting('solid_top') == 'True' else 0, 'infillOverlap': int(profile.getProfileSettingFloat('fill_overlap')), 'initialSpeedupLayers': int(4), 'initialLayerSpeed': int(profile.getProfileSettingFloat('bottom_layer_speed')), 'printSpeed': int(profile.getProfileSettingFloat('print_speed')), 'infillSpeed': int(profile.getProfileSettingFloat('infill_speed')) if int(profile.getProfileSettingFloat('infill_speed')) > 0 else int( profile.getProfileSettingFloat('print_speed')), 'moveSpeed': int(profile.getProfileSettingFloat('travel_speed')), 'fanSpeedMin': int(profile.getProfileSettingFloat('fan_speed')) if profile.getProfileSetting('fan_enabled') == 'True' else 0, 'fanSpeedMax': int(profile.getProfileSettingFloat('fan_speed_max')) if profile.getProfileSetting('fan_enabled') == 'True' else 0, 'supportAngle': int(-1) if profile.getProfileSetting('support') == 'None' else int( profile.getProfileSettingFloat('support_angle')), 'supportEverywhere': int(1) if profile.getProfileSetting('support') == 'Everywhere' else int(0), 'supportLineDistance': int(100 * profile.calculateEdgeWidth() * 1000 / profile.getProfileSettingFloat('support_fill_rate')) if profile.getProfileSettingFloat('support_fill_rate') > 0 else -1, 'supportXYDistance': int(1000 * profile.getProfileSettingFloat('support_xy_distance')), 'supportZDistance': int(1000 * profile.getProfileSettingFloat('support_z_distance')), 'supportExtruder': 0 if profile.getProfileSetting('support_dual_extrusion') == 'First extruder' else (1 if profile.getProfileSetting('support_dual_extrusion') == 'Second extruder' and profile.minimalExtruderCount() > 1 else -1), 'retractionAmount': int(profile.getProfileSettingFloat('retraction_amount') * 1000) if profile.getProfileSetting('retraction_enable') == 'True' else 0, 'retractionSpeed': int(profile.getProfileSettingFloat('retraction_speed')), 'retractionMinimalDistance': int( profile.getProfileSettingFloat('retraction_min_travel') * 1000), 'retractionAmountExtruderSwitch': int( profile.getProfileSettingFloat('retraction_dual_amount') * 1000), 'minimalExtrusionBeforeRetraction': int( profile.getProfileSettingFloat('retraction_minimal_extrusion') * 1000), 'enableCombing': 1 if profile.getProfileSetting('retraction_combing') == 'True' else 0, 'multiVolumeOverlap': int(profile.getProfileSettingFloat('overlap_dual') * 1000), 'objectSink': int(profile.getProfileSettingFloat('object_sink') * 1000), 'minimalLayerTime': int(profile.getProfileSettingFloat('cool_min_layer_time')), 'minimalFeedrate': int(profile.getProfileSettingFloat('cool_min_feedrate')), 'coolHeadLift': 1 if profile.getProfileSetting('cool_head_lift') == 'True' else 0, 'startCode': profile.getAlterationFileContents('start.gcode', extruderCount), 'endCode': profile.getAlterationFileContents('end.gcode', extruderCount), 'extruderOffset[1].X': int(profile.getMachineSettingFloat('extruder_offset_x1') * 1000), 'extruderOffset[1].Y': int(profile.getMachineSettingFloat('extruder_offset_y1') * 1000), 'extruderOffset[2].X': int(profile.getMachineSettingFloat('extruder_offset_x2') * 1000), 'extruderOffset[2].Y': int(profile.getMachineSettingFloat('extruder_offset_y2') * 1000), 'extruderOffset[3].X': int(profile.getMachineSettingFloat('extruder_offset_x3') * 1000), 'extruderOffset[3].Y': int(profile.getMachineSettingFloat('extruder_offset_y3') * 1000), 'fixHorrible': 0, } fanFullHeight = int( profile.getProfileSettingFloat('fan_full_height') * 1000) settings['fanFullOnLayerNr'] = (fanFullHeight - settings['initialLayerThickness'] - 1) / settings['layerThickness'] + 1 if settings['fanFullOnLayerNr'] < 0: settings['fanFullOnLayerNr'] = 0 if profile.getProfileSettingFloat('fill_density') == 0: settings['sparseInfillLineDistance'] = -1 elif profile.getProfileSettingFloat('fill_density') == 100: settings['sparseInfillLineDistance'] = settings['extrusionWidth'] #Set the up/down skins height to 10000 if we want a 100% filled object. # This gives better results then normal 100% infill as the sparse and up/down skin have some overlap. settings['downSkinCount'] = 10000 settings['upSkinCount'] = 10000 else: settings['sparseInfillLineDistance'] = int( 100 * profile.calculateEdgeWidth() * 1000 / profile.getProfileSettingFloat('fill_density')) if profile.getProfileSetting('platform_adhesion') == 'Brim': settings['skirtDistance'] = 0 settings['skirtLineCount'] = int( profile.getProfileSettingFloat('brim_line_count')) elif profile.getProfileSetting('platform_adhesion') == 'Raft': settings['skirtDistance'] = 0 settings['skirtLineCount'] = 0 settings['raftMargin'] = int( profile.getProfileSettingFloat('raft_margin') * 1000) settings['raftLineSpacing'] = int( profile.getProfileSettingFloat('raft_line_spacing') * 1000) settings['raftBaseThickness'] = int( profile.getProfileSettingFloat('raft_base_thickness') * 1000) settings['raftBaseLinewidth'] = int( profile.getProfileSettingFloat('raft_base_linewidth') * 1000) settings['raftInterfaceThickness'] = int( profile.getProfileSettingFloat('raft_interface_thickness') * 1000) settings['raftInterfaceLinewidth'] = int( profile.getProfileSettingFloat('raft_interface_linewidth') * 1000) else: settings['skirtDistance'] = int( profile.getProfileSettingFloat('skirt_gap') * 1000) settings['skirtLineCount'] = int( profile.getProfileSettingFloat('skirt_line_count')) settings['skirtMinLength'] = int( profile.getProfileSettingFloat('skirt_minimal_length') * 1000) if profile.getProfileSetting( 'fix_horrible_union_all_type_a') == 'True': settings['fixHorrible'] |= 0x01 if profile.getProfileSetting( 'fix_horrible_union_all_type_b') == 'True': settings['fixHorrible'] |= 0x02 if profile.getProfileSetting('fix_horrible_use_open_bits') == 'True': settings['fixHorrible'] |= 0x10 if profile.getProfileSetting( 'fix_horrible_extensive_stitching') == 'True': settings['fixHorrible'] |= 0x04 if settings['layerThickness'] <= 0: settings['layerThickness'] = 1000 if profile.getMachineSetting('gcode_flavor') == 'UltiGCode': settings['gcodeFlavor'] = 1 if profile.getProfileSetting('spiralize') == 'True': settings['spiralizeMode'] = 1 if profile.getProfileSetting('wipe_tower') == 'True': settings['wipeTowerSize'] = int( math.sqrt( profile.getProfileSettingFloat('wipe_tower_volume') * 1000 * 1000 * 1000 / settings['layerThickness'])) if profile.getProfileSetting('ooze_shield') == 'True': settings['enableOozeShield'] = 1 return settings
def OnDraw(self): machineSize = self.parent.machineSize if self.parent.gcode != None and self.parent.gcodeDirty: if self.gcodeDisplayListCount < len(self.parent.gcode.layerList) or self.gcodeDisplayList == None: if self.gcodeDisplayList != None: glDeleteLists(self.gcodeDisplayList, self.gcodeDisplayListCount) self.gcodeDisplayList = glGenLists(len(self.parent.gcode.layerList)); self.gcodeDisplayListCount = len(self.parent.gcode.layerList) self.parent.gcodeDirty = False self.gcodeDisplayListMade = 0 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 wx.CallAfter(self.Refresh) glPushMatrix() glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0) for obj in self.parent.objectList: if obj.mesh == None: continue if obj.displayList == None: obj.displayList = glGenLists(1); if obj.dirty: obj.dirty = False glNewList(obj.displayList, GL_COMPILE) opengl.DrawMesh(obj.mesh) glEndList() if self.viewMode == "Mixed": glDisable(GL_BLEND) glColor3f(0.0,0.0,0.0) self.drawModel(obj) glColor3f(1.0,1.0,1.0) glClear(GL_DEPTH_BUFFER_BIT) glPopMatrix() if self.parent.gcode != None and (self.viewMode == "GCode" or self.viewMode == "Mixed"): glEnable(GL_COLOR_MATERIAL) glEnable(GL_LIGHTING) drawUpToLayer = min(self.gcodeDisplayListMade, self.parent.layerSpin.GetValue() + 1) starttime = time.time() for i in xrange(drawUpToLayer - 1, -1, -1): c = 1.0 if i < self.parent.layerSpin.GetValue(): 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]) glCallList(self.gcodeDisplayList + i) if time.time() - starttime > 0.1: break glDisable(GL_LIGHTING) glDisable(GL_COLOR_MATERIAL) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, [0.2, 0.2, 0.2, 1.0]); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, [0.8, 0.8, 0.8, 1.0]); glColor3f(1.0,1.0,1.0) glPushMatrix() glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0) for obj in self.parent.objectList: if obj.mesh == None: continue if self.viewMode == "Transparent" or self.viewMode == "Mixed": glLightfv(GL_LIGHT0, GL_DIFFUSE, map(lambda x: x / 2, self.objColor[self.parent.objectList.index(obj)])) 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 self.viewMode != "Mixed": glDisable(GL_BLEND) glColor3f(0.0,0.0,0.0) self.drawModel(obj) glColor3f(1.0,1.0,1.0) #After the black model is rendered, render the model again but now with lighting and no depth testing. glDisable(GL_DEPTH_TEST) glEnable(GL_LIGHTING) glEnable(GL_BLEND) glBlendFunc(GL_ONE, GL_ONE) glEnable(GL_LIGHTING) self.drawModel(obj) glEnable(GL_DEPTH_TEST) elif self.viewMode == "X-Ray": glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) glDisable(GL_LIGHTING) glDisable(GL_DEPTH_TEST) glEnable(GL_STENCIL_TEST) glStencilFunc(GL_ALWAYS, 1, 1) glStencilOp(GL_INCR, GL_INCR, GL_INCR) self.drawModel(obj) glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) glStencilFunc(GL_EQUAL, 0, 1) glColor(1, 1, 1) self.drawModel(obj) glStencilFunc(GL_EQUAL, 1, 1) glColor(1, 0, 0) self.drawModel(obj) glPushMatrix() glLoadIdentity() for i in xrange(2, 15, 2): glStencilFunc(GL_EQUAL, i, 0xFF); glColor(float(i)/10, float(i)/10, float(i)/5) glBegin(GL_QUADS) glVertex3f(-1000,-1000,-1) glVertex3f( 1000,-1000,-1) glVertex3f( 1000, 1000,-1) glVertex3f(-1000, 1000,-1) glEnd() for i in xrange(1, 15, 2): glStencilFunc(GL_EQUAL, i, 0xFF); glColor(float(i)/10, 0, 0) glBegin(GL_QUADS) glVertex3f(-1000,-1000,-1) glVertex3f( 1000,-1000,-1) glVertex3f( 1000, 1000,-1) glVertex3f(-1000, 1000,-1) glEnd() glPopMatrix() glDisable(GL_STENCIL_TEST) glEnable(GL_DEPTH_TEST) #Fix the depth buffer glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) self.drawModel(obj) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) elif self.viewMode == "Normal": glLightfv(GL_LIGHT0, GL_DIFFUSE, self.objColor[self.parent.objectList.index(obj)]) glLightfv(GL_LIGHT0, GL_AMBIENT, map(lambda x: x / 5, self.objColor[self.parent.objectList.index(obj)])) glEnable(GL_LIGHTING) self.drawModel(obj) if self.drawBorders and (self.viewMode == "Normal" or self.viewMode == "Transparent" or self.viewMode == "X-Ray"): glEnable(GL_DEPTH_TEST) glDisable(GL_LIGHTING) glColor3f(1,1,1) glPushMatrix() modelScale = profile.getProfileSettingFloat('model_scale') glScalef(modelScale, modelScale, modelScale) opengl.DrawMeshOutline(obj.mesh) glPopMatrix() glPopMatrix() if self.viewMode == "Normal" or self.viewMode == "Transparent" or self.viewMode == "X-Ray": glDisable(GL_LIGHTING) glDisable(GL_DEPTH_TEST) glDisable(GL_BLEND) glColor3f(1,0,0) glBegin(GL_LINES) for err in self.parent.errorList: glVertex3f(err[0].x, err[0].y, err[0].z) glVertex3f(err[1].x, err[1].y, err[1].z) glEnd() glEnable(GL_DEPTH_TEST) opengl.DrawMachine(machineSize) glPushMatrix() glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0) #Draw the rotate circle if self.parent.objectsMaxV != None and False: glDisable(GL_LIGHTING) glDisable(GL_CULL_FACE) glEnable(GL_BLEND) glBegin(GL_TRIANGLE_STRIP) size = (self.parent.objectsMaxV - self.parent.objectsMinV) sizeXY = math.sqrt((size[0] * size[0]) + (size[1] * size[1])) for i in xrange(0, 64+1): f = i if i < 64/2 else 64 - i glColor4ub(255,int(f*255/(64/2)),0,128) glVertex3f(sizeXY * 0.7 * math.cos(i/32.0*math.pi), sizeXY * 0.7 * math.sin(i/32.0*math.pi),0.1) glColor4ub( 0,128,0,128) glVertex3f((sizeXY * 0.7 + 3) * math.cos(i/32.0*math.pi), (sizeXY * 0.7 + 3) * math.sin(i/32.0*math.pi),0.1) glEnd() glEnable(GL_CULL_FACE) glPopMatrix() glFlush()
def getProfileInformation(): return { 'carve': { 'Add_Layer_Template_to_SVG': DEFSET, 'Edge_Width_mm': calculateEdgeWidth, 'Extra_Decimal_Places_float': DEFSET, 'Import_Coarseness_ratio': DEFSET, 'Layer_Height_mm': storedSettingFloat("layer_height"), 'Layers_From_index': calcLayerSkip, 'Layers_To_index': DEFSET, 'Correct_Mesh': DEFSET, 'Unproven_Mesh': DEFSET, 'SVG_Viewer': DEFSET, 'FlipX': storedSetting("flip_x"), 'FlipY': storedSetting("flip_y"), 'FlipZ': storedSetting("flip_z"), 'SwapXZ': storedSetting("swap_xz"), 'SwapYZ': storedSetting("swap_yz"), 'Scale': storedSettingFloat("model_scale"), 'Rotate': storedSettingFloat("model_rotate_base"), 'CenterX': storedSettingFloat("machine_center_x"), 'CenterY': storedSettingFloat("machine_center_y"), 'AlternativeCenterFile': storedSetting("alternative_center"), },'scale': { 'Activate_Scale': "False", 'XY_Plane_Scale_ratio': DEFSET, 'Z_Axis_Scale_ratio': DEFSET, 'SVG_Viewer': DEFSET, },'bottom': { 'Activate_Bottom': DEFSET, 'Additional_Height_over_Layer_Thickness_ratio': DEFSET, 'Altitude_mm': calcExtraBottomThickness, 'SVG_Viewer': DEFSET, },'preface': { 'Meta': DEFSET, 'Set_Positioning_to_Absolute': "False", 'Set_Units_to_Millimeters': "False", 'Start_at_Home': DEFSET, 'Turn_Extruder_Off_at_Shut_Down': DEFSET, 'Turn_Extruder_Off_at_Start_Up': DEFSET, },'widen': { 'Activate_Widen': DEFSET, 'Widen_Width_over_Edge_Width_ratio': DEFSET, },'inset': { 'Add_Custom_Code_for_Temperature_Reading': "False", '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, 'Turn_Extruder_Heater_Off_at_Shut_Down': "False", 'Volume_Fraction_ratio': DEFSET, },'fill': { 'Activate_Fill': "True", 'Solid_Surface_Top': storedSetting("solid_top"), 'Override_First_Layer_Sequence': storedSetting("force_first_layer_sequence"), 'Diaphragm_Period_layers': DEFSET, 'Diaphragm_Thickness_layers': DEFSET, 'Extra_Shells_on_Alternating_Solid_Layer_layers': calculateShells, 'Extra_Shells_on_Base_layers': calculateShellsBase, 'Extra_Shells_on_Sparse_Layer_layers': calculateShells, 'Grid_Circle_Separation_over_Perimeter_Width_ratio': DEFSET, 'Grid_Extra_Overlap_ratio': DEFSET, 'Grid_Junction_Separation_Band_Height_layers': DEFSET, 'Grid_Junction_Separation_over_Octogon_Radius_At_End_ratio': DEFSET, 'Grid_Junction_Separation_over_Octogon_Radius_At_Middle_ratio': DEFSET, 'Infill_Begin_Rotation_degrees': DEFSET, 'Infill_Begin_Rotation_Repeat_layers': DEFSET, 'Infill_Odd_Layer_Extra_Rotation_degrees': DEFSET, 'Grid_Circular': ifSettingIs('infill_type', 'Grid Circular'), 'Grid_Hexagonal': ifSettingIs('infill_type', 'Grid Hexagonal'), 'Grid_Rectangular': ifSettingIs('infill_type', 'Grid Rectangular'), 'Line': ifSettingIs('infill_type', 'Line'), 'Infill_Perimeter_Overlap_ratio': storedPercentSetting('fill_overlap'), 'Infill_Solidity_ratio': storedPercentSetting('fill_density'), 'Infill_Width': storedSettingFloat("nozzle_size"), 'Sharpest_Angle_degrees': DEFSET, 'Solid_Surface_Thickness_layers': calculateSolidLayerCount, 'Start_From_Choice': DEFSET, 'Surrounding_Angle_degrees': DEFSET, 'Thread_Sequence_Choice': storedSetting('sequence'), },'multiply': { 'Activate_Multiply': "False", 'Center_X_mm': storedSettingFloat("machine_center_x"), 'Center_Y_mm': storedSettingFloat("machine_center_y"), 'Number_of_Columns_integer': storedSetting('model_multiply_x'), 'Number_of_Rows_integer': storedSetting('model_multiply_y'), 'Reverse_Sequence_every_Odd_Layer': DEFSET, 'Separation_over_Perimeter_Width_ratio': calculateMultiplyDistance, },'speed': { 'Activate_Speed': "True", 'Add_Flow_Rate': "True", 'Bridge_Feed_Rate_Multiplier_ratio': storedPercentSetting('bridge_speed'), 'Bridge_Flow_Rate_Multiplier_ratio': storedPercentSetting('bridge_speed'), 'Duty_Cyle_at_Beginning_portion': DEFSET, 'Duty_Cyle_at_Ending_portion': DEFSET, 'Feed_Rate_mm/s': storedSettingFloat("print_speed"), 'Flow_Rate_Setting_float': storedSettingFloat("print_speed"), 'Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio': firstLayerSpeedRatio, 'Object_First_Layer_Feed_Rate_Perimeter_Multiplier_ratio': firstLayerSpeedRatio, 'Object_First_Layer_Feed_Rate_Travel_Multiplier_ratio': firstLayerSpeedRatio, 'Object_First_Layer_Flow_Rate_Infill_Multiplier_ratio': firstLayerSpeedRatio, 'Object_First_Layer_Flow_Rate_Perimeter_Multiplier_ratio': firstLayerSpeedRatio, 'Object_First_Layers_Amount_Of_Layers_For_Speed_Change': DEFSET, 'Orbital_Feed_Rate_over_Operating_Feed_Rate_ratio': DEFSET, 'Maximum_Z_Feed_Rate_mm/s': DEFSET, 'Perimeter_Feed_Rate_Multiplier_ratio': DEFSET, 'Perimeter_Flow_Rate_Multiplier_ratio': DEFSET, 'Travel_Feed_Rate_mm/s': storedSettingFloat("travel_speed"), 'Bottom_layer_flow_rate_ratio': calcBottomLayerFlowRateRatio, },'temperature': { 'Activate_Temperature': DEFSET,#ifSettingAboveZero('print_temperature'), 'Cooling_Rate_Celcius/second': DEFSET, 'Heating_Rate_Celcius/second': DEFSET, 'Base_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"), 'Interface_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"), 'Object_First_Layer_Infill_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"), 'Object_First_Layer_Perimeter_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"), 'Object_Next_Layers_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"), 'Support_Layers_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"), 'Supported_Layers_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"), },'raft': { 'Activate_Raft': "True", 'Add_Raft,_Elevate_Nozzle,_Orbit': DEFSET, 'Base_Feed_Rate_Multiplier_ratio': DEFSET, 'Base_Flow_Rate_Multiplier_ratio': storedPercentSetting('raft_base_material_amount'), 'Base_Infill_Density_ratio': DEFSET, 'Base_Layer_Thickness_over_Layer_Thickness': DEFSET, 'Base_Layers_integer': raftLayerCount, 'Base_Nozzle_Lift_over_Base_Layer_Thickness_ratio': DEFSET, 'Initial_Circling': DEFSET, 'Infill_Overhang_over_Extrusion_Width_ratio': DEFSET, 'Interface_Feed_Rate_Multiplier_ratio': DEFSET, 'Interface_Flow_Rate_Multiplier_ratio': storedPercentSetting('raft_interface_material_amount'), 'Interface_Infill_Density_ratio': DEFSET, 'Interface_Layer_Thickness_over_Layer_Thickness': DEFSET, 'Interface_Layers_integer': raftLayerCount, 'Interface_Nozzle_Lift_over_Interface_Layer_Thickness_ratio': DEFSET, 'Name_of_Support_End_File': DEFSET, 'Name_of_Support_Start_File': DEFSET, 'Operating_Nozzle_Lift_over_Layer_Thickness_ratio': DEFSET, 'Raft_Additional_Margin_over_Length_%': DEFSET, 'Raft_Margin_mm': storedSettingFloat('raft_margin'), 'Support_Cross_Hatch': 'False', 'Support_Flow_Rate_over_Operating_Flow_Rate_ratio': storedPercentSetting('support_rate'), 'Support_Gap_over_Perimeter_Extrusion_Width_ratio': calcSupportDistanceRatio, 'Support_Material_Choice_': storedSetting('support'), 'Support_Minimum_Angle_degrees': DEFSET, 'Support_Margin_mm': '3.0', 'Support_Offset_X_mm': lambda setting: -profile.getPreferenceFloat('extruder_offset_x1') if profile.getProfileSetting('support_dual_extrusion') == 'True' and int(profile.getPreference('extruder_amount')) > 1 else '0', 'Support_Offset_Y_mm': lambda setting: -profile.getPreferenceFloat('extruder_offset_y1') if profile.getProfileSetting('support_dual_extrusion') == 'True' and int(profile.getPreference('extruder_amount')) > 1 else '0', },'skirt': { 'Skirt_line_count': storedSetting("skirt_line_count"), 'Convex': "True", 'Gap_Width_mm': storedSetting("skirt_gap"), 'Layers_To_index': "1", },'joris': { 'Activate_Joris': storedSetting("joris"), 'Layers_From_index': calculateSolidLayerCount, },'chamber': { 'Activate_Chamber': "False", 'Bed_Temperature_Celcius': DEFSET, 'Bed_Temperature_Begin_Change_Height_mm': DEFSET, 'Bed_Temperature_End_Change_Height_mm': DEFSET, 'Bed_Temperature_End_Celcius': DEFSET, 'Chamber_Temperature_Celcius': DEFSET, 'Holding_Force_bar': DEFSET, },'tower': { 'Activate_Tower': "False", 'Extruder_Possible_Collision_Cone_Angle_degrees': DEFSET, 'Maximum_Tower_Height_layers': DEFSET, 'Tower_Start_Layer_integer': DEFSET, },'jitter': { 'Activate_Jitter': "False", 'Jitter_Over_Perimeter_Width_ratio': DEFSET, },'clip': { 'Activate_Clip': "False", 'Clip_Over_Perimeter_Width_ratio': DEFSET, 'Maximum_Connection_Distance_Over_Perimeter_Width_ratio': DEFSET, },'smooth': { 'Activate_Smooth': "False", 'Layers_From_index': DEFSET, 'Maximum_Shortening_over_Width_float': DEFSET, },'stretch': { 'Activate_Stretch': "False", 'Cross_Limit_Distance_Over_Perimeter_Width_ratio': DEFSET, 'Loop_Stretch_Over_Perimeter_Width_ratio': DEFSET, 'Path_Stretch_Over_Perimeter_Width_ratio': DEFSET, 'Perimeter_Inside_Stretch_Over_Perimeter_Width_ratio': DEFSET, 'Perimeter_Outside_Stretch_Over_Perimeter_Width_ratio': DEFSET, 'Stretch_From_Distance_Over_Perimeter_Width_ratio': DEFSET, },'skin': { 'Activate_Skin': storedSetting("enable_skin"), 'Horizontal_Infill_Divisions_integer': "1", 'Horizontal_Perimeter_Divisions_integer': "1", 'Vertical_Divisions_integer': "2", 'Hop_When_Extruding_Infill': "False", 'Layers_From_index': "1", },'comb': { 'Activate_Comb': "True", 'Running_Jump_Space_mm': DEFSET, },'cool': { 'Activate_Cool': "True", 'Bridge_Cool_Celcius': DEFSET, 'Cool_Type': DEFSET, 'Maximum_Cool_Celcius': DEFSET, 'Minimum_Layer_Time_seconds': storedSettingFloat("cool_min_layer_time"), 'Minimum_Orbital_Radius_millimeters': DEFSET, 'Name_of_Cool_End_File': DEFSET, 'Name_of_Cool_Start_File': DEFSET, 'Orbital_Outset_millimeters': DEFSET, 'Turn_Fan_On_at_Beginning': storedSetting("fan_enabled"), 'Turn_Fan_Off_at_Ending': storedSetting("fan_enabled"), 'Minimum_feed_rate_mm/s': storedSettingFloat("cool_min_feedrate"), 'Fan_on_at_layer': storedSettingInt('fan_layer'), 'Fan_speed_min_%': storedSettingInt('fan_speed'), 'Fan_speed_max_%': storedSettingInt('fan_speed_max'), },'hop': { 'Activate_Hop': "False", 'Hop_Over_Layer_Thickness_ratio': DEFSET, 'Minimum_Hop_Angle_degrees': DEFSET, },'wipe': { 'Activate_Wipe': "False", 'Arrival_X_mm': DEFSET, 'Arrival_Y_mm': DEFSET, 'Arrival_Z_mm': DEFSET, 'Departure_X_mm': DEFSET, 'Departure_Y_mm': DEFSET, 'Departure_Z_mm': DEFSET, 'Wipe_X_mm': DEFSET, 'Wipe_Y_mm': DEFSET, 'Wipe_Z_mm': DEFSET, 'Wipe_Period_layers': DEFSET, },'oozebane': { 'Activate_Oozebane': "False", 'After_Startup_Distance_millimeters': DEFSET, 'Early_Shutdown_Distance_millimeters': DEFSET, 'Early_Startup_Distance_Constant_millimeters': DEFSET, 'Early_Startup_Maximum_Distance_millimeters': DEFSET, 'First_Early_Startup_Distance_millimeters': DEFSET, 'Minimum_Distance_for_Early_Startup_millimeters': DEFSET, 'Minimum_Distance_for_Early_Shutdown_millimeters': DEFSET, 'Slowdown_Startup_Steps_positive_integer': DEFSET, },'dwindle': { 'Activate_Dwindle': "False", 'End_Rate_Multiplier_ratio': '0.5', 'Pent_Up_Volume_cubic_millimeters': "0.4", 'Slowdown_Steps_positive_integer': '5', 'Slowdown_Volume_cubic_millimeters': "5.0", },'splodge': { 'Activate_Splodge': "False", 'Initial_Lift_over_Extra_Thickness_ratio': DEFSET, 'Initial_Splodge_Feed_Rate_mm/s': DEFSET, 'Operating_Splodge_Feed_Rate_mm/s': DEFSET, 'Operating_Splodge_Quantity_Length_millimeters': DEFSET, 'Initial_Splodge_Quantity_Length_millimeters': DEFSET, 'Operating_Lift_over_Extra_Thickness_ratio': DEFSET, },'home': { 'Activate_Home': "False", 'Name_of_Home_File': DEFSET, },'lash': { 'Activate_Lash': "False", 'X_Backlash_mm': DEFSET, 'Y_Backlash_mm': DEFSET, },'fillet': { 'Activate_Fillet': "False", 'Arc_Point': DEFSET, 'Arc_Radius': DEFSET, 'Arc_Segment': DEFSET, 'Bevel': DEFSET, 'Corner_Feed_Rate_Multiplier_ratio': DEFSET, 'Fillet_Radius_over_Perimeter_Width_ratio': DEFSET, 'Reversal_Slowdown_Distance_over_Perimeter_Width_ratio': DEFSET, 'Use_Intermediate_Feed_Rate_in_Corners': DEFSET, },'limit': { 'Activate_Limit': "False", 'Maximum_Initial_Feed_Rate_mm/s': DEFSET, },'unpause': { 'Activate_Unpause': "False", 'Delay_milliseconds': DEFSET, 'Maximum_Speed_ratio': DEFSET, },'dimension': { 'Activate_Dimension': "True", 'Absolute_Extrusion_Distance': "True", 'Relative_Extrusion_Distance': "False", 'Extruder_Retraction_Speed_mm/s': storedSettingFloat('retraction_speed'), 'Filament_Diameter_mm': storedSettingFloat("filament_diameter"), 'Filament_Packing_Density_ratio': storedSettingFloat("filament_density"), 'Maximum_E_Value_before_Reset_float': DEFSET, 'Minimum_Travel_for_Retraction_millimeters': storedSettingFloat("retraction_min_travel"), 'Retract_Within_Island': storedSettingInvertBoolean("retract_on_jumps_only"), 'Retraction_Distance_millimeters': lambda setting: profile.getProfileSettingFloat('retraction_amount') if profile.getProfileSetting('retraction_enable') == 'True' else 0, 'Restart_Extra_Distance_millimeters': storedSettingFloat('retraction_extra'), },'alteration': { 'Activate_Alteration': storedSetting('add_start_end_gcode'), 'Name_of_End_File': "end.gcode", 'Name_of_Start_File': "start.gcode", 'Remove_Redundant_Mcode': "True", 'Replace_Variable_with_Setting': DEFSET, },'export': { 'Activate_Export': "True", 'Add_Descriptive_Extension': DEFSET, 'Add_Export_Suffix': DEFSET, 'Add_Profile_Extension': DEFSET, 'Add_Timestamp_Extension': DEFSET, 'Also_Send_Output_To': DEFSET, 'Analyze_Gcode': DEFSET, 'Comment_Choice': DEFSET, 'Do_Not_Change_Output': DEFSET, 'binary_16_byte': DEFSET, 'gcode_step': DEFSET, 'gcode_time_segment': DEFSET, 'gcode_small': DEFSET, 'File_Extension': storedSetting('gcode_extension'), 'Name_of_Replace_File': DEFSET, 'Save_Penultimate_Gcode': "False", } }
def calcLayerSkip(setting): bottomThickness = profile.getProfileSettingFloat('bottom_thickness') layerThickness = profile.getProfileSettingFloat('layer_height') if bottomThickness < layerThickness: return 0 return int(math.ceil((bottomThickness - layerThickness) / layerThickness + 0.0001) - 1)
def calcExtraBottomThickness(setting): bottomThickness = profile.getProfileSettingFloat('bottom_thickness') layerThickness = profile.getProfileSettingFloat('layer_height') if bottomThickness < layerThickness: return 0.0 return bottomThickness - layerThickness
def calcBottomLayerFlowRateRatio(setting): bottomThickness = profile.getProfileSettingFloat('bottom_thickness') layerThickness = profile.getProfileSettingFloat('layer_height') if bottomThickness < layerThickness: return 1.0 return bottomThickness / layerThickness
def OnMouseMotion(self, e): if self.parent.objectsMaxV != None: size = (self.parent.objectsMaxV - self.parent.objectsMinV) sizeXY = math.sqrt((size[0] * size[0]) + (size[1] * size[1])) p0 = numpy.array( gluUnProject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 0, self.modelMatrix, self.projMatrix, self.viewport)) p1 = numpy.array( gluUnProject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 1, self.modelMatrix, self.projMatrix, self.viewport)) cursorZ0 = p0 - (p1 - p0) * (p0[2] / (p1[2] - p0[2])) cursorXY = math.sqrt((cursorZ0[0] * cursorZ0[0]) + (cursorZ0[1] * cursorZ0[1])) if cursorXY >= sizeXY * 0.7 and cursorXY <= sizeXY * 0.7 + 3: self.SetCursor(wx.StockCursor(wx.CURSOR_SIZING)) else: self.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) if e.Dragging() and e.LeftIsDown(): if self.dragType == '': #Define the drag type depending on the cursor position. if cursorXY >= sizeXY * 0.7 and cursorXY <= sizeXY * 0.7 + 3: self.dragType = 'modelRotate' self.dragStart = math.atan2(cursorZ0[0], cursorZ0[1]) else: self.dragType = 'viewRotate' if self.dragType == 'viewRotate': if self.view3D: self.yaw += e.GetX() - self.oldX self.pitch -= e.GetY() - self.oldY if self.pitch > 170: self.pitch = 170 if self.pitch < 10: self.pitch = 10 else: self.offsetX += float( e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2 self.offsetY -= float( e.GetY() - self.oldY) * self.zoom / self.GetSize().GetHeight() * 2 elif self.dragType == 'modelRotate': angle = math.atan2(cursorZ0[0], cursorZ0[1]) diff = self.dragStart - angle self.tempRotate = diff * 180 / math.pi #Workaround for buggy ATI cards. size = self.GetSizeTuple() self.SetSize((size[0] + 1, size[1])) self.SetSize((size[0], size[1])) self.Refresh() else: if self.tempRotate != 0: profile.putProfileSetting( 'model_rotate_base', profile.getProfileSettingFloat('model_rotate_base') + self.tempRotate) self.parent.updateModelTransform() self.tempRotate = 0 self.dragType = '' if e.Dragging() and e.RightIsDown(): self.zoom += e.GetY() - self.oldY if self.zoom < 1: self.zoom = 1 self.Refresh() self.oldX = e.GetX() self.oldY = e.GetY()
def main(): parser = OptionParser(usage="usage: %prog [options] <filename>.stl") parser.add_option("-i", "--ini", action="store", type="string", dest="profileini", help="Load settings from a profile ini file") parser.add_option( "-r", "--print", action="store", type="string", dest="printfile", help= "Open the printing interface, instead of the normal cura interface.") parser.add_option("-p", "--profile", action="store", type="string", dest="profile", help="Internal option, do not use!") parser.add_option("-x", "--scale", action="store", type="string", dest="scale", help="scale the stl object") parser.add_option( "-s", "--slice", action="store_true", dest="slice", help="Slice the given files instead of opening them in Cura") parser.add_option("-o", "--output", action="store", type="string", dest="output", help="path to write sliced file to") parser.add_option("-t", "--transform", action="store", type="string", dest="transform", help="rotate and transform the object") (options, args) = parser.parse_args() #print "load preferences from " + profile.getPreferencePath() profile.loadPreferences(profile.getPreferencePath()) #default_profile_string = profile.getProfileString() #print("default_profile_string = %s" % (default_profile_string)) #profile.setProfileFromString(default_profile_string) if options.profile is not None: profile.loadProfile( r"/home/buccaneer/bin/buccaneer-slicer/current/slicer.ini") #profile.setProfileFromString(options.profile) #print("options.profile Input\n\n") #print(options.profile) custom_params = [] for param in options.profile.split(','): param = param.replace("++", " ") custom_params.append(param) #print(custom_params) profile.setProfileFromString(custom_params) elif options.profileini is not None: profile.loadProfile(options.profileini) else: #print("Default Path: %s" % (profile.getDefaultProfilePath())) profile.loadProfile( r"/home/buccaneer/bin/buccaneer-slicer/current/slicer.ini") if options.printfile is not None: from Cura.gui import printWindow printWindow.startPrintInterface(options.printfile) elif options.slice is not None: from util import sliceEngine from util import objectScene from util import meshLoader from util import mesh import shutil import numpy as np def commandlineProgessCallback(progress, ready, loading): if progress >= 0 and not ready and not loading: sys.stdout.write("Slicing: %d%%\n" % (progress * 100, )) sys.stdout.flush() elif progress >= 0 and not ready and loading: sys.stdout.write("Loading: %d%%" % (progress * 100, )) sys.stdout.flush() profile.putMachineSetting('machine_name', 'Buccaneer') profile.putMachineSetting('machine_width', '138') profile.putMachineSetting('machine_depth', '112') profile.putMachineSetting('machine_height', '149.5') profile.putProfileSetting('nozzle_size', '0.4') profile.putProfileSetting( 'wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2) profile.putMachineSetting('has_heated_bed', str(False)) profile.putMachineSetting('machine_center_is_zero', str(False)) profile.putMachineSetting('extruder_head_size_min_x', '0') profile.putMachineSetting('extruder_head_size_min_y', '0') profile.putMachineSetting('extruder_head_size_max_x', '0') profile.putMachineSetting('extruder_head_size_max_y', '0') profile.putMachineSetting('extruder_head_size_height', '0') profile.checkAndUpdateMachineName() scene = objectScene.Scene() scene.updateMachineDimensions() slicer = sliceEngine.Slicer(commandlineProgessCallback) matrix = [] if options.transform is not None: transform_params = [] for param in options.transform.split(','): param = param.replace("[", " ") param = param.replace("]", " ") transform_params.append(param) data = np.array(transform_params) print data matrix = [[ transform_params[0], transform_params[1], transform_params[2] ], [transform_params[3], transform_params[4], transform_params[5]], [ transform_params[6], transform_params[7], transform_params[8] ]] if options.scale is not None: if (int(options.scale) >= 1): obj = meshLoader.loadMeshes(args[0], int(options.scale)) else: obj = meshLoader.loadMeshes(args[0]) else: obj = meshLoader.loadMeshes(args[0]) for m in obj: scene.addNewMatrix(m, matrix) sys.stdout.write("Slicing: %d%%\n" % (0 * 100, )) sys.stdout.flush() slicer.runSlicer(scene) slicer.wait() profile.replaceGCodeTagsFromSlicer(slicer.getGCodeFilename(), slicer) if options.output: shutil.copyfile(slicer.getGCodeFilename(), options.output) print 'GCode file saved : %s' % options.output else: shutil.copyfile(slicer.getGCodeFilename(), args[0] + '.gcode') print 'GCode file saved as: %s' % (args[0] + '.gcode') slicer.cleanup() else: from Cura.gui import app app.CuraApp(args).MainLoop()
def firstLayerSpeedRatio(setting): bottomSpeed = profile.getProfileSettingFloat('bottom_layer_speed') speed = profile.getProfileSettingFloat('print_speed') return bottomSpeed/speed
def _watchProcess(self, commandList, oldThread): if oldThread is not None: if self._process is not None: self._process.terminate() oldThread.join() self._id += 1 self._callback(-1.0, False, False) try: self._process = self._runSliceProcess(commandList) except OSError: traceback.print_exc() return if self._thread != threading.currentThread(): self._process.terminate() self._callback(0.0, False, False) self._sliceLog = [] self._printTimeSeconds = None self._filamentMM = [0.0, 0.0] line = self._process.stdout.readline() objectNr = 0 while len(line): line = line.strip() if line.startswith('Progress:'): line = line.split(':') if line[1] == 'process': objectNr += 1 elif line[1] == 'Loading': #print ("Loading....\n") progressValue = float(line[2]) / float(line[3]) try: self._callback(progressValue, False, True) except: pass elif line[1] in self._progressSteps: progressValue = float(line[2]) / float(line[3]) progressValue /= len(self._progressSteps) progressValue += 1.0 / len( self._progressSteps) * self._progressSteps.index( line[1]) progressValue /= self._objCount progressValue += 1.0 / self._objCount * objectNr try: self._callback(progressValue, False, False) except: pass elif line.startswith('Print time:'): self._printTimeSeconds = int(line.split(':')[1].strip()) elif line.startswith('Filament:'): self._filamentMM[0] = int(line.split(':')[1].strip()) if profile.getMachineSetting('gcode_flavor') == 'UltiGCode': radius = profile.getProfileSettingFloat( 'filament_diameter') / 2.0 self._filamentMM[0] /= (math.pi * radius * radius) elif line.startswith('Filament2:'): self._filamentMM[1] = int(line.split(':')[1].strip()) if profile.getMachineSetting('gcode_flavor') == 'UltiGCode': radius = profile.getProfileSettingFloat( 'filament_diameter') / 2.0 self._filamentMM[1] /= (math.pi * radius * radius) else: self._sliceLog.append(line.strip()) line = self._process.stdout.readline() self._callback(1, False, False) print('\n') for line in self._process.stderr: self._sliceLog.append(line.strip()) returnCode = self._process.wait() try: if returnCode == 0: pluginError = profile.runPostProcessingPlugins( self._exportFilename) if pluginError is not None: print pluginError self._sliceLog.append(pluginError) self._callback(1.0, True, False) else: for line in self._sliceLog: print line self._callback(-1.0, False, False) except: pass self._process = None
def OnSlice(self, e): dlg=wx.FileDialog(self, "Save project gcode file", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE) dlg.SetWildcard("GCode file (*.gcode)|*.gcode") if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() return resultFilename = dlg.GetPath() dlg.Destroy() put = profile.setTempOverride oldProfile = profile.getGlobalProfileString() put('add_start_end_gcode', 'False') put('gcode_extension', 'project_tmp') if self.printMode == 0: clearZ = 0 actionList = [] for item in self.list: if item.profile != None and os.path.isfile(item.profile): profile.loadGlobalProfile(item.profile) put('machine_center_x', item.centerX - self.extruderOffset[item.extruder][0]) put('machine_center_y', item.centerY - self.extruderOffset[item.extruder][1]) put('model_scale', item.scale) put('flip_x', item.flipX) put('flip_y', item.flipY) put('flip_z', item.flipZ) put('model_rotate_base', item.rotate) put('swap_xz', item.swapXZ) put('swap_yz', item.swapYZ) action = Action() action.sliceCmd = sliceRun.getSliceCommand(item.filename) action.centerX = item.centerX action.centerY = item.centerY action.temperature = profile.getProfileSettingFloat('print_temperature') action.extruder = item.extruder action.filename = item.filename clearZ = max(clearZ, item.getMaximum()[2] * item.scale + 5.0) action.clearZ = clearZ action.leaveResultForNextSlice = False action.usePreviousSlice = False actionList.append(action) if self.list.index(item) > 0 and item.isSameExceptForPosition(self.list[self.list.index(item)-1]): actionList[-2].leaveResultForNextSlice = True actionList[-1].usePreviousSlice = True if item.profile != None: profile.loadGlobalProfileFromString(oldProfile) else: self._saveCombinedSTL(resultFilename + "_temp_.stl") put('model_scale', 1.0) put('flip_x', False) put('flip_y', False) put('flip_z', False) put('model_rotate_base', 0) put('swap_xz', False) put('swap_yz', False) actionList = [] action = Action() action.sliceCmd = sliceRun.getSliceCommand(resultFilename + "_temp_.stl") action.centerX = profile.getProfileSettingFloat('machine_center_x') action.centerY = profile.getProfileSettingFloat('machine_center_y') action.temperature = profile.getProfileSettingFloat('print_temperature') action.extruder = 0 action.filename = resultFilename + "_temp_.stl" action.clearZ = 0 action.leaveResultForNextSlice = False action.usePreviousSlice = False actionList.append(action) #Restore the old profile. profile.resetTempOverride() pspw = ProjectSliceProgressWindow(actionList, resultFilename) pspw.extruderOffset = self.extruderOffset pspw.Centre() pspw.Show(True)
def ifSettingAboveZero(name): return lambda setting: profile.getProfileSettingFloat(name) > 0
def OnDraw(self): machineSize = self.parent.machineSize if self.parent.gcode != None and self.parent.gcodeDirty: if self.gcodeDisplayListCount < len( self.parent.gcode.layerList ) or self.gcodeDisplayList == None: if self.gcodeDisplayList != None: glDeleteLists(self.gcodeDisplayList, self.gcodeDisplayListCount) self.gcodeDisplayList = glGenLists( len(self.parent.gcode.layerList)) self.gcodeDisplayListCount = len(self.parent.gcode.layerList) self.parent.gcodeDirty = False self.gcodeDisplayListMade = 0 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() glPushMatrix() glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0) for obj in self.parent.objectList: if obj.mesh == None: continue if obj.displayList == None: obj.displayList = glGenLists(1) if obj.dirty: obj.dirty = False glNewList(obj.displayList, GL_COMPILE) opengl.DrawMesh(obj.mesh) glEndList() if self.viewMode == "Mixed": glDisable(GL_BLEND) glColor3f(0.0, 0.0, 0.0) self.drawModel(obj) glColor3f(1.0, 1.0, 1.0) glClear(GL_DEPTH_BUFFER_BIT) glPopMatrix() if self.parent.gcode != None and (self.viewMode == "GCode" or self.viewMode == "Mixed"): glEnable(GL_COLOR_MATERIAL) glEnable(GL_LIGHTING) drawUpToLayer = min(self.gcodeDisplayListMade, self.parent.layerSpin.GetValue() + 1) starttime = time.time() for i in xrange(drawUpToLayer - 1, -1, -1): c = 1.0 if i < self.parent.layerSpin.GetValue(): 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]) glCallList(self.gcodeDisplayList + i) if time.time() - starttime > 0.1: break glDisable(GL_LIGHTING) glDisable(GL_COLOR_MATERIAL) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, [0.2, 0.2, 0.2, 1.0]) glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, [0.8, 0.8, 0.8, 1.0]) glColor3f(1.0, 1.0, 1.0) glPushMatrix() glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0) for obj in self.parent.objectList: if obj.mesh == None: continue if self.viewMode == "Transparent" or self.viewMode == "Mixed": glLightfv( GL_LIGHT0, GL_DIFFUSE, map(lambda x: x / 2, self.objColor[self.parent.objectList.index(obj)])) 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 self.viewMode != "Mixed": glDisable(GL_BLEND) glColor3f(0.0, 0.0, 0.0) self.drawModel(obj) glColor3f(1.0, 1.0, 1.0) #After the black model is rendered, render the model again but now with lighting and no depth testing. glDisable(GL_DEPTH_TEST) glEnable(GL_LIGHTING) glEnable(GL_BLEND) glBlendFunc(GL_ONE, GL_ONE) glEnable(GL_LIGHTING) self.drawModel(obj) glEnable(GL_DEPTH_TEST) elif self.viewMode == "X-Ray": glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) glDisable(GL_LIGHTING) glDisable(GL_DEPTH_TEST) glEnable(GL_STENCIL_TEST) glStencilFunc(GL_ALWAYS, 1, 1) glStencilOp(GL_INCR, GL_INCR, GL_INCR) self.drawModel(obj) glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) glStencilFunc(GL_EQUAL, 0, 1) glColor(1, 1, 1) self.drawModel(obj) glStencilFunc(GL_EQUAL, 1, 1) glColor(1, 0, 0) self.drawModel(obj) glPushMatrix() glLoadIdentity() for i in xrange(2, 15, 2): glStencilFunc(GL_EQUAL, i, 0xFF) glColor(float(i) / 10, float(i) / 10, float(i) / 5) glBegin(GL_QUADS) glVertex3f(-1000, -1000, -1) glVertex3f(1000, -1000, -1) glVertex3f(1000, 1000, -1) glVertex3f(-1000, 1000, -1) glEnd() for i in xrange(1, 15, 2): glStencilFunc(GL_EQUAL, i, 0xFF) glColor(float(i) / 10, 0, 0) glBegin(GL_QUADS) glVertex3f(-1000, -1000, -1) glVertex3f(1000, -1000, -1) glVertex3f(1000, 1000, -1) glVertex3f(-1000, 1000, -1) glEnd() glPopMatrix() glDisable(GL_STENCIL_TEST) glEnable(GL_DEPTH_TEST) #Fix the depth buffer glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) self.drawModel(obj) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) elif self.viewMode == "Normal": glLightfv(GL_LIGHT0, GL_DIFFUSE, self.objColor[self.parent.objectList.index(obj)]) glLightfv( GL_LIGHT0, GL_AMBIENT, map(lambda x: x / 5, self.objColor[self.parent.objectList.index(obj)])) glEnable(GL_LIGHTING) self.drawModel(obj) if self.drawBorders and (self.viewMode == "Normal" or self.viewMode == "Transparent" or self.viewMode == "X-Ray"): glEnable(GL_DEPTH_TEST) glDisable(GL_LIGHTING) glColor3f(1, 1, 1) glPushMatrix() modelScale = profile.getProfileSettingFloat('model_scale') glScalef(modelScale, modelScale, modelScale) opengl.DrawMeshOutline(obj.mesh) glPopMatrix() glPopMatrix() if self.viewMode == "Normal" or self.viewMode == "Transparent" or self.viewMode == "X-Ray": glDisable(GL_LIGHTING) glDisable(GL_DEPTH_TEST) glDisable(GL_BLEND) glColor3f(1, 0, 0) glBegin(GL_LINES) for err in self.parent.errorList: glVertex3f(err[0].x, err[0].y, err[0].z) glVertex3f(err[1].x, err[1].y, err[1].z) glEnd() glEnable(GL_DEPTH_TEST) opengl.DrawMachine(machineSize) glPushMatrix() glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0) #Draw the rotate circle if self.parent.objectsMaxV != None: glDisable(GL_LIGHTING) glDisable(GL_CULL_FACE) glEnable(GL_BLEND) glBegin(GL_TRIANGLE_STRIP) size = (self.parent.objectsMaxV - self.parent.objectsMinV) sizeXY = math.sqrt((size[0] * size[0]) + (size[1] * size[1])) for i in xrange(0, 64 + 1): f = i if i < 64 / 2 else 64 - i glColor4ub(255, int(f * 255 / (64 / 2)), 0, 128) glVertex3f(sizeXY * 0.7 * math.cos(i / 32.0 * math.pi), sizeXY * 0.7 * math.sin(i / 32.0 * math.pi), 0.1) glColor4ub(0, 128, 0, 128) glVertex3f((sizeXY * 0.7 + 3) * math.cos(i / 32.0 * math.pi), (sizeXY * 0.7 + 3) * math.sin(i / 32.0 * math.pi), 0.1) glEnd() glEnable(GL_CULL_FACE) glPopMatrix() glFlush()
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]] moveColor = [0, 0, 1] retractColor = [1, 0, 0.5] supportColor = [0, 1, 1] extrudeColor = [1, 0, 0] innerWallColor = [0, 1, 0] skirtColor = [0, 0.5, 0.5] prevPathWasRetract = False glDisable(GL_CULL_FACE) for path in layer: if path.type == "move": if prevPathWasRetract: c = retractColor else: c = moveColor zOffset = 0.01 if path.type == "extrude": if path.pathType == "FILL": c = fillColorCycle[fillCycle] fillCycle = (fillCycle + 1) % len(fillColorCycle) elif path.pathType == "WALL-INNER": c = innerWallColor zOffset = 0.02 elif path.pathType == "SUPPORT": c = supportColor elif path.pathType == "SKIRT": c = skirtColor else: c = extrudeColor if path.type == "retract": c = [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) glColor3fv(c) glVertex3f(vv0.x, vv0.y, vv0.z - zOffset) glVertex3f(vv1.x, vv1.y, vv1.z - zOffset) glVertex3f(vv3.x, vv3.y, vv3.z - zOffset) glVertex3f(vv2.x, vv2.y, vv2.z - zOffset) glEnd() if prevNormal != None: n = normal + prevNormal n.normalize() vv4 = v0 + n * lineWidth vv5 = v0 - n * lineWidth glBegin(GL_QUADS) glColor3fv(c) glVertex3f(vv2.x, vv2.y, vv2.z - zOffset) glVertex3f(vv4.x, vv4.y, vv4.z - zOffset) glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset) glVertex3f(v0.x, v0.y, v0.z - zOffset) glVertex3f(vv0.x, vv0.y, vv0.z - zOffset) glVertex3f(vv5.x, vv5.y, vv5.z - zOffset) glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset) glVertex3f(v0.x, v0.y, v0.z - zOffset) glEnd() prevNormal = normal prevVv1 = vv1 prevVv3 = vv3 else: glBegin(GL_LINE_STRIP) glColor3fv(c) for v in path.list: glVertex3f(v.x, v.y, v.z) glEnd() if not path.type == "move": prevPathWasRetract = False if path.type == "retract" and path.list[0].almostEqual(path.list[-1]): prevPathWasRetract = True glEnable(GL_CULL_FACE)
def storedPercentSetting(name): return lambda setting: profile.getProfileSettingFloat(name) / 100