Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: o3d/samples/o3d-webgl/param_operation.js

Issue 3029050: o3d-webgl: Added remaining param_operation classes. (Closed)
Patch Set: make sure nothing changed Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « o3d/samples/o3d-webgl/curve.js ('k') | o3d/samples/o3d-webgl/skin.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2010, Google Inc. 2 * Copyright 2010, Google Inc.
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 function(value) {} 125 function(value) {}
126 ); 126 );
127 127
128 /** 128 /**
129 * A Param operation that takes 2 floats to produce a float2. 129 * A Param operation that takes 2 floats to produce a float2.
130 * @constructor 130 * @constructor
131 * @extends {o3d.ParamObject} 131 * @extends {o3d.ParamObject}
132 */ 132 */
133 o3d.ParamOp2FloatsToFloat2 = function() { 133 o3d.ParamOp2FloatsToFloat2 = function() {
134 o3d.ParamObject.call(this); 134 o3d.ParamObject.call(this);
135 this.last_output_value_ = [0,0]; 135 this.last_output_value_ = [0, 0];
136 }; 136 };
137 o3d.inherit('ParamOp2FloatsToFloat2', 'ParamObject'); 137 o3d.inherit('ParamOp2FloatsToFloat2', 'ParamObject');
138 138
139 (function(){ 139 (function(){
140 for (var i = 0; i < 2; i++) { 140 for (var i = 0; i < 2; i++) {
141 o3d.ParamObject.setUpO3DParam_( 141 o3d.ParamObject.setUpO3DParam_(
142 o3d.ParamOp2FloatsToFloat2, "input"+i, "ParamFloat"); 142 o3d.ParamOp2FloatsToFloat2, "input"+i, "ParamFloat");
143 } 143 }
144 o3d.ParamObject.setUpO3DParam_( 144 o3d.ParamObject.setUpO3DParam_(
145 o3d.ParamOp2FloatsToFloat2, "output", "ParamMatrix4Output"); 145 o3d.ParamOp2FloatsToFloat2, "output", "ParamMatrix4Output");
146 })(); 146 })();
147 147
148 /** 148 /**
149 * Called by o3d.Param*Output whenever its value gets read. 149 * Called by o3d.Param*Output whenever its value gets read.
150 * @return {!Array<number>} 2-element array equal to [input0,input1] 150 * @return {!Array.<number>} 2-element array equal to [input0,input1]
151 */ 151 */
152 o3d.ParamOp2FloatsToFloat2.prototype.updateOutputs = function() { 152 o3d.ParamOp2FloatsToFloat2.prototype.updateOutputs = function() {
153 this.last_output_value_[0] = this.getParam("input0").value; 153 this.last_output_value_[0] = this.getParam("input0").value;
154 this.last_output_value_[1] = this.getParam("input1").value; 154 this.last_output_value_[1] = this.getParam("input1").value;
155 return this.last_output_value_; 155 return this.last_output_value_;
156 }; 156 };
157 157
158 /** 158 /**
159 * A Param operation that takes 3 floats to produce a float3. 159 * A Param operation that takes 3 floats to produce a float3.
160 * @constructor 160 * @constructor
161 * @extends {o3d.ParamObject} 161 * @extends {o3d.ParamObject}
162 */ 162 */
163 o3d.ParamOp3FloatsToFloat3 = function() { 163 o3d.ParamOp3FloatsToFloat3 = function() {
164 o3d.ParamObject.call(this); 164 o3d.ParamObject.call(this);
165 this.last_output_value_ = [0,0,0]; 165 this.last_output_value_ = [0, 0, 0];
166 }; 166 };
167 o3d.inherit('ParamOp3FloatsToFloat3', 'ParamObject'); 167 o3d.inherit('ParamOp3FloatsToFloat3', 'ParamObject');
168 168
169 (function(){ 169 (function(){
170 for (var i = 0; i < 3; i++) { 170 for (var i = 0; i < 3; i++) {
171 o3d.ParamObject.setUpO3DParam_( 171 o3d.ParamObject.setUpO3DParam_(
172 o3d.ParamOp3FloatsToFloat3, "input"+i, "ParamFloat"); 172 o3d.ParamOp3FloatsToFloat3, "input"+i, "ParamFloat");
173 } 173 }
174 o3d.ParamObject.setUpO3DParam_( 174 o3d.ParamObject.setUpO3DParam_(
175 o3d.ParamOp3FloatsToFloat3, "output", "ParamMatrix4Output"); 175 o3d.ParamOp3FloatsToFloat3, "output", "ParamMatrix4Output");
176 })(); 176 })();
177 177
178 /** 178 /**
179 * Called by o3d.Param*Output whenever its value gets read. 179 * Called by o3d.Param*Output whenever its value gets read.
180 * @return {!Array<number>} 3-element array equal to [input0,input1,input2] 180 * @return {!Array.<number>} 3-element array equal to [input0,input1,input2]
181 */ 181 */
182 o3d.ParamOp3FloatsToFloat3.prototype.updateOutputs = function() { 182 o3d.ParamOp3FloatsToFloat3.prototype.updateOutputs = function() {
183 this.last_output_value_[0] = this.getParam("input0").value; 183 this.last_output_value_[0] = this.getParam("input0").value;
184 this.last_output_value_[1] = this.getParam("input1").value; 184 this.last_output_value_[1] = this.getParam("input1").value;
185 this.last_output_value_[2] = this.getParam("input2").value; 185 this.last_output_value_[2] = this.getParam("input2").value;
186 return this.last_output_value_; 186 return this.last_output_value_;
187 }; 187 };
188 188
189 /** 189 /**
190 * A Param operation that takes 4 floats to produce a float4. 190 * A Param operation that takes 4 floats to produce a float4.
191 * @constructor 191 * @constructor
192 * @extends {o3d.ParamObject} 192 * @extends {o3d.ParamObject}
193 */ 193 */
194 o3d.ParamOp4FloatsToFloat4 = function() { 194 o3d.ParamOp4FloatsToFloat4 = function() {
195 o3d.ParamObject.call(this); 195 o3d.ParamObject.call(this);
196 this.last_output_value_ = [0,0,0,0]; 196 this.last_output_value_ = [0, 0, 0, 0];
197 }; 197 };
198 o3d.inherit('ParamOp4FloatsToFloat4', 'ParamObject'); 198 o3d.inherit('ParamOp4FloatsToFloat4', 'ParamObject');
199 199
200 (function(){ 200 (function(){
201 for (var i = 0; i < 4; i++) { 201 for (var i = 0; i < 4; i++) {
202 o3d.ParamObject.setUpO3DParam_( 202 o3d.ParamObject.setUpO3DParam_(
203 o3d.ParamOp4FloatsToFloat4, "input"+i, "ParamFloat"); 203 o3d.ParamOp4FloatsToFloat4, "input"+i, "ParamFloat");
204 } 204 }
205 o3d.ParamObject.setUpO3DParam_( 205 o3d.ParamObject.setUpO3DParam_(
206 o3d.ParamOp4FloatsToFloat4, "output", "ParamMatrix4Output"); 206 o3d.ParamOp4FloatsToFloat4, "output", "ParamMatrix4Output");
207 })(); 207 })();
208 208
209 /** 209 /**
210 * Called by o3d.Param*Output whenever its value gets read. 210 * Called by o3d.Param*Output whenever its value gets read.
211 * @return {!Array<number>} 4-element array equal to 211 * @return {!Array.<number>} 4-element array equal to
212 * [input0,input1,input2,input3] 212 * [input0,input1,input2,input3]
213 */ 213 */
214 o3d.ParamOp4FloatsToFloat4.prototype.updateOutputs = function() { 214 o3d.ParamOp4FloatsToFloat4.prototype.updateOutputs = function() {
215 this.last_output_value_[0] = this.getParam("input0").value; 215 this.last_output_value_[0] = this.getParam("input0").value;
216 this.last_output_value_[1] = this.getParam("input1").value; 216 this.last_output_value_[1] = this.getParam("input1").value;
217 this.last_output_value_[2] = this.getParam("input2").value; 217 this.last_output_value_[2] = this.getParam("input2").value;
218 this.last_output_value_[3] = this.getParam("input3").value; 218 this.last_output_value_[3] = this.getParam("input3").value;
219 return this.last_output_value_; 219 return this.last_output_value_;
220 }; 220 };
221 221
222 /** 222 /**
223 * A Param operation that takes 16 floats to produce a 4-by-4 matrix. 223 * A Param operation that takes 16 floats to produce a 4-by-4 matrix.
224 * @constructor 224 * @constructor
225 * @extends {o3d.ParamObject} 225 * @extends {o3d.ParamObject}
226 */ 226 */
227 o3d.ParamOp16FloatsToMatrix4 = function() { 227 o3d.ParamOp16FloatsToMatrix4 = function() {
228 o3d.ParamObject.call(this); 228 o3d.ParamObject.call(this);
229 this.last_output_value_ = [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]; 229 this.last_output_value_ =
230 [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]];
230 }; 231 };
231 o3d.inherit('ParamOp16FloatsToMatrix4', 'ParamObject'); 232 o3d.inherit('ParamOp16FloatsToMatrix4', 'ParamObject');
232 233
233 (function(){ 234 (function(){
234 for (var i = 0; i < 16; i++) { 235 for (var i = 0; i < 16; i++) {
235 o3d.ParamObject.setUpO3DParam_( 236 o3d.ParamObject.setUpO3DParam_(
236 o3d.ParamOp16FloatsToMatrix4, "input"+i, "ParamFloat"); 237 o3d.ParamOp16FloatsToMatrix4, "input"+i, "ParamFloat");
237 } 238 }
238 o3d.ParamObject.setUpO3DParam_( 239 o3d.ParamObject.setUpO3DParam_(
239 o3d.ParamOp16FloatsToMatrix4, "output", "ParamMatrix4Output"); 240 o3d.ParamOp16FloatsToMatrix4, "output", "ParamMatrix4Output");
240 })(); 241 })();
241 242
242 /** 243 /**
243 * Called by o3d.Param*Output whenever its value gets read. 244 * Called by o3d.Param*Output whenever its value gets read.
244 * @return {!Array<!Array<number>>} 4x4 array equal to 245 * @return {!Array.<!Array.<number>>} 4x4 array equal to
245 * [[i0,i1,i2,i3],[i4,i5,i6,i7],[i8,i9,i10,i11],[i12,i13,i14,i15]] 246 * [[i0,i1,i2,i3],[i4,i5,i6,i7],[i8,i9,i10,i11],[i12,i13,i14,i15]]
246 */ 247 */
247 o3d.ParamOp16FloatsToMatrix4.prototype.updateOutputs = function() { 248 o3d.ParamOp16FloatsToMatrix4.prototype.updateOutputs = function() {
248 for (var i = 0; i < 16; i++) { 249 for (var i = 0; i < 16; i++) {
249 this.last_output_value_[Math.floor(i/4)][i%4] = 250 this.last_output_value_[Math.floor(i/4)][i%4] =
250 this.getParam("input"+i).value; 251 this.getParam("input"+i).value;
251 } 252 }
252 return this.last_output_value_; 253 return this.last_output_value_;
253 }; 254 };
254 255
(...skipping 19 matching lines...) Expand all
274 this.rotateZ = 0; 275 this.rotateZ = 0;
275 276
276 this.translateX = 0; 277 this.translateX = 0;
277 this.translateY = 0; 278 this.translateY = 0;
278 this.translateZ = 0; 279 this.translateZ = 0;
279 280
280 this.scaleX = 1; 281 this.scaleX = 1;
281 this.scaleY = 1; 282 this.scaleY = 1;
282 this.scaleZ = 1; 283 this.scaleZ = 1;
283 284
284 this.last_output_value_ = [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]; 285 this.last_output_value_ =
286 [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]];
285 }; 287 };
286 o3d.inherit('TRSToMatrix4', 'ParamObject'); 288 o3d.inherit('TRSToMatrix4', 'ParamObject');
287 289
288 (function(){ 290 (function(){
289 var proplist = ["rotateX", "rotateY", "rotateZ", 291 var proplist = ["rotateX", "rotateY", "rotateZ",
290 "translateX", "translateY", "translateZ", 292 "translateX", "translateY", "translateZ",
291 "scaleX", "scaleY", "scaleZ"]; 293 "scaleX", "scaleY", "scaleZ"];
292 for (var i = 0; i < proplist.length; i++) { 294 for (var i = 0; i < proplist.length; i++) {
293 o3d.ParamObject.setUpO3DParam_(o3d.TRSToMatrix4, proplist[i], "ParamFloat"); 295 o3d.ParamObject.setUpO3DParam_(o3d.TRSToMatrix4, proplist[i], "ParamFloat");
294 } 296 }
295 o3d.ParamObject.setUpO3DParam_( 297 o3d.ParamObject.setUpO3DParam_(
296 o3d.TRSToMatrix4, "output", "ParamMatrix4Output"); 298 o3d.TRSToMatrix4, "output", "ParamMatrix4Output");
297 })(); 299 })();
298 300
299 /** 301 /**
300 * Called by o3d.Param*Output whenever its value gets read. 302 * Called by o3d.Param*Output whenever its value gets read.
301 * @return {!Array<!Array<number>>} Matrix4 equal to Translate * Rotate * Scale. 303 * @return {!Array.<!Array.<number>>} Matrix4 equal to applying the operations
304 * in the order Translate * Rotate * Scale.
302 */ 305 */
303 o3d.TRSToMatrix4.prototype.updateOutputs = function () { 306 o3d.TRSToMatrix4.prototype.updateOutputs = function () {
304 var ret = this.last_output_value_; 307 var ret = this.last_output_value_;
305 var rX = this.rotateX; 308 var rX = this.rotateX;
306 var rY = this.rotateY; 309 var rY = this.rotateY;
307 var rZ = this.rotateZ; 310 var rZ = this.rotateZ;
308 var sX = this.scaleX; 311 var sX = this.scaleX;
309 var sY = this.scaleY; 312 var sY = this.scaleY;
310 var sZ = this.scaleZ; 313 var sZ = this.scaleZ;
311 var sinX = Math.sin(rX); 314 var sinX = Math.sin(rX);
(...skipping 18 matching lines...) Expand all
330 cosY * cosX * sZ, 333 cosY * cosX * sZ,
331 0); 334 0);
332 ret[3].splice(0, 4, this.translateX, 335 ret[3].splice(0, 4, this.translateX,
333 this.translateY, 336 this.translateY,
334 this.translateZ, 337 this.translateZ,
335 1); 338 1);
336 return ret; 339 return ret;
337 }; 340 };
338 341
339 /** 342 /**
340 * A Param operation that takes 16 floats to produce a 4-by-4 matrix. 343 * A Param operation that takes an input matrix and a local matrix
344 * to produce an output matrix.
341 * @constructor 345 * @constructor
342 * @extends {o3d.ParamObject} 346 * @extends {o3d.ParamObject}
343 */ 347 */
344 o3d.Matrix4Composition = function() { 348 o3d.Matrix4Composition = function() {
345 o3d.ParamObject.call(this); 349 o3d.ParamObject.call(this);
346 this.last_output_value_ = [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]; 350 this.last_output_value_ =
351 [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]];
347 }; 352 };
348 o3d.inherit('Matrix4Composition', 'ParamObject'); 353 o3d.inherit('Matrix4Composition', 'ParamObject');
349 354
350 o3d.ParamObject.setUpO3DParam_( 355 o3d.ParamObject.setUpO3DParam_(
351 o3d.Matrix4Composition, "inputMatrix", "ParamMatrix4"); 356 o3d.Matrix4Composition, "inputMatrix", "ParamMatrix4");
352 357
353 o3d.ParamObject.setUpO3DParam_( 358 o3d.ParamObject.setUpO3DParam_(
354 o3d.Matrix4Composition, "localMatrix", "ParamMatrix4"); 359 o3d.Matrix4Composition, "localMatrix", "ParamMatrix4");
355 360
356 o3d.ParamObject.setUpO3DParam_( 361 o3d.ParamObject.setUpO3DParam_(
357 o3d.Matrix4Composition, "outputMatrix", "ParamMatrix4Output"); 362 o3d.Matrix4Composition, "outputMatrix", "ParamMatrix4Output");
358 363
359 /** 364 /**
360 * Called by o3d.Param*Output whenever its value gets read. 365 * Called by o3d.Param*Output whenever its value gets read.
361 * @return {!Array<!Array<number>>} 4x4 array equal to 366 * @return {!Array.<!Array.<number>>} 4x4 array equal to
362 * [[i0,i1,i2,i3],[i4,i5,i6,i7],[i8,i9,i10,i11],[i12,i13,i14,i15]] 367 * inputMatrix * localMatrix
363 */ 368 */
364 o3d.Matrix4Composition.prototype.updateOutputs = function() { 369 o3d.Matrix4Composition.prototype.updateOutputs = function() {
365 o3d.Transform.compose(this.inputMatrix, this.localMatrix, 370 var input = this.getParam("inputMatrix").value;
366 this.last_output_value_); 371 var local = this.getParam("localMatrix").value;
372 o3d.Transform.compose(input, local, this.last_output_value_);
367 return this.last_output_value_; 373 return this.last_output_value_;
368 }; 374 };
369 375
370 376
377 /**
378 * A Param operation that takes an input matrix, a float3 axis and an angle
379 * to produce an output matrix.
380 * @constructor
381 * @extends {o3d.ParamObject}
382 */
383 o3d.Matrix4AxisRotation = function() {
384 o3d.ParamObject.call(this);
385 this.last_output_value_ =
386 [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]];
387 };
388 o3d.inherit('Matrix4AxisRotation', 'ParamObject');
389
390 o3d.ParamObject.setUpO3DParam_(
391 o3d.Matrix4AxisRotation, "inputMatrix", "ParamMatrix4");
392
393 o3d.ParamObject.setUpO3DParam_(
394 o3d.Matrix4AxisRotation, "axis", "ParamFloat3");
395
396 o3d.ParamObject.setUpO3DParam_(
397 o3d.Matrix4AxisRotation, "angle", "ParamFloat");
398
399 o3d.ParamObject.setUpO3DParam_(
400 o3d.Matrix4AxisRotation, "outputMatrix", "ParamMatrix4Output");
401
402 /**
403 * Called by o3d.Param*Output whenever its value gets read.
404 * @return {!Array.<!Array.<number>>} 4x4 array from rotating inputMatrix around
405 * axis by angle.
406 */
407 o3d.Matrix4AxisRotation.prototype.updateOutputs = function() {
408 var input = this.getParam("inputMatrix").value;
409 var axis = this.getParam("axis").value;
410 var angle = this.getParam("angle").value;
411 o3d.Transform.axisRotateMatrix(input, axis, angle, this.last_output_value_);
412 return this.last_output_value_;
413 };
414
415
416 /**
417 * A Param operation that takes an input matrix and a float3 scale
418 * to produce an output matrix.
419 * @constructor
420 * @extends {o3d.ParamObject}
421 */
422 o3d.Matrix4Scale = function() {
423 o3d.ParamObject.call(this);
424 this.last_output_value_ =
425 [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]];
426 };
427 o3d.inherit('Matrix4Scale', 'ParamObject');
428
429 o3d.ParamObject.setUpO3DParam_(
430 o3d.Matrix4Scale, "inputMatrix", "ParamMatrix4");
431
432 o3d.ParamObject.setUpO3DParam_(
433 o3d.Matrix4Scale, "scale", "ParamFloat3");
434
435 o3d.ParamObject.setUpO3DParam_(
436 o3d.Matrix4Scale, "outputMatrix", "ParamMatrix4Output");
437
438 /**
439 * Called by o3d.Param*Output whenever its value gets read.
440 * @return {!Array.<!Array.<number>>} 4x4 array from scaling inputMatrix by
441 * scale.
442 */
443 o3d.Matrix4Scale.prototype.updateOutputs = function() {
444 var m = this.getParam("inputMatrix").value;
445 var ret = this.last_output_value_;
446 var v = this.getParam("scale").value;
447
448 var v0 = v[0];
449 var v1 = v[1];
450 var v2 = v[2];
451
452 var m0 = m[0];
453 var m1 = m[1];
454 var m2 = m[2];
455 var m3 = m[3];
456
457 ret[0].splice(0, 4, v0 * m0[0], v0 * m0[1], v0 * m0[2], v0 * m0[3]);
458 ret[1].splice(0, 4, v1 * m1[0], v1 * m1[1], v1 * m1[2], v1 * m1[3]);
459 ret[2].splice(0, 4, v2 * m2[0], v2 * m2[1], v2 * m2[2], v2 * m2[3]);
460 ret[3] = m3.slice(0);
461 return ret;
462 };
463
464
465 /**
466 * A Param operation that takes an input matrix, and a translation
467 * to produce an output matrix.
468 * @constructor
469 * @extends {o3d.ParamObject}
470 */
471 o3d.Matrix4Translation = function() {
472 o3d.ParamObject.call(this);
473 this.last_output_value_ =
474 [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]];
475 };
476 o3d.inherit('Matrix4Translation', 'ParamObject');
477
478 o3d.ParamObject.setUpO3DParam_(
479 o3d.Matrix4Translation, "inputMatrix", "ParamMatrix4");
480
481 o3d.ParamObject.setUpO3DParam_(
482 o3d.Matrix4Translation, "translation", "ParamFloat3");
483
484 o3d.ParamObject.setUpO3DParam_(
485 o3d.Matrix4Translation, "outputMatrix", "ParamMatrix4Output");
486
487 /**
488 * Called by o3d.Param*Output whenever its value gets read.
489 * @return {!Array.<!Array.<number>>} 4x4 array from translating inputMatrix
490 * by translation.
491 */
492 o3d.Matrix4Translation.prototype.updateOutputs = function() {
493 var m = this.getParam("inputMatrix").value;
494 var ret = this.last_output_value_;
495 var v = this.getParam("translation").value;
496
497 var v0 = v[0];
498 var v1 = v[1];
499 var v2 = v[2];
500
501 var m0 = m[0];
502 var m1 = m[1];
503 var m2 = m[2];
504 var m3 = m[3];
505
506 ret[0] = m0.slice(0);
507 ret[1] = m1.slice(0);
508 ret[2] = m2.slice(0);
509 ret[3].splice(0, 4, m0[0] * v0 + m1[0] * v1 + m2[0] * v2 + m3[0],
510 m0[1] * v0 + m1[1] * v1 + m2[1] * v2 + m3[1],
511 m0[2] * v0 + m1[2] * v1 + m2[2] * v2 + m3[2],
512 m0[3] * v0 + m1[3] * v1 + m2[3] * v2 + m3[3]);
513 return ret;
514 };
515
516
OLDNEW
« no previous file with comments | « o3d/samples/o3d-webgl/curve.js ('k') | o3d/samples/o3d-webgl/skin.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698