# Copyright 2009, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import __builtin__
import os.path
import re
Import('env')
class Error(Exception):
pass
samples_output_dir = env.Dir('$OBJ_ROOT/samples').abspath
samples_artifact_dir = env.Dir('$ARTIFACTS_DIR/samples').abspath
copyright_header = """/*
* Copyright 2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
"""
def sample_emitter(env, target, source):
target.append(env.subst('${TARGET.base}.js', target=target, source=source))
return (target, source)
def sample_action(target, source, env):
content = source[0].get_contents()
regexp = re.compile(r'(.*)(.*)', re.DOTALL)
m = regexp.match(content)
if not m:
raise Error('Regexp failed on input file %s' % source.abspath)
(html_start, type, charset, script, html_end) = m.groups()
if not type:
raise Error('Found a script that lacked the javascript tag!');
if not charset:
charset = ''
html_content = (
'%(html_start)s%(html_end)s' %
{
'html_start' : html_start,
'type' : type,
'charset' : charset,
'js_path' : target[1].name,
'html_end' : html_end
})
print "Writing sample HTML to %s" % target[0].abspath
file(target[0].abspath, 'wb').write(html_content)
print "Writing sample JS to %s" % target[1].abspath
file(target[1].abspath, 'wb').write(copyright_header + script)
return None
sample_builder = Builder(action = sample_action, emitter = sample_emitter)
env.Append(BUILDERS = {'SplitSampleHTML' : sample_builder})
# These are the files we process for the interactive sampler.
# TODO: We don't currently verify that these samples are included in
# interactive_samples.js, which constructs the sampler, or that all the files
# in there are mentioned here. The build script should parse the
# interactive_samples.js file instead of using this list.
samples = [
'2d.html',
'animated-scene.html',
'animation.html',
'bitmap-draw-image.html',
'billboards.html',
'canvas-texturedraw.html',
'canvas.html',
'convolution.html',
'culling.html',
'customcamera.html',
'displayfps.html',
'error-texture.html',
'generate-texture.html',
'hellocube-colors.html',
'hellocube-textures.html',
'hellocube.html',
'helloworld.html',
'hud-2d-overlay.html',
'instance-override.html',
'instancing.html',
'juggler.html',
'julia.html',
'multiple-clients.html',
'multiple-views.html',
'old-school-shadows.html',
'particles.html',
'phongshading.html',
'picking.html',
'primitives.html',
'procedural-texture.html',
'render-mode.html',
'render-targets.html',
'rotatemodel.html',
'scatter-chart.html',
'shader-test.html',
'simple.html',
'simpletexture.html',
'skinning.html',
'sobel.html',
'stencil_example.html',
'texturesamplers.html',
'tutorial-primitive.html',
'vertex-shader.html',
'vertex-shader-animation.html',
'zsorting.html'
]
# Split the samples into separate HTML and JS files
for input_file in samples:
destdir = os.path.join(samples_artifact_dir, os.path.dirname(input_file))
# env.SplitSampleHTML(os.path.join(destdir, 'sampler_' + input_file),
# input_file)
# We want all the samples unprocessed, as well.
env.Replicate(destdir, input_file)
env.Alias('samples_export', samples_artifact_dir)
######################################################################
#
# PLEASE NOTE: If you add samples you MUST add their files to the
# MANIFEST file in this directory for them to be included in the docs.
#
######################################################################
# Here we load up the manifest so that we only include the files that
# are part of the samples, and not any spurious test files or images
# that might be left around.
manifest = env.File("MANIFEST").get_contents().strip().split('\n')
manifest = [x.strip() for x in manifest]
def DeferManifestInstall(env):
# Only do this if we tried to convert at least some samples (which
# means that at least some existed when we declared their build steps).
if len(env.GetPublished('samples', 'asset_files')) > 0:
for manifest_item in manifest:
# TODO: Why doesn't replicate hookup things correctly?
env.Command('$ARTIFACTS_DIR/samples/' + manifest_item,
'$MAIN_DIR/samples/' + manifest_item,
[Delete('$TARGET'),
Copy('$TARGET', '$SOURCE'),
Chmod('$TARGET', 0777)])
env.Defer(DeferManifestInstall)
#######
# Build JSON sample assets from zipped Collada files. Put them in the assets
# directory in the source tree (so that we can run the samples from the source
# tree). If one is needed in the scons-out artifacts directory, that's handled
# by the MANIFEST file.
if env.Bit('mac'):
converter_path = env.subst('$ARTIFACTS_DIR/converter/o3dConverter$PROGSUFFIX')
else:
converter_path = env.subst('$ARTIFACTS_DIR/o3dConverter$PROGSUFFIX')
serializer_version_path = env.subst(
'$SCONSTRUCT_DIR/serializer/cross/version.h')
def model_emitter(env, target, source):
# Massage the target a little bit.
sample_file = env.subst('${TARGET.srcdir}/${TARGET.filebase}.o3dtgz',
target=target, source=source)
sample_file = sample_file.replace('convert_','')
target = [env.File(sample_file)]
source.append(serializer_version_path)
source.append(converter_path)
return (target, source)
def model_action(target, source, env):
import shutil
import subprocess
import stat
# Invoke converter to generate target.
error = subprocess.call([
converter_path,
'--no-condition',
'--up-axis=%s' % env['UP_AXIS'],
source[0].abspath,
target[0].abspath,
], env={'LD_LIBRARY_PATH': env.Dir('$ARTIFACTS_DIR').abspath})
if error != 0:
raise Exception('Failed to run o3dConverter on %s to produce %s' %
(source[0].abspath, target[0].abspath))
# Copy generated target to remaining targets. This should be faster than
# running the converter several times.
for item in target[1:]:
shutil.copy(target[0].abspath, item.abspath)
os.chmod(item.abspath, stat.S_IWRITE | stat.S_IREAD)
model_builder = Builder(action = model_action, emitter = model_emitter)
env.Append(BUILDERS = {'ConvertJsonSampleAssets' : model_builder})
x_up_env = env.Clone(UP_AXIS='1,0,0')
y_up_env = env.Clone(UP_AXIS='0,1,0')
z_up_env = env.Clone(UP_AXIS='0,0,1')
models = [
{'path': 'beachdemo/convert_assets/beachdemo.zip', 'env': z_up_env},
{'path': 'beachdemo/convert_assets/beach-low-poly.dae', 'env': z_up_env},
{'path': 'GoogleIO-2009/convert_assets/background.zip', 'env': y_up_env},
{'path': 'GoogleIO-2009/convert_assets/character.zip', 'env': y_up_env},
{'path': 'home-configurators/convert_cbassets/House_Roofless.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Agra_Rug.kmz', 'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Asimi_Rug.kmz', 'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Camden_Chair.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Elements_Bookshelf.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Ferrara_Rug.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Lounge_Chair.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Lounge_Chaise.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Lounge_Sofa.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Lounge_Storage_Ottoman.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Madison_Dining_Table.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Miles_Side_Chair.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Pullman_Bar_Stool.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Puzzle_TV_Stand.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Stow_Leather_Ottoman.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Tivoli_Dining_Table.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Tivoli_Miles_Dining_Set.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Troy_Chair.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Troy_Ottoman.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Troy_Sofa.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Troy_Storage_Ottoman.kmz',
'env': z_up_env},
{'path': 'home-configurators/convert_cbassets/Troy_Twin_Sleeper.kmz',
'env': z_up_env},
{'path': 'io/convert_levels/all_actors.kmz', 'env': y_up_env},
{'path': 'io/convert_levels/map1.kmz', 'env': y_up_env},
{'path': 'simpleviewer/convert_assets/cube.zip', 'env': y_up_env},
{'path': 'convert_assets/dome1.zip', 'env': y_up_env},
{'path': 'convert_assets/dome2.zip', 'env': y_up_env},
{'path': 'convert_assets/dome3.zip', 'env': y_up_env},
{'path': 'convert_assets/dome4.zip', 'env': y_up_env},
{'path': 'convert_assets/kitty_151_idle_stand05_cff1.zip', 'env': y_up_env},
{'path': 'convert_assets/part1.zip', 'env': y_up_env},
{'path': 'convert_assets/part2.zip', 'env': y_up_env},
{'path': 'convert_assets/part3.zip', 'env': y_up_env},
{'path': 'convert_assets/seven_shapes.zip', 'env': y_up_env},
{'path': 'convert_assets/stencil_frame.zip', 'env': y_up_env},
{'path': 'convert_assets/teapot.zip', 'env': y_up_env},
{'path': 'convert_assets/yard.zip', 'env': y_up_env},
{'path': 'waterdemo/convert_assets/bamboo.zip', 'env': y_up_env},
{'path': 'waterdemo/convert_assets/coconuts.zip', 'env': y_up_env},
{'path': 'waterdemo/convert_assets/driftwood.zip', 'env': y_up_env},
{'path': 'waterdemo/convert_assets/island.zip', 'env': y_up_env},
{'path': 'waterdemo/convert_assets/lazy_bridge.zip', 'env': y_up_env},
{'path': 'waterdemo/convert_assets/palm_leaves.zip', 'env': y_up_env},
{'path': 'waterdemo/convert_assets/palm_trees.zip', 'env': y_up_env},
{'path': 'waterdemo/convert_assets/rocks.9.zip', 'env': y_up_env},
{'path': 'waterdemo/convert_assets/rocks.zip', 'env': y_up_env},
]
# Little dance to do this only once so MODE=all works.
try:
_ = __builtin__.done_json_assets
except AttributeError:
__builtin__.done_json_assets = True
for model in models:
# We generate the sample assets into the samples directory directly,
# and the artifacts directory in the name of sanity -- so we don't
# have to do a build whenever we change a .js file in order to test
# the change. We only generate them if the sources exist because we
# might not map them in all the time.
if os.path.exists(
model['env'].File("$SAMPLE_ASSETS/" + model['path']).abspath):
converted = model['env'].ConvertJsonSampleAssets(
source = "$SAMPLE_ASSETS/" + model['path'],
target = model['path'])
model['env'].Publish('samples', 'asset_files', converted);