commit
e29dd70efe
|
@ -3,3 +3,4 @@
|
|||
*.swp
|
||||
*.bak
|
||||
uploads
|
||||
.DS_Store
|
||||
|
|
14
README.md
14
README.md
|
@ -25,9 +25,19 @@ You can run Printrun directly from source, as there are no packages available ye
|
|||
|
||||
`sudo apt-get install python-serial python-wxgtk2.8 python-pyglet`
|
||||
|
||||
### Fedora 15 and newer
|
||||
### Fedora 17 and newer
|
||||
|
||||
You can run Printrun directly from source, as there are no packages available yet. Fetch and install the dependencies using
|
||||
You can install Printrun from official packages. Install the whole package using
|
||||
|
||||
`sudo yum install printrun`
|
||||
|
||||
Or get only apps you need by
|
||||
|
||||
`sudo yum install pronsole` or `pronterface` or `plater`
|
||||
|
||||
Adding `--enablerepo updates-testing` option to `yum` might give you newer packages (but also not very tested).
|
||||
|
||||
You can also run Printrun directly from source, if the packages are too old for you anyway, or you have Fedora 15 or 16. Fetch and install the dependencies using
|
||||
|
||||
`sudo yum install pyserial wxpython pyglet`
|
||||
|
||||
|
|
|
@ -461,12 +461,12 @@ if __name__ == '__main__':
|
|||
try:
|
||||
if statusreport:
|
||||
p.loud = False
|
||||
sys.stdout.write("Progress: 00.0%")
|
||||
sys.stdout.write("Progress: 00.0%\r")
|
||||
sys.stdout.flush()
|
||||
while p.printing:
|
||||
time.sleep(1)
|
||||
if statusreport:
|
||||
sys.stdout.write("%02.1f%%\r" % (100 * float(p.queueindex) / len(p.mainqueue),) )
|
||||
sys.stdout.write("Progress: %02.1f%%\r" % (100 * float(p.queueindex) / len(p.mainqueue),) )
|
||||
sys.stdout.flush()
|
||||
p.disconnect()
|
||||
sys.exit(0)
|
||||
|
|
|
@ -77,7 +77,7 @@ class BufferedCanvas(wx.Panel):
|
|||
## General methods
|
||||
##
|
||||
|
||||
def draw(self, dc):
|
||||
def draw(self, dc, w, h):
|
||||
"""
|
||||
Stub: called when the canvas needs to be re-drawn.
|
||||
"""
|
||||
|
|
|
@ -47,10 +47,13 @@ class Line(object):
|
|||
if ";" in self.raw:
|
||||
self.raw = self.raw.split(";")[0].rstrip()
|
||||
self.split_raw = self.raw.split(" ")
|
||||
self.command = self.split_raw[0].upper()
|
||||
self.command = self.split_raw[0].upper() if not self.split_raw[0].startswith("n") else self.split_raw[1]
|
||||
self.is_move = self.command in ["G0", "G1"]
|
||||
|
||||
def parse_coordinates(self, imperial):
|
||||
# Not a G-line, we don't want to parse its arguments
|
||||
if not self.command[0] == "G":
|
||||
return
|
||||
if imperial:
|
||||
for bit in self.split_raw:
|
||||
code = bit[0]
|
||||
|
|
|
@ -23,14 +23,13 @@ class Graph(BufferedCanvas):
|
|||
'''A class to show a Graph with Pronterface.'''
|
||||
|
||||
def __init__(self, parent, id, pos = wx.DefaultPosition,
|
||||
size = wx.DefaultSize, style = 0):
|
||||
size = wx.Size(150, 80), style = 0):
|
||||
# Forcing a no full repaint to stop flickering
|
||||
style = style | wx.NO_FULL_REPAINT_ON_RESIZE
|
||||
#call super function
|
||||
#super(Graph, self).__init__(parent, id, pos, size, style)
|
||||
BufferedCanvas.__init__(self, parent, id)
|
||||
super(Graph, self).__init__(parent, id, pos, size, style)
|
||||
#BufferedCanvas.__init__(self, parent, id)
|
||||
|
||||
self.SetSize(wx.Size(150, 80))
|
||||
|
||||
self.extruder0temps = [0]
|
||||
self.extruder0targettemps = [0]
|
||||
|
@ -80,8 +79,7 @@ class Graph(BufferedCanvas):
|
|||
#b = gc.CreateLinearGradientBrush(0, 0, w, h, col1, col2)
|
||||
|
||||
gc.SetPen(wx.Pen(wx.Colour(255, 0, 0, 0), 4))
|
||||
#gc.SetBrush(gc.CreateBrush(wx.Brush(wx.Colour(245, 245, 255, 252))))
|
||||
#gc.SetBrush(b)
|
||||
gc.SetBrush(gc.CreateBrush(wx.Brush(wx.Colour(0, 0, 0, 0))))
|
||||
gc.DrawRectangle(0, 0, self.width, self.height)
|
||||
|
||||
#gc.SetBrush(wx.Brush(wx.Colour(245, 245, 255, 52)))
|
||||
|
|
|
@ -26,6 +26,7 @@ from printrun import gviz
|
|||
from printrun.xybuttons import XYButtons
|
||||
from printrun.zbuttons import ZButtons
|
||||
from printrun.graph import Graph
|
||||
from printrun.pronterface_widgets import TempGauge
|
||||
|
||||
def make_button(parent, label, callback, tooltip, container = None, size = wx.DefaultSize, style = 0):
|
||||
button = wx.Button(parent, -1, label, style = style, size = size)
|
||||
|
@ -56,9 +57,9 @@ class LeftPane(wx.GridBagSizer):
|
|||
def __init__(self, root):
|
||||
super(LeftPane, self).__init__()
|
||||
llts = wx.BoxSizer(wx.HORIZONTAL)
|
||||
self.Add(llts, pos = (0, 0), span = (1, 9))
|
||||
self.Add(llts, pos = (0, 0), span = (1, 6))
|
||||
self.xyzsizer = XYZControlsSizer(root)
|
||||
self.Add(self.xyzsizer, pos = (1, 0), span = (1, 8), flag = wx.ALIGN_CENTER)
|
||||
self.Add(self.xyzsizer, pos = (1, 0), span = (1, 6), flag = wx.ALIGN_CENTER)
|
||||
|
||||
for i in root.cpbuttons:
|
||||
btn = make_button(root.panel, i.label, root.procbutton, i.tooltip, style = wx.BU_EXACTFIT)
|
||||
|
@ -84,7 +85,7 @@ class LeftPane(wx.GridBagSizer):
|
|||
|
||||
root.monitorbox = wx.CheckBox(root.panel,-1, _("Watch"))
|
||||
root.monitorbox.SetToolTip(wx.ToolTip("Monitor Temperatures in Graph"))
|
||||
self.Add(root.monitorbox, pos = (2, 6))
|
||||
self.Add(root.monitorbox, pos = (3, 5))
|
||||
root.monitorbox.Bind(wx.EVT_CHECKBOX, root.setmonitor)
|
||||
|
||||
self.Add(wx.StaticText(root.panel,-1, _("Heat:")), pos = (2, 0), span = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT)
|
||||
|
@ -164,9 +165,31 @@ class LeftPane(wx.GridBagSizer):
|
|||
root.zfeedc.SetBackgroundColour((180, 255, 180))
|
||||
root.zfeedc.SetForegroundColour("black")
|
||||
|
||||
if root.display_gauges:
|
||||
root.hottgauge = TempGauge(root.panel, size = (-1, 24), title = _("Heater:"), maxval = 300)
|
||||
self.Add(root.hottgauge, pos = (6, 0), span = (1, 6), flag = wx.EXPAND)
|
||||
root.bedtgauge = TempGauge(root.panel, size = (-1, 24), title = _("Bed:"), maxval = 150)
|
||||
self.Add(root.bedtgauge, pos = (7, 0), span = (1, 6), flag = wx.EXPAND)
|
||||
def hotendgauge_scroll_setpoint(e):
|
||||
rot = e.GetWheelRotation()
|
||||
if rot > 0:
|
||||
root.do_settemp(str(root.hsetpoint + 1))
|
||||
elif rot < 0:
|
||||
root.do_settemp(str(max(0, root.hsetpoint - 1)))
|
||||
def bedgauge_scroll_setpoint(e):
|
||||
rot = e.GetWheelRotation()
|
||||
if rot > 0:
|
||||
root.do_settemp(str(root.bsetpoint + 1))
|
||||
elif rot < 0:
|
||||
root.do_settemp(str(max(0, root.bsetpoint - 1)))
|
||||
root.hottgauge.Bind(wx.EVT_MOUSEWHEEL, hotendgauge_scroll_setpoint)
|
||||
root.bedtgauge.Bind(wx.EVT_MOUSEWHEEL, bedgauge_scroll_setpoint)
|
||||
self.Add(root.tempdisp, pos = (8, 0), span = (1, 6))
|
||||
else:
|
||||
self.Add(root.tempdisp, pos = (6, 0), span = (1, 6))
|
||||
|
||||
root.graph = Graph(root.panel, wx.ID_ANY)
|
||||
self.Add(root.graph, pos = (3, 5), span = (3, 3))
|
||||
self.Add(root.tempdisp, pos = (6, 0), span = (1, 9))
|
||||
self.Add(root.graph, pos = (4, 5), span = (2, 1))
|
||||
|
||||
class VizPane(wx.BoxSizer):
|
||||
|
||||
|
@ -199,6 +222,7 @@ class LogPane(wx.BoxSizer):
|
|||
super(LogPane, self).__init__(wx.VERTICAL)
|
||||
root.lowerrsizer = self
|
||||
root.logbox = wx.TextCtrl(root.panel, style = wx.TE_MULTILINE, size = (350,-1))
|
||||
root.logbox.SetMinSize((100,-1))
|
||||
root.logbox.SetEditable(0)
|
||||
self.Add(root.logbox, 1, wx.EXPAND)
|
||||
lbrs = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
@ -223,7 +247,7 @@ class MainToolbar(wx.BoxSizer):
|
|||
|
||||
root.serialport = wx.ComboBox(root.panel, -1,
|
||||
choices = root.scanserial(),
|
||||
style = wx.CB_DROPDOWN, size = (150, 25))
|
||||
style = wx.CB_DROPDOWN, size = (-1, 25))
|
||||
root.serialport.SetToolTip(wx.ToolTip("Select Port Printer is connected to"))
|
||||
root.rescanports()
|
||||
self.Add(root.serialport)
|
||||
|
@ -263,10 +287,10 @@ class MainWindow(wx.Frame):
|
|||
self.mainsizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.uppersizer = MainToolbar(self)
|
||||
self.lowersizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
self.lowersizer.Add(LeftPane(self))
|
||||
self.lowersizer.Add(LeftPane(self), 0)
|
||||
self.lowersizer.Add(VizPane(self), 1, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL)
|
||||
self.lowersizer.Add(LogPane(self), 0, wx.EXPAND)
|
||||
self.mainsizer.Add(self.uppersizer)
|
||||
self.lowersizer.Add(LogPane(self), 1, wx.EXPAND)
|
||||
self.mainsizer.Add(self.uppersizer, 0)
|
||||
self.mainsizer.Add(self.lowersizer, 1, wx.EXPAND)
|
||||
self.panel.SetSizer(self.mainsizer)
|
||||
self.status = self.CreateStatusBar()
|
||||
|
@ -276,6 +300,12 @@ class MainWindow(wx.Frame):
|
|||
|
||||
self.mainsizer.Layout()
|
||||
self.mainsizer.Fit(self)
|
||||
# This prevents resizing below a reasonnable value
|
||||
# We sum the lowersizer (left pane / viz / log) min size
|
||||
# the toolbar height and the statusbar/menubar sizes
|
||||
minsize = self.lowersizer.GetMinSize() # lower pane
|
||||
minsize[1] += self.uppersizer.GetMinSize()[1] # toolbar height
|
||||
self.SetMinSize(self.ClientToWindowSize(minsize)) # client to window
|
||||
|
||||
# disable all printer controls until we connect to a printer
|
||||
self.pausebtn.Disable()
|
||||
|
|
180
printrun/gviz.py
180
printrun/gviz.py
|
@ -44,8 +44,8 @@ class window(wx.Frame):
|
|||
vbox.Add(self.p, 1, wx.EXPAND)
|
||||
panel.SetSizer(vbox)
|
||||
self.SetMinSize(self.ClientToWindowSize(vbox.GetMinSize()))
|
||||
self.Bind(wx.EVT_TOOL, lambda x:self.p.zoom(200, 200, 1.2), id = 1)
|
||||
self.Bind(wx.EVT_TOOL, lambda x:self.p.zoom(200, 200, 1/1.2), id = 2)
|
||||
self.Bind(wx.EVT_TOOL, lambda x:self.p.zoom(-1, -1, 1.2), id = 1)
|
||||
self.Bind(wx.EVT_TOOL, lambda x:self.p.zoom(-1, -1, 1/1.2), id = 2)
|
||||
self.Bind(wx.EVT_TOOL, lambda x:self.p.layerup(), id = 3)
|
||||
self.Bind(wx.EVT_TOOL, lambda x:self.p.layerdown(), id = 4)
|
||||
self.Bind(wx.EVT_TOOL, self.resetview, id = 5)
|
||||
|
@ -123,6 +123,17 @@ class window(wx.Frame):
|
|||
elif z < 0: self.p.zoom(event.GetX(), event.GetY(), 1/1.2)
|
||||
|
||||
class gviz(wx.Panel):
|
||||
|
||||
# Mark canvas as dirty when setting showall
|
||||
_showall = 0
|
||||
def _get_showall(self):
|
||||
return self._showall
|
||||
def _set_showall(self, showall):
|
||||
if showall != self._showall:
|
||||
self.dirty = 1
|
||||
self._showall = showall
|
||||
showall = property(_get_showall, _set_showall)
|
||||
|
||||
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)
|
||||
self.SetMinSize((150, 150))
|
||||
|
@ -202,18 +213,18 @@ class gviz(wx.Panel):
|
|||
pass
|
||||
|
||||
def resize(self, event):
|
||||
oldwidth, oldheight = max(1.0, self.size[0]), max(1.0, self.size[1])
|
||||
oldside = min(oldwidth, oldheight)
|
||||
newwidth, newheight = self.GetClientSizeTuple()
|
||||
newwidth, newheight = [max(1.0, newwidth), max(1.0, newheight)]
|
||||
newside = min(newwidth, newheight)
|
||||
oldside = max(1.0, min(self.size))
|
||||
self.size = self.GetClientSizeTuple()
|
||||
newside = max(1.0, min(self.size))
|
||||
self.basescale = 2*[min(float(self.size[0])/self.build_dimensions[0],
|
||||
float(self.size[1])/self.build_dimensions[1])]
|
||||
zoomratio = float(newside) / oldside
|
||||
print newwidth, newheight
|
||||
print zoomratio
|
||||
self.size = self.GetClientSize()
|
||||
wx.CallAfter(self.zoom, 0, 0, zoomratio)
|
||||
|
||||
def zoom(self, x, y, factor):
|
||||
if x == -1 and y == -1:
|
||||
side = min(self.size)
|
||||
x = y = side / 2
|
||||
self.scale = [s * factor for s in self.scale]
|
||||
|
||||
self.translate = [ x - (x-self.translate[0]) * factor,
|
||||
|
@ -291,14 +302,18 @@ class gviz(wx.Panel):
|
|||
def paint(self, event):
|
||||
dc = wx.PaintDC(self)
|
||||
if self.dirty:
|
||||
self.repaint()
|
||||
self.dirty = 0
|
||||
self.repaint()
|
||||
dc.DrawBitmap(self.blitmap, 0, 0)
|
||||
|
||||
def addfile(self, gcode):
|
||||
self.clear()
|
||||
self.add_parsed_gcodes(gcode.lines)
|
||||
|
||||
# FIXME : there's code duplication going on there, we should factor it (but
|
||||
# the reason addgcode is not factored as a add_parsed_gcodes([gline]) is
|
||||
# because when loading a file there's no hilight, so it simply lets us not
|
||||
# do the if hilight: all the time for nothing when loading a lot of lines
|
||||
def add_parsed_gcodes(self, lines):
|
||||
def _y(y):
|
||||
return self.build_dimensions[1] - (y - self.build_dimensions[4])
|
||||
|
@ -312,10 +327,19 @@ class gviz(wx.Panel):
|
|||
target = self.lastpos[:]
|
||||
target[5] = 0.0
|
||||
target[6] = 0.0
|
||||
if gline.x != None: target[0] = gline.x
|
||||
if gline.y != None: target[1] = gline.y
|
||||
if gline.z != None: target[2] = gline.z
|
||||
if gline.e != None: target[3] = gline.e
|
||||
if gline.relative:
|
||||
if gline.x != None: target[0] += gline.x
|
||||
if gline.y != None: target[1] += gline.y
|
||||
if gline.z != None: target[2] += gline.z
|
||||
else:
|
||||
if gline.x != None: target[0] = gline.x
|
||||
if gline.y != None: target[1] = gline.y
|
||||
if gline.z != None: target[2] = gline.z
|
||||
if gline.e != None:
|
||||
if gline.relative_e:
|
||||
target[3] += gline.e
|
||||
else:
|
||||
target[3] = gline.e
|
||||
if gline.f != None: target[4] = gline.f
|
||||
if gline.i != None: target[5] = gline.i
|
||||
if gline.j != None: target[6] = gline.j
|
||||
|
@ -330,100 +354,88 @@ class gviz(wx.Panel):
|
|||
start_pos = self.lastpos[:]
|
||||
|
||||
if gline.command in ["G0", "G1"]:
|
||||
line = [ _x(start_pos[0]), _y(start_pos[1]), _x(target[0]), _y(target[1]) ]
|
||||
self.lines[z].append(line)
|
||||
self.lines[z].append((_x(start_pos[0]), _y(start_pos[1]), _x(target[0]), _y(target[1])))
|
||||
self.pens[z].append(self.mainpen if target[3] != self.lastpos[3] else self.travelpen)
|
||||
self.lastpos = target
|
||||
self.dirty = 1
|
||||
|
||||
if gline.command in ["G2", "G3"]:
|
||||
elif gline.command in ["G2", "G3"]:
|
||||
# startpos, endpos, arc center
|
||||
arc = [_x(start_pos[0]), _y(start_pos[1]),
|
||||
_x(target[0]), _y(target[1]),
|
||||
_x(start_pos[0] + target[5]), _y(start_pos[1] + target[6]) ] # center
|
||||
_x(start_pos[0] + target[5]), _y(start_pos[1] + target[6])]
|
||||
# FIXME : verify this works : why not reverse endpoints 4, 5
|
||||
if gline.command == "G2": # clockwise, reverse endpoints
|
||||
arc[0], arc[1], arc[2], arc[3] = arc[2], arc[3], arc[0], arc[1]
|
||||
|
||||
self.arcs[z].append(arc)
|
||||
self.arcpens[z].append(self.arcpen)
|
||||
self.lastpos = target
|
||||
self.dirty = 1
|
||||
|
||||
self.lastpos = target
|
||||
self.dirty = 1
|
||||
self.Refresh()
|
||||
|
||||
def addgcode(self, gcode = "M105", hilight = 0):
|
||||
gcode = gcode.split("*")[0]
|
||||
gcode = gcode.split(";")[0]
|
||||
gcode = gcode.lower().strip().split()
|
||||
gcode = gcode.lower().strip()
|
||||
if not gcode:
|
||||
return
|
||||
if gcode[0][0] == 'n': # not sure what this check is for ?
|
||||
gcode.pop(0)
|
||||
|
||||
def _readgcode():
|
||||
target = self.lastpos[:]
|
||||
target[5]=0.0
|
||||
target[6]=0.0
|
||||
if hilight:
|
||||
target = self.hilightpos[:]
|
||||
for i in gcode:
|
||||
if i[0]=="x":
|
||||
target[0]=float(i[1:])
|
||||
elif i[0]=="y":
|
||||
target[1]=float(i[1:])
|
||||
elif i[0]=="z":
|
||||
target[2]=float(i[1:])
|
||||
elif i[0]=="e":
|
||||
target[3]=float(i[1:])
|
||||
elif i[0]=="f":
|
||||
target[4]=float(i[1:])
|
||||
elif i[0]=="i":
|
||||
target[5]=float(i[1:])
|
||||
elif i[0]=="j":
|
||||
target[6]=float(i[1:])
|
||||
if not hilight:
|
||||
if not target[2] in self.lines.keys():
|
||||
self.lines[target[2]]=[]
|
||||
self.pens[target[2]]=[]
|
||||
self.arcs[target[2]]=[]
|
||||
self.arcpens[target[2]]=[]
|
||||
self.layers+=[target[2]]
|
||||
return target
|
||||
gline = gcoder.Line(gcode)
|
||||
gline.parse_coordinates(False)
|
||||
|
||||
def _y(y):
|
||||
return self.build_dimensions[1]-(y-self.build_dimensions[4])
|
||||
return self.build_dimensions[1] - (y - self.build_dimensions[4])
|
||||
def _x(x):
|
||||
return x-self.build_dimensions[3]
|
||||
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]) ]
|
||||
if not hilight:
|
||||
self.lines[ target[2] ] += [line]
|
||||
self.pens[ target[2] ] += [self.mainpen if target[3] != self.lastpos[3] else self.travelpen]
|
||||
self.lastpos = target
|
||||
else:
|
||||
self.hilight += [line]
|
||||
self.hilightpos = target
|
||||
self.dirty = 1
|
||||
if gline.command not in ["G0", "G1", "G2", "G3"]:
|
||||
return
|
||||
|
||||
target = self.hilightpos[:] if hilight else self.lastpos[:]
|
||||
target[5] = 0.0
|
||||
target[6] = 0.0
|
||||
if gline.x != None: target[0] = gline.x
|
||||
if gline.y != None: target[1] = gline.y
|
||||
if gline.z != None: target[2] = gline.z
|
||||
if gline.e != None: target[3] = gline.e
|
||||
if gline.f != None: target[4] = gline.f
|
||||
if gline.i != None: target[5] = gline.i
|
||||
if gline.j != None: target[6] = gline.j
|
||||
|
||||
if gcode[0] in [ "g2", "g3" ]:
|
||||
target = _readgcode()
|
||||
arc = []
|
||||
arc += [ _x(start_pos[0]), _y(start_pos[1]) ]
|
||||
arc += [ _x(target[0]), _y(target[1]) ]
|
||||
arc += [ _x(start_pos[0] + target[5]), _y(start_pos[1] + target[6]) ] # center
|
||||
if gcode[0] == "g2": # clockwise, reverse endpoints
|
||||
z = target[2]
|
||||
if not hilight and z not in self.layers:
|
||||
self.lines[z] = []
|
||||
self.pens[z] = []
|
||||
self.arcs[z] = []
|
||||
self.arcpens[z] = []
|
||||
self.layers.append(z)
|
||||
|
||||
if gline.command in ["G0", "G1"]:
|
||||
line = [_x(start_pos[0]), _y(start_pos[1]), _x(target[0]), _y(target[1])]
|
||||
if not hilight:
|
||||
self.lines[z].append((_x(start_pos[0]), _y(start_pos[1]), _x(target[0]), _y(target[1])))
|
||||
self.pens[z].append(self.mainpen if target[3] != self.lastpos[3] else self.travelpen)
|
||||
else:
|
||||
self.hilight.append(line)
|
||||
elif gline.command in ["G2", "G3"]:
|
||||
# startpos, endpos, arc center
|
||||
arc = [_x(start_pos[0]), _y(start_pos[1]),
|
||||
_x(target[0]), _y(target[1]),
|
||||
_x(start_pos[0] + target[5]), _y(start_pos[1] + target[6])]
|
||||
if gline.command == "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]
|
||||
self.lastpos = target
|
||||
self.arcs[z].append(arc)
|
||||
self.arcpens[z].append(self.arcpen)
|
||||
else:
|
||||
self.hilightarcs += [arc]
|
||||
self.hilightpos = target
|
||||
self.dirty = 1
|
||||
self.hilightarcs.append(arc)
|
||||
|
||||
if not hilight:
|
||||
self.lastpos = target
|
||||
else:
|
||||
self.hilightpos = target
|
||||
self.dirty = 1
|
||||
self.Refresh()
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
|
|
@ -211,6 +211,113 @@ class ButtonEdit(wx.Dialog):
|
|||
if self.name.GetValue()=="":
|
||||
self.name.SetValue(macro)
|
||||
|
||||
class TempGauge(wx.Panel):
|
||||
|
||||
def __init__(self, parent, size = (200, 22), title = "", maxval = 240, gaugeColour = None):
|
||||
wx.Panel.__init__(self, parent,-1, size = size)
|
||||
self.Bind(wx.EVT_PAINT, self.paint)
|
||||
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
|
||||
self.width, self.height = size
|
||||
self.title = title
|
||||
self.max = maxval
|
||||
self.gaugeColour = gaugeColour
|
||||
self.value = 0
|
||||
self.setpoint = 0
|
||||
self.recalc()
|
||||
|
||||
def recalc(self):
|
||||
mmax = max(int(self.setpoint*1.05), self.max)
|
||||
self.scale = float(self.width-2)/float(mmax)
|
||||
self.ypt = max(16, int(self.scale*max(self.setpoint, self.max/6)))
|
||||
|
||||
def SetValue(self, value):
|
||||
self.value = value
|
||||
wx.CallAfter(self.Refresh)
|
||||
|
||||
def SetTarget(self, value):
|
||||
self.setpoint = value
|
||||
wx.CallAfter(self.Refresh)
|
||||
|
||||
def interpolatedColour(self, val, vmin, vmid, vmax, cmin, cmid, cmax):
|
||||
if val < vmin: return cmin
|
||||
if val > vmax: return cmax
|
||||
if val <= vmid:
|
||||
lo, hi, val, valhi = cmin, cmid, val-vmin, vmid-vmin
|
||||
else:
|
||||
lo, hi, val, valhi = cmid, cmax, val-vmid, vmax-vmid
|
||||
vv = float(val)/valhi
|
||||
rgb = lo.Red()+(hi.Red()-lo.Red())*vv, lo.Green()+(hi.Green()-lo.Green())*vv, lo.Blue()+(hi.Blue()-lo.Blue())*vv
|
||||
rgb = map(lambda x:x*0.8, rgb)
|
||||
return wx.Colour(*map(int, rgb))
|
||||
|
||||
def paint(self, ev):
|
||||
self.width, self.height = self.GetClientSizeTuple()
|
||||
self.recalc()
|
||||
x0, y0, x1, y1, xE, yE = 1, 1, self.ypt+1, 1, self.width+1-2, 20
|
||||
dc = wx.PaintDC(self)
|
||||
dc.SetBackground(wx.Brush((255, 255, 255)))
|
||||
dc.Clear()
|
||||
cold, medium, hot = wx.Colour(0, 167, 223), wx.Colour(239, 233, 119), wx.Colour(210, 50.100)
|
||||
gauge1, gauge2 = wx.Colour(255, 255, 210), (self.gaugeColour or wx.Colour(234, 82, 0))
|
||||
shadow1, shadow2 = wx.Colour(110, 110, 110), wx.Colour(255, 255, 255)
|
||||
gc = wx.GraphicsContext.Create(dc)
|
||||
# draw shadow first
|
||||
# corners
|
||||
gc.SetBrush(gc.CreateRadialGradientBrush(xE-7, 9, xE-7, 9, 8, shadow1, shadow2))
|
||||
gc.DrawRectangle(xE-7, 1, 8, 8)
|
||||
gc.SetBrush(gc.CreateRadialGradientBrush(xE-7, 17, xE-7, 17, 8, shadow1, shadow2))
|
||||
gc.DrawRectangle(xE-7, 17, 8, 8)
|
||||
gc.SetBrush(gc.CreateRadialGradientBrush(x0+6, 17, x0+6, 17, 8, shadow1, shadow2))
|
||||
gc.DrawRectangle(0, 17, x0+6, 8)
|
||||
# edges
|
||||
gc.SetBrush(gc.CreateLinearGradientBrush(xE-6, 0, xE+1, 0, shadow1, shadow2))
|
||||
gc.DrawRectangle(xE-7, 9, 8, 8)
|
||||
gc.SetBrush(gc.CreateLinearGradientBrush(x0, yE-2, x0, yE+5, shadow1, shadow2))
|
||||
gc.DrawRectangle(x0+6, yE-2, xE-12, 7)
|
||||
# draw gauge background
|
||||
gc.SetBrush(gc.CreateLinearGradientBrush(x0, y0, x1+1, y1, cold, medium))
|
||||
gc.DrawRoundedRectangle(x0, y0, x1+4, yE, 6)
|
||||
gc.SetBrush(gc.CreateLinearGradientBrush(x1-2, y1, xE, y1, medium, hot))
|
||||
gc.DrawRoundedRectangle(x1-2, y1, xE-x1, yE, 6)
|
||||
# draw gauge
|
||||
width = 12
|
||||
w1 = y0+9-width/2
|
||||
w2 = w1+width
|
||||
value = x0+max(10, min(self.width+1-2, int(self.value*self.scale)))
|
||||
#gc.SetBrush(gc.CreateLinearGradientBrush(x0, y0+3, x0, y0+15, gauge1, gauge2))
|
||||
#gc.SetBrush(gc.CreateLinearGradientBrush(0, 3, 0, 15, wx.Colour(255, 255, 255), wx.Colour(255, 90, 32)))
|
||||
gc.SetBrush(gc.CreateLinearGradientBrush(x0, y0+3, x0, y0+15, gauge1, self.interpolatedColour(value, x0, x1, xE, cold, medium, hot)))
|
||||
val_path = gc.CreatePath()
|
||||
val_path.MoveToPoint(x0, w1)
|
||||
val_path.AddLineToPoint(value, w1)
|
||||
val_path.AddLineToPoint(value+2, w1+width/4)
|
||||
val_path.AddLineToPoint(value+2, w2-width/4)
|
||||
val_path.AddLineToPoint(value, w2)
|
||||
#val_path.AddLineToPoint(value-4, 10)
|
||||
val_path.AddLineToPoint(x0, w2)
|
||||
gc.DrawPath(val_path)
|
||||
# draw setpoint markers
|
||||
setpoint = x0+max(10, int(self.setpoint*self.scale))
|
||||
gc.SetBrush(gc.CreateBrush(wx.Brush(wx.Colour(0, 0, 0))))
|
||||
setp_path = gc.CreatePath()
|
||||
setp_path.MoveToPoint(setpoint-4, y0)
|
||||
setp_path.AddLineToPoint(setpoint+4, y0)
|
||||
setp_path.AddLineToPoint(setpoint, y0+5)
|
||||
setp_path.MoveToPoint(setpoint-4, yE)
|
||||
setp_path.AddLineToPoint(setpoint+4, yE)
|
||||
setp_path.AddLineToPoint(setpoint, yE-5)
|
||||
gc.DrawPath(setp_path)
|
||||
# draw readout
|
||||
text = u"T\u00B0 %u/%u"%(self.value, self.setpoint)
|
||||
#gc.SetFont(gc.CreateFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD), wx.WHITE))
|
||||
#gc.DrawText(text, 29,-2)
|
||||
gc.SetFont(gc.CreateFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD), wx.WHITE))
|
||||
gc.DrawText(self.title, x0+19, y0+4)
|
||||
gc.DrawText(text, x0+119, y0+4)
|
||||
gc.SetFont(gc.CreateFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)))
|
||||
gc.DrawText(self.title, x0+18, y0+3)
|
||||
gc.DrawText(text, x0+118, y0+3)
|
||||
|
||||
class SpecialButton(object):
|
||||
|
||||
label = None
|
||||
|
|
|
@ -60,8 +60,7 @@ class XYButtons(BufferedCanvas):
|
|||
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())
|
||||
BufferedCanvas.__init__(self, parent, ID, size=self.bg_bmp.GetSize())
|
||||
|
||||
# Set up mouse and keyboard event capture
|
||||
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
||||
|
|
|
@ -46,9 +46,7 @@ class ZButtons(BufferedCanvas):
|
|||
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(wx.Size(59, 244))
|
||||
BufferedCanvas.__init__(self, parent, ID, size=wx.Size(59, 244))
|
||||
|
||||
# Set up mouse and keyboard event capture
|
||||
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
||||
|
|
12
pronsole.py
12
pronsole.py
|
@ -1207,12 +1207,12 @@ class pronsole(cmd.Cmd):
|
|||
self.log("home e - set extruder position to zero (Using G92)")
|
||||
self.log("home xyze - homes all axes and zeroes the extruder (Using G28 and G92)")
|
||||
|
||||
def parse_cmdline(self, args):
|
||||
parser = argparse.ArgumentParser(description = 'Printrun 3D printer interface')
|
||||
def add_cmdline_arguments(self, parser):
|
||||
parser.add_argument('-c','--conf','--config', help = _("load this file on startup instead of .pronsolerc ; you may chain config files, if so settings auto-save will use the last specified file"), action = "append", default = [])
|
||||
parser.add_argument('-e','--execute', help = _("executes command after configuration/.pronsolerc is loaded ; macros/settings from these commands are not autosaved"), action = "append", default = [])
|
||||
parser.add_argument('filename', nargs='?', help = _("file to load"))
|
||||
args = parser.parse_args()
|
||||
|
||||
def process_cmdline_arguments(self, args):
|
||||
for config in args.conf:
|
||||
self.load_rc(config)
|
||||
if not self.rc_loaded:
|
||||
|
@ -1224,6 +1224,12 @@ class pronsole(cmd.Cmd):
|
|||
if args.filename:
|
||||
self.do_load(args.filename)
|
||||
|
||||
def parse_cmdline(self, args):
|
||||
parser = argparse.ArgumentParser(description = 'Printrun 3D printer interface')
|
||||
self.add_cmdline_arguments(parser)
|
||||
args = parser.parse_args()
|
||||
self.process_cmdline_arguments(args)
|
||||
|
||||
# We replace this function, defined in cmd.py .
|
||||
# It's default behavior with reagrds to Ctr-C
|
||||
# and Ctr-D doesn't make much sense...
|
||||
|
|
|
@ -198,15 +198,23 @@ class PronterWindow(MainWindow, pronsole.pronsole):
|
|||
if self.filename is not None:
|
||||
self.do_load(self.filename)
|
||||
|
||||
def add_cmdline_arguments(self, parser):
|
||||
pronsole.pronsole.add_cmdline_arguments(self, parser)
|
||||
parser.add_argument('-g','--gauges', help = _("display graphical temperature gauges in addition to the temperatures graph"), action = "store_true")
|
||||
|
||||
def process_cmdline_arguments(self, args):
|
||||
pronsole.pronsole.process_cmdline_arguments(self, args)
|
||||
self.display_gauges = args.gauges
|
||||
|
||||
def startcb(self):
|
||||
self.starttime = time.time()
|
||||
print "Print Started at: " + format_time(self.starttime)
|
||||
|
||||
def endcb(self):
|
||||
if self.p.queueindex == 0:
|
||||
print "Print ended at: " + format_time(time.time())
|
||||
print_duration = int(time.time () - self.starttime + self.extra_print_time)
|
||||
print "and took: " + format_duration(print_duration)
|
||||
print _("Print ended at: %(end_time)s and took %(duration)s") % {"end_time": format_time(time.time()),
|
||||
"duration": format_duration(print_duration)}
|
||||
wx.CallAfter(self.pausebtn.Disable)
|
||||
wx.CallAfter(self.printbtn.SetLabel, _("Print"))
|
||||
|
||||
|
@ -239,7 +247,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
|
|||
if "G1" in line:
|
||||
if "Z" in line:
|
||||
try:
|
||||
layer = float(line.split("Z")[1].split()[0])
|
||||
layer = float(line.split("Z")[1].split()[0].split("*")[0])
|
||||
if layer != self.curlayer:
|
||||
self.curlayer = layer
|
||||
self.gviz.hilight = []
|
||||
|
@ -256,6 +264,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
|
|||
if "S" in line:
|
||||
try:
|
||||
temp = float(line.split("S")[1].split("*")[0])
|
||||
if self.display_gauges: wx.CallAfter(self.hottgauge.SetTarget, temp)
|
||||
wx.CallAfter(self.graph.SetExtruder0TargetTemperature, temp)
|
||||
except:
|
||||
pass
|
||||
|
@ -267,6 +276,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
|
|||
if "S" in line:
|
||||
try:
|
||||
temp = float(line.split("S")[1].split("*")[0])
|
||||
if self.display_gauges: wx.CallAfter(self.bedtgauge.SetTarget, temp)
|
||||
wx.CallAfter(self.graph.SetBedTargetTemperature, temp)
|
||||
except:
|
||||
pass
|
||||
|
@ -293,6 +303,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
|
|||
|
||||
def setbedgui(self, f):
|
||||
self.bsetpoint = f
|
||||
if self.display_gauges: self.bedtgauge.SetTarget(int(f))
|
||||
wx.CallAfter(self.graph.SetBedTargetTemperature, int(f))
|
||||
if f>0:
|
||||
wx.CallAfter(self.btemp.SetValue, str(f))
|
||||
|
@ -312,6 +323,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
|
|||
|
||||
def sethotendgui(self, f):
|
||||
self.hsetpoint = f
|
||||
if self.display_gauges: self.hottgauge.SetTarget(int(f))
|
||||
wx.CallAfter(self.graph.SetExtruder0TargetTemperature, int(f))
|
||||
if f > 0:
|
||||
wx.CallAfter(self.htemp.SetValue, str(f))
|
||||
|
@ -591,7 +603,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
|
|||
wx.CallAfter(self.btemp.SetInsertionPoint, 0)
|
||||
|
||||
def showwin(self, event):
|
||||
if(self.f is not None):
|
||||
if self.f is not None:
|
||||
self.gwindow.Show(True)
|
||||
self.gwindow.SetToolTip(wx.ToolTip("Mousewheel zooms the display\nShift / Mousewheel scrolls layers"))
|
||||
self.gwindow.Raise()
|
||||
|
@ -1015,8 +1027,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
|
|||
try:
|
||||
self.logbox.AppendText(text)
|
||||
except:
|
||||
print "attempted to write invalid text to console"
|
||||
pass
|
||||
print _("Attempted to write invalid text to console, which could be due to an invalid baudrate")
|
||||
|
||||
def setloud(self,e):
|
||||
self.p.loud=e.IsChecked()
|
||||
|
@ -1034,15 +1045,22 @@ class PronterWindow(MainWindow, pronsole.pronsole):
|
|||
def clearOutput(self, e):
|
||||
self.logbox.Clear()
|
||||
|
||||
def update_tempdisplay(self):
|
||||
try:
|
||||
hotend_temp = parse_temperature_report(self.tempreport, "T:")
|
||||
wx.CallAfter(self.graph.SetExtruder0Temperature, hotend_temp)
|
||||
if self.display_gauges: wx.CallAfter(self.hottgauge.SetValue, hotend_temp)
|
||||
bed_temp = parse_temperature_report(self.tempreport, "B:")
|
||||
wx.CallAfter(self.graph.SetBedTemperature, bed_temp)
|
||||
if self.display_gauges: wx.CallAfter(self.bedtgauge.SetValue, bed_temp)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
def statuschecker(self):
|
||||
while self.statuscheck:
|
||||
string = ""
|
||||
wx.CallAfter(self.tempdisp.SetLabel, self.tempreport.strip().replace("ok ", ""))
|
||||
try:
|
||||
wx.CallAfter(self.graph.SetExtruder0Temperature, parse_temperature_report(self.tempreport, "T:"))
|
||||
wx.CallAfter(self.graph.SetBedTemperature, parse_temperature_report(self.tempreport, "B:"))
|
||||
except:
|
||||
pass
|
||||
self.update_tempdisplay()
|
||||
fractioncomplete = 0.0
|
||||
if self.sdprinting:
|
||||
fractioncomplete = float(self.percentdone / 100.0)
|
||||
|
@ -1103,11 +1121,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
|
|||
if "T:" in l:
|
||||
self.tempreport = l
|
||||
wx.CallAfter(self.tempdisp.SetLabel, self.tempreport.strip().replace("ok ", ""))
|
||||
try:
|
||||
wx.CallAfter(self.graph.SetExtruder0Temperature, parse_temperature_report(self.tempreport, "T:"))
|
||||
wx.CallAfter(self.graph.SetBedTemperature, parse_temperature_report(self.tempreport, "B:"))
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.update_tempdisplay()
|
||||
tstring = l.rstrip()
|
||||
#print tstring
|
||||
if (tstring!="ok") and (tstring!="wait") and ("ok T:" not in tstring) and (not self.p.loud):
|
||||
|
@ -1286,15 +1300,10 @@ class PronterWindow(MainWindow, pronsole.pronsole):
|
|||
print _("the print goes from %f mm to %f mm in Y\nand is %f mm wide\n") % (gcode.ymin, gcode.ymax, gcode.depth)
|
||||
print _("the print goes from %f mm to %f mm in Z\nand is %f mm high\n") % (gcode.zmin, gcode.zmax, gcode.height)
|
||||
print _("Estimated duration (pessimistic): "), gcode.estimate_duration()
|
||||
#import time
|
||||
#t0 = time.time()
|
||||
self.gviz.clear()
|
||||
self.gwindow.p.clear()
|
||||
self.gviz.addfile(self.f)
|
||||
#print "generated 2d view in %f s"%(time.time()-t0)
|
||||
#t0 = time.time()
|
||||
self.gwindow.p.addfile(self.f)
|
||||
#print "generated 3d view in %f s"%(time.time()-t0)
|
||||
self.gviz.addfile(gcode)
|
||||
self.gwindow.p.addfile(gcode)
|
||||
self.gviz.showall = 1
|
||||
wx.CallAfter(self.gviz.Refresh)
|
||||
|
||||
|
@ -1516,5 +1525,5 @@ if __name__ == '__main__':
|
|||
main.Show()
|
||||
try:
|
||||
app.MainLoop()
|
||||
except:
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue