#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module.\r
import __init__\r
\r
-import ConfigParser, os, traceback, math, re\r
+import ConfigParser, os, traceback, math, re, zlib, base64\r
\r
#########################################################\r
-## Profile and preferences functions\r
+## Default settings when none are found.\r
#########################################################\r
\r
#Single place to store the defaults, so we have a consistent set of default settings.\r
'fill_overlap': '15',\r
'support_rate': '50',\r
'support_distance': '0.5',\r
+ 'support_margin': '3.0',\r
'joris': 'False',\r
'enable_skin': 'False',\r
'enable_raft': 'False',\r
'add_start_end_gcode': 'True',\r
'gcode_extension': 'gcode',\r
}\r
+alterationDefault = {\r
+#######################################################################################\r
+ 'start.gcode': """;Start GCode\r
+G21 ;metric values\r
+G90 ;absolute positioning\r
+\r
+G28 X0 Y0 ;move X/Y to min endstops\r
+G28 Z0 ;move Z to min endstops\r
+\r
+; if your prints start too high, try changing the Z0.0 below\r
+; to Z1.0 - the number after the Z is the actual, physical\r
+; height of the nozzle in mm. This can take some messing around\r
+; with to get just right...\r
+G92 X0 Y0 Z0 E0 ;reset software position to front/left/z=0.0\r
+G1 Z15.0 F{max_z_speed} ;move the platform down 15mm\r
+G92 E0 ;zero the extruded length\r
+\r
+G1 F200 E5 ;extrude 5mm of feed stock\r
+G1 F200 E3.5 ;reverse feed stock by 1.5mm\r
+G92 E0 ;zero the extruded length again\r
+\r
+;go to the middle of the platform, and move to Z=0 before starting the print.\r
+G1 X{machine_center_x} Y{machine_center_y} F{travel_speed}\r
+G1 Z0.0 F{max_z_speed}\r
+""",\r
+#######################################################################################\r
+ 'end.gcode': """;End GCode\r
+M104 S0 ;extruder heat off\r
+G91 ;relative positioning\r
+G1 Z+10 E-5 F{max_z_speed} ;move Z up a bit and retract filament by 5mm\r
+G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\r
+M84 ;steppers off\r
+G90 ;absolute positioning\r
+""",\r
+#######################################################################################\r
+ 'support_start.gcode': '',\r
+ 'support_end.gcode': '',\r
+ 'cool_start.gcode': '',\r
+ 'cool_end.gcode': '',\r
+ 'replace.csv': '',\r
+#######################################################################################\r
+ 'nextobject.gcode': """;Move to next object on the platform. clear_z is the minimal z height we need to make sure we do not hit any objects.\r
+G92 E0\r
+G1 Z{clear_z} E-5 F{max_z_speed}\r
+G92 E0\r
+G1 X{machine_center_x} Y{machine_center_y} F{travel_speed}\r
+G1 F200 E5.5\r
+G92 E0\r
+G1 Z0 F{max_z_speed}\r
+""",\r
+#######################################################################################\r
+}\r
preferencesDefaultSettings = {\r
'wizardDone': 'False',\r
'startMode': 'Simple',\r
'filament_cost_meter': '0',\r
}\r
\r
+#########################################################\r
+## Profile and preferences functions\r
+#########################################################\r
+\r
def getDefaultProfilePath():\r
return os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../current_profile.ini"))\r
\r
global globalProfileParser\r
globalProfileParser = ConfigParser.ConfigParser()\r
globalProfileParser.add_section('profile')\r
- for option in options.split('#'):\r
+ globalProfileParser.add_section('alterations')\r
+ options = base64.b64decode(options)\r
+ options = zlib.decompress(options)\r
+ (profileOpts, alt) = options.split('\f', 1)\r
+ for option in profileOpts.split('\b'):\r
(key, value) = option.split('=', 1)\r
globalProfileParser.set('profile', key, value)\r
+ for option in alt.split('\b'):\r
+ (key, value) = option.split('=', 1)\r
+ globalProfileParser.set('alterations', key, value)\r
\r
def getGlobalProfileString():\r
global globalProfileParser\r
if not globals().has_key('globalProfileParser'):\r
loadGlobalProfile(getDefaultProfilePath())\r
\r
- ret = []\r
+ p = []\r
+ alt = []\r
for key in globalProfileParser.options('profile'):\r
- ret.append(key + "=" + globalProfileParser.get('profile', key))\r
- return '#'.join(ret)\r
+ p.append(key + "=" + globalProfileParser.get('profile', key))\r
+ for key in globalProfileParser.options('alterations'):\r
+ alt.append(key + "=" + globalProfileParser.get('alterations', 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
#Check if we have a configuration file loaded, else load the default.\r
#########################################################\r
## Alteration file functions\r
#########################################################\r
-def getCuraBasePath():\r
- return os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))\r
-\r
-def getAlterationFilePath(filename):\r
- return os.path.join(getCuraBasePath(), "alterations", filename)\r
-\r
def replaceTagMatch(m):\r
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
\r
-def getAlterationFileContents(filename, modifyForOutput = True):\r
- "Get the file from the fileName or the lowercase fileName in the alterations directories."\r
+### Get aleration raw contents. (Used internally in Cura)\r
+def getAlterationFile(filename):\r
+ #Check if we have a configuration file loaded, else load the default.\r
+ if not globals().has_key('globalProfileParser'):\r
+ loadGlobalProfile(getDefaultProfilePath())\r
+ \r
+ if not globalProfileParser.has_option('alterations', filename):\r
+ if filename in alterationDefault:\r
+ default = alterationDefault[filename]\r
+ else:\r
+ print "Missing default alteration for: '" + filename + "'"\r
+ alterationDefault[filename] = ''\r
+ default = ''\r
+ if not globalProfileParser.has_section('alterations'):\r
+ globalProfileParser.add_section('alterations')\r
+ #print "Using default for: %s" % (filename)\r
+ globalProfileParser.set('alterations', filename, default)\r
+ return unicode(globalProfileParser.get('alterations', filename), "utf-8")\r
+\r
+def setAlterationFile(filename, value):\r
+ #Check if we have a configuration file loaded, else load the default.\r
+ if not globals().has_key('globalProfileParser'):\r
+ loadGlobalProfile(getDefaultProfilePath())\r
+ if not globalProfileParser.has_section('alterations'):\r
+ globalProfileParser.add_section('alterations')\r
+ globalProfileParser.set('alterations', filename, value.encode("utf-8"))\r
+ saveGlobalProfile(profile.getDefaultProfilePath())\r
+\r
+### Get the alteration file for output. (Used by Skeinforge)\r
+def getAlterationFileContents(filename):\r
prefix = ''\r
- if modifyForOutput:\r
- if filename == 'start.gcode':\r
- #For the start code, hack the temperature and the steps per E value into it. So the temperature is reached before the start code extrusion.\r
- #We also set our steps per E here, if configured.\r
- eSteps = float(getPreference('steps_per_e'))\r
- if eSteps > 0:\r
- prefix += 'M92 E'+str(eSteps)+'\n'\r
- temp = getProfileSettingFloat('print_temperature')\r
- if temp > 0:\r
- prefix += 'M109 S'+str(temp)+'\n'\r
- elif filename == 'replace.csv':\r
- prefix = 'M101\nM103\n'\r
- fullFilename = getAlterationFilePath(filename)\r
- if os.path.isfile(fullFilename):\r
- file = open(fullFilename, "r")\r
- fileText = file.read()\r
- file.close()\r
- if modifyForOutput:\r
- fileText = re.sub("\{[^\}]*\}", replaceTagMatch, fileText)\r
- return prefix + fileText\r
- return prefix\r
+ if filename == 'start.gcode':\r
+ #For the start code, hack the temperature and the steps per E value into it. So the temperature is reached before the start code extrusion.\r
+ #We also set our steps per E here, if configured.\r
+ eSteps = float(getPreference('steps_per_e'))\r
+ if eSteps > 0:\r
+ prefix += 'M92 E%f\n' % (eSteps)\r
+ temp = getProfileSettingFloat('print_temperature')\r
+ if temp > 0:\r
+ prefix += 'M109 S%f\n' % (temp)\r
+ elif filename == 'replace.csv':\r
+ #Always remove the extruder on/off M codes. These are no longer needed in 5D printing.\r
+ prefix = 'M101\nM103\n'\r
+ \r
+ return prefix + re.sub("\{[^\}]*\}", replaceTagMatch, getAlterationFile(filename))\r
\r