from __future__ import absolute_import\r
import __init__\r
\r
-import wx, os, platform, types, webbrowser, math, subprocess\r
+import wx, os, platform, types, webbrowser, math, subprocess, threading, time\r
import ConfigParser\r
\r
from wx import glcanvas\r
from util import stl\r
from util import sliceRun\r
\r
+class Action():\r
+ pass\r
+\r
class projectPlanner(wx.Frame):\r
"Main user interface window"\r
def __init__(self):\r
put('add_start_end_gcode', 'False')\r
put('gcode_extension', 'project_tmp')\r
\r
+ clearZ = 0\r
+ actionList = []\r
for item in self.list:\r
put('machine_center_x', item.centerX)\r
put('machine_center_y', item.centerY)\r
put('swap_xz', item.swapXZ)\r
put('swap_yz', item.swapYZ)\r
\r
- item.sliceCmd = sliceRun.getSliceCommand(item.filename)\r
+ action = Action()\r
+ action.sliceCmd = sliceRun.getSliceCommand(item.filename)\r
+ action.centerX = item.centerX\r
+ action.centerY = item.centerY\r
+ action.filename = item.filename\r
+ clearZ = max(clearZ, item.getMaximum().z * item.scale)\r
+ action.clearZ = clearZ\r
+ actionList.append(action)\r
\r
#Restore the old profile.\r
profile.loadGlobalProfileFromString(oldProfile)\r
if dlg.ShowModal() != wx.ID_OK:\r
dlg.Destroy()\r
return\r
- resultFile = open(dlg.GetPath(), "w")\r
+ resultFilename = dlg.GetPath()\r
dlg.Destroy()\r
\r
- i = 1\r
- maxZ = 0\r
- prevItem = None\r
- for item in self.list:\r
- subprocess.call(item.sliceCmd)\r
- \r
- maxZ = max(maxZ, item.getMaximum().z * item.scale)\r
- put('machine_center_x', item.centerX)\r
- put('machine_center_y', item.centerY)\r
- put('clear_z', maxZ)\r
- \r
- if prevItem == None:\r
- resultFile.write(';TYPE:CUSTOM\n')\r
- resultFile.write(profile.getAlterationFileContents('start.gcode'))\r
- else:\r
- #reset the extrusion length, and move to the next object center.\r
- resultFile.write(';TYPE:CUSTOM\n')\r
- resultFile.write(profile.getAlterationFileContents('nextobject.gcode'))\r
- resultFile.write(';PRINTNR:%d\n' % (i))\r
- profile.loadGlobalProfileFromString(oldProfile)\r
- \r
- f = open(item.filename[: item.filename.rfind('.')] + "_export.project_tmp", "r")\r
- data = f.read(4096)\r
- while data != '':\r
- resultFile.write(data)\r
- data = f.read(4096)\r
- f.close()\r
- os.remove(item.filename[: item.filename.rfind('.')] + "_export.project_tmp")\r
- i += 1\r
- \r
- prevItem = item\r
- \r
- resultFile.write(';TYPE:CUSTOM\n')\r
- resultFile.write(profile.getAlterationFileContents('end.gcode'))\r
- resultFile.close()\r
+ pspw = ProjectSliceProgressWindow(actionList, resultFilename)\r
+ pspw.Centre()\r
+ pspw.Show(True)\r
\r
def loadModelFile(self, item):\r
item.load(item.filename)\r
\r
glFlush()\r
\r
+class ProjectSliceProgressWindow(wx.Frame):\r
+ def __init__(self, actionList, resultFilename):\r
+ super(ProjectSliceProgressWindow, self).__init__(None, title='Cura')\r
+ self.actionList = actionList\r
+ self.resultFilename = resultFilename\r
+ self.abort = False\r
+ self.prevStep = 'start'\r
+ self.totalDoneFactor = 0.0\r
+ self.startTime = time.time()\r
+ \r
+ #How long does each step take compared to the others. This is used to make a better scaled progress bar, and guess time left.\r
+ # TODO: Duplicate with sliceProgressPanel, move to sliceRun.\r
+ self.sliceStepTimeFactor = {\r
+ 'start': 3.3713991642,\r
+ 'slice': 15.4984838963,\r
+ 'preface': 5.17178297043,\r
+ 'inset': 116.362634182,\r
+ 'fill': 215.702672005,\r
+ 'multiply': 21.9536788464,\r
+ 'speed': 12.759510994,\r
+ 'raft': 31.4580039978,\r
+ 'skirt': 19.3436040878,\r
+ 'skin': 1.0,\r
+ 'joris': 1.0,\r
+ 'comb': 23.7805759907,\r
+ 'cool': 27.148763895,\r
+ 'dimension': 90.4914340973\r
+ }\r
+ self.totalRunTimeFactor = 0\r
+ for v in self.sliceStepTimeFactor.itervalues():\r
+ self.totalRunTimeFactor += v\r
+ \r
+ self.sizer = wx.GridBagSizer(2, 2) \r
+ self.statusText = wx.StaticText(self, -1, "Building: %s" % (resultFilename))\r
+ self.progressGauge = wx.Gauge(self, -1)\r
+ self.progressGauge.SetRange(10000)\r
+ self.progressGauge2 = wx.Gauge(self, -1)\r
+ self.progressGauge2.SetRange(len(self.actionList))\r
+ self.abortButton = wx.Button(self, -1, "Abort")\r
+ 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
+ self.sizer.Add(self.abortButton, (3,0), flag=wx.ALIGN_CENTER)\r
+\r
+ self.Bind(wx.EVT_BUTTON, self.OnAbort, self.abortButton)\r
+ self.SetSizer(self.sizer)\r
+ self.Layout()\r
+ self.Fit()\r
+ \r
+ threading.Thread(target=self.OnRun).start()\r
+\r
+ def OnAbort(self, e):\r
+ self.abort = True\r
+\r
+ def SetProgress(self, stepName, layer, maxLayer):\r
+ if self.prevStep != stepName:\r
+ self.totalDoneFactor += self.sliceStepTimeFactor[self.prevStep]\r
+ newTime = time.time()\r
+ #print "#####" + str(newTime-self.startTime) + " " + self.prevStep + " -> " + stepName\r
+ self.startTime = newTime\r
+ self.prevStep = stepName\r
+ \r
+ progresValue = ((self.totalDoneFactor + self.sliceStepTimeFactor[stepName] * layer / maxLayer) / self.totalRunTimeFactor) * 10000\r
+ self.progressGauge.SetValue(int(progresValue))\r
+ self.statusText.SetLabel(stepName + " [" + str(layer) + "/" + str(maxLayer) + "]")\r
+ \r
+ def OnRun(self):\r
+ resultFile = open(self.resultFilename, "w")\r
+ put = profile.putProfileSetting\r
+ for action in self.actionList:\r
+ p = subprocess.Popen(action.sliceCmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\r
+ line = p.stdout.readline()\r
+ \r
+ maxValue = 1\r
+ self.progressLog = []\r
+ while(len(line) > 0):\r
+ line = line.rstrip()\r
+ if line[0:9] == "Progress[" and line[-1:] == "]":\r
+ progress = line[9:-1].split(":")\r
+ if len(progress) > 2:\r
+ maxValue = int(progress[2])\r
+ wx.CallAfter(self.SetProgress, progress[0], int(progress[1]), maxValue)\r
+ else:\r
+ print line\r
+ self.progressLog.append(line)\r
+ wx.CallAfter(self.statusText.SetLabel, line)\r
+ if self.abort:\r
+ p.terminate()\r
+ wx.CallAfter(self.statusText.SetLabel, "Aborted by user.")\r
+ return\r
+ line = p.stdout.readline()\r
+ self.returnCode = p.wait()\r
+ \r
+ oldProfile = profile.getGlobalProfileString()\r
+ put('machine_center_x', action.centerX)\r
+ put('machine_center_y', action.centerY)\r
+ put('clear_z', action.clearZ)\r
+ \r
+ if action == self.actionList[0]:\r
+ resultFile.write(';TYPE:CUSTOM\n')\r
+ resultFile.write(profile.getAlterationFileContents('start.gcode'))\r
+ else:\r
+ #reset the extrusion length, and move to the next object center.\r
+ 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
+ \r
+ f = open(action.filename[: action.filename.rfind('.')] + "_export.project_tmp", "r")\r
+ data = f.read(4096)\r
+ while data != '':\r
+ resultFile.write(data)\r
+ data = f.read(4096)\r
+ f.close()\r
+ os.remove(action.filename[: action.filename.rfind('.')] + "_export.project_tmp")\r
+ \r
+ wx.CallAfter(self.progressGauge.SetValue, 10000)\r
+ wx.CallAfter(self.progressGauge2.SetValue, self.actionList.index(action) + 1)\r
+ \r
+ resultFile.write(';TYPE:CUSTOM\n')\r
+ resultFile.write(profile.getAlterationFileContents('end.gcode'))\r
+ resultFile.close()\r
+\r
def main():\r
app = wx.App(False)\r
projectPlanner().Show(True)\r