chiark / gitweb /
Split off some code from preview3d.py, which is becoming way to large.
[cura.git] / Cura / gui / flatSlicerWindow.py
1 from __future__ import absolute_import
2
3 import wx
4 import os
5
6 from wx import glcanvas
7
8 import OpenGL
9 OpenGL.ERROR_CHECKING = False
10 from OpenGL.GLU import *
11 from OpenGL.GL import *
12
13 from Cura.gui.util import toolbarUtil
14 from Cura.gui.util import opengl
15 from Cura.util import util3d
16 from Cura.util import svg
17 from Cura.util import profile
18 from Cura.util import version
19
20 class flatSlicerWindow(wx.Frame):
21         "Cura 2D SVG slicer"
22         def __init__(self):
23                 super(flatSlicerWindow, self).__init__(None, title='Cura - ' + version.getVersion())
24
25                 self.machineSize = util3d.Vector3(profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height'))
26                 self.filename = None
27                 self.svg = None
28
29                 wx.EVT_CLOSE(self, self.OnClose)
30                 self.panel = wx.Panel(self, -1)
31                 self.SetSizer(wx.BoxSizer(wx.VERTICAL))
32                 self.GetSizer().Add(self.panel, 1, flag=wx.EXPAND)
33
34                 self.toolbar = toolbarUtil.Toolbar(self.panel)
35
36                 toolbarUtil.NormalButton(self.toolbar, self.OnOpenSVG, 'open.png', 'Open SVG')
37                 self.toolbar.AddSeparator()
38                 group = []
39                 toolbarUtil.RadioButton(self.toolbar, group, 'object-3d-on.png', 'object-3d-off.png', '3D view', callback=self.On3DClick)
40                 toolbarUtil.RadioButton(self.toolbar, group, 'object-top-on.png', 'object-top-off.png', 'Topdown view', callback=self.OnTopClick).SetValue(True)
41                 self.toolbar.AddSeparator()
42                 toolbarUtil.NormalButton(self.toolbar, self.OnQuit, 'exit.png', 'Close project planner')
43                 
44                 self.toolbar.Realize()
45                 
46                 sizer = wx.GridBagSizer(2,2)
47                 self.panel.SetSizer(sizer)
48                 self.preview = PreviewGLCanvas(self.panel, self)
49
50                 sizer.Add(self.toolbar, (0,0), span=(1,1), flag=wx.EXPAND|wx.LEFT|wx.RIGHT)
51                 sizer.Add(self.preview, (1,0), span=(5,1), flag=wx.EXPAND)
52
53                 sizer.AddGrowableCol(0)
54                 sizer.AddGrowableRow(1)
55
56                 self.SetSize((600,400))
57
58         def OnClose(self, e):
59                 self.Destroy()
60
61         def OnQuit(self, e):
62                 self.Close()
63
64         def On3DClick(self):
65                 self.preview.yaw = 30
66                 self.preview.pitch = 60
67                 self.preview.zoom = 300
68                 self.preview.view3D = True
69                 self.preview.Refresh()
70
71         def OnTopClick(self):
72                 self.preview.view3D = False
73                 self.preview.zoom = self.machineSize.x / 2 + 10
74                 self.preview.offsetX = 0
75                 self.preview.offsetY = 0
76                 self.preview.Refresh()
77
78         def OnOpenSVG(self, e):
79                 dlg=wx.FileDialog(self, "Open SVG file", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
80                 dlg.SetWildcard("SVG files (*.svg)|*.svg;*.SVG")
81                 if dlg.ShowModal() == wx.ID_OK:
82                         self.filename = dlg.GetPath()
83                         self.svg = svg.SVG(self.filename)
84                         self.svg.center(complex(profile.getPreferenceFloat('machine_width')/2, profile.getPreferenceFloat('machine_depth')/2))
85                         self.preview.Refresh()
86                 dlg.Destroy()
87
88 class PreviewGLCanvas(glcanvas.GLCanvas):
89         def __init__(self, parent, realParent):
90                 attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 24, glcanvas.WX_GL_STENCIL_SIZE, 8)
91                 glcanvas.GLCanvas.__init__(self, parent, attribList = attribList)
92                 self.parent = realParent
93                 self.context = glcanvas.GLContext(self)
94                 wx.EVT_PAINT(self, self.OnPaint)
95                 wx.EVT_SIZE(self, self.OnSize)
96                 wx.EVT_ERASE_BACKGROUND(self, self.OnEraseBackground)
97                 wx.EVT_LEFT_DOWN(self, self.OnMouseLeftDown)
98                 wx.EVT_MOTION(self, self.OnMouseMotion)
99                 wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel)
100                 self.yaw = 30
101                 self.pitch = 60
102                 self.zoom = self.parent.machineSize.x / 2 + 10
103                 self.offsetX = 0
104                 self.offsetY = 0
105                 self.view3D = False
106                 self.allowDrag = False
107         
108         def OnMouseLeftDown(self,e):
109                 self.allowDrag = True
110         
111         def OnMouseMotion(self,e):
112                 if self.allowDrag and e.Dragging() and e.LeftIsDown():
113                         if self.view3D:
114                                 self.yaw += e.GetX() - self.oldX
115                                 self.pitch -= e.GetY() - self.oldY
116                                 if self.pitch > 170:
117                                         self.pitch = 170
118                                 if self.pitch < 10:
119                                         self.pitch = 10
120                         else:
121                                 self.offsetX += float(e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2
122                                 self.offsetY -= float(e.GetY() - self.oldY) * self.zoom / self.GetSize().GetHeight() * 2
123                         self.Refresh()
124                 else:
125                         self.allowDrag = False
126                 if e.Dragging() and e.RightIsDown():
127                         if self.view3D:
128                                 self.zoom += e.GetY() - self.oldY
129                                 if self.zoom < 1:
130                                         self.zoom = 1
131                         self.Refresh()
132                 self.oldX = e.GetX()
133                 self.oldY = e.GetY()
134         
135         def OnMouseWheel(self,e):
136                 if self.view3D:
137                         self.zoom *= 1.0 - float(e.GetWheelRotation() / e.GetWheelDelta()) / 10.0
138                         if self.zoom < 1.0:
139                                 self.zoom = 1.0
140                         self.Refresh()
141         
142         def OnEraseBackground(self,event):
143                 #Workaround for windows background redraw flicker.
144                 pass
145         
146         def OnSize(self,event):
147                 self.Refresh()
148
149         def OnPaint(self,event):
150                 dc = wx.PaintDC(self)
151                 self.SetCurrent(self.context)
152                 opengl.InitGL(self, self.view3D, self.zoom)
153                 if self.view3D:
154                         glTranslate(0,0,-self.zoom)
155                         glRotate(-self.pitch, 1,0,0)
156                         glRotate(self.yaw, 0,0,1)
157                         if False: #self.parent.triangleMesh != None:
158                                 glTranslate(0,0,-self.parent.triangleMesh.getMaximum().z / 2)
159                 else:
160                         glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)
161                         glTranslate(self.offsetX, self.offsetY, 0.0)
162                 glTranslate(-self.parent.machineSize.x/2, -self.parent.machineSize.y/2, 0)
163
164                 self.OnDraw()
165                 self.SwapBuffers()
166
167         def OnDraw(self):
168                 machineSize = self.parent.machineSize
169                 opengl.DrawMachine(machineSize)
170                 
171                 if self.parent.svg != None:
172                         for path in self.parent.svg.paths:
173                                 glColor3f(1.0,0.8,0.6)
174                                 glBegin(GL_LINE_STRIP)
175                                 for p in path:
176                                         glVertex3f(p.real, p.imag, 1)
177                                 glEnd()
178                 
179                 glFlush()