Wed, 20 Jan 2021 11:37:03 +0100
reimplemented lasercutter changes
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")) | |
46 | 27 | self.toolbar.AddTool(128, " " + _("Reset selection"), |
28 | wx.Image(imagefile('reset.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), | |
29 | _("Reset selection")) | |
15 | 30 | self.Bind(wx.EVT_TOOL, self.reset_selection, id = 128) |
31 | self.parent = excluder | |
32 | self.p.paint_overlay = self.paint_selection | |
33 | self.p.layerup() | |
34 | ||
35 | def real_to_gcode(self, x, y): | |
36 | return (x + self.p.build_dimensions[3], | |
37 | self.p.build_dimensions[4] + self.p.build_dimensions[1] - y) | |
38 | ||
39 | def gcode_to_real(self, x, y): | |
40 | return (x - self.p.build_dimensions[3], | |
41 | self.p.build_dimensions[1] - (y - self.p.build_dimensions[4])) | |
42 | ||
43 | def mouse(self, event): | |
44 | if event.ButtonUp(wx.MOUSE_BTN_LEFT) \ | |
45 | or event.ButtonUp(wx.MOUSE_BTN_RIGHT): | |
46 | self.initpos = None | |
47 | elif event.Dragging() and event.RightIsDown(): | |
46 | 48 | e = event.GetPosition() |
15 | 49 | if not self.initpos or not hasattr(self, "basetrans"): |
50 | self.initpos = e | |
51 | self.basetrans = self.p.translate | |
52 | self.p.translate = [self.basetrans[0] + (e[0] - self.initpos[0]), | |
53 | self.basetrans[1] + (e[1] - self.initpos[1])] | |
54 | self.p.dirty = 1 | |
55 | wx.CallAfter(self.p.Refresh) | |
56 | elif event.Dragging() and event.LeftIsDown(): | |
46 | 57 | x, y = event.GetPosition() |
15 | 58 | if not self.initpos: |
59 | self.basetrans = self.p.translate | |
60 | x = (x - self.basetrans[0]) / self.p.scale[0] | |
61 | y = (y - self.basetrans[1]) / self.p.scale[1] | |
62 | x, y = self.real_to_gcode(x, y) | |
63 | if not self.initpos: | |
64 | self.initpos = (x, y) | |
65 | self.parent.rectangles.append((0, 0, 0, 0)) | |
66 | else: | |
67 | pos = (x, y) | |
68 | x0 = min(self.initpos[0], pos[0]) | |
69 | y0 = min(self.initpos[1], pos[1]) | |
70 | x1 = max(self.initpos[0], pos[0]) | |
71 | y1 = max(self.initpos[1], pos[1]) | |
72 | self.parent.rectangles[-1] = (x0, y0, x1, y1) | |
73 | wx.CallAfter(self.p.Refresh) | |
74 | else: | |
75 | event.Skip() | |
76 | ||
77 | def _line_scaler(self, orig): | |
78 | x0, y0 = self.gcode_to_real(orig[0], orig[1]) | |
79 | x0 = self.p.scale[0] * x0 + self.p.translate[0] | |
80 | y0 = self.p.scale[1] * y0 + self.p.translate[1] | |
81 | x1, y1 = self.gcode_to_real(orig[2], orig[3]) | |
82 | x1 = self.p.scale[0] * x1 + self.p.translate[0] | |
83 | y1 = self.p.scale[1] * y1 + self.p.translate[1] | |
84 | width = max(x0, x1) - min(x0, x1) + 1 | |
85 | height = max(y0, y1) - min(y0, y1) + 1 | |
86 | return (min(x0, x1), min(y0, y1), width, height,) | |
87 | ||
88 | def paint_selection(self, dc): | |
89 | dc = wx.GCDC(dc) | |
90 | dc.SetPen(wx.TRANSPARENT_PEN) | |
91 | dc.DrawRectangleList([self._line_scaler(rect) | |
92 | for rect in self.parent.rectangles], | |
93 | None, wx.Brush((200, 200, 200, 150))) | |
94 | ||
95 | def reset_selection(self, event): | |
96 | self.parent.rectangles = [] | |
97 | wx.CallAfter(self.p.Refresh) | |
98 | ||
46 | 99 | class Excluder: |
15 | 100 | |
101 | def __init__(self): | |
102 | self.rectangles = [] | |
103 | self.window = None | |
104 | ||
105 | def pop_window(self, gcode, *args, **kwargs): | |
106 | if not self.window: | |
107 | self.window = ExcluderWindow(self, *args, **kwargs) | |
108 | self.window.p.addfile(gcode, True) | |
109 | self.window.Bind(wx.EVT_CLOSE, self.close_window) | |
110 | self.window.Show() | |
111 | else: | |
112 | self.window.Show() | |
113 | self.window.Raise() | |
114 | ||
115 | def close_window(self, event = None): | |
116 | if self.window: | |
117 | self.window.Destroy() | |
118 | self.window = None | |
119 | ||
120 | if __name__ == '__main__': | |
121 | import sys | |
46 | 122 | from . import gcoder |
15 | 123 | gcode = gcoder.GCode(open(sys.argv[1])) |
124 | app = wx.App(False) | |
125 | ex = Excluder() | |
126 | ex.pop_window(gcode) | |
127 | app.MainLoop() |