OLD | NEW |
| (Empty) |
1 # Copyright 2009, Google Inc. | |
2 # All rights reserved. | |
3 # | |
4 # Redistribution and use in source and binary forms, with or without | |
5 # modification, are permitted provided that the following conditions are | |
6 # met: | |
7 # | |
8 # * Redistributions of source code must retain the above copyright | |
9 # notice, this list of conditions and the following disclaimer. | |
10 # * Redistributions in binary form must reproduce the above | |
11 # copyright notice, this list of conditions and the following disclaimer | |
12 # in the documentation and/or other materials provided with the | |
13 # distribution. | |
14 # * Neither the name of Google Inc. nor the names of its | |
15 # contributors may be used to endorse or promote products derived from | |
16 # this software without specific prior written permission. | |
17 # | |
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | |
30 | |
31 import __builtin__ | |
32 import os.path | |
33 import re | |
34 Import('env') | |
35 | |
36 class Error(Exception): | |
37 pass | |
38 | |
39 samples_output_dir = env.Dir('$OBJ_ROOT/samples').abspath | |
40 samples_artifact_dir = env.Dir('$ARTIFACTS_DIR/samples').abspath | |
41 | |
42 copyright_header = """/* | |
43 * Copyright 2009, Google Inc. | |
44 * All rights reserved. | |
45 * | |
46 * Redistribution and use in source and binary forms, with or without | |
47 * modification, are permitted provided that the following conditions are | |
48 * met: | |
49 * | |
50 * * Redistributions of source code must retain the above copyright | |
51 * notice, this list of conditions and the following disclaimer. | |
52 * * Redistributions in binary form must reproduce the above | |
53 * copyright notice, this list of conditions and the following disclaimer | |
54 * in the documentation and/or other materials provided with the | |
55 * distribution. | |
56 * * Neither the name of Google Inc. nor the names of its | |
57 * contributors may be used to endorse or promote products derived from | |
58 * this software without specific prior written permission. | |
59 * | |
60 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
61 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
62 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
63 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
64 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
65 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
66 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
67 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
68 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
69 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
70 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
71 */ | |
72 """ | |
73 | |
74 def sample_emitter(env, target, source): | |
75 target.append(env.subst('${TARGET.base}.js', target=target, source=source)) | |
76 return (target, source) | |
77 | |
78 def sample_action(target, source, env): | |
79 content = source[0].get_contents() | |
80 regexp = re.compile(r'(.*)<script(\s+type="text/javascript")' + | |
81 r'(\s+charset="utf-8")?\s*>(.*)</script>(.*)', re.DOTALL) | |
82 m = regexp.match(content) | |
83 if not m: | |
84 raise Error('Regexp failed on input file %s' % source.abspath) | |
85 (html_start, type, charset, script, html_end) = m.groups() | |
86 if not type: | |
87 raise Error('Found a script that lacked the javascript tag!'); | |
88 if not charset: | |
89 charset = '' | |
90 | |
91 html_content = ( | |
92 '%(html_start)s<script %(type)s%(charset)s ' | |
93 'src="%(js_path)s"></script>%(html_end)s' % | |
94 { | |
95 'html_start' : html_start, | |
96 'type' : type, | |
97 'charset' : charset, | |
98 'js_path' : target[1].name, | |
99 'html_end' : html_end | |
100 }) | |
101 | |
102 print "Writing sample HTML to %s" % target[0].abspath | |
103 file(target[0].abspath, 'wb').write(html_content) | |
104 print "Writing sample JS to %s" % target[1].abspath | |
105 file(target[1].abspath, 'wb').write(copyright_header + script) | |
106 return None | |
107 | |
108 sample_builder = Builder(action = sample_action, emitter = sample_emitter) | |
109 | |
110 env.Append(BUILDERS = {'SplitSampleHTML' : sample_builder}) | |
111 | |
112 # These are the files we process for the interactive sampler. | |
113 # TODO: We don't currently verify that these samples are included in | |
114 # interactive_samples.js, which constructs the sampler, or that all the files | |
115 # in there are mentioned here. The build script should parse the | |
116 # interactive_samples.js file instead of using this list. | |
117 samples = [ | |
118 '2d.html', | |
119 'animated-scene.html', | |
120 'animation.html', | |
121 'bitmap-draw-image.html', | |
122 'billboards.html', | |
123 'canvas-texturedraw.html', | |
124 'canvas.html', | |
125 'convolution.html', | |
126 'culling.html', | |
127 'customcamera.html', | |
128 'displayfps.html', | |
129 'error-texture.html', | |
130 'generate-texture.html', | |
131 'hellocube-colors.html', | |
132 'hellocube-textures.html', | |
133 'hellocube.html', | |
134 'helloworld.html', | |
135 'hud-2d-overlay.html', | |
136 'instance-override.html', | |
137 'instancing.html', | |
138 'juggler.html', | |
139 'julia.html', | |
140 'multiple-clients.html', | |
141 'multiple-views.html', | |
142 'old-school-shadows.html', | |
143 'particles.html', | |
144 'phongshading.html', | |
145 'picking.html', | |
146 'primitives.html', | |
147 'procedural-texture.html', | |
148 'render-mode.html', | |
149 'render-targets.html', | |
150 'rotatemodel.html', | |
151 'scatter-chart.html', | |
152 'shader-test.html', | |
153 'simple.html', | |
154 'simpletexture.html', | |
155 'skinning.html', | |
156 'sobel.html', | |
157 'stencil_example.html', | |
158 'texturesamplers.html', | |
159 'tutorial-primitive.html', | |
160 'vertex-shader.html', | |
161 'vertex-shader-animation.html', | |
162 'zsorting.html' | |
163 ] | |
164 | |
165 # Split the samples into separate HTML and JS files | |
166 for input_file in samples: | |
167 destdir = os.path.join(samples_artifact_dir, os.path.dirname(input_file)) | |
168 # env.SplitSampleHTML(os.path.join(destdir, 'sampler_' + input_file), | |
169 # input_file) | |
170 | |
171 # We want all the samples unprocessed, as well. | |
172 env.Replicate(destdir, input_file) | |
173 | |
174 env.Alias('samples_export', samples_artifact_dir) | |
175 | |
176 ###################################################################### | |
177 # | |
178 # PLEASE NOTE: If you add samples you MUST add their files to the | |
179 # MANIFEST file in this directory for them to be included in the docs. | |
180 # | |
181 ###################################################################### | |
182 | |
183 # Here we load up the manifest so that we only include the files that | |
184 # are part of the samples, and not any spurious test files or images | |
185 # that might be left around. | |
186 manifest = env.File("MANIFEST").get_contents().strip().split('\n') | |
187 manifest = [x.strip() for x in manifest] | |
188 | |
189 def DeferManifestInstall(env): | |
190 # Only do this if we tried to convert at least some samples (which | |
191 # means that at least some existed when we declared their build steps). | |
192 if len(env.GetPublished('samples', 'asset_files')) > 0: | |
193 for manifest_item in manifest: | |
194 # TODO: Why doesn't replicate hookup things correctly? | |
195 env.Command('$ARTIFACTS_DIR/samples/' + manifest_item, | |
196 '$MAIN_DIR/samples/' + manifest_item, | |
197 [Delete('$TARGET'), | |
198 Copy('$TARGET', '$SOURCE'), | |
199 Chmod('$TARGET', 0777)]) | |
200 | |
201 env.Defer(DeferManifestInstall) | |
202 | |
203 ####### | |
204 # Build JSON sample assets from zipped Collada files. Put them in the assets | |
205 # directory in the source tree (so that we can run the samples from the source | |
206 # tree). If one is needed in the scons-out artifacts directory, that's handled | |
207 # by the MANIFEST file. | |
208 | |
209 if env.Bit('mac'): | |
210 converter_path = env.subst('$ARTIFACTS_DIR/converter/o3dConverter$PROGSUFFIX') | |
211 else: | |
212 converter_path = env.subst('$ARTIFACTS_DIR/o3dConverter$PROGSUFFIX') | |
213 serializer_version_path = env.subst( | |
214 '$SCONSTRUCT_DIR/serializer/cross/version.h') | |
215 | |
216 def model_emitter(env, target, source): | |
217 # Massage the target a little bit. | |
218 sample_file = env.subst('${TARGET.srcdir}/${TARGET.filebase}.o3dtgz', | |
219 target=target, source=source) | |
220 sample_file = sample_file.replace('convert_','') | |
221 target = [env.File(sample_file)] | |
222 source.append(serializer_version_path) | |
223 source.append(converter_path) | |
224 return (target, source) | |
225 | |
226 def model_action(target, source, env): | |
227 import shutil | |
228 import subprocess | |
229 import stat | |
230 | |
231 # Invoke converter to generate target. | |
232 error = subprocess.call([ | |
233 converter_path, | |
234 '--no-condition', | |
235 '--up-axis=%s' % env['UP_AXIS'], | |
236 source[0].abspath, | |
237 target[0].abspath, | |
238 ], env={'LD_LIBRARY_PATH': env.Dir('$ARTIFACTS_DIR').abspath}) | |
239 if error != 0: | |
240 raise Exception('Failed to run o3dConverter on %s to produce %s' % | |
241 (source[0].abspath, target[0].abspath)) | |
242 | |
243 # Copy generated target to remaining targets. This should be faster than | |
244 # running the converter several times. | |
245 for item in target[1:]: | |
246 shutil.copy(target[0].abspath, item.abspath) | |
247 os.chmod(item.abspath, stat.S_IWRITE | stat.S_IREAD) | |
248 | |
249 model_builder = Builder(action = model_action, emitter = model_emitter) | |
250 | |
251 env.Append(BUILDERS = {'ConvertJsonSampleAssets' : model_builder}) | |
252 | |
253 x_up_env = env.Clone(UP_AXIS='1,0,0') | |
254 y_up_env = env.Clone(UP_AXIS='0,1,0') | |
255 z_up_env = env.Clone(UP_AXIS='0,0,1') | |
256 | |
257 models = [ | |
258 {'path': 'beachdemo/convert_assets/beachdemo.zip', 'env': z_up_env}, | |
259 {'path': 'beachdemo/convert_assets/beach-low-poly.dae', 'env': z_up_env}, | |
260 {'path': 'GoogleIO-2009/convert_assets/background.zip', 'env': y_up_env}, | |
261 {'path': 'GoogleIO-2009/convert_assets/character.zip', 'env': y_up_env}, | |
262 | |
263 {'path': 'home-configurators/convert_cbassets/House_Roofless.kmz', | |
264 'env': z_up_env}, | |
265 {'path': 'home-configurators/convert_cbassets/Agra_Rug.kmz', 'env': z_up_env}, | |
266 {'path': 'home-configurators/convert_cbassets/Asimi_Rug.kmz', 'env': z_up_env}
, | |
267 {'path': 'home-configurators/convert_cbassets/Camden_Chair.kmz', | |
268 'env': z_up_env}, | |
269 {'path': 'home-configurators/convert_cbassets/Elements_Bookshelf.kmz', | |
270 'env': z_up_env}, | |
271 {'path': 'home-configurators/convert_cbassets/Ferrara_Rug.kmz', | |
272 'env': z_up_env}, | |
273 {'path': 'home-configurators/convert_cbassets/Lounge_Chair.kmz', | |
274 'env': z_up_env}, | |
275 {'path': 'home-configurators/convert_cbassets/Lounge_Chaise.kmz', | |
276 'env': z_up_env}, | |
277 {'path': 'home-configurators/convert_cbassets/Lounge_Sofa.kmz', | |
278 'env': z_up_env}, | |
279 {'path': 'home-configurators/convert_cbassets/Lounge_Storage_Ottoman.kmz', | |
280 'env': z_up_env}, | |
281 {'path': 'home-configurators/convert_cbassets/Madison_Dining_Table.kmz', | |
282 'env': z_up_env}, | |
283 {'path': 'home-configurators/convert_cbassets/Miles_Side_Chair.kmz', | |
284 'env': z_up_env}, | |
285 {'path': 'home-configurators/convert_cbassets/Pullman_Bar_Stool.kmz', | |
286 'env': z_up_env}, | |
287 {'path': 'home-configurators/convert_cbassets/Puzzle_TV_Stand.kmz', | |
288 'env': z_up_env}, | |
289 {'path': 'home-configurators/convert_cbassets/Stow_Leather_Ottoman.kmz', | |
290 'env': z_up_env}, | |
291 {'path': 'home-configurators/convert_cbassets/Tivoli_Dining_Table.kmz', | |
292 'env': z_up_env}, | |
293 {'path': 'home-configurators/convert_cbassets/Tivoli_Miles_Dining_Set.kmz', | |
294 'env': z_up_env}, | |
295 {'path': 'home-configurators/convert_cbassets/Troy_Chair.kmz', | |
296 'env': z_up_env}, | |
297 {'path': 'home-configurators/convert_cbassets/Troy_Ottoman.kmz', | |
298 'env': z_up_env}, | |
299 {'path': 'home-configurators/convert_cbassets/Troy_Sofa.kmz', | |
300 'env': z_up_env}, | |
301 {'path': 'home-configurators/convert_cbassets/Troy_Storage_Ottoman.kmz', | |
302 'env': z_up_env}, | |
303 {'path': 'home-configurators/convert_cbassets/Troy_Twin_Sleeper.kmz', | |
304 'env': z_up_env}, | |
305 | |
306 | |
307 {'path': 'io/convert_levels/all_actors.kmz', 'env': y_up_env}, | |
308 {'path': 'io/convert_levels/map1.kmz', 'env': y_up_env}, | |
309 | |
310 {'path': 'simpleviewer/convert_assets/cube.zip', 'env': y_up_env}, | |
311 | |
312 {'path': 'convert_assets/dome1.zip', 'env': y_up_env}, | |
313 {'path': 'convert_assets/dome2.zip', 'env': y_up_env}, | |
314 {'path': 'convert_assets/dome3.zip', 'env': y_up_env}, | |
315 {'path': 'convert_assets/dome4.zip', 'env': y_up_env}, | |
316 {'path': 'convert_assets/kitty_151_idle_stand05_cff1.zip', 'env': y_up_env}, | |
317 {'path': 'convert_assets/part1.zip', 'env': y_up_env}, | |
318 {'path': 'convert_assets/part2.zip', 'env': y_up_env}, | |
319 {'path': 'convert_assets/part3.zip', 'env': y_up_env}, | |
320 {'path': 'convert_assets/seven_shapes.zip', 'env': y_up_env}, | |
321 {'path': 'convert_assets/stencil_frame.zip', 'env': y_up_env}, | |
322 {'path': 'convert_assets/teapot.zip', 'env': y_up_env}, | |
323 {'path': 'convert_assets/yard.zip', 'env': y_up_env}, | |
324 | |
325 {'path': 'waterdemo/convert_assets/bamboo.zip', 'env': y_up_env}, | |
326 {'path': 'waterdemo/convert_assets/coconuts.zip', 'env': y_up_env}, | |
327 {'path': 'waterdemo/convert_assets/driftwood.zip', 'env': y_up_env}, | |
328 {'path': 'waterdemo/convert_assets/island.zip', 'env': y_up_env}, | |
329 {'path': 'waterdemo/convert_assets/lazy_bridge.zip', 'env': y_up_env}, | |
330 {'path': 'waterdemo/convert_assets/palm_leaves.zip', 'env': y_up_env}, | |
331 {'path': 'waterdemo/convert_assets/palm_trees.zip', 'env': y_up_env}, | |
332 {'path': 'waterdemo/convert_assets/rocks.9.zip', 'env': y_up_env}, | |
333 {'path': 'waterdemo/convert_assets/rocks.zip', 'env': y_up_env}, | |
334 ] | |
335 | |
336 # Little dance to do this only once so MODE=all works. | |
337 try: | |
338 _ = __builtin__.done_json_assets | |
339 except AttributeError: | |
340 __builtin__.done_json_assets = True | |
341 for model in models: | |
342 # We generate the sample assets into the samples directory directly, | |
343 # and the artifacts directory in the name of sanity -- so we don't | |
344 # have to do a build whenever we change a .js file in order to test | |
345 # the change. We only generate them if the sources exist because we | |
346 # might not map them in all the time. | |
347 if os.path.exists( | |
348 model['env'].File("$SAMPLE_ASSETS/" + model['path']).abspath): | |
349 converted = model['env'].ConvertJsonSampleAssets( | |
350 source = "$SAMPLE_ASSETS/" + model['path'], | |
351 target = model['path']) | |
352 model['env'].Publish('samples', 'asset_files', converted); | |
OLD | NEW |