1 |
|
2 |
|
3 | from optparse import OptionParser
|
4 | import json
|
5 | import re
|
6 | import sys
|
7 |
|
8 |
|
9 |
|
10 | ESCAPE_SEQUENCE = {
|
11 | '\\': '\\\\',
|
12 | '\n': '\\n',
|
13 | '\t': '\\t'
|
14 | }
|
15 |
|
16 |
|
17 | def js_escape(s):
|
18 | return ''.join(ESCAPE_SEQUENCE.get(c, c) for c in s)
|
19 |
|
20 |
|
21 | def glsl_compress(s, shortNames):
|
22 |
|
23 | s = re.sub(r'\A\s+', '', s)
|
24 |
|
25 | s = re.sub(r'\s+\Z', '', s)
|
26 |
|
27 | s = re.sub(r'/\*.*?\*/', '', s)
|
28 |
|
29 | s = re.sub(r'//.*?\n', '', s)
|
30 |
|
31 | s = re.sub(r'\s+', ' ', s)
|
32 |
|
33 | s = re.sub(r'(\S)\s+([^\w])', r'\1\2', s)
|
34 | s = re.sub(r'([^\w])\s+(\S)', r'\1\2', s)
|
35 |
|
36 | for originalName, shortName in shortNames.items():
|
37 | s = s.replace(originalName, shortName)
|
38 | return s
|
39 |
|
40 |
|
41 | def main(argv):
|
42 | option_parser = OptionParser()
|
43 | option_parser.add_option('--input')
|
44 | option_parser.add_option('--output')
|
45 | options, args = option_parser.parse_args(argv[1:])
|
46 |
|
47 | context = {}
|
48 | nextShortName = ord('a')
|
49 | shortNames = {}
|
50 |
|
51 | common, vertex, fragment = [], [], []
|
52 | attributes, uniforms, varyings = {}, {}, {}
|
53 | block = None
|
54 | for line in open(options.input, 'rU'):
|
55 | if line.startswith('//!'):
|
56 | m = re.match(r'//!\s+NAMESPACE=(\S+)\s*\Z', line)
|
57 | if m:
|
58 | context['namespace'] = m.group(1)
|
59 | continue
|
60 | m = re.match(r'//!\s+CLASS=(\S+)\s*\Z', line)
|
61 | if m:
|
62 | context['className'] = m.group(1)
|
63 | continue
|
64 | m = re.match(r'//!\s+COMMON\s*\Z', line)
|
65 | if m:
|
66 | block = common
|
67 | continue
|
68 | m = re.match(r'//!\s+VERTEX\s*\Z', line)
|
69 | if m:
|
70 | block = vertex
|
71 | continue
|
72 | m = re.match(r'//!\s+FRAGMENT\s*\Z', line)
|
73 | if m:
|
74 | block = fragment
|
75 | continue
|
76 | else:
|
77 | if block is None:
|
78 | assert line.rstrip() == ''
|
79 | else:
|
80 | block.append(line)
|
81 | m = re.match(r'attribute\s+\S+\s+(\S+);\s*\Z', line)
|
82 | if m:
|
83 | attribute = m.group(1)
|
84 | if attribute not in attributes:
|
85 | shortName = chr(nextShortName)
|
86 | nextShortName += 1
|
87 | attributes[attribute] = {'originalName': attribute, 'shortName': shortName}
|
88 | shortNames[attribute] = shortName
|
89 | m = re.match(r'uniform\s+\S+\s+(\S+);\s*\Z', line)
|
90 | if m:
|
91 | uniform = m.group(1)
|
92 | if uniform not in uniforms:
|
93 | shortName = chr(nextShortName)
|
94 | nextShortName += 1
|
95 | uniforms[uniform] = {'originalName': uniform, 'shortName': shortName}
|
96 | shortNames[uniform] = shortName
|
97 | m = re.match(r'varying\s+\S+\s+(\S+);\s*\Z', line)
|
98 | if m:
|
99 | varying = m.group(1)
|
100 | if varying not in varyings:
|
101 | shortName = chr(nextShortName)
|
102 | nextShortName += 1
|
103 | shortNames[varying] = shortName
|
104 |
|
105 | context['getOriginalFragmentSource'] = js_escape(''.join(common + fragment))
|
106 | context['getOriginalVertexSource'] = js_escape(''.join(common + vertex))
|
107 | context['getFragmentSource'] = glsl_compress(''.join(common + fragment), shortNames)
|
108 | context['getVertexSource'] = glsl_compress(''.join(common + vertex), shortNames)
|
109 | context['getAttributes'] = [attributes[a] for a in sorted(attributes.keys())]
|
110 | context['getUniforms'] = [uniforms[u] for u in sorted(uniforms.keys())]
|
111 |
|
112 | if options.output and options.output != '-':
|
113 | output = open(options.output, 'wb')
|
114 | else:
|
115 | output = sys.stdout
|
116 | json.dump(context, output)
|
117 |
|
118 |
|
119 | if __name__ == '__main__':
|
120 | sys.exit(main(sys.argv))
|