chiark / gitweb /
Add layer slider. Solve the issue where loading a new file takes a long time and...
[cura.git] / Cura / gui / util / openglGui.py
1 from __future__ import absolute_import
2 from __future__ import division
3
4 import wx
5 import math
6
7 from wx import glcanvas
8 import OpenGL
9 OpenGL.ERROR_CHECKING = False
10 from OpenGL.GL import *
11
12 from Cura.gui.util import opengl
13
14 class glGuiControl(object):
15         def __init__(self, parent, pos):
16                 self._parent = parent
17                 self._base = parent._base
18                 self._pos = pos
19                 self._size = (0,0, 1, 1)
20                 self._parent.add(self)
21
22         def setSize(self, x, y, w, h):
23                 self._size = (x, y, w, h)
24
25         def getSize(self):
26                 return self._size
27
28         def getMinSize(self):
29                 return 1, 1
30
31         def updateLayout(self):
32                 pass
33
34         def focusNext(self):
35                 for n in xrange(self._parent._glGuiControlList.index(self) + 1, len(self._parent._glGuiControlList)):
36                         if self._parent._glGuiControlList[n].setFocus():
37                                 return
38                 for n in xrange(0, self._parent._glGuiControlList.index(self)):
39                         if self._parent._glGuiControlList[n].setFocus():
40                                 return
41
42         def focusPrevious(self):
43                 for n in xrange(self._parent._glGuiControlList.index(self) -1, -1, -1):
44                         if self._parent._glGuiControlList[n].setFocus():
45                                 return
46                 for n in xrange(len(self._parent._glGuiControlList) - 1, self._parent._glGuiControlList.index(self), -1):
47                         if self._parent._glGuiControlList[n].setFocus():
48                                 return
49
50         def setFocus(self):
51                 return False
52
53         def hasFocus(self):
54                 return self._base._focus == self
55
56         def OnMouseUp(self, x, y):
57                 pass
58
59         def OnKeyChar(self, key):
60                 pass
61
62 class glGuiContainer(glGuiControl):
63         def __init__(self, parent, pos):
64                 self._glGuiControlList = []
65                 glGuiLayoutButtons(self)
66                 super(glGuiContainer, self).__init__(parent, pos)
67
68         def add(self, ctrl):
69                 self._glGuiControlList.append(ctrl)
70                 self.updateLayout()
71
72         def OnMouseDown(self, x, y):
73                 for ctrl in self._glGuiControlList:
74                         if ctrl.OnMouseDown(x, y):
75                                 return True
76                 return False
77
78         def OnMouseUp(self, x, y):
79                 for ctrl in self._glGuiControlList:
80                         if ctrl.OnMouseUp(x, y):
81                                 return True
82                 return False
83
84         def OnMouseMotion(self, x, y):
85                 handled = False
86                 for ctrl in self._glGuiControlList:
87                         if ctrl.OnMouseMotion(x, y):
88                                 handled = True
89                 return handled
90
91         def draw(self):
92                 for ctrl in self._glGuiControlList:
93                         ctrl.draw()
94
95         def updateLayout(self):
96                 self._layout.update()
97                 for ctrl in self._glGuiControlList:
98                         ctrl.updateLayout()
99
100 class glGuiPanel(glcanvas.GLCanvas):
101         def __init__(self, parent):
102                 attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 24, glcanvas.WX_GL_STENCIL_SIZE, 8)
103                 glcanvas.GLCanvas.__init__(self, parent, style=wx.WANTS_CHARS, attribList = attribList)
104                 self._base = self
105                 self._focus = None
106                 self._container = None
107                 self._container = glGuiContainer(self, (0,0))
108
109                 self._context = glcanvas.GLContext(self)
110                 self._glButtonsTexture = None
111                 self._buttonSize = 64
112
113                 wx.EVT_PAINT(self, self._OnGuiPaint)
114                 wx.EVT_SIZE(self, self._OnSize)
115                 wx.EVT_ERASE_BACKGROUND(self, self._OnEraseBackground)
116                 wx.EVT_LEFT_DOWN(self, self._OnGuiMouseLeftDown)
117                 wx.EVT_LEFT_UP(self, self._OnGuiMouseLeftUp)
118                 wx.EVT_MOTION(self, self._OnGuiMouseMotion)
119                 wx.EVT_CHAR(self, self.OnKeyChar)
120                 wx.EVT_KILL_FOCUS(self, self.OnFocusLost)
121
122         def OnKeyChar(self, e):
123                 if self._focus is not None:
124                         self._focus.OnKeyChar(e.GetKeyCode())
125                         self.Refresh()
126
127         def OnFocusLost(self, e):
128                 self._focus = None
129                 self.Refresh()
130
131         def _OnGuiMouseLeftDown(self,e):
132                 self.SetFocus()
133                 if self._container.OnMouseDown(e.GetX(), e.GetY()):
134                         self.Refresh()
135                         return
136                 self.OnMouseLeftDown(e)
137         def _OnGuiMouseLeftUp(self, e):
138                 if self._container.OnMouseUp(e.GetX(), e.GetY()):
139                         self.Refresh()
140                         return
141                 self.OnMouseLeftUp(e)
142
143         def _OnGuiMouseMotion(self,e):
144                 self.Refresh()
145                 if not self._container.OnMouseMotion(e.GetX(), e.GetY()):
146                         self.OnMouseMotion(e)
147
148         def _OnGuiPaint(self, e):
149                 h = self.GetSize().GetHeight()
150                 w = self.GetSize().GetWidth()
151                 oldButtonSize = self._buttonSize
152                 if h / 3 < w / 4:
153                         w = h * 4 / 3
154                 if w < 64 * 8:
155                         self._buttonSize = 32
156                 elif w < 64 * 10:
157                         self._buttonSize = 48
158                 elif w < 64 * 15:
159                         self._buttonSize = 64
160                 elif w < 64 * 20:
161                         self._buttonSize = 80
162                 else:
163                         self._buttonSize = 96
164                 if self._buttonSize != oldButtonSize:
165                         self._container.updateLayout()
166
167                 dc = wx.PaintDC(self)
168                 self.SetCurrent(self._context)
169                 self.OnPaint(e)
170                 self._drawGui()
171                 glFlush()
172                 self.SwapBuffers()
173
174         def _drawGui(self):
175                 if self._glButtonsTexture is None:
176                         self._glButtonsTexture = opengl.loadGLTexture('glButtons.png')
177
178                 glDisable(GL_DEPTH_TEST)
179                 glEnable(GL_BLEND)
180                 glDisable(GL_LIGHTING)
181                 glColor4ub(255,255,255,255)
182
183                 glMatrixMode(GL_PROJECTION)
184                 glLoadIdentity()
185                 size = self.GetSize()
186                 glOrtho(0, size.GetWidth()-1, size.GetHeight()-1, 0, -1000.0, 1000.0)
187                 glMatrixMode(GL_MODELVIEW)
188                 glLoadIdentity()
189
190                 self._container.draw()
191
192         def _OnEraseBackground(self,event):
193                 #Workaround for windows background redraw flicker.
194                 pass
195
196         def _OnSize(self,e):
197                 self._container.setSize(0, 0, self.GetSize().GetWidth(), self.GetSize().GetHeight())
198                 self._container.updateLayout()
199                 self.Refresh()
200
201         def OnMouseLeftDown(self,e):
202                 pass
203         def OnMouseLeftUp(self,e):
204                 pass
205         def OnMouseMotion(self, e):
206                 pass
207         def OnPaint(self, e):
208                 pass
209
210         def add(self, ctrl):
211                 if self._container is not None:
212                         self._container.add(ctrl)
213
214 class glGuiLayoutButtons(object):
215         def __init__(self, parent):
216                 self._parent = parent
217                 self._parent._layout = self
218
219         def update(self):
220                 bs = self._parent._base._buttonSize
221                 x0, y0, w, h = self._parent.getSize()
222                 gridSize = bs * 1.2
223                 for ctrl in self._parent._glGuiControlList:
224                         pos = ctrl._pos
225                         if pos[0] < 0:
226                                 x = w + pos[0] * gridSize - bs * 0.2
227                         else:
228                                 x = pos[0] * gridSize + bs * 0.2
229                         if pos[1] < 0:
230                                 y = h + pos[1] * gridSize - bs * 0.2
231                         else:
232                                 y = pos[1] * gridSize + bs * 0.2
233                         ctrl.setSize(x, y, gridSize, gridSize)
234
235         def getLayoutSize(self):
236                 _, _, w, h = self._parent.getSize()
237                 return w, h
238
239 class glGuiLayoutGrid(object):
240         def __init__(self, parent):
241                 self._parent = parent
242                 self._parent._layout = self
243                 self._size = 0,0
244
245         def update(self):
246                 borderSize = self._parent._base._buttonSize * 0.2
247                 x0, y0, w, h = self._parent.getSize()
248                 x0 += borderSize
249                 y0 += borderSize
250                 widths = {}
251                 heights = {}
252                 for ctrl in self._parent._glGuiControlList:
253                         x, y = ctrl._pos
254                         w, h = ctrl.getMinSize()
255                         if not x in widths:
256                                 widths[x] = w
257                         else:
258                                 widths[x] = max(widths[x], w)
259                         if not y in heights:
260                                 heights[y] = h
261                         else:
262                                 heights[y] = max(heights[y], h)
263                 for ctrl in self._parent._glGuiControlList:
264                         x, y = ctrl._pos
265                         x1 = x0
266                         y1 = y0
267                         for n in xrange(0, x):
268                                 if not n in widths:
269                                         widths[n] = 3
270                                 x1 += widths[n]
271                         for n in xrange(0, y):
272                                 if not n in heights:
273                                         heights[n] = 3
274                                 y1 += heights[n]
275                         ctrl.setSize(x1, y1, widths[x], heights[y])
276                 self._size = sum(widths.values()) + borderSize * 2, sum(heights.values()) + borderSize * 2
277
278         def getLayoutSize(self):
279                 return self._size
280
281 class glButton(glGuiControl):
282         def __init__(self, parent, imageID, tooltip, pos, callback):
283                 super(glButton, self).__init__(parent, pos)
284                 self._tooltip = tooltip
285                 self._parent = parent
286                 self._imageID = imageID
287                 self._callback = callback
288                 self._selected = False
289                 self._focus = False
290                 self._hidden = False
291                 self._disabled = False
292
293         def setSelected(self, value):
294                 self._selected = value
295
296         def setHidden(self, value):
297                 self._hidden = value
298
299         def setDisabled(self, value):
300                 self._disabled = value
301
302         def getSelected(self):
303                 return self._selected
304
305         def getMinSize(self):
306                 return self._base._buttonSize, self._base._buttonSize
307
308         def _getPixelPos(self):
309                 x0, y0, w, h = self.getSize()
310                 return x0 + w / 2, y0 + h / 2
311
312         def draw(self):
313                 if self._hidden:
314                         return
315
316                 cx = (self._imageID % 4) / 4
317                 cy = int(self._imageID / 4) / 4
318                 bs = self._base._buttonSize
319                 pos = self._getPixelPos()
320
321                 glPushMatrix()
322                 glTranslatef(pos[0], pos[1], 0)
323                 glBindTexture(GL_TEXTURE_2D, self._base._glButtonsTexture)
324                 glEnable(GL_TEXTURE_2D)
325                 scale = 0.8
326                 if self._selected:
327                         scale = 1.0
328                 elif self._focus:
329                         scale = 0.9
330                 glScalef(bs * scale, bs * scale, bs * scale)
331                 if self._disabled:
332                         glColor4ub(128,128,128,128)
333                 else:
334                         glColor4ub(255,255,255,255)
335                 glBegin(GL_QUADS)
336                 glTexCoord2f(cx+0.25, cy)
337                 glVertex2f( 0.5,-0.5)
338                 glTexCoord2f(cx, cy)
339                 glVertex2f(-0.5,-0.5)
340                 glTexCoord2f(cx, cy+0.25)
341                 glVertex2f(-0.5, 0.5)
342                 glTexCoord2f(cx+0.25, cy+0.25)
343                 glVertex2f( 0.5, 0.5)
344                 glEnd()
345                 glDisable(GL_TEXTURE_2D)
346                 if self._focus:
347                         glColor4ub(0,0,0,255)
348                         glTranslatef(0, -0.55, 0)
349                         opengl.glDrawStringCenter(self._tooltip)
350                 glPopMatrix()
351
352         def _checkHit(self, x, y):
353                 if self._hidden or self._disabled:
354                         return False
355                 bs = self.getMinSize()[0]
356                 pos = self._getPixelPos()
357                 return -bs * 0.5 <= x - pos[0] <= bs * 0.5 and -bs * 0.5 <= y - pos[1] <= bs * 0.5
358
359         def OnMouseMotion(self, x, y):
360                 if self._checkHit(x, y):
361                         self._focus = True
362                         return True
363                 self._focus = False
364                 return False
365
366         def OnMouseDown(self, x, y):
367                 if self._checkHit(x, y):
368                         self._callback()
369                         return True
370                 return False
371
372 class glRadioButton(glButton):
373         def __init__(self, parent, imageID, tooltip, pos, group, callback):
374                 super(glRadioButton, self).__init__(parent, imageID, tooltip, pos, self._onRadioSelect)
375                 self._group = group
376                 self._radioCallback = callback
377                 self._group.append(self)
378
379         def setSelected(self, value):
380                 self._selected = value
381
382         def _onRadioSelect(self):
383                 self._base._focus = None
384                 for ctrl in self._group:
385                         if ctrl != self:
386                                 ctrl.setSelected(False)
387                 if self.getSelected():
388                         self.setSelected(False)
389                 else:
390                         self.setSelected(True)
391                 self._radioCallback()
392
393 class glComboButton(glButton):
394         def __init__(self, parent, tooltip, imageIDs, tooltips, pos, callback):
395                 super(glComboButton, self).__init__(parent, imageIDs[0], tooltip, pos, self._onComboOpenSelect)
396                 self._imageIDs = imageIDs
397                 self._tooltips = tooltips
398                 self._comboCallback = callback
399                 self._selection = 0
400
401         def _onComboOpenSelect(self):
402                 self._base._focus = self
403
404         def draw(self):
405                 if self._hidden:
406                         return
407                 self._selected = self.hasFocus()
408                 super(glComboButton, self).draw()
409                 if not self._selected:
410                         return
411
412                 bs = self._base._buttonSize / 2
413                 pos = self._getPixelPos()
414
415                 glPushMatrix()
416                 glTranslatef(pos[0]+bs*0.5, pos[1] + bs*0.5, 0)
417                 glBindTexture(GL_TEXTURE_2D, self._base._glButtonsTexture)
418                 glScalef(bs, bs, bs)
419                 for n in xrange(0, len(self._imageIDs)):
420                         cx = (self._imageIDs[n] % 4) / 4
421                         cy = int(self._imageIDs[n] / 4) / 4
422                         glEnable(GL_TEXTURE_2D)
423                         glTranslatef(0, 1, 0)
424                         if self._disabled:
425                                 glColor4ub(128,128,128,128)
426                         else:
427                                 glColor4ub(255,255,255,255)
428                         glBegin(GL_QUADS)
429                         glTexCoord2f(cx+0.25, cy)
430                         glVertex2f( 0.5,-0.5)
431                         glTexCoord2f(cx, cy)
432                         glVertex2f(-0.5,-0.5)
433                         glTexCoord2f(cx, cy+0.25)
434                         glVertex2f(-0.5, 0.5)
435                         glTexCoord2f(cx+0.25, cy+0.25)
436                         glVertex2f( 0.5, 0.5)
437                         glEnd()
438                         glDisable(GL_TEXTURE_2D)
439
440                         glPushMatrix()
441                         glColor4ub(0,0,0,255)
442                         glTranslatef(-0.55, 0.1, 0)
443                         opengl.glDrawStringRight(self._tooltips[n])
444                         glPopMatrix()
445                 glPopMatrix()
446
447         def getValue(self):
448                 return self._selection
449
450         def setValue(self, value):
451                 self._selection = value
452                 self._comboCallback()
453
454         def OnMouseDown(self, x, y):
455                 if self._hidden or self._disabled:
456                         return False
457                 if self.hasFocus():
458                         bs = self._base._buttonSize / 2
459                         pos = self._getPixelPos()
460                         if 0 <= x - pos[0] <= bs and 0 <= y - pos[1] - bs <= bs * len(self._imageIDs):
461                                 self._selection = int((y - pos[1] - bs) / bs)
462                                 self._imageID = self._imageIDs[self._selection]
463                                 self._base._focus = None
464                                 self._comboCallback()
465                                 return True
466                 return super(glComboButton, self).OnMouseDown(x, y)
467
468 class glFrame(glGuiContainer):
469         def __init__(self, parent, pos):
470                 super(glFrame, self).__init__(parent, pos)
471                 self._selected = False
472                 self._focus = False
473                 self._hidden = False
474
475         def setSelected(self, value):
476                 self._selected = value
477
478         def setHidden(self, value):
479                 self._hidden = value
480
481         def getSelected(self):
482                 return self._selected
483
484         def getMinSize(self):
485                 return self._base._buttonSize, self._base._buttonSize
486
487         def _getPixelPos(self):
488                 x0, y0, w, h = self.getSize()
489                 return x0, y0
490
491         def draw(self):
492                 if self._hidden:
493                         return
494
495                 bs = self._parent._buttonSize
496                 pos = self._getPixelPos()
497
498                 glPushMatrix()
499                 glTranslatef(pos[0], pos[1], 0)
500                 glBindTexture(GL_TEXTURE_2D, self._parent._glButtonsTexture)
501                 glEnable(GL_TEXTURE_2D)
502
503                 size = self._layout.getLayoutSize()
504                 glColor4ub(255,255,255,128)
505                 glBegin(GL_QUADS)
506                 glTexCoord2f(1, 0)
507                 glVertex2f( size[0], 0)
508                 glTexCoord2f(0, 0)
509                 glVertex2f( 0, 0)
510                 glTexCoord2f(0, 1)
511                 glVertex2f( 0, size[1])
512                 glTexCoord2f(1, 1)
513                 glVertex2f( size[0], size[1])
514                 glEnd()
515                 glDisable(GL_TEXTURE_2D)
516                 glPopMatrix()
517                 #Draw the controls on the frame
518                 super(glFrame, self).draw()
519
520         def _checkHit(self, x, y):
521                 if self._hidden:
522                         return False
523                 pos = self._getPixelPos()
524                 w, h = self._layout.getLayoutSize()
525                 return 0 <= x - pos[0] <= w and 0 <= y - pos[1] <= h
526
527         def OnMouseMotion(self, x, y):
528                 super(glFrame, self).OnMouseMotion(x, y)
529                 if self._checkHit(x, y):
530                         self._focus = True
531                         return True
532                 self._focus = False
533                 return False
534
535         def OnMouseDown(self, x, y):
536                 if self._checkHit(x, y):
537                         super(glFrame, self).OnMouseDown(x, y)
538                         return True
539                 return False
540
541 class glLabel(glGuiControl):
542         def __init__(self, parent, label, pos):
543                 self._label = label
544                 super(glLabel, self).__init__(parent, pos)
545
546         def getMinSize(self):
547                 w, h = opengl.glGetStringSize(self._label)
548                 return w + 10, h + 4
549
550         def _getPixelPos(self):
551                 x0, y0, w, h = self.getSize()
552                 return x0, y0
553
554         def draw(self):
555                 x, y, w, h = self.getSize()
556
557                 glPushMatrix()
558                 glTranslatef(x, y, 0)
559
560                 glColor4ub(255,255,255,128)
561                 glBegin(GL_QUADS)
562                 glTexCoord2f(1, 0)
563                 glVertex2f( w, 0)
564                 glTexCoord2f(0, 0)
565                 glVertex2f( 0, 0)
566                 glTexCoord2f(0, 1)
567                 glVertex2f( 0, h)
568                 glTexCoord2f(1, 1)
569                 glVertex2f( w, h)
570                 glEnd()
571
572                 glTranslate(5, h - 5, 0)
573                 glColor4ub(0,0,0,255)
574                 opengl.glDrawStringLeft(self._label)
575                 glPopMatrix()
576
577         def _checkHit(self, x, y):
578                 return False
579
580         def OnMouseMotion(self, x, y):
581                 return False
582
583         def OnMouseDown(self, x, y):
584                 return False
585
586 class glNumberCtrl(glGuiControl):
587         def __init__(self, parent, value, pos, callback):
588                 self._callback = callback
589                 self._value = str(value)
590                 self._selectPos = 0
591                 self._maxLen = 6
592                 self._inCallback = False
593                 super(glNumberCtrl, self).__init__(parent, pos)
594
595         def setValue(self, value):
596                 if self._inCallback:
597                         return
598                 self._value = str(value)
599
600         def getMinSize(self):
601                 w, h = opengl.glGetStringSize("VALUES")
602                 return w + 10, h + 4
603
604         def _getPixelPos(self):
605                 x0, y0, w, h = self.getSize()
606                 return x0, y0
607
608         def draw(self):
609                 x, y, w, h = self.getSize()
610
611                 glPushMatrix()
612                 glTranslatef(x, y, 0)
613
614                 if self.hasFocus():
615                         glColor4ub(255,255,255,255)
616                 else:
617                         glColor4ub(255,255,255,192)
618                 glBegin(GL_QUADS)
619                 glTexCoord2f(1, 0)
620                 glVertex2f( w, 0)
621                 glTexCoord2f(0, 0)
622                 glVertex2f( 0, 0)
623                 glTexCoord2f(0, 1)
624                 glVertex2f( 0, h)
625                 glTexCoord2f(1, 1)
626                 glVertex2f( w, h)
627                 glEnd()
628
629                 glTranslate(5, h - 5, 0)
630                 glColor4ub(0,0,0,255)
631                 opengl.glDrawStringLeft(self._value)
632                 if self.hasFocus():
633                         glTranslate(opengl.glGetStringSize(self._value[0:self._selectPos])[0] - 2, -1, 0)
634                         opengl.glDrawStringLeft('|')
635                 glPopMatrix()
636
637         def _checkHit(self, x, y):
638                 x1, y1, w, h = self.getSize()
639                 return 0 <= x - x1 <= w and 0 <= y - y1 <= h
640
641         def OnMouseMotion(self, x, y):
642                 return False
643
644         def OnMouseDown(self, x, y):
645                 if self._checkHit(x, y):
646                         self.setFocus()
647                         return True
648                 return False
649
650         def OnKeyChar(self, c):
651                 self._inCallback = True
652                 if c == wx.WXK_LEFT:
653                         self._selectPos -= 1
654                         self._selectPos = max(0, self._selectPos)
655                 if c == wx.WXK_RIGHT:
656                         self._selectPos += 1
657                         self._selectPos = min(self._selectPos, len(self._value))
658                 if c == wx.WXK_UP:
659                         try:
660                                 value = float(self._value)
661                         except:
662                                 pass
663                         else:
664                                 value += 0.1
665                                 self._value = str(value)
666                                 self._callback(self._value)
667                 if c == wx.WXK_DOWN:
668                         try:
669                                 value = float(self._value)
670                         except:
671                                 pass
672                         else:
673                                 value -= 0.1
674                                 if value > 0:
675                                         self._value = str(value)
676                                         self._callback(self._value)
677                 if c == wx.WXK_BACK and self._selectPos > 0:
678                         self._value = self._value[0:self._selectPos - 1] + self._value[self._selectPos:]
679                         self._selectPos -= 1
680                         self._callback(self._value)
681                 if c == wx.WXK_DELETE:
682                         self._value = self._value[0:self._selectPos] + self._value[self._selectPos + 1:]
683                         self._callback(self._value)
684                 if c == wx.WXK_TAB:
685                         if wx.GetKeyState(wx.WXK_SHIFT):
686                                 self.focusPrevious()
687                         else:
688                                 self.focusNext()
689                 if (ord('0') <= c <= ord('9') or c == ord('.')) and len(self._value) < self._maxLen:
690                         self._value = self._value[0:self._selectPos] + chr(c) + self._value[self._selectPos:]
691                         self._selectPos += 1
692                         self._callback(self._value)
693                 self._inCallback = False
694
695         def setFocus(self):
696                 self._base._focus = self
697                 self._selectPos = len(self._value)
698                 return True
699
700 class glCheckbox(glGuiControl):
701         def __init__(self, parent, value, pos, callback):
702                 self._callback = callback
703                 self._value = value
704                 self._selectPos = 0
705                 self._maxLen = 6
706                 self._inCallback = False
707                 super(glCheckbox, self).__init__(parent, pos)
708
709         def setValue(self, value):
710                 if self._inCallback:
711                         return
712                 self._value = str(value)
713
714         def getValue(self):
715                 return self._value
716
717         def getMinSize(self):
718                 return 20, 20
719
720         def _getPixelPos(self):
721                 x0, y0, w, h = self.getSize()
722                 return x0, y0
723
724         def draw(self):
725                 x, y, w, h = self.getSize()
726
727                 glPushMatrix()
728                 glTranslatef(x, y, 0)
729
730                 if self._value:
731                         glColor4ub(0,255,0,255)
732                 else:
733                         glColor4ub(255,0,0,255)
734                 glBegin(GL_QUADS)
735                 glTexCoord2f(1, 0)
736                 glVertex2f( w, 0)
737                 glTexCoord2f(0, 0)
738                 glVertex2f( 0, 0)
739                 glTexCoord2f(0, 1)
740                 glVertex2f( 0, h)
741                 glTexCoord2f(1, 1)
742                 glVertex2f( w, h)
743                 glEnd()
744
745                 glPopMatrix()
746
747         def _checkHit(self, x, y):
748                 x1, y1, w, h = self.getSize()
749                 return 0 <= x - x1 <= w and 0 <= y - y1 <= h
750
751         def OnMouseMotion(self, x, y):
752                 return False
753
754         def OnMouseDown(self, x, y):
755                 if self._checkHit(x, y):
756                         self._value = not self._value
757                         return True
758                 return False
759
760 class glSlider(glGuiControl):
761         def __init__(self, parent, value, minValue, maxValue, pos, callback):
762                 super(glSlider, self).__init__(parent, pos)
763                 self._callback = callback
764                 self._focus = False
765                 self._hidden = False
766                 self._value = value
767                 self._minValue = minValue
768                 self._maxValue = maxValue
769
770         def setValue(self, value):
771                 self._value = value
772                 self._value = max(self._minValue, self._value)
773                 self._value = min(self._maxValue, self._value)
774
775         def getValue(self):
776                 return self._value
777
778         def setRange(self, minValue, maxValue):
779                 self._minValue = minValue
780                 self._maxValue = maxValue
781                 self._value = max(minValue, self._value)
782                 self._value = min(maxValue, self._value)
783
784         def getMinValue(self):
785                 return self._minValue
786
787         def getMaxValue(self):
788                 return self._maxValue
789
790         def setHidden(self, value):
791                 self._hidden = value
792
793         def getMinSize(self):
794                 return self._base._buttonSize, self._base._buttonSize
795
796         def _getPixelPos(self):
797                 x0, y0, w, h = self.getSize()
798                 return x0 + w / 2, y0
799
800         def draw(self):
801                 if self._hidden:
802                         return
803
804                 cx = 0
805                 cy = 0
806                 bs = self._base._buttonSize
807                 pos = self._getPixelPos()
808
809                 glPushMatrix()
810                 glTranslatef(pos[0], pos[1], 0)
811                 glDisable(GL_TEXTURE_2D)
812                 if self.hasFocus():
813                         glColor4ub(32,32,32,255)
814                 else:
815                         glColor4ub(32,32,32,192)
816                 glScalef(bs, bs, bs)
817                 glBegin(GL_QUADS)
818                 glVertex2f( 0.1,-1.0)
819                 glVertex2f(-0.1,-1.0)
820                 glVertex2f(-0.1, 1.0)
821                 glVertex2f( 0.1, 1.0)
822                 glEnd()
823                 glTranslate(0.0,0.9,0)
824                 if self._focus:
825                         glColor4ub(0,0,0,255)
826                         glPushMatrix()
827                         glTranslate(-0.1,0,0)
828                         opengl.glDrawStringRight(str(self._minValue))
829                         glTranslate(0,-1.8,0)
830                         opengl.glDrawStringRight(str(self._maxValue))
831                         glTranslate(0.2,1.8-1.8*((self._value-self._minValue)/(self._maxValue-self._minValue)),0)
832                         opengl.glDrawStringLeft(str(self._value))
833                         glPopMatrix()
834                 glColor4ub(255,255,255,240)
835                 glTranslate(0.0,-1.8*((self._value-self._minValue)/(self._maxValue-self._minValue)),0)
836                 glBegin(GL_QUADS)
837                 glVertex2f( 0.1,-0.1)
838                 glVertex2f(-0.1,-0.1)
839                 glVertex2f(-0.1, 0.1)
840                 glVertex2f( 0.1, 0.1)
841                 glEnd()
842                 glPopMatrix()
843
844         def _checkHit(self, x, y):
845                 if self._hidden:
846                         return False
847                 bs = self._base._buttonSize
848                 pos = self._getPixelPos()
849                 return -bs * 0.1 <= x - pos[0] <= bs * 0.1 and -bs * 1.0 <= y - pos[1] <= bs * 1.0
850
851         def setFocus(self):
852                 self._base._focus = self
853                 return True
854
855         def OnMouseMotion(self, x, y):
856                 if self.hasFocus():
857                         bs = self._base._buttonSize
858                         pos = self._getPixelPos()
859                         self.setValue(int(self._minValue + (self._maxValue - self._minValue) * -(y - pos[1] - bs * 0.9) / (bs * 1.8)))
860                         self._callback()
861                         return True
862                 if self._checkHit(x, y):
863                         self._focus = True
864                         return True
865                 self._focus = False
866                 return False
867
868         def OnMouseDown(self, x, y):
869                 if self._checkHit(x, y):
870                         self.setFocus()
871                         self.OnMouseMotion(x, y)
872                         return True
873                 return False
874
875         def OnMouseUp(self, x, y):
876                 if self.hasFocus():
877                         self._base._focus = None
878                         return True
879                 return False