chiark / gitweb /
Added more GCode validation to GCode editor. Made temp changes to profile really...
authordaid <daid303@gmail.com>
Thu, 3 May 2012 10:29:55 +0000 (12:29 +0200)
committerdaid <daid303@gmail.com>
Thu, 3 May 2012 10:29:55 +0000 (12:29 +0200)
Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/cool.py
Cura/gui/gcodeTextArea.py
Cura/gui/projectPlanner.py
Cura/gui/sliceProgessPanel.py
Cura/util/profile.py

index f018e0c6a55a36e2e33510ac7058ef03124b900d..eb363a8cddd94e06fd872a9180b6954ff266faf5 100644 (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.'
index e6d8565524f43586d2cb25c22e62c2a64bfdb581..6cb108a17658f8df7b893fe60b18323321b3497b 100644 (file)
@@ -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()
        
index 9b664ce5c50e8edb525bdf552180ebe883166517..a198a76d190f14d6a096b6ff5815ad4b4e0491c8 100644 (file)
@@ -285,9 +285,7 @@ class projectPlanner(wx.Frame):
                return (maxX - minX) + (maxY - minY)\r
 \r
        def OnSlice(self, e):\r
-               oldProfile = profile.getGlobalProfileString()\r
-               \r
-               put = profile.putProfileSetting\r
+               put = profile.setTempOverride\r
 \r
                put('model_multiply_x', '1')\r
                put('model_multiply_y', '1')\r
@@ -319,7 +317,7 @@ class projectPlanner(wx.Frame):
                        actionList.append(action)\r
                \r
                #Restore the old profile.\r
-               profile.loadGlobalProfileFromString(oldProfile)\r
+               profile.resetTempOverride()\r
                \r
                dlg=wx.FileDialog(self, "Save project gcode file", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE)\r
                dlg.SetWildcard("GCode file (*.gcode)|*.gcode")\r
@@ -670,6 +668,7 @@ class ProjectSliceProgressWindow(wx.Frame):
                self.sizer.Add(self.statusText, (0,0), flag=wx.ALIGN_CENTER)\r
                self.sizer.Add(self.progressGauge, (1, 0), flag=wx.EXPAND)\r
                self.sizer.Add(self.progressGauge2, (2, 0), flag=wx.EXPAND)\r
+\r
                self.sizer.Add(self.abortButton, (3,0), flag=wx.ALIGN_CENTER)\r
                self.sizer.AddGrowableCol(0)\r
                self.sizer.AddGrowableRow(0)\r
@@ -702,7 +701,7 @@ class ProjectSliceProgressWindow(wx.Frame):
        \r
        def OnRun(self):\r
                resultFile = open(self.resultFilename, "w")\r
-               put = profile.putProfileSetting\r
+               put = profile.setTempOverride\r
                for action in self.actionList:\r
                        p = subprocess.Popen(action.sliceCmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\r
                        line = p.stdout.readline()\r
@@ -727,7 +726,6 @@ class ProjectSliceProgressWindow(wx.Frame):
                                line = p.stdout.readline()\r
                        self.returnCode = p.wait()\r
                        \r
-                       oldProfile = profile.getGlobalProfileString()\r
                        put('machine_center_x', action.centerX - self.extruderOffset[action.extruder].x)\r
                        put('machine_center_y', action.centerY - self.extruderOffset[action.extruder].y)\r
                        put('clear_z', action.clearZ)\r
@@ -743,7 +741,7 @@ class ProjectSliceProgressWindow(wx.Frame):
                                resultFile.write(';TYPE:CUSTOM\n')\r
                                resultFile.write(profile.getAlterationFileContents('nextobject.gcode'))\r
                        resultFile.write(';PRINTNR:%d\n' % self.actionList.index(action))\r
-                       profile.loadGlobalProfileFromString(oldProfile)\r
+                       profile.resetTempOverride()\r
                        \r
                        f = open(action.filename[: action.filename.rfind('.')] + "_export.project_tmp", "r")\r
                        data = f.read(4096)\r
@@ -762,7 +760,7 @@ class ProjectSliceProgressWindow(wx.Frame):
                resultFile.close()\r
                self.abort = True\r
                sliceTime = time.time() - self.sliceStartTime\r
-               wx.CallAfter(self.statusText.SetLabel, 'Slicing took: %d:%d' % (sliceTime / 60, sliceTime % 60))\r
+               wx.CallAfter(self.statusText.SetLabel, 'Slicing took: %02d:%02d' % (sliceTime / 60, sliceTime % 60))\r
                wx.CallAfter(self.abortButton.SetLabel, 'Close')\r
 \r
 def main():\r
index 17fc78575470c6fcd4285297dc3f7e3e2bb89d2c..3fd0ad023d25897980322abbee172d9cb586dbb4 100644 (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))
index 96e1eb3555ece2738312fdd529f886709b09bf1a..686a8d8b0a0aa1ae71446123865b6349efdbd02d 100644 (file)
@@ -67,6 +67,9 @@ profileDefaultSettings = {
        \r
        'add_start_end_gcode': 'True',\r
        'gcode_extension': 'gcode',\r
+       'alternative_center': '',\r
+       'clear_z': '0.0',\r
+       'extruder': '0',\r
 }\r
 alterationDefault = {\r
 #######################################################################################\r
@@ -153,6 +156,7 @@ preferencesDefaultSettings = {
 ## Profile and preferences functions\r
 #########################################################\r
 \r
+## Profile functions\r
 def getDefaultProfilePath():\r
        return os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../current_profile.ini"))\r
 \r
@@ -188,17 +192,31 @@ def getGlobalProfileString():
        \r
        p = []\r
        alt = []\r
+       tempDone = []\r
        if globalProfileParser.has_section('profile'):\r
                for key in globalProfileParser.options('profile'):\r
-                       p.append(key + "=" + globalProfileParser.get('profile', key))\r
+                       if key in tempOverride:\r
+                               p.append(key + "=" + unicode(tempOverride[key]))\r
+                               tempDone.append(key)\r
+                       else:\r
+                               p.append(key + "=" + globalProfileParser.get('profile', key))\r
        if globalProfileParser.has_section('alterations'):\r
                for key in globalProfileParser.options('alterations'):\r
-                       alt.append(key + "=" + globalProfileParser.get('alterations', key))\r
+                       if key in tempOverride:\r
+                               p.append(key + "=" + tempOverride[key])\r
+                               tempDone.append(key)\r
+                       else:\r
+                               alt.append(key + "=" + globalProfileParser.get('alterations', key))\r
+       for key in tempOverride:\r
+               if key not in tempDone:\r
+                       p.append(key + "=" + unicode(tempOverride[key]))\r
        ret = '\b'.join(p) + '\f' + '\b'.join(alt)\r
        ret = base64.b64encode(zlib.compress(ret, 9))\r
        return ret\r
 \r
 def getProfileSetting(name):\r
+       if name in tempOverride:\r
+               return unicode(tempOverride[name])\r
        #Check if we have a configuration file loaded, else load the default.\r
        if not globals().has_key('globalProfileParser'):\r
                loadGlobalProfile(getDefaultProfilePath())\r
@@ -230,6 +248,12 @@ def putProfileSetting(name, value):
                globalProfileParser.add_section('profile')\r
        globalProfileParser.set('profile', name, str(value))\r
 \r
+def isProfileSetting(name):\r
+       if name in profileDefaultSettings:\r
+               return True\r
+       return False\r
+\r
+## Preferences functions\r
 global globalPreferenceParser\r
 globalPreferenceParser = None\r
 \r
@@ -239,11 +263,12 @@ def getPreferencePath():
 def getPreferenceFloat(name):\r
        try:\r
                return float(eval(getPreference(name), {}, {}))\r
-\r
        except (ValueError, SyntaxError):\r
                return 0.0\r
 \r
 def getPreference(name):\r
+       if name in tempOverride:\r
+               return unicode(tempOverride[name])\r
        global globalPreferenceParser\r
        if globalPreferenceParser == None:\r
                globalPreferenceParser = ConfigParser.ConfigParser()\r
@@ -273,6 +298,18 @@ def putPreference(name, value):
        globalPreferenceParser.set('preference', name, unicode(value).encode("utf-8"))\r
        globalPreferenceParser.write(open(getPreferencePath(), 'w'))\r
 \r
+def isPreference(name):\r
+       if name in preferencesDefaultSettings:\r
+               return True\r
+       return False\r
+\r
+## Temp overrides for multi-extruder slicing and the project planner.\r
+tempOverride = {}\r
+def setTempOverride(name, value):\r
+       tempOverride[name] = value\r
+def resetTempOverride():\r
+       tempOverride = {}\r
+\r
 #########################################################\r
 ## Utility functions to calculate common profile values\r
 #########################################################\r
@@ -316,7 +353,11 @@ def replaceTagMatch(m):
        tag = m.group(0)[1:-1]\r
        if tag in ['print_speed', 'retraction_speed', 'travel_speed', 'max_z_speed', 'bottom_layer_speed', 'cool_min_feedrate']:\r
                return str(getProfileSettingFloat(tag) * 60)\r
-       return str(getProfileSettingFloat(tag))\r
+       if isProfileSetting(tag):\r
+               return str(getProfileSettingFloat(tag))\r
+       if isPreference(tag):\r
+               return str(getProfileSettingFloat(tag))\r
+       return tag\r
 \r
 ### Get aleration raw contents. (Used internally in Cura)\r
 def getAlterationFile(filename):\r