1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import pygame
24 from OpenGL.GL import *
25 import math
26
27 from View import Layer
28 from Input import KeyListener
29 import Data
30 import Theme
31 import Dialogs
32 import Player
33
35 - def __init__(self, text, callback, values = None, valueIndex = 0):
36 self.text = unicode(text)
37 self.callback = callback
38 self.values = values
39 self.valueIndex = valueIndex
40
41 if self.text.endswith(" >"):
42 self.text = text[:-2]
43 self.isSubMenu = True
44 else:
45 self.isSubMenu = isinstance(self.callback, Menu) or isinstance(self.callback, list)
46
48 if engine and isinstance(self.callback, list):
49 nextMenu = Menu(engine, self.callback)
50 elif engine and isinstance(self.callback, Menu):
51 nextMenu = self.callback
52 elif self.values:
53 nextMenu = self.callback(self.values[self.valueIndex])
54 else:
55 nextMenu = self.callback()
56 if isinstance(nextMenu, Menu):
57 engine.view.pushLayer(nextMenu)
58
60 if self.values:
61 self.valueIndex = (self.valueIndex + 1) % len(self.values)
62 self.trigger()
63
65 if self.values:
66 self.valueIndex = (self.valueIndex - 1) % len(self.values)
67 self.trigger()
68
69 - def getText(self, selected):
70 if not self.values:
71 if self.isSubMenu:
72 return "%s >" % self.text
73 return self.text
74 if selected:
75 return "%s: %s%s%s" % (self.text, Data.LEFT, self.values[self.valueIndex], Data.RIGHT)
76 else:
77 return "%s: %s" % (self.text, self.values[self.valueIndex])
78
81 self.engine = engine
82 self.choices = []
83 self.currentIndex = 0
84 self.time = 0
85 self.onClose = onClose
86 self.onCancel = onCancel
87 self.viewOffset = 0
88 self.pos = pos
89 self.viewSize = viewSize
90 self.fadeScreen = fadeScreen
91
92 for c in choices:
93 try:
94 text, callback = c
95 if isinstance(text, tuple):
96 c = Choice(text[0], callback, values = text[2], valueIndex = text[1])
97 else:
98 c = Choice(text, callback)
99 except TypeError:
100 pass
101 self.choices.append(c)
102
104 self.currentIndex = index
105
109
115
117 if self.currentIndex > self.viewOffset + self.viewSize - 1:
118 self.viewOffset = self.currentIndex - self.viewSize + 1
119 if self.currentIndex < self.viewOffset:
120 self.viewOffset = self.currentIndex
121
148
150 self.time += ticks / 50.0
151
153 left = (-up[1], up[0])
154 glBegin(GL_TRIANGLES)
155 glVertex2f( up[0] * s, up[1] * s)
156 glVertex2f((-up[0] + left[0]) * s, (-up[1] + left[1]) * s)
157 glVertex2f((-up[0] - left[0]) * s, (-up[1] - left[1]) * s)
158 glEnd()
159
161 if not visibility:
162 return
163
164 self.engine.view.setOrthogonalProjection(normalize = True)
165 try:
166 v = (1 - visibility) ** 2
167 font = self.engine.data.font
168
169 if self.fadeScreen:
170 Dialogs.fadeScreen(v)
171
172 glEnable(GL_BLEND)
173 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
174 glEnable(GL_COLOR_MATERIAL)
175
176 n = len(self.choices)
177 x, y = self.pos
178 w, h = font.getStringSize("_")
179
180 for i, choice in enumerate(self.choices[self.viewOffset:self.viewOffset + self.viewSize]):
181 text = choice.getText(i + self.viewOffset == self.currentIndex)
182 glPushMatrix()
183 glRotate(v * 45, 0, 0, 1)
184
185
186 if i == 0 and self.viewOffset > 0:
187 Theme.setBaseColor((1 - v) * max(.1, 1 - (1.0 / self.viewOffset) / 3))
188 glPushMatrix()
189 glTranslatef(x - v / 4 - w * 2, y + h / 2, 0)
190 self.renderTriangle(up = (0, -1), s = .015)
191 glPopMatrix()
192 elif i == self.viewSize - 1 and self.viewOffset + self.viewSize < n:
193 Theme.setBaseColor((1 - v) * max(.1, 1 - (1.0 / (n - self.viewOffset - self.viewSize)) / 3))
194 glPushMatrix()
195 glTranslatef(x - v / 4 - w * 2, y + h / 2, 0)
196 self.renderTriangle(up = (0, 1), s = .015)
197 glPopMatrix()
198
199 if i + self.viewOffset == self.currentIndex:
200 a = (math.sin(self.time) * .15 + .75) * (1 - v * 2)
201 Theme.setSelectedColor(a)
202 a *= -.005
203 glTranslatef(a, a, a)
204 else:
205 Theme.setBaseColor(1 - v)
206
207 font.render(text, (x - v / 4, y))
208 v *= 2
209 y += h
210 glPopMatrix()
211 finally:
212 self.engine.view.resetProjection()
213