From 0afcc88bd46da839aa09c4f28662cf1c210cc5d7 Mon Sep 17 00:00:00 2001 From: Kliment Yanev Date: Fri, 18 Nov 2011 09:52:16 +0100 Subject: [PATCH] Integrate plating into pronterface UI --- plater.py | 59 +++++++++++++++++++++----------- pronsole.py | 31 ++++++++--------- pronterface.py | 91 ++++++++++++++++++++++++++++++++++---------------- xybuttons.py | 10 +++--- zbuttons.py | 6 ++-- 5 files changed, 123 insertions(+), 74 deletions(-) diff --git a/plater.py b/plater.py index 10842c0..4349bf4 100755 --- a/plater.py +++ b/plater.py @@ -159,8 +159,8 @@ class showstl(wx.Window): #s.export() class stlwin(wx.Frame): - def __init__(self,size=(800,580)): - wx.Frame.__init__(self,None,title="Plate building tool",size=size) + def __init__(self,size=(800,580),callback=None,parent=None): + wx.Frame.__init__(self,parent,title="Plate building tool",size=size) self.SetIcon(wx.Icon("plater.ico",wx.BITMAP_TYPE_ICO)) self.mainsizer = wx.BoxSizer(wx.HORIZONTAL) self.panel=wx.Panel(self,-1,size=(150,600),pos=(0,0)) @@ -168,14 +168,20 @@ class stlwin(wx.Frame): self.l=wx.ListBox(self.panel,size=(300,180),pos=(0,30)) self.cl=wx.Button(self.panel,label="Clear",pos=(0,205)) self.lb=wx.Button(self.panel,label="Load",pos=(0,0)) - self.eb=wx.Button(self.panel,label="Export",pos=(100,0)) + if(callback is None): + self.eb=wx.Button(self.panel,label="Export",pos=(100,0)) + self.eb.Bind(wx.EVT_BUTTON,self.export) + else: + self.eb=wx.Button(self.panel,label="Done",pos=(100,0)) + self.eb.Bind(wx.EVT_BUTTON,lambda e:self.done(e,callback)) + self.eb=wx.Button(self.panel,label="Cancel",pos=(200,0)) + self.eb.Bind(wx.EVT_BUTTON,self.Destroy) self.sb=wx.Button(self.panel,label="Snap to Z=0",pos=(00,255)) self.cb=wx.Button(self.panel,label="Put at 100,100",pos=(0,280)) self.db=wx.Button(self.panel,label="Delete",pos=(0,305)) self.ab=wx.Button(self.panel,label="Auto",pos=(0,330)) self.cl.Bind(wx.EVT_BUTTON,self.clear) self.lb.Bind(wx.EVT_BUTTON,self.right) - self.eb.Bind(wx.EVT_BUTTON,self.export) self.sb.Bind(wx.EVT_BUTTON,self.snap) self.cb.Bind(wx.EVT_BUTTON,self.center) self.db.Bind(wx.EVT_BUTTON,self.delete) @@ -266,28 +272,43 @@ class stlwin(wx.Frame): self.l.Select(self.l.GetCount()-1) self.Refresh() + def done(self,event,cb): + import os,time + try: + os.mkdir("tempstl") + except: + pass + name="tempstl/"+str(int(time.time())%10000)+".stl" + self.writefiles(name) + if cb is not None: + cb(name) + self.Destroy() + + def export(self,event): dlg=wx.FileDialog(self,"Pick file to save to",self.basedir,style=wx.FD_SAVE) dlg.SetWildcard("STL files (;*.stl;)") if(dlg.ShowModal() == wx.ID_OK): name=dlg.GetPath() - sf=open(name.replace(".","_")+".scad","w") + self.writefiles(name) - facets=[] - for i in self.models.values(): - - r=i.rot - o=i.offsets - sf.write('translate([%s,%s,%s]) rotate([0,0,%s]) import_stl("%s");\n'%(str(o[0]),str(o[1]),str(o[2]),r,os.path.split(i.filename)[1])) - if r != 0: - i=i.rotate([0,0,r]) - if o != [0,0,0]: - i=i.translate([o[0],o[1],o[2]]) - facets+=i.facets - sf.close() - stltool.emitstl(name,facets,"plater_export") - print "wrote ",name + def writefiles(self,name): + sf=open(name.replace(".","_")+".scad","w") + facets=[] + for i in self.models.values(): + r=i.rot + o=i.offsets + sf.write('translate([%s,%s,%s]) rotate([0,0,%s]) import_stl("%s");\n'%(str(o[0]),str(o[1]),str(o[2]),r,os.path.split(i.filename)[1])) + if r != 0: + i=i.rotate([0,0,r]) + if o != [0,0,0]: + i=i.translate([o[0],o[1],o[2]]) + facets+=i.facets + sf.close() + stltool.emitstl(name,facets,"plater_export") + print "wrote ",name + def right(self,event): dlg=wx.FileDialog(self,"Pick file to load",self.basedir,style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) dlg.SetWildcard("STL files (;*.stl;)|*.stl|OpenSCAD files (;*.scad;)|*.scad") diff --git a/pronsole.py b/pronsole.py index fd3be45..1c6b046 100755 --- a/pronsole.py +++ b/pronsole.py @@ -153,6 +153,9 @@ class Settings: self.xy_feedrate = 3000 self.z_feedrate = 200 self.e_feedrate = 300 + self.slicecommand="python skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py $s" + self.sliceoptscommand="python skeinforge/skeinforge_application/skeinforge.py" + def _set(self,key,value): try: value = getattr(self,"_%s_alias"%key)()[value] @@ -1070,6 +1073,9 @@ class pronsole(cmd.Cmd): print "monitor - Reports temperature and SD print status (if SD printing) every 5 seconds" print "monitor 2 - Reports temperature and SD print status (if SD printing) every 2 seconds" + def expandcommand(self,c): + return c.replace("$python",sys.executable) + def do_skein(self,l): l=l.split() if len(l)==0: @@ -1083,27 +1089,16 @@ class pronsole(cmd.Cmd): if not(os.path.exists(l[0])): print "File not found!" return - if not os.path.exists("skeinforge"): - print "Skeinforge not found. \nPlease copy Skeinforge into a directory named \"skeinforge\" in the same directory as this file." - return - if not os.path.exists("skeinforge/__init__.py"): - f=open("skeinforge/__init__.py","w") - f.close() try: - from skeinforge.skeinforge_application.skeinforge_utilities import skeinforge_craft - from skeinforge.skeinforge_application import skeinforge + import shlex if(settings): - param = "skeinforge/skeinforge_application/skeinforge.py" - print "Entering skeinforge settings: ",sys.executable," ",param - subprocess.call([sys.executable,param]) + param = self.expandcommand(self.settings.sliceoptscommand).encode() + print "Entering skeinforge settings: ",param + subprocess.call(shlex.split(param)) else: - if(len(l)>1): - if(l[1] == "view"): - skeinforge_craft.writeOutput(l[0],True) - else: - skeinforge_craft.writeOutput(l[0],False) - else: - skeinforge_craft.writeOutput(l[0],False) + param = self.expandcommand(self.settings.slicecommand).replace("$s",l[0]).replace("$o",l[0].replace(".stl","_export.gcode").replace(".STL","_export.gcode")).encode() + print "Slicing: ",param + subprocess.call(shlex.split(param)) print "Loading skeined file." self.do_load(l[0].replace(".stl","_export.gcode")) except Exception,e: diff --git a/pronterface.py b/pronterface.py index 4487a0f..014ee5c 100755 --- a/pronterface.py +++ b/pronterface.py @@ -14,11 +14,12 @@ try: except: print _("WX is not installed. This program requires WX to run.") raise -import printcore, sys, glob, time, threading, traceback, StringIO, gviz, traceback, cStringIO +import printcore, sys, glob, time, threading, traceback, gviz, traceback, cStringIO, subprocess try: os.chdir(os.path.split(__file__)[0]) except: pass +StringIO=cStringIO thread=threading.Thread winsize=(800,500) @@ -71,6 +72,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): self.statuscheck=False self.tempreport="" self.monitor=0 + self.skeinp=None self.monitor_interval=3 self.paused=False xcol=(245,245,108) @@ -110,6 +112,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): self.popwindow() self.t=Tee(self.catchprint) self.stdout=sys.stdout + self.skeining=0 self.mini=False self.p.sendcb=self.sentcb self.p.startcb=self.startcb @@ -305,12 +308,12 @@ class PronterWindow(wx.Frame,pronsole.pronsole): self.Bind(wx.EVT_MENU, self.new_macro, self.macros_menu.Append(-1, _("<&New...>"))) self.Bind(wx.EVT_MENU, lambda *e:options(self), m.Append(-1,_("&Options"),_(" Options dialog"))) - self.Bind(wx.EVT_MENU, lambda x:threading.Thread(target=lambda :self.do_skein("set")).start(), m.Append(-1,_("SFACT Settings"),_(" Adjust SFACT settings"))) - try: - from SkeinforgeQuickEditDialog import SkeinforgeQuickEditDialog - self.Bind(wx.EVT_MENU, lambda *e:SkeinforgeQuickEditDialog(self), m.Append(-1,_("SFACT Quick Settings"),_(" Quickly adjust SFACT settings for active profile"))) - except: - pass + self.Bind(wx.EVT_MENU, lambda x:threading.Thread(target=lambda :self.do_skein("set")).start(), m.Append(-1,_("Slicing Settings"),_(" Adjust slicing settings"))) + #try: + # from SkeinforgeQuickEditDialog import SkeinforgeQuickEditDialog + # self.Bind(wx.EVT_MENU, lambda *e:SkeinforgeQuickEditDialog(self), m.Append(-1,_("SFACT Quick Settings"),_(" Quickly adjust SFACT settings for active profile"))) + #except: + # pass self.menustrip.Append(m,_("&Settings")) self.update_macros_menu() @@ -447,7 +450,6 @@ class PronterWindow(wx.Frame,pronsole.pronsole): # elif e.GetWheelRotation()<0: # self.do_settemp(str(max(0,self.hsetpoint-1))) #self.tgauge.Bind(wx.EVT_MOUSEWHEEL,scroll_setpoint) - uts.Add((10,-1)) self.monitorbox=wx.CheckBox(self.panel,-1,"",pos=(450,37)) uts.Add((15,-1)) @@ -465,14 +467,14 @@ class PronterWindow(wx.Frame,pronsole.pronsole): self.loadbtn=wx.Button(self.panel,-1,_("Load file"),pos=(0,40)) self.loadbtn.Bind(wx.EVT_BUTTON,self.loadfile) ubs.Add(self.loadbtn) - self.uploadbtn=wx.Button(self.panel,-1,_("SD Upload"),pos=(90,40)) - self.uploadbtn.Bind(wx.EVT_BUTTON,self.upload) - self.printerControls.append(self.uploadbtn) - ubs.Add(self.uploadbtn) - self.sdprintbtn=wx.Button(self.panel,-1,_("SD Print"),pos=(180,40)) - self.sdprintbtn.Bind(wx.EVT_BUTTON,self.sdprintfile) - self.printerControls.append(self.sdprintbtn) - ubs.Add(self.sdprintbtn) + self.platebtn=wx.Button(self.panel,-1,_("Compose"),pos=(90,40)) + self.platebtn.Bind(wx.EVT_BUTTON,self.plate) + #self.printerControls.append(self.uploadbtn) + ubs.Add(self.platebtn) + self.sdbtn=wx.Button(self.panel,-1,_("SD"),pos=(180,40),size=(-1,-1)) + self.sdbtn.Bind(wx.EVT_BUTTON,self.sdmenu) + self.printerControls.append(self.sdbtn) + ubs.Add(self.sdbtn) self.printbtn=wx.Button(self.panel,-1,_("Print"),pos=(270,40)) self.printbtn.Bind(wx.EVT_BUTTON,self.printfile) self.printbtn.Disable() @@ -606,6 +608,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): self.zfeedc.SetBackgroundColour((180,255,180)) self.zfeedc.SetForegroundColour("black") # lls.Add((10,0),pos=(0,11),span=(1,1)) + self.gviz=gviz.gviz(self.panel,(300,300), bedsize=(self.settings.bed_size_x,self.settings.bed_size_y), grid=(self.settings.preview_grid_step1,self.settings.preview_grid_step2), @@ -636,6 +639,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): self.status.SetStatusText(_("Not connected to printer.")) self.panel.Bind(wx.EVT_MOUSE_EVENTS,self.editbutton) self.Bind(wx.EVT_CLOSE, self.kill) + self.topsizer.Layout() self.topsizer.Fit(self) @@ -648,6 +652,24 @@ class PronterWindow(wx.Frame,pronsole.pronsole): #uts.Layout() self.cbuttons_reload() + def plate(self,e): + import plater + print "plate function activated" + plater.stlwin(size=(800,580),callback=self.platecb,parent=self).Show() + + def platecb(self,name): + print "plated: "+name + self.loadfile(None,name) + + def sdmenu(self,e): + obj = e.GetEventObject() + popupmenu=wx.Menu() + item = popupmenu.Append(-1,_("SD Upload")) + self.Bind(wx.EVT_MENU,self.upload) + item = popupmenu.Append(-1,_("SD Print")) + self.Bind(wx.EVT_MENU,self.sdprintfile) + self.panel.PopupMenu(popupmenu, obj.GetPosition()) + def htemp_change(self,event): if self.hsetpoint > 0: self.do_settemp("") @@ -1196,11 +1218,20 @@ class PronterWindow(wx.Frame,pronsole.pronsole): def skein_func(self): try: - from skeinforge.skeinforge_application.skeinforge_utilities import skeinforge_craft - from skeinforge.skeinforge_application import skeinforge - from skeinforge.fabmetheus_utilities import settings - skeinforge_craft.writeOutput(self.filename,False) - #print len(self.cout.getvalue().split()) + import shlex + param = self.expandcommand(self.settings.slicecommand).replace("$s",self.filename).replace("$o",self.filename.replace(".stl","_export.gcode").replace(".STL","_export.gcode")).encode() + print shlex.split(param) + print "Slicing: ",param + self.cancelskein=0 + #p=subprocess.Popen(param,shell=True,bufsize=10,stderr=subprocess.STDOUT,stdout=subprocess.PIPE,close_fds=True) + pararray=shlex.split(param) + #print pararray + self.skeinp=subprocess.Popen(pararray,stderr=subprocess.STDOUT,stdout=subprocess.PIPE) + while True: + o = self.skeinp.stdout.read(1) + if o == '' and self.skeinp.poll() != None: break + sys.stdout.write(o) + self.skeinp.wait() self.stopsf=1 except: print _("Skeinforge execution failed.") @@ -1210,7 +1241,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): def skein_monitor(self): while(not self.stopsf): try: - wx.CallAfter(self.status.SetStatusText,_("Skeining..."))#+self.cout.getvalue().split("\n")[-1]) + wx.CallAfter(self.status.SetStatusText,_("Slicing..."))#+self.cout.getvalue().split("\n")[-1]) except: pass time.sleep(0.1) @@ -1230,22 +1261,24 @@ class PronterWindow(wx.Frame,pronsole.pronsole): threading.Thread(target=self.loadviz).start() except: self.filename=fn + wx.CallAfter(self.loadbtn.SetLabel,_("Load File")) + wx.CallAfter(self.status.SetStatusText,_("Slicing cancelled.")) + def skein(self,filename): - print _("Skeining ") + filename - if not os.path.exists("skeinforge"): - print _("Skeinforge not found. \nPlease copy Skeinforge into a directory named \"skeinforge\" in the same directory as this file.") - return - if not os.path.exists("skeinforge/__init__.py"): - f=open("skeinforge/__init__.py","w") - f.close() + wx.CallAfter(self.loadbtn.SetLabel,_("Cancel")) + print _("Slicing ") + filename self.cout=StringIO.StringIO() self.filename=filename self.stopsf=0 + self.skeining=1 thread(target=self.skein_func).start() thread(target=self.skein_monitor).start() def loadfile(self,event,filename=None): + if self.skeining and self.skeinp is not None: + self.skeinp.terminate() + return basedir=self.settings.last_file_path if not os.path.exists(basedir): basedir = "." diff --git a/xybuttons.py b/xybuttons.py index 50b5575..0a91b05 100644 --- a/xybuttons.py +++ b/xybuttons.py @@ -38,9 +38,8 @@ class XYButtons(BufferedCanvas): self.moveCallback = moveCallback self.cornerCallback = cornerCallback self.enabled = False - + BufferedCanvas.__init__(self, parent, ID) - self.SetSize(self.bg_bmp.GetSize()) # Set up mouse and keyboard event capture @@ -192,8 +191,9 @@ class XYButtons(BufferedCanvas): gc = wx.GraphicsContext.Create(dc) center = wx.Point(XYButtons.center[0], XYButtons.center[1]) - w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight()) - gc.DrawBitmap(self.bg_bmp, 0, 0, w, h) + if self.bg_bmp: + w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight()) + gc.DrawBitmap(self.bg_bmp, 0, 0, w, h) if self.enabled: # Brush and pen for grey overlay when mouse hovers over @@ -327,4 +327,4 @@ class XYButtons(BufferedCanvas): def OnLeaveWindow(self, evt): self.quadrant = None self.concentric = None - self.update() \ No newline at end of file + self.update() diff --git a/zbuttons.py b/zbuttons.py index c5e0887..567f1a8 100644 --- a/zbuttons.py +++ b/zbuttons.py @@ -75,9 +75,9 @@ class ZButtons(BufferedCanvas): def draw(self, dc, w, h): dc.Clear() gc = wx.GraphicsContext.Create(dc) - w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight()) - - gc.DrawBitmap(self.bg_bmp, 0, 0, w, h) + if self.bg_bmp: + w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight()) + gc.DrawBitmap(self.bg_bmp, 0, 0, w, h) if self.enabled: # Draw label overlays