création d'un dispatcher d'événement central.
[minwii.git] / src / gui / InstrumentChoice.py
1 '''
2 Created on 15 juil. 2009
3
4 @author: Samuel Benveniste
5 '''
6
7 import pygame
8 import pygame.midi
9 import sys
10 import time
11 import pickle
12
13 from numpy import array
14 from numpy.linalg import norm
15
16 from math import floor
17
18 from gui.constants import *
19 from PlayingScreen import PlayingScreen
20 from instruments.Instrument import Instrument
21 from cursor.WarpingCursor import *
22 from controllers.Wiimote import Wiimote
23 from logging.EventLog import EventLog
24 from logging.PickleableEvent import PickleableEvent
25
26 class InstrumentChoice:
27 '''
28 The screen for choosing instruments
29
30 instruments:
31 The available instruments
32 wiimotes:
33 The wiimotes used in this session
34 window:
35 The main display window
36 screen:
37 The main display surface
38 clock:
39 The clock used to animate the screen
40 savedScreen:
41 The background that is painted every time
42 playerScreen:
43 The buffer for painting everything before bliting
44 width:
45 The width of the window in pixels
46 height:
47 The height of the window in pixels
48 done:
49 Goes to True when all instruments have been selected
50 cursorPositions:
51 The positions of the cursors on the screen, in pixels
52 imageRects:
53 The rectangles where the images of the instruments are located
54 focus:
55 The numbers of the instruments currently in focus
56 '''
57
58 def __init__(self, instruments, wiimotes, window, screen, clock, joys, portOffset, activeWiimotes, eventLog=None, replay = False, logFilePath = None, scaleFactor = 1):
59 '''
60 Constructor
61
62 instruments:
63 The instruments for this session
64 wiimotes:
65 The wiimotes used in this session
66 '''
67 self.scaleFactor = scaleFactor
68
69 self.instruments = instruments
70 self.wiimotes = wiimotes
71 self.window = window
72 self.screen = screen
73 self.clock = clock
74 self.width = int(floor(screen.get_width()*self.scaleFactor))
75 self.height = int(floor(screen.get_height()*self.scaleFactor))
76 self.blitOrigin = ((self.screen.get_width()-self.width)/2,(self.screen.get_height()-self.height)/2)
77 self.joys = joys
78 self.portOffset = portOffset
79
80 self.activeWiimotes = activeWiimotes
81
82 self.currentWiimote = 0
83 while not self.activeWiimotes[self.currentWiimote] :
84 self.currentWiimote += 1
85 self.done = False
86
87 self.cursorPositions = []
88 self.imageRects = []
89 self.savedImageRects = []
90 self.focus = []
91 self.zoomed = []
92
93 if eventLog == None:
94 self.eventLog = EventLog()
95 self.replay = False
96 else:
97 self.eventLog = eventLog
98 self.replay = replay
99 print self.replay
100
101 #There are 3 instruments per row, up to 9 instruments
102 #Draw their images on the screen
103 self.savedScreen = pygame.Surface(self.screen.get_size())
104 self.savedScreen.fill((255, 255, 255))
105 for i in range(len(self.instruments)) :
106 drawPos = array([(self.width / 3) * (i % 3), (self.height / 3) * (i / 3)])
107 curImage = pygame.image.load(self.instruments[i].image).convert_alpha()
108 scaledImage = pygame.transform.smoothscale(curImage, (self.width / 3, self.height / 3))
109 self.imageRects.append(self.savedScreen.blit(scaledImage, drawPos + self.blitOrigin))
110 self.savedImageRects = self.imageRects[:]
111 #Draw the initial cursor on the buffer
112 self.playerScreen = pygame.Surface(self.savedScreen.get_size())
113 self.playerScreen.blit(self.savedScreen, (0, 0))
114
115 for i in range(len(self.wiimotes)):
116 #Create the list of instrument focus (one focus per wiimote)
117 self.focus.append(0)
118 self.zoomed.append(None)
119 #Set the screen for the cursors (it can't be set before)
120 self.wiimotes[i].cursor.screen = self.playerScreen
121 self.cursorPositions.append(self.wiimotes[i].cursor.centerPosition)
122
123 self.wiimotes[self.currentWiimote].cursor.blit(self.playerScreen)
124
125 #The main loop
126 while self.done == False :
127
128 #Clear the cursors from the screen
129 self.playerScreen.blit(self.savedScreen, (0, 0))
130
131 # Limit frame speed to 50 FPS
132 #
133 timePassed = self.clock.tick(50)
134
135 if self.replay:
136 self.eventLog.update(timePassed)
137 pickledEventsToPost = self.eventLog.getPickledEvents()
138 for pickledEvent in pickledEventsToPost:
139 pygame.event.post(pickledEvent.event)
140
141 events = pygame.event.get()
142
143 if not self.replay:
144 pickledEvents = [PickleableEvent(event.type,event.dict) for event in events if self.eventFilter(event)]
145 if pickledEvents != [] :
146 self.eventLog.appendEventGroup(pickledEvents)
147
148 for event in events:
149 self.input(event)
150
151
152 if self.zoomed[self.currentWiimote] != None :
153 self.imageRects = self.savedImageRects[:]
154 #inflate the chosen rect
155 zoomedRectNumber = self.zoomed[self.currentWiimote]
156 newRect = zoomRect(self.imageRects[zoomedRectNumber], 1.3)
157 self.imageRects[zoomedRectNumber] = newRect
158 curImage = pygame.image.load(self.instruments[zoomedRectNumber].image).convert_alpha()
159 self.scaledImage = pygame.transform.smoothscale(curImage, newRect.size)
160 self.playerScreen.blit(self.scaledImage, newRect.topleft)
161
162 for i in range(len(self.wiimotes)):
163 self.wiimotes[i].cursor.update(timePassed, self.cursorPositions[i])
164
165 self.wiimotes[self.currentWiimote].cursor.blit(self.playerScreen)
166
167 if self.zoomed[self.currentWiimote] != None and self.imageRects[self.zoomed[self.currentWiimote]].collidepoint(self.cursorPositions[self.currentWiimote]):
168 self.focus[self.currentWiimote] = self.zoomed[self.currentWiimote]
169 pygame.draw.rect(self.playerScreen, pygame.Color(0, 255, 0, 255), self.imageRects[self.zoomed[self.currentWiimote]], 10)
170 else:
171 for i in range(len(self.imageRects)) :
172 if self.imageRects[i].collidepoint(self.cursorPositions[self.currentWiimote]):
173 self.focus[self.currentWiimote] = i
174 pygame.draw.rect(self.playerScreen, pygame.Color(0, 255, 0, 255), self.imageRects[i], 10)
175 if self.zoomed[self.currentWiimote] != None:
176 self.playerScreen.blit(self.scaledImage, self.imageRects[self.zoomed[self.currentWiimote]].topleft)
177
178 self.screen.blit(self.playerScreen, (0, 0))
179
180 pygame.display.flip()
181
182 def input(self, event):
183 if event.type == pygame.QUIT:
184 pygame.midi.quit()
185 sys.exit()
186 if event.type == pygame.JOYAXISMOTION:
187 self.updateCursorPositionFromJoy(event)
188 if event.type == pygame.JOYBUTTONDOWN :
189 self.assignInstrumentToWiimote(event)
190 if event.type == pygame.MOUSEBUTTONDOWN:
191 if self.zoomed[self.currentWiimote] == self.focus[self.currentWiimote]:
192 self.assignInstrumentToMouse(event)
193 else:
194 self.zoomed[self.currentWiimote] = self.focus[self.currentWiimote]
195 if event.type == pygame.MOUSEMOTION:
196 self.updateCursorPositionFromMouse(event)
197
198 def updateCursorPositionFromJoy(self, joyEvent):
199 joyName = pygame.joystick.Joystick(joyEvent.joy).get_name()
200 print joyName
201 correctedJoyId = joyNames.index(joyName)
202 if self.activeWiimotes[correctedJoyId]:
203 if correctedJoyId < len(self.cursorPositions):
204 if joyEvent.axis == 0 :
205 self.cursorPositions[correctedJoyId] = (int((joyEvent.value + 1) / 2 * self.screen.get_width()), self.cursorPositions[correctedJoyId][1])
206 if joyEvent.axis == 1 :
207 self.cursorPositions[correctedJoyId] = (self.cursorPositions[correctedJoyId][0], int((joyEvent.value + 1) / 2 * self.screen.get_height()))
208
209 def assignInstrumentToWiimote(self, joyEvent):
210 joyName = pygame.joystick.Joystick(joyEvent.joy).get_name()
211 correctedJoyId = joyNames.index(joyName)
212 if self.activeWiimotes[correctedJoyId]:
213 if self.zoomed[correctedJoyId] == self.focus[correctedJoyId]:
214 self.wiimotes[correctedJoyId].instrument = self.instruments[self.focus[correctedJoyId]]
215 self.zoomed[correctedJoyId] = None
216 self.imageRects = self.savedImageRects[:]
217 if self.currentWiimote<len(self.wiimotes)-1:
218 self.currentWiimote = self.currentWiimote+1
219 else:
220 self.zoomed[correctedJoyId] = self.focus[correctedJoyId]
221 if self.hasFinished():
222 self.done = True
223
224 def updateCursorPositionFromMouse(self, mouseEvent):
225 correctedJoyId = 0
226 while not self.activeWiimotes[correctedJoyId] :
227 correctedJoyId += 1
228 self.cursorPositions[correctedJoyId] = mouseEvent.pos
229
230 def assignInstrumentToMouse(self, mouseEvent):
231 correctedJoyId = 0
232 while not self.activeWiimotes[correctedJoyId] :
233 correctedJoyId += 1
234 self.wiimotes[correctedJoyId].instrument = self.instruments[self.focus[correctedJoyId]]
235 if self.hasFinished():
236 self.done = True
237
238 def hasFinished(self):
239 finished = True
240 for i in range(len(self.wiimotes)):
241 if self.wiimotes[i].instrument == None and self.activeWiimotes[i]:
242 finished = False
243 return(finished)
244
245 def eventFilter(self, event):
246 c = event.type
247 if c == 17:
248 return False
249 elif c == pygame.MOUSEMOTION or pygame.MOUSEBUTTONDOWN or pygame.MOUSEBUTTONUP or pygame.JOYAXISMOTION or pygame.JOYBUTTONDOWN or pygame.JOYBUTTONUP or pygame.KEYDOWN:
250 return True
251 else:
252 return False
253
254 def zoomRect(rect, ratio):
255 zoomedRect = rect.inflate(int(floor((ratio - 1) * rect.width)), int(floor((ratio - 1) * rect.height)))
256 return(zoomedRect)
257
258 if __name__ == "__main__":
259 pygame.init()
260 #pygame.event.set_blocked([pygame.MOUSEBUTTONDOWN,pygame.MOUSEBUTTONUP,pygame.MOUSEMOTION])
261
262 pygame.midi.init()
263 instruments = [Instrument(majorScale, i + 1, "".join(["../instruments/instrumentImages/", instrumentImagePathList[i], ".jpg"]), octaves[i]) for i in range(9)]
264
265 joys = [pygame.joystick.Joystick(id).get_name() for id in range(pygame.joystick.get_count())]
266 joyOffset = joys.index(joyNames[0])
267 pygame.joystick.Joystick(joyOffset).init()
268 print(joyOffset)
269
270 ports = [pygame.midi.get_device_info(id)[1] for id in range(pygame.midi.get_count())]
271 portOffset = ports.index(portNames[0])
272 print(portOffset)
273
274 window = pygame.display.set_mode((1280, 1024),pygame.FULLSCREEN)
275 screen = pygame.display.get_surface()
276 clock = pygame.time.Clock()
277 cursorImages = createImageListFromPath('../cursor/cursorImages/black', 11)
278 durations = [75 for i in range(len(cursorImages))]
279
280 extsc = False
281 casc = False
282
283 jadbt = [3, 4, 5, 3, 4, 4, 5, 6, 6, 5, 3, 3, 4, 5, 3, 4, 4, 5, 6, 7, 3]
284 song = None
285
286 cursors = [WarpingCursor(None, cursorImages, durations, (300 * i, 300 * i)) for i in range(1)]
287 wiimotes = [Wiimote(i, i + portOffset, None, None, cursors[i]) for i in range(1)]
288 choice = InstrumentChoice(instruments, wiimotes, window, screen, clock, joyOffset, portOffset)
289 play = PlayingScreen(choice, song, casc, extsc)
290 for wiimote in wiimotes:
291 del wiimote.port
292
293 f = file('temp.pkl', 'w')
294 pickler = pickle.Pickler(f)
295 pickler.dump(play.eventLog.eventGroups)
296 pickler.dump(play.eventLog.times)
297 f.close()
298
299 f = file('temp.pkl', 'r')
300 unpickler = pickle.Unpickler(f)
301 eventGroups = unpickler.load()
302 times = unpickler.load()
303 f.close()
304 eventLog = EventLog(eventGroups,times)
305
306 cursors = [WarpingCursor(None, cursorImages, durations, (300 * i, 300 * i)) for i in range(1)]
307 wiimotes = [Wiimote(i, i + portOffset, None, None, cursors[i]) for i in range(1)]
308 choice2 = InstrumentChoice(instruments, wiimotes, window, screen, clock, joyOffset, portOffset, eventLog)
309 play = PlayingScreen(choice2, song, casc, extsc)
310
311 for wiimote in wiimotes:
312 del wiimote.port
313
314 pygame.midi.quit()
315 sys.exit()