3 import os, os.path, re, math
10 songcache = 'songcache.pickle'
16 f = open(songcache,'w')
21 filetile = pygame.image.load("gfx/filetile.png")
23 class SelectWidget(FX):
33 def __init__(self,text,location=(0,0)):
35 f = pygame.font.Font('font/Nano.ttf',16)
36 self.text = f.render(text,True,self.color)
37 self.surface = pygame.Surface(self.size).convert_alpha()
38 self.surface.fill( (0,0,0,0) )
39 self.surface.blit(filetile,(0,0))
40 self.surface.blit(self.text, (9,7))
41 self.pointlist = [(10,0),(self.size[0]-2,0),(self.size[0]-2,self.size[1]-2),(0,self.size[1]-2),(0,10)]
43 self.location = location
46 if self.state == self.ON:
47 self.state = self.FADING
48 self.fade_t = pygame.time.get_ticks()
54 self.screen.blit(self.surface,self.location)
55 color = self.basecolor
56 if self.state == self.ON:
58 if self.state == self.FADING:
59 dt = pygame.time.get_ticks() - self.fade_t
60 if dt < self.fadetime:
61 alpha = math.exp(-0.003*dt)
62 color = [(1.0-alpha) * self.basecolor[n] + alpha * self.color[n] for n in range(0,3)]
65 pointlist = [(x[0] + self.location[0],x[1] + self.location[1]) for x in self.pointlist]
66 pygame.draw.lines(self.screen,color,True,pointlist,2)
68 # This would look a lot less ugly if only there were something like
69 # perl's cmp and <=> operators.
70 # FUCK YOU PYTHON WHY DOES THIS HAVE TO BE SO COMPLICATED!?!?!?!
72 if a.type == a.DIRECTORY and b.type == b.DIRECTORY:
79 elif a.type == a.DIRECTORY and b.type == b.FILE:
81 elif a.type == a.FILE and b.type == b.DIRECTORY:
84 if a.info['player'] > b.info['player']:
86 elif a.info['player'] < b.info['player']:
89 if not 'playlevel' in a.info:
91 if not 'playlevel' in b.info:
93 if a.info['playlevel'] > b.info['playlevel']:
95 elif a.info['playlevel'] < b.info['playlevel']:
98 if not 'total' in a.info:
100 if not 'total' in b.info:
102 if a.info['total'] > b.info['total']:
104 elif a.info['total'] < b.info['total']:
109 filematch = re.compile('\.(bms|bme|sm)$',re.I)
121 def crawl(self,path):
122 print "Crawling " + path
124 if os.path.isdir(path):
125 self.type = self.DIRECTORY
126 self.name = os.path.basename(path)
127 files = filter(lambda x: os.path.isdir(os.path.join(path,x)) or filematch.search(x), os.listdir(path))
130 if c.crawl(os.path.join(path,f)):
131 self.children.append(c)
132 self.children.sort(WTFsort)
133 elif os.path.isfile(path):
134 self.type = self.FILE
135 self.info = kf_info(path)
136 self.name = self.info['title']
138 print path + " isn't a file or a directory. Ignoring."
143 for c in self.children:
144 if not os.path.exists(c.path):
145 self.children.remove(c)
150 self.children.append(child)
152 def tolist(self,depth=0):
156 for c in self.children:
157 r = c.tolist(depth+1)
164 self.widget = SelectWidget(self.name)
167 def nukewidgets(self):
169 for c in self.children:
175 self.screen = pygame.display.get_surface()
177 f = open(songcache,'r')
178 self.songs = cPickle.load(f)
181 self.songs = mksongcache()
182 except cPickle.UnpicklingError:
183 self.songs = mksongcache()
186 self.songlist = self.songs.tolist()
188 self.position = self.songlist.index(self.songs.current)
189 except AttributeError:
194 self.fslabel = Text('file select','font/Nano.ttf',30,(330,30),(255,0,0))
195 self.fadebottom = pygame.Surface((640,200)).convert_alpha()
196 for n in range(0,200):
197 alpha = int((1.0 - math.exp(-n/30.0)) * 255.0)
198 color = (0,0,0,alpha)
199 pygame.draw.line(self.fadebottom,color,(0,n),(640,n))
202 self.olabels['title'] = Text('title','font/Nano.ttf',12, (20,320),(255,130,130))
203 self.labels['title'] = Text('','font/Nano.ttf',18, (30,330),(230,230,255))
204 self.olabels['artist'] = Text('artist','font/Nano.ttf',12, (20,360),(255,130,130))
205 self.labels['artist'] = Text('','font/Nano.ttf',16, (30,370),(230,230,255))
206 self.olabels['genre'] = Text('genre','font/Nano.ttf',12, (20,390),(255,130,130))
207 self.labels['genre'] = Text('','font/Nano.ttf',16, (30,400),(230,230,255))
208 self.olabels['playlevel'] = Text('difficulty','font/Nano.ttf',12, (20,420),(255,130,130))
209 self.labels['playlevel'] = Text('','font/Nano.ttf',16, (30,430),(230,230,255))
210 self.olabels['bpm'] = Text('BPM','font/Nano.ttf',12, (20,450),(255,130,130))
211 self.labels['bpm'] = Text('','font/Nano.ttf',16, (30,460),(230,230,255))
212 self.calcsongwidgets()
215 self.screen.fill( (30,0,0) )
216 l = len(self.songlist)
217 for nu in range(self.position-4,self.position+8):
219 self.songlist[n].getwidget().draw(t)
221 self.screen.blit(self.fadebottom,(0,280))
222 for k in self.olabels.keys():
223 self.olabels[k].draw(t)
224 for k in self.labels.keys():
225 self.labels[k].draw(t)
228 def calcsongwidgets(self):
229 l = len(self.songlist)
230 for nu in range(self.position-4,self.position+8):
232 w = self.songlist[n].getwidget()
233 w.location = (10 + self.songlist[n].depth * 20, 150 - (self.position - nu)*30)
234 if n == self.position:
236 if self.songlist[n].type == FileNode.DIRECTORY:
237 for tag in ('artist','genre','playlevel','bpm'):
238 self.labels[tag].settext('')
239 self.labels['title'].settext(self.songlist[n].name)
241 for tag in ('title','artist','genre','bpm'):
242 self.labels[tag].settext(self.songlist[n].info[tag])
244 playlevel = int(self.songlist[n].info['playlevel'])
245 self.labels['playlevel'].settext(("*" * playlevel) + "(" + str(playlevel) + ")")
247 self.labels['playlevel'].settext(str(self.songlist[n].info['playlevel']))
254 pygame.mixer.music.load('snd/0x01.ogg')
255 pygame.mixer.music.set_volume(0.75)
256 pygame.mixer.music.play(-1)
257 stab = pygame.mixer.Sound('snd/stab.ogg')
258 stab.set_volume(0.25)
259 start_t = pygame.time.get_ticks()
262 t = pygame.time.get_ticks() - start_t
263 act = event.getaction()
265 if act == event.CANCEL:
267 elif act == event.DOWN:
269 self.calcsongwidgets()
270 elif act == event.UP:
272 self.calcsongwidgets()
273 elif act == event.OK:
274 if self.songlist[self.position].type == FileNode.DIRECTORY:
275 self.songlist[self.position].open = not self.songlist[self.position].open
276 self.songlist = self.songs.tolist()
277 self.calcsongwidgets()
279 decided = self.position
280 act = event.getaction()
282 self.position = self.position % len(self.songlist)
284 pygame.display.flip()
286 pygame.mixer.music.fadeout(1500)
289 self.songs.nukewidgets()
290 self.songs.current = self.songlist[self.position]
291 f = open(songcache,'w')
292 cPickle.dump(self.songs,f)
295 #possave = self.position
296 return ['play',self.songlist[decided].path]