Merge branch 'master' of github.com:daid/Cura

This commit is contained in:
Daid 2012-05-03 19:23:12 +02:00
commit 06bf4c6f93
8 changed files with 215 additions and 52 deletions

View File

@ -406,9 +406,10 @@ class CoolSkein:
def setMultiplier(self, remainingOrbitTime):
'Set the feed and flow rate multiplier.'
layerTimeActive = self.getLayerTimeActive()
self.multiplier = min(1.0, layerTimeActive / (remainingOrbitTime + layerTimeActive))
if remainingOrbitTime + layerTimeActive > 0.00001:
self.multiplier = min(1.0, layerTimeActive / (remainingOrbitTime + layerTimeActive))
else:
self.multiplier = 1.0
def main():
'Display the cool dialog.'

View File

@ -1,6 +1,7 @@
import wx
import sys,math,threading,os
from gui import gcodeTextArea
from util import profile
class alterationPanel(wx.Panel):
@ -10,8 +11,9 @@ class alterationPanel(wx.Panel):
self.alterationFileList = ['start.gcode', 'end.gcode', 'support_start.gcode', 'support_end.gcode', 'nextobject.gcode', 'replace.csv']
self.currentFile = None
self.textArea = wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_DONTWRAP|wx.TE_PROCESS_TAB)
self.textArea.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
#self.textArea = wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_DONTWRAP|wx.TE_PROCESS_TAB)
#self.textArea.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
self.textArea = gcodeTextArea.GcodeTextArea(self)
self.list = wx.ListBox(self, choices=self.alterationFileList, style=wx.LB_SINGLE)
self.list.SetSelection(0)
self.Bind(wx.EVT_LISTBOX, self.OnSelect, self.list)

101
Cura/gui/gcodeTextArea.py Normal file
View File

@ -0,0 +1,101 @@
import wx, wx.stc
import sys,math,os
from util import profile
class GcodeTextArea(wx.stc.StyledTextCtrl):
def __init__(self, parent):
super(GcodeTextArea, self).__init__(parent)
self.SetLexer(wx.stc.STC_LEX_CONTAINER)
self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyle)
fontSize = wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize()
fontName = wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL).GetFaceName()
self.SetStyleBits(5)
self.StyleSetSpec(0, "face:%s,size:%d" % (fontName, fontSize))
self.StyleSetSpec(1, "fore:#008000,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")
#GCodes and MCodes as supported by Marlin
#GCode 21 is not really supported by Marlin, but we still do not report it as error as it's often used.
self.supportedGCodes = [0,1,2,3,4,21,28,90,91,92]
self.supportedMCodes = [17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,42,80,81,82,83,84,85,92,104,105,106,107,109,114,115,117,119,140,190,201,202,203,204,205,206,220,221,240,301,302,303,400,500,501,502,503,999]
def OnStyle(self, e):
lineNr = self.LineFromPosition(self.GetEndStyled())
while self.PositionFromLine(lineNr) > -1:
line = self.GetLine(lineNr)
start = self.PositionFromLine(lineNr)
length = self.LineLength(lineNr)
self.StartStyling(start, 255)
self.SetStyling(length, 0)
if ';' in line:
pos = line.index(';')
self.StartStyling(start + pos, 31)
self.SetStyling(length - pos, 1)
length = pos
pos = 0
while pos < length:
if line[pos] in " \t\n\r":
while pos < length and line[pos] in " \t\n\r":
pos += 1
else:
end = pos
while end < length and not line[end] in " \t\n\r":
end += 1
if self.checkGCodePart(line[pos:end], start + pos):
self.StartStyling(start + pos, 0x20)
self.SetStyling(end - pos, 0x20)
pos = end
lineNr += 1
def checkGCodePart(self, part, pos):
if len(part) < 2:
self.StartStyling(pos, 0x40)
self.SetStyling(1, 0x40)
return True
if not part[0] in "GMXYZFESTBPIDCJ":
self.StartStyling(pos, 0x40)
self.SetStyling(1, 0x40)
return True
if part[1] == '{':
if part[-1] != '}':
return True
tag = part[2:-1]
if not profile.isProfileSetting(tag) and not profile.isPreference(tag):
self.StartStyling(pos + 2, 0x40)
self.SetStyling(len(tag), 0x40)
return True
elif part[0] in "GM":
try:
code = int(part[1:])
except (ValueError):
self.StartStyling(pos + 1, 0x40)
self.SetStyling(len(part) - 1, 0x40)
return True
if part[0] == 'G':
if not code in self.supportedGCodes:
return True
if part[0] == 'M':
if not code in self.supportedMCodes:
return True
else:
try:
float(part[1:])
except (ValueError):
self.StartStyling(pos + 1, 0x40)
self.SetStyling(len(part) - 1, 0x40)
return True
return False
def GetValue(self):
return self.GetText()
def SetValue(self, s):
self.SetText(s)

View File

@ -86,6 +86,7 @@ class mainWindow(configBase.configWindowBase):
if profile.getPreference('lastFile') != '':
self.filelist = profile.getPreference('lastFile').split(';')
self.SetTitle(self.filelist[-1] + ' - Cura - ' + version.getVersion())
else:
self.filelist = []
self.progressPanelList = []
@ -299,6 +300,7 @@ class mainWindow(configBase.configWindowBase):
filelist.append(self._showOpenDialog("Open file to print"))
if filelist[-1] == False:
return
self.SetTitle(filelist[-1] + ' - Cura - ' + version.getVersion())
self.filelist = filelist
profile.putPreference('lastFile', ';'.join(self.filelist))
self.preview3d.loadModelFiles(self.filelist)

View File

@ -1,11 +1,6 @@
from __future__ import division
import sys
import math
import threading
import re
import time
import os
import sys, math, threading, re, time, os
from wx import glcanvas
import wx
@ -63,7 +58,6 @@ class previewPanel(wx.Panel):
self.xrayViewButton = toolbarUtil.RadioButton(self.toolbar, group, 'view-xray-on.png', 'view-xray-off.png', 'X-Ray view', callback=self.OnViewChange)
self.gcodeViewButton = toolbarUtil.RadioButton(self.toolbar, group, 'view-gcode-on.png', 'view-gcode-off.png', 'GCode view', callback=self.OnViewChange)
self.mixedViewButton = toolbarUtil.RadioButton(self.toolbar, group, 'view-mixed-on.png', 'view-mixed-off.png', 'Mixed model/GCode view', callback=self.OnViewChange)
self.OnViewChange()
self.toolbar.AddSeparator()
self.layerSpin = wx.SpinCtrl(self.toolbar, -1, '', size=(21*4,21), style=wx.SP_ARROW_KEYS)
@ -103,11 +97,11 @@ class previewPanel(wx.Panel):
self.rotateReset = toolbarUtil.NormalButton(self.toolbar2, self.OnRotateReset, 'object-rotate.png', 'Reset model rotation')
self.rotate = wx.SpinCtrl(self.toolbar2, -1, profile.getProfileSetting('model_rotate_base'), size=(21*3,21), style=wx.SP_WRAP|wx.SP_ARROW_KEYS)
self.rotate.SetRange(0, 360)
self.Bind(wx.EVT_TEXT, self.OnRotate)
self.rotate.Bind(wx.EVT_TEXT, self.OnRotate)
self.toolbar2.AddControl(self.rotate)
self.toolbar2.Realize()
self.updateToolbar()
self.OnViewChange()
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.toolbar, 0, flag=wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, border=1)
@ -180,7 +174,6 @@ class previewPanel(wx.Panel):
self.glCanvas.Refresh()
def OnLayerNrChange(self, e):
self.gcodeDirty = True
self.glCanvas.Refresh()
def updateCenterX(self):
@ -272,7 +265,9 @@ class previewPanel(wx.Panel):
pass
def updateToolbar(self):
self.layerSpin.Show(self.gcode != None)
self.gcodeViewButton.Show(self.gcode != None)
self.mixedViewButton.Show(self.gcode != None)
self.layerSpin.Show(self.glCanvas.viewMode == "GCode" or self.glCanvas.viewMode == "Mixed")
if self.gcode != None:
self.layerSpin.SetRange(1, len(self.gcode.layerList))
self.toolbar.Realize()
@ -288,6 +283,7 @@ class previewPanel(wx.Panel):
self.glCanvas.viewMode = "GCode"
elif self.mixedViewButton.GetValue():
self.glCanvas.viewMode = "Mixed"
self.updateToolbar()
self.glCanvas.Refresh()
def updateModelTransform(self, f=0):
@ -376,6 +372,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
self.offsetY = 0
self.view3D = True
self.gcodeDisplayList = None
self.gcodeDisplayListCount = 0
self.objColor = [[1.0, 0.8, 0.6, 1.0], [0.2, 1.0, 0.1, 1.0], [1.0, 0.2, 0.1, 1.0], [0.1, 0.2, 1.0, 1.0]]
def OnMouseMotion(self,e):
@ -439,33 +436,37 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
opengl.DrawMachine(machineSize)
if self.parent.gcode != None:
if self.gcodeDisplayList == None:
self.gcodeDisplayList = glGenLists(1);
if 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
glNewList(self.gcodeDisplayList, GL_COMPILE)
prevLayerZ = 0.0
curLayerZ = 0.0
layerThickness = 0.0
filamentRadius = float(profile.getProfileSetting('filament_diameter')) / 2
filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
filamentArea = math.pi * filamentRadius * filamentRadius
lineWidth = float(profile.getProfileSetting('nozzle_size')) / 2 / 10
lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
curLayerNum = 0
for layer in self.parent.gcode.layerList:
glNewList(self.gcodeDisplayList + curLayerNum, GL_COMPILE)
glDisable(GL_CULL_FACE)
curLayerZ = layer[0].list[1].z
layerThickness = curLayerZ - prevLayerZ
prevLayerZ = layer[-1].list[-1].z
for path in layer:
c = 1.0
if curLayerNum != self.parent.layerSpin.GetValue():
if curLayerNum < self.parent.layerSpin.GetValue():
c = 0.9 - (self.parent.layerSpin.GetValue() - curLayerNum) * 0.1
if c < 0.4:
c = 0.4
else:
break
#if curLayerNum != self.parent.layerSpin.GetValue():
# if curLayerNum < self.parent.layerSpin.GetValue():
# c = 0.9 - (self.parent.layerSpin.GetValue() - curLayerNum) * 0.1
# if c < 0.4:
# c = 0.4
# else:
# break
if path.type == 'move':
glColor3f(0,0,c)
if path.type == 'extrude':
@ -527,9 +528,24 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
glVertex3f(v.x, v.y, v.z)
glEnd()
curLayerNum += 1
glEndList()
glEnable(GL_CULL_FACE)
glEndList()
if self.viewMode == "GCode" or self.viewMode == "Mixed":
glCallList(self.gcodeDisplayList)
glEnable(GL_COLOR_MATERIAL)
glEnable(GL_LIGHTING)
glLightfv(GL_LIGHT0, GL_DIFFUSE, [0,0,0,0])
for i in xrange(0, self.parent.layerSpin.GetValue() + 1):
c = 1.0
if i < self.parent.layerSpin.GetValue():
c = 0.9 - (self.parent.layerSpin.GetValue() - i) * 0.1
if c < 0.4:
c = (0.4 + c) / 2
if c < 0.1:
c = 0.1
glLightfv(GL_LIGHT0, GL_AMBIENT, [c,c,c,c])
glCallList(self.gcodeDisplayList + i)
glDisable(GL_COLOR_MATERIAL)
glDisable(GL_LIGHTING)
glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0)
for obj in self.parent.objectList:

View File

@ -285,9 +285,7 @@ class projectPlanner(wx.Frame):
return (maxX - minX) + (maxY - minY)
def OnSlice(self, e):
oldProfile = profile.getGlobalProfileString()
put = profile.putProfileSetting
put = profile.setTempOverride
put('model_multiply_x', '1')
put('model_multiply_y', '1')
@ -319,7 +317,7 @@ class projectPlanner(wx.Frame):
actionList.append(action)
#Restore the old profile.
profile.loadGlobalProfileFromString(oldProfile)
profile.resetTempOverride()
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")
@ -670,6 +668,7 @@ class ProjectSliceProgressWindow(wx.Frame):
self.sizer.Add(self.statusText, (0,0), flag=wx.ALIGN_CENTER)
self.sizer.Add(self.progressGauge, (1, 0), flag=wx.EXPAND)
self.sizer.Add(self.progressGauge2, (2, 0), flag=wx.EXPAND)
self.sizer.Add(self.abortButton, (3,0), flag=wx.ALIGN_CENTER)
self.sizer.AddGrowableCol(0)
self.sizer.AddGrowableRow(0)
@ -702,7 +701,7 @@ class ProjectSliceProgressWindow(wx.Frame):
def OnRun(self):
resultFile = open(self.resultFilename, "w")
put = profile.putProfileSetting
put = profile.setTempOverride
for action in self.actionList:
p = subprocess.Popen(action.sliceCmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
line = p.stdout.readline()
@ -727,7 +726,6 @@ class ProjectSliceProgressWindow(wx.Frame):
line = p.stdout.readline()
self.returnCode = p.wait()
oldProfile = profile.getGlobalProfileString()
put('machine_center_x', action.centerX - self.extruderOffset[action.extruder].x)
put('machine_center_y', action.centerY - self.extruderOffset[action.extruder].y)
put('clear_z', action.clearZ)
@ -743,7 +741,7 @@ class ProjectSliceProgressWindow(wx.Frame):
resultFile.write(';TYPE:CUSTOM\n')
resultFile.write(profile.getAlterationFileContents('nextobject.gcode'))
resultFile.write(';PRINTNR:%d\n' % self.actionList.index(action))
profile.loadGlobalProfileFromString(oldProfile)
profile.resetTempOverride()
f = open(action.filename[: action.filename.rfind('.')] + "_export.project_tmp", "r")
data = f.read(4096)
@ -762,7 +760,7 @@ class ProjectSliceProgressWindow(wx.Frame):
resultFile.close()
self.abort = True
sliceTime = time.time() - self.sliceStartTime
wx.CallAfter(self.statusText.SetLabel, 'Slicing took: %d:%d' % (sliceTime / 60, sliceTime % 60))
wx.CallAfter(self.statusText.SetLabel, 'Slicing took: %02d:%02d' % (sliceTime / 60, sliceTime % 60))
wx.CallAfter(self.abortButton.SetLabel, 'Close')
def main():

View File

@ -59,21 +59,20 @@ class sliceProgessPanel(wx.Panel):
if profile.getPreference('save_profile') == 'True':
profile.saveGlobalProfile(self.filelist[0][: self.filelist[0].rfind('.')] + "_profile.ini")
cmdList = []
oldProfile = profile.getGlobalProfileString()
for filename in self.filelist:
idx = self.filelist.index(filename)
print filename, idx
if idx > 0:
profile.putProfileSetting('fan_enabled', 'False')
profile.putProfileSetting('skirt_line_count', '0')
profile.putProfileSetting('machine_center_x', profile.getProfileSettingFloat('machine_center_x') - profile.getPreferenceFloat('extruder_offset_x%d' % (idx)))
profile.putProfileSetting('machine_center_y', profile.getProfileSettingFloat('machine_center_y') - profile.getPreferenceFloat('extruder_offset_y%d' % (idx)))
profile.putProfileSetting('alternative_center', self.filelist[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.putProfileSetting('add_start_end_gcode', 'False')
profile.putProfileSetting('gcode_extension', 'multi_extrude_tmp')
profile.setTempOverride('add_start_end_gcode', 'False')
profile.setTempOverride('gcode_extension', 'multi_extrude_tmp')
cmdList.append(sliceRun.getSliceCommand(filename))
profile.loadGlobalProfileFromString(oldProfile)
profile.resetTempOverride()
self.thread = WorkerThread(self, filelist, cmdList)
def OnAbort(self, e):
@ -188,7 +187,10 @@ class WorkerThread(threading.Thread):
resultFile.write(';TYPE:CUSTOM\n')
resultFile.write(profile.getAlterationFileContents('start.gcode'))
for filename in self.filelist:
files.append(open(filename[:filename.rfind('.')]+'_export.multi_extrude_tmp', "r"))
if os.path.isfile(filename[:filename.rfind('.')]+'_export.multi_extrude_tmp'):
files.append(open(filename[:filename.rfind('.')]+'_export.multi_extrude_tmp', "r"))
else:
return
currentExtruder = 0
resultFile.write('T%d\n' % (currentExtruder))

View File

@ -67,6 +67,9 @@ profileDefaultSettings = {
'add_start_end_gcode': 'True',
'gcode_extension': 'gcode',
'alternative_center': '',
'clear_z': '0.0',
'extruder': '0',
}
alterationDefault = {
#######################################################################################
@ -153,6 +156,7 @@ preferencesDefaultSettings = {
## Profile and preferences functions
#########################################################
## Profile functions
def getDefaultProfilePath():
return os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../current_profile.ini"))
@ -188,17 +192,31 @@ def getGlobalProfileString():
p = []
alt = []
tempDone = []
if globalProfileParser.has_section('profile'):
for key in globalProfileParser.options('profile'):
p.append(key + "=" + globalProfileParser.get('profile', key))
if key in tempOverride:
p.append(key + "=" + unicode(tempOverride[key]))
tempDone.append(key)
else:
p.append(key + "=" + globalProfileParser.get('profile', key))
if globalProfileParser.has_section('alterations'):
for key in globalProfileParser.options('alterations'):
alt.append(key + "=" + globalProfileParser.get('alterations', key))
if key in tempOverride:
p.append(key + "=" + tempOverride[key])
tempDone.append(key)
else:
alt.append(key + "=" + globalProfileParser.get('alterations', key))
for key in tempOverride:
if key not in tempDone:
p.append(key + "=" + unicode(tempOverride[key]))
ret = '\b'.join(p) + '\f' + '\b'.join(alt)
ret = base64.b64encode(zlib.compress(ret, 9))
return ret
def getProfileSetting(name):
if name in tempOverride:
return unicode(tempOverride[name])
#Check if we have a configuration file loaded, else load the default.
if not globals().has_key('globalProfileParser'):
loadGlobalProfile(getDefaultProfilePath())
@ -230,6 +248,12 @@ def putProfileSetting(name, value):
globalProfileParser.add_section('profile')
globalProfileParser.set('profile', name, str(value))
def isProfileSetting(name):
if name in profileDefaultSettings:
return True
return False
## Preferences functions
global globalPreferenceParser
globalPreferenceParser = None
@ -239,11 +263,12 @@ def getPreferencePath():
def getPreferenceFloat(name):
try:
return float(eval(getPreference(name), {}, {}))
except (ValueError, SyntaxError):
return 0.0
def getPreference(name):
if name in tempOverride:
return unicode(tempOverride[name])
global globalPreferenceParser
if globalPreferenceParser == None:
globalPreferenceParser = ConfigParser.ConfigParser()
@ -273,6 +298,18 @@ def putPreference(name, value):
globalPreferenceParser.set('preference', name, unicode(value).encode("utf-8"))
globalPreferenceParser.write(open(getPreferencePath(), 'w'))
def isPreference(name):
if name in preferencesDefaultSettings:
return True
return False
## Temp overrides for multi-extruder slicing and the project planner.
tempOverride = {}
def setTempOverride(name, value):
tempOverride[name] = value
def resetTempOverride():
tempOverride = {}
#########################################################
## Utility functions to calculate common profile values
#########################################################
@ -316,7 +353,11 @@ def replaceTagMatch(m):
tag = m.group(0)[1:-1]
if tag in ['print_speed', 'retraction_speed', 'travel_speed', 'max_z_speed', 'bottom_layer_speed', 'cool_min_feedrate']:
return str(getProfileSettingFloat(tag) * 60)
return str(getProfileSettingFloat(tag))
if isProfileSetting(tag):
return str(getProfileSettingFloat(tag))
if isPreference(tag):
return str(getProfileSettingFloat(tag))
return tag
### Get aleration raw contents. (Used internally in Cura)
def getAlterationFile(filename):