Initial commit from version 1e-99
[beatscape.git] / loaders / SMloader.py
1 import pygame
2 import os.path
3 import re
4 from bmevent import *
5 from keyfile import *
6
7 # Required information for a loader module. If this isn't here, the game
8 # will crash and burn and it will be ALL YOUR FAULT.
9 name = "StepMania"
10 version = 0.0
11
12 def detect(file):
13         res = [re.compile("^#SUBTITLE"), re.compile("^#BANNER"),
14                re.compile("^#BACKGROUND"),re.compile("^#NOTES")]
15         match = [0,0,0,0]
16
17         f = open(file)
18         for line in f:
19                 for n in range(0,len(res)):
20                         if res[n].match(line):
21                                 match[n] = 1
22         return sum(match) / float(len(match))
23
24 def info(file):
25         return {}
26
27 def load(file,status=lambda x,y:None):
28         keymapping = {0:1, 1:2, 2:3, 3:4, 4:5, 5:0, 7:6, 8:7}
29         kf = KeyFile()
30         kf.numkeys = len(keymapping)
31         dir = os.path.dirname(file)
32         f = open(file,'r')
33         kf.track = -1
34         matcher = re.compile("#([A-Z]+):(.*);",re.DOTALL)
35         kf.stoplist = []
36         buf = ''
37         for line in f:
38                 line = line.split('//')[0];
39                 line = line.strip()
40                 if len(line) == 0:
41                         continue
42                 buf += line
43                 m = matcher.match(buf)
44                 if m:
45                         buf = '';
46                         cmd = m.group(1)
47                         arg = m.group(2).split(':')
48                 else:
49                         continue
50
51                 if cmd == "TITLE":
52                         kf.title = arg[0]
53                 elif cmd == "SUBTITLE":
54                         kf.subtitle = arg[0]
55                 elif cmd == "ARTIST":
56                         kf.artist = arg[0]
57                 elif cmd == "BPMS":
58                         bpmlist = map(lambda x: x.split('='),arg[0].split(','))
59                         kf.bpm = bpmlist[0][1]
60                         for b in bpmlist:
61                                 kf.add(BMEvent(float(b[0]), BME_TEMPO, None, float(b[1])))
62                 elif cmd == "STOPS":
63                         if arg[0]:
64                                 stoplist = map(lambda x: x.split('='),arg[0].split(','))
65                                 for s in stoplist:
66                                         print s[0]
67                                         kf.add(BMEvent(float(s[0]), BME_STOP, None, int(float(s[1])*1000)))
68                 elif cmd == "BACKGROUND":
69                         if arg[0]:
70                                 try:
71                                         kf.stagefile = pygame.image.load(os.path.join(dir,arg[0]))
72                                         kf.stagefile = kf.stagefile.convert()
73                                         status("STAGEFILE",kf.stagefile)
74                                 except pygame.error:
75                                         pass
76                 elif cmd == "OFFSET":
77                         kf.offset = float(arg[0])
78                         kf.add(BMEvent(int(kf.offset * 1000), BME_BGM, None, 255))
79                 elif cmd == "MUSIC":
80                         print os.path.join(dir,arg[0])
81                         try:
82                                 pygame.mixer.music.load(os.path.join(dir,arg[0]))
83                         except pygame.error:
84                                 pygame.mixer.music.load(os.path.join(dir,arg[0].lower()))
85                         kf.wavs[255] = pygame.mixer.music
86                 elif cmd == "NOTES":
87                         if arg[0] == 'dance-single' and arg[2].lower() == 'challenge':
88                                 parse_notes(arg[5],kf)
89                 else:
90                         print "Unknown command:",cmd
91         kf.sort()
92         f.close()
93
94         return kf
95
96 # BUGS! This assumes a four-column chart.
97 def parse_notes(str,kf):
98         tracks = str.split(',')
99         track = 0
100
101         for t in tracks:
102                 l = len(t) / 4
103                 for n in range(0,l):
104                         for m in range(0,4):
105                                 k = t[n*4+m]
106                                 if k == 'M':    # Freaking mines...
107                                         continue
108                                 k = int(k)
109                                 if k > 0:
110                                         beat = 4 * (track + (float(n)/l))
111                                         # Add note filter here?
112                                         kf.add(BMEvent(beat, BME_NOTE1, m*2+1, 1))
113                 track += 1
114