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