Fri, 22 Sep 2017 17:40:08 +0200
SVG bugfix: first shape line not drawn
SVG feature: Dont control the laser via extrusion, switch on at shape start, off at shape end
15 | 1 | # This file is part of the Printrun suite. |
2 | # | |
3 | # Printrun is free software: you can redistribute it and/or modify | |
4 | # it under the terms of the GNU General Public License as published by | |
5 | # the Free Software Foundation, either version 3 of the License, or | |
6 | # (at your option) any later version. | |
7 | # | |
8 | # Printrun is distributed in the hope that it will be useful, | |
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | # GNU General Public License for more details. | |
12 | # | |
13 | # You should have received a copy of the GNU General Public License | |
14 | # along with Printrun. If not, see <http://www.gnu.org/licenses/>. | |
15 | ||
16 | import wx | |
17 | from printrun import gviz | |
18 | ||
19 | from .utils import imagefile, install_locale | |
20 | install_locale('pronterface') | |
21 | ||
22 | class ExcluderWindow(gviz.GvizWindow): | |
23 | ||
24 | def __init__(self, excluder, *args, **kwargs): | |
25 | super(ExcluderWindow, self).__init__(*args, **kwargs) | |
26 | self.SetTitle(_("Part excluder: draw rectangles where print instructions should be ignored")) | |
27 | self.toolbar.AddLabelTool(128, " " + _("Reset selection"), | |
28 | wx.Image(imagefile('reset.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), | |
29 | shortHelp = _("Reset selection"), | |
30 | longHelp = "") | |
31 | self.Bind(wx.EVT_TOOL, self.reset_selection, id = 128) | |
32 | self.parent = excluder | |
33 | self.p.paint_overlay = self.paint_selection | |
34 | self.p.layerup() | |
35 | ||
36 | def real_to_gcode(self, x, y): | |
37 | return (x + self.p.build_dimensions[3], | |
38 | self.p.build_dimensions[4] + self.p.build_dimensions[1] - y) | |
39 | ||
40 | def gcode_to_real(self, x, y): | |
41 | return (x - self.p.build_dimensions[3], | |
42 | self.p.build_dimensions[1] - (y - self.p.build_dimensions[4])) | |
43 | ||
44 | def mouse(self, event): | |
45 | if event.ButtonUp(wx.MOUSE_BTN_LEFT) \ | |
46 | or event.ButtonUp(wx.MOUSE_BTN_RIGHT): | |
47 | self.initpos = None | |
48 | elif event.Dragging() and event.RightIsDown(): | |
49 | e = event.GetPositionTuple() | |
50 | if not self.initpos or not hasattr(self, "basetrans"): | |
51 | self.initpos = e | |
52 | self.basetrans = self.p.translate | |
53 | self.p.translate = [self.basetrans[0] + (e[0] - self.initpos[0]), | |
54 | self.basetrans[1] + (e[1] - self.initpos[1])] | |
55 | self.p.dirty = 1 | |
56 | wx.CallAfter(self.p.Refresh) | |
57 | elif event.Dragging() and event.LeftIsDown(): | |
58 | x, y = event.GetPositionTuple() | |
59 | if not self.initpos: | |
60 | self.basetrans = self.p.translate | |
61 | x = (x - self.basetrans[0]) / self.p.scale[0] | |
62 | y = (y - self.basetrans[1]) / self.p.scale[1] | |
63 | x, y = self.real_to_gcode(x, y) | |
64 | if not self.initpos: | |
65 | self.initpos = (x, y) | |
66 | self.parent.rectangles.append((0, 0, 0, 0)) | |
67 | else: | |
68 | pos = (x, y) | |
69 | x0 = min(self.initpos[0], pos[0]) | |
70 | y0 = min(self.initpos[1], pos[1]) | |
71 | x1 = max(self.initpos[0], pos[0]) | |
72 | y1 = max(self.initpos[1], pos[1]) | |
73 | self.parent.rectangles[-1] = (x0, y0, x1, y1) | |
74 | wx.CallAfter(self.p.Refresh) | |
75 | else: | |
76 | event.Skip() | |
77 | ||
78 | def _line_scaler(self, orig): | |
79 | x0, y0 = self.gcode_to_real(orig[0], orig[1]) | |
80 | x0 = self.p.scale[0] * x0 + self.p.translate[0] | |
81 | y0 = self.p.scale[1] * y0 + self.p.translate[1] | |
82 | x1, y1 = self.gcode_to_real(orig[2], orig[3]) | |
83 | x1 = self.p.scale[0] * x1 + self.p.translate[0] | |
84 | y1 = self.p.scale[1] * y1 + self.p.translate[1] | |
85 | width = max(x0, x1) - min(x0, x1) + 1 | |
86 | height = max(y0, y1) - min(y0, y1) + 1 | |
87 | return (min(x0, x1), min(y0, y1), width, height,) | |
88 | ||
89 | def paint_selection(self, dc): | |
90 | dc = wx.GCDC(dc) | |
91 | dc.SetPen(wx.TRANSPARENT_PEN) | |
92 | dc.DrawRectangleList([self._line_scaler(rect) | |
93 | for rect in self.parent.rectangles], | |
94 | None, wx.Brush((200, 200, 200, 150))) | |
95 | ||
96 | def reset_selection(self, event): | |
97 | self.parent.rectangles = [] | |
98 | wx.CallAfter(self.p.Refresh) | |
99 | ||
100 | class Excluder(object): | |
101 | ||
102 | def __init__(self): | |
103 | self.rectangles = [] | |
104 | self.window = None | |
105 | ||
106 | def pop_window(self, gcode, *args, **kwargs): | |
107 | if not self.window: | |
108 | self.window = ExcluderWindow(self, *args, **kwargs) | |
109 | self.window.p.addfile(gcode, True) | |
110 | self.window.Bind(wx.EVT_CLOSE, self.close_window) | |
111 | self.window.Show() | |
112 | else: | |
113 | self.window.Show() | |
114 | self.window.Raise() | |
115 | ||
116 | def close_window(self, event = None): | |
117 | if self.window: | |
118 | self.window.Destroy() | |
119 | self.window = None | |
120 | ||
121 | if __name__ == '__main__': | |
122 | import sys | |
123 | import gcoder | |
124 | gcode = gcoder.GCode(open(sys.argv[1])) | |
125 | app = wx.App(False) | |
126 | ex = Excluder() | |
127 | ex.pop_window(gcode) | |
128 | app.MainLoop() |