Added more GCode validation to GCode editor. Made temp changes to profile really temp so they are never stored in the ini file. Fixed crash bug in skeinforge where there is no layer code.
This commit is contained in:
parent
9385aa8c25
commit
e29261a992
5 changed files with 138 additions and 31 deletions
|
@ -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.'
|
||||
|
|
|
@ -13,21 +13,86 @@ class GcodeTextArea(wx.stc.StyledTextCtrl):
|
|||
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(wx.stc.STC_STYLE_DEFAULT, "face:%s,size:%d" % (fontName, fontSize))
|
||||
self.StyleSetSpec(1, "fore:#008000,face:%s,size:%d" % (fontName, fontSize))
|
||||
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)
|
||||
self.StartStyling(self.PositionFromLine(lineNr), 31)
|
||||
self.SetStyling(self.LineLength(lineNr), wx.stc.STC_STYLE_DEFAULT)
|
||||
start = self.PositionFromLine(lineNr)
|
||||
length = self.LineLength(lineNr)
|
||||
self.StartStyling(start, 255)
|
||||
self.SetStyling(length, 0)
|
||||
if ';' in line:
|
||||
pos = line.index(';')
|
||||
self.StartStyling(self.PositionFromLine(lineNr) + pos, 31)
|
||||
self.SetStyling(self.LineLength(lineNr) - pos, 1)
|
||||
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()
|
||||
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in a new issue