Run reindent.py on the whole repository
parent
ec596c5ab6
commit
8cc134955f
28
plater.py
28
plater.py
|
@ -1,17 +1,17 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of the Printrun suite.
|
||||
#
|
||||
#
|
||||
# Printrun is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Printrun is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
@ -336,25 +336,25 @@ class stlwin(wx.Frame):
|
|||
def center(self, event):
|
||||
i = self.l.GetSelection()
|
||||
if i != -1:
|
||||
m = self.models[self.l.GetString(i)]
|
||||
m.offsets = [100, 100, m.offsets[2]]
|
||||
self.Refresh()
|
||||
m = self.models[self.l.GetString(i)]
|
||||
m.offsets = [100, 100, m.offsets[2]]
|
||||
self.Refresh()
|
||||
|
||||
def snap(self, event):
|
||||
i = self.l.GetSelection()
|
||||
if i != -1:
|
||||
m = self.models[self.l.GetString(i)]
|
||||
m.offsets[2] = -1.0 * min(m.facetsminz)[0]
|
||||
#print m.offsets[2]
|
||||
self.Refresh()
|
||||
m = self.models[self.l.GetString(i)]
|
||||
m.offsets[2] = -1.0 * min(m.facetsminz)[0]
|
||||
#print m.offsets[2]
|
||||
self.Refresh()
|
||||
|
||||
def delete(self, event):
|
||||
i = self.l.GetSelection()
|
||||
if i != -1:
|
||||
del self.models[self.l.GetString(i)]
|
||||
self.l.Delete(i)
|
||||
self.l.Select(self.l.GetCount() - 1)
|
||||
self.Refresh()
|
||||
del self.models[self.l.GetString(i)]
|
||||
self.l.Delete(i)
|
||||
self.l.Select(self.l.GetCount() - 1)
|
||||
self.Refresh()
|
||||
|
||||
def done(self, event, cb):
|
||||
try:
|
||||
|
|
42
printcore.py
42
printcore.py
|
@ -1,17 +1,17 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of the Printrun suite.
|
||||
#
|
||||
#
|
||||
# Printrun is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Printrun is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
@ -45,7 +45,7 @@ class printcore():
|
|||
self.clear = 0 #clear to send, enabled after responses
|
||||
self.online = False #The printer has responded to the initial command and is active
|
||||
self.printing = False #is a print currently running, true if printing, false if paused
|
||||
self.mainqueue = []
|
||||
self.mainqueue = []
|
||||
self.priqueue = []
|
||||
self.queueindex = 0
|
||||
self.lineno = 0
|
||||
|
@ -69,7 +69,7 @@ class printcore():
|
|||
self.print_thread = None
|
||||
if port is not None and baud is not None:
|
||||
self.connect(port, baud)
|
||||
|
||||
|
||||
def disconnect(self):
|
||||
"""Disconnects from printer and pauses the print
|
||||
"""
|
||||
|
@ -82,7 +82,7 @@ class printcore():
|
|||
self.printer = None
|
||||
self.online = False
|
||||
self.printing = False
|
||||
|
||||
|
||||
def connect(self,port=None,baud=None):
|
||||
"""Set port and baudrate if given, then connect to printer
|
||||
"""
|
||||
|
@ -98,7 +98,7 @@ class printcore():
|
|||
self.stop_read_thread = False
|
||||
self.read_thread = Thread(target=self._listen)
|
||||
self.read_thread.start()
|
||||
|
||||
|
||||
def reset(self):
|
||||
"""Reset the printer
|
||||
"""
|
||||
|
@ -106,7 +106,7 @@ class printcore():
|
|||
self.printer.setDTR(1)
|
||||
time.sleep(0.2)
|
||||
self.printer.setDTR(0)
|
||||
|
||||
|
||||
def _readline(self):
|
||||
try:
|
||||
line = self.printer.readline()
|
||||
|
@ -164,11 +164,11 @@ class printcore():
|
|||
self.clear = True
|
||||
if line.startswith('ok') and "T:" in line and self.tempcb:
|
||||
#callback for temp, status, whatever
|
||||
try: self.tempcb(line)
|
||||
except: pass
|
||||
try: self.tempcb(line)
|
||||
except: pass
|
||||
elif line.startswith('Error'):
|
||||
if self.errorcb:
|
||||
#callback for errors
|
||||
#callback for errors
|
||||
try: self.errorcb(line)
|
||||
except: pass
|
||||
if line.lower().startswith("resend") or line.startswith("rs"):
|
||||
|
@ -181,10 +181,10 @@ class printcore():
|
|||
self.resendfrom = toresend
|
||||
self.clear = True
|
||||
self.clear = True
|
||||
|
||||
|
||||
def _checksum(self, command):
|
||||
return reduce(lambda x,y:x^y, map(ord, command))
|
||||
|
||||
|
||||
def startprint(self, data, startindex = 0):
|
||||
"""Start a print, data is an array of gcode commands.
|
||||
returns True on success, False if already printing.
|
||||
|
@ -205,7 +205,7 @@ class printcore():
|
|||
self.print_thread = Thread(target = self._print)
|
||||
self.print_thread.start()
|
||||
return True
|
||||
|
||||
|
||||
def pause(self):
|
||||
"""Pauses the print, saving the current position.
|
||||
"""
|
||||
|
@ -213,7 +213,7 @@ class printcore():
|
|||
self.printing = False
|
||||
self.print_thread.join()
|
||||
self.print_thread = None
|
||||
|
||||
|
||||
def resume(self):
|
||||
"""Resumes a paused print.
|
||||
"""
|
||||
|
@ -221,11 +221,11 @@ class printcore():
|
|||
self.printing = True
|
||||
self.print_thread = Thread(target = self._print)
|
||||
self.print_thread.start()
|
||||
|
||||
|
||||
def send(self, command, wait = 0):
|
||||
"""Adds a command to the checksummed main command queue if printing, or sends the command immediately if not printing
|
||||
"""
|
||||
|
||||
|
||||
if self.online:
|
||||
if self.printing:
|
||||
self.mainqueue.append(command)
|
||||
|
@ -243,7 +243,7 @@ class printcore():
|
|||
wait -= 1
|
||||
else:
|
||||
print "Not connected to printer."
|
||||
|
||||
|
||||
def send_now(self, command, wait = 0):
|
||||
"""Sends a command to the printer ahead of the command queue, without a checksum
|
||||
"""
|
||||
|
@ -263,7 +263,7 @@ class printcore():
|
|||
wait -= 1
|
||||
else:
|
||||
print "Not connected to printer."
|
||||
|
||||
|
||||
def _print(self):
|
||||
if self.startcb:
|
||||
#callback for printing started
|
||||
|
@ -278,7 +278,7 @@ class printcore():
|
|||
#callback for printing done
|
||||
try: self.endcb()
|
||||
except: pass
|
||||
|
||||
|
||||
def _sendnext(self):
|
||||
if not self.printer:
|
||||
return
|
||||
|
@ -313,7 +313,7 @@ class printcore():
|
|||
self.queueindex = 0
|
||||
self.lineno = 0
|
||||
self._send("M110", -1, True)
|
||||
|
||||
|
||||
def _send(self, command, lineno = 0, calcchecksum = False):
|
||||
if calcchecksum:
|
||||
prefix = "N" + str(lineno) + " " + command
|
||||
|
|
|
@ -16,13 +16,13 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
|
|||
self.cancelButton = wx.Button(self, wx.ID_CANCEL, "")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnExit, self.cancelButton)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnSave, self.okButton)
|
||||
|
||||
|
||||
"""
|
||||
The following list determines which settings are shown.
|
||||
The dictionary key is the plugin name and the value is a list of setting names as found in the corresponding .csv file for that plugin.
|
||||
|
||||
|
||||
NOTE: Skeinforge is tightly integrated with Tkinter and there appears to be a dependency which stops radio-button values from being saved.
|
||||
Perhaps this can be solved, but at the moment this dialog cannot modify radio button values. One will have to use the main Skeinforge application.
|
||||
Perhaps this can be solved, but at the moment this dialog cannot modify radio button values. One will have to use the main Skeinforge application.
|
||||
"""
|
||||
self.moduleSettingsMap = {
|
||||
'dimension':['Filament Diameter (mm):','Retraction Distance (millimeters):', 'Retraction Distance (millimeters):','Extruder Retraction Speed (mm/s):'],
|
||||
|
@ -34,28 +34,28 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
|
|||
'raft':['First Layer Main Feedrate (mm/s):','First Layer Perimeter Feedrate (mm/s):','First Layer Flow Rate Infill(scaler):','First Layer Flow Rate Perimeter(scaler):',],
|
||||
'speed':['Main Feed Rate (mm/s):','Main Flow Rate (scaler):','Perimeter Feed Rate (mm/s):','Perimeter Flow Rate (scaler):','Travel Feed Rate (mm/s):']
|
||||
}
|
||||
|
||||
|
||||
self.scrollbarPanel = wx.ScrolledWindow(self, -1, style=wx.TAB_TRAVERSAL)
|
||||
self.settingsSizer = self.getProfileSettings()
|
||||
self.scrollbarPanel.SetSizer(self.settingsSizer)
|
||||
|
||||
self.__set_properties()
|
||||
self.__do_layout()
|
||||
self.__set_properties()
|
||||
self.__do_layout()
|
||||
self.Show()
|
||||
|
||||
|
||||
def __set_properties(self):
|
||||
self.profileName = skeinforge_profile.getProfileName(skeinforge_profile.getCraftTypeName())
|
||||
self.SetTitle("Skeinforge Quick Edit Profile: " + self.profileName)
|
||||
|
||||
# For some reason the dialog size is not consistent between Windows and Linux - this is a hack to get it working
|
||||
|
||||
# For some reason the dialog size is not consistent between Windows and Linux - this is a hack to get it working
|
||||
if (os.name == 'nt'):
|
||||
self.SetMinSize(wx.DLG_SZE(self, (465, 370)))
|
||||
else:
|
||||
self.SetSize(wx.DLG_SZE(self, (465, 325)))
|
||||
|
||||
|
||||
self.SetPosition((0, 0))
|
||||
self.scrollbarPanel.SetScrollRate(10, 10)
|
||||
|
||||
|
||||
def __do_layout(self):
|
||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
actionsSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
@ -65,34 +65,34 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
|
|||
mainSizer.Add(actionsSizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)
|
||||
self.SetSizer(mainSizer)
|
||||
self.Layout()
|
||||
|
||||
|
||||
def getProfileSettings(self):
|
||||
settingsSizer = wx.GridBagSizer(hgap=2, vgap=1)
|
||||
settingsRow = 0
|
||||
|
||||
|
||||
for craftName in sorted(self.moduleSettingsMap.keys()):
|
||||
|
||||
|
||||
craftStaticBox = wx.StaticBox(self.scrollbarPanel, -1, craftName.capitalize())
|
||||
craftStaticBoxSizer = wx.StaticBoxSizer(craftStaticBox, wx.VERTICAL)
|
||||
|
||||
|
||||
# For some reason the dialog size is not consistent between Windows and Linux - this is a hack to get it working
|
||||
if (os.name == 'nt'):
|
||||
craftStaticBoxSizer.SetMinSize((320, -1))
|
||||
else:
|
||||
else:
|
||||
craftStaticBoxSizer.SetMinSize((450, -1))
|
||||
pluginModule = archive.getModuleWithPath(os.path.join(skeinforge_craft.getPluginsDirectoryPath(), craftName))
|
||||
repo = pluginModule.getNewRepository()
|
||||
|
||||
|
||||
for setting in settings.getReadRepository(repo).preferences:
|
||||
if setting.name in self.moduleSettingsMap[craftName]:
|
||||
|
||||
|
||||
settingSizer = wx.GridBagSizer(hgap=2, vgap=2)
|
||||
settingSizer.AddGrowableCol(0)
|
||||
settingRow = 0
|
||||
settingLabel = wx.StaticText(self.scrollbarPanel, -1, setting.name)
|
||||
settingLabel.Wrap(400)
|
||||
settingSizer.Add(settingLabel, pos=(settingRow, 0))
|
||||
|
||||
|
||||
if (isinstance(setting.value, bool)):
|
||||
checkbox = wx.CheckBox(self.scrollbarPanel)
|
||||
checkbox.SetName(craftName + '.' + setting.name)
|
||||
|
@ -103,7 +103,7 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
|
|||
textCtrl = wx.TextCtrl(self.scrollbarPanel, value=str(setting.value), size=(50, -1))
|
||||
textCtrl.SetName(craftName + '.' + setting.name)
|
||||
settingSizer.Add(textCtrl, pos=(settingRow, 1))
|
||||
|
||||
|
||||
craftStaticBoxSizer.Add(settingSizer, 1, wx.EXPAND, 0)
|
||||
settingRow += 1
|
||||
col = settingsRow % 2
|
||||
|
@ -114,7 +114,7 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
|
|||
|
||||
def OnExit(self, e):
|
||||
self.Destroy()
|
||||
|
||||
|
||||
def OnSave(self, e):
|
||||
for x in self.scrollbarPanel.GetChildren():
|
||||
if (isinstance(x, (wx.CheckBox, wx.TextCtrl))):
|
||||
|
|
|
@ -13,7 +13,7 @@ class MyFrame(wx.Frame):
|
|||
def __init__(self, parent, mysize):
|
||||
wx.Frame.__init__(self, parent, wx.ID_ANY, size=mysize)
|
||||
self.SetBackgroundColour('black')
|
||||
|
||||
|
||||
# milliseconds per frame
|
||||
self.delay = 60
|
||||
# number of loops
|
||||
|
@ -41,7 +41,7 @@ class MyFrame(wx.Frame):
|
|||
self.image_list = []
|
||||
for image_file in file_list:
|
||||
self.image_list.append(wx.Bitmap(image_file))
|
||||
|
||||
|
||||
# bind the panel to the paint event
|
||||
wx.EVT_PAINT(self, self.onPaint)
|
||||
|
||||
|
@ -73,4 +73,4 @@ width = 800
|
|||
frameoffset = 35
|
||||
height = 600 + frameoffset
|
||||
MyFrame(None, (width, height)).Show()
|
||||
app.MainLoop()
|
||||
app.MainLoop()
|
||||
|
|
|
@ -23,9 +23,9 @@ modify it under the terms of the GNU Lesser General Public License as
|
|||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
As a special exception, the copyright holders of this library
|
||||
As a special exception, the copyright holders of this library
|
||||
hereby recind Section 3 of the GNU Lesser General Public License. This
|
||||
means that you MAY NOT apply the terms of the ordinary GNU General
|
||||
means that you MAY NOT apply the terms of the ordinary GNU General
|
||||
Public License instead of this License to any given copy of the
|
||||
Library. This has been done to prevent users of the Library from being
|
||||
denied access or the ability to use future improvements.
|
||||
|
@ -94,7 +94,7 @@ class BufferedCanvas(wx.Panel):
|
|||
Causes the canvas to be updated.
|
||||
"""
|
||||
self.Refresh()
|
||||
|
||||
|
||||
def getWidthHeight(self):
|
||||
width,height = self.GetClientSizeTuple()
|
||||
if width == 0:
|
||||
|
|
|
@ -2,150 +2,150 @@
|
|||
#Interactive RepRap e axis calibration program
|
||||
#(C) Nathan Zadoks 2011
|
||||
#Licensed under CC-BY-SA or GPLv2 and higher - Pick your poison.
|
||||
s=300 #Extrusion speed (mm/min)
|
||||
n=100 #Default length to extrude
|
||||
m= 0 #User-entered measured extrusion length
|
||||
k=300 #Default amount of steps per mm
|
||||
port='/dev/ttyUSB0' #Default serial port to connect to printer
|
||||
temp=210 #Default extrusion temperature
|
||||
s=300 #Extrusion speed (mm/min)
|
||||
n=100 #Default length to extrude
|
||||
m= 0 #User-entered measured extrusion length
|
||||
k=300 #Default amount of steps per mm
|
||||
port='/dev/ttyUSB0' #Default serial port to connect to printer
|
||||
temp=210 #Default extrusion temperature
|
||||
|
||||
tempmax=250 #Maximum extrusion temperature
|
||||
tempmax=250 #Maximum extrusion temperature
|
||||
|
||||
t=int(n*60)/s #Time to wait for extrusion
|
||||
|
||||
try:
|
||||
from printdummy import printcore
|
||||
from printdummy import printcore
|
||||
except ImportError:
|
||||
from printcore import printcore
|
||||
from printcore import printcore
|
||||
import time,getopt,sys,os
|
||||
|
||||
def float_input(prompt=''):
|
||||
import sys
|
||||
f=None
|
||||
while f==None:
|
||||
s=raw_input(prompt)
|
||||
try:
|
||||
f=float(s)
|
||||
except ValueError:
|
||||
sys.stderr.write("Not a valid floating-point number.\n")
|
||||
sys.stderr.flush()
|
||||
return f
|
||||
import sys
|
||||
f=None
|
||||
while f==None:
|
||||
s=raw_input(prompt)
|
||||
try:
|
||||
f=float(s)
|
||||
except ValueError:
|
||||
sys.stderr.write("Not a valid floating-point number.\n")
|
||||
sys.stderr.flush()
|
||||
return f
|
||||
def wait(t,m=''):
|
||||
import time,sys
|
||||
sys.stdout.write(m+'['+(' '*t)+']\r'+m+'[')
|
||||
sys.stdout.flush()
|
||||
for i in range(t):
|
||||
for s in ['|\b','/\b','-\b','\\\b','|']:
|
||||
sys.stdout.write(s)
|
||||
sys.stdout.flush()
|
||||
time.sleep(1.0/5)
|
||||
print
|
||||
import time,sys
|
||||
sys.stdout.write(m+'['+(' '*t)+']\r'+m+'[')
|
||||
sys.stdout.flush()
|
||||
for i in range(t):
|
||||
for s in ['|\b','/\b','-\b','\\\b','|']:
|
||||
sys.stdout.write(s)
|
||||
sys.stdout.flush()
|
||||
time.sleep(1.0/5)
|
||||
print
|
||||
def w(s):
|
||||
sys.stdout.write(s)
|
||||
sys.stdout.flush()
|
||||
sys.stdout.write(s)
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def heatup(p,temp,s=0):
|
||||
curtemp=gettemp(p)
|
||||
p.send_now('M109 S%03d'%temp)
|
||||
p.temp=0
|
||||
if not s: w("Heating extruder up..")
|
||||
f=False
|
||||
while curtemp<=(temp-1):
|
||||
p.send_now('M105')
|
||||
time.sleep(0.5)
|
||||
if not f:
|
||||
time.sleep(1.5)
|
||||
f=True
|
||||
curtemp=gettemp(p)
|
||||
if curtemp: w(u"\rHeating extruder up.. %3d \xb0C"%curtemp)
|
||||
if s: print
|
||||
else: print "\nReady."
|
||||
curtemp=gettemp(p)
|
||||
p.send_now('M109 S%03d'%temp)
|
||||
p.temp=0
|
||||
if not s: w("Heating extruder up..")
|
||||
f=False
|
||||
while curtemp<=(temp-1):
|
||||
p.send_now('M105')
|
||||
time.sleep(0.5)
|
||||
if not f:
|
||||
time.sleep(1.5)
|
||||
f=True
|
||||
curtemp=gettemp(p)
|
||||
if curtemp: w(u"\rHeating extruder up.. %3d \xb0C"%curtemp)
|
||||
if s: print
|
||||
else: print "\nReady."
|
||||
|
||||
def gettemp(p):
|
||||
try: p.logl
|
||||
except: setattr(p,'logl',0)
|
||||
try: p.temp
|
||||
except: setattr(p,'temp',0)
|
||||
for n in range(p.logl,len(p.log)):
|
||||
line=p.log[n]
|
||||
if 'T:' in line:
|
||||
try:
|
||||
setattr(p,'temp',int(line.split('T:')[1].split()[0]))
|
||||
except: print line
|
||||
p.logl=len(p.log)
|
||||
return p.temp
|
||||
try: p.logl
|
||||
except: setattr(p,'logl',0)
|
||||
try: p.temp
|
||||
except: setattr(p,'temp',0)
|
||||
for n in range(p.logl,len(p.log)):
|
||||
line=p.log[n]
|
||||
if 'T:' in line:
|
||||
try:
|
||||
setattr(p,'temp',int(line.split('T:')[1].split()[0]))
|
||||
except: print line
|
||||
p.logl=len(p.log)
|
||||
return p.temp
|
||||
if not os.path.exists(port):
|
||||
port=0
|
||||
port=0
|
||||
|
||||
#Parse options
|
||||
help=u"""
|
||||
%s [ -l DISTANCE ] [ -s STEPS ] [ -t TEMP ] [ -p PORT ]
|
||||
-l --length Length of filament to extrude for each calibration step (default: %d mm)
|
||||
-s --steps Initial amount of steps to use (default: %d steps)
|
||||
-t --temp Extrusion temperature in degrees Celsius (default: %d \xb0C, max %d \xb0C)
|
||||
-p --port Serial port the printer is connected to (default: %s)
|
||||
-h --help This cruft.
|
||||
-l --length Length of filament to extrude for each calibration step (default: %d mm)
|
||||
-s --steps Initial amount of steps to use (default: %d steps)
|
||||
-t --temp Extrusion temperature in degrees Celsius (default: %d \xb0C, max %d \xb0C)
|
||||
-p --port Serial port the printer is connected to (default: %s)
|
||||
-h --help This cruft.
|
||||
"""[1:-1].encode('utf-8')%(sys.argv[0],n,k,temp,tempmax,port if port else 'auto')
|
||||
try:
|
||||
opts,args=getopt.getopt(sys.argv[1:],"hl:s:t:p:",["help","length=","steps=","temp=","port="])
|
||||
opts,args=getopt.getopt(sys.argv[1:],"hl:s:t:p:",["help","length=","steps=","temp=","port="])
|
||||
except getopt.GetoptError,err:
|
||||
print str(err)
|
||||
print help
|
||||
sys.exit(2)
|
||||
print str(err)
|
||||
print help
|
||||
sys.exit(2)
|
||||
for o,a in opts:
|
||||
if o in ('-h','--help'):
|
||||
print help
|
||||
sys.exit()
|
||||
elif o in ('-l','--length'):
|
||||
n=float(a)
|
||||
elif o in ('-s','--steps'):
|
||||
k=int(a)
|
||||
elif o in ('-t','--temp'):
|
||||
temp=int(a)
|
||||
if temp>=tempmax:
|
||||
print (u'%d \xb0C? Are you insane?'.encode('utf-8')%temp)+(" That's over nine thousand!" if temp>9000 else '')
|
||||
sys.exit(255)
|
||||
elif o in ('-p','--port'):
|
||||
port=a
|
||||
if o in ('-h','--help'):
|
||||
print help
|
||||
sys.exit()
|
||||
elif o in ('-l','--length'):
|
||||
n=float(a)
|
||||
elif o in ('-s','--steps'):
|
||||
k=int(a)
|
||||
elif o in ('-t','--temp'):
|
||||
temp=int(a)
|
||||
if temp>=tempmax:
|
||||
print (u'%d \xb0C? Are you insane?'.encode('utf-8')%temp)+(" That's over nine thousand!" if temp>9000 else '')
|
||||
sys.exit(255)
|
||||
elif o in ('-p','--port'):
|
||||
port=a
|
||||
|
||||
#Show initial parameters
|
||||
print "Initial parameters"
|
||||
print "Steps per mm: %3d steps"%k
|
||||
print "Length extruded: %3d mm"%n
|
||||
print
|
||||
print
|
||||
print "Serial port: %s"%(port if port else 'auto')
|
||||
|
||||
p=None
|
||||
try:
|
||||
#Connect to printer
|
||||
w("Connecting to printer..")
|
||||
try:
|
||||
p=printcore(port,115200)
|
||||
except:
|
||||
print 'Error.'
|
||||
raise
|
||||
while not p.online:
|
||||
time.sleep(1)
|
||||
w('.')
|
||||
print " connected."
|
||||
|
||||
heatup(p,temp)
|
||||
|
||||
#Calibration loop
|
||||
while n!=m:
|
||||
heatup(p,temp,True)
|
||||
p.send_now("G92 E0") #Reset e axis
|
||||
p.send_now("G1 E%d F%d"%(n,s)) #Extrude length of filament
|
||||
wait(t,'Extruding.. ')
|
||||
m=float_input("How many millimeters of filament were extruded? ")
|
||||
if m==0: continue
|
||||
if n!=m:
|
||||
k=(n/m)*k
|
||||
p.send_now("M92 E%d"%int(round(k))) #Set new step count
|
||||
print "Steps per mm: %3d steps"%k #Tell user
|
||||
print 'Calibration completed.' #Yay!
|
||||
#Connect to printer
|
||||
w("Connecting to printer..")
|
||||
try:
|
||||
p=printcore(port,115200)
|
||||
except:
|
||||
print 'Error.'
|
||||
raise
|
||||
while not p.online:
|
||||
time.sleep(1)
|
||||
w('.')
|
||||
print " connected."
|
||||
|
||||
heatup(p,temp)
|
||||
|
||||
#Calibration loop
|
||||
while n!=m:
|
||||
heatup(p,temp,True)
|
||||
p.send_now("G92 E0") #Reset e axis
|
||||
p.send_now("G1 E%d F%d"%(n,s)) #Extrude length of filament
|
||||
wait(t,'Extruding.. ')
|
||||
m=float_input("How many millimeters of filament were extruded? ")
|
||||
if m==0: continue
|
||||
if n!=m:
|
||||
k=(n/m)*k
|
||||
p.send_now("M92 E%d"%int(round(k))) #Set new step count
|
||||
print "Steps per mm: %3d steps"%k #Tell user
|
||||
print 'Calibration completed.' #Yay!
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
pass
|
||||
finally:
|
||||
if p: p.disconnect()
|
||||
if p: p.disconnect()
|
||||
|
|
|
@ -263,5 +263,3 @@ class Graph(BufferedCanvas):
|
|||
self.drawextruder0temp(dc, gc)
|
||||
self.drawextruder1targettemp(dc, gc)
|
||||
self.drawextruder1temp(dc, gc)
|
||||
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
# This file is part of the Printrun suite.
|
||||
#
|
||||
#
|
||||
# Printrun is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Printrun is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
|
||||
import wx,time
|
||||
|
@ -20,9 +20,9 @@ ID_ABOUT = 101
|
|||
ID_EXIT = 110
|
||||
class window(wx.Frame):
|
||||
def __init__(self,f,size=(600,600),build_dimensions=[200,200,100,0,0,0],grid=(10,50),extrusion_width=0.5):
|
||||
wx.Frame.__init__(self,None,title="Gcode view, shift to move view, mousewheel to set layer",size=(size[0],size[1]))
|
||||
wx.Frame.__init__(self,None,title="Gcode view, shift to move view, mousewheel to set layer",size=(size[0],size[1]))
|
||||
self.p=gviz(self,size=size,build_dimensions=build_dimensions,grid=grid,extrusion_width=extrusion_width)
|
||||
|
||||
|
||||
vbox = wx.BoxSizer(wx.VERTICAL)
|
||||
toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER)
|
||||
toolbar.AddSimpleTool(1, wx.Image(imagefile('zoom_in.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Zoom In [+]', '')
|
||||
|
@ -42,8 +42,8 @@ class window(wx.Frame):
|
|||
self.Bind(wx.EVT_TOOL, lambda x:self.p.layerdown(), id=4)
|
||||
self.Bind(wx.EVT_TOOL, self.resetview, id=5)
|
||||
#self.Bind(wx.EVT_TOOL, lambda x:self.p.inject(), id=5)
|
||||
|
||||
|
||||
|
||||
|
||||
self.CreateStatusBar(1);
|
||||
self.SetStatusText("Layer number and Z position show here when you scroll");
|
||||
#self.bu=wx.Button(self.p,-1,"U",pos=(0,100),size=(40,140))
|
||||
|
@ -51,19 +51,19 @@ class window(wx.Frame):
|
|||
#self.bi=wx.Button(self.p,-1,"+",pos=(40,100),size=(40,140))
|
||||
#self.bo=wx.Button(self.p,-1,"-",pos=(40,140),size=(40,140))
|
||||
#self.bs=wx.Button(self.p, -1, "Inject", pos=(85, 103), size=(50, 20))
|
||||
|
||||
|
||||
#self.bu.SetToolTip(wx.ToolTip("Move up one layer"))
|
||||
#self.bd.SetToolTip(wx.ToolTip("Move down one layer"))
|
||||
#self.bi.SetToolTip(wx.ToolTip("Zoom view in"))
|
||||
#self.bo.SetToolTip(wx.ToolTip("Zoom view out"))
|
||||
#self.bs.SetToolTip(wx.ToolTip("Insert Code at start of this layer"))
|
||||
|
||||
|
||||
#self.bu.Bind(wx.EVT_BUTTON,lambda x:self.p.layerup())
|
||||
#self.bd.Bind(wx.EVT_BUTTON,lambda x:self.p.layerdown())
|
||||
#self.bi.Bind(wx.EVT_BUTTON,lambda x:self.p.zoom(200,200,1.2))
|
||||
#self.bo.Bind(wx.EVT_BUTTON,lambda x:self.p.zoom(200,200,1/1.2))
|
||||
#self.bs.Bind(wx.EVT_BUTTON,lambda x:self.p.inject())
|
||||
|
||||
|
||||
s=time.time()
|
||||
#print time.time()-s
|
||||
self.initpos=[0,0]
|
||||
|
@ -77,12 +77,12 @@ class window(wx.Frame):
|
|||
self.Bind(wx.EVT_MOUSEWHEEL,self.zoom)
|
||||
self.p.Bind(wx.EVT_MOUSE_EVENTS,self.mouse)
|
||||
self.Bind(wx.EVT_MOUSE_EVENTS,self.mouse)
|
||||
|
||||
|
||||
def resetview(self,event):
|
||||
self.p.translate=[0.0,0.0]
|
||||
self.p.scale=self.p.basescale
|
||||
self.p.zoom(0,0,1.0)
|
||||
|
||||
|
||||
def mouse(self,event):
|
||||
if event.ButtonUp(wx.MOUSE_BTN_LEFT):
|
||||
if(self.initpos is not None):
|
||||
|
@ -97,14 +97,14 @@ class window(wx.Frame):
|
|||
self.basetrans[1]+(e[1]-self.initpos[1]) ]
|
||||
self.p.repaint()
|
||||
self.p.Refresh()
|
||||
|
||||
|
||||
else:
|
||||
event.Skip()
|
||||
|
||||
|
||||
def key(self, event):
|
||||
# Keycode definitions
|
||||
kup=[85, 315] # Up keys
|
||||
kdo=[68, 317] # Down Keys
|
||||
kdo=[68, 317] # Down Keys
|
||||
kzi=[388, 316, 61] # Zoom In Keys
|
||||
kzo=[390, 314, 45] # Zoom Out Keys
|
||||
x=event.GetKeyCode()
|
||||
|
@ -118,7 +118,7 @@ class window(wx.Frame):
|
|||
#else:
|
||||
# if x==wx.WXK_UP:
|
||||
# self.p.layerup()
|
||||
# if x==wx.WXK_DOWN:
|
||||
# if x==wx.WXK_DOWN:
|
||||
# self.p.layerdown()
|
||||
if x in kup:
|
||||
self.p.layerup()
|
||||
|
@ -128,7 +128,7 @@ class window(wx.Frame):
|
|||
self.p.zoom(cx,cy,1.2)
|
||||
if x in kzo:
|
||||
self.p.zoom(cx, cy, 1/1.2)
|
||||
|
||||
|
||||
#print p.lines.keys()
|
||||
def zoom(self, event):
|
||||
z=event.GetWheelRotation()
|
||||
|
@ -138,7 +138,7 @@ class window(wx.Frame):
|
|||
else:
|
||||
if z > 0: self.p.zoom(event.GetX(),event.GetY(),1.2)
|
||||
elif z < 0: self.p.zoom(event.GetX(),event.GetY(),1/1.2)
|
||||
|
||||
|
||||
class gviz(wx.Panel):
|
||||
def __init__(self,parent,size=(200,200),build_dimensions=[200,200,100,0,0,0],grid=(10,50),extrusion_width=0.5):
|
||||
wx.Panel.__init__(self,parent,-1,size=(size[0],size[1]))
|
||||
|
@ -172,12 +172,12 @@ class gviz(wx.Panel):
|
|||
self.hilightarcs=[]
|
||||
self.dirty=1
|
||||
self.blitmap=wx.EmptyBitmap(self.GetClientSize()[0],self.GetClientSize()[1],-1)
|
||||
|
||||
|
||||
def inject(self):
|
||||
#import pdb; pdb.set_trace()
|
||||
print"Inject code here..."
|
||||
print "Layer "+str(self.layerindex +1)+" - Z = "+str(self.layers[self.layerindex])+" mm"
|
||||
|
||||
|
||||
def clear(self):
|
||||
self.lastpos=[0,0,0,0,0,0,0]
|
||||
self.lines={}
|
||||
|
@ -190,7 +190,7 @@ class gviz(wx.Panel):
|
|||
self.layerindex=0
|
||||
self.showall=0
|
||||
self.dirty=1
|
||||
#self.repaint()
|
||||
#self.repaint()
|
||||
def layerup(self):
|
||||
if(self.layerindex+1<len(self.layers)):
|
||||
self.layerindex+=1
|
||||
|
@ -198,15 +198,15 @@ class gviz(wx.Panel):
|
|||
self.parent.SetStatusText("Layer "+str(self.layerindex +1)+" - Going Up - Z = "+str(self.layers[self.layerindex])+" mm",0)
|
||||
self.repaint()
|
||||
self.Refresh()
|
||||
|
||||
|
||||
def layerdown(self):
|
||||
if(self.layerindex>0):
|
||||
self.layerindex-=1
|
||||
self.layerindex-=1
|
||||
# Display layer info on statusbar (Jezmy)
|
||||
self.parent.SetStatusText("Layer "+str(self.layerindex + 1)+" - Going Down - Z = "+str(self.layers[self.layerindex])+ " mm",0)
|
||||
self.repaint()
|
||||
self.Refresh()
|
||||
|
||||
|
||||
def setlayer(self,layer):
|
||||
try:
|
||||
self.layerindex=self.layers.index(layer)
|
||||
|
@ -215,17 +215,17 @@ class gviz(wx.Panel):
|
|||
self.showall=0
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def resize(self,event):
|
||||
size=self.GetClientSize()
|
||||
newsize=min(float(size[0])/self.size[0],float(size[1])/self.size[1])
|
||||
self.size=self.GetClientSize()
|
||||
wx.CallAfter(self.zoom,0,0,newsize)
|
||||
|
||||
|
||||
|
||||
def zoom(self,x,y,factor):
|
||||
self.scale = [s * factor for s in self.scale]
|
||||
|
||||
|
||||
self.translate = [ x - (x-self.translate[0]) * factor,
|
||||
y - (y-self.translate[1]) * factor]
|
||||
penwidth = max(1.0,self.filament_width*((self.scale[0]+self.scale[1])/2.0))
|
||||
|
@ -234,8 +234,8 @@ class gviz(wx.Panel):
|
|||
#self.dirty=1
|
||||
self.repaint()
|
||||
self.Refresh()
|
||||
|
||||
|
||||
|
||||
|
||||
def repaint(self):
|
||||
self.blitmap=wx.EmptyBitmap(self.GetClientSize()[0],self.GetClientSize()[1],-1)
|
||||
dc=wx.MemoryDC()
|
||||
|
@ -257,7 +257,7 @@ class gviz(wx.Panel):
|
|||
dc.SetBrush(wx.Brush((0,255,0)))
|
||||
if len(self.layers):
|
||||
dc.DrawRectangle(self.size[0]-14,(1.0-(1.0*(self.layerindex+1))/len(self.layers))*self.size[1],13,self.size[1]-1)
|
||||
|
||||
|
||||
def _drawlines(lines,pens):
|
||||
def _scaler(x):
|
||||
return (self.scale[0]*x[0]+self.translate[0],
|
||||
|
@ -266,7 +266,7 @@ class gviz(wx.Panel):
|
|||
self.scale[1]*x[3]+self.translate[1],)
|
||||
scaled_lines = map(_scaler,lines)
|
||||
dc.DrawLineList(scaled_lines, pens)
|
||||
|
||||
|
||||
def _drawarcs(arcs,pens):
|
||||
def _scaler(x):
|
||||
return (self.scale[0]*x[0]+self.translate[0],
|
||||
|
@ -280,7 +280,7 @@ class gviz(wx.Panel):
|
|||
dc.SetPen(pens[i] if type(pens).__name__ == 'list' else pens)
|
||||
dc.SetBrush(wx.TRANSPARENT_BRUSH)
|
||||
dc.DrawArc(*scaled_arcs[i])
|
||||
|
||||
|
||||
if self.showall:
|
||||
l=[]
|
||||
for i in self.layers:
|
||||
|
@ -295,12 +295,12 @@ class gviz(wx.Panel):
|
|||
_drawarcs(self.arcs[self.layers[layer_i]], self.fades[self.layerindex-layer_i-1])
|
||||
_drawlines(self.lines[self.layers[self.layerindex]], self.pens[self.layers[self.layerindex]])
|
||||
_drawarcs(self.arcs[self.layers[self.layerindex]], self.arcpens[self.layers[self.layerindex]])
|
||||
|
||||
|
||||
_drawlines(self.hilight, self.hlpen)
|
||||
_drawarcs(self.hilightarcs, self.hlpen)
|
||||
|
||||
|
||||
dc.SelectObject(wx.NullBitmap)
|
||||
|
||||
|
||||
def paint(self,event):
|
||||
dc=wx.PaintDC(self)
|
||||
if(self.dirty):
|
||||
|
@ -309,12 +309,12 @@ class gviz(wx.Panel):
|
|||
sz=self.GetClientSize()
|
||||
dc.DrawBitmap(self.blitmap,0,0)
|
||||
del dc
|
||||
|
||||
|
||||
def addfile(self,gcodes=[]):
|
||||
self.clear()
|
||||
for i in gcodes:
|
||||
self.addgcode(i)
|
||||
|
||||
|
||||
def addgcode(self,gcode="M105",hilight=0):
|
||||
gcode=gcode.split("*")[0]
|
||||
gcode=gcode.split(";")[0]
|
||||
|
@ -323,7 +323,7 @@ class gviz(wx.Panel):
|
|||
return
|
||||
if gcode[0][0] == 'n':
|
||||
gcode.pop(0)
|
||||
|
||||
|
||||
def _readgcode():
|
||||
target=self.lastpos[:]
|
||||
target[5]=0.0
|
||||
|
@ -353,14 +353,14 @@ class gviz(wx.Panel):
|
|||
self.arcpens[target[2]]=[]
|
||||
self.layers+=[target[2]]
|
||||
return target
|
||||
|
||||
|
||||
def _y(y):
|
||||
return self.build_dimensions[1]-(y-self.build_dimensions[4])
|
||||
def _x(x):
|
||||
return x-self.build_dimensions[3]
|
||||
|
||||
|
||||
start_pos = self.hilightpos[:] if hilight else self.lastpos[:]
|
||||
|
||||
|
||||
if gcode[0] in [ "g0", "g1" ]:
|
||||
target = _readgcode()
|
||||
line = [ _x(start_pos[0]), _y(start_pos[1]), _x(target[0]), _y(target[1]) ]
|
||||
|
@ -372,7 +372,7 @@ class gviz(wx.Panel):
|
|||
self.hilight += [line]
|
||||
self.hilightpos = target
|
||||
self.dirty = 1
|
||||
|
||||
|
||||
if gcode[0] in [ "g2", "g3" ]:
|
||||
target = _readgcode()
|
||||
arc = []
|
||||
|
@ -381,7 +381,7 @@ class gviz(wx.Panel):
|
|||
arc += [ _x(start_pos[0] + target[5]), _y(start_pos[1] + target[6]) ] # center
|
||||
if gcode[0] == "g2": # clockwise, reverse endpoints
|
||||
arc[0], arc[1], arc[2], arc[3] = arc[2], arc[3], arc[0], arc[1]
|
||||
|
||||
|
||||
if not hilight:
|
||||
self.arcs[ target[2] ] += [arc]
|
||||
self.arcpens[ target[2] ] += [self.arcpen]
|
||||
|
@ -390,11 +390,10 @@ class gviz(wx.Panel):
|
|||
self.hilightarcs += [arc]
|
||||
self.hilightpos = target
|
||||
self.dirty = 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = wx.App(False)
|
||||
#main = window(open("/home/kliment/designs/spinner/arm_export.gcode"))
|
||||
main = window(open("jam.gcode"))
|
||||
main.Show()
|
||||
app.MainLoop()
|
||||
|
||||
|
|
|
@ -8,14 +8,14 @@ def install_locale(domain):
|
|||
gettext.install(domain, '/usr/share/pronterface/locale', unicode=1)
|
||||
elif os.path.exists('/usr/local/share/pronterface/locale'):
|
||||
gettext.install(domain, '/usr/local/share/pronterface/locale', unicode=1)
|
||||
else:
|
||||
else:
|
||||
gettext.install(domain, './locale', unicode=1)
|
||||
|
||||
def imagefile(filename):
|
||||
for prefix in ['/usr/local/share/pronterface/images', '/usr/share/pronterface/images']:
|
||||
candidate = os.path.join(prefix, filename)
|
||||
if os.path.exists(candidate):
|
||||
return candidate
|
||||
candidate = os.path.join(prefix, filename)
|
||||
if os.path.exists(candidate):
|
||||
return candidate
|
||||
local_candidate = os.path.join(os.path.dirname(__file__), "images", filename)
|
||||
if os.path.exists(local_candidate):
|
||||
return local_candidate
|
||||
|
@ -24,9 +24,9 @@ def imagefile(filename):
|
|||
|
||||
def lookup_file(filename, prefixes):
|
||||
for prefix in prefixes:
|
||||
candidate = os.path.join(prefix, filename)
|
||||
if os.path.exists(candidate):
|
||||
return candidate
|
||||
candidate = os.path.join(prefix, filename)
|
||||
if os.path.exists(candidate):
|
||||
return candidate
|
||||
return filename
|
||||
|
||||
def pixmapfile(filename):
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
# This file is part of the Printrun suite.
|
||||
#
|
||||
#
|
||||
# Printrun is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Printrun is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
@ -21,7 +21,7 @@ import tempfile
|
|||
import shutil
|
||||
import svg.document as wxpsvgdocument
|
||||
import imghdr
|
||||
|
||||
|
||||
class dispframe(wx.Frame):
|
||||
def __init__(self, parent, title, res=(800, 600), printer=None):
|
||||
wx.Frame.__init__(self, parent=parent, title=title)
|
||||
|
@ -58,7 +58,7 @@ class dispframe(wx.Frame):
|
|||
points = [wx.Point(*map(lambda x:int(round(float(x) * self.scale)), j.strip().split())) for j in i.strip().split("M")[1].split("L")]
|
||||
dc.DrawPolygon(points, self.size[0] / 2, self.size[1] / 2)
|
||||
elif self.slicer == 'Slic3r':
|
||||
gc = wx.GraphicsContext_Create(dc)
|
||||
gc = wx.GraphicsContext_Create(dc)
|
||||
gc.Translate(*self.offset)
|
||||
gc.Scale(self.scale, self.scale)
|
||||
wxpsvgdocument.SVGDocument(image).render(gc)
|
||||
|
@ -69,12 +69,12 @@ class dispframe(wx.Frame):
|
|||
self.pic.SetBitmap(self.bitmap)
|
||||
self.pic.Show()
|
||||
self.Refresh()
|
||||
|
||||
|
||||
|
||||
|
||||
except:
|
||||
raise
|
||||
pass
|
||||
|
||||
|
||||
def showimgdelay(self, image):
|
||||
self.drawlayer(image)
|
||||
self.pic.Show()
|
||||
|
@ -82,10 +82,10 @@ class dispframe(wx.Frame):
|
|||
|
||||
self.Refresh()
|
||||
if self.p != None and self.p.online:
|
||||
self.p.send_now("G91")
|
||||
self.p.send_now("G1 Z%f F300" % (self.thickness,))
|
||||
self.p.send_now("G90")
|
||||
|
||||
self.p.send_now("G91")
|
||||
self.p.send_now("G1 Z%f F300" % (self.thickness,))
|
||||
self.p.send_now("G90")
|
||||
|
||||
def nextimg(self, event):
|
||||
if self.index < len(self.layers):
|
||||
i = self.index
|
||||
|
@ -99,8 +99,8 @@ class dispframe(wx.Frame):
|
|||
wx.CallAfter(self.pic.Hide)
|
||||
wx.CallAfter(self.Refresh)
|
||||
wx.CallAfter(self.ShowFullScreen, 0)
|
||||
wx.CallAfter(self.timer.Stop)
|
||||
|
||||
wx.CallAfter(self.timer.Stop)
|
||||
|
||||
def present(self, layers, interval=0.5, pause=0.2, thickness=0.4, scale=20, size=(800, 600), offset=(0, 0)):
|
||||
wx.CallAfter(self.pic.Hide)
|
||||
wx.CallAfter(self.Refresh)
|
||||
|
@ -117,7 +117,7 @@ class dispframe(wx.Frame):
|
|||
self.timer.Start(1000 * interval + 1000 * pause)
|
||||
|
||||
class setframe(wx.Frame):
|
||||
|
||||
|
||||
def __init__(self, parent, printer=None):
|
||||
wx.Frame.__init__(self, parent, title="Projector setup")
|
||||
self.f = dispframe(None, "", printer=printer)
|
||||
|
@ -147,26 +147,26 @@ class setframe(wx.Frame):
|
|||
|
||||
wx.StaticText(self.panel, -1, "Y:", pos=(160, 60))
|
||||
self.Y = wx.TextCtrl(self.panel, -1, "768", pos=(210, 60))
|
||||
|
||||
|
||||
wx.StaticText(self.panel, -1, "OffsetX:", pos=(160, 90))
|
||||
self.offsetX = wx.TextCtrl(self.panel, -1, "50", pos=(210, 90))
|
||||
|
||||
wx.StaticText(self.panel, -1, "OffsetY:", pos=(160, 120))
|
||||
self.offsetY = wx.TextCtrl(self.panel, -1, "50", pos=(210, 120))
|
||||
|
||||
|
||||
self.bload = wx.Button(self.panel, -1, "Present", pos=(0, 150))
|
||||
self.bload.Bind(wx.EVT_BUTTON, self.startdisplay)
|
||||
|
||||
|
||||
wx.StaticText(self.panel, -1, "Fullscreen:", pos=(160, 150))
|
||||
self.fullscreen = wx.CheckBox(self.panel, -1, pos=(220, 150))
|
||||
self.fullscreen.SetValue(True)
|
||||
|
||||
|
||||
self.Show()
|
||||
|
||||
def __del__(self):
|
||||
if hasattr(self, 'image_dir') and self.image_dir != '':
|
||||
shutil.rmtree(self.image_dir)
|
||||
|
||||
|
||||
def parsesvg(self, name):
|
||||
et = xml.etree.ElementTree.ElementTree(file=name)
|
||||
#xml.etree.ElementTree.dump(et)
|
||||
|
@ -177,18 +177,18 @@ class setframe(wx.Frame):
|
|||
if (slicer == 'Slic3r'):
|
||||
height = et.getroot().get('height')
|
||||
width = et.getroot().get('width')
|
||||
|
||||
|
||||
for i in et.findall("{http://www.w3.org/2000/svg}g"):
|
||||
z = float(i.get('{http://slic3r.org/namespaces/slic3r}z'))
|
||||
zdiff = z - zlast
|
||||
zlast = z
|
||||
|
||||
|
||||
svgSnippet = xml.etree.ElementTree.Element('{http://www.w3.org/2000/svg}svg')
|
||||
svgSnippet.set('height', height + 'mm')
|
||||
svgSnippet.set('width', width + 'mm')
|
||||
svgSnippet.set('viewBox', '0 0 ' + height + ' ' + width)
|
||||
svgSnippet.append(i)
|
||||
|
||||
|
||||
ol += [svgSnippet]
|
||||
else :
|
||||
for i in et.findall("{http://www.w3.org/2000/svg}g")[0].findall("{http://www.w3.org/2000/svg}g"):
|
||||
|
@ -198,7 +198,7 @@ class setframe(wx.Frame):
|
|||
path = i.find('{http://www.w3.org/2000/svg}path')
|
||||
ol += [(path.get("d").split("z"))[:-1]]
|
||||
return ol, zdiff, slicer
|
||||
|
||||
|
||||
def parse3DLPzip(self, name):
|
||||
if not zipfile.is_zipfile(name):
|
||||
raise Exception(name + " is not a zip file!")
|
||||
|
@ -212,7 +212,7 @@ class setframe(wx.Frame):
|
|||
if os.path.isfile(path) and imghdr.what(path) in acceptedImageTypes:
|
||||
ol.append(wx.Bitmap(path))
|
||||
return ol, -1, "bitmap"
|
||||
|
||||
|
||||
def loadfile(self, event):
|
||||
dlg = wx.FileDialog(self, ("Open file to print"), style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
|
||||
dlg.SetWildcard(("Slic3r or Skeinforge svg files (;*.svg;*.SVG;);3DLP Zip (;*.3dlp.zip;)"))
|
||||
|
|
|
@ -17,7 +17,7 @@ import wx
|
|||
|
||||
class macroed(wx.Dialog):
|
||||
"""Really simple editor to edit macro definitions"""
|
||||
|
||||
|
||||
def __init__(self,macro_name,definition,callback,gcode=False):
|
||||
self.indent_chars = " "
|
||||
title=" macro %s"
|
||||
|
@ -54,7 +54,7 @@ class macroed(wx.Dialog):
|
|||
topsizer.Fit(self)
|
||||
self.Show()
|
||||
self.e.SetFocus()
|
||||
|
||||
|
||||
def find(self,ev):
|
||||
# Ask user what to look for, find it and point at it ... (Jezmy)
|
||||
S = self.e.GetStringSelection()
|
||||
|
@ -63,27 +63,27 @@ class macroed(wx.Dialog):
|
|||
FindValue = wx.GetTextFromUser('Please enter a search string:', caption="Search", default_value=S, parent=None)
|
||||
somecode = self.e.GetValue()
|
||||
numLines = len(somecode)
|
||||
position = somecode.find(FindValue, self.e.GetInsertionPoint())
|
||||
position = somecode.find(FindValue, self.e.GetInsertionPoint())
|
||||
if position == -1 :
|
||||
# ShowMessage(self,-1, "Not found!")
|
||||
titletext = wx.TextCtrl(self.panel,-1,"Not Found!")
|
||||
else:
|
||||
# self.title.SetValue("Position : "+str(position))
|
||||
|
||||
titletext = wx.TextCtrl(self.panel,-1,str(position))
|
||||
|
||||
# ananswer = wx.MessageBox(str(numLines)+" Lines detected in file\n"+str(position), "OK")
|
||||
titletext = wx.TextCtrl(self.panel,-1,"Not Found!")
|
||||
else:
|
||||
# self.title.SetValue("Position : "+str(position))
|
||||
|
||||
titletext = wx.TextCtrl(self.panel,-1,str(position))
|
||||
|
||||
# ananswer = wx.MessageBox(str(numLines)+" Lines detected in file\n"+str(position), "OK")
|
||||
self.e.SetFocus()
|
||||
self.e.SetInsertionPoint(position)
|
||||
self.e.SetInsertionPoint(position)
|
||||
self.e.SetSelection(position, position + len(FindValue))
|
||||
self.e.ShowPosition(position)
|
||||
|
||||
|
||||
def ShowMessage(self, ev , message):
|
||||
dlg = wxMessageDialog(self, message,
|
||||
"Info!", wxOK | wxICON_INFORMATION)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
|
||||
def save(self,ev):
|
||||
self.Destroy()
|
||||
if not self.gcode:
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
# This file is part of the Printrun suite.
|
||||
#
|
||||
#
|
||||
# Printrun is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Printrun is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
@ -38,15 +38,15 @@ I=[
|
|||
def transpose(matrix):
|
||||
return zip(*matrix)
|
||||
#return [[v[i] for v in matrix] for i in xrange(len(matrix[0]))]
|
||||
|
||||
|
||||
def multmatrix(vector,matrix):
|
||||
return map(sum, transpose(map(lambda x:[x[0]*p for p in x[1]], zip(vector, transpose(matrix)))))
|
||||
|
||||
|
||||
def applymatrix(facet,matrix=I):
|
||||
#return facet
|
||||
#return [map(lambda x:-1.0*x,multmatrix(facet[0]+[1],matrix)[:3]),map(lambda x:multmatrix(x+[1],matrix)[:3],facet[1])]
|
||||
return genfacet(map(lambda x:multmatrix(x+[1],matrix)[:3],facet[1]))
|
||||
|
||||
|
||||
f=[[0,0,0],[[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565]]]
|
||||
m=[
|
||||
[1,0,0,0],
|
||||
|
@ -73,7 +73,7 @@ def emitstl(filename,facets=[],objname="stltool_export",binary=1):
|
|||
f.write(buf)
|
||||
f.close()
|
||||
return
|
||||
|
||||
|
||||
|
||||
f=open(filename,"w")
|
||||
f.write("solid "+objname+"\n")
|
||||
|
@ -85,8 +85,8 @@ def emitstl(filename,facets=[],objname="stltool_export",binary=1):
|
|||
f.write(" endfacet"+"\n")
|
||||
f.write("endsolid "+objname+"\n")
|
||||
f.close()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class stl:
|
||||
def __init__(self, filename=None):
|
||||
|
@ -94,7 +94,7 @@ class stl:
|
|||
self.facets=[]
|
||||
self.facetsminz=[]
|
||||
self.facetsmaxz=[]
|
||||
|
||||
|
||||
self.name=""
|
||||
self.insolid=0
|
||||
self.infacet=0
|
||||
|
@ -133,7 +133,7 @@ class stl:
|
|||
for i in self.f:
|
||||
if not self.parseline(i):
|
||||
return
|
||||
|
||||
|
||||
def translate(self,v=[0,0,0]):
|
||||
matrix=[
|
||||
[1,0,0,v[0]],
|
||||
|
@ -142,7 +142,7 @@ class stl:
|
|||
[0,0,0,1]
|
||||
]
|
||||
return self.transform(matrix)
|
||||
|
||||
|
||||
def rotate(self,v=[0,0,0]):
|
||||
import math
|
||||
z=v[2]
|
||||
|
@ -167,7 +167,7 @@ class stl:
|
|||
[0,0,0,1]
|
||||
]
|
||||
return self.transform(matrix1).transform(matrix2).transform(matrix3)
|
||||
|
||||
|
||||
def scale(self,v=[0,0,0]):
|
||||
matrix=[
|
||||
[v[0],0,0,0],
|
||||
|
@ -176,8 +176,8 @@ class stl:
|
|||
[0,0,0,1]
|
||||
]
|
||||
return self.transform(matrix)
|
||||
|
||||
|
||||
|
||||
|
||||
def transform(self,m=I):
|
||||
s=stl()
|
||||
s.facets=[applymatrix(i,m) for i in self.facets]
|
||||
|
@ -190,7 +190,7 @@ class stl:
|
|||
s.facetsminz+=[(min(map(lambda x:x[2], facet[1])),facet)]
|
||||
s.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])),facet)]
|
||||
return s
|
||||
|
||||
|
||||
def export(self,f=sys.stdout):
|
||||
f.write("solid "+self.name+"\n")
|
||||
for i in self.facets:
|
||||
|
@ -202,14 +202,14 @@ class stl:
|
|||
f.write(" endfacet"+"\n")
|
||||
f.write("endsolid "+self.name+"\n")
|
||||
f.flush()
|
||||
|
||||
|
||||
def parseline(self,l):
|
||||
l=l.strip()
|
||||
if l.startswith("solid"):
|
||||
self.insolid=1
|
||||
self.name=l[6:]
|
||||
#print self.name
|
||||
|
||||
|
||||
elif l.startswith("endsolid"):
|
||||
self.insolid=0
|
||||
return 0
|
||||
|
@ -244,7 +244,7 @@ if __name__=="__main__":
|
|||
working.remove(j[1])
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
print i,len(working)
|
||||
emitstl("../../Downloads/frame-vertex-neo-foot-x4-a.stl",s.facets,"emitted_object")
|
||||
#stl("../prusamendel/stl/mendelplate.stl")
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# This file is part of the Printrun suite.
|
||||
#
|
||||
#
|
||||
# Printrun is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Printrun is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
@ -304,14 +304,14 @@ class gcview(object):
|
|||
('v3f/static', vertices),
|
||||
('n3f/static', normals)))
|
||||
if lasth is not None:
|
||||
self.layers[lasth] = pyglet.graphics.Batch()
|
||||
indices = range(len(layertemp[lasth][0])) # [[3*i,3*i+1,3*i+2] for i in xrange(len(facets))]
|
||||
self.vlists.append(self.layers[lasth].add_indexed(len(layertemp[lasth][0]) // 3,
|
||||
GL_TRIANGLES,
|
||||
None, # group,
|
||||
indices,
|
||||
('v3f/static', layertemp[lasth][0]),
|
||||
('n3f/static', layertemp[lasth][1])))
|
||||
self.layers[lasth] = pyglet.graphics.Batch()
|
||||
indices = range(len(layertemp[lasth][0])) # [[3*i,3*i+1,3*i+2] for i in xrange(len(facets))]
|
||||
self.vlists.append(self.layers[lasth].add_indexed(len(layertemp[lasth][0]) // 3,
|
||||
GL_TRIANGLES,
|
||||
None, # group,
|
||||
indices,
|
||||
('v3f/static', layertemp[lasth][0]),
|
||||
('n3f/static', layertemp[lasth][1])))
|
||||
|
||||
def genline(self, i, h, w):
|
||||
S = i[0][:3]
|
||||
|
@ -356,28 +356,28 @@ class gcview(object):
|
|||
return spoints, epoints, S, E
|
||||
|
||||
def transform(self, line):
|
||||
line = line.split(";")[0]
|
||||
cur = self.prev[:]
|
||||
if len(line) > 0:
|
||||
if "G1" in line or "G0" in line or "G92" in line:
|
||||
if("X" in line):
|
||||
cur[0] = float(line.split("X")[1].split(" ")[0])
|
||||
if("Y" in line):
|
||||
cur[1] = float(line.split("Y")[1].split(" ")[0])
|
||||
if("Z" in line):
|
||||
cur[2] = float(line.split("Z")[1].split(" ")[0])
|
||||
if("E" in line):
|
||||
cur[3] = float(line.split("E")[1].split(" ")[0])
|
||||
if self.prev == cur:
|
||||
return None
|
||||
if self.fline or "G92" in line:
|
||||
self.prev = cur
|
||||
self.fline = 0
|
||||
return None
|
||||
else:
|
||||
r = [self.prev, cur]
|
||||
self.prev = cur
|
||||
return r
|
||||
line = line.split(";")[0]
|
||||
cur = self.prev[:]
|
||||
if len(line) > 0:
|
||||
if "G1" in line or "G0" in line or "G92" in line:
|
||||
if("X" in line):
|
||||
cur[0] = float(line.split("X")[1].split(" ")[0])
|
||||
if("Y" in line):
|
||||
cur[1] = float(line.split("Y")[1].split(" ")[0])
|
||||
if("Z" in line):
|
||||
cur[2] = float(line.split("Z")[1].split(" ")[0])
|
||||
if("E" in line):
|
||||
cur[3] = float(line.split("E")[1].split(" ")[0])
|
||||
if self.prev == cur:
|
||||
return None
|
||||
if self.fline or "G92" in line:
|
||||
self.prev = cur
|
||||
self.fline = 0
|
||||
return None
|
||||
else:
|
||||
r = [self.prev, cur]
|
||||
self.prev = cur
|
||||
return r
|
||||
|
||||
def delete(self):
|
||||
for i in self.vlists:
|
||||
|
@ -570,27 +570,27 @@ class TestGlPanel(GLPanel):
|
|||
self.initpos = None
|
||||
|
||||
elif event.Dragging() and event.RightIsDown() and event.ShiftDown():
|
||||
if self.initpos is None:
|
||||
self.initpos = event.GetPositionTuple()
|
||||
else:
|
||||
p1 = self.initpos
|
||||
p2 = event.GetPositionTuple()
|
||||
sz = self.GetClientSize()
|
||||
p1 = list(p1)
|
||||
p2 = list(p2)
|
||||
p1[1] *= -1
|
||||
p2[1] *= -1
|
||||
if self.initpos is None:
|
||||
self.initpos = event.GetPositionTuple()
|
||||
else:
|
||||
p1 = self.initpos
|
||||
p2 = event.GetPositionTuple()
|
||||
sz = self.GetClientSize()
|
||||
p1 = list(p1)
|
||||
p2 = list(p2)
|
||||
p1[1] *= -1
|
||||
p2[1] *= -1
|
||||
|
||||
self.transv = map(lambda x, y, z, c: c - self.dist * (x - y) / z, list(p1) + [0], list(p2) + [0], list(sz) + [1], self.transv)
|
||||
self.transv = map(lambda x, y, z, c: c - self.dist * (x - y) / z, list(p1) + [0], list(p2) + [0], list(sz) + [1], self.transv)
|
||||
|
||||
glLoadIdentity()
|
||||
glTranslatef(self.transv[0], self.transv[1], 0)
|
||||
glTranslatef(0, 0, self.transv[2])
|
||||
if(self.rot):
|
||||
glMultMatrixd(build_rotmatrix(self.basequat))
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
|
||||
self.rot = 1
|
||||
self.initpos = None
|
||||
glLoadIdentity()
|
||||
glTranslatef(self.transv[0], self.transv[1], 0)
|
||||
glTranslatef(0, 0, self.transv[2])
|
||||
if(self.rot):
|
||||
glMultMatrixd(build_rotmatrix(self.basequat))
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
|
||||
self.rot = 1
|
||||
self.initpos = None
|
||||
else:
|
||||
#mouse is moving without a button press
|
||||
p = event.GetPositionTuple()
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
import wx
|
||||
|
||||
def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False):
|
||||
""" Draws an arc of an ellipse within bounding rect (x,y,w,h)
|
||||
""" Draws an arc of an ellipse within bounding rect (x,y,w,h)
|
||||
from startArc to endArc (in radians, relative to the horizontal line of the eclipse)"""
|
||||
|
||||
|
||||
if True:
|
||||
import warnings
|
||||
warnings.warn("elliptical arcs are not supported")
|
||||
|
@ -15,7 +15,7 @@ def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False):
|
|||
h = h/2.0
|
||||
self.AddArc(x+w, y+h, ((w+h)/2), startAngle, endAngle, clockwise)
|
||||
return
|
||||
else:
|
||||
else:
|
||||
#implement in terms of AddArc by applying a transformation matrix
|
||||
#Sigh this can't work, still need to patch wx to allow
|
||||
#either a) AddPath that's not a closed path or
|
||||
|
@ -25,19 +25,18 @@ def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False):
|
|||
#possibly be simulated by combining the current transform with option a.
|
||||
mtx = wx.GraphicsRenderer_GetDefaultRenderer().CreateMatrix()
|
||||
path = wx.GraphicsRenderer_GetDefaultRenderer().CreatePath()
|
||||
|
||||
|
||||
|
||||
mtx.Translate(x+(w/2.0), y+(h/2.0))
|
||||
mtx.Scale(w/2.0, y/2.0)
|
||||
|
||||
|
||||
path.AddArc(0, 0, 1, startAngle, endAngle, clockwise)
|
||||
path.Transform(mtx)
|
||||
self.AddPath(path)
|
||||
self.MoveToPoint(path.GetCurrentPoint())
|
||||
self.CloseSubpath()
|
||||
|
||||
|
||||
if not hasattr(wx.GraphicsPath, "AddEllipticalArc"):
|
||||
wx.GraphicsPath.AddEllipticalArc = AddEllipticalArc
|
||||
|
||||
del AddEllipticalArc
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
Parsers for specific attributes
|
||||
"""
|
||||
import urlparse
|
||||
from pyparsing import (Literal,
|
||||
from pyparsing import (Literal,
|
||||
Optional, oneOf, Group, StringEnd, Combine, Word, alphas, hexnums,
|
||||
CaselessLiteral, SkipTo
|
||||
)
|
||||
|
@ -21,14 +21,14 @@ def parsePossibleURL(t):
|
|||
colorDeclaration = none | currentColor | colourValue
|
||||
|
||||
urlEnd = (
|
||||
Literal(")").suppress() +
|
||||
Optional(Group(colorDeclaration), default=()) +
|
||||
Literal(")").suppress() +
|
||||
Optional(Group(colorDeclaration), default=()) +
|
||||
StringEnd()
|
||||
)
|
||||
|
||||
url = (
|
||||
CaselessLiteral("URL")
|
||||
+
|
||||
+
|
||||
Literal("(").suppress()+
|
||||
Group(SkipTo(urlEnd, include=True).setParseAction(parsePossibleURL))
|
||||
)
|
||||
|
@ -37,7 +37,7 @@ url = (
|
|||
#For none and currentColor, the details tuple will be the empty tuple
|
||||
#for CSS color declarations, it will be (type, (R,G,B))
|
||||
#for URLs, it will be ("URL", ((url tuple), fallback))
|
||||
#The url tuple will be as returned by urlparse.urlsplit, and can be
|
||||
#The url tuple will be as returned by urlparse.urlsplit, and can be
|
||||
#an empty tuple if the parser has an error
|
||||
#The fallback will be another (type, details) tuple as a parsed
|
||||
#colorDeclaration, but may be the empty tuple if it is not present
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
from pyparsing import Literal, Combine
|
||||
from .identifier import identifier
|
||||
|
||||
atkeyword = Combine(Literal("@") + identifier)
|
||||
atkeyword = Combine(Literal("@") + identifier)
|
||||
|
|
|
@ -5,4 +5,3 @@
|
|||
from pyparsing import nestedExpr
|
||||
|
||||
block = nestedExpr(opener="{", closer="}")
|
||||
|
||||
|
|
|
@ -21,31 +21,31 @@ comma = Literal(",").suppress()
|
|||
def clampColourByte(val):
|
||||
val = int(val)
|
||||
return min(max(0,val), 255)
|
||||
|
||||
|
||||
def clampColourPerc(val):
|
||||
val = float(val)
|
||||
return min(max(0,val), 100)
|
||||
|
||||
|
||||
def parseColorPerc(token):
|
||||
val = token[0]
|
||||
val = clampColourPerc(val)
|
||||
#normalize to bytes
|
||||
return int(255 * (val / 100.0))
|
||||
|
||||
|
||||
|
||||
colorByte = Optional(sign) + integerConstant.setParseAction(lambda t: clampColourByte(t[0]))
|
||||
colorPerc = number.setParseAction(parseColorPerc) + Literal("%").suppress()
|
||||
|
||||
rgb = (
|
||||
Literal("rgb(").setParseAction(lambda t: "RGB") +
|
||||
|
||||
Literal("rgb(").setParseAction(lambda t: "RGB") +
|
||||
|
||||
(
|
||||
#integer constants, ie 255,255,255
|
||||
Group(colorByte + comma + colorByte + comma + colorByte) ^
|
||||
#percentage values, ie 100%, 50%
|
||||
Group(colorPerc + comma + colorPerc + comma + colorPerc)
|
||||
)
|
||||
+
|
||||
+
|
||||
Literal(")").suppress() + StringEnd()
|
||||
)
|
||||
|
||||
|
@ -54,10 +54,10 @@ def parseShortHex(t):
|
|||
|
||||
|
||||
doubleHex = Word(hexnums, exact=2).setParseAction(lambda t: int(t[0], 16))
|
||||
hexLiteral = (Literal("#").setParseAction(lambda t: "RGB") +
|
||||
hexLiteral = (Literal("#").setParseAction(lambda t: "RGB") +
|
||||
(
|
||||
Group(doubleHex + doubleHex + doubleHex) |
|
||||
Word(hexnums, exact=3).setParseAction(parseShortHex)
|
||||
Word(hexnums, exact=3).setParseAction(parseShortHex)
|
||||
) + StringEnd()
|
||||
)
|
||||
|
||||
|
@ -66,7 +66,7 @@ def parseNamedColour(t):
|
|||
return ["RGB", NamedColours[t[0].lower()]]
|
||||
except KeyError:
|
||||
return ["RGB", (0,0,0)]
|
||||
|
||||
|
||||
namedColour = Word(alphas).setParseAction(parseNamedColour)
|
||||
|
||||
|
||||
|
@ -246,7 +246,7 @@ NamedColours = {
|
|||
|
||||
def fillCSS2SystemColours():
|
||||
#The system colours require a wxApp to be present to retrieve,
|
||||
#so if you wnat support for them you'll need
|
||||
#so if you wnat support for them you'll need
|
||||
#to call this function after your wxApp instance starts
|
||||
systemColors = {
|
||||
"ActiveBorder": wx.SYS_COLOUR_ACTIVEBORDER,
|
||||
|
@ -280,4 +280,4 @@ def fillCSS2SystemColours():
|
|||
NamedColours.update(
|
||||
#strip the alpha from the system colors. Is this really what we want to do?
|
||||
(k.lower(), wx.SystemSettings.GetColour(v)[:3]) for (k,v) in systemColors.iteritems()
|
||||
)
|
||||
)
|
||||
|
|
|
@ -10,7 +10,7 @@ class White(White):
|
|||
super(White, self).__init__(ws, min, max, exact)
|
||||
|
||||
escaped = (
|
||||
Literal("\\").suppress() +
|
||||
Literal("\\").suppress() +
|
||||
#chr(20)-chr(126) + chr(128)-unichr(sys.maxunicode)
|
||||
Regex(u"[\u0020-\u007e\u0080-\uffff]", re.IGNORECASE)
|
||||
)
|
||||
|
@ -18,7 +18,7 @@ escaped = (
|
|||
def convertToUnicode(t):
|
||||
return unichr(int(t[0], 16))
|
||||
hex_unicode = (
|
||||
Literal("\\").suppress() +
|
||||
Literal("\\").suppress() +
|
||||
Regex("[0-9a-f]{1,6}", re.IGNORECASE) +
|
||||
Optional(White(exact=1)).suppress()
|
||||
).setParseAction(convertToUnicode)
|
||||
|
@ -29,9 +29,9 @@ escape = hex_unicode | escaped
|
|||
#any unicode literal outside the 0-127 ascii range
|
||||
nonascii = Regex(u"[^\u0000-\u007f]")
|
||||
|
||||
#single character for starting an identifier.
|
||||
#single character for starting an identifier.
|
||||
nmstart = Regex(u"[A-Z]", re.IGNORECASE) | nonascii | escape
|
||||
|
||||
nmchar = Regex(u"[0-9A-Z-]", re.IGNORECASE) | nonascii | escape
|
||||
|
||||
identifier = Combine(nmstart + ZeroOrMore(nmchar))
|
||||
identifier = Combine(nmstart + ZeroOrMore(nmchar))
|
||||
|
|
|
@ -5,4 +5,4 @@ def inlineStyle(styleString):
|
|||
return {}
|
||||
styles = styleString.split(";")
|
||||
rv = dict(style.split(":") for style in styles if len(style) != 0)
|
||||
return rv
|
||||
return rv
|
||||
|
|
|
@ -48,4 +48,4 @@ transformList = delimitedList(Group(transform), delim=maybeComma)
|
|||
|
||||
if __name__ == '__main__':
|
||||
from tests.test_css import *
|
||||
unittest.main()
|
||||
unittest.main()
|
||||
|
|
|
@ -43,4 +43,4 @@ length = lengthValue + Optional(lengthUnit, default=None) + StringEnd()
|
|||
length.leaveWhitespace()
|
||||
|
||||
#set the parse action aftward so it doesn't "infect" the parsers that build on it
|
||||
number.setParseAction(asFloat)
|
||||
number.setParseAction(asFloat)
|
||||
|
|
|
@ -15,7 +15,7 @@ from svg.css import values
|
|||
from attributes import paintValue
|
||||
|
||||
document = """<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="4cm" height="4cm" viewBox="0 0 400 400"
|
||||
xmlns="http://www.w3.org/2000/svg" version="1.1">
|
||||
|
@ -38,7 +38,7 @@ def attrAsFloat(node, attr, defaultValue="0"):
|
|||
return float(val)
|
||||
except ValueError:
|
||||
return valueToPixels(val)
|
||||
|
||||
|
||||
def valueToPixels(val, defaultUnits="px"):
|
||||
#TODO manage default units
|
||||
from pyparsing import ParseException
|
||||
|
@ -67,7 +67,7 @@ def pathHandler(func):
|
|||
ops = self.generatePathOps(path)
|
||||
return path, ops
|
||||
return inner
|
||||
|
||||
|
||||
|
||||
class SVGDocument(object):
|
||||
lastControl = None
|
||||
|
@ -102,12 +102,12 @@ class SVGDocument(object):
|
|||
def state(self):
|
||||
""" Retrieve the current state, without popping"""
|
||||
return self.stateStack[-1]
|
||||
|
||||
|
||||
def processElement(self, element):
|
||||
""" Process one element of the XML tree.
|
||||
Returns the path representing the node,
|
||||
and an operation list for drawing the node.
|
||||
|
||||
|
||||
Parent nodes should return a path (for hittesting), but
|
||||
no draw operations
|
||||
"""
|
||||
|
@ -126,7 +126,7 @@ class SVGDocument(object):
|
|||
""" Returns an oplist for transformations.
|
||||
This applies to a node, not the current state because
|
||||
the transform stack is saved in the wxGraphicsContext.
|
||||
|
||||
|
||||
This oplist does *not* include the push/pop state commands
|
||||
"""
|
||||
ops = []
|
||||
|
@ -188,8 +188,8 @@ class SVGDocument(object):
|
|||
(wx.GraphicsContext.ConcatTransform, (matrix,))
|
||||
)
|
||||
return ops
|
||||
|
||||
|
||||
|
||||
|
||||
def addGroupToDocument(self, node):
|
||||
""" For parent elements: push on a state,
|
||||
then process all child elements
|
||||
|
@ -197,7 +197,7 @@ class SVGDocument(object):
|
|||
ops = [
|
||||
(wx.GraphicsContext.PushState, ())
|
||||
]
|
||||
|
||||
|
||||
path = makePath()
|
||||
ops.extend(self.createTransformOpsFromNode(node))
|
||||
for child in node.getchildren():
|
||||
|
@ -210,7 +210,7 @@ class SVGDocument(object):
|
|||
(wx.GraphicsContext.PopState, ())
|
||||
)
|
||||
return path, ops
|
||||
|
||||
|
||||
def getFontFromState(self):
|
||||
font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
||||
family = self.state.get("font-family")
|
||||
|
@ -227,10 +227,10 @@ class SVGDocument(object):
|
|||
else:
|
||||
font.SetPointSize(int(val))
|
||||
return font
|
||||
|
||||
|
||||
def addTextToDocument(self, node):
|
||||
x, y = [attrAsFloat(node, attr) for attr in ('x', 'y')]
|
||||
|
||||
|
||||
def DoDrawText(context, text, x, y, brush=wx.NullGraphicsBrush):
|
||||
#SVG spec appears to originate text from the bottom
|
||||
#rather than the top as with our API. This function
|
||||
|
@ -252,7 +252,7 @@ class SVGDocument(object):
|
|||
(DoDrawText, (text, x, y))
|
||||
]
|
||||
return None, ops
|
||||
|
||||
|
||||
@pathHandler
|
||||
def addRectToDocument(self, node, path):
|
||||
x, y, w, h = (attrAsFloat(node, attr) for attr in ['x', 'y', 'width', 'height'])
|
||||
|
@ -271,7 +271,7 @@ class SVGDocument(object):
|
|||
#value clamping as per spec section 9.2
|
||||
rx = min(rx, w/2)
|
||||
ry = min(ry, h/2)
|
||||
|
||||
|
||||
#origin
|
||||
path.MoveToPoint(x+rx, y)
|
||||
path.AddLineToPoint(x+w-rx, y)
|
||||
|
@ -315,12 +315,12 @@ class SVGDocument(object):
|
|||
path.AddRectangle(
|
||||
x, y, w, h
|
||||
)
|
||||
|
||||
|
||||
@pathHandler
|
||||
def addCircleToDocument(self, node, path):
|
||||
cx, cy, r = [attrAsFloat(node, attr) for attr in ('cx', 'cy', 'r')]
|
||||
path.AddCircle(cx, cy, r)
|
||||
|
||||
|
||||
@pathHandler
|
||||
def addEllipseToDocument(self, node, path):
|
||||
cx, cy, rx, ry = [float(node.get(attr, 0)) for attr in ('cx', 'cy', 'rx', 'ry')]
|
||||
|
@ -332,29 +332,29 @@ class SVGDocument(object):
|
|||
x = cx - rx
|
||||
y = cy - ry
|
||||
path.AddEllipse(x, y, rx*2, ry*2)
|
||||
|
||||
@pathHandler
|
||||
|
||||
@pathHandler
|
||||
def addLineToDocument(self, node, path):
|
||||
x1, y1, x2, y2 = [attrAsFloat(node, attr) for attr in ('x1', 'y1', 'x2', 'y2')]
|
||||
path.MoveToPoint(x1, y1)
|
||||
path.AddLineToPoint(x2, y2)
|
||||
|
||||
|
||||
@pathHandler
|
||||
def addPolyLineToDocument(self, node, path):
|
||||
#translate to pathdata and render that
|
||||
data = "M " + node.get("points")
|
||||
self.addPathDataToPath(data, path)
|
||||
|
||||
@pathHandler
|
||||
|
||||
@pathHandler
|
||||
def addPolygonToDocument(self, node, path):
|
||||
#translate to pathdata and render that
|
||||
data = "M " + node.get("points") + " Z"
|
||||
self.addPathDataToPath(data, path)
|
||||
|
||||
|
||||
@pathHandler
|
||||
def addPathDataToDocument(self, node, path):
|
||||
self.addPathDataToPath(node.get('d', ''), path)
|
||||
|
||||
|
||||
def addPathDataToPath(self, data, path):
|
||||
self.lastControl = None
|
||||
self.lastControlQ = None
|
||||
|
@ -364,7 +364,7 @@ class SVGDocument(object):
|
|||
form of (command, [list of arguments]).
|
||||
We translate that to [(command, args[0]), (command, args[1])]
|
||||
via a generator.
|
||||
|
||||
|
||||
M is special cased because its subsequent arguments
|
||||
become linetos.
|
||||
"""
|
||||
|
@ -388,10 +388,10 @@ class SVGDocument(object):
|
|||
#print "parsed in", time.time()-t
|
||||
for stroke in normalizeStrokes(parsed):
|
||||
self.addStrokeToPath(path, stroke)
|
||||
|
||||
|
||||
|
||||
|
||||
def generatePathOps(self, path):
|
||||
""" Look at the current state and generate the
|
||||
""" Look at the current state and generate the
|
||||
draw operations (fill, stroke, neither) for the path"""
|
||||
ops = []
|
||||
brush = self.getBrushFromState(path)
|
||||
|
@ -414,7 +414,7 @@ class SVGDocument(object):
|
|||
(wx.GraphicsContext.StrokePath, (path,))
|
||||
)
|
||||
return ops
|
||||
|
||||
|
||||
def getPenFromState(self):
|
||||
pencolour = self.state.get('stroke', 'none')
|
||||
if pencolour == 'currentColor':
|
||||
|
@ -494,7 +494,7 @@ class SVGDocument(object):
|
|||
opacity = float(opacity)
|
||||
opacity = min(max(opacity, 0.0), 1.0)
|
||||
a = 255 * opacity
|
||||
#using try/except block instead of
|
||||
#using try/except block instead of
|
||||
#just setdefault because the wxBrush and wxColour would
|
||||
#be created every time anyway in order to pass them,
|
||||
#defeating the purpose of the cache
|
||||
|
@ -502,14 +502,14 @@ class SVGDocument(object):
|
|||
return SVGDocument.brushCache[(r,g,b,a)]
|
||||
except KeyError:
|
||||
return SVGDocument.brushCache.setdefault((r,g,b,a), wx.Brush(wx.Colour(r,g,b,a)))
|
||||
|
||||
|
||||
|
||||
|
||||
def resolveURL(self, urlData):
|
||||
"""
|
||||
Resolve a URL and return an elementTree Element from it.
|
||||
|
||||
|
||||
Return None if unresolvable
|
||||
|
||||
|
||||
"""
|
||||
scheme, netloc, path, query, fragment = urlData
|
||||
if scheme == netloc == path == '':
|
||||
|
@ -524,15 +524,15 @@ class SVGDocument(object):
|
|||
return None
|
||||
else:
|
||||
return self.resolveRemoteURL(urlData)
|
||||
|
||||
|
||||
def resolveRemoteURL(self, url):
|
||||
return None
|
||||
|
||||
|
||||
def addStrokeToPath(self, path, stroke):
|
||||
""" Given a stroke from a path command
|
||||
(in the form (command, arguments)) create the path
|
||||
commands that represent it.
|
||||
|
||||
|
||||
TODO: break out into (yet another) class/module,
|
||||
especially so we can get O(1) dispatch on type?
|
||||
"""
|
||||
|
@ -564,8 +564,8 @@ class SVGDocument(object):
|
|||
)
|
||||
self.lastControl = control2
|
||||
path.AddCurveToPoint(
|
||||
control1,
|
||||
control2,
|
||||
control1,
|
||||
control2,
|
||||
endpoint
|
||||
)
|
||||
#~ cp = path.GetCurrentPoint()
|
||||
|
@ -574,7 +574,7 @@ class SVGDocument(object):
|
|||
#~ path.AddCircle(x,y, 7)
|
||||
#~ path.MoveToPoint(cp)
|
||||
#~ print "C", control1, control2, endpoint
|
||||
|
||||
|
||||
elif type == 'S':
|
||||
#control2, endpoint = arg
|
||||
control2, endpoint = map(
|
||||
|
@ -584,11 +584,11 @@ class SVGDocument(object):
|
|||
control1 = reflectPoint(self.lastControl, path.GetCurrentPoint())
|
||||
else:
|
||||
control1 = path.GetCurrentPoint()
|
||||
#~ print "S", self.lastControl,":",control1, control2, endpoint
|
||||
#~ print "S", self.lastControl,":",control1, control2, endpoint
|
||||
self.lastControl = control2
|
||||
path.AddCurveToPoint(
|
||||
control1,
|
||||
control2,
|
||||
control1,
|
||||
control2,
|
||||
endpoint
|
||||
)
|
||||
elif type == "Q":
|
||||
|
@ -603,50 +603,50 @@ class SVGDocument(object):
|
|||
cx, cy = path.GetCurrentPoint()
|
||||
self.lastControlQ = (cx, cy)
|
||||
path.AddQuadCurveToPoint(cx, cy, x, y)
|
||||
|
||||
|
||||
elif type == "V":
|
||||
_, y = normalizePoint((0, arg))
|
||||
x, _ = path.GetCurrentPoint()
|
||||
path.AddLineToPoint(x,y)
|
||||
|
||||
|
||||
elif type == "H":
|
||||
x, _ = normalizePoint((arg, 0))
|
||||
_, y = path.GetCurrentPoint()
|
||||
path.AddLineToPoint(x,y)
|
||||
|
||||
|
||||
elif type == "A":
|
||||
#wxGC currently only supports circular arcs,
|
||||
#not eliptical ones
|
||||
|
||||
|
||||
(
|
||||
(rx, ry), #radii of ellipse
|
||||
angle, #angle of rotation on the ellipse in degrees
|
||||
(fa, fs), #arc and stroke angle flags
|
||||
(x, y) #endpoint on the arc
|
||||
) = arg
|
||||
|
||||
) = arg
|
||||
|
||||
x, y = normalizePoint((x,y))
|
||||
cx, cy = path.GetCurrentPoint()
|
||||
if (cx, cy) == (x, y):
|
||||
return #noop
|
||||
|
||||
|
||||
if (rx == 0 or ry == 0):
|
||||
#no radius is effectively a line
|
||||
path.AddLineToPoint(x,y)
|
||||
return
|
||||
|
||||
|
||||
#find the center point for the ellipse
|
||||
#translation via the angle
|
||||
angle = angle % 360
|
||||
angle = math.radians(angle)
|
||||
|
||||
|
||||
#translated endpoint
|
||||
xPrime = math.cos(angle) * ((cx-x)/2)
|
||||
xPrime += math.sin(angle) * ((cx-x)/2)
|
||||
yPrime = -(math.sin(angle)) * ((cy-y)/2)
|
||||
yPrime += (math.cos(angle)) * ((cy-y)/2)
|
||||
|
||||
|
||||
|
||||
|
||||
temp = ((rx**2) * (ry**2)) - ((rx**2) * (yPrime**2)) - ((ry**2) * (xPrime**2))
|
||||
temp /= ((rx**2) * (yPrime**2)) + ((ry**2)*(xPrime**2))
|
||||
temp = abs(temp)
|
||||
|
@ -659,7 +659,7 @@ class SVGDocument(object):
|
|||
cyPrime = temp * -((ry * xPrime) / rx)
|
||||
if fa == fs:
|
||||
cxPrime, cyPrime = -cxPrime, -cyPrime
|
||||
|
||||
|
||||
#reflect backwards now for the origin
|
||||
cnx = math.cos(angle) * cxPrime
|
||||
cnx += math.sin(angle) * cxPrime
|
||||
|
@ -667,18 +667,18 @@ class SVGDocument(object):
|
|||
cny += (math.cos(angle)) * cyPrime
|
||||
cnx += ((cx+x)/2.0)
|
||||
cny += ((cy+y)/2.0)
|
||||
|
||||
|
||||
#calculate the angle between the two endpoints
|
||||
lastArc = wx.Point2D(x-cnx, y-cny).GetVectorAngle()
|
||||
firstArc = wx.Point2D(cx-cnx, cy-cny).GetVectorAngle()
|
||||
lastArc = math.radians(lastArc)
|
||||
firstArc = math.radians(firstArc)
|
||||
|
||||
|
||||
|
||||
|
||||
#aargh buggines.
|
||||
#AddArc draws a straight line between
|
||||
#the endpoints of the arc.
|
||||
#putting it in a subpath makes the strokes come out
|
||||
#putting it in a subpath makes the strokes come out
|
||||
#correctly, but it still only fills the slice
|
||||
#taking out the MoveToPoint fills correctly.
|
||||
path.AddEllipse(cnx-rx, cny-ry, rx*2, ry*2)
|
||||
|
@ -687,7 +687,7 @@ class SVGDocument(object):
|
|||
#~ npath.AddEllipticalArc(cnx-rx, cny-ry, rx*2, ry*2, firstArc, lastArc, False)
|
||||
#~ npath.MoveToPoint(x,y)
|
||||
#~ path.AddPath(npath)
|
||||
|
||||
|
||||
elif type == 'Z':
|
||||
#~ Bugginess:
|
||||
#~ CloseSubpath() doesn't change the
|
||||
|
@ -699,17 +699,17 @@ class SVGDocument(object):
|
|||
#~ results
|
||||
#~ Manually closing the path *and* calling CloseSubpath() appears
|
||||
#~ to give correct results on win32
|
||||
|
||||
|
||||
pt = self.firstPoints.pop()
|
||||
path.AddLineToPoint(pt)
|
||||
path.CloseSubpath()
|
||||
|
||||
|
||||
def render(self, context):
|
||||
if not hasattr(self, "ops"):
|
||||
return
|
||||
for op, args in self.ops:
|
||||
op(context, *args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from tests.test_document import *
|
||||
unittest.main()
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
"""
|
||||
SVG path data parser
|
||||
|
||||
|
||||
|
||||
|
||||
Usage:
|
||||
steps = svg.parseString(pathdata)
|
||||
for command, arguments in steps:
|
||||
pass
|
||||
|
||||
|
||||
"""
|
||||
|
||||
from pyparsing import (ParserElement, Literal, Word, CaselessLiteral,
|
||||
from pyparsing import (ParserElement, Literal, Word, CaselessLiteral,
|
||||
Optional, Combine, Forward, ZeroOrMore, nums, oneOf, Group, ParseException, OneOrMore)
|
||||
|
||||
|
||||
#ParserElement.enablePackrat()
|
||||
|
||||
def Command(char):
|
||||
""" Case insensitive but case preserving"""
|
||||
return CaselessPreservingLiteral(char)
|
||||
|
||||
|
||||
def Arguments(token):
|
||||
return Group(token)
|
||||
|
||||
|
||||
|
||||
|
||||
class CaselessPreservingLiteral(CaselessLiteral):
|
||||
""" Like CaselessLiteral, but returns the match as found
|
||||
instead of as defined.
|
||||
|
@ -40,8 +40,8 @@ class CaselessPreservingLiteral(CaselessLiteral):
|
|||
exc = self.myException
|
||||
exc.loc = loc
|
||||
exc.pstr = instring
|
||||
raise exc
|
||||
|
||||
raise exc
|
||||
|
||||
def Sequence(token):
|
||||
""" A sequence of the token"""
|
||||
return OneOrMore(token+maybeComma)
|
||||
|
@ -58,13 +58,13 @@ def convertToFloat(s, loc, toks):
|
|||
|
||||
exponent = CaselessLiteral("e")+Optional(sign)+Word(nums)
|
||||
|
||||
#note that almost all these fields are optional,
|
||||
#note that almost all these fields are optional,
|
||||
#and this can match almost anything. We rely on Pythons built-in
|
||||
#float() function to clear out invalid values - loosely matching like this
|
||||
#speeds up parsing quite a lot
|
||||
floatingPointConstant = Combine(
|
||||
Optional(sign) +
|
||||
Optional(Word(nums)) +
|
||||
Optional(sign) +
|
||||
Optional(Word(nums)) +
|
||||
Optional(Literal(".") + Optional(Word(nums)))+
|
||||
Optional(exponent)
|
||||
)
|
||||
|
@ -75,7 +75,7 @@ number = floatingPointConstant
|
|||
|
||||
#same as FP constant but don't allow a - sign
|
||||
nonnegativeNumber = Combine(
|
||||
Optional(Word(nums)) +
|
||||
Optional(Word(nums)) +
|
||||
Optional(Literal(".") + Optional(Word(nums)))+
|
||||
Optional(exponent)
|
||||
)
|
||||
|
@ -120,7 +120,7 @@ ellipticalArcArgument = Group(
|
|||
coordinatePair #(x,y)
|
||||
)
|
||||
|
||||
|
||||
|
||||
ellipticalArc = Group(Command("A") + Arguments(Sequence(ellipticalArcArgument)))
|
||||
|
||||
smoothQuadraticBezierCurveto = Group(Command("T") + Arguments(coordinatePairSequence))
|
||||
|
@ -155,39 +155,37 @@ def profile():
|
|||
p.disable()
|
||||
p.print_stats()
|
||||
|
||||
bpath = """M204.33 139.83 C196.33 133.33 206.68 132.82 206.58 132.58 C192.33 97.08 169.35
|
||||
81.41 167.58 80.58 C162.12 78.02 159.48 78.26 160.45 76.97 C161.41 75.68 167.72 79.72 168.58
|
||||
80.33 C193.83 98.33 207.58 132.33 207.58 132.33 C207.58 132.33 209.33 133.33 209.58 132.58
|
||||
C219.58 103.08 239.58 87.58 246.33 81.33 C253.08 75.08 256.63 74.47 247.33 81.58 C218.58 103.58
|
||||
210.34 132.23 210.83 132.33 C222.33 134.83 211.33 140.33 211.83 139.83 C214.85 136.81 214.83 145.83 214.83
|
||||
145.83 C214.83 145.83 231.83 110.83 298.33 66.33 C302.43 63.59 445.83 -14.67 395.83 80.83 C393.24 85.79 375.83
|
||||
bpath = """M204.33 139.83 C196.33 133.33 206.68 132.82 206.58 132.58 C192.33 97.08 169.35
|
||||
81.41 167.58 80.58 C162.12 78.02 159.48 78.26 160.45 76.97 C161.41 75.68 167.72 79.72 168.58
|
||||
80.33 C193.83 98.33 207.58 132.33 207.58 132.33 C207.58 132.33 209.33 133.33 209.58 132.58
|
||||
C219.58 103.08 239.58 87.58 246.33 81.33 C253.08 75.08 256.63 74.47 247.33 81.58 C218.58 103.58
|
||||
210.34 132.23 210.83 132.33 C222.33 134.83 211.33 140.33 211.83 139.83 C214.85 136.81 214.83 145.83 214.83
|
||||
145.83 C214.83 145.83 231.83 110.83 298.33 66.33 C302.43 63.59 445.83 -14.67 395.83 80.83 C393.24 85.79 375.83
|
||||
105.83 375.83 105.83 C375.83 105.83 377.33 114.33 371.33 121.33 C370.3 122.53 367.83 134.33 361.83 140.83 C360.14 142.67
|
||||
361.81 139.25 361.83 140.83 C362.33 170.83 337.76 170.17 339.33 170.33 C348.83 171.33 350.19 183.66 350.33 183.83 C355.83
|
||||
190.33 353.83 191.83 355.83 194.83 C366.63 211.02 355.24 210.05 356.83 212.83 C360.83 219.83 355.99 222.72 357.33 224.83
|
||||
C360.83 230.33 354.75 233.84 354.83 235.33 C355.33 243.83 349.67 240.73 349.83 244.33 C350.33 255.33 346.33 250.83 343.83 254.83
|
||||
361.81 139.25 361.83 140.83 C362.33 170.83 337.76 170.17 339.33 170.33 C348.83 171.33 350.19 183.66 350.33 183.83 C355.83
|
||||
190.33 353.83 191.83 355.83 194.83 C366.63 211.02 355.24 210.05 356.83 212.83 C360.83 219.83 355.99 222.72 357.33 224.83
|
||||
C360.83 230.33 354.75 233.84 354.83 235.33 C355.33 243.83 349.67 240.73 349.83 244.33 C350.33 255.33 346.33 250.83 343.83 254.83
|
||||
C336.33 266.83 333.46 262.38 332.83 263.83 C329.83 270.83 325.81 269.15 324.33 270.83 C320.83 274.83 317.33 274.83 315.83 276.33
|
||||
C308.83 283.33 304.86 278.39 303.83 278.83 C287.83 285.83 280.33 280.17 277.83 280.33 C270.33 280.83 271.48 279.67 269.33 277.83
|
||||
C237.83 250.83 219.33 211.83 215.83 206.83 C214.4 204.79 211.35 193.12 212.33 195.83 C214.33 201.33 213.33 250.33 207.83 250.33
|
||||
C202.33 250.33 201.83 204.33 205.33 195.83 C206.43 193.16 204.4 203.72 201.79 206.83 C196.33 213.33 179.5 250.83 147.59 277.83
|
||||
C145.42 279.67 146.58 280.83 138.98 280.33 C136.46 280.17 128.85 285.83 112.65 278.83 C111.61 278.39 107.58 283.33 100.49 276.33
|
||||
C98.97 274.83 95.43 274.83 91.88 270.83 C90.39 269.15 86.31 270.83 83.27 263.83 C82.64 262.38 79.73 266.83 72.13 254.83 C69.6 250.83
|
||||
65.54 255.33 66.05 244.33 C66.22 240.73 60.48 243.83 60.99 235.33 C61.08 233.84 54.91 230.33 58.45 224.83 C59.81 222.72 54.91 219.83
|
||||
58.96 212.83 C60.57 210.05 49.04 211.02 59.97 194.83 C62 191.83 59.97 190.33 65.54 183.83 C65.69 183.66 67.06 171.33 76.69 170.33
|
||||
C78.28 170.17 53.39 170.83 53.9 140.83 C53.92 139.25 55.61 142.67 53.9 140.83 C47.82 134.33 45.32 122.53 44.27 121.33 C38.19 114.33
|
||||
39.71 105.83 39.71 105.83 C39.71 105.83 22.08 85.79 19.46 80.83 C-31.19 -14.67 114.07 63.59 118.22 66.33 C185.58 110.83 202 145.83
|
||||
C308.83 283.33 304.86 278.39 303.83 278.83 C287.83 285.83 280.33 280.17 277.83 280.33 C270.33 280.83 271.48 279.67 269.33 277.83
|
||||
C237.83 250.83 219.33 211.83 215.83 206.83 C214.4 204.79 211.35 193.12 212.33 195.83 C214.33 201.33 213.33 250.33 207.83 250.33
|
||||
C202.33 250.33 201.83 204.33 205.33 195.83 C206.43 193.16 204.4 203.72 201.79 206.83 C196.33 213.33 179.5 250.83 147.59 277.83
|
||||
C145.42 279.67 146.58 280.83 138.98 280.33 C136.46 280.17 128.85 285.83 112.65 278.83 C111.61 278.39 107.58 283.33 100.49 276.33
|
||||
C98.97 274.83 95.43 274.83 91.88 270.83 C90.39 269.15 86.31 270.83 83.27 263.83 C82.64 262.38 79.73 266.83 72.13 254.83 C69.6 250.83
|
||||
65.54 255.33 66.05 244.33 C66.22 240.73 60.48 243.83 60.99 235.33 C61.08 233.84 54.91 230.33 58.45 224.83 C59.81 222.72 54.91 219.83
|
||||
58.96 212.83 C60.57 210.05 49.04 211.02 59.97 194.83 C62 191.83 59.97 190.33 65.54 183.83 C65.69 183.66 67.06 171.33 76.69 170.33
|
||||
C78.28 170.17 53.39 170.83 53.9 140.83 C53.92 139.25 55.61 142.67 53.9 140.83 C47.82 134.33 45.32 122.53 44.27 121.33 C38.19 114.33
|
||||
39.71 105.83 39.71 105.83 C39.71 105.83 22.08 85.79 19.46 80.83 C-31.19 -14.67 114.07 63.59 118.22 66.33 C185.58 110.83 202 145.83
|
||||
202 145.83 C202 145.83 202.36 143.28 203 141.83 C203.64 140.39 204.56 140.02 204.33 139.83 z"""
|
||||
|
||||
def ptest():
|
||||
svg.parseString(bpath)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
|
||||
#~ from tests.test_pathdata import *
|
||||
#~ unittest.main()
|
||||
profile()
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ def PrintHeader():
|
|||
|
||||
def PrintMenu():
|
||||
return '<div id="mainmenu"><ul><li><a href="/">home</a></li><li><a href="/settings">settings</a></li><li><a href="/console">console</a></li><li><a href="/status">status (XML)</a></li></ul></div>'
|
||||
|
||||
|
||||
def PrintFooter():
|
||||
return "</body></html>"
|
||||
|
||||
|
@ -24,7 +24,7 @@ def TReloadPage(action):
|
|||
|
||||
def clear_text(mypass):
|
||||
return mypass
|
||||
|
||||
|
||||
gPronterPtr = 0
|
||||
gWeblog = ""
|
||||
gLogRefresh =5
|
||||
|
@ -80,7 +80,7 @@ class ConnectButton(object):
|
|||
'tools.basic_auth.realm': 'My Print Server',
|
||||
'tools.basic_auth.users': users,
|
||||
'tools.basic_auth.encrypt': clear_text}
|
||||
|
||||
|
||||
class DisconnectButton(object):
|
||||
def index(self):
|
||||
#handle connect push, then reload page
|
||||
|
@ -149,7 +149,7 @@ class MoveButton(object):
|
|||
'tools.basic_auth.realm': 'My Print Server',
|
||||
'tools.basic_auth.users': users,
|
||||
'tools.basic_auth.encrypt': clear_text}
|
||||
|
||||
|
||||
class CustomButton(object):
|
||||
def button(self, *args):
|
||||
if not args:
|
||||
|
@ -164,7 +164,7 @@ class CustomButton(object):
|
|||
'tools.basic_auth.realm': 'My Print Server',
|
||||
'tools.basic_auth.users': users,
|
||||
'tools.basic_auth.encrypt': clear_text}
|
||||
|
||||
|
||||
class HomeButton(object):
|
||||
def axis(self, *args):
|
||||
if not args:
|
||||
|
@ -183,13 +183,13 @@ class HomeButton(object):
|
|||
if(taxis == "all"):
|
||||
gPronterPtr.onecmd('home')
|
||||
return ReloadPage("Home All")
|
||||
|
||||
|
||||
axis.exposed = True
|
||||
axis._cp_config = {'tools.basic_auth.on': True,
|
||||
'tools.basic_auth.realm': 'My Print Server',
|
||||
'tools.basic_auth.users': users,
|
||||
'tools.basic_auth.encrypt': clear_text}
|
||||
|
||||
|
||||
class XMLstatus(object):
|
||||
def index(self):
|
||||
#handle connect push, then reload page
|
||||
|
@ -203,7 +203,7 @@ class XMLstatus(object):
|
|||
state="Printing"
|
||||
if gPronterPtr.paused:
|
||||
state="Paused"
|
||||
|
||||
|
||||
txt=txt+'<state>'+state+'</state>\n'
|
||||
txt=txt+'<file>'+str(gPronterPtr.filename)+'</file>\n'
|
||||
txt=txt+'<status>'+str(gPronterPtr.status.GetStatusText())+'</status>\n'
|
||||
|
@ -234,13 +234,13 @@ class XMLstatus(object):
|
|||
index.exposed = True
|
||||
|
||||
class WebInterface(object):
|
||||
|
||||
|
||||
def __init__(self, pface):
|
||||
if (sys.version_info[1] > 6):
|
||||
# 'allow_no_value' wasn't added until 2.7
|
||||
config = ConfigParser.SafeConfigParser(allow_no_value=True)
|
||||
# 'allow_no_value' wasn't added until 2.7
|
||||
config = ConfigParser.SafeConfigParser(allow_no_value=True)
|
||||
else:
|
||||
config = ConfigParser.SafeConfigParser()
|
||||
config = ConfigParser.SafeConfigParser()
|
||||
config.read(configfile(pface.web_auth_config or 'auth.config'))
|
||||
users[config.get("user", "user")] = config.get("user", "pass")
|
||||
self.pface = pface
|
||||
|
@ -248,12 +248,12 @@ class WebInterface(object):
|
|||
global gWeblog
|
||||
self.name="<div id='title'>Pronterface Web-Interface</div>"
|
||||
gWeblog = ""
|
||||
gPronterPtr = self.pface
|
||||
gPronterPtr = self.pface
|
||||
|
||||
settings = SettingsPage()
|
||||
logpage = LogPage()
|
||||
console = ConsolePage()
|
||||
|
||||
|
||||
#actions
|
||||
connect = ConnectButton()
|
||||
disconnect = DisconnectButton()
|
||||
|
@ -264,7 +264,7 @@ class WebInterface(object):
|
|||
home = HomeButton()
|
||||
move = MoveButton()
|
||||
custom =CustomButton()
|
||||
|
||||
|
||||
def index(self):
|
||||
pageText=PrintHeader()+self.name+PrintMenu()
|
||||
pageText+="<div id='content'>\n"
|
||||
|
@ -274,20 +274,20 @@ class WebInterface(object):
|
|||
pageText+="<li><a href='/reset'>Reset</a></li>\n"
|
||||
pageText+="<li><a href='/printbutton'>Print</a></li>\n"
|
||||
pageText+="<li><a href='/pausebutton'>Pause</a></li>\n"
|
||||
|
||||
|
||||
for i in gPronterPtr.cpbuttons:
|
||||
pageText+="<li><a href='/custom/button/"+i[1]+"'>"+i[0]+"</a></li>\n"
|
||||
|
||||
|
||||
#for i in gPronterPtr.custombuttons:
|
||||
# print(str(i));
|
||||
|
||||
|
||||
pageText+="</ul>\n"
|
||||
pageText+="</div>\n"
|
||||
pageText+="<div id='gui'>\n"
|
||||
pageText+="<div id='control_xy'>"
|
||||
pageText+="<img src='/images/control_xy.png' usemap='#xymap'/>"
|
||||
pageText+='<map name="xymap">'
|
||||
|
||||
|
||||
pageText+='<area shape="rect" coords="8,5,51,48" href="/home/axis/x" alt="X Home" title="X Home" />'
|
||||
pageText+='<area shape="rect" coords="195,6,236,46" href="/home/axis/y" alt="Y Home" title="Y Home" />'
|
||||
pageText+='<area shape="rect" coords="7,192,48,232" href="/home/axis/all" alt="All Home" title="All Home" />'
|
||||
|
@ -336,7 +336,7 @@ class WebInterface(object):
|
|||
# pageText+="<ul><li><b>Bed Temp:</b></li><li><a href='/off'>OFF</a></li><li><a href='/185'>185 (PLA)</a></li><li><a href='/240'>240 (ABS)</a></li></ul>"
|
||||
# pageText+="</div>"
|
||||
# pageText+="</div>"
|
||||
|
||||
|
||||
pageText=pageText+"<div id='file'>File Loaded: <i>"+str(gPronterPtr.filename)+"</i></div>"
|
||||
pageText+="<div id='logframe'><iframe src='/logpage' width='100%' height='100%'>iFraming Not Supported?? No log for you.</iframe></div>"
|
||||
pageText+=PrintFooter()
|
||||
|
@ -357,7 +357,7 @@ class WebInterfaceStub(object):
|
|||
|
||||
def KillWebInterfaceThread():
|
||||
cherrypy.engine.exit()
|
||||
|
||||
|
||||
def StartWebInterfaceThread(webInterface):
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
cherrypy.config.update({'engine.autoreload_on':False})
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
# This file is part of the Printrun suite.
|
||||
#
|
||||
#
|
||||
# Printrun is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Printrun is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import wx, os, math
|
||||
from bufferedcanvas import *
|
||||
from printrun_utils import *
|
||||
from printrun_utils import *
|
||||
|
||||
def sign(n):
|
||||
if n < 0: return -1
|
||||
|
@ -56,10 +56,10 @@ class XYButtons(BufferedCanvas):
|
|||
self.lastMove = None
|
||||
self.lastCorner = None
|
||||
|
||||
self.bgcolor = wx.Colour()
|
||||
self.bgcolor.SetFromName(bgcolor)
|
||||
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
|
||||
|
||||
self.bgcolor = wx.Colour()
|
||||
self.bgcolor.SetFromName(bgcolor)
|
||||
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
|
||||
|
||||
BufferedCanvas.__init__(self, parent, ID)
|
||||
self.SetSize(self.bg_bmp.GetSize())
|
||||
|
||||
|
@ -70,11 +70,11 @@ class XYButtons(BufferedCanvas):
|
|||
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
|
||||
self.Bind(wx.EVT_KEY_UP, self.OnKey)
|
||||
wx.GetTopLevelParent(self).Bind(wx.EVT_CHAR_HOOK, self.OnTopLevelKey)
|
||||
|
||||
|
||||
def disable(self):
|
||||
self.enabled = False
|
||||
self.update()
|
||||
|
||||
|
||||
def enable(self):
|
||||
self.enabled = True
|
||||
self.update()
|
||||
|
@ -84,7 +84,7 @@ class XYButtons(BufferedCanvas):
|
|||
self.moveCallback(*self.lastMove)
|
||||
if self.lastCorner:
|
||||
self.cornerCallback(self.lastCorner)
|
||||
|
||||
|
||||
def clearRepeat(self):
|
||||
self.lastMove = None
|
||||
self.lastCorner = None
|
||||
|
@ -95,7 +95,7 @@ class XYButtons(BufferedCanvas):
|
|||
pxlen = x1 - pos.x
|
||||
pylen = y1 - pos.y
|
||||
return abs(xlen*pylen-ylen*pxlen)/math.sqrt(xlen**2+ylen**2)
|
||||
|
||||
|
||||
def distanceToPoint(self, x1, y1, x2, y2):
|
||||
return math.sqrt((x1-x2)**2 + (y1-y2)**2)
|
||||
|
||||
|
@ -103,17 +103,17 @@ class XYButtons(BufferedCanvas):
|
|||
idx = self.keypad_idx + 1
|
||||
if idx > 2: idx = 0
|
||||
return idx
|
||||
|
||||
|
||||
def setKeypadIndex(self, idx):
|
||||
self.keypad_idx = idx
|
||||
self.update()
|
||||
|
||||
|
||||
def getMovement(self):
|
||||
xdir = [1, 0, -1, 0][self.quadrant]
|
||||
ydir = [0, 1, 0, -1][self.quadrant]
|
||||
magnitude = math.pow(10, self.concentric-1)
|
||||
return (magnitude * xdir, magnitude * ydir)
|
||||
|
||||
|
||||
def lookupConcentric(self, radius):
|
||||
idx = 0
|
||||
for r in XYButtons.concentric_circle_radii[1:]:
|
||||
|
@ -134,27 +134,27 @@ class XYButtons(BufferedCanvas):
|
|||
quadrant = 1 # Up
|
||||
else:
|
||||
quadrant = 2 # Left
|
||||
|
||||
|
||||
idx = self.lookupConcentric(radius)
|
||||
return (quadrant, idx)
|
||||
|
||||
|
||||
def mouseOverKeypad(self, mpos):
|
||||
for idx, kpos in XYButtons.keypad_positions.items():
|
||||
radius = self.distanceToPoint(mpos[0], mpos[1], kpos[0], kpos[1])
|
||||
if radius < 9:
|
||||
return idx
|
||||
return None
|
||||
|
||||
|
||||
def drawPartialPie(self, gc, center, r1, r2, angle1, angle2):
|
||||
p1 = wx.Point(center.x + r1*math.cos(angle1), center.y + r1*math.sin(angle1))
|
||||
|
||||
|
||||
path = gc.CreatePath()
|
||||
path.MoveToPoint(p1.x, p1.y)
|
||||
path.AddArc(center.x, center.y, r1, angle1, angle2, True)
|
||||
path.AddArc(center.x, center.y, r2, angle2, angle1, False)
|
||||
path.AddLineToPoint(p1.x, p1.y)
|
||||
gc.DrawPath(path)
|
||||
|
||||
|
||||
def highlightQuadrant(self, gc, quadrant, concentric):
|
||||
assert(quadrant >= 0 and quadrant <= 3)
|
||||
assert(concentric >= 0 and concentric <= 3)
|
||||
|
@ -175,12 +175,12 @@ class XYButtons(BufferedCanvas):
|
|||
elif quadrant == 3:
|
||||
a1, a2 = (math.pi*0.25, math.pi*0.75)
|
||||
center.y += inner_ring_radius
|
||||
|
||||
|
||||
r1 = XYButtons.concentric_circle_radii[concentric]
|
||||
r2 = XYButtons.concentric_circle_radii[concentric+1]
|
||||
|
||||
self.drawPartialPie(gc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge)
|
||||
|
||||
|
||||
def drawCorner(self, gc, x, y, angle=0.0):
|
||||
w, h = XYButtons.corner_size
|
||||
|
||||
|
@ -201,7 +201,7 @@ class XYButtons(BufferedCanvas):
|
|||
w, h = XYButtons.corner_size
|
||||
cx, cy = XYButtons.center
|
||||
ww, wh = self.GetSizeTuple()
|
||||
|
||||
|
||||
inset = 10
|
||||
if corner == 0:
|
||||
x, y = (cx - ww/2 + inset, cy - wh/2 + inset)
|
||||
|
@ -215,10 +215,10 @@ class XYButtons(BufferedCanvas):
|
|||
elif corner == 3:
|
||||
x, y = (cx - ww/2 + inset, cy + wh/2 - inset)
|
||||
self.drawCorner(gc, x+w/2, y-h/2, math.pi*3/2)
|
||||
|
||||
|
||||
|
||||
def draw(self, dc, w, h):
|
||||
dc.SetBackground(wx.Brush(self.bgcolor))
|
||||
dc.SetBackground(wx.Brush(self.bgcolor))
|
||||
dc.Clear()
|
||||
gc = wx.GraphicsContext.Create(dc)
|
||||
|
||||
|
@ -226,7 +226,7 @@ class XYButtons(BufferedCanvas):
|
|||
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
|
||||
gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4))
|
||||
|
@ -238,13 +238,13 @@ class XYButtons(BufferedCanvas):
|
|||
self.highlightQuadrant(gc, self.quadrant, self.concentric)
|
||||
elif self.corner != None:
|
||||
self.highlightCorner(gc, self.corner)
|
||||
|
||||
|
||||
if self.keypad_idx >= 0:
|
||||
padw, padh = (self.keypad_bmp.GetWidth(), self.keypad_bmp.GetHeight())
|
||||
pos = XYButtons.keypad_positions[self.keypad_idx]
|
||||
pos = (pos[0] - padw/2 - 3, pos[1] - padh/2 - 3)
|
||||
gc.DrawBitmap(self.keypad_bmp, pos[0], pos[1], padw, padh)
|
||||
|
||||
|
||||
# Draw label overlays
|
||||
gc.SetPen(wx.Pen(wx.Colour(255,255,255,128), 1))
|
||||
gc.SetBrush(wx.Brush(wx.Colour(255,255,255,128+64)))
|
||||
|
@ -256,7 +256,7 @@ class XYButtons(BufferedCanvas):
|
|||
gc.SetPen(wx.Pen(self.bgcolor, 0))
|
||||
gc.SetBrush(wx.Brush(self.bgcolormask))
|
||||
gc.DrawRectangle(0, 0, w, h)
|
||||
|
||||
|
||||
|
||||
# Used to check exact position of keypad dots, should we ever resize the bg image
|
||||
# for idx, kpos in XYButtons.label_overlay_positions.items():
|
||||
|
@ -289,7 +289,7 @@ class XYButtons(BufferedCanvas):
|
|||
else:
|
||||
evt.Skip()
|
||||
return
|
||||
|
||||
|
||||
if self.moveCallback:
|
||||
self.concentric = self.keypad_idx
|
||||
x, y = self.getMovement()
|
||||
|
@ -301,7 +301,7 @@ class XYButtons(BufferedCanvas):
|
|||
def OnMotion(self, event):
|
||||
if not self.enabled:
|
||||
return
|
||||
|
||||
|
||||
oldcorner = self.corner
|
||||
oldq, oldc = self.quadrant, self.concentric
|
||||
|
||||
|
@ -318,7 +318,7 @@ class XYButtons(BufferedCanvas):
|
|||
# If mouse hovers in space between quadrants, don't commit to a quadrant
|
||||
if riseDist <= XYButtons.spacer or fallDist <= XYButtons.spacer:
|
||||
self.quadrant = None
|
||||
|
||||
|
||||
cx, cy = XYButtons.center
|
||||
if mpos.x < cx and mpos.y < cy:
|
||||
self.corner = 0
|
||||
|
@ -335,7 +335,7 @@ class XYButtons(BufferedCanvas):
|
|||
def OnLeftDown(self, event):
|
||||
if not self.enabled:
|
||||
return
|
||||
|
||||
|
||||
# Take focus when clicked so that arrow keys can control movement
|
||||
self.SetFocus()
|
||||
|
||||
|
@ -362,7 +362,7 @@ class XYButtons(BufferedCanvas):
|
|||
self.setKeypadIndex(-1)
|
||||
else:
|
||||
self.setKeypadIndex(idx)
|
||||
|
||||
|
||||
def OnLeaveWindow(self, evt):
|
||||
self.quadrant = None
|
||||
self.concentric = None
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
# This file is part of the Printrun suite.
|
||||
#
|
||||
#
|
||||
# Printrun is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Printrun is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import wx, os, math
|
||||
from bufferedcanvas import *
|
||||
from printrun_utils import *
|
||||
from printrun_utils import *
|
||||
|
||||
def sign(n):
|
||||
if n < 0: return -1
|
||||
|
@ -42,9 +42,9 @@ class ZButtons(BufferedCanvas):
|
|||
# Remember the last clicked value, so we can repeat when spacebar pressed
|
||||
self.lastValue = None
|
||||
|
||||
self.bgcolor = wx.Colour()
|
||||
self.bgcolor.SetFromName(bgcolor)
|
||||
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
|
||||
self.bgcolor = wx.Colour()
|
||||
self.bgcolor.SetFromName(bgcolor)
|
||||
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
|
||||
|
||||
BufferedCanvas.__init__(self, parent, ID)
|
||||
|
||||
|
@ -59,7 +59,7 @@ class ZButtons(BufferedCanvas):
|
|||
def disable(self):
|
||||
self.enabled = False
|
||||
self.update()
|
||||
|
||||
|
||||
def enable(self):
|
||||
self.enabled = True
|
||||
self.update()
|
||||
|
@ -78,7 +78,7 @@ class ZButtons(BufferedCanvas):
|
|||
return idx
|
||||
idx += 1
|
||||
return None
|
||||
|
||||
|
||||
def highlight(self, gc, rng, dir):
|
||||
assert(rng >= -1 and rng <= 3)
|
||||
assert(dir >= -1 and dir <= 1)
|
||||
|
@ -93,13 +93,13 @@ class ZButtons(BufferedCanvas):
|
|||
gc.DrawRoundedRectangle(x, y, w, h, 4)
|
||||
# gc.DrawRectangle(x, y, w, h)
|
||||
# self.drawPartialPie(dc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge)
|
||||
|
||||
|
||||
def getRangeDir(self, pos):
|
||||
ydelta = ZButtons.center[1] - pos[1]
|
||||
return (self.lookupRange(abs(ydelta)), sign(ydelta))
|
||||
|
||||
def draw(self, dc, w, h):
|
||||
dc.SetBackground(wx.Brush(self.bgcolor))
|
||||
dc.SetBackground(wx.Brush(self.bgcolor))
|
||||
dc.Clear()
|
||||
gc = wx.GraphicsContext.Create(dc)
|
||||
if self.bg_bmp:
|
||||
|
@ -114,7 +114,7 @@ class ZButtons(BufferedCanvas):
|
|||
if kpos and idx != self.range:
|
||||
r = kpos[2]
|
||||
gc.DrawEllipse(ZButtons.center[0]-kpos[0]-r, ZButtons.center[1]-kpos[1]-r, r*2, r*2)
|
||||
|
||||
|
||||
# Top 'layer' is the mouse-over highlights
|
||||
gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4))
|
||||
gc.SetBrush(wx.Brush(wx.Colour(0,0,0,128)))
|
||||
|
@ -132,7 +132,7 @@ class ZButtons(BufferedCanvas):
|
|||
def OnMotion(self, event):
|
||||
if not self.enabled:
|
||||
return
|
||||
|
||||
|
||||
oldr, oldd = self.range, self.direction
|
||||
|
||||
mpos = event.GetPosition()
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
# This file is part of the Printrun suite.
|
||||
#
|
||||
#
|
||||
# Printrun is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Printrun is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
@ -70,7 +70,7 @@ class scapewin(wx.Frame):
|
|||
self.SetIcon(wx.Icon("plater.ico",wx.BITMAP_TYPE_ICO))
|
||||
self.SetClientSize(size)
|
||||
self.panel=wx.Panel(self,size=size)
|
||||
|
||||
|
||||
|
||||
"""
|
||||
if __name__ == '__main__':
|
||||
|
@ -82,4 +82,3 @@ if __name__ == '__main__':
|
|||
"""
|
||||
zimage("catposthtmap2.jpg","testobj.stl")
|
||||
del a
|
||||
|
||||
|
|
217
pronsole.py
217
pronsole.py
|
@ -1,23 +1,23 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of the Printrun suite.
|
||||
#
|
||||
#
|
||||
# Printrun is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Printrun is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import cmd, sys
|
||||
import cmd, sys
|
||||
import glob, os, time, datetime
|
||||
import sys, subprocess
|
||||
import sys, subprocess
|
||||
import math, codecs
|
||||
from math import sqrt
|
||||
|
||||
|
@ -42,7 +42,7 @@ except:
|
|||
|
||||
def dosify(name):
|
||||
return os.path.split(name)[1].split(".")[0][:8]+".g"
|
||||
|
||||
|
||||
def measurements(g):
|
||||
Xcur=0.0
|
||||
Ycur=0.0
|
||||
|
@ -56,8 +56,8 @@ def measurements(g):
|
|||
Xtot=0
|
||||
Ytot=0
|
||||
Ztot=0
|
||||
|
||||
|
||||
|
||||
|
||||
for i in g:
|
||||
if "X" in i and ("G1" in i or "G0" in i):
|
||||
try:
|
||||
|
@ -73,7 +73,7 @@ def measurements(g):
|
|||
if Ycur>Ymax: Ymax=Ycur
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
if "Z" in i and ("G1" in i or "G0" in i):
|
||||
try:
|
||||
Zcur = float(i.split("Z")[1].split(" ")[0])
|
||||
|
@ -81,12 +81,12 @@ def measurements(g):
|
|||
if Zcur>Zmax: Zmax=Zcur
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
Xtot = Xmax - Xmin
|
||||
Ytot = Ymax - Ymin
|
||||
Ztot = Zmax - Zmin
|
||||
|
||||
Ztot = Zmax - Zmin
|
||||
|
||||
return (Xtot,Ytot,Ztot,Xmin,Xmax,Ymin,Ymax,Zmin,Zmax)
|
||||
|
||||
def totalelength(g):
|
||||
|
@ -108,11 +108,11 @@ def get_coordinate_value(axis, parts):
|
|||
return float(i[1:])
|
||||
return None
|
||||
|
||||
def hypot3d(X1, Y1, Z1, X2=0.0, Y2=0.0, Z2=0.0):
|
||||
def hypot3d(X1, Y1, Z1, X2=0.0, Y2=0.0, Z2=0.0):
|
||||
return math.hypot(X2-X1, math.hypot(Y2-Y1, Z2-Z1))
|
||||
|
||||
def estimate_duration(g):
|
||||
|
||||
|
||||
lastx = lasty = lastz = laste = lastf = 0.0
|
||||
x = y = z = e = f = 0.0
|
||||
currenttravel = 0.0
|
||||
|
@ -150,7 +150,7 @@ def estimate_duration(g):
|
|||
f = get_coordinate_value("F", parts[1:])
|
||||
if f is None: f=lastf
|
||||
else: f /= 60.0 # mm/s vs mm/m
|
||||
|
||||
|
||||
# given last feedrate and current feedrate calculate the distance needed to achieve current feedrate.
|
||||
# if travel is longer than req'd distance, then subtract distance to achieve full speed, and add the time it took to get there.
|
||||
# then calculate the time taken to complete the remaining distance
|
||||
|
@ -279,7 +279,7 @@ class pronsole(cmd.Cmd):
|
|||
self.webrequested=False
|
||||
self.web_config=None
|
||||
self.web_auth_config=None
|
||||
|
||||
|
||||
def set_temp_preset(self,key,value):
|
||||
if not key.startswith("bed"):
|
||||
self.temps["pla"] = str(self.settings.temperature_pla)
|
||||
|
@ -289,7 +289,7 @@ class pronsole(cmd.Cmd):
|
|||
self.bedtemps["pla"] = str(self.settings.bedtemp_pla)
|
||||
self.bedtemps["abs"] = str(self.settings.bedtemp_abs)
|
||||
print "Bed temperature presets updated, pla:%s, abs:%s" % (self.bedtemps["pla"],self.bedtemps["abs"])
|
||||
|
||||
|
||||
def scanserial(self):
|
||||
"""scan for available ports. return a list of device names."""
|
||||
baselist=[]
|
||||
|
@ -309,16 +309,16 @@ class pronsole(cmd.Cmd):
|
|||
print "Printer is now online"
|
||||
sys.stdout.write(self.prompt)
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def help_help(self,l):
|
||||
self.do_help("")
|
||||
|
||||
|
||||
def do_gcodes(self,l):
|
||||
self.help_gcodes()
|
||||
|
||||
|
||||
def help_gcodes(self):
|
||||
print "Gcodes are passed through to the printer as they are"
|
||||
|
||||
|
||||
def complete_macro(self,text,line,begidx,endidx):
|
||||
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "):
|
||||
return [i for i in self.macros.keys() if i.startswith(text)]
|
||||
|
@ -326,7 +326,7 @@ class pronsole(cmd.Cmd):
|
|||
return [i for i in ["/D", "/S"] + self.completenames(text) if i.startswith(text)]
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
def hook_macro(self,l):
|
||||
l = l.rstrip()
|
||||
ls = l.lstrip()
|
||||
|
@ -336,8 +336,8 @@ class pronsole(cmd.Cmd):
|
|||
# pass the unprocessed line to regular command processor to not require empty line in .pronsolerc
|
||||
return self.onecmd(l)
|
||||
self.cur_macro_def += l + "\n"
|
||||
|
||||
def end_macro(self):
|
||||
|
||||
def end_macro(self):
|
||||
if self.__dict__.has_key("onecmd"): del self.onecmd # remove override
|
||||
self.prompt="PC>"
|
||||
if self.cur_macro_def!="":
|
||||
|
@ -360,7 +360,7 @@ class pronsole(cmd.Cmd):
|
|||
else:
|
||||
print "Empty macro - cancelled"
|
||||
del self.cur_macro_name,self.cur_macro_def
|
||||
|
||||
|
||||
def compile_macro_line(self,line):
|
||||
line = line.rstrip()
|
||||
ls = line.lstrip()
|
||||
|
@ -370,7 +370,7 @@ class pronsole(cmd.Cmd):
|
|||
return ws + ls[1:] + "\n" # python mode
|
||||
else:
|
||||
return ws + 'self.onecmd("'+ls+'".format(*arg))\n' # parametric command mode
|
||||
|
||||
|
||||
def compile_macro(self,macro_name,macro_def):
|
||||
if macro_def.strip() == "":
|
||||
print "Empty macro - cancelled"
|
||||
|
@ -384,7 +384,7 @@ class pronsole(cmd.Cmd):
|
|||
pycode += self.compile_macro_line(l)
|
||||
exec pycode
|
||||
return macro
|
||||
|
||||
|
||||
def start_macro(self,macro_name,prev_definition="",suppress_instructions=False):
|
||||
if not self.processing_rc and not suppress_instructions:
|
||||
print "Enter macro using indented lines, end with empty line"
|
||||
|
@ -392,7 +392,7 @@ class pronsole(cmd.Cmd):
|
|||
self.cur_macro_def = ""
|
||||
self.onecmd = self.hook_macro # override onecmd temporarily
|
||||
self.prompt="..>"
|
||||
|
||||
|
||||
def delete_macro(self,macro_name):
|
||||
if macro_name in self.macros.keys():
|
||||
delattr(self.__class__,"do_"+macro_name)
|
||||
|
@ -427,7 +427,7 @@ class pronsole(cmd.Cmd):
|
|||
self.start_macro(macro_name,self.macros[macro_name])
|
||||
else:
|
||||
self.start_macro(macro_name)
|
||||
|
||||
|
||||
def help_macro(self):
|
||||
print "Define single-line macro: macro <name> <definition>"
|
||||
print "Define multi-line macro: macro <name>"
|
||||
|
@ -436,7 +436,7 @@ class pronsole(cmd.Cmd):
|
|||
print "Delete macro: macro <name> /d"
|
||||
print "Show macro definition: macro <name> /s"
|
||||
print "'macro' without arguments displays list of defined macros"
|
||||
|
||||
|
||||
def subhelp_macro(self,macro_name):
|
||||
if macro_name in self.macros.keys():
|
||||
macro_def = self.macros[macro_name]
|
||||
|
@ -458,7 +458,7 @@ class pronsole(cmd.Cmd):
|
|||
print "Unknown variable '%s'" % var
|
||||
except ValueError, ve:
|
||||
print "Bad value for variable '%s', expecting %s (%s)" % (var,repr(t)[1:-1],ve.args[0])
|
||||
|
||||
|
||||
def do_set(self,argl):
|
||||
args = argl.split(None,1)
|
||||
if len(args) < 1:
|
||||
|
@ -473,7 +473,7 @@ class pronsole(cmd.Cmd):
|
|||
print "Unknown variable '%s'" % args[0]
|
||||
return
|
||||
self.set(args[0],args[1])
|
||||
|
||||
|
||||
def help_set(self):
|
||||
print "Set variable: set <variable> <value>"
|
||||
print "Show variable: set <variable>"
|
||||
|
@ -486,11 +486,11 @@ class pronsole(cmd.Cmd):
|
|||
return [i for i in self.settings._tabcomplete(line.split()[1]) if i.startswith(text)]
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
def postloop(self):
|
||||
self.p.disconnect()
|
||||
cmd.Cmd.postloop(self)
|
||||
|
||||
|
||||
def load_rc(self,rc_filename):
|
||||
self.processing_rc=True
|
||||
try:
|
||||
|
@ -505,7 +505,7 @@ class pronsole(cmd.Cmd):
|
|||
self.rc_loaded = True
|
||||
finally:
|
||||
self.processing_rc=False
|
||||
|
||||
|
||||
def load_default_rc(self,rc_filename=".pronsolerc"):
|
||||
try:
|
||||
try:
|
||||
|
@ -515,10 +515,10 @@ class pronsole(cmd.Cmd):
|
|||
except IOError:
|
||||
# make sure the filename is initialized
|
||||
self.rc_filename = os.path.abspath(os.path.join(os.path.expanduser("~"),rc_filename))
|
||||
|
||||
|
||||
def save_in_rc(self,key,definition):
|
||||
"""
|
||||
Saves or updates macro or other definitions in .pronsolerc
|
||||
Saves or updates macro or other definitions in .pronsolerc
|
||||
key is prefix that determines what is being defined/updated (e.g. 'macro foo')
|
||||
definition is the full definition (that is written to file). (e.g. 'macro foo move x 10')
|
||||
Set key as empty string to just add (and not overwrite)
|
||||
|
@ -566,17 +566,17 @@ class pronsole(cmd.Cmd):
|
|||
print "Saving failed for",key+":",str(e)
|
||||
finally:
|
||||
del rci,rco
|
||||
|
||||
|
||||
def preloop(self):
|
||||
print "Welcome to the printer console! Type \"help\" for a list of available commands."
|
||||
cmd.Cmd.preloop(self)
|
||||
|
||||
|
||||
def do_connect(self,l):
|
||||
a=l.split()
|
||||
p=self.scanserial()
|
||||
port=self.settings.port
|
||||
if (port == "" or port not in p) and len(p)>0:
|
||||
port=p[0]
|
||||
port=p[0]
|
||||
baud=self.settings.baudrate or 115200
|
||||
if(len(a)>0):
|
||||
port=a[0]
|
||||
|
@ -597,7 +597,7 @@ class pronsole(cmd.Cmd):
|
|||
self.settings.baudrate = baud
|
||||
self.save_in_rc("set baudrate","set baudrate %d" % baud)
|
||||
self.p.connect(port, baud)
|
||||
|
||||
|
||||
def help_connect(self):
|
||||
print "Connect to printer"
|
||||
print "connect <port> <baudrate>"
|
||||
|
@ -607,7 +607,7 @@ class pronsole(cmd.Cmd):
|
|||
print "Available ports: ", " ".join(ports)
|
||||
else:
|
||||
print "No serial ports were automatically found."
|
||||
|
||||
|
||||
def complete_connect(self, text, line, begidx, endidx):
|
||||
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "):
|
||||
return [i for i in self.scanserial() if i.startswith(text)]
|
||||
|
@ -615,13 +615,13 @@ class pronsole(cmd.Cmd):
|
|||
return [i for i in ["2400", "9600", "19200", "38400", "57600", "115200"] if i.startswith(text)]
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
def do_disconnect(self,l):
|
||||
self.p.disconnect()
|
||||
|
||||
|
||||
def help_disconnect(self):
|
||||
print "Disconnects from the printer"
|
||||
|
||||
|
||||
def do_load(self,l):
|
||||
if len(l)==0:
|
||||
print "No file name given."
|
||||
|
@ -633,7 +633,7 @@ class pronsole(cmd.Cmd):
|
|||
self.f=[i.replace("\n","").replace("\r","") for i in open(l)]
|
||||
self.filename=l
|
||||
print "Loaded ",l,", ",len(self.f)," lines."
|
||||
|
||||
|
||||
def complete_load(self, text, line, begidx, endidx):
|
||||
s=line.split()
|
||||
if len(s)>2:
|
||||
|
@ -643,11 +643,11 @@ class pronsole(cmd.Cmd):
|
|||
return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.g*")]
|
||||
else:
|
||||
return glob.glob("*/")+glob.glob("*.g*")
|
||||
|
||||
|
||||
def help_load(self):
|
||||
print "Loads a gcode file (with tab-completion)"
|
||||
|
||||
|
||||
|
||||
|
||||
def do_upload(self,l):
|
||||
if len(l)==0:
|
||||
print "No file name given."
|
||||
|
@ -699,8 +699,8 @@ class pronsole(cmd.Cmd):
|
|||
self.p.clear=1
|
||||
self.p.startprint([])
|
||||
print "A partial file named ",tname," may have been written to the sd card."
|
||||
|
||||
|
||||
|
||||
|
||||
def complete_upload(self, text, line, begidx, endidx):
|
||||
s=line.split()
|
||||
if len(s)>2:
|
||||
|
@ -710,17 +710,17 @@ class pronsole(cmd.Cmd):
|
|||
return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.g*")]
|
||||
else:
|
||||
return glob.glob("*/")+glob.glob("*.g*")
|
||||
|
||||
|
||||
def help_upload(self):
|
||||
print "Uploads a gcode file to the sd card"
|
||||
|
||||
|
||||
|
||||
|
||||
def help_print(self):
|
||||
if self.f is None:
|
||||
print "Send a loaded gcode file to the printer. Load a file with the load command first."
|
||||
else:
|
||||
print "Send a loaded gcode file to the printer. You have "+self.filename+" loaded right now."
|
||||
|
||||
|
||||
def do_print(self, l):
|
||||
if self.f is None:
|
||||
print "No file loaded. Please use load first."
|
||||
|
@ -734,7 +734,7 @@ class pronsole(cmd.Cmd):
|
|||
#self.p.pause()
|
||||
#self.paused=True
|
||||
#self.do_resume(None)
|
||||
|
||||
|
||||
def do_pause(self,l):
|
||||
if self.sdprinting:
|
||||
self.p.send_now("M25")
|
||||
|
@ -743,14 +743,14 @@ class pronsole(cmd.Cmd):
|
|||
print "Not printing, cannot pause."
|
||||
return
|
||||
self.p.pause()
|
||||
#self.p.connect()# This seems to work, but is not a good solution.
|
||||
#self.p.connect()# This seems to work, but is not a good solution.
|
||||
self.paused=True
|
||||
|
||||
|
||||
#self.do_resume(None)
|
||||
|
||||
|
||||
def help_pause(self):
|
||||
print "Pauses a running print"
|
||||
|
||||
|
||||
def do_resume(self,l):
|
||||
if not self.paused:
|
||||
print "Not paused, unable to resume. Start a print first."
|
||||
|
@ -761,16 +761,16 @@ class pronsole(cmd.Cmd):
|
|||
return
|
||||
else:
|
||||
self.p.resume()
|
||||
|
||||
|
||||
def help_resume(self):
|
||||
print "Resumes a paused print."
|
||||
|
||||
|
||||
def emptyline(self):
|
||||
pass
|
||||
|
||||
|
||||
def do_shell(self,l):
|
||||
exec(l)
|
||||
|
||||
|
||||
def listfiles(self,line):
|
||||
if "Begin file list" in line:
|
||||
self.listing=1
|
||||
|
@ -779,7 +779,7 @@ class pronsole(cmd.Cmd):
|
|||
self.recvlisteners.remove(self.listfiles)
|
||||
elif self.listing:
|
||||
self.sdfiles+=[line.replace("\n","").replace("\r","").lower()]
|
||||
|
||||
|
||||
def do_ls(self,l):
|
||||
if not self.p.online:
|
||||
print "Printer is not online. Try connect to it first."
|
||||
|
@ -790,10 +790,10 @@ class pronsole(cmd.Cmd):
|
|||
self.p.send_now("M20")
|
||||
time.sleep(0.5)
|
||||
print " ".join(self.sdfiles)
|
||||
|
||||
|
||||
def help_ls(self):
|
||||
print "lists files on the SD card"
|
||||
|
||||
|
||||
def waitforsdresponse(self,l):
|
||||
if "file.open failed" in l:
|
||||
print "Opening file failed."
|
||||
|
@ -820,13 +820,13 @@ class pronsole(cmd.Cmd):
|
|||
self.percentdone=100.0*int(vals[0])/int(vals[1])
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def do_reset(self,l):
|
||||
self.p.reset()
|
||||
|
||||
|
||||
def help_reset(self):
|
||||
print "Resets the printer."
|
||||
|
||||
|
||||
def do_sdprint(self,l):
|
||||
if not self.p.online:
|
||||
print "Printer is not online. Try connect to it first."
|
||||
|
@ -844,11 +844,11 @@ class pronsole(cmd.Cmd):
|
|||
print "Printing file: "+l.lower()+" from SD card."
|
||||
print "Requesting SD print..."
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
def help_sdprint(self):
|
||||
print "Print a file from the SD card. Tabcompletes with available file names."
|
||||
print "sdprint filename.g"
|
||||
|
||||
|
||||
def complete_sdprint(self, text, line, begidx, endidx):
|
||||
if self.sdfiles==[] and self.p.online:
|
||||
self.listing=2
|
||||
|
@ -857,7 +857,7 @@ class pronsole(cmd.Cmd):
|
|||
time.sleep(0.5)
|
||||
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "):
|
||||
return [i for i in self.sdfiles if i.startswith(text)]
|
||||
|
||||
|
||||
def recvcb(self,l):
|
||||
if "T:" in l:
|
||||
self.tempreadings=l
|
||||
|
@ -868,11 +868,11 @@ class pronsole(cmd.Cmd):
|
|||
sys.stdout.flush()
|
||||
for i in self.recvlisteners:
|
||||
i(l)
|
||||
|
||||
|
||||
def help_shell(self):
|
||||
print "Executes a python command. Example:"
|
||||
print "! os.listdir('.')"
|
||||
|
||||
|
||||
def default(self,l):
|
||||
if(l[0] in self.commandprefixes.upper()):
|
||||
if(self.p and self.p.online):
|
||||
|
@ -890,24 +890,24 @@ class pronsole(cmd.Cmd):
|
|||
return
|
||||
else:
|
||||
cmd.Cmd.default(self,l)
|
||||
|
||||
|
||||
def help_help(self):
|
||||
self.do_help("")
|
||||
|
||||
|
||||
def tempcb(self,l):
|
||||
if "T:" in l:
|
||||
print l.replace("\r","").replace("T","Hotend").replace("B","Bed").replace("\n","").replace("ok ","")
|
||||
|
||||
|
||||
def do_gettemp(self,l):
|
||||
if self.p.online:
|
||||
self.recvlisteners+=[self.tempcb]
|
||||
self.p.send_now("M105")
|
||||
time.sleep(0.75)
|
||||
self.recvlisteners.remove(self.tempcb)
|
||||
|
||||
|
||||
def help_gettemp(self):
|
||||
print "Read the extruder and bed temperature."
|
||||
|
||||
|
||||
def do_settemp(self,l):
|
||||
try:
|
||||
l=l.lower().replace(",",".")
|
||||
|
@ -924,16 +924,16 @@ class pronsole(cmd.Cmd):
|
|||
print "You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0."
|
||||
except:
|
||||
print "You must enter a temperature."
|
||||
|
||||
|
||||
def help_settemp(self):
|
||||
print "Sets the hotend temperature to the value entered."
|
||||
print "Enter either a temperature in celsius or one of the following keywords"
|
||||
print ", ".join([i+"("+self.temps[i]+")" for i in self.temps.keys()])
|
||||
|
||||
|
||||
def complete_settemp(self, text, line, begidx, endidx):
|
||||
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "):
|
||||
return [i for i in self.temps.keys() if i.startswith(text)]
|
||||
|
||||
|
||||
def do_bedtemp(self,l):
|
||||
try:
|
||||
l=l.lower().replace(",",".")
|
||||
|
@ -950,16 +950,16 @@ class pronsole(cmd.Cmd):
|
|||
print "You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0."
|
||||
except:
|
||||
print "You must enter a temperature."
|
||||
|
||||
|
||||
def help_bedtemp(self):
|
||||
print "Sets the bed temperature to the value entered."
|
||||
print "Enter either a temperature in celsius or one of the following keywords"
|
||||
print ", ".join([i+"("+self.bedtemps[i]+")" for i in self.bedtemps.keys()])
|
||||
|
||||
|
||||
def complete_bedtemp(self, text, line, begidx, endidx):
|
||||
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "):
|
||||
return [i for i in self.bedtemps.keys() if i.startswith(text)]
|
||||
|
||||
|
||||
def do_move(self,l):
|
||||
if(len(l.split())<2):
|
||||
print "No move specified."
|
||||
|
@ -999,14 +999,14 @@ class pronsole(cmd.Cmd):
|
|||
self.p.send_now("G91")
|
||||
self.p.send_now("G1 "+axis+str(l[1])+" F"+str(feed))
|
||||
self.p.send_now("G90")
|
||||
|
||||
|
||||
def help_move(self):
|
||||
print "Move an axis. Specify the name of the axis and the amount. "
|
||||
print "move X 10 will move the X axis forward by 10mm at ",self.settings.xy_feedrate,"mm/min (default XY speed)"
|
||||
print "move Y 10 5000 will move the Y axis forward by 10mm at 5000mm/min"
|
||||
print "move Z -1 will move the Z axis down by 1mm at ",self.settings.z_feedrate,"mm/min (default Z speed)"
|
||||
print "Common amounts are in the tabcomplete list."
|
||||
|
||||
|
||||
def complete_move(self, text, line, begidx, endidx):
|
||||
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "):
|
||||
return [i for i in ["X ","Y ","Z ","E "] if i.lower().startswith(text)]
|
||||
|
@ -1020,7 +1020,7 @@ class pronsole(cmd.Cmd):
|
|||
return [i[rlen:] for i in ["-100","-10","-1","-0.1","100","10","1","0.1","-50","-5","-0.5","50","5","0.5","-200","-20","-2","-0.2","200","20","2","0.2"] if i.startswith(base)]
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
def do_extrude(self,l,override=None,overridefeed=300):
|
||||
length=5#default extrusion length
|
||||
feed=self.settings.e_feedrate#default speed
|
||||
|
@ -1053,14 +1053,14 @@ class pronsole(cmd.Cmd):
|
|||
self.p.send_now("G91")
|
||||
self.p.send_now("G1 E"+str(length)+" F"+str(feed))
|
||||
self.p.send_now("G90")
|
||||
|
||||
|
||||
def help_extrude(self):
|
||||
print "Extrudes a length of filament, 5mm by default, or the number of mm given as a parameter"
|
||||
print "extrude - extrudes 5mm of filament at 300mm/min (5mm/s)"
|
||||
print "extrude 20 - extrudes 20mm of filament at 300mm/min (5mm/s)"
|
||||
print "extrude -5 - REVERSES 5mm of filament at 300mm/min (5mm/s)"
|
||||
print "extrude 10 210 - extrudes 10mm of filament at 210mm/min (3.5mm/s)"
|
||||
|
||||
|
||||
def do_reverse(self, l):
|
||||
length=5#default extrusion length
|
||||
feed=self.settings.e_feedrate#default speed
|
||||
|
@ -1082,23 +1082,23 @@ class pronsole(cmd.Cmd):
|
|||
except:
|
||||
print "Invalid speed given."
|
||||
self.do_extrude("",length*-1.0,feed)
|
||||
|
||||
|
||||
def help_reverse(self):
|
||||
print "Reverses the extruder, 5mm by default, or the number of mm given as a parameter"
|
||||
print "reverse - reverses 5mm of filament at 300mm/min (5mm/s)"
|
||||
print "reverse 20 - reverses 20mm of filament at 300mm/min (5mm/s)"
|
||||
print "reverse 10 210 - extrudes 10mm of filament at 210mm/min (3.5mm/s)"
|
||||
print "reverse -5 - EXTRUDES 5mm of filament at 300mm/min (5mm/s)"
|
||||
|
||||
|
||||
def do_exit(self,l):
|
||||
print "Disconnecting from printer..."
|
||||
self.p.disconnect()
|
||||
print "Exiting program. Goodbye!"
|
||||
return True
|
||||
|
||||
|
||||
def help_exit(self):
|
||||
print "Disconnects from the printer and exits the program."
|
||||
|
||||
|
||||
def do_monitor(self,l):
|
||||
interval=5
|
||||
if not self.p.online:
|
||||
|
@ -1121,23 +1121,23 @@ class pronsole(cmd.Cmd):
|
|||
#print (self.tempreadings.replace("\r","").replace("T","Hotend").replace("B","Bed").replace("\n","").replace("ok ",""))
|
||||
if(self.p.printing):
|
||||
print "Print progress: ", 100*float(self.p.queueindex)/len(self.p.mainqueue), "%"
|
||||
|
||||
|
||||
if(self.sdprinting):
|
||||
print "SD print progress: ", self.percentdone,"%"
|
||||
|
||||
|
||||
except:
|
||||
print "Done monitoring."
|
||||
pass
|
||||
self.monitoring=0
|
||||
|
||||
|
||||
def help_monitor(self):
|
||||
print "Monitor a machine's temperatures and an SD print's status."
|
||||
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:
|
||||
|
@ -1166,7 +1166,7 @@ class pronsole(cmd.Cmd):
|
|||
self.do_load(l[0].replace(".stl","_export.gcode"))
|
||||
except Exception,e:
|
||||
print "Skeinforge execution failed: ",e
|
||||
|
||||
|
||||
def complete_skein(self, text, line, begidx, endidx):
|
||||
s=line.split()
|
||||
if len(s)>2:
|
||||
|
@ -1176,14 +1176,14 @@ class pronsole(cmd.Cmd):
|
|||
return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.stl")]
|
||||
else:
|
||||
return glob.glob("*/")+glob.glob("*.stl")
|
||||
|
||||
|
||||
def help_skein(self):
|
||||
print "Creates a gcode file from an stl model using the slicer (with tab-completion)"
|
||||
print "skein filename.stl - create gcode file"
|
||||
print "skein filename.stl view - create gcode file and view using skeiniso"
|
||||
print "skein set - adjust slicer settings"
|
||||
|
||||
|
||||
|
||||
|
||||
def do_home(self,l):
|
||||
if not self.p.online:
|
||||
print "Printer is not online. Unable to move."
|
||||
|
@ -1202,7 +1202,7 @@ class pronsole(cmd.Cmd):
|
|||
if not len(l):
|
||||
self.p.send_now("G28")
|
||||
self.p.send_now("G92 E0")
|
||||
|
||||
|
||||
def help_home(self):
|
||||
print "Homes the printer"
|
||||
print "home - homes all axes and zeroes the extruder(Using G28 and G92)"
|
||||
|
@ -1210,7 +1210,7 @@ class pronsole(cmd.Cmd):
|
|||
print "home z - homes z axis only (Using G28)"
|
||||
print "home e - set extruder position to zero (Using G92)"
|
||||
print "home xyze - homes all axes and zeroes the extruder (Using G28 and G92)"
|
||||
|
||||
|
||||
def parse_cmdline(self,args):
|
||||
import getopt
|
||||
opts,args = getopt.getopt(args, "c:e:hw", ["conf=","config=","help","web","web-config=", "web-auth-config="])
|
||||
|
@ -1240,7 +1240,7 @@ class pronsole(cmd.Cmd):
|
|||
self.processing_args = False
|
||||
|
||||
if __name__=="__main__":
|
||||
|
||||
|
||||
interp=pronsole()
|
||||
interp.parse_cmdline(sys.argv[1:])
|
||||
try:
|
||||
|
@ -1248,4 +1248,3 @@ if __name__=="__main__":
|
|||
except:
|
||||
interp.p.disconnect()
|
||||
#raise
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ from printrun.zbuttons import ZButtons
|
|||
from printrun.graph import Graph
|
||||
from printrun.printrun_utils import pixmapfile, configfile
|
||||
import pronsole
|
||||
|
||||
|
||||
def dosify(name):
|
||||
return os.path.split(name)[1].split(".")[0][:8]+".g"
|
||||
|
||||
|
@ -316,7 +316,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
|||
wx.CallAfter(self.settbtn.SetForegroundColour, "")
|
||||
wx.CallAfter(self.htemp.SetBackgroundColour, "white")
|
||||
wx.CallAfter(self.htemp.Refresh)
|
||||
|
||||
|
||||
def do_settemp(self, l = ""):
|
||||
try:
|
||||
if not l.__class__ in (str, unicode) or not len(l):
|
||||
|
@ -579,7 +579,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
|||
#self.minibtn.Bind(wx.EVT_BUTTON,self.toggleview)
|
||||
|
||||
#uts.Add((25,-1))
|
||||
|
||||
|
||||
#uts.Add((15,-1),flag=wx.EXPAND)
|
||||
#uts.Add(self.minibtn,0,wx.ALIGN_CENTER)
|
||||
|
||||
|
@ -642,7 +642,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
|||
#lls.Add((200,375))
|
||||
|
||||
szbuttons=wx.GridBagSizer()
|
||||
|
||||
|
||||
self.xyb = XYButtons(self.panel, self.moveXY, self.homeButtonClicked, self.spacebarAction, self.settings.bgcolor)
|
||||
szbuttons.Add(self.xyb,pos=(0,1),flag=wx.ALIGN_CENTER)
|
||||
self.zb = ZButtons(self.panel, self.moveZ, self.settings.bgcolor)
|
||||
|
@ -738,7 +738,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
|||
self.btemp.SetValue(i)
|
||||
for i in htemp_choices:
|
||||
if i.split()[0] == str(self.settings.last_temperature).split('.')[0] or i.split()[0] == str(self.settings.last_temperature) :
|
||||
self.htemp.SetValue(i)
|
||||
self.htemp.SetValue(i)
|
||||
|
||||
if( '(' not in self.btemp.Value):
|
||||
self.btemp.SetValue(self.btemp.Value + ' (user)')
|
||||
|
@ -748,7 +748,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
|||
#lls.Add(self.btemp,pos=(4,1),span=(1,3))
|
||||
#lls.Add(self.setbbtn,pos=(4,4),span=(1,2))
|
||||
self.tempdisp=wx.StaticText(self.panel,-1,"")
|
||||
|
||||
|
||||
self.edist=wx.SpinCtrl(self.panel,-1,"5",min=0,max=1000,size=(60,-1))
|
||||
self.edist.SetBackgroundColour((225,200,200))
|
||||
self.edist.SetForegroundColour("black")
|
||||
|
@ -767,7 +767,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.hottgauge=TempGauge(self.panel,size=(200,24),title=_("Heater:"),maxval=230)
|
||||
#lls.Add(self.hottgauge,pos=(7,0),span=(1,4))
|
||||
#self.bedtgauge=TempGauge(self.panel,size=(200,24),title=_("Bed:"),maxval=130)
|
||||
|
@ -778,11 +778,11 @@ 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)
|
||||
|
||||
|
||||
self.graph = Graph(self.panel, wx.ID_ANY)
|
||||
lls.Add(self.graph, pos=(3,5), span=(3,3))
|
||||
lls.Add(self.tempdisp,pos=(6,0),span=(1,1))
|
||||
|
||||
|
||||
self.gviz=gviz.gviz(self.panel,(300,300),
|
||||
build_dimensions=self.build_dimensions_list,
|
||||
grid=(self.settings.preview_grid_step1,self.settings.preview_grid_step2),
|
||||
|
@ -845,12 +845,12 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
|||
self.commandbox.SetSelection(0,len(self.commandbox.history[self.commandbox.histindex]))
|
||||
elif e.GetKeyCode()==wx.WXK_DOWN:
|
||||
if self.commandbox.histindex==len(self.commandbox.history):
|
||||
self.commandbox.history+=[self.commandbox.GetValue()] #save current command
|
||||
self.commandbox.history+=[self.commandbox.GetValue()] #save current command
|
||||
if len(self.commandbox.history):
|
||||
self.commandbox.histindex=(self.commandbox.histindex+1)%len(self.commandbox.history)
|
||||
self.commandbox.SetValue(self.commandbox.history[self.commandbox.histindex])
|
||||
self.commandbox.SetSelection(0,len(self.commandbox.history[self.commandbox.histindex]))
|
||||
|
||||
|
||||
else:
|
||||
e.Skip()
|
||||
|
||||
|
@ -957,10 +957,10 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
|||
b.SetToolTip(wx.ToolTip(_("click to add new custom button")))
|
||||
b.Bind(wx.EVT_BUTTON,self.cbutton_edit)
|
||||
else:
|
||||
b=wx.Button(self.panel,-1,".",size=(1,1))
|
||||
#b=wx.StaticText(self.panel,-1,"",size=(72,22),style=wx.ALIGN_CENTRE+wx.ST_NO_AUTORESIZE) #+wx.SIMPLE_BORDER
|
||||
b.Disable()
|
||||
#continue
|
||||
b=wx.Button(self.panel,-1,".",size=(1,1))
|
||||
#b=wx.StaticText(self.panel,-1,"",size=(72,22),style=wx.ALIGN_CENTRE+wx.ST_NO_AUTORESIZE) #+wx.SIMPLE_BORDER
|
||||
b.Disable()
|
||||
#continue
|
||||
b.custombutton=i
|
||||
b.properties=btndef
|
||||
if btndef is not None:
|
||||
|
@ -984,9 +984,9 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
|||
def nextarg(rest):
|
||||
rest=rest.lstrip()
|
||||
if rest.startswith('"'):
|
||||
return rest[1:].split('"',1)
|
||||
return rest[1:].split('"',1)
|
||||
else:
|
||||
return rest.split(None,1)
|
||||
return rest.split(None,1)
|
||||
#try:
|
||||
num,argstr=nextarg(argstr)
|
||||
num=int(num)
|
||||
|
@ -1385,7 +1385,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
|||
except:
|
||||
break
|
||||
wx.CallAfter(self.status.SetStatusText,_("Not connected to printer."))
|
||||
|
||||
|
||||
def capture(self, func, *args, **kwargs):
|
||||
stdout=sys.stdout
|
||||
cout=None
|
||||
|
@ -1518,7 +1518,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
|||
self.f=[i.replace("\n","").replace("\r","") for i in of]
|
||||
of.close()
|
||||
if self.p.online:
|
||||
wx.CallAfter(self.printbtn.Enable)
|
||||
wx.CallAfter(self.printbtn.Enable)
|
||||
|
||||
wx.CallAfter(self.status.SetStatusText,_("Loaded ")+self.filename+_(", %d lines") % (len(self.f),))
|
||||
wx.CallAfter(self.pausebtn.Disable)
|
||||
|
@ -1553,7 +1553,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
|||
except:
|
||||
pass
|
||||
dlg=wx.FileDialog(self,_("Open file to print"),basedir,style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
|
||||
dlg.SetWildcard(_("OBJ, STL, and GCODE files (*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ)|*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ|All Files (*.*)|*.*"))
|
||||
dlg.SetWildcard(_("OBJ, STL, and GCODE files (*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ)|*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ|All Files (*.*)|*.*"))
|
||||
if(filename is not None or dlg.ShowModal() == wx.ID_OK):
|
||||
if filename is not None:
|
||||
name=filename
|
||||
|
@ -1810,4 +1810,3 @@ if __name__ == '__main__':
|
|||
app.MainLoop()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
|
10
setup.py
10
setup.py
|
@ -1,17 +1,17 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of the Printrun suite.
|
||||
#
|
||||
#
|
||||
# Printrun is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Printrun is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
@ -43,7 +43,7 @@ class install (_install):
|
|||
except:
|
||||
self.warn ("Could not write installed files list %s" % \
|
||||
INSTALLED_FILES)
|
||||
return
|
||||
return
|
||||
file.write (data)
|
||||
file.close ()
|
||||
|
||||
|
@ -66,7 +66,7 @@ class uninstall (_install):
|
|||
except:
|
||||
self.warn ("Could not read installed files list %s" % \
|
||||
INSTALLED_FILES)
|
||||
return
|
||||
return
|
||||
files = file.readlines ()
|
||||
file.close ()
|
||||
prepend = ""
|
||||
|
|
Loading…
Reference in New Issue