Commit 2337cb12 authored by D1plo1d's avatar D1plo1d

Merge branch 'experimental' of github.com:kliment/Printrun into experimental

parents 313a51f3 b91265ee
...@@ -74,6 +74,7 @@ class printcore(): ...@@ -74,6 +74,7 @@ class printcore():
self.tempcb = None #impl (wholeline) self.tempcb = None #impl (wholeline)
self.recvcb = None #impl (wholeline) self.recvcb = None #impl (wholeline)
self.sendcb = None #impl (wholeline) self.sendcb = None #impl (wholeline)
self.preprintsendcb = None #impl (wholeline)
self.printsendcb = None #impl (wholeline) self.printsendcb = None #impl (wholeline)
self.layerchangecb = None #impl (wholeline) self.layerchangecb = None #impl (wholeline)
self.errorcb = None #impl (wholeline) self.errorcb = None #impl (wholeline)
...@@ -414,7 +415,9 @@ class printcore(): ...@@ -414,7 +415,9 @@ class printcore():
if self.startcb: if self.startcb:
#callback for printing started #callback for printing started
try: self.startcb(resuming) try: self.startcb(resuming)
except: pass except:
print "Print start callback failed with:"
traceback.print_exc(file = sys.stdout)
while self.printing and self.printer and self.online: while self.printing and self.printer and self.online:
self._sendnext() self._sendnext()
self.sentlines = {} self.sentlines = {}
...@@ -423,10 +426,12 @@ class printcore(): ...@@ -423,10 +426,12 @@ class printcore():
if self.endcb: if self.endcb:
#callback for printing done #callback for printing done
try: self.endcb() try: self.endcb()
except: pass except:
print "Print end callback failed with:"
traceback.print_exc(file = sys.stdout)
except: except:
print "Print thread died due to the following error:" print "Print thread died due to the following error:"
traceback.print_exc() traceback.print_exc(file = sys.stdout)
finally: finally:
self.print_thread = None self.print_thread = None
self._start_sender() self._start_sender()
...@@ -460,16 +465,23 @@ class printcore(): ...@@ -460,16 +465,23 @@ class printcore():
return return
if self.printing and self.queueindex < len(self.mainqueue): if self.printing and self.queueindex < len(self.mainqueue):
(layer, line) = self.mainqueue.idxs(self.queueindex) (layer, line) = self.mainqueue.idxs(self.queueindex)
gline = self.mainqueue.all_layers[layer].lines[line] gline = self.mainqueue.all_layers[layer][line]
if self.layerchangecb and self.queueindex > 0: if self.layerchangecb and self.queueindex > 0:
(prev_layer, prev_line) = self.mainqueue.idxs(self.queueindex - 1) (prev_layer, prev_line) = self.mainqueue.idxs(self.queueindex - 1)
if prev_layer != layer: if prev_layer != layer:
try: self.layerchangecb(layer) try: self.layerchangecb(layer)
except: traceback.print_exc() except: traceback.print_exc()
if self.preprintsendcb:
gline = self.preprintsendcb(gline)
if gline == None:
self.queueindex += 1
self.clear = True
return
tline = gline.raw tline = gline.raw
if tline.lstrip().startswith(";@"): # check for host command if tline.lstrip().startswith(";@"): # check for host command
self.processHostCommand(tline) self.processHostCommand(tline)
self.queueindex += 1 self.queueindex += 1
self.clear = True
return return
tline = tline.split(";")[0] tline = tline.split(";")[0]
......
...@@ -69,8 +69,9 @@ class GCodeAnalyzer(): ...@@ -69,8 +69,9 @@ class GCodeAnalyzer():
def Analyze(self, gcode): def Analyze(self, gcode):
gline = gcoder.Line(gcode) gline = gcoder.Line(gcode)
split_raw = gcoder.split(gline)
if gline.command.startswith(";@"): return # code is a host command if gline.command.startswith(";@"): return # code is a host command
gline.parse_coordinates(self.imperial) gcoder.parse_coordinates(gline, split_raw, self.imperial)
code_g = int(gline.command[1:]) if gline.command.startswith("G") else None code_g = int(gline.command[1:]) if gline.command.startswith("G") else None
code_m = int(gline.command[1:]) if gline.command.startswith("M") else None code_m = int(gline.command[1:]) if gline.command.startswith("M") else None
......
# 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
from printrun import gviz
from printrun_utils import imagefile, install_locale
install_locale('pronterface')
class ExcluderWindow(gviz.GvizWindow):
def __init__(self, excluder, *args, **kwargs):
super(ExcluderWindow, self).__init__(*args, **kwargs)
self.SetTitle(_("Part excluder: draw rectangles where print instructions should be ignored"))
self.toolbar.AddLabelTool(128, " " + _("Reset selection"), wx.Image(imagefile('reset.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), shortHelp = _("Reset selection"), longHelp = "")
self.Bind(wx.EVT_TOOL, self.reset_selection, id = 128)
self.parent = excluder
self.p.paint_overlay = self.paint_selection
self.p.layerup()
def real_to_gcode(self, x, y):
return (x + self.p.build_dimensions[3],
self.p.build_dimensions[4] + self.p.build_dimensions[1] - y)
def gcode_to_real(self, x, y):
return (x - self.p.build_dimensions[3],
self.p.build_dimensions[1] - (y - self.p.build_dimensions[4]))
def mouse(self, event):
if event.ButtonUp(wx.MOUSE_BTN_LEFT) or event.ButtonUp(wx.MOUSE_BTN_RIGHT):
self.initpos = None
elif event.Dragging() and event.RightIsDown():
e = event.GetPositionTuple()
if not self.initpos or not hasattr(self, "basetrans"):
self.initpos = e
self.basetrans = self.p.translate
self.p.translate = [self.basetrans[0] + (e[0] - self.initpos[0]),
self.basetrans[1] + (e[1] - self.initpos[1])]
self.p.dirty = 1
wx.CallAfter(self.p.Refresh)
elif event.Dragging() and event.LeftIsDown():
x, y = event.GetPositionTuple()
if not hasattr(self, "basetrans"):
self.basetrans = self.p.translate
x = (x - self.basetrans[0]) / self.p.scale[0]
y = (y - self.basetrans[1]) / self.p.scale[1]
x, y = self.real_to_gcode(x, y)
if not self.initpos:
self.initpos = (x, y)
self.basetrans = self.p.translate
self.parent.rectangles.append((0, 0, 0, 0))
else:
pos = (x, y)
x0 = min(self.initpos[0], pos[0])
y0 = min(self.initpos[1], pos[1])
x1 = max(self.initpos[0], pos[0])
y1 = max(self.initpos[1], pos[1])
self.parent.rectangles[-1] = (x0, y0, x1, y1)
wx.CallAfter(self.p.Refresh)
else:
event.Skip()
def _line_scaler(self, orig):
x0, y0 = self.gcode_to_real(orig[0], orig[1])
x0 = self.p.scale[0]*x0 + self.p.translate[0]
y0 = self.p.scale[1]*y0 + self.p.translate[1]
x1, y1 = self.gcode_to_real(orig[2], orig[3])
x1 = self.p.scale[0]*x1 + self.p.translate[0]
y1 = self.p.scale[1]*y1 + self.p.translate[1]
width = max(x0, x1) - min(x0, x1) + 1
height = max(y0, y1) - min(y0, y1) + 1
return (min(x0, x1), min(y0, y1), width, height,)
def paint_selection(self, dc):
dc = wx.GCDC(dc)
dc.SetPen(wx.TRANSPARENT_PEN)
dc.DrawRectangleList([self._line_scaler(rect) for rect in self.parent.rectangles],
None, wx.Brush((200, 200, 200, 150)))
def reset_selection(self, event):
self.parent.rectangles = []
wx.CallAfter(self.p.Refresh)
class Excluder(object):
def __init__(self):
self.rectangles = []
self.window = None
def pop_window(self, gcode, *args, **kwargs):
if not self.window:
self.window = ExcluderWindow(self, *args, **kwargs)
self.window.p.addfile(gcode)
self.window.p.layerup()
self.window.Bind(wx.EVT_CLOSE, self.close_window)
self.window.Show()
else:
self.window.Show()
self.window.Raise()
def close_window(self, event = None):
if self.window:
self.window.Destroy()
self.window = None
if __name__ == '__main__':
import sys
gcode = gcoder.GCode(open(sys.argv[1]))
app = wx.App(False)
ex = Excluder()
ex.pop_window(gcode)
app.MainLoop()
...@@ -20,66 +20,67 @@ import math ...@@ -20,66 +20,67 @@ import math
import datetime import datetime
from array import array from array import array
gcode_parsed_args = ["x", "y", "e", "f", "z", "p", "i", "j", "s"] gcode_parsed_args = ["x", "y", "e", "f", "z", "i", "j"]
gcode_exp = re.compile("\([^\(\)]*\)|;.*|[/\*].*\n|[a-z][-+]?[0-9]*\.?[0-9]*") gcode_parsed_nonargs = ["g", "t", "m", "n"]
m114_exp = re.compile("\([^\(\)]*\)|[/\*].*\n|[A-Z]:?[-+]?[0-9]*\.?[0-9]*") to_parse = "".join(gcode_parsed_args + gcode_parsed_nonargs)
gcode_exp = re.compile("\([^\(\)]*\)|;.*|[/\*].*\n|([%s])([-+]?[0-9]*\.?[0-9]*)" % to_parse)
m114_exp = re.compile("\([^\(\)]*\)|[/\*].*\n|([XYZ]):?([-+]?[0-9]*\.?[0-9]*)")
specific_exp = "(?:\([^\(\)]*\))|(?:;.*)|(?:[/\*].*\n)|(%s[-+]?[0-9]*\.?[0-9]*)"
move_gcodes = ["G0", "G1", "G2", "G3"] move_gcodes = ["G0", "G1", "G2", "G3"]
class PyLine(object): class PyLine(object):
__slots__ = ('x','y','z','e','f','i','j','s','p', __slots__ = ('x','y','z','e','f','i','j',
'raw','split_raw', 'raw','split_raw',
'command','is_move', 'command','is_move',
'relative','relative_e', 'relative','relative_e',
'current_x', 'current_y', 'current_z', 'extruding', 'current_tool', 'current_x', 'current_y', 'current_z', 'extruding', 'current_tool',
'gcview_end_vertex') 'gcview_end_vertex')
def __init__(self, l):
self.raw = l
def __getattr__(self, name): def __getattr__(self, name):
return None return None
try: try:
import gcoder_line import gcoder_line
LineBase = gcoder_line.GLine Line = gcoder_line.GLine
except ImportError: except ImportError:
LineBase = PyLine Line = PyLine
class Line(LineBase): def find_specific_code(line, code):
exp = specific_exp % code
bits = [bit for bit in re.findall(exp, line.raw) if bit]
if not bits: return None
else: return float(bits[0][1:])
__slots__ = () def S(line):
return find_specific_code(line, "S")
def __init__(self, l): def P(line):
super(Line, self).__init__() return find_specific_code(line, "P")
self.raw = l
self.split_raw = gcode_exp.findall(self.raw.lower()) def split(line):
self.command = self.split_raw[0].upper() if not self.split_raw[0].startswith("n") else self.split_raw[1].upper() split_raw = gcode_exp.findall(line.raw.lower())
self.is_move = self.command in move_gcodes command = split_raw[0] if split_raw[0][0] != "n" else split_raw[1]
line.command = command[0].upper() + command[1]
line.is_move = line.command in move_gcodes
return split_raw
def parse_coordinates(self, imperial = False, force = False): def parse_coordinates(line, split_raw, imperial = False, force = False):
# Not a G-line, we don't want to parse its arguments # Not a G-line, we don't want to parse its arguments
if not force and not self.command[0] == "G": if not force and line.command[0] != "G":
return return
if imperial: unit_factor = 25.4 if imperial else 1
for bit in self.split_raw: for bit in split_raw:
code = bit[0]
if code in gcode_parsed_args and len(bit) > 1:
setattr(self, code, 25.4*float(bit[1:]))
else:
for bit in self.split_raw:
code = bit[0] code = bit[0]
if code in gcode_parsed_args and len(bit) > 1: if code not in gcode_parsed_nonargs and bit[1]:
setattr(self, code, float(bit[1:])) setattr(line, code, unit_factor*float(bit[1]))
del self.split_raw
def __repr__(self):
return self.raw
class Layer(object): class Layer(list):
lines = None
duration = None
def __init__(self, lines): __slots__ = ("duration")
self.lines = lines
def _preprocess(self, current_x, current_y, current_z): def _preprocess(self, current_x, current_y, current_z):
xmin = float("inf") xmin = float("inf")
...@@ -91,7 +92,7 @@ class Layer(object): ...@@ -91,7 +92,7 @@ class Layer(object):
relative = False relative = False
relative_e = False relative_e = False
for line in self.lines: for line in self:
if not line.is_move and line.command != "G92": if not line.is_move and line.command != "G92":
continue continue
if line.is_move: if line.is_move:
...@@ -178,9 +179,9 @@ class GCode(object): ...@@ -178,9 +179,9 @@ class GCode(object):
self.lines.append(gline) self.lines.append(gline)
self._preprocess_lines([gline]) self._preprocess_lines([gline])
self._preprocess_extrusion([gline]) self._preprocess_extrusion([gline])
self.append_layer.lines.append(gline) self.append_layer.append(gline)
self.layer_idxs.append(self.append_layer_id) self.layer_idxs.append(self.append_layer_id)
self.line_idxs.append(len(self.append_layer.lines)) self.line_idxs.append(len(self.append_layer))
return gline return gline
def _preprocess_lines(self, lines = None): def _preprocess_lines(self, lines = None):
...@@ -192,6 +193,9 @@ class GCode(object): ...@@ -192,6 +193,9 @@ class GCode(object):
relative_e = self.relative_e relative_e = self.relative_e
current_tool = self.current_tool current_tool = self.current_tool
for line in lines: for line in lines:
split_raw = split(line)
if not line.command:
continue
if line.is_move: if line.is_move:
line.relative = relative line.relative = relative
line.relative_e = relative_e line.relative_e = relative_e
...@@ -213,7 +217,7 @@ class GCode(object): ...@@ -213,7 +217,7 @@ class GCode(object):
elif line.command[0] == "T": elif line.command[0] == "T":
current_tool = int(line.command[1:]) current_tool = int(line.command[1:])
if line.command[0] == "G": if line.command[0] == "G":
line.parse_coordinates(imperial) parse_coordinates(line, split_raw, imperial)
self.imperial = imperial self.imperial = imperial
self.relative = relative self.relative = relative
self.relative_e = relative_e self.relative_e = relative_e
...@@ -283,7 +287,7 @@ class GCode(object): ...@@ -283,7 +287,7 @@ class GCode(object):
if cur_lines: if cur_lines:
all_layers.append(Layer(cur_lines)) all_layers.append(Layer(cur_lines))
old_lines = layers.pop(prev_z, []) old_lines = layers.get(prev_z, [])
old_lines += cur_lines old_lines += cur_lines
layers[prev_z] = old_lines layers[prev_z] = old_lines
...@@ -359,7 +363,7 @@ class GCode(object): ...@@ -359,7 +363,7 @@ class GCode(object):
# get device caps from firmware: max speed, acceleration/axis (including extruder) # get device caps from firmware: max speed, acceleration/axis (including extruder)
# calculate the maximum move duration accounting for above ;) # calculate the maximum move duration accounting for above ;)
for layer in self.all_layers: for layer in self.all_layers:
for line in layer.lines: for line in layer:
if line.command not in ["G1", "G0", "G4"]: if line.command not in ["G1", "G0", "G4"]:
continue continue
if line.command == "G4": if line.command == "G4":
...@@ -408,6 +412,7 @@ def main(): ...@@ -408,6 +412,7 @@ def main():
print "usage: %s filename.gcode" % sys.argv[0] print "usage: %s filename.gcode" % sys.argv[0]
return return
print "Line object size:", sys.getsizeof(Line("G0 X0"))
gcode = GCode(open(sys.argv[1])) gcode = GCode(open(sys.argv[1]))
print "Dimensions:" print "Dimensions:"
......
--- printrun/gcoder_line.c 2013-06-15 16:08:53.260081109 +0200
+++ printrun/gcoder_line.c 2013-06-15 16:08:57.083439793 +0200
@@ -3945,2 +3945,4 @@ static int __Pyx_InitGlobals(void) {
+#include "gcoder_line_extra.h"
+
#if PY_MAJOR_VERSION < 3
@@ -4032,2 +4034,7 @@ PyMODINIT_FUNC PyInit_gcoder_line(void)
/*--- Execution code ---*/
+ nysets_heapdefs[0].type = &__pyx_type_8printrun_11gcoder_line_GLine;
+ if (PyDict_SetItemString(__pyx_d,
+ "_NyHeapDefs_",
+ PyCObject_FromVoidPtrAndDesc(&nysets_heapdefs, "NyHeapDef[] v1.0", 0)) < 0)
+{__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
...@@ -36,20 +36,18 @@ cdef enum BitPos: ...@@ -36,20 +36,18 @@ cdef enum BitPos:
pos_f = 1 << 4 pos_f = 1 << 4
pos_i = 1 << 5 pos_i = 1 << 5
pos_j = 1 << 6 pos_j = 1 << 6
pos_s = 1 << 7 pos_is_move = 1 << 7
pos_p = 1 << 8 pos_relative = 1 << 8
pos_is_move = 1 << 9 pos_relative_e = 1 << 9
pos_relative = 1 << 10 pos_extruding = 1 << 10
pos_relative_e = 1 << 11 pos_current_x = 1 << 11
pos_extruding = 1 << 12 pos_current_y = 1 << 12
pos_current_x = 1 << 13 pos_current_z = 1 << 13
pos_current_y = 1 << 14 pos_current_tool = 1 << 14
pos_current_z = 1 << 15 pos_raw = 1 << 15
pos_current_tool = 1 << 16 pos_command = 1 << 16
pos_raw = 1 << 17 pos_gcview_end_vertex = 1 << 17
pos_split_raw = 1 << 18 # WARNING: don't use bits 24 to 31 as we store current_tool there
pos_command = 1 << 19
pos_gcview_end_vertex = 1 << 20
cdef inline uint32_t has_var(uint32_t status, uint32_t pos): cdef inline uint32_t has_var(uint32_t status, uint32_t pos):
return status & pos return status & pos
...@@ -60,16 +58,14 @@ cdef inline uint32_t set_has_var(uint32_t status, uint32_t pos): ...@@ -60,16 +58,14 @@ cdef inline uint32_t set_has_var(uint32_t status, uint32_t pos):
cdef inline uint32_t unset_has_var(uint32_t status, uint32_t pos): cdef inline uint32_t unset_has_var(uint32_t status, uint32_t pos):
return status & ~pos return status & ~pos
cdef class GLine(object): cdef class GLine:
cdef char* _raw cdef char* _raw
cdef char* _command cdef char* _command
cdef object _split_raw cdef float _x, _y, _z, _e, _f, _i, _j
cdef float _x, _y, _z, _e, _f, _i, _j, _s, _p
cdef float _current_x, _current_y, _current_z cdef float _current_x, _current_y, _current_z
cdef uint32_t _gcview_end_vertex cdef uint32_t _gcview_end_vertex
cdef uint32_t _status cdef uint32_t _status
cdef char _current_tool
__slots__ = () __slots__ = ()
...@@ -78,6 +74,9 @@ cdef class GLine(object): ...@@ -78,6 +74,9 @@ cdef class GLine(object):
self._raw = NULL self._raw = NULL
self._command = NULL self._command = NULL
def __init__(self, line):
self.raw = line
def __dealloc__(self): def __dealloc__(self):
if self._raw != NULL: free(self._raw) if self._raw != NULL: free(self._raw)
if self._command != NULL: free(self._command) if self._command != NULL: free(self._command)
...@@ -131,20 +130,6 @@ cdef class GLine(object): ...@@ -131,20 +130,6 @@ cdef class GLine(object):
def __set__(self, value): def __set__(self, value):
self._j = value self._j = value
self._status = set_has_var(self._status, pos_j) self._status = set_has_var(self._status, pos_j)
property s:
def __get__(self):
if has_var(self._status, pos_s): return self._s
else: return None
def __set__(self, value):
self._s = value
self._status = set_has_var(self._status, pos_s)
property p:
def __get__(self):
if has_var(self._status, pos_p): return self._p
else: return None
def __set__(self, value):
self._p = value
self._status = set_has_var(self._status, pos_p)
property is_move: property is_move:
def __get__(self): def __get__(self):
if has_var(self._status, pos_is_move): return True if has_var(self._status, pos_is_move): return True
...@@ -196,10 +181,10 @@ cdef class GLine(object): ...@@ -196,10 +181,10 @@ cdef class GLine(object):
self._status = set_has_var(self._status, pos_current_z) self._status = set_has_var(self._status, pos_current_z)
property current_tool: property current_tool:
def __get__(self): def __get__(self):
if has_var(self._status, pos_current_tool): return self._current_tool if has_var(self._status, pos_current_tool): return self._status >> 24
else: return None else: return None
def __set__(self, value): def __set__(self, value):
self._current_tool = value self._status = (self._status & ((1 << 24) - 1)) | (value << 24)
self._status = set_has_var(self._status, pos_current_tool) self._status = set_has_var(self._status, pos_current_tool)
property gcview_end_vertex: property gcview_end_vertex:
def __get__(self): def __get__(self):
...@@ -208,20 +193,13 @@ cdef class GLine(object): ...@@ -208,20 +193,13 @@ cdef class GLine(object):
def __set__(self, value): def __set__(self, value):
self._gcview_end_vertex = value self._gcview_end_vertex = value
self._status = set_has_var(self._status, pos_gcview_end_vertex) self._status = set_has_var(self._status, pos_gcview_end_vertex)
property split_raw:
def __get__(self):
if has_var(self._status, pos_split_raw): return self._split_raw
else: return None
def __set__(self, value):
self._split_raw = value
self._status = set_has_var(self._status, pos_split_raw)
def __del__(self):
self._split_raw = None
property raw: property raw:
def __get__(self): def __get__(self):
if has_var(self._status, pos_raw): return self._raw if has_var(self._status, pos_raw): return self._raw
else: return None else: return None
def __set__(self, value): def __set__(self, value):
# WARNING: memory leak could happen here, as we don't do the following :
# if self._raw != NULL: free(self._raw)
self._raw = copy_string(value) self._raw = copy_string(value)
self._status = set_has_var(self._status, pos_raw) self._status = set_has_var(self._status, pos_raw)
property command: property command:
...@@ -229,5 +207,7 @@ cdef class GLine(object): ...@@ -229,5 +207,7 @@ cdef class GLine(object):
if has_var(self._status, pos_command): return self._command if has_var(self._status, pos_command): return self._command
else: return None else: return None
def __set__(self, value): def __set__(self, value):
# WARNING: memory leak could happen here, as we don't do the following :
# if self._command != NULL: free(self._command)
self._command = copy_string(value) self._command = copy_string(value)
self._status = set_has_var(self._status, pos_command) self._status = set_has_var(self._status, pos_command)
typedef int (*NyHeapDef_SizeGetter) (PyObject *obj);
typedef struct {
int flags; /* As yet, only 0 */
PyTypeObject *type; /* The type it regards */
NyHeapDef_SizeGetter size;
void *traverse;
void *relate;
void *resv3, *resv4, *resv5; /* Reserved for future bin. comp. */
} NyHeapDef;
int gline_size(struct __pyx_obj_8printrun_11gcoder_line_GLine *gline) {
int size = __pyx_type_8printrun_11gcoder_line_GLine.tp_basicsize;
if (gline->_raw != NULL)
size += strlen(gline->_raw) + 1;
if (gline->_command != NULL)
size += strlen(gline->_command) + 1;
return size;
}
static NyHeapDef nysets_heapdefs[] = {
{0, 0, (NyHeapDef_SizeGetter) gline_size},
};
/*
nysets_heapdefs[0].type = &__pyx_type_8printrun_11gcoder_line_GLine;
if (PyDict_SetItemString(__pyx_d,
"_NyHeapDefs_",
PyCObject_FromVoidPtrAndDesc(&nysets_heapdefs, "NyHeapDef[] v1.0", 0)) < 0)
{__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
*/
...@@ -34,6 +34,8 @@ from .libtatlin import actors ...@@ -34,6 +34,8 @@ from .libtatlin import actors
class wxGLPanel(wx.Panel): class wxGLPanel(wx.Panel):
'''A simple class for using OpenGL with wxPython.''' '''A simple class for using OpenGL with wxPython.'''
orthographic = True
def __init__(self, parent, id, pos = wx.DefaultPosition, def __init__(self, parent, id, pos = wx.DefaultPosition,
size = wx.DefaultSize, style = 0): size = wx.DefaultSize, style = 0):
# Forcing a no full repaint to stop flickering # Forcing a no full repaint to stop flickering
...@@ -63,11 +65,11 @@ class wxGLPanel(wx.Panel): ...@@ -63,11 +65,11 @@ class wxGLPanel(wx.Panel):
def processSizeEvent(self, event): def processSizeEvent(self, event):
'''Process the resize event.''' '''Process the resize event.'''
if (wx.VERSION > (2,9) and self.canvas.IsShownOnScreen()) or self.canvas.GetContext():
# Make sure the frame is shown before calling SetCurrent.
size = self.GetClientSize() size = self.GetClientSize()
self.winsize = (size.width, size.height) self.winsize = (size.width, size.height)
self.width, self.height = size.width, size.height self.width, self.height = size.width, size.height
if (wx.VERSION > (2,9) and self.canvas.IsShownOnScreen()) or self.canvas.GetContext():
# Make sure the frame is shown before calling SetCurrent.
self.canvas.SetCurrent(self.context) self.canvas.SetCurrent(self.context)
self.OnReshape(size.width, size.height) self.OnReshape(size.width, size.height)
self.canvas.Refresh(False) self.canvas.Refresh(False)
...@@ -97,11 +99,9 @@ class wxGLPanel(wx.Panel): ...@@ -97,11 +99,9 @@ class wxGLPanel(wx.Panel):
def OnInitGL(self): def OnInitGL(self):
'''Initialize OpenGL for use in the window.''' '''Initialize OpenGL for use in the window.'''
#create a pyglet context for this panel #create a pyglet context for this panel
self.mvmat = (GLdouble * 16)()
self.pygletcontext = gl.Context(gl.current_context) self.pygletcontext = gl.Context(gl.current_context)
self.pygletcontext.canvas = self self.pygletcontext.canvas = self
self.pygletcontext.set_current() self.pygletcontext.set_current()
self.dist = 1000
#normal gl init #normal gl init
glClearColor(0.98, 0.98, 0.78, 1) glClearColor(0.98, 0.98, 0.78, 1)
glClearDepth(1.0) # set depth value to 1 glClearDepth(1.0) # set depth value to 1
...@@ -121,12 +121,15 @@ class wxGLPanel(wx.Panel): ...@@ -121,12 +121,15 @@ class wxGLPanel(wx.Panel):
glViewport(0, 0, width, height) glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION) glMatrixMode(GL_PROJECTION)
glLoadIdentity() glLoadIdentity()
gluPerspective(60., width / float(height), .1, 1000.) if self.orthographic:
glOrtho(-width / 2, width / 2, -height / 2, height / 2, 0.1, 3 * self.dist)
else:
gluPerspective(60., float(width) / height, 10.0, 3 * self.dist)
glMatrixMode(GL_MODELVIEW) glMatrixMode(GL_MODELVIEW)
glLoadIdentity() glLoadIdentity()
glTranslatef(*self.transv) if self.orthographic:
glMultMatrixd(build_rotmatrix(self.basequat)) ratio = 0.9 * float(min(self.width, self.height)) / self.dist
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat) glScalef(ratio, ratio, 1)
# Wrap text to the width of the window # Wrap text to the width of the window
if self.GLinitialized: if self.GLinitialized:
...@@ -250,7 +253,6 @@ class GcodeViewPanel(wxGLPanel): ...@@ -250,7 +253,6 @@ class GcodeViewPanel(wxGLPanel):
self.dist = max(build_dimensions[0], build_dimensions[1]) self.dist = max(build_dimensions[0], build_dimensions[1])
else: else:
self.dist = 200 self.dist = 200
self.transv = [0, 0, -self.dist]
self.basequat = [0, 0, 0, 1] self.basequat = [0, 0, 0, 1]
self.mousepos = [0, 0] self.mousepos = [0, 0]
...@@ -268,11 +270,10 @@ class GcodeViewPanel(wxGLPanel): ...@@ -268,11 +270,10 @@ class GcodeViewPanel(wxGLPanel):
'''called in the middle of ondraw after the buffer has been cleared''' '''called in the middle of ondraw after the buffer has been cleared'''
self.create_objects() self.create_objects()
glLoadIdentity()
glMultMatrixd(self.mvmat)
glPushMatrix() glPushMatrix()
glTranslatef(-self.parent.platform.width/2, -self.parent.platform.depth/2, 0) glTranslatef(0, 0, -self.dist) # Move back
glMultMatrixd(build_rotmatrix(self.basequat)) # Rotate according to trackball
glTranslatef(-self.parent.platform.width/2, -self.parent.platform.depth/2, 0) # Move origin to bottom left of platform
for obj in self.parent.objects: for obj in self.parent.objects:
if not obj.model or not obj.model.loaded or not obj.model.initialized: if not obj.model or not obj.model.loaded or not obj.model.initialized:
...@@ -290,66 +291,52 @@ class GcodeViewPanel(wxGLPanel): ...@@ -290,66 +291,52 @@ class GcodeViewPanel(wxGLPanel):
if self.parent.clickcb: if self.parent.clickcb:
self.parent.clickcb(event) self.parent.clickcb(event)
def move(self, event): def handle_rotation(self, event):
"""react to mouse actions:
no mouse: show red mousedrop
LMB: rotate viewport
RMB: move viewport
"""
if event.Entering():
self.canvas.SetFocus()
event.Skip()
return
if event.Dragging() and event.LeftIsDown():
if self.initpos == None: if self.initpos == None:
self.initpos = event.GetPositionTuple() self.initpos = event.GetPositionTuple()
else: else:
#print self.initpos
p1 = self.initpos p1 = self.initpos
self.initpos = None
p2 = event.GetPositionTuple() p2 = event.GetPositionTuple()
sz = self.GetClientSize() sz = self.GetClientSize()
p1x = (float(p1[0]) - sz[0] / 2) / (sz[0] / 2) p1x = float(p1[0]) / (sz[0] / 2) - 1
p1y = -(float(p1[1]) - sz[1] / 2) / (sz[1] / 2) p1y = 1 - float(p1[1]) / (sz[1] / 2)
p2x = (float(p2[0]) - sz[0] / 2) / (sz[0] / 2) p2x = float(p2[0]) / (sz[0] / 2) - 1
p2y = -(float(p2[1]) - sz[1] / 2) / (sz[1] / 2) p2y = 1 - float(p2[1]) / (sz[1] / 2)
#print p1x, p1y, p2x, p2y quat = trackball(p1x, p1y, p2x, p2y, self.dist / 250.0)
quat = trackball(p1x, p1y, p2x, p2y, -self.transv[2] / 250.0)
self.basequat = mulquat(self.basequat, quat) self.basequat = mulquat(self.basequat, quat)
mat = build_rotmatrix(self.basequat) self.initpos = p2
glLoadIdentity()
glTranslatef(*self.transv)
glMultMatrixd(mat)
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
elif event.ButtonUp(wx.MOUSE_BTN_LEFT): def handle_translation(self, event):
if self.initpos is not None:
self.initpos = None
elif event.ButtonUp(wx.MOUSE_BTN_RIGHT):
if self.initpos is not None:
self.initpos = None
elif event.Dragging() and event.RightIsDown():
if self.initpos is None: if self.initpos is None:
self.initpos = event.GetPositionTuple() self.initpos = event.GetPositionTuple()
else: else:
p1 = self.initpos p1 = self.initpos
p2 = event.GetPositionTuple() p2 = event.GetPositionTuple()
sz = self.GetClientSize() if self.orthographic:
p1 = list(p1) + [0] x1, y1, _ = self.mouse_to_3d(p1[0], p1[1])
p2 = list(p2) + [0] x2, y2, _ = self.mouse_to_3d(p2[0], p2[1])
p1[1] *= -1 glTranslatef(x2 - x1, y2 - y1, 0)
p2[1] *= -1 else:
sz = list(sz) + [1] glTranslatef(p2[0] - p1[0], -(p2[1] - p1[1]), 0)
sz[0] *= 2 self.initpos = p2
sz[1] *= 2
self.transv = map(lambda x, y, z, c: c - self.dist * (x - y) / z, p1, p2, sz, self.transv)
glLoadIdentity() def move(self, event):
glTranslatef(*self.transv) """react to mouse actions:
glMultMatrixd(build_rotmatrix(self.basequat)) no mouse: show red mousedrop
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat) LMB: rotate viewport
RMB: move viewport
"""
if event.Entering():
self.canvas.SetFocus()
event.Skip()
return
if event.Dragging() and event.LeftIsDown():
self.handle_rotation(event)
elif event.Dragging() and event.RightIsDown():
self.handle_translation(event)
elif event.ButtonUp(wx.MOUSE_BTN_LEFT):
self.initpos = None
elif event.ButtonUp(wx.MOUSE_BTN_RIGHT):
self.initpos = None self.initpos = None
else: else:
event.Skip() event.Skip()
...@@ -362,7 +349,10 @@ class GcodeViewPanel(wxGLPanel): ...@@ -362,7 +349,10 @@ class GcodeViewPanel(wxGLPanel):
return return
max_layers = self.parent.model.max_layers max_layers = self.parent.model.max_layers
current_layer = self.parent.model.num_layers_to_draw current_layer = self.parent.model.num_layers_to_draw
new_layer = min(max_layers, current_layer + 1) # accept going up to max_layers + 1
# max_layers means visualizing the last layer differently,
# max_layers + 1 means visualizing all layers with the same color
new_layer = min(max_layers + 1, current_layer + 1)
self.parent.model.num_layers_to_draw = new_layer self.parent.model.num_layers_to_draw = new_layer
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
...@@ -374,13 +364,15 @@ class GcodeViewPanel(wxGLPanel): ...@@ -374,13 +364,15 @@ class GcodeViewPanel(wxGLPanel):
self.parent.model.num_layers_to_draw = new_layer self.parent.model.num_layers_to_draw = new_layer
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
def zoom(self, dist): def zoom(self, factor, to = None):
self.transv[2] += dist
glMatrixMode(GL_MODELVIEW) glMatrixMode(GL_MODELVIEW)
glLoadIdentity() if to:
glTranslatef(*self.transv) delta_x = to[0]
glMultMatrixd(build_rotmatrix(self.basequat)) delta_y = to[1]
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat) glTranslatef(delta_x, delta_y, 0)
glScalef(factor, factor, 1)
if to:
glTranslatef(-delta_x, -delta_y, 0)
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
def wheel(self, event): def wheel(self, event):
...@@ -388,40 +380,60 @@ class GcodeViewPanel(wxGLPanel): ...@@ -388,40 +380,60 @@ class GcodeViewPanel(wxGLPanel):
without shift: set max layer without shift: set max layer
with shift: zoom viewport with shift: zoom viewport
""" """
z = event.GetWheelRotation() delta = event.GetWheelRotation()
dist = 10 factor = 1.05
if event.ShiftDown(): if event.ShiftDown():
if not self.parent.model: if not self.parent.model:
return return
if z > 0: if delta > 0:
self.layerup() self.layerup()
else: else:
self.layerdown() self.layerdown()
return return
if z > 0: x, y = event.GetPositionTuple()
self.zoom(dist) x, y, _ = self.mouse_to_3d(x, y)
if delta > 0:
self.zoom(factor, (x, y))
else: else:
self.zoom(-dist) self.zoom(1/factor, (x, y))
def mouse_to_3d(self, x, y):
x = float(x)
y = self.height - float(y)
# The following could work if we were not initially scaling to zoom on the bed
#if self.orthographic:
# return (x - self.width / 2, y - self.height / 2, 0)
pmat = (GLdouble * 16)()
mvmat = (GLdouble * 16)()
viewport = (GLint * 4)()
px = (GLdouble)()
py = (GLdouble)()
pz = (GLdouble)()
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_PROJECTION_MATRIX, pmat)
glGetDoublev(GL_MODELVIEW_MATRIX, mvmat)
gluUnProject(x, y, 1.0, mvmat, pmat, viewport, px, py, pz)
return (px.value, py.value, pz.value)
def keypress(self, event): def keypress(self, event):
"""gets keypress events and moves/rotates acive shape""" """gets keypress events and moves/rotates acive shape"""
keycode = event.GetKeyCode() step = 1.1
step = 10
if event.ControlDown(): if event.ControlDown():
step = 3 step = 1.05
kup = [85, 315] # Up keys kup = [85, 315] # Up keys
kdo = [68, 317] # Down Keys kdo = [68, 317] # Down Keys
kzi = [wx.WXK_PAGEDOWN, 388, 316, 61] # Zoom In Keys kzi = [wx.WXK_PAGEDOWN, 388, 316, 61] # Zoom In Keys
kzo = [wx.WXK_PAGEUP, 390, 314, 45] # Zoom Out Keys kzo = [wx.WXK_PAGEUP, 390, 314, 45] # Zoom Out Keys
x = event.GetKeyCode() key = event.GetKeyCode()
if x in kup: if key in kup:
self.layerup() self.layerup()
if x in kdo: if key in kdo:
self.layerdown() self.layerdown()
if x in kzi: x, y, _ = self.mouse_to_3d(self.width / 2, self.height / 2)
self.zoom(step) if key in kzi:
if x in kzo: self.zoom(step, (x, y))
self.zoom(-step) if key in kzo:
self.zoom(1 / step, (x, y))
event.Skip() event.Skip()
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
......
...@@ -266,7 +266,7 @@ class VizPane(wx.BoxSizer): ...@@ -266,7 +266,7 @@ class VizPane(wx.BoxSizer):
print "Falling back to 2D view, and here is the backtrace:" print "Falling back to 2D view, and here is the backtrace:"
traceback.print_exc() traceback.print_exc()
if use2dview: if use2dview:
root.gviz = gviz.gviz(parentpanel, (300, 300), root.gviz = gviz.Gviz(parentpanel, (300, 300),
build_dimensions = root.build_dimensions_list, build_dimensions = root.build_dimensions_list,
grid = (root.settings.preview_grid_step1, root.settings.preview_grid_step2), grid = (root.settings.preview_grid_step1, root.settings.preview_grid_step2),
extrusion_width = root.settings.preview_extrusion_width, extrusion_width = root.settings.preview_extrusion_width,
...@@ -288,7 +288,7 @@ class VizPane(wx.BoxSizer): ...@@ -288,7 +288,7 @@ class VizPane(wx.BoxSizer):
print "Falling back to 2D view, and here is the backtrace:" print "Falling back to 2D view, and here is the backtrace:"
traceback.print_exc() traceback.print_exc()
if not use3dview: if not use3dview:
root.gwindow = gviz.window([], root.gwindow = gviz.GvizWindow(
build_dimensions = root.build_dimensions_list, build_dimensions = root.build_dimensions_list,
grid = (root.settings.preview_grid_step1, root.settings.preview_grid_step2), grid = (root.settings.preview_grid_step1, root.settings.preview_grid_step2),
extrusion_width = root.settings.preview_extrusion_width, extrusion_width = root.settings.preview_extrusion_width,
......
...@@ -18,31 +18,33 @@ from collections import deque ...@@ -18,31 +18,33 @@ from collections import deque
import wx, time import wx, time
from printrun import gcoder from printrun import gcoder
from printrun_utils import imagefile from printrun_utils import imagefile, install_locale
install_locale('pronterface')
ID_ABOUT = 101 ID_ABOUT = 101
ID_EXIT = 110 ID_EXIT = 110
class window(wx.Frame): class GvizWindow(wx.Frame):
def __init__(self, f, size = (600, 600), build_dimensions = [200, 200, 100, 0, 0, 0], grid = (10, 50), extrusion_width = 0.5, bgcolor = "#000000"): def __init__(self, f = None, size = (600, 600), build_dimensions = [200, 200, 100, 0, 0, 0], grid = (10, 50), extrusion_width = 0.5, bgcolor = "#000000"):
wx.Frame.__init__(self, None, title = "Gcode view, shift to move view, mousewheel to set layer", size = size) wx.Frame.__init__(self, None, title = _("Gcode view, shift to move view, mousewheel to set layer"), size = size)
self.CreateStatusBar(1); self.CreateStatusBar(1);
self.SetStatusText("Layer number and Z position show here when you scroll"); self.SetStatusText(_("Layer number and Z position show here when you scroll"))
panel = wx.Panel(self, -1) panel = wx.Panel(self, -1)
self.p = gviz(panel, size = size, build_dimensions = build_dimensions, grid = grid, extrusion_width = extrusion_width, bgcolor = bgcolor, realparent = self) self.p = Gviz(panel, size = size, build_dimensions = build_dimensions, grid = grid, extrusion_width = extrusion_width, bgcolor = bgcolor, realparent = self)
vbox = wx.BoxSizer(wx.VERTICAL) vbox = wx.BoxSizer(wx.VERTICAL)
toolbar = wx.ToolBar(panel, -1, style = wx.TB_HORIZONTAL | wx.NO_BORDER) toolbar = wx.ToolBar(panel, -1, style = wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_HORZ_TEXT)
toolbar.AddSimpleTool(1, wx.Image(imagefile('zoom_in.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Zoom In [+]', '') toolbar.AddSimpleTool(1, wx.Image(imagefile('zoom_in.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), _("Zoom In [+]"), '')
toolbar.AddSimpleTool(2, wx.Image(imagefile('zoom_out.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Zoom Out [-]', '') toolbar.AddSimpleTool(2, wx.Image(imagefile('zoom_out.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), _("Zoom Out [-]"), '')
toolbar.AddSeparator() toolbar.AddSeparator()
toolbar.AddSimpleTool(3, wx.Image(imagefile('arrow_up.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Move Up a Layer [U]', '') toolbar.AddSimpleTool(3, wx.Image(imagefile('arrow_up.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), _("Move Up a Layer [U]"), '')
toolbar.AddSimpleTool(4, wx.Image(imagefile('arrow_down.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Move Down a Layer [D]', '') toolbar.AddSimpleTool(4, wx.Image(imagefile('arrow_down.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), _("Move Down a Layer [D]"), '')
toolbar.AddSimpleTool(5, wx.Image(imagefile('reset.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Reset view', '') toolbar.AddLabelTool(5, " " + _("Reset view"), wx.Image(imagefile('reset.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), shortHelp = _("Reset view"), longHelp = '')
toolbar.AddSeparator() toolbar.AddSeparator()
#toolbar.AddSimpleTool(6, wx.Image(imagefile('inject.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Insert Code at start of this layer', '') #toolbar.AddSimpleTool(6, wx.Image(imagefile('inject.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), _("Insert Code at start of this layer"), '')
toolbar.Realize() toolbar.Realize()
self.toolbar = toolbar
vbox.Add(toolbar, 0, border = 5) vbox.Add(toolbar, 0, border = 5)
vbox.Add(self.p, 1, wx.EXPAND) vbox.Add(self.p, 1, wx.EXPAND)
panel.SetSizer(vbox) panel.SetSizer(vbox)
...@@ -54,7 +56,7 @@ class window(wx.Frame): ...@@ -54,7 +56,7 @@ class window(wx.Frame):
self.Bind(wx.EVT_TOOL, self.resetview, id = 5) self.Bind(wx.EVT_TOOL, self.resetview, id = 5)
#self.Bind(wx.EVT_TOOL, lambda x:self.p.inject(), id = 6) #self.Bind(wx.EVT_TOOL, lambda x:self.p.inject(), id = 6)
self.initpos = [0, 0] self.initpos = None
self.p.Bind(wx.EVT_KEY_DOWN, self.key) self.p.Bind(wx.EVT_KEY_DOWN, self.key)
self.Bind(wx.EVT_KEY_DOWN, self.key) self.Bind(wx.EVT_KEY_DOWN, self.key)
self.p.Bind(wx.EVT_MOUSEWHEEL, self.zoom) self.p.Bind(wx.EVT_MOUSEWHEEL, self.zoom)
...@@ -75,12 +77,12 @@ class window(wx.Frame): ...@@ -75,12 +77,12 @@ class window(wx.Frame):
self.p.zoom(0, 0, 1.0) self.p.zoom(0, 0, 1.0)
def mouse(self, event): def mouse(self, event):
if event.ButtonUp(wx.MOUSE_BTN_LEFT): if event.ButtonUp(wx.MOUSE_BTN_LEFT) or event.ButtonUp(wx.MOUSE_BTN_RIGHT):
if self.initpos is not None: if self.initpos is not None:
self.initpos = None self.initpos = None
elif event.Dragging(): elif event.Dragging():
e = event.GetPositionTuple() e = event.GetPositionTuple()
if self.initpos is None or not hasattr(self, "basetrans"): if self.initpos is None:
self.initpos = e self.initpos = e
self.basetrans = self.p.translate self.basetrans = self.p.translate
self.p.translate = [self.basetrans[0] + (e[0] - self.initpos[0]), self.p.translate = [self.basetrans[0] + (e[0] - self.initpos[0]),
...@@ -116,7 +118,7 @@ class window(wx.Frame): ...@@ -116,7 +118,7 @@ class window(wx.Frame):
if z > 0: self.p.zoom(event.GetX(), event.GetY(), 1.2) 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) elif z < 0: self.p.zoom(event.GetX(), event.GetY(), 1/1.2)
class gviz(wx.Panel): class Gviz(wx.Panel):
# Mark canvas as dirty when setting showall # Mark canvas as dirty when setting showall
_showall = 0 _showall = 0
...@@ -168,6 +170,7 @@ class gviz(wx.Panel): ...@@ -168,6 +170,7 @@ class gviz(wx.Panel):
self.bgcolor = wx.Colour() self.bgcolor = wx.Colour()
self.bgcolor.SetFromName(bgcolor) self.bgcolor.SetFromName(bgcolor)
self.blitmap = wx.EmptyBitmap(self.GetClientSize()[0], self.GetClientSize()[1], -1) self.blitmap = wx.EmptyBitmap(self.GetClientSize()[0], self.GetClientSize()[1], -1)
self.paint_overlay = None
def inject(self): def inject(self):
#import pdb; pdb.set_trace() #import pdb; pdb.set_trace()
...@@ -198,14 +201,14 @@ class gviz(wx.Panel): ...@@ -198,14 +201,14 @@ class gviz(wx.Panel):
def layerup(self): def layerup(self):
if self.layerindex + 1 < len(self.layers): if self.layerindex + 1 < len(self.layers):
self.layerindex += 1 self.layerindex += 1
self.parent.SetStatusText("Layer %d - Going Up - Z = %.03f mm" % (self.layerindex + 1, self.layers[self.layerindex]), 0) self.parent.SetStatusText(_("Layer %d - Going Up - Z = %.03f mm") % (self.layerindex + 1, self.layers[self.layerindex]), 0)
self.dirty = 1 self.dirty = 1
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
def layerdown(self): def layerdown(self):
if self.layerindex > 0: if self.layerindex > 0:
self.layerindex -= 1 self.layerindex -= 1
self.parent.SetStatusText("Layer %d - Going Down - Z = %.03f mm" % (self.layerindex + 1, self.layers[self.layerindex]), 0) self.parent.SetStatusText(_("Layer %d - Going Down - Z = %.03f mm") % (self.layerindex + 1, self.layers[self.layerindex]), 0)
self.dirty = 1 self.dirty = 1
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
...@@ -337,6 +340,8 @@ class gviz(wx.Panel): ...@@ -337,6 +340,8 @@ class gviz(wx.Panel):
dc.SetBackground(wx.Brush(self.bgcolor)) dc.SetBackground(wx.Brush(self.bgcolor))
dc.Clear() dc.Clear()
dc.DrawBitmap(self.blitmap, self.translate[0], self.translate[1]) dc.DrawBitmap(self.blitmap, self.translate[0], self.translate[1])
if self.paint_overlay:
self.paint_overlay(dc)
def addfile(self, gcode): def addfile(self, gcode):
self.clear() self.clear()
...@@ -474,6 +479,6 @@ class gviz(wx.Panel): ...@@ -474,6 +479,6 @@ class gviz(wx.Panel):
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
app = wx.App(False) app = wx.App(False)
main = window(open(sys.argv[1])) main = GvizWindow(open(sys.argv[1]))
main.Show() main.Show()
app.MainLoop() app.MainLoop()
...@@ -241,6 +241,7 @@ class GcodeModel(Model): ...@@ -241,6 +241,7 @@ class GcodeModel(Model):
color_tool0 = (1.0, 0.0, 0.0, 0.6) color_tool0 = (1.0, 0.0, 0.0, 0.6)
color_tool1 = (0.0, 0.0, 1.0, 0.6) color_tool1 = (0.0, 0.0, 1.0, 0.6)
color_printed = (0.2, 0.75, 0, 0.6) color_printed = (0.2, 0.75, 0, 0.6)
color_current = (0.6, 0.3, 0, 1)
use_vbos = True use_vbos = True
loaded = False loaded = False
...@@ -256,7 +257,7 @@ class GcodeModel(Model): ...@@ -256,7 +257,7 @@ class GcodeModel(Model):
prev_pos = (0, 0, 0) prev_pos = (0, 0, 0)
for layer_idx, layer in enumerate(model_data.all_layers): for layer_idx, layer in enumerate(model_data.all_layers):
for gline in layer.lines: for gline in layer:
if not gline.is_move: if not gline.is_move:
continue continue
vertex_list.append(prev_pos) vertex_list.append(prev_pos)
...@@ -337,33 +338,56 @@ class GcodeModel(Model): ...@@ -337,33 +338,56 @@ class GcodeModel(Model):
else: else:
glVertexPointer(3, GL_FLOAT, 0, self.vertex_buffer.ptr) glVertexPointer(3, GL_FLOAT, 0, self.vertex_buffer.ptr)
if mode_2d: self.vertex_color_buffer.bind()
glScale(1.0, 1.0, 0.0) # discard z coordinates if has_vbo:
start = self.layer_stops[self.num_layers_to_draw - 1] glColorPointer(4, GL_FLOAT, 0, None)
end = self.layer_stops[self.num_layers_to_draw] - start else:
else: # 3d glColorPointer(4, GL_FLOAT, 0, self.vertex_color_buffer.ptr)
start = 0 start = 0
end = self.layer_stops[self.num_layers_to_draw] if self.num_layers_to_draw <= self.max_layers:
end_prev_layer = self.layer_stops[self.num_layers_to_draw - 1]
else:
end_prev_layer = -1
end = self.layer_stops[min(self.num_layers_to_draw, self.max_layers)]
glDisableClientState(GL_COLOR_ARRAY) glDisableClientState(GL_COLOR_ARRAY)
glColor4f(*self.color_printed) glColor4f(*self.color_printed)
printed_end = min(self.printed_until, end) # Draw printed stuff until end or end_prev_layer
if start < printed_end: cur_end = min(self.printed_until, end)
glDrawArrays(GL_LINES, start, printed_end) if end_prev_layer >= 0:
cur_end = min(cur_end, end_prev_layer)
if cur_end >= 0:
glDrawArrays(GL_LINES, start, cur_end)
glEnableClientState(GL_COLOR_ARRAY) glEnableClientState(GL_COLOR_ARRAY)
self.vertex_color_buffer.bind() # Draw nonprinted stuff until end_prev_layer
if has_vbo: start = max(cur_end, 0)
glColorPointer(4, GL_FLOAT, 0, None) if end_prev_layer >= start:
else: glDrawArrays(GL_LINES, start, end_prev_layer - start)
glColorPointer(4, GL_FLOAT, 0, self.vertex_color_buffer.ptr) cur_end = end_prev_layer
glDisableClientState(GL_COLOR_ARRAY)
glColor4f(*self.color_current)
# Draw current layer
orig_linewidth = (GLfloat)()
glGetFloatv(GL_LINE_WIDTH, orig_linewidth)
glLineWidth(2.0)
if end_prev_layer >= 0 and end > end_prev_layer:
glDrawArrays(GL_LINES, end_prev_layer, end - end_prev_layer)
glLineWidth(orig_linewidth)
glEnableClientState(GL_COLOR_ARRAY)
# Draw non printed stuff until end (if not ending at a given layer)
start = max(self.printed_until, 0) start = max(self.printed_until, 0)
end = end - start end = end - start
if start >= 0 and end > 0: if end_prev_layer < 0 and end > 0:
glDrawArrays(GL_LINES, start, end) glDrawArrays(GL_LINES, start, end)
self.vertex_buffer.unbind() self.vertex_buffer.unbind()
......
...@@ -77,7 +77,7 @@ class RemainingTimeEstimator(object): ...@@ -77,7 +77,7 @@ class RemainingTimeEstimator(object):
if self.previous_layers_estimate > 0 and printtime > 0: if self.previous_layers_estimate > 0 and printtime > 0:
self.drift = printtime / self.previous_layers_estimate self.drift = printtime / self.previous_layers_estimate
self.current_layer_estimate = self.gcode.all_layers[layer].duration self.current_layer_estimate = self.gcode.all_layers[layer].duration
self.current_layer_lines = len(self.gcode.all_layers[layer].lines) self.current_layer_lines = len(self.gcode.all_layers[layer])
self.remaining_layers_estimate -= self.current_layer_estimate self.remaining_layers_estimate -= self.current_layer_estimate
self.last_idx = -1 self.last_idx = -1
self.last_estimate = None self.last_estimate = None
......
...@@ -462,7 +462,7 @@ class pronsole(cmd.Cmd): ...@@ -462,7 +462,7 @@ class pronsole(cmd.Cmd):
pass pass
for g in ['/dev/ttyUSB*', '/dev/ttyACM*', "/dev/tty.*", "/dev/cu.*", "/dev/rfcomm*"]: for g in ['/dev/ttyUSB*', '/dev/ttyACM*', "/dev/tty.*", "/dev/cu.*", "/dev/rfcomm*"]:
baselist+=glob.glob(g) baselist += glob.glob(g)
return filter(self._bluetoothSerialFilter, baselist) return filter(self._bluetoothSerialFilter, baselist)
def _bluetoothSerialFilter(self, serial): def _bluetoothSerialFilter(self, serial):
...@@ -1369,7 +1369,7 @@ class pronsole(cmd.Cmd): ...@@ -1369,7 +1369,7 @@ class pronsole(cmd.Cmd):
self.log(_("Loading sliced file.")) self.log(_("Loading sliced file."))
self.do_load(l[0].replace(".stl", "_export.gcode")) self.do_load(l[0].replace(".stl", "_export.gcode"))
except Exception, e: except Exception, e:
self.logError(_("Skeinforge execution failed: %s") % e) self.logError(_("Slicing failed: %s") % e)
def complete_skein(self, text, line, begidx, endidx): def complete_skein(self, text, line, begidx, endidx):
s = line.split() s = line.split()
......
...@@ -45,6 +45,7 @@ if os.name == "nt": ...@@ -45,6 +45,7 @@ if os.name == "nt":
import printcore import printcore
from printrun.printrun_utils import pixmapfile, configfile from printrun.printrun_utils import pixmapfile, configfile
from printrun.gui import MainWindow from printrun.gui import MainWindow
from printrun.excluder import Excluder
import pronsole import pronsole
from pronsole import dosify, wxSetting, HiddenSetting, StringSetting, SpinSetting, FloatSpinSetting, BooleanSetting, StaticTextSetting from pronsole import dosify, wxSetting, HiddenSetting, StringSetting, SpinSetting, FloatSpinSetting, BooleanSetting, StaticTextSetting
from printrun import gcoder from printrun import gcoder
...@@ -175,6 +176,15 @@ class ComboSetting(wxSetting): ...@@ -175,6 +176,15 @@ class ComboSetting(wxSetting):
return self.widget return self.widget
class PronterWindow(MainWindow, pronsole.pronsole): class PronterWindow(MainWindow, pronsole.pronsole):
_fgcode = None
def _get_fgcode(self):
return self._fgcode
def _set_fgcode(self, value):
self._fgcode = value
self.excluder = None
fgcode = property(_get_fgcode, _set_fgcode)
def __init__(self, filename = None, size = winsize): def __init__(self, filename = None, size = winsize):
pronsole.pronsole.__init__(self) pronsole.pronsole.__init__(self)
#default build dimensions are 200x200x100 with 0, 0, 0 in the corner of the bed and endstops at 0, 0 and 0 #default build dimensions are 200x200x100 with 0, 0, 0 in the corner of the bed and endstops at 0, 0 and 0
...@@ -182,6 +192,7 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -182,6 +192,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
monitorsetting.hidden = True monitorsetting.hidden = True
self.settings._add(monitorsetting) self.settings._add(monitorsetting)
self.settings._add(BuildDimensionsSetting("build_dimensions", "200x200x100+0+0+0+0+0+0", _("Build dimensions"), _("Dimensions of Build Platform\n & optional offset of origin\n & optional switch position\n\nExamples:\n XXXxYYY\n XXX,YYY,ZZZ\n XXXxYYYxZZZ+OffX+OffY+OffZ\nXXXxYYYxZZZ+OffX+OffY+OffZ+HomeX+HomeY+HomeZ"), "Printer")) self.settings._add(BuildDimensionsSetting("build_dimensions", "200x200x100+0+0+0+0+0+0", _("Build dimensions"), _("Dimensions of Build Platform\n & optional offset of origin\n & optional switch position\n\nExamples:\n XXXxYYY\n XXX,YYY,ZZZ\n XXXxYYYxZZZ+OffX+OffY+OffZ\nXXXxYYYxZZZ+OffX+OffY+OffZ+HomeX+HomeY+HomeZ"), "Printer"))
self.settings._add(BooleanSetting("clamp_jogging", False, _("Clamp manual moves"), _("Prevent manual moves from leaving the specified build dimensions"), "Printer"))
self.settings._add(StringSetting("bgcolor", "#FFFFFF", _("Background color"), _("Pronterface background color"), "UI")) self.settings._add(StringSetting("bgcolor", "#FFFFFF", _("Background color"), _("Pronterface background color"), "UI"))
self.settings._add(ComboSetting("uimode", "Standard", ["Standard", "Compact", "Tabbed"], _("Interface mode"), _("Standard interface is a one-page, three columns layout with controls/visualization/log\nCompact mode is a one-page, two columns layout with controls + log/visualization\nTabbed mode is a two-pages mode, where the first page shows controls and the second one shows visualization and log."), "UI")) self.settings._add(ComboSetting("uimode", "Standard", ["Standard", "Compact", "Tabbed"], _("Interface mode"), _("Standard interface is a one-page, three columns layout with controls/visualization/log\nCompact mode is a one-page, two columns layout with controls + log/visualization\nTabbed mode is a two-pages mode, where the first page shows controls and the second one shows visualization and log."), "UI"))
self.settings._add(BooleanSetting("viz3d", False, _("Enable 3D viewer"), _("Use 3D visualization instead of 2D layered visualization"), "UI")) self.settings._add(BooleanSetting("viz3d", False, _("Enable 3D viewer"), _("Use 3D visualization instead of 2D layered visualization"), "UI"))
...@@ -217,6 +228,7 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -217,6 +228,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
self.userm105 = 0 self.userm105 = 0
self.monitor = 0 self.monitor = 0
self.fgcode = None self.fgcode = None
self.excluder = None
self.skeinp = None self.skeinp = None
self.monitor_interval = 3 self.monitor_interval = 3
self.current_pos = [0, 0, 0] self.current_pos = [0, 0, 0]
...@@ -291,6 +303,7 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -291,6 +303,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
self.skeining = 0 self.skeining = 0
self.mini = False self.mini = False
self.p.sendcb = self.sentcb self.p.sendcb = self.sentcb
self.p.preprintsendcb = self.preprintsendcb
self.p.printsendcb = self.printsentcb self.p.printsendcb = self.printsentcb
self.p.layerchangecb = self.layer_change_cb self.p.layerchangecb = self.layer_change_cb
self.p.startcb = self.startcb self.p.startcb = self.startcb
...@@ -367,7 +380,8 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -367,7 +380,8 @@ class PronterWindow(MainWindow, pronsole.pronsole):
def sentcb(self, line): def sentcb(self, line):
gline = gcoder.Line(line) gline = gcoder.Line(line)
gline.parse_coordinates(imperial = False) split_raw = gcoder.split(gline)
gcoder.parse_coordinates(gline, split_raw, imperial = False)
if gline.is_move: if gline.is_move:
if gline.z != None: if gline.z != None:
layer = gline.z layer = gline.z
...@@ -376,21 +390,36 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -376,21 +390,36 @@ class PronterWindow(MainWindow, pronsole.pronsole):
self.gviz.clearhilights() self.gviz.clearhilights()
wx.CallAfter(self.gviz.setlayer, layer) wx.CallAfter(self.gviz.setlayer, layer)
elif gline.command in ["M104", "M109"]: elif gline.command in ["M104", "M109"]:
gline.parse_coordinates(imperial = False, force = True) gcoder.parse_coordinates(gline, split_raw, imperial = False, force = True)
if gline.s != None: gline_s = gcoder.S(gline)
temp = gline.s if gline_s != None:
temp = gline_s
if self.display_gauges: wx.CallAfter(self.hottgauge.SetTarget, temp) if self.display_gauges: wx.CallAfter(self.hottgauge.SetTarget, temp)
if self.display_graph: wx.CallAfter(self.graph.SetExtruder0TargetTemperature, temp) if self.display_graph: wx.CallAfter(self.graph.SetExtruder0TargetTemperature, temp)
elif gline.command == "M140": elif gline.command == "M140":
gline.parse_coordinates(imperial = False, force = True) gline.parse_coordinates(gline, split_raw, imperial = False, force = True)
if gline.s != None: gline_s = gcoder.S(gline)
temp = gline.s if gline_s != None:
temp = gline_s
if self.display_gauges: wx.CallAfter(self.bedtgauge.SetTarget, temp) if self.display_gauges: wx.CallAfter(self.bedtgauge.SetTarget, temp)
if self.display_graph: wx.CallAfter(self.graph.SetBedTargetTemperature, temp) if self.display_graph: wx.CallAfter(self.graph.SetBedTargetTemperature, temp)
else: else:
return return
self.sentlines.put_nowait(line) self.sentlines.put_nowait(line)
def preprintsendcb(self, gline):
if not gline.is_move or not self.excluder or not self.excluder.rectangles:
return gline
if gline.x == None and gline.y == None:
return gline
for (x0, y0, x1, y1) in self.excluder.rectangles:
if x0 <= gline.current_x <= x1 and y0 <= gline.current_y <= y1:
if gline.e != None and not gline.relative_e:
return gcoder.Line("G92 E%.5f" % gline.e)
else:
return None
return gline
def printsentcb(self, gline): def printsentcb(self, gline):
if gline.is_move and hasattr(self.gwindow, "set_current_gline"): if gline.is_move and hasattr(self.gwindow, "set_current_gline"):
wx.CallAfter(self.gwindow.set_current_gline, gline) wx.CallAfter(self.gwindow.set_current_gline, gline)
...@@ -530,24 +559,18 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -530,24 +559,18 @@ class PronterWindow(MainWindow, pronsole.pronsole):
return return
wx.CallAfter(self.addtexttolog,l); wx.CallAfter(self.addtexttolog,l);
def scanserial(self):
"""scan for available ports. return a list of device names."""
baselist = []
if os.name == "nt":
try:
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM")
i = 0
while True:
baselist += [_winreg.EnumValue(key, i)[1]]
i += 1
except:
pass
return baselist+glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') + glob.glob("/dev/tty.*") + glob.glob("/dev/cu.*") + glob.glob("/dev/rfcomm*")
def project(self,event): def project(self,event):
from printrun import projectlayer from printrun import projectlayer
projectlayer.SettingsFrame(self, self.p).Show() projectlayer.SettingsFrame(self, self.p).Show()
def exclude(self, event):
if not self.fgcode:
wx.CallAfter(self.statusbar.SetStatusText, _("No file loaded. Please use load first."))
return
if not self.excluder:
self.excluder = Excluder()
self.excluder.pop_window(self.fgcode, bgcolor = self.settings.bgcolor)
def popmenu(self): def popmenu(self):
self.menustrip = wx.MenuBar() self.menustrip = wx.MenuBar()
# File menu # File menu
...@@ -555,6 +578,7 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -555,6 +578,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
self.Bind(wx.EVT_MENU, self.loadfile, m.Append(-1, _("&Open..."), _(" Opens file"))) self.Bind(wx.EVT_MENU, self.loadfile, m.Append(-1, _("&Open..."), _(" Opens file")))
self.Bind(wx.EVT_MENU, self.do_editgcode, m.Append(-1, _("&Edit..."), _(" Edit open file"))) self.Bind(wx.EVT_MENU, self.do_editgcode, m.Append(-1, _("&Edit..."), _(" Edit open file")))
self.Bind(wx.EVT_MENU, self.clearOutput, m.Append(-1, _("Clear console"), _(" Clear output console"))) self.Bind(wx.EVT_MENU, self.clearOutput, m.Append(-1, _("Clear console"), _(" Clear output console")))
self.Bind(wx.EVT_MENU, self.exclude, m.Append(-1, _("Excluder"), _(" Exclude parts of the bed from being printed")))
self.Bind(wx.EVT_MENU, self.project, m.Append(-1, _("Projector"), _(" Project slices"))) self.Bind(wx.EVT_MENU, self.project, m.Append(-1, _("Projector"), _(" Project slices")))
self.Bind(wx.EVT_MENU, self.OnExit, m.Append(wx.ID_EXIT, _("E&xit"), _(" Closes the Window"))) self.Bind(wx.EVT_MENU, self.OnExit, m.Append(wx.ID_EXIT, _("E&xit"), _(" Closes the Window")))
self.menustrip.Append(m, _("&File")) self.menustrip.Append(m, _("&File"))
...@@ -647,19 +671,16 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -647,19 +671,16 @@ class PronterWindow(MainWindow, pronsole.pronsole):
self.Close() self.Close()
def rescanports(self, event = None): def rescanports(self, event = None):
scan = self.scanserial() scanned = self.scanserial()
portslist = list(scan) portslist = list(scanned)
if self.settings.port != "" and self.settings.port not in portslist: if self.settings.port != "" and self.settings.port not in portslist:
portslist += [self.settings.port] portslist.append(self.settings.port)
self.serialport.Clear() self.serialport.Clear()
self.serialport.AppendItems(portslist) self.serialport.AppendItems(portslist)
try: if os.path.exists(self.settings.port) or self.settings.port in scanned:
if os.path.exists(self.settings.port) or self.settings.port in scan:
self.serialport.SetValue(self.settings.port) self.serialport.SetValue(self.settings.port)
elif len(portslist) > 0: elif portslist:
self.serialport.SetValue(portslist[0]) self.serialport.SetValue(portslist[0])
except:
pass
def cbkey(self, e): def cbkey(self, e):
if e.GetKeyCode() == wx.WXK_UP: if e.GetKeyCode() == wx.WXK_UP:
...@@ -1062,12 +1083,25 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -1062,12 +1083,25 @@ class PronterWindow(MainWindow, pronsole.pronsole):
return return
self.p.send_now('M114') self.p.send_now('M114')
def clamped_move_message(self):
print _("Manual move outside of the build volume prevented (see the \"Clamp manual moves\" option).")
def moveXY(self, x, y): def moveXY(self, x, y):
# When user clicks on the XY control, the Z control no longer gets spacebar/repeat signals # When user clicks on the XY control, the Z control no longer gets spacebar/repeat signals
self.zb.clearRepeat() self.zb.clearRepeat()
if x != 0: if x != 0:
if self.settings.clamp_jogging:
new_x = self.current_pos[0] + x
if new_x < self.build_dimensions_list[3] or new_x > self.build_dimensions_list[0] + self.build_dimensions_list[3]:
self.clamped_move_message()
return
self.onecmd('move X %s' % x) self.onecmd('move X %s' % x)
elif y != 0: elif y != 0:
if self.settings.clamp_jogging:
new_y = self.current_pos[1] + y
if new_y < self.build_dimensions_list[4] or new_y > self.build_dimensions_list[1] + self.build_dimensions_list[4]:
self.clamped_move_message()
return
self.onecmd('move Y %s' % y) self.onecmd('move Y %s' % y)
else: else:
return return
...@@ -1075,6 +1109,11 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -1075,6 +1109,11 @@ class PronterWindow(MainWindow, pronsole.pronsole):
def moveZ(self, z): def moveZ(self, z):
if z != 0: if z != 0:
if self.settings.clamp_jogging:
new_z = self.current_pos[2] + z
if new_z < self.build_dimensions_list[5] or new_z > self.build_dimensions_list[2] + self.build_dimensions_list[5]:
self.clamped_move_message()
return
self.onecmd('move Z %s' % z) self.onecmd('move Z %s' % z)
self.p.send_now('M114') self.p.send_now('M114')
# When user clicks on the Z control, the XY control no longer gets spacebar/repeat signals # When user clicks on the Z control, the XY control no longer gets spacebar/repeat signals
...@@ -1116,6 +1155,8 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -1116,6 +1155,8 @@ class PronterWindow(MainWindow, pronsole.pronsole):
self.save_in_rc("set xy_feedrate", "set xy_feedrate %d" % self.settings.xy_feedrate) self.save_in_rc("set xy_feedrate", "set xy_feedrate %d" % self.settings.xy_feedrate)
self.save_in_rc("set z_feedrate", "set z_feedrate %d" % self.settings.z_feedrate) self.save_in_rc("set z_feedrate", "set z_feedrate %d" % self.settings.z_feedrate)
self.save_in_rc("set e_feedrate", "set e_feedrate %d" % self.settings.e_feedrate) self.save_in_rc("set e_feedrate", "set e_feedrate %d" % self.settings.e_feedrate)
if self.excluder:
self.excluder.close_window()
wx.CallAfter(self.gwindow.Destroy) wx.CallAfter(self.gwindow.Destroy)
wx.CallAfter(self.Destroy) wx.CallAfter(self.Destroy)
...@@ -1193,12 +1234,13 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -1193,12 +1234,13 @@ class PronterWindow(MainWindow, pronsole.pronsole):
y = None y = None
z = None z = None
for bit in bits: for bit in bits:
if x is None and bit.startswith("X"): if not bit[0]: continue
x = float(bit[1:].replace(":","")) if x is None and bit[0] == "X":
elif y is None and bit.startswith("Y"): x = float(bit[1])
y = float(bit[1:].replace(":","")) elif y is None and bit[0] == "Y":
elif z is None and bit.startswith("Z"): y = float(bit[1])
z = float(bit[1:].replace(":","")) elif z is None and bit[0] == "Z":
z = float(bit[1])
if x is not None: self.current_pos[0] = x if x is not None: self.current_pos[0] = x
if y is not None: self.current_pos[1] = y if y is not None: self.current_pos[1] = y
if z is not None: self.current_pos[2] = z if z is not None: self.current_pos[2] = z
...@@ -1568,17 +1610,18 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -1568,17 +1610,18 @@ class PronterWindow(MainWindow, pronsole.pronsole):
def connect(self, event = None): def connect(self, event = None):
print _("Connecting...") print _("Connecting...")
port = None port = None
try: if self.serialport.GetValue():
port = self.scanserial()[0]
except:
pass
if self.serialport.GetValue()!="":
port = str(self.serialport.GetValue()) port = str(self.serialport.GetValue())
else:
scanned = self.scanserial()
if scanned:
port = scanned[0]
baud = 115200 baud = 115200
try: try:
baud = int(self.baud.GetValue()) baud = int(self.baud.GetValue())
except: except:
pass print _("Could not parse baud rate: ")
traceback.print_exc(file = sys.stdout)
if self.paused: if self.paused:
self.p.paused = 0 self.p.paused = 0
self.p.printing = 0 self.p.printing = 0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment