├── .gitignore
├── Gruntfile.js
├── README.md
├── bower.json
├── docs.md
├── example
├── assets
│ └── sometexture.png
├── example-requirejs.html
├── example-requirejs.js
├── example.html
├── example2.html
├── line.html
└── picking.html
├── js
└── require.js
├── jsdoc.conf.json
├── package.json
└── tdl
├── base-rs.js
├── base.js
├── buffers.js
├── clock.js
├── error.jpg
├── fast.js
├── fps.js
├── framebuffers.js
├── fullscreen.js
├── io.js
├── loader.js
├── log.js
├── math.js
├── misc.js
├── models.js
├── particles.js
├── primitives.js
├── programs.js
├── quaternions.js
├── screenshot.js
├── shader.js
├── string.js
├── sync.js
├── textures.js
└── webgl.js
/.gitignore:
--------------------------------------------------------------------------------
1 | docs
2 | *.Makefile
3 | *.mk
4 | *.ncb
5 | *.ninja
6 | *.props
7 | *.pyc
8 | *.rules
9 | *.scons
10 | *.sdf
11 | *.sln
12 | *.suo
13 | *.targets
14 | *.user
15 | *.vcproj
16 | *.vcxproj
17 | *.vcxproj.filters
18 | *.vpj
19 | *.vpw
20 | *.vpwhistu
21 | *.vtg
22 | *.xcodeproj
23 | *~
24 | .*.sw?
25 | .DS_Store
26 | .cproject
27 | .gdb_history
28 | .gdbinit
29 | .metadata
30 | .project
31 | tags
32 | Thumbs.db
33 | v8.log
34 | node_modules
35 |
36 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = function(grunt) {
4 |
5 | grunt.initConfig({
6 | jsdoc: {
7 | tdl: {
8 | src: ['tdl/*.js'],
9 | options: {
10 | destination: 'docs/gen',
11 | configure: 'jsdoc.conf.json',
12 | template: 'node_modules/ink-docstrap/template',
13 | private: false,
14 | },
15 | },
16 | },
17 | clean: [
18 | 'docs/gen',
19 | ],
20 | uglify: {
21 | my_target: {
22 | files: {
23 | 'build/tdl.min.js': [
24 | 'tdl/base.js',
25 | 'tdl/buffers.js',
26 | 'tdl/clock.js',
27 | 'tdl/fast.js',
28 | 'tdl/fps.js',
29 | 'tdl/framebuffers.js',
30 | 'tdl/fullscreen.js',
31 | 'tdl/io.js',
32 | 'tdl/loader.js',
33 | 'tdl/log.js',
34 | 'tdl/math.js',
35 | 'tdl/misc.js',
36 | 'tdl/models.js',
37 | 'tdl/particles.js',
38 | 'tdl/primitives.js',
39 | 'tdl/programs.js',
40 | 'tdl/quaternions.js',
41 | 'tdl/screenshot.js',
42 | 'tdl/shader.js',
43 | 'tdl/string.js',
44 | 'tdl/sync.js',
45 | 'tdl/textures.js',
46 | 'tdl/webgl.js',
47 | ],
48 | },
49 | },
50 | },
51 | });
52 |
53 | grunt.loadNpmTasks('grunt-contrib-clean');
54 | grunt.loadNpmTasks('grunt-jsdoc');
55 | grunt.loadNpmTasks('grunt-contrib-uglify');
56 |
57 | grunt.registerTask('default', ['clean', 'jsdoc', 'uglify']);
58 | };
59 |
60 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | TDL
2 | ===
3 |
4 | Please check out [TWGL](http://twgljs.org). It's arguably the spiritual successor to TDL.
5 |
6 | TDL is a **low-level** library for WebGL apps. It currently focuses on speed of rendering rather than ease of use.
7 |
8 | Some [terse docs can be found at here](docs.md)
9 |
10 | Note: By **low-level** I mean TDL doesn't currently provide any 3D knowledge.
11 | There are almost no built in shaders. There is no scene graph. There are just some objects for wrapping WebGL
12 | shaders and helping to easily associate vertex data with attributes and update uniforms.
13 |
14 | Example: Assuming a shaders like this.
15 |
16 |
30 |
31 |
39 |
40 | In WebGL you'd do this
41 |
42 | // At init time:
43 | var program = UtilToCompileShaders("vshader", "fshader");
44 | var positionLoc = gl.getAttribLocation(program, "position");
45 | var texcoordLoc = gl.getAttribLocation(program, "texcoord");
46 | var worldMatLoc = gl.getUniformLocation(program, "u_worldMatrix");
47 | var projectionMatLoc = gl.getUniformLocation(program, "u_projectionMatrix");
48 | var textureLoc = gl.getUniformLocation(program, "u_texture");
49 |
50 | var positions = gl.createBuffer();
51 | gl.bindBuffer(gl.ARRAY_BUFFER, positions);
52 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positionData), gl.STATIC_DRAW);
53 |
54 | var tecoords = gl.createBuffer();
55 | gl.bindBuffer(gl.ARRAY_BUFFER, texcoords);
56 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoordData), gl.STATIC_DRAW);
57 |
58 | var texture = gl.createTexture();
59 | gl.bindTexture(gl.TEXTURE_2D, texture);
60 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, someImage);
61 |
62 |
63 | // At draw time
64 | gl.bindBuffer(gl.ARRAY_BUFFER, positions);
65 | gl.enableVertexAttribArray(programLoc);
66 | gl.vertexAttribPointer(programLoc, 3, gl.FLOAT, false, 0, 0);
67 |
68 | gl.bindBuffer(gl.ARRAY_BUFFER, positions);
69 | gl.enableVertexAttribArray(texcoordLoc);
70 | gl.vertexAttribPointer(tecoordLoc, 2, gl.FLOAT, false, 0, 0);
71 |
72 | gl.useProgram(program);
73 | gl.uniformMatrix4f(projectionMatLoc, false, projectionMatrix);
74 |
75 | for (var i = 0; i < 3; ++i)
76 | {
77 | gl.uniformMatrix4f(worldMatLoc, false, computeWorldMatrix(i));
78 | gl.drawArrays(gl.TRIANGLES, 0, num);
79 | }
80 |
81 | In TDL that would be shortened to
82 |
83 | // At init time.
84 | var program = tdl.programs.loadProgramFromScriptTags("vshader", "fshader");
85 | var arrays = {
86 | position: new tdl.primitives.AttribBuffer(3, positionData),
87 | texcoord: new tdl.primitives.AttribBuffer(2, texcoordData),
88 | };
89 | var textures = {
90 | u_texture: new tdl.textures.loadTexture(someImage),
91 | }
92 | var model = new tdl.models.Model(program, arrays, textures);
93 |
94 |
95 | // At Draw time
96 | var sharedUniforms = {
97 | u_projectionMatrix: projectionMatrix,
98 | };
99 | var perObjectUniforms = {
100 | u_worldMatrix: worldMatrix,
101 | };
102 |
103 | model.drawPrep(sharedUniforms);
104 |
105 | for (var i = 0; i < 3; ++i)
106 | {
107 | perObjectUnifirms.u_worldMatrix = computeWorldMatrix(i);
108 | model.draw(perObjectuniforms);
109 | }
110 |
111 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tdl",
3 | "version": "0.0.8",
4 | "authors": [
5 | {
6 | "name": "Gregg Tavares",
7 | "email": "github@greggman.com",
8 | "homepage": "http://games.greggman.com"
9 | }
10 | ],
11 | "description": "A JavaScript library for WebGL",
12 | "main": "tdl/base.js",
13 | "moduleType": [
14 | "amd"
15 | ],
16 | "keywords": [
17 | "webgl",
18 | "tdl"
19 | ],
20 | "license": "MIT",
21 | "homepage": "https://github.com/greggman/tdl",
22 | "repository": "git://github.com/greggman/tdl.git",
23 | "ignore": [
24 | "**/.*",
25 | "*.md",
26 | "Gruntfile.js",
27 | "package.json",
28 | "bower.json",
29 | "node_modules",
30 | "docs",
31 | "build",
32 | "example",
33 | "js",
34 | "bower_components",
35 | "test",
36 | "tests"
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/docs.md:
--------------------------------------------------------------------------------
1 | TDL Docs
2 | ========
3 | I hope the code is pretty straight forward. There's some simple examples here
4 |
5 | http://greggman.github.com/tdl/example/example.html
6 |
7 | http://greggman.github.com/tdl/example/example2.html
8 |
9 | http://greggman.github.com/tdl/example/picking.html
10 |
11 | More complex samples can be found at http://webglsamples.googlecode.com
12 |
13 | Briefly...
14 |
15 | Your startup code should look like this
16 |
17 | canvas = document.getElementById("canvas");
18 | gl = tdl.webgl.setupWebGL(canvas);
19 | if (!gl) {
20 | return; // Do nothing
21 | }
22 |
23 | Where "canvas" is the id of the canvas you want to draw into.
24 | tdl.webgl.setupWebGL will replace the contents of the containing div
25 | with a link to getting a WebGL capable browser if the user's browser
26 | does not support WebGL.
27 |
28 | Otherwise...
29 |
30 | Loading Shaders
31 | ---------------
32 |
33 | var program = tdl.programs.loadProgram(vertexShaderSource, fragmentShaderSource);
34 |
35 | Compiles your shaders and creates a Program object.
36 |
37 | Loading Textures
38 | ----------------
39 |
40 | var textures = {
41 | name1: tdl.textures.loadTexture(url),
42 | name2: tdl.textures.loadTexture(url)
43 | };
44 |
45 | Loads your textures. The property names must match whatever you called the samplers
46 | in your shaders. loadTexture can take `[url]` for an image, `[r,g,b,a]` for solid
47 | texture. `[url,url,url,url,url,url]` for a cubemap and also `[url]` for a cubemap
48 | where all 6 faces are in a cross. It can also take an img or canvas tag.
49 |
50 | Create Vertices or a Mesh
51 | -------------------------
52 |
53 | var arrays = tdl.primitives.createSphere(1, 10, 10);
54 |
55 | Creates vertices
56 |
57 | The tdl.primitives functions return an object like this
58 |
59 | {
60 | position: AttribBuffer,
61 | normal: AttribBuffer,
62 | texCoord: AttribBuffer
63 | };
64 |
65 | The property names must match the attributes in your vertex shader if you want to
66 | add more.
67 |
68 | A call to tdl.primitives.addTangentsAndBinormals adds the fields "tangent" and
69 | "binormal"
70 |
71 | Create a Model
72 | --------------
73 |
74 | Once you have a program, a texture object and an arrays object you make a new
75 | model with
76 |
77 | var model = new tdl.models.Model(program, array, textures);
78 |
79 |
80 | Rendering
81 | ---------
82 |
83 | To draw the model there are 2 functions, `model.drawPrep(uniformMap)` and
84 | `model.draw(uniformMap)`.
85 |
86 | Both of them take an object with uniformName/value pairs.
87 |
88 | model.drawPrep binds the program, binds all the textures and attributes and
89 | sets whatever uniforms you pass in.
90 |
91 | model.draw sets any more uniforms you pass in and then calls gl.drawElements.
92 | The idea is you call `model.drawPrep` once and then `model.draw` to draw a
93 | bunch of the same model, changing as few uniforms as possible. This is the
94 | fastest way to use WebGL.
95 |
96 | Your rendering loop should look something like this
97 |
98 | function render() {
99 | var time = tdl.webgl.animationTime();
100 | model.drawPrep({...});
101 | model.draw({...});
102 | tdl.webgl.requestAnimationFrame(render, canvas);
103 | }
104 | render(); // call the first render manually to start it off.
105 |
106 |
107 | Math
108 | ----
109 |
110 | The math is a little funky. There are 2 math libraries, math.js and fast.js.
111 | math.js comes from O3D and uses `JavaScript` arrays. A Matrix in that
112 | library is a an array of numbers. fast.js uses `Float32Array` for its storage
113 | and most functions take a destination object as the first argument.
114 | Theoretically this is faster because you can avoid a certain number of
115 | allocations. It also means the numbers in the array do not have to be queried
116 | and converted from `JavaScript` Number to floats before calling glUniform.
117 |
--------------------------------------------------------------------------------
/example/assets/sometexture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/greggman/tdl/6b633052599e8ee95245b6bfa17c645a935e16ae/example/assets/sometexture.png
--------------------------------------------------------------------------------
/example/example-requirejs.html:
--------------------------------------------------------------------------------
1 |
31 |
32 |
33 |
34 |
35 | WebGL TDL Example
36 |
78 |
79 |
80 |
81 |
82 |
85 |
86 |
87 |
88 |
89 |
113 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/example/example-requirejs.js:
--------------------------------------------------------------------------------
1 | var main = function(
2 | TDLBuffers,
3 | TDLFast,
4 | TDLFps,
5 | TDLLog,
6 | TDLMath,
7 | TDLModels,
8 | TDLPrimitives,
9 | TDLPrograms,
10 | TDLTextures,
11 | TDLWebGL) {
12 | // globals
13 | var gl; // the gl context.
14 | var canvas; // the canvas
15 | var math; // the math lib.
16 | var fast; // the fast math lib.
17 | var g_fpsTimer; // object to measure frames per second;
18 | var g_logGLCalls = true; // whether or not to log webgl calls
19 | var g_debug = false; // whether or not to debug.
20 | var g_drawOnce = false; // draw just one frame.
21 |
22 | //g_drawOnce = true;
23 | //g_debug = true;
24 |
25 | var g_eyeSpeed = 0.5;
26 | var g_eyeHeight = 2;
27 | var g_eyeRadius = 9;
28 |
29 | function ValidateNoneOfTheArgsAreUndefined(functionName, args) {
30 | for (var ii = 0; ii < args.length; ++ii) {
31 | if (args[ii] === undefined) {
32 | TDLLog.error("undefined passed to gl." + functionName + "(" +
33 | TDLWebGL.glFunctionArgsToString(functionName, args) + ")");
34 | }
35 | }
36 | }
37 |
38 | function Log(msg) {
39 | if (g_logGLCalls) {
40 | TDLLog.log(msg);
41 | }
42 | }
43 |
44 | function LogGLCall(functionName, args) {
45 | if (g_logGLCalls) {
46 | ValidateNoneOfTheArgsAreUndefined(functionName, args)
47 | TDLLog.log("gl." + functionName + "(" +
48 | TDLWebGL.glFunctionArgsToString(functionName, args) + ")");
49 | }
50 | }
51 |
52 | function createProgramFromTags(vertexTagId, fragmentTagId) {
53 | return TDLPrograms.loadProgram(
54 | document.getElementById(vertexTagId).text,
55 | document.getElementById(fragmentTagId).text);
56 | }
57 |
58 | /**
59 | * Sets up Planet.
60 | */
61 | function setupSphere() {
62 | var textures = {
63 | diffuseSampler: TDLTextures.loadTexture('assets/sometexture.png')};
64 | var program = createProgramFromTags(
65 | 'sphereVertexShader',
66 | 'sphereFragmentShader');
67 | var arrays = TDLPrimitives.createSphere(0.4, 10, 12);
68 |
69 | return new TDLModels.Model(program, arrays, textures);
70 | }
71 |
72 | function initialize() {
73 | math = TDLMath;
74 | fast = TDLFast;
75 | canvas = document.getElementById("canvas");
76 | g_fpsTimer = new TDLFps.FPSTimer();
77 |
78 | gl = TDLWebGL.setupWebGL(canvas);
79 | if (!gl) {
80 | return false;
81 | }
82 | if (g_debug) {
83 | gl = TDLWebGL.makeDebugContext(gl, undefined, LogGLCall);
84 | }
85 |
86 | Log("--Setup Sphere---------------------------------------");
87 | var sphere = setupSphere();
88 |
89 | var then = 0.0;
90 | var clock = 0.0;
91 | var fpsElem = document.getElementById("fps");
92 |
93 | // pre-allocate a bunch of arrays
94 | var projection = new Float32Array(16);
95 | var view = new Float32Array(16);
96 | var world = new Float32Array(16);
97 | var worldInverse = new Float32Array(16);
98 | var worldInverseTranspose = new Float32Array(16);
99 | var viewProjection = new Float32Array(16);
100 | var worldViewProjection = new Float32Array(16);
101 | var viewInverse = new Float32Array(16);
102 | var viewProjectionInverse = new Float32Array(16);
103 | var eyePosition = new Float32Array(3);
104 | var target = new Float32Array(3);
105 | var up = new Float32Array([0,1,0]);
106 | var lightWorldPos = new Float32Array(3);
107 | var v3t0 = new Float32Array(3);
108 | var v3t1 = new Float32Array(3);
109 | var v3t2 = new Float32Array(3);
110 | var v3t3 = new Float32Array(3);
111 | var m4t0 = new Float32Array(16);
112 | var m4t1 = new Float32Array(16);
113 | var m4t2 = new Float32Array(16);
114 | var m4t3 = new Float32Array(16);
115 | var zero4 = new Float32Array(4);
116 | var one4 = new Float32Array([1,1,1,1]);
117 |
118 | // Sphere uniforms.
119 | var sphereConst = {
120 | viewInverse: viewInverse,
121 | lightWorldPos: lightWorldPos,
122 | specular: one4,
123 | shininess: 50,
124 | specularFactor: 0.2};
125 | var spherePer = {
126 | lightColor: new Float32Array([0,0,0,1]),
127 | world: world,
128 | worldViewProjection: worldViewProjection,
129 | worldInverse: worldInverse,
130 | worldInverseTranspose: worldInverseTranspose};
131 |
132 | var frameCount = 0;
133 | function render() {
134 | ++frameCount;
135 | if (!g_drawOnce) {
136 | TDLWebGL.requestAnimationFrame(render, canvas);
137 | }
138 | var now = (new Date()).getTime() * 0.001;
139 | var elapsedTime;
140 | if(then == 0.0) {
141 | elapsedTime = 0.0;
142 | } else {
143 | elapsedTime = now - then;
144 | }
145 | then = now;
146 |
147 | g_fpsTimer.update(elapsedTime);
148 | fpsElem.innerHTML = g_fpsTimer.averageFPS;
149 |
150 | clock += elapsedTime;
151 | eyePosition[0] = Math.sin(clock * g_eyeSpeed) * g_eyeRadius;
152 | eyePosition[1] = g_eyeHeight;
153 | eyePosition[2] = Math.cos(clock * g_eyeSpeed) * g_eyeRadius;
154 |
155 | gl.colorMask(true, true, true, true);
156 | gl.depthMask(true);
157 | gl.clearColor(0,0,0,0);
158 | gl.clearDepth(1);
159 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
160 |
161 | gl.enable(gl.CULL_FACE);
162 | gl.enable(gl.DEPTH_TEST);
163 |
164 | fast.matrix4.perspective(
165 | projection,
166 | math.degToRad(60),
167 | canvas.clientWidth / canvas.clientHeight,
168 | 1,
169 | 5000);
170 | fast.matrix4.lookAt(
171 | view,
172 | eyePosition,
173 | target,
174 | up);
175 | fast.matrix4.mul(viewProjection, view, projection);
176 | fast.matrix4.inverse(viewInverse, view);
177 | fast.matrix4.inverse(viewProjectionInverse, viewProjection);
178 |
179 | fast.matrix4.getAxis(v3t0, viewInverse, 0); // x
180 | fast.matrix4.getAxis(v3t1, viewInverse, 1); // y;
181 | fast.matrix4.getAxis(v3t2, viewInverse, 2); // z;
182 | fast.mulScalarVector(v3t0, 10, v3t0);
183 | fast.mulScalarVector(v3t1, 10, v3t1);
184 | fast.mulScalarVector(v3t2, 10, v3t2);
185 | fast.addVector(lightWorldPos, eyePosition, v3t0);
186 | fast.addVector(lightWorldPos, lightWorldPos, v3t1);
187 | fast.addVector(lightWorldPos, lightWorldPos, v3t2);
188 |
189 | // view: view,
190 | // projection: projection,
191 | // viewProjection: viewProjection,
192 |
193 | Log("--Draw sphere---------------------------------------");
194 | sphere.drawPrep(sphereConst);
195 | var across = 6;
196 | var lightColor = spherePer.lightColor;
197 | var half = (across - 1) * 0.5;
198 | for (var xx = 0; xx < across; ++xx) {
199 | for (var yy = 0; yy < across; ++yy) {
200 | for (var zz = 0; zz < across; ++zz) {
201 | lightColor[0] = xx / across;
202 | lightColor[1] = yy / across;
203 | lightColor[2] = zz / across;
204 | var scale = (xx + yy + zz) % 4 / 4 + 0.5;
205 | fast.matrix4.scaling(m4t0, [scale, scale, scale]);
206 | fast.matrix4.translation(m4t1, [xx - half, yy - half, zz - half]);
207 | fast.matrix4.mul(world, m4t0, m4t1);
208 | fast.matrix4.mul(worldViewProjection, world, viewProjection);
209 | fast.matrix4.inverse(worldInverse, world);
210 | fast.matrix4.transpose(worldInverseTranspose, worldInverse);
211 | sphere.draw(spherePer);
212 | }
213 | }
214 | }
215 |
216 | // Set the alpha to 255.
217 | gl.colorMask(false, false, false, true);
218 | gl.clearColor(0,0,0,1);
219 | gl.clear(gl.COLOR_BUFFER_BIT);
220 |
221 | // turn off logging after 1 frame.
222 | g_logGLCalls = false;
223 | }
224 | render();
225 | return true;
226 | }
227 | initialize();
228 | }
229 |
230 | requirejs(
231 | [ '../tdl/buffers',
232 | '../tdl/fast',
233 | '../tdl/fps',
234 | '../tdl/log',
235 | '../tdl/math',
236 | '../tdl/models',
237 | '../tdl/primitives',
238 | '../tdl/programs',
239 | '../tdl/textures',
240 | '../tdl/webgl',
241 | ],
242 | main);
243 |
--------------------------------------------------------------------------------
/example/example.html:
--------------------------------------------------------------------------------
1 |
31 |
32 |
33 |
34 |
35 | WebGL TDL Example
36 |
78 |
79 |
308 |
309 |
310 |
311 |
314 |
315 |
316 |
317 |
318 |
342 |
377 |
378 |
379 |
380 |
--------------------------------------------------------------------------------
/example/example2.html:
--------------------------------------------------------------------------------
1 |
31 |
32 |
33 |
34 |
35 | WebGL TDL Example
36 |
52 |
53 |
286 |
287 |
288 | WebGL Spheres
289 |
290 |
293 |
294 |
295 |
296 |
297 |
298 |
322 |
356 |
357 |
358 |
359 |
--------------------------------------------------------------------------------
/example/line.html:
--------------------------------------------------------------------------------
1 |
31 |
32 |
33 |
34 |
35 | WebGL TDL Example
36 |
78 |
79 |
313 |
314 |
315 |
316 |
319 |
320 |
321 |
322 |
323 |
344 |
377 |
378 |
379 |
380 |
--------------------------------------------------------------------------------
/js/require.js:
--------------------------------------------------------------------------------
1 | /*
2 | RequireJS 2.1.11 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
3 | Available via the MIT or new BSD license.
4 | see: http://github.com/jrburke/requirejs for details
5 | */
6 | var requirejs,require,define;
7 | (function(ca){function G(b){return"[object Function]"===M.call(b)}function H(b){return"[object Array]"===M.call(b)}function v(b,c){if(b){var d;for(d=0;dthis.depCount&&!this.defined){if(G(c)){if(this.events.error&&this.map.isDefine||h.onError!==da)try{f=i.execCb(b,c,e,f)}catch(d){a=d}else f=i.execCb(b,c,e,f);this.map.isDefine&&void 0===f&&((e=this.module)?f=e.exports:this.usingExports&&
19 | (f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=c;this.exports=f;if(this.map.isDefine&&!this.ignore&&(p[b]=f,h.onResourceLoad))h.onResourceLoad(i,this.map,this.depMaps);y(b);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=
20 | this.map,b=a.id,d=m(a.prefix);this.depMaps.push(d);r(d,"defined",t(this,function(f){var d,g;g=j(ba,this.map.id);var J=this.map.name,u=this.map.parentMap?this.map.parentMap.name:null,p=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(J=f.normalize(J,function(a){return c(a,u,!0)})||""),f=m(a.prefix+"!"+J,this.map.parentMap),r(f,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),g=j(k,f.id)){this.depMaps.push(f);
21 | if(this.events.error)g.on("error",t(this,function(a){this.emit("error",a)}));g.enable()}}else g?(this.map.url=i.nameToUrl(g),this.load()):(d=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),d.error=t(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),d.fromText=t(this,function(f,c){var g=a.name,J=m(g),k=O;c&&(f=c);k&&(O=!1);q(J);s(l.config,b)&&(l.config[g]=l.config[b]);try{h.exec(f)}catch(j){return w(C("fromtexteval",
22 | "fromText eval for "+b+" failed: "+j,j,[b]))}k&&(O=!0);this.depMaps.push(J);i.completeLoad(g);p([g],d)}),f.load(a.name,p,d,l))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){W[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,t(this,function(a,b){var c,f;if("string"===typeof a){a=m(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=j(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;r(a,"defined",t(this,function(a){this.defineDep(b,
23 | a);this.check()}));this.errback&&r(a,"error",t(this,this.errback))}c=a.id;f=k[c];!s(N,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,t(this,function(a){var b=j(k,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:l,contextName:b,registry:k,defined:p,urlFetched:T,defQueue:A,Module:$,makeModuleMap:m,
24 | nextTick:h.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=l.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(l[b]||(l[b]={}),V(l[b],a,!0,!0)):l[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(ba[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),l.shim=b);a.packages&&v(a.packages,function(a){var b,
25 | a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(l.paths[b]=a.location);l.pkgs[b]=a.name+"/"+(a.main||"main").replace(ja,"").replace(R,"")});B(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=m(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ca,arguments));return b||a.exports&&ea(a.exports)}},makeRequire:function(a,e){function g(f,c,d){var j,l;e.enableBuildCallback&&(c&&G(c))&&(c.__requireJsBuild=
26 | !0);if("string"===typeof f){if(G(c))return w(C("requireargs","Invalid require call"),d);if(a&&s(N,f))return N[f](k[a.id]);if(h.get)return h.get(i,f,a,g);j=m(f,a,!1,!0);j=j.id;return!s(p,j)?w(C("notloaded",'Module name "'+j+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[j]}L();i.nextTick(function(){L();l=q(m(null,a));l.skipMap=e.skipMap;l.init(f,c,d,{enabled:!0});D()});return g}e=e||{};V(g,{isBrowser:z,toUrl:function(b){var e,d=b.lastIndexOf("."),g=b.split("/")[0];if(-1!==
27 | d&&(!("."===g||".."===g)||1g.attachEvent.toString().indexOf("[native code"))&&!Z?(O=!0,g.attachEvent("onreadystatechange",b.onScriptLoad)):
34 | (g.addEventListener("load",b.onScriptLoad,!1),g.addEventListener("error",b.onScriptError,!1)),g.src=d,L=g,D?y.insertBefore(g,D):y.appendChild(g),L=null,g;if(fa)try{importScripts(d),b.completeLoad(c)}catch(j){b.onError(C("importscripts","importScripts failed for "+c+" at "+d,j,[c]))}};z&&!r.skipDataMain&&U(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(K=b.getAttribute("data-main"))return q=K,r.baseUrl||(E=q.split("/"),q=E.pop(),Q=E.length?E.join("/")+"/":"./",r.baseUrl=
35 | Q),q=q.replace(R,""),h.jsExtRegExp.test(q)&&(q=K),r.deps=r.deps?r.deps.concat(q):[q],!0});define=function(b,c,d){var g,h;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(la,"").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(O){if(!(g=L))P&&"interactive"===P.readyState||U(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),g=P;g&&(b||
36 | (b=g.getAttribute("data-requiremodule")),h=F[g.getAttribute("data-requirecontext")])}(h?h.defQueue:S).push([b,c,d])};define.amd={jQuery:!0};h.exec=function(b){return eval(b)};h(r)}})(this);
37 |
--------------------------------------------------------------------------------
/jsdoc.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "tags" : {
3 | "allowUnknownTags" : false
4 | },
5 | "plugins" : ["plugins/markdown"],
6 | "templates" : {
7 | "cleverLinks" : false,
8 | "monospaceLinks" : false,
9 | "dateFormat" : "ddd MMM Do YYYY",
10 | "outputSourceFiles" : false,
11 | "outputSourcePath" : false,
12 | "systemName" : "ThreeDLibrary",
13 | "footer" : "",
14 | "copyright" : "copyright Google, Greggman",
15 | "navType" : "vertical",
16 | "theme" : "cerulean",
17 | "linenums" : true,
18 | "collapseSymbols" : false,
19 | "inverseNav" : true,
20 | "highlightTutorialCode" : true
21 | },
22 | "markdown" : {
23 | "parser" : "gfm",
24 | "hardwrap" : true
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tdl",
3 | "version": "0.0.8",
4 | "description": "Some WebGL Library",
5 | "main": "tdl/base.js",
6 | "directories": {
7 | "doc": "docs",
8 | "example": "example"
9 | },
10 | "scripts": {
11 | "test": "echo \"Error: no test specified\" && exit 1"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/greggman/tdl.git"
16 | },
17 | "keywords": [
18 | "WebGL"
19 | ],
20 | "author": "Greggman",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/greggman/tdl/issues"
24 | },
25 | "homepage": "https://github.com/greggman/tdl",
26 | "devDependencies": {
27 | "grunt": "^0.4.5",
28 | "grunt-contrib-clean": "^0.6.0",
29 | "grunt-contrib-uglify": "^0.7.0",
30 | "grunt-jsdoc": "^0.5.7"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tdl/base-rs.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014, Gregg Tavares.
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above
12 | * copyright notice, this list of conditions and the following disclaimer
13 | * in the documentation and/or other materials provided with the
14 | * distribution.
15 | * * Neither the name of Gregg Tavares. nor the names of its
16 | * contributors may be used to endorse or promote products derived from
17 | * this software without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | // emulate tdl/base.js for require.js
33 |
34 | define(function() {
35 |
36 | // Was base.js already included?
37 | var haveBaseJS = (this.tdl !== undefined);
38 | if (haveBaseJS) {
39 | tdl.provide('tdl.base-rs');
40 | return;
41 | }
42 |
43 | this.tdl = {base:{}};
44 | this.goog = {};
45 |
46 | var noop = function() {};
47 |
48 | // Let's assume if the user is using require JS they don't need tdl.require
49 | // If that's not the case we'd need provide a version of tdl.require that
50 | // ignores the tdl files but not the user's files. Probably hooked into requirejs
51 | tdl.require = noop;
52 | tdl.provide = noop;
53 |
54 |
55 | /**
56 | * Determine whether a value is an array. Do not use instanceof because that
57 | * will not work for V8 arrays (the browser thinks they are Objects).
58 | * @param {*} value A value.
59 | * @return {boolean} Whether the value is an array.
60 | */
61 | tdl.base.isArray = function(value) {
62 | var valueAsObject = /** @type {!Object} */ (value);
63 | return typeof(value) === 'object' && value !== null &&
64 | 'length' in valueAsObject && 'splice' in valueAsObject;
65 | };
66 |
67 | /**
68 | * A stub for later optionally converting obfuscated names
69 | * @private
70 | * @param {string} name Name to un-obfuscate.
71 | * @return {string} un-obfuscated name.
72 | */
73 | tdl.base.maybeDeobfuscateFunctionName_ = function(name) {
74 | return name;
75 | };
76 |
77 | /**
78 | * Makes one class inherit from another.
79 | * @param {!Object} subClass Class that wants to inherit.
80 | * @param {!Object} superClass Class to inherit from.
81 | */
82 | tdl.base.inherit = function(subClass, superClass) {
83 | /**
84 | * TmpClass.
85 | * @ignore
86 | * @constructor
87 | */
88 | var TmpClass = function() { };
89 | TmpClass.prototype = superClass.prototype;
90 | subClass.prototype = new TmpClass();
91 | };
92 |
93 | /**
94 | * Parses an error stack from an exception
95 | * @param {!Exception} excp The exception to get a stack trace from.
96 | * @return {!Array.} An array of strings of the stack trace.
97 | */
98 | tdl.base.parseErrorStack = function(excp) {
99 | var stack = [];
100 | var name;
101 | var line;
102 |
103 | if (!excp || !excp.stack) {
104 | return stack;
105 | }
106 |
107 | var stacklist = excp.stack.split('\n');
108 |
109 | for (var i = 0; i < stacklist.length - 1; i++) {
110 | var framedata = stacklist[i];
111 |
112 | name = framedata.match(/^([a-zA-Z0-9_$]*)/)[1];
113 | if (name) {
114 | name = tdl.base.maybeDeobfuscateFunctionName_(name);
115 | } else {
116 | name = 'anonymous';
117 | }
118 |
119 | var result = framedata.match(/(.*:[0-9]+)$/);
120 | line = result && result[1];
121 |
122 | if (!line) {
123 | line = '(unknown)';
124 | }
125 |
126 | stack[stack.length] = name + ' : ' + line
127 | }
128 |
129 | // remove top level anonymous functions to match IE
130 | var omitRegexp = /^anonymous :/;
131 | while (stack.length && omitRegexp.exec(stack[stack.length - 1])) {
132 | stack.length = stack.length - 1;
133 | }
134 |
135 | return stack;
136 | };
137 |
138 | /**
139 | * Gets a function name from a function object.
140 | * @param {!function(...): *} aFunction The function object to try to get a
141 | * name from.
142 | * @return {string} function name or 'anonymous' if not found.
143 | */
144 | tdl.base.getFunctionName = function(aFunction) {
145 | var regexpResult = aFunction.toString().match(/function(\s*)(\w*)/);
146 | if (regexpResult && regexpResult.length >= 2 && regexpResult[2]) {
147 | return tdl.base.maybeDeobfuscateFunctionName_(regexpResult[2]);
148 | }
149 | return 'anonymous';
150 | };
151 |
152 | /**
153 | * Pretty prints an exception's stack, if it has one.
154 | * @param {Array.} stack An array of errors.
155 | * @return {string} The pretty stack.
156 | */
157 | tdl.base.formatErrorStack = function(stack) {
158 | var result = '';
159 | for (var i = 0; i < stack.length; i++) {
160 | result += '> ' + stack[i] + '\n';
161 | }
162 | return result;
163 | };
164 |
165 | /**
166 | * Gets a stack trace as a string.
167 | * @param {number} stripCount The number of entries to strip from the top of the
168 | * stack. Example: Pass in 1 to remove yourself from the stack trace.
169 | * @return {string} The stack trace.
170 | */
171 | tdl.base.getStackTrace = function(stripCount) {
172 | var result = '';
173 |
174 | if (typeof(arguments.caller) != 'undefined') { // IE, not ECMA
175 | for (var a = arguments.caller; a != null; a = a.caller) {
176 | result += '> ' + tdl.base.getFunctionName(a.callee) + '\n';
177 | if (a.caller == a) {
178 | result += '*';
179 | break;
180 | }
181 | }
182 | } else { // Mozilla, not ECMA
183 | // fake an exception so we can get Mozilla's error stack
184 | var testExcp;
185 | try {
186 | eval('var var;');
187 | } catch (testExcp) {
188 | var stack = tdl.base.parseErrorStack(testExcp);
189 | result += tdl.base.formatErrorStack(stack.slice(3 + stripCount,
190 | stack.length));
191 | }
192 | }
193 |
194 | return result;
195 | };
196 |
197 | /**
198 | * Returns true if the user's browser is Microsoft IE.
199 | * @return {boolean} true if the user's browser is Microsoft IE.
200 | */
201 | tdl.base.IsMSIE = function() {
202 | var ua = navigator.userAgent.toLowerCase();
203 | var msie = /msie/.test(ua) && !/opera/.test(ua);
204 | return msie;
205 | };
206 |
207 | return {};
208 | });
209 |
--------------------------------------------------------------------------------
/tdl/base.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2009, Google Inc.
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above
12 | * copyright notice, this list of conditions and the following disclaimer
13 | * in the documentation and/or other materials provided with the
14 | * distribution.
15 | * * Neither the name of Google Inc. nor the names of its
16 | * contributors may be used to endorse or promote products derived from
17 | * this software without specific prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 |
33 | /**
34 | * @fileoverview Base for all tdl sample utilties.
35 | *
36 | * The main point of this module is to provide a central place to
37 | * have an init function to register an tdl namespace object because many other
38 | * modules need access to it.
39 | */
40 |
41 | /**
42 | * A namespace for all the tdl utility libraries.
43 | * @namespace
44 | */
45 | var tdl = tdl || {};
46 |
47 | /**
48 | * Define this because the Google internal JSCompiler needs goog.typedef below.
49 | */
50 | var goog = goog || {};
51 |
52 |
53 | if (!window.Int32Array) {
54 | window.Int32Array = function() { };
55 | window.Float32Array = function() { };
56 | window.Uint16Array = function() { };
57 | }
58 |
59 | /**
60 | * A macro for defining composite types.
61 | *
62 | * By assigning goog.typedef to a name, this tells Google internal JSCompiler
63 | * that this is not the name of a class, but rather it's the name of a composite
64 | * type.
65 | *
66 | * For example,
67 | * /** @type {Array|NodeList} / goog.ArrayLike = goog.typedef;
68 | * will tell JSCompiler to replace all appearances of goog.ArrayLike in type
69 | * definitions with the union of Array and NodeList.
70 | *
71 | * Does nothing in uncompiled code.
72 | */
73 | goog.typedef = true;
74 |
75 | /**
76 | * Reference to the global context. In most cases this will be 'window'.
77 | */
78 | tdl.global = this;
79 |
80 | /**
81 | * Some javascripts don't support __defineGetter__ or __defineSetter__
82 | * so we define some here so at least we don't get compile errors.
83 | * We expect the initialzation code will check and complain. This stubs
84 | * are just here to make sure we can actually get to the initialization code.
85 | */
86 | //if (!Object.prototype.__defineSetter__) {
87 | // Object.prototype.__defineSetter__ = function() {}
88 | // Object.prototype.__defineGetter__ = function() {}
89 | //}
90 | //
91 | /**
92 | * Flag used to force a function to run in the browser when it is called
93 | * from V8.
94 | * @type {boolean}
95 | */
96 | tdl.BROWSER_ONLY = true;
97 |
98 | /**
99 | * Array of namespaces that have been provided.
100 | * @private
101 | * @type {!Array.}
102 | */
103 | tdl.provided_ = [];
104 |
105 | /**
106 | * Creates object stubs for a namespace. When present in a file,
107 | * tdl.provide also indicates that the file defines the indicated
108 | * object.
109 | * @param {string} name name of the object that this file defines.
110 | */
111 | tdl.provide = function(name) {
112 | // Ensure that the same namespace isn't provided twice.
113 | if (tdl.getObjectByName(name) &&
114 | !tdl.implicitNamespaces_[name]) {
115 | throw 'Namespace "' + name + '" already declared.';
116 | }
117 |
118 | var namespace = name;
119 | while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {
120 | tdl.implicitNamespaces_[namespace] = true;
121 | }
122 |
123 | tdl.exportPath_(name);
124 | tdl.provided_.push(name);
125 | };
126 |
127 |
128 | /**
129 | * Namespaces implicitly defined by tdl.provide. For example,
130 | * tdl.provide('tdl.events.Event') implicitly declares
131 | * that 'tdl' and 'tdl.events' must be namespaces.
132 | *
133 | * @type {Object}
134 | * @private
135 | */
136 | tdl.implicitNamespaces_ = {};
137 |
138 | /**
139 | * Builds an object structure for the provided namespace path,
140 | * ensuring that names that already exist are not overwritten. For
141 | * example:
142 | * "a.b.c" -> a = {};a.b={};a.b.c={};
143 | * Used by tdl.provide and tdl.exportSymbol.
144 | * @param {string} name name of the object that this file defines.
145 | * @param {Object} opt_object the object to expose at the end of the path.
146 | * @param {Object} opt_objectToExportTo The object to add the path to; default
147 | * is |tdl.global|.
148 | * @private
149 | */
150 | tdl.exportPath_ = function(name, opt_object, opt_objectToExportTo) {
151 | var parts = name.split('.');
152 | var cur = opt_objectToExportTo || tdl.global;
153 | var part;
154 |
155 | // Internet Explorer exhibits strange behavior when throwing errors from
156 | // methods externed in this manner. See the testExportSymbolExceptions in
157 | // base_test.html for an example.
158 | if (!(parts[0] in cur) && cur.execScript) {
159 | cur.execScript('var ' + parts[0]);
160 | }
161 |
162 | // Parentheses added to eliminate strict JS warning in Firefox.
163 | while (parts.length && (part = parts.shift())) {
164 | if (!parts.length && tdl.isDef(opt_object)) {
165 | // last part and we have an object; use it.
166 | cur[part] = opt_object;
167 | } else if (cur[part]) {
168 | cur = cur[part];
169 | } else {
170 | cur = cur[part] = {};
171 | }
172 | }
173 | };
174 |
175 |
176 | /**
177 | * Returns an object based on its fully qualified external name. If you are
178 | * using a compilation pass that renames property names beware that using this
179 | * function will not find renamed properties.
180 | *
181 | * @param {string} name The fully qualified name.
182 | * @param {Object} opt_obj The object within which to look; default is
183 | * |tdl.global|.
184 | * @return {Object} The object or, if not found, null.
185 | */
186 | tdl.getObjectByName = function(name, opt_obj) {
187 | var parts = name.split('.');
188 | var cur = opt_obj || tdl.global;
189 | for (var pp = 0; pp < parts.length; ++pp) {
190 | var part = parts[pp];
191 | if (cur[part]) {
192 | cur = cur[part];
193 | } else {
194 | return null;
195 | }
196 | }
197 | return cur;
198 | };
199 |
200 |
201 | /**
202 | * Implements a system for the dynamic resolution of dependencies.
203 | * @param {string} rule Rule to include, in the form tdl.package.part.
204 | */
205 | tdl.require = function(rule) {
206 | // TODO(gman): For some unknown reason, when we call
207 | // tdl.util.getScriptTagText_ it calls
208 | // document.getElementsByTagName('script') and for some reason the scripts do
209 | // not always show up. Calling it here seems to fix that as long as we
210 | // actually ask for the length, at least in FF 3.5.1 It would be nice to
211 | // figure out why.
212 | var dummy = document.getElementsByTagName('script').length;
213 | // if the object already exists we do not need do do anything
214 | if (tdl.getObjectByName(rule)) {
215 | return;
216 | }
217 | var path = tdl.getPathFromRule_(rule);
218 | if (path) {
219 | tdl.included_[path] = true;
220 | tdl.writeScripts_();
221 | } else {
222 | throw new Error('tdl.require could not find: ' + rule);
223 | }
224 | };
225 |
226 |
227 | /**
228 | * Path for included scripts.
229 | * @type {string}
230 | */
231 | tdl.basePath = '';
232 |
233 |
234 | /**
235 | * Object used to keep track of urls that have already been added. This
236 | * record allows the prevention of circular dependencies.
237 | * @type {Object}
238 | * @private
239 | */
240 | tdl.included_ = {};
241 |
242 |
243 | /**
244 | * This object is used to keep track of dependencies and other data that is
245 | * used for loading scripts.
246 | * @private
247 | * @type {Object}
248 | */
249 | tdl.dependencies_ = {
250 | visited: {}, // used when resolving dependencies to prevent us from
251 | // visiting the file twice.
252 | written: {} // used to keep track of script files we have written.
253 | };
254 |
255 |
256 | /**
257 | * Tries to detect the base path of the tdl-base.js script that
258 | * bootstraps the tdl libraries.
259 | * @private
260 | */
261 | tdl.findBasePath_ = function() {
262 | var doc = tdl.global.document;
263 | if (typeof doc == 'undefined') {
264 | return;
265 | }
266 | if (tdl.global.BASE_PATH) {
267 | tdl.basePath = tdl.global.BASE_PATH;
268 | return;
269 | } else {
270 | // HACKHACK to hide compiler warnings :(
271 | tdl.global.BASE_PATH = null;
272 | }
273 | var expectedBase = 'tdl/base.js';
274 | var scripts = doc.getElementsByTagName('script');
275 | for (var script, i = 0; script = scripts[i]; i++) {
276 | var src = script.src;
277 | var l = src.length;
278 | if (src.substr(l - expectedBase.length) == expectedBase) {
279 | tdl.basePath = src.substr(0, l - expectedBase.length);
280 | return;
281 | }
282 | }
283 | };
284 |
285 |
286 | /**
287 | * Writes a script tag if, and only if, that script hasn't already been added
288 | * to the document. (Must be called at execution time.)
289 | * @param {string} src Script source.
290 | * @private
291 | */
292 | tdl.writeScriptTag_ = function(src) {
293 | var doc = tdl.global.document;
294 | if (typeof doc != 'undefined' &&
295 | !tdl.dependencies_.written[src]) {
296 | tdl.dependencies_.written[src] = true;
297 | var html = '