2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 /* eslint-env browser */
20 /* eslint "brace-style": [2, "1tbs"] */
21 /* eslint "no-console": 0 */
22 /* eslint "no-underscore-dangle": 0 */
25 // Dali browser application for testing the javascript API.
28 // browser variables defined for eslint
49 var actorIdToShaderSet = {}; // actor id to shader
50 var compiledShaders = {}; // compiled shaders by name
52 var animationList = []; // list of animations that have been added [ { animation: new dali.Animation(), properties: [] } ]
53 var animationSelectionIndex; // selected animation
60 var shaderSourceSelection = 0;
63 name: "pass through texture",
67 "attribute mediump vec3 aPosition;\n" +
68 "attribute mediump vec2 aTexCoord;\n" +
69 "varying mediump vec2 vTexCoord;\n" +
70 "uniform mediump vec3 uSize;\n" +
71 "uniform mediump mat4 uModelView;\n" +
72 "uniform mediump mat4 uProjection;\n" +
73 "uniform mediump mat4 uMvpMatrix;\n" +
77 " mediump vec4 vertexPosition = vec4(aPosition, 1.0);\n" +
78 " vertexPosition.xyz *= uSize;\n" +
79 " gl_Position = uMvpMatrix * vertexPosition;\n" +
80 " vTexCoord = aTexCoord;\n" +
82 fragment: "precision mediump float;\n" +
84 "uniform sampler2D sTexture;\n" +
85 "uniform mediump vec4 uColor;\n" +
86 "varying mediump vec2 vTexCoord;\n" +
90 " gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n" +
94 name: "pass through color",
97 "attribute mediump vec3 aPosition;\n" +
98 "attribute mediump vec2 aTexCoord;\n" +
99 "varying mediump vec2 vTexCoord;\n" +
100 "uniform mediump vec3 uSize;\n" +
101 "uniform mediump mat4 uModelView;\n" +
102 "uniform mediump mat4 uProjection;\n" +
104 "void main(void)\n" +
106 " gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\n" +
107 " vertexPosition.xyz *= uSize;\n" +
108 " vTexCoord = aTexCoord;\n" +
110 fragment: "precision mediump float;\n" +
112 "uniform mediump vec4 uColor;\n" +
113 "varying mediump vec2 vTexCoord;\n" +
117 " gl_FragColor = vColor * uColor;\n" +
121 name: "sRGB Correction",
124 "uniform mediump mat4 uModelView;\n" +
125 "uniform mediump mat4 uProjection;\n" +
126 "uniform mediump mat4 uModelMatrix;\n" +
127 "attribute mediump vec3 aPosition;\n" +
128 "attribute mediump vec2 aTexCoord;\n" +
129 "varying mediump vec2 vTexCoord;\n" +
130 "uniform mediump vec3 uSize;\n" +
132 "void main(void)\n" +
134 " mediump vec3 vertexPosition = aPosition * uSize;\n" +
135 " gl_Position = uProjection * uModelView * vec4(vertexPosition, 1.0);\n" +
136 " vTexCoord = aTexCoord;\n" +
138 fragment: "precision mediump float;\n" +
140 "uniform mediump vec4 uColor;\n" +
141 "uniform sampler2D sTexture;\n" +
142 "varying mediump vec2 vTexCoord;\n" +
146 "vec4 col = texture2D( sTexture, vTexCoord ) * uColor;\n" +
147 "vec3 mask = vec3(greaterThan(col.rgb, vec3(0.0031308)));\n" +
148 "vec3 o = mix(col.rgb * 12.92, \n" +
149 " pow(col.rgb, vec3(1.0/2.4)) * 1.055 - 0.055, \n" +
151 "gl_FragColor = vec4(o.r, o.g, o.b, col.a);\n" +
155 name: "adjust brightness",
157 animateTo: [ ["uGain", 1.0, "Linear", 0, 3],
158 ["uOffset", 0.2, "Linear", 0, 3] ],
161 "uniform mediump mat4 uModelView;\n" +
162 "uniform mediump mat4 uProjection;\n" +
163 "attribute mediump vec3 aPosition;\n" +
164 "attribute mediump vec2 aTexCoord;\n" +
165 "varying mediump vec2 vTexCoord;\n" +
166 "uniform mediump vec3 uSize;\n" +
168 "void main(void)\n" +
170 " mediump vec3 vertexPosition = aPosition * uSize;\n" +
171 " gl_Position = uProjection * uModelView * vec4(vertexPosition, 1.0);\n" +
172 " vTexCoord = aTexCoord;\n" +
177 "precision mediump float;\n" +
179 "uniform mediump vec4 uColor;\n" +
180 "uniform sampler2D sTexture;\n" +
181 "varying mediump vec2 vTexCoord;\n" +
183 "uniform float uGain; // {default:1.0} \n" +
184 "uniform float uOffset; // {default:0.0} \n" +
187 " vec4 t = texture2D( sTexture, vTexCoord );\n" +
189 " float y = 0.0 + (0.299 *t.r) + 0.587*t.g + 0.114*t.b;\n" +
190 " float cb= 128.0-(0.168736*t.r)-0.331264*t.g+0.5*t.b;\n" +
191 " float cr= 128.0+(0.5*t.r)-(0.418688*t.g)-0.081312*t.b;\n" +
193 " y = (y*uGain) + uOffset;\n" +
195 " vec4 col = vec4(t.a);\n" +
197 " col.r = y + 1.402*(cr-128.0);\n" +
198 " col.g = y - 0.34414*(cb-128.0)-0.71414*(cr-128.0);\n" +
199 " col.b = y + 1.722*(cb-128.0);\n" +
202 " gl_FragColor = col * uColor;\n" +
210 animateTo: [ ["uAmplitude", 0.2, "Linear", 0, 3],
211 ["uFrequency", 4, "Linear", 0, 3] ],
213 "uniform mediump mat4 uModelView;\n" +
214 "uniform mediump mat4 uProjection;\n" +
215 "attribute mediump vec3 aPosition;\n" +
216 "attribute mediump vec2 aTexCoord;\n" +
217 "varying mediump vec2 vTexCoord;\n" +
218 "uniform mediump vec3 uSize;\n" +
220 "void main(void)\n" +
222 " mediump vec3 vertexPosition = aPosition * uSize;\n" +
223 " gl_Position = uProjection * uModelView * vec4(vertexPosition, 1.0);\n" +
224 " vTexCoord = aTexCoord;\n" +
226 fragment: "precision mediump float;\n" +
228 "uniform mediump vec4 uColor;\n" +
229 "uniform sampler2D sTexture;\n" +
230 "varying mediump vec2 vTexCoord;\n" +
232 "uniform float uAmplitude; // {default:0.4, description:\"amplitude in x\"} \n" +
233 "uniform float uFrequency; // {default: 4, description:\"frequence in y\"} \n" +
236 " vec2 uv = vTexCoord.xy;\n" +
238 " uv.x += sin(uv.y * 3.14 * uFrequency) * uAmplitude;\n" +
240 " vec4 color = texture2D(sTexture, uv);\n" +
242 " gl_FragColor = color;\n" +
248 animateTo: [ ["uFactor", -4.0, "Linear", 0, 3] ],
251 "uniform mediump mat4 uModelView;\n" +
252 "uniform mediump mat4 uProjection;\n" +
253 "attribute mediump vec3 aPosition;\n" +
254 "attribute mediump vec2 aTexCoord;\n" +
255 "varying mediump vec2 vTexCoord;\n" +
256 "uniform mediump vec3 uSize;\n" +
258 "void main(void)\n" +
260 " mediump vec3 vertexPosition = aPosition * uSize;\n" +
261 " gl_Position = uProjection * uModelView * vec4(vertexPosition, 1.0);\n" +
262 " vTexCoord = aTexCoord;\n" +
267 "precision mediump float;\n" +
269 "uniform mediump vec4 uColor;\n" +
270 "uniform sampler2D sTexture;\n" +
271 "varying mediump vec2 vTexCoord;\n" +
273 "uniform float uFactor; // {default:0.2, description:\"drip factor\"} \n" +
276 "float random( vec2 p )\n" +
278 " float q = p.x * 269.5 + p.y * 183.3;\n" +
279 " return fract( sin( q ) * 43758.5453 );\n" +
284 " vec2 uv = vTexCoord.xy;\n" +
286 " float kindaRandom = (texture2D(sTexture, vec2(uv.x,0.5)).r + texture2D(sTexture, vec2(0.5,uv.x)).r) / 2.0;\n" +
288 " //kindaRandom = random( vec2(texture2D(sTexture, vec2(uv.x,0.5)).r, texture2D(sTexture, vec2(0.5,uv.y)).g) );\n" +
290 " uv.y += uFactor * kindaRandom;\n" +
293 " gl_FragColor = texture2D( sTexture, uv ) * uColor;\n" +
300 name: "round window",
302 animateTo: [ ["uRadius", 0.8, "Linear", 0, 3] ],
304 "uniform mediump mat4 uModelView;\n" +
305 "uniform mediump mat4 uProjection;\n" +
306 "attribute mediump vec3 aPosition;\n" +
307 "attribute mediump vec2 aTexCoord;\n" +
308 "varying mediump vec2 vTexCoord;\n" +
310 "void main(void)\n" +
312 " gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\n" +
313 " vTexCoord = aTexCoord;\n" +
315 fragment: "precision lowp float;\n" +
317 "uniform mediump vec4 uColor;\n" +
318 "uniform sampler2D sTexture;\n" +
320 "uniform lowp float uRadius; // {default: 0.2} \n" +
321 "varying mediump vec2 vTexCoord;\n" +
324 " precision lowp float;\n" +
325 " lowp vec2 pos= vec2(vTexCoord.x-0.5,vTexCoord.y-0.5);\n" +
326 " lowp float radius = dot(pos, pos ) ;\n" +
327 " if( radius > (uRadius*uRadius) )\n" +
329 " gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor ;\n" +
335 animateTo: [ ["uPixelFactor", 0.3, "Linear", 0, 3] ],
337 "uniform mediump mat4 uModelView;\n" +
338 "uniform mediump mat4 uProjection;\n" +
339 "attribute mediump vec3 aPosition;\n" +
340 "attribute mediump vec2 aTexCoord;\n" +
341 "varying mediump vec2 vTexCoord;\n" +
342 "uniform mediump vec3 uSize;\n" +
344 "void main(void)\n" +
346 " mediump vec3 vertexPosition = aPosition * uSize;\n" +
347 " gl_Position = uProjection * uModelView * vec4(vertexPosition, 1.0);\n" +
348 " vTexCoord = aTexCoord;\n" +
350 fragment: "precision mediump float;\n" +
352 "uniform mediump vec4 uColor;\n" +
353 "uniform sampler2D sTexture;\n" +
354 "varying mediump vec2 vTexCoord;\n" +
357 "uniform float uPixelFactor; // {default:0.1, min:0.0, max:0.3} \n" +
360 "float smooth(float f) {\n" +
361 " return 32.0*f*f*(0.25*f*f-0.5*f+0.25)+0.5;\n" +
366 " vec2 resolution = vec2(1,1); // uniform vec2 resolution;\n" +
367 " //uPixelFactor = 8.0 + 8.0 * (0.5 + 0.5 * sin(globaltime * 0.25));\n" +
368 " vec2 chunkCoord = floor(vTexCoord.xy / uPixelFactor) * uPixelFactor;\n" +
369 " vec2 locCoord = (vTexCoord.xy - chunkCoord) / uPixelFactor;\n" +
370 " vec4 color = vec4(floor(5.0 * texture2D(sTexture, chunkCoord / resolution.xy).xyz) / 5.0, 1.0);\n" +
371 " float grey = (color.x + color.y + color.z) / 3.0;\n" +
372 " gl_FragColor = color * smooth(locCoord.x) * smooth(locCoord.y);\n" +
378 animateTo: [ ["uThresh", 0.8, "Linear", 0, 3] ],
381 "uniform mediump mat4 uModelView;\n" +
382 "uniform mediump mat4 uProjection;\n" +
383 "attribute mediump vec3 aPosition;\n" +
384 "attribute mediump vec2 aTexCoord;\n" +
385 "varying mediump vec2 vTexCoord;\n" +
386 "uniform mediump vec3 uSize;\n" +
388 "void main(void)\n" +
390 " mediump vec3 vertexPosition = aPosition * uSize;\n" +
391 " gl_Position = uProjection * uModelView * vec4(vertexPosition, 1.0);\n" +
392 " vTexCoord = aTexCoord;\n" +
399 "precision mediump float;\n" +
401 "uniform mediump vec4 uColor;\n" +
402 "uniform sampler2D sTexture;\n" +
403 "varying mediump vec2 vTexCoord;\n" +
406 "float uScale = 2.0; // {default:10.0, description:\"noise texture scaling\"} \n" +
407 "uniform float uThresh; // {default:1.1, description:\"threshold of noise for burn\"} \n" +
409 "float random( vec2 p )\n" +
411 " float q = p.x * 269.5 + p.y * 183.3;\n" +
412 " return fract( sin( q ) * 43758.5453 );\n" +
415 "float noise( vec2 point )\n" +
417 " vec2 p = floor( point );\n" +
418 " vec2 f = fract( point );\n" +
420 " mix( random( p + vec2( 0.0, 0.0 ) ), random( p + vec2( 1.0, 0.0 ) ), f.x ),\n" +
421 " mix( random( p + vec2( 0.0, 1.0 ) ), random( p + vec2( 1.0, 1.0 ) ), f.x ),\n" +
426 "float fractal( vec2 point )\n" +
428 " float sum = 0.0;\n" +
429 " float scale = 0.5;\n" +
430 " for ( int i = 0; i < 5; i++ )\n" +
432 " sum += noise( point ) * scale;\n" +
443 " vec2 point = vTexCoord.xy / uScale;\n" +
444 " //point.x += iGlobalTime * 0.1;\n" +
445 " float noise = fractal( point * 20.0 );\n" +
447 " vec2 uv = vTexCoord.xy; // iResolution.xy;\n" +
448 " //uv.y = 1.0-uv.y;\n" +
449 " gl_FragColor = texture2D(sTexture, uv);\n" +
451 " if(noise < uThresh)\n" +
453 " gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0);\n" +
455 " if(noise < uThresh - 0.05)\n" +
457 " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" +
459 " if(noise < uThresh - 0.1)\n" +
462 " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); // use discard?\n" +
472 animateTo: [ ["uAmplitude", 0.1, "Linear", 0, 3],
473 ["uTime", 6, "Linear", 0, 3] ],
475 "uniform mediump mat4 uModelView;\n" +
476 "uniform mediump mat4 uProjection;\n" +
477 "attribute mediump vec3 aPosition;\n" +
478 "attribute mediump vec2 aTexCoord;\n" +
479 "varying mediump vec2 vTexCoord;\n" +
481 "void main(void)\n" +
483 " gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\n" +
484 " vTexCoord = aTexCoord;\n" +
489 "precision mediump float;\n" +
491 "uniform mediump vec4 uColor;\n" +
492 "uniform sampler2D sTexture;\n" +
493 "varying mediump vec2 vTexCoord;\n" +
495 "uniform float uAmplitude; // {default:0.02, min:0.0, max:1.0}\n" +
496 "uniform float uTime;\n" +
497 "uniform mediump vec4 sTextureRect;\n" +
500 " highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\n" +
501 " highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\n" +
502 " highp float len = length(pos);\n" +
503 " highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \n" +
504 " gl_FragColor = texture2D(sTexture, texCoord) * uColor;\n" +
511 name: "emboss combine",
513 animateTo: [ ["uWeight", [10.0, 10.0, 10.0, 10.0], "Linear", 0, 3] ],
515 "uniform mediump mat4 uModelView;\n" +
516 "uniform mediump mat4 uProjection;\n" +
517 "attribute mediump vec3 aPosition;\n" +
518 "attribute mediump vec2 aTexCoord;\n" +
519 "varying mediump vec2 vTexCoord;\n" +
520 "uniform mediump vec3 uSize;\n" +
522 "void main(void)\n" +
524 " mediump vec3 vertexPosition = aPosition * uSize;\n" +
525 " gl_Position = uProjection * uModelView * vec4(vertexPosition, 1.0);\n" +
526 " vTexCoord = aTexCoord;\n" +
530 fragment: "precision mediump float;\n" +
532 "uniform mediump vec4 uColor;\n" +
533 "uniform sampler2D sTexture;\n" +
534 "varying mediump vec2 vTexCoord;\n" +
536 "const int KERNEL_SIZE = 9;\n" +
538 "uniform vec4 uWeight; // {default: [10,10,10,10] }\n" +
540 "// Gaussian kernel\n" +
541 "float kernel[KERNEL_SIZE];\n" +
543 "float width = 512.0;\n" +
544 "float height = 512.0;\n" +
546 "float step_w = 1.0/width;\n" +
547 "float step_h = 1.0/height;\n" +
549 "vec2 offset[KERNEL_SIZE];\n" +
551 "void main(void)\n" +
553 " precision mediump float;\n" +
555 " vec4 sum = vec4(0.0);\n" +
557 " offset[0] = vec2(-step_w, -step_h);\n" +
558 " offset[1] = vec2(0.0, -step_h);\n" +
559 " offset[2] = vec2(step_w, -step_h);\n" +
561 " offset[3] = vec2(-step_w, 0.0);\n" +
562 " offset[4] = vec2(0.0, 0.0);\n" +
563 " offset[5] = vec2(step_w, 0.0);\n" +
565 " offset[6] = vec2(-step_w, step_h);\n" +
566 " offset[7] = vec2(0.0, step_h);\n" +
567 " offset[8] = vec2(step_w, step_h);\n" +
569 " // guassian blur\n" +
570 " // kernel[0] = 1.0/16.0; kernel[1] = 2.0/16.0; kernel[2] = 1.0/16.0;\n" +
571 " // kernel[3] = 2.0/16.0; kernel[4] = 4.0/16.0; kernel[5] = 2.0/16.0;\n" +
572 " // kernel[6] = 1.0/16.0; kernel[7] = 2.0/16.0; kernel[8] = 1.0/16.0;\n" +
575 " // kernel[0] = 0.0; kernel[1] = 1.0; kernel[2] = 0.0;\n" +
576 " // kernel[3] = 1.0; kernel[4] = -4.0; kernel[5] = 1.0;\n" +
577 " // kernel[6] = 0.0; kernel[7] = 1.0; kernel[8] = 0.0;\n" +
580 " // kernel[0] = -1.0; kernel[1] = -1.0; kernel[2] = -1.0;\n" +
581 " // kernel[3] = -1.0; kernel[4] = +9.0; kernel[5] = -1.0;\n" +
582 " // kernel[6] = -1.0; kernel[7] = -1.0; kernel[8] = -1.0;\n" +
588 " kernel[0] = 2.0; kernel[1] = 0.0; kernel[2] = 0.0;\n" +
589 " kernel[3] = 0.0; kernel[4] = -1.0; kernel[5] = 0.0;\n" +
590 " kernel[6] = 0.0; kernel[7] = 0.0; kernel[8] =-1.0;\n" +
592 " vec4 tmp = texture2D(sTexture, vTexCoord.st + offset[0]);\n" +
593 " sum += tmp * kernel[0];\n" +
595 " tmp = texture2D(sTexture, vTexCoord.st + offset[1]);\n" +
596 " sum += tmp * kernel[1];\n" +
598 " tmp = texture2D(sTexture, vTexCoord.st + offset[2]);\n" +
599 " sum += tmp * kernel[2];\n" +
601 " tmp = texture2D(sTexture, vTexCoord.st + offset[3]);\n" +
602 " sum += tmp * kernel[3];\n" +
604 " tmp = texture2D(sTexture, vTexCoord.st + offset[4]);\n" +
605 " sum += tmp * kernel[4];\n" +
607 " tmp = texture2D(sTexture, vTexCoord.st + offset[5]);\n" +
608 " sum += tmp * kernel[5];\n" +
610 " tmp = texture2D(sTexture, vTexCoord.st + offset[6]);\n" +
611 " sum += tmp * kernel[6];\n" +
613 " tmp = texture2D(sTexture, vTexCoord.st + offset[7]);\n" +
614 " sum += tmp * kernel[7];\n" +
616 " tmp = texture2D(sTexture, vTexCoord.st + offset[8]);\n" +
617 " sum += tmp * kernel[8];\n" +
619 " sum = texture2D(sTexture, vTexCoord.xy) + (sum * uWeight);\n" +
621 " gl_FragColor = sum;\n" +
628 "uniform mediump mat4 uModelView;\n" +
629 "uniform mediump mat4 uProjection;\n" +
630 "uniform mediump vec3 uSize;\n" +
631 "attribute mediump vec3 aPosition;\n" +
632 "attribute mediump vec2 aTexCoord;\n" +
633 "varying mediump vec2 vTexCoord;\n" +
635 "void main(void)\n" +
637 " mediump vec3 vertexPosition = aPosition * uSize;\n" +
638 " gl_Position = uProjection * uModelView * vec4(vertexPosition, 1.0);\n" +
639 " vTexCoord = aTexCoord;\n" +
645 "precision mediump float;\n" +
647 "uniform mediump vec4 uColor;\n" +
648 "uniform sampler2D sTexture;\n" +
649 "varying mediump vec2 vTexCoord;\n" +
652 "#define PI2 6.283184\n" +
655 "#define ST 0.05\n" +
657 "uniform float uFactor; // {default: 0.5, min:0.0, max:1.0}\n" +
659 "vec4 colorat(vec2 uv) {\n" +
660 " return texture2D(sTexture, uv);\n" +
662 "vec4 blur(vec2 uv) { // convolve\n" +
663 " vec4 col = vec4(0.0);\n" +
664 " for(float r0 = 0.0; r0 < 1.0; r0 += ST) {\n" +
665 " float r = r0 * CV;\n" +
666 " for(float a0 = 0.0; a0 < 1.0; a0 += ST) {\n" +
667 " float a = a0 * PI2;\n" +
668 " col += colorat(uv + vec2(cos(a), sin(a)) * r);\n" +
671 " col *= ST * ST;\n" +
678 " vec2 uv = vTexCoord.xy;\n" +
679 " gl_FragColor = blur(uv) * uFactor + ((1.0-uFactor) * texture2D(sTexture, uv));\n" +
683 {name: "image-click",
685 animateTo: [ ["uRadius", 0.3, "Linear", 0, 0.3] ],
687 "uniform mediump mat4 uModelView;\n" +
688 "uniform mediump mat4 uProjection;\n" +
689 "attribute mediump vec3 aPosition;\n" +
690 "attribute mediump vec2 aTexCoord;\n" +
691 "varying mediump vec2 vTexCoord;\n" +
692 "uniform mediump vec3 uSize;\n" +
694 "void main(void)\n" +
696 " mediump vec3 vertexPosition = aPosition * uSize;\n" +
697 " gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\n" +
698 " vTexCoord = aTexCoord;\n" +
703 "precision lowp float;\n" +
705 "uniform mediump vec4 uColor;\n" +
706 "varying mediump vec2 vTexCoord;\n" +
707 "uniform sampler2D sTexture;\n" +
709 "uniform lowp float uRadius; // {default 0.2, min:0, max:0.3, description:\"touch radius and brightness mix\"\n" +
710 "vec2 offset = vec2(0.3,-0.2); // offset from center; for touch point (todo - make uniform)\n" +
714 " precision lowp float;\n" +
715 " lowp vec2 pos= vec2(vTexCoord.x-0.5-offset.x,vTexCoord.y-0.5-offset.y);\n" +
716 " lowp float radius = dot(pos, pos ) ;\n" +
718 " // use sRGB correction to brighten image\n" +
719 " vec4 col = texture2D( sTexture, vTexCoord ) * uColor;\n" +
720 " vec3 mask = vec3(greaterThan(col.rgb, vec3(0.0031308)));\n" +
721 " vec3 o = mix(col.rgb * 12.92, \n" +
722 " pow(col.rgb, vec3(1.0/2.4)) * 1.055 - 0.055, \n" +
725 " vec3 diff = o - col.rgb;\n" +
726 " diff *= uRadius * 3.0;\n" +
727 " o = col.rgb + diff;\n" +
729 " gl_FragColor = vec4(o.r, o.g, o.b, col.a);\n" +
731 " if( radius <= (uRadius*uRadius) )\n" +
733 " gl_FragColor += vec4(0.1);\n" +
740 {name: "iris effect",
742 animateTo: [ ["uRadius", 1.0, "Linear", 0, 0.3],
743 ["uCenter", [0.2, 0.2], "Linear", 0, 0.0],
744 ["uBlendFactor", 1.0, "Linear", 0, 0.0]
748 "uniform mediump mat4 uModelView;\n" +
749 "uniform mediump mat4 uProjection;\n" +
750 "attribute mediump vec3 aPosition;\n" +
751 "attribute mediump vec2 aTexCoord;\n" +
752 "varying mediump vec2 vTexCoord;\n" +
753 "uniform mediump vec3 uSize;\n" +
755 "uniform mediump vec2 uCenter; // { default: [0.7, 0.7] } \n" +
756 "varying mediump vec2 vRelativePosition;\n" +
760 " mediump vec3 vertexPosition = aPosition * uSize;\n" +
761 " mediump vec4 world = uModelView * vec4(vertexPosition,1.0);\n" +
762 " gl_Position = uProjection * world;\n" +
764 " vTexCoord = aTexCoord;\n" +
765 " vRelativePosition = aTexCoord - uCenter;\n" +
772 "uniform mediump vec4 uColor;\n" +
773 "uniform sampler2D sTexture;\n" +
774 "varying mediump vec2 vTexCoord;\n" +
776 "uniform mediump float uRadius; // {default:0.5} \n" +
777 "uniform mediump float uBlendFactor; // {default:2} \n" +
778 "varying mediump vec2 vRelativePosition;\n" +
781 " mediump float delta = (length(vRelativePosition) - uRadius);\n" +
782 " delta = clamp(0.0 - delta * uBlendFactor, 0.0, 1.0);\n" +
783 " gl_FragColor = texture2D(sTexture, vTexCoord) * uColor;\n" +
784 " gl_FragColor.a *= delta;\n" +
789 {name: "mirror effect",
791 animateTo: [ ["uDepth", 0.5, "Linear", 0, 0.0],
792 ["uAlpha", 1.0, "Linear", 0, 0.0]
796 "uniform mediump mat4 uModelView;\n" +
797 "uniform mediump mat4 uProjection;\n" +
798 "attribute mediump vec3 aPosition;\n" +
799 "attribute mediump vec2 aTexCoord;\n" +
800 "varying mediump vec2 vTexCoord;\n" +
801 "uniform mediump vec3 uSize;\n" +
805 " mediump vec3 pos = aPosition * uSize;\n" +
806 " pos.y = pos.y * 3.0;\n" +
807 " mediump vec4 world = uModelView * vec4(pos,1.0);\n" +
808 " gl_Position = uProjection * world;\n" +
809 " vTexCoord = aTexCoord;\n" +
815 "uniform mediump vec4 uColor;\n" +
816 "uniform sampler2D sTexture;\n" +
817 "varying mediump vec2 vTexCoord;\n" +
819 "uniform mediump float uDepth; // {default: 0.3 }\n" +
820 "uniform mediump float uAlpha; // {default: 10.0 }\n" +
823 " if(vTexCoord.y < 1.0 / 3.0)\n" +
825 " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n" +
827 " else if(vTexCoord.y < 2.0 / 3.0)\n" +
829 " gl_FragColor = texture2D(sTexture, vec2(vTexCoord.x, vTexCoord.y * 3.0 - 1.0)) * uColor;\n" +
830 " gl_FragColor.a *= uAlpha;\n" +
834 " highp float darkness = 3.0 - vTexCoord.y * 3.0;\n" +
835 " darkness = (1.0 - 1.0 / uDepth + darkness * 1.0/ uDepth) * 0.65;\n" +
836 " highp vec4 color = texture2D(sTexture, vec2(vTexCoord.x, -vTexCoord.y *3.0 + 3.0)) * uColor;\n" +
837 " color.a *= uAlpha;\n" +
838 " gl_FragColor = color * vec4(darkness, darkness, darkness, darkness);\n" +
843 {name: "square dissolve",
844 animateTo: [ ["uRows", 0.4, "Linear", 0, 0.0],
845 ["uColumns", 0.4, "Linear", 0, 0.0],
846 ["texSize", [100, 100], "Linear", 0, 0.0],
847 ["uStep", 1, "Linear", 0, 3.0]
849 hints: " grid blending",
851 "uniform mediump mat4 uModelView;\n" +
852 "uniform mediump mat4 uProjection;\n" +
853 "attribute mediump vec3 aPosition;\n" +
854 "attribute mediump vec2 aTexCoord;\n" +
855 "varying mediump vec2 vTexCoord;\n" +
857 "void main(void)\n" +
859 " gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\n" +
860 " vTexCoord = aTexCoord;\n" +
866 "uniform mediump vec4 uColor;\n" +
867 "uniform sampler2D sTexture;\n" +
868 "varying mediump vec2 vTexCoord;\n" +
870 "uniform mediump vec2 texSize;\n" +
871 "uniform mediump float uStep;\n" +
872 "uniform mediump float uRows;\n" +
873 "uniform mediump float uColumns;\n" +
874 "uniform sampler2D sTexture;\n" +
877 " mediump vec2 mosaicSize = vec2(1.0 / uRows, 1.0 / uColumns);\n" +
878 " mediump vec2 intXY = vec2(vTexCoord.x * texSize.x, vTexCoord.y * texSize.y);\n" +
879 " mediump vec2 XYMosaic = vec2(floor(intXY.x / mosaicSize.x) * mosaicSize.x, floor(intXY.y / mosaicSize.y) * mosaicSize.y);\n" +
880 " mediump vec2 UVMosaic = vec2(XYMosaic.x /texSize.x, XYMosaic.y / texSize.y);\n" +
881 " mediump vec4 noiseVec = texture2D(sEffect, UVMosaic);\n" +
882 " mediump float intensity = (noiseVec[0] + noiseVec[1] + noiseVec[2] + noiseVec[3]) / 4.0;\n" +
883 " if(intensity < uStep)\n" +
884 " gl_FragColor = vec4(0.1, 0.1, 0.1, 1.0);\n" +
886 " gl_FragColor = texture2D(sTexture, vTexCoord);\n" +
887 " gl_FragColor *= uColor;\n" +
893 hints: " grid blending",
894 animateTo: [ ["uCenter", [0.5, 0.5], "Linear", 0, 0.0],
895 ["uTextureSize", [100, 100], "Linear", 0, 0.0],
896 ["uRadius", 1.0, "Linear", 0, 3.0],
897 ["uAngle", 3.0, "Linear", 0, 3.0]
900 "uniform mediump mat4 uModelView;\n" +
901 "uniform mediump mat4 uProjection;\n" +
902 "attribute mediump vec3 aPosition;\n" +
903 "attribute mediump vec2 aTexCoord;\n" +
904 "varying mediump vec2 vTexCoord;\n" +
905 "uniform mediump vec3 uSize;\n" +
907 "void main(void)\n" +
909 " mediump vec3 vertexPosition = aPosition * uSize;\n" +
910 " gl_Position = uProjection * uModelView * vec4(vertexPosition, 1.0);\n" +
911 " vTexCoord = aTexCoord;\n" +
916 "uniform mediump vec4 uColor;\n" +
917 "uniform sampler2D sTexture;\n" +
918 "uniform mediump vec4 sTextureRect;\n" +
920 "uniform mediump vec2 uTextureSize;\n" +
921 "uniform highp float uRadius;\n" +
922 "uniform highp float uAngle;\n" +
923 "uniform mediump vec2 uCenter;\n" +
924 "varying mediump vec2 vTexCoord;\n" +
927 " highp vec2 textureCenter = (sTextureRect.xy + sTextureRect.zw) * 0.5;\n" +
928 " textureCenter = vTexCoord.st - textureCenter;\n" +
929 " highp float distance = length(textureCenter);\n" +
930 " if (distance >= uRadius)\n" +
932 " highp float percent = (uRadius - distance) / uRadius;\n" +
933 " highp float theta = percent * percent * uAngle * 4.0;\n" +
934 " highp float sinTheta = sin(theta);\n" +
935 " highp float cosTheta = cos(theta);\n" +
936 "// if warp, loose the sign from sin\n" +
937 " bool warp = true;\n" +
940 " textureCenter = vec2( dot( textureCenter, vec2(cosTheta, sinTheta) ),\n" +
941 " dot( textureCenter, vec2(sinTheta, cosTheta) ) );\n" +
945 " textureCenter = vec2( dot( textureCenter, vec2(cosTheta, -sinTheta) ),\n" +
946 " dot( textureCenter, vec2(sinTheta, cosTheta) ) );\n" +
948 " textureCenter += uCenter;\n" +
949 " gl_FragColor = texture2D( sTexture, textureCenter ) * uColor;\n" +
955 {name: "drop shadow",
958 "uniform mediump mat4 uModelView;\n" +
959 "uniform mediump mat4 uProjection;\n" +
960 "attribute mediump vec3 aPosition;\n" +
961 "attribute mediump vec2 aTexCoord;\n" +
962 "varying mediump vec2 vTexCoord;\n" +
963 "uniform mediump vec3 uSize;\n" +
967 " mediump vec3 pos = aPosition * uSize;\n" +
968 " pos.y = pos.y * 1.1; \n" +
969 " pos.x = pos.x * 1.1;\n" +
971 " mediump vec4 world = uModelView * vec4(pos,1.0);\n" +
972 " gl_Position = uProjection * world;\n" +
973 " vTexCoord = aTexCoord;\n" +
980 "uniform mediump vec4 uColor;\n" +
981 "uniform sampler2D sTexture;\n" +
982 "varying mediump vec2 vTexCoord;\n" +
986 " if(vTexCoord.y < 0.05)\n" +
989 " gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n" +
991 " else if(vTexCoord.x < 0.05)\n" +
994 " gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n" +
996 " else if(vTexCoord.y < 0.95 && vTexCoord.x < 0.95)\n" +
998 " gl_FragColor = texture2D(sTexture, vec2(vTexCoord.x/ (1.0/1.1) - 0.05, vTexCoord.y / (1.0/1.0) - 0.05 )) * uColor;\n" +
1002 " if(vTexCoord.y < 0.1 || vTexCoord.x < 0.1)\n" +
1008 " gl_FragColor = vec4(0.2, 0.2, 0.2, 1.0);\n" +
1021 "uniform mediump mat4 uModelView;\n" +
1022 "uniform mediump mat4 uProjection;\n" +
1023 "attribute mediump vec3 aPosition;\n" +
1024 "attribute mediump vec2 aTexCoord;\n" +
1025 "varying mediump vec2 vTexCoord;\n" +
1026 "uniform mediump vec3 uSize; \n" +
1028 "void main(void)\n" +
1030 " mediump vec3 vertexPosition = aPosition * uSize;\n" +
1032 " gl_Position = uProjection * uModelView * vec4(vertexPosition, 1.0);\n" +
1033 " vTexCoord = aTexCoord;\n" +
1039 "precision mediump float;\n" +
1041 "uniform mediump vec4 uColor;\n" +
1042 "varying mediump vec2 vTexCoord;\n" +
1045 "float noise(vec2 pos)\n" +
1047 " return fract( sin( dot(pos*0.001 ,vec2(24.12357, 36.789) ) ) * 12345.123);\n" +
1052 "float smooth_noise(vec2 pos)\n" +
1054 " return ( noise(pos + vec2(1,1)) + noise(pos + vec2(1,1)) + noise(pos + vec2(1,1)) + noise(pos + vec2(1,1)) ) / 16.0\n" +
1055 " + ( noise(pos + vec2(1,0)) + noise(pos + vec2(-1,0)) + noise(pos + vec2(0,1)) + noise(pos + vec2(0,-1)) ) / 8.0\n" +
1056 " + noise(pos) / 4.0;\n" +
1060 "// linear interpolation\n" +
1061 "float interpolate_noise(vec2 pos)\n" +
1063 "float a, b, c, d;\n" +
1065 " a = smooth_noise(floor(pos));\n" +
1066 " b = smooth_noise(vec2(floor(pos.x+1.0), floor(pos.y)));\n" +
1067 " c = smooth_noise(vec2(floor(pos.x), floor(pos.y+1.0)));\n" +
1068 " d = smooth_noise(vec2(floor(pos.x+1.0), floor(pos.y+1.0)));\n" +
1070 " a = mix(a, b, fract(pos.x));\n" +
1071 " b = mix(c, d, fract(pos.x));\n" +
1072 " a = mix(a, b, fract(pos.y));\n" +
1078 "float perlin_noise(vec2 pos)\n" +
1082 " n = interpolate_noise(pos*0.0625)*0.5;\n" +
1083 " n += interpolate_noise(pos*0.125)*0.25;\n" +
1084 " n += interpolate_noise(pos*0.025)*0.225;\n" +
1085 " n += interpolate_noise(pos*0.05)*0.0625;\n" +
1086 " n += interpolate_noise(pos)*0.03125;\n" +
1094 " vec2 pos = vTexCoord.xy;\n" +
1098 " n = perlin_noise(pos);\n" +
1101 " vec2 p = pos; // / iResolution.xy;\n" +
1103 " if(p.y < 0.333) // last row\n" +
1106 " if(p.x < 0.333)\n" +
1107 " c = abs(cos(n*10.0));\n" +
1108 " else if(p.x < 0.666)\n" +
1109 " c = cos(pos.x*0.02 + n*10.0);//*0.5+0.5;\n" +
1113 " c = abs(sin(pos.x+n*5.0)*cos(pos.y+n*5.0));\n" +
1116 " else if(p.y < 0.666) // middle row\n" +
1119 " if(p.x < 0.333)\n" +
1122 " pos += vec2(10.0, 10.0);\n" +
1123 " c = sqrt(pos.x * pos.x + pos.y * pos.y);\n" +
1124 " c = fract(c+n);\n" +
1126 " else if(p.x < 0.666)\n" +
1128 " c = max(1.0 - mod(pos.x*0.5, 80.3+n*4.0)*0.5, 1.0 - mod(pos.y*0.5, 80.3+n*4.0)*0.5);\n" +
1129 " c = max(c, 0.5*max(1.0 - mod(pos.x*0.5+40.0, 80.3+n*4.0)*0.5, 1.0 - mod(pos.y*0.5+40.0, 80.3+n*4.0)*0.5));\n" +
1132 " c = abs(cos(pos.x*0.1 + n*20.0));// mod(pos.x*0.1, cos(pos.x));\n" +
1134 " else // first row\n" +
1136 " if(p.x < 0.333)\n" +
1137 " c = noise(pos);\n" +
1138 " else if(p.x < 0.666)\n" +
1141 " c =max(fract(n*20.0), max(fract(n*5.0), fract(n*10.0)));\n" +
1144 " gl_FragColor = vec4(c, c, c, 1.0);\n" +
1152 // Demo Javascript snippets
1155 var javascriptSources =
1158 name: "XX. Regression tests",
1161 "var test = new Test();\n" +
1162 "test.regression(); // results in developer console (F12)\n" +
1166 name: "10. ImageView",
1168 "var a = new dali.ImageView();\n" +
1170 "var img = imageFromUiBuffer(\"field\");\n" +
1172 "a.setImage(img);\n" +
1174 "a.size = [100,100,1];\n" +
1176 "dali.stage.add(a)\n" +
1180 name: "01. Colored Quad",
1181 source: "var halfQuadSize = 0.5;\n" +
1183 "// using helper function to create property buffer\n" +
1184 "var verts = dali.createPropertyBuffer( {format: [ [\"aPosition\", dali.PropertyType.VECTOR3],\n" +
1185 " [\"aCol\", dali.PropertyType.VECTOR4] ],\n" +
1186 " data: { \"aPosition\": [ [-halfQuadSize, -halfQuadSize, 0.0],\n" +
1187 " [+halfQuadSize, -halfQuadSize, 0.0],\n" +
1188 " [-halfQuadSize, +halfQuadSize, 0.0],\n" +
1189 " [+halfQuadSize, +halfQuadSize, 0.0]\n" +
1191 " \"aCol\": [ [0, 0, 0, 1],\n" +
1192 " [1, 0, 1, 1],\n" +
1193 " [0, 1, 0, 1],\n" +
1200 "var indices = dali.createPropertyBuffer( { format: [ [\"indices\", dali.PropertyType.INTEGER]],\n" +
1201 " data: { \"indices\": [0, 3, 1, 0, 2, 3] } } ) ;\n" +
1203 "var geometry = new dali.Geometry();\n" +
1205 "geometry.addVertexBuffer(verts);\n" +
1206 "geometry.setIndexBuffer(indices);\n" +
1208 "var vertex = \"\" +\n" +
1209 " \"attribute mediump vec3 aPosition;\" +\n" +
1210 " \"attribute mediump vec4 aCol;\" +\n" +
1211 " \"uniform mediump mat4 uMvpMatrix;\" +\n" +
1212 " \"uniform mediump vec3 uSize;\" +\n" +
1213 " \"uniform lowp vec4 uColor;\" +\n" +
1214 " \"varying lowp vec4 vColor;\" +\n" +
1216 " \"void main()\" +\n" +
1218 " \" vColor = aCol * uColor;\" +\n" +
1219 " \" mediump vec4 vertexPosition = vec4(aPosition,1.0);\" +\n" +
1220 " \" vertexPosition.xyz *= uSize;\" +\n" +
1221 " \" gl_Position = uMvpMatrix * vertexPosition;\" +\n" +
1224 "var fragment = \"\" +\n" +
1225 " \"varying lowp vec4 vColor;\" +\n" +
1226 " \"uniform lowp vec4 uColor;\" +\n" +
1228 " \"void main()\" +\n" +
1230 " \" gl_FragColor = vColor * uColor;\" +\n" +
1233 "var shader = new dali.Shader(vertex, fragment, dali.ShaderHints.HINT_NONE);\n" +
1235 "var material = new dali.Material(shader);\n" +
1237 "var renderer = new dali.Renderer(geometry, material);\n" +
1239 "var actor = new dali.Actor();\n" +
1241 "actor.addRenderer(renderer);\n" +
1243 "dali.stage.add(actor);\n" +
1245 "actor.parentOrigin = [0.5, 0.5, 0.0];\n" +
1246 "actor.size = [100,100,1];\n" +
1251 name: "02. Textured Quad",
1252 source: "var halfQuadSize = 0.5;\n" +
1254 "// using helper function to create property buffer\n" +
1255 "var verts = dali.createPropertyBuffer( {format: [ [\"aPosition\", dali.PropertyType.VECTOR3],\n" +
1256 " [\"aTexCoord\", dali.PropertyType.VECTOR2] ],\n" +
1257 " data: { \"aPosition\": [ [-halfQuadSize, -halfQuadSize, 0.0],\n" +
1258 " [+halfQuadSize, -halfQuadSize, 0.0],\n" +
1259 " [-halfQuadSize, +halfQuadSize, 0.0],\n" +
1260 " [+halfQuadSize, +halfQuadSize, 0.0]\n" +
1262 " \"aTexCoord\": [ [0, 0],\n" +
1270 "var indices = dali.createPropertyBuffer( { format: [ [\"indices\", dali.PropertyType.INTEGER]],\n" +
1271 " data: { \"indices\": [0, 3, 1, 0, 2, 3] } } ) ;\n" +
1273 "var geometry = new dali.Geometry();\n" +
1275 "geometry.addVertexBuffer(verts);\n" +
1276 "geometry.setIndexBuffer(indices);\n" +
1278 "var shader = shaderFromUiBuffer(\"pass through texture\");\n" +
1280 "var material = new dali.Material(shader);\n" +
1282 "var image = imageFromUiBuffer(\"ducks\");\n" +
1283 "var sampler = new dali.Sampler();\n" +
1284 "material.addTexture(image, \"sTexture\", sampler);\n" +
1286 "var renderer = new dali.Renderer(geometry, material);\n" +
1288 "var actor = new dali.Actor();\n" +
1290 "actor.addRenderer(renderer);\n" +
1292 "dali.stage.add(actor);\n" +
1294 "actor.parentOrigin = [0.5, 0.5, 0.0];\n" +
1295 "actor.size = [100,100,1];\n" +
1301 name: "03. Shaded Quads",
1302 source: "var halfQuadSize = 0.5;\n" +
1304 "// using helper function to create property buffer\n" +
1305 "var verts = dali.createPropertyBuffer( {format: [ [\"aPosition\", dali.PropertyType.VECTOR3],\n" +
1306 " [\"aTexCoord\", dali.PropertyType.VECTOR2] ],\n" +
1307 " data: { \"aPosition\": [ [-halfQuadSize, -halfQuadSize, 0.0],\n" +
1308 " [+halfQuadSize, -halfQuadSize, 0.0],\n" +
1309 " [-halfQuadSize, +halfQuadSize, 0.0],\n" +
1310 " [+halfQuadSize, +halfQuadSize, 0.0]\n" +
1312 " \"aTexCoord\": [ [0, 0],\n" +
1321 "var indices = dali.createPropertyBuffer( { format: [ [\"indices\", dali.PropertyType.INTEGER]],\n" +
1322 " data: { \"indices\": [0, 3, 1, 0, 2, 3] } } ) ;\n" +
1324 "var geometry = new dali.Geometry();\n" +
1326 "geometry.addVertexBuffer(verts);\n" +
1327 "geometry.setIndexBuffer(indices);\n" +
1330 "// some shader buffers for textured quad\n" +
1331 "var names = [\"adjust brightness\", \"blur\", \"burn\", \"drop shadow\", \"emboss combine\",\n" +
1332 " \"image-click\", \"melt\", \"ripple 2D\", \"mirror effect\", \"iris effect\",\n" +
1333 " \"mosaic\", \"round window\", \"swirl\", \"noise\"];\n" +
1335 "var n = Math.floor(Math.sqrt(names.length));\n" +
1337 "var x = -(0.5*n*100);\n" +
1338 "var y = -(0.5*n*100);\n" +
1340 "for(var i = 0; i < names.length; i++) {\n" +
1341 " var shader = shaderFromUiBuffer(names[i]);\n" +
1343 " var material = new dali.Material(shader);\n" +
1345 " var image = imageFromUiBuffer(\"ducks\");\n" +
1346 " var sampler = new dali.Sampler();\n" +
1347 " material.addTexture(image, \"sTexture\", sampler);\n" +
1349 " var renderer = new dali.Renderer(geometry, material);\n" +
1351 " var actor = new dali.Actor();\n" +
1353 " actor.name = \"actor for shader:\" + names[i];\n" +
1355 " actor.addRenderer(renderer);\n" +
1357 " dali.stage.add(actor);\n" +
1359 " actor.parentOrigin = [0.5, 0.5, 0.0];\n" +
1360 " actor.size = [100,100,1];\n" +
1362 " actor.position = [x,\n" +
1363 " y + (c*110), \n" +
1378 name: "04. Animation",
1379 source: "var halfQuadSize = 0.5;\n" +
1381 "// use helper function to create property buffer\n" +
1382 "var verts = dali.createPropertyBuffer( {format: [ [\"aPosition\", dali.PropertyType.VECTOR3],\n" +
1383 " [\"aTexCoord\", dali.PropertyType.VECTOR2] ],\n" +
1384 " data: { \"aPosition\": [ [-halfQuadSize, -halfQuadSize, 0.0],\n" +
1385 " [+halfQuadSize, -halfQuadSize, 0.0],\n" +
1386 " [-halfQuadSize, +halfQuadSize, 0.0],\n" +
1387 " [+halfQuadSize, +halfQuadSize, 0.0]\n" +
1389 " \"aTexCoord\": [ [0, 0],\n" +
1397 "var indices = dali.createPropertyBuffer( { format: [ [\"indices\", dali.PropertyType.INTEGER]],\n" +
1398 " data: { \"indices\": [0, 3, 1, 0, 2, 3] } } ) ;\n" +
1400 "var geometry = new dali.Geometry();\n" +
1402 "geometry.addVertexBuffer(verts);\n" +
1403 "geometry.setIndexBuffer(indices);\n" +
1405 "var vertex = \"\" + \n" +
1406 " \"// atributes\\n\" + \n" +
1407 " \"attribute mediump vec3 aPosition;\\n\" + \n" +
1408 " \"attribute mediump vec2 aTexCoord;\\n\" + \n" +
1409 " \"// inbuilt\\n\" + \n" +
1410 " \"uniform mediump mat4 uMvpMatrix;\\n\" + \n" +
1411 " \"uniform mediump vec3 uSize;\\n\" + \n" +
1412 " \"uniform lowp vec4 uColor;\\n\" + \n" +
1413 " \"// varying\\n\" + \n" +
1414 " \"varying mediump vec2 vTexCoord;\\n\" + \n" +
1416 " \"void main()\\n\" + \n" +
1418 " \" mediump vec4 vertexPosition = vec4(aPosition, 1.0);\\n\" + \n" +
1419 " \" vertexPosition.xyz *= uSize;\\n\" + \n" +
1420 " \" gl_Position = uMvpMatrix * vertexPosition;\\n\" + \n" +
1421 " \" vTexCoord = aTexCoord;\\n\" + \n" +
1424 "var fragment = \"\" + \n" +
1425 " \"uniform lowp vec4 uColor;\\n\" + \n" +
1426 " \"uniform sampler2D sTexture;\\n\" + \n" +
1427 " \"varying mediump vec2 vTexCoord;\\n\" + \n" +
1429 " \"void main()\\n\" + \n" +
1431 " \" gl_FragColor = texture2D(sTexture, vTexCoord) * uColor;\\n\" + \n" +
1434 "var shader = new dali.Shader(vertex, fragment, dali.ShaderHints.HINT_NONE);\n" +
1436 "var material = new dali.Material(shader);\n" +
1438 "var image = imageFromUiBuffer(\"ducks\");\n" +
1439 "var sampler = new dali.Sampler();\n" +
1440 "material.addTexture(image, \"sTexture\",sampler);\n" +
1442 "var renderer = new dali.Renderer(geometry, material);\n" +
1444 "var actor = new dali.Actor();\n" +
1446 "actor.addRenderer(renderer);\n" +
1448 "dali.stage.add(actor);\n" +
1450 "actor.parentOrigin = [0.5, 0.5, 0.0];\n" +
1451 "actor.size = [100,100,1];\n" +
1454 "var animation = new dali.Animation(9);\n" +
1456 "animation.animateTo(actor, \"orientation\", [0,90,0], \"linear\", 0, 3);\n" +
1457 "animation.animateTo(actor, \"orientation\", [0,0,0], \"linear\", 6, 3);\n" +
1459 "var p = new dali.Path();\n" +
1461 "p.addPoint( [0,0,0] );\n" +
1462 "p.addPoint( [200,200,200] );\n" +
1463 "p.addPoint( [0,0,-200] );\n" +
1464 "p.addPoint( [0,-200,-900] );\n" +
1465 "p.addPoint( [0,0,0] );\n" +
1467 "p.generateControlPoints(0.43);\n" +
1469 "animation.animatePath( actor, p, [1,0,0], \"linear\", 0, 6);\n" +
1471 "//animation.setEndAction(dali.EndAction.Discard);\n" +
1473 "animation.play();\n" +
1479 name: "05. Event driven Animation",
1480 source: "var halfQuadSize = 0.5;\n" +
1482 "// use helper function to create property buffer\n" +
1483 "var verts = dali.createPropertyBuffer( {format: [ [\"aPosition\", dali.PropertyType.VECTOR3],\n" +
1484 " [\"aTexCoord\", dali.PropertyType.VECTOR2] ],\n" +
1485 " data: { \"aPosition\": [ [-halfQuadSize, -halfQuadSize, 0.0],\n" +
1486 " [+halfQuadSize, -halfQuadSize, 0.0],\n" +
1487 " [-halfQuadSize, +halfQuadSize, 0.0],\n" +
1488 " [+halfQuadSize, +halfQuadSize, 0.0]\n" +
1490 " \"aTexCoord\": [ [0, 0],\n" +
1498 "var indices = dali.createPropertyBuffer( { format: [ [\"indices\", dali.PropertyType.INTEGER]],\n" +
1499 " data: { \"indices\": [0, 3, 1, 0, 2, 3] } } ) ;\n" +
1501 "var geometry = new dali.Geometry();\n" +
1503 "geometry.addVertexBuffer(verts);\n" +
1504 "geometry.setIndexBuffer(indices);\n" +
1506 "var vertex = \"\" +\n" +
1507 " \"// atributes\\n\" + \n" +
1508 " \"attribute mediump vec3 aPosition;\\n\" + \n" +
1509 " \"attribute mediump vec2 aTexCoord;\\n\" + \n" +
1510 " \"// inbuilt\\n\" + \n" +
1511 " \"uniform mediump mat4 uMvpMatrix;\\n\" + \n" +
1512 " \"uniform mediump vec3 uSize;\\n\" + \n" +
1513 " \"uniform lowp vec4 uColor;\\n\" + \n" +
1514 " \"// varying\\n\" + \n" +
1515 " \"varying mediump vec2 vTexCoord;\\n\" + \n" +
1517 " \"void main()\\n\" + \n" +
1519 " \" mediump vec4 vertexPosition = vec4(aPosition, 1.0);\\n\" + \n" +
1520 " \" vertexPosition.xyz *= uSize;\\n\" + \n" +
1521 " \" gl_Position = uMvpMatrix * vertexPosition;\\n\" + \n" +
1522 " \" vTexCoord = aTexCoord;\\n\" + \n" +
1525 "var fragment = \"\" +\n" +
1526 " \"uniform lowp vec4 uColor;\\n\" + \n" +
1527 " \"uniform sampler2D sTexture;\\n\" + \n" +
1528 " \"varying mediump vec2 vTexCoord;\\n\" + \n" +
1530 " \"void main()\\n\" + \n" +
1532 " \" gl_FragColor = texture2D(sTexture, vTexCoord) * uColor;\\n\" + \n" +
1535 "var shader = new dali.Shader(vertex, fragment, dali.ShaderHints.HINT_NONE);\n" +
1537 "var material = new dali.Material(shader);\n" +
1539 "var image = imageFromUiBuffer(\"ducks\");\n" +
1540 "var sampler = new dali.Sampler();\n" +
1541 "material.addTexture(image, \"sTexture\", sampler);\n" +
1543 "var renderer = new dali.Renderer(geometry, material);\n" +
1545 "var actor = new dali.Actor();\n" +
1547 "actor.addRenderer(renderer);\n" +
1549 "dali.stage.add(actor);\n" +
1551 "actor.parentOrigin = [0.5, 0.5, 0.0];\n" +
1552 "actor.size = [100,100,1];\n" +
1554 "var actor2 = new dali.Actor();\n" +
1556 "// @todo?? why can I no reuse the same renderer?\n" +
1557 "//actor2.addRenderer(renderer);\n" +
1558 "var renderer2 = new dali.Renderer(geometry, material);\n" +
1559 "actor2.addRenderer(renderer2);\n" +
1561 "dali.stage.add(actor2);\n" +
1563 "actor2.position = [-200,0,0];\n" +
1564 "actor2.parentOrigin = [0.5, 0.5, 0.0];\n" +
1565 "actor2.size = [100,100,1];\n" +
1567 "var animation = new dali.Animation(9);\n" +
1569 "animation.animateTo(actor, \"orientation\", [0,90,0], \"linear\", 0, 3);\n" +
1570 "animation.animateTo(actor, \"orientation\", [0,0,0], \"linear\", 6, 3);\n" +
1572 "var p = new dali.Path();\n" +
1574 "p.addPoint( [0,0,0] );\n" +
1575 "p.addPoint( [200,200,200] );\n" +
1576 "p.addPoint( [0,0,-200] );\n" +
1577 "p.addPoint( [0,-200,-900] );\n" +
1578 "p.addPoint( [0,0,0] );\n" +
1580 "p.generateControlPoints(0.43);\n" +
1582 "animation.animatePath( actor, p, [1,0,0], \"linear\", 0, 6);\n" +
1584 "function onTouched(actor, e) {\n" +
1585 " for(var i = 0; i < e.points.length; i++) {\n" +
1586 " if(e.points[i].state === \"Down\") {\n" +
1587 " console.log(e);\n" +
1588 " animation.play();\n" +
1594 "actor2.connect(\"touched\", onTouched);\n" +
1600 name: "06. Offscreen",
1605 name: "07. DALi toy pseudo dsl",
1610 "addTo(\"stage\",\n" +
1612 " name:\"img\",\n" +
1613 " image:\"ducks\",\n" +
1614 " size:[100,100,1]\n" +
1617 " name:\"img2\",\n" +
1618 " tag:\"listitem\",\n" +
1619 " image:\"field\",\n" +
1620 " position:[100,0,0],\n" +
1621 " size:[100,100,1]\n" +
1624 " name:\"img3\",\n" +
1625 " tag:\"listitem\",\n" +
1626 " image:\"funnyface\",\n" +
1627 " position:[100,0,0],\n" +
1628 " size:[100,100,1]\n" +
1631 " name:\"img4\",\n" +
1632 " tag:\"listitem\",\n" +
1633 " image:\"girl1\",\n" +
1634 " position:[100,0,0],\n" +
1635 " size:[100,100,1]\n" +
1640 "when(\"img\", \"touchedDown\",\n" +
1641 " set(\"sensitive\", true),\n" +
1642 " set(\"size\", to([200,200,200])),\n" +
1643 " set(\"img2\", \"size\", to([200,200,200], 0,3, \"ease_in\")),\n" +
1644 " set(excludeFrom(tagged(\"scrollitem\"), \"myimage\"), path(0,3, \"ease_in\", \"path0\")),\n" +
1645 " endAction(\"Discard\")\n" +
1646 " then(set(\"img4\", \"hide\"),\n" +
1647 " play(\"anAnim\")) );\n" +
1654 function log(errorLog) {
1655 console.log(errorLog);
1658 function consoleAssert( test, message )
1660 // using this rather than inbuild assert
1661 // it lets dali carry on for some reason
1668 function consoleLogErrorEvent(event) {
1670 console.log("Error");
1673 if(event.target.result) {
1674 event.target.result.close();
1679 function consoleLogSuccess(message) {
1682 console.log("Success:" + message);
1688 * Gets embedded base64 images embedded in the HTML file
1690 function getStockImageData(index) {
1692 var name = "testImage" + index;
1693 // need to draw it off screen first? @todo
1694 var c = document.createElement("canvas");
1695 var img = document.getElementById(name);
1696 c.width = img.naturalWidth;
1697 c.height = img.naturalHeight;
1698 var context = c.getContext("2d");
1699 context.drawImage(img, 0, 0 );
1700 var imageData = context.getImageData(0, 0, img.naturalWidth, img.naturalHeight); // <-ImageData
1704 function formatValue(value)
1706 if(typeof(value) === "number") {
1707 if(value === 3.4028234663852886e+38)
1710 } else if(value === Number.MAX_VALUE) {
1712 } else if(value === 2147483647) {
1714 } else if(value === 9223372036854775807) {
1717 return value.toFixed(3);
1725 * Add bootstrap column for single value (not array)
1727 function add1ColElement(elem, value)
1729 var e = document.createElement("div");
1730 e.className = "col-md-3";
1731 e.innerHTML = formatValue(value);
1732 elem.appendChild(e);
1734 e = document.createElement("div");
1735 e.className = "col-md-3";
1737 elem.appendChild(e);
1739 e = document.createElement("div");
1740 e.className = "col-md-3";
1742 elem.appendChild(e);
1744 e = document.createElement("div");
1745 e.className = "col-md-3";
1747 elem.appendChild(e);
1753 * Add bootstrap column for array of 2 value
1755 function add2ColElement(elem, value)
1757 var e = document.createElement("div");
1758 e.className = "col-md-3";
1759 e.innerHTML = formatValue(value[0]);
1760 elem.appendChild(e);
1762 e = document.createElement("div");
1763 e.className = "col-md-3";
1764 e.innerHTML = formatValue(value[1]);
1765 elem.appendChild(e);
1767 e = document.createElement("div");
1768 e.className = "col-md-3";
1770 elem.appendChild(e);
1772 e = document.createElement("div");
1773 e.className = "col-md-3";
1775 elem.appendChild(e);
1781 * Add bootstrap table cell for array of 3 value
1783 function add3ColElement(elem, value)
1785 var e = document.createElement("div");
1786 e.className = "col-md-3";
1787 e.innerHTML = formatValue(value[0]);
1788 elem.appendChild(e);
1790 e = document.createElement("div");
1791 e.className = "col-md-3";
1792 e.innerHTML = formatValue(value[1]);
1793 elem.appendChild(e);
1795 e = document.createElement("div");
1796 e.className = "col-md-3";
1797 e.innerHTML = formatValue(value[2]);
1798 elem.appendChild(e);
1800 e = document.createElement("div");
1801 e.className = "col-md-3";
1803 elem.appendChild(e);
1808 * Add bootstrap table cell for array of 4 value
1810 function add4ColElement(elem, value)
1812 var e = document.createElement("div");
1813 e.className = "col-md-3";
1814 e.innerHTML = formatValue(value[0]);
1815 elem.appendChild(e);
1817 e = document.createElement("div");
1818 e.className = "col-md-3";
1819 e.innerHTML = formatValue(value[1]);
1820 elem.appendChild(e);
1822 e = document.createElement("div");
1823 e.className = "col-md-3";
1824 e.innerHTML = formatValue(value[2]);
1825 elem.appendChild(e);
1827 e = document.createElement("div");
1828 e.className = "col-md-3";
1829 e.innerHTML = formatValue(value[3]);
1830 elem.appendChild(e);
1835 * Add a bootstrap table cell for property 'name' for an actor
1837 function createElementForActorProperty(actor, name) {
1839 var elem = document.createElement("div");
1841 var value = actor[name];
1842 var type = typeof value;
1844 if(name === "maximumSize") {
1848 if(type === "string" || type === "number" || type === "boolean") {
1849 elem.className = "row";
1850 add1ColElement(elem, value);
1851 } else if(value === undefined) {
1852 elem.className = "row";
1853 add1ColElement(elem, "???undefined???");
1856 var length = value.length;
1858 elem.className = "row";
1859 add2ColElement(elem, value);
1860 } else if(length === 3) {
1861 elem.className = "row";
1862 add3ColElement(elem, value);
1863 } else if(length === 4) {
1864 elem.className = "row";
1865 add4ColElement(elem, value);
1866 } else if(length === 9) {
1867 r = document.createElement("div");
1868 r.className = "row";
1869 add3ColElement(r, value.slice(0, 3));
1870 elem.appendChild(r);
1872 r = document.createElement("div");
1873 r.className = "row";
1874 add3ColElement(r, value.slice(3, 6));
1875 elem.appendChild(r);
1877 r = document.createElement("div");
1878 r.className = "row";
1879 add3ColElement(r, value.slice(6, 9));
1880 elem.appendChild(r);
1881 } else if(length === 16) {
1882 r = document.createElement("div");
1883 r.className = "row";
1884 add4ColElement(r, value.slice(0, 4));
1885 elem.appendChild(r);
1887 r = document.createElement("div");
1888 r.className = "row";
1889 add4ColElement(r, value.slice(4, 8));
1890 elem.appendChild(r);
1892 r = document.createElement("div");
1893 r.className = "row";
1894 add4ColElement(r, value.slice(8, 12));
1895 elem.appendChild(r);
1897 r = document.createElement("div");
1898 r.className = "row";
1899 add4ColElement(r, value.slice(12, 16));
1900 elem.appendChild(r);
1908 * Adds a bootstrap table to show the actor properties
1910 function onActorSelected(actor) {
1920 // recreate property tab
1922 var elem = document.getElementById("selected");
1924 removeAllChildren(elem);
1927 // setup property view
1930 actorId = actor.getId();
1932 var p = document.createElement("div");
1933 p.innerHTML = "<h3><b>" + actor.name + "</b> [<b>" + actorId + "</b>] (<b>" + actor.position + "</b>)</h3>";
1934 elem.appendChild(p);
1936 var parent = actor.getParent();
1938 p = document.createElement("div");
1941 "(Parent: <b>" + parent.name + "</b> [<b>" + parent.getId() + "</b>] (<b>" + parent.position + "</b>)" +
1942 " Anchored: <b>" + actor.anchorPoint + "</b>" +
1943 " ParentOrigin: <b>" + actor.parentOrigin + "</b> )" +
1945 elem.appendChild(p);
1948 if( actorId in actorIdToShaderSet &&
1949 "shaderEffect" in actorIdToShaderSet[actorId]) { // if has compiled
1950 var shaderOptions = actorIdToShaderSet[actorId];
1951 var uniforms = dali.sourceUniformMetaData(shaderOptions.vertex);
1952 uniforms = uniforms.concat(dali.sourceUniformMetaData(shaderOptions.fragment));
1954 var shader = getShader(actor);
1956 if(uniforms.length) {
1957 gridBlock = document.createElement("div");
1958 gridBlock.className = "row";
1960 nameBlock = document.createElement("div");
1961 nameBlock.className = "col-md-5";
1962 nameBlock.innerHTML = "<u>Shader Uniforms:</u>";
1963 gridBlock.appendChild(nameBlock);
1965 valueBlock = document.createElement("div");
1966 valueBlock.className = "col-md-7";
1967 valueBlock.innerHTML = "";
1968 gridBlock.appendChild(valueBlock);
1970 elem.appendChild(gridBlock);
1972 for(i = 0; i < uniforms.length; i++) {
1973 var type = uniforms[i].type;
1974 name = uniforms[i].name;
1975 gridBlock = document.createElement("div");
1976 gridBlock.className = "row";
1978 nameBlock = document.createElement("div");
1979 nameBlock.className = "col-md-5";
1980 nameBlock.innerHTML = type + " " + name + "<i> (Animatable) </i>";
1982 gridBlock.appendChild(nameBlock);
1984 valueBlock = document.createElement("div");
1985 valueBlock.className = "col-md-7";
1986 valueBlock.innerHTML = shader[ name ];
1987 gridBlock.appendChild(valueBlock);
1989 elem.appendChild(gridBlock);
1996 // getproperties returns std::vector<string>
1997 var props = actor.getProperties();
1999 gridBlock = document.createElement("div");
2000 gridBlock.className = "row";
2002 nameBlock = document.createElement("div");
2003 nameBlock.className = "col-md-5";
2004 nameBlock.innerHTML = "<u>Properties:</ul>";
2005 gridBlock.appendChild(nameBlock);
2007 valueBlock = document.createElement("div");
2008 valueBlock.className = "col-md-7";
2009 valueBlock.innerHTML = "";
2010 gridBlock.appendChild(valueBlock);
2012 elem.appendChild(gridBlock);
2015 for (i = 0; i < props.size(); i++) {
2016 name = props.get(i);
2018 gridBlock = document.createElement("div");
2019 gridBlock.className = "row";
2021 var animatable = actor.isPropertyAnimatable(actor.getPropertyIndex(name));
2023 nameBlock = document.createElement("div");
2024 nameBlock.className = "col-md-5";
2026 nameBlock.innerHTML = "'" + name + "'" + "<i> (animatable)</i>";
2028 nameBlock.innerHTML = "'" + name + "'";
2030 gridBlock.appendChild(nameBlock);
2032 valueBlock = document.createElement("div");
2033 valueBlock.className = "col-md-7";
2035 valueBlock.appendChild( createElementForActorProperty(actor, name) );
2037 gridBlock.appendChild(valueBlock);
2039 elem.appendChild(gridBlock);
2049 * creates page element and set namesValues array
2051 function createElement(elementName, namesValues) {
2053 var e = document.createElement(elementName);
2054 for(var name in namesValues) {
2055 e[name] = namesValues[name];
2061 * create element with innerHTML
2063 function createElementInnerHTML(elementName, innerHTML) {
2065 return createElement(elementName, {"innerHTML": innerHTML});
2069 * remove all the children from the element
2071 function removeAllChildren(elem) {
2073 var count = elem.children.length;
2074 for (var i = 0; i < count; i++) {
2075 elem.removeChild(elem.children[0]);
2082 function onChangeSetDataChanged(e) {
2083 e.currentTarget["data-changed"] = true;
2087 * creates a document input element [ ]
2089 function inputElem(type, propObject, property, val, arrayIndex) {
2091 var e = document.createElement("input");
2093 // for number then step of any means it can be a real number not just integer
2096 e.className = "form-control";
2097 e["data-value"] = val;
2098 e["data-arrayIndex"] = arrayIndex;
2099 e["data-changed"] = false;
2100 e.addEventListener("changed", onChangeSetDataChanged);
2105 * creates an input 2 element [ , ]
2107 function inputElem2(type, propObject, property, val, startIndex) {
2109 var d = document.createElement("div");
2110 var a = inputElem("number", propObject, property, val[startIndex], startIndex);
2111 a.className = "col-md-3";
2113 a = inputElem("number", propObject, property, val[startIndex + 1], startIndex + 1);
2114 a.className = "col-md-3";
2116 a.className = "col-md-3";
2118 a = createElement("div");
2119 a.className = "col-md-3";
2125 * creates an input 3 element [ , , ]
2127 function inputElem3(type, propObject, property, val, startIndex) {
2129 var d = document.createElement("div");
2130 var a = inputElem("number", propObject, property, val[startIndex], startIndex);
2131 a.className = "col-md-3";
2133 a = inputElem("number", propObject, property, val[startIndex + 1], startIndex + 1);
2134 a.className = "col-md-3";
2136 a = inputElem("number", propObject, property, val[startIndex + 2], startIndex + 2);
2137 a.className = "col-md-3";
2139 a = createElement("div");
2140 a.className = "col-md-3";
2146 * creates an input 4 element [ , , , ]
2148 function inputElem4(type, propObject, property, val, startIndex) {
2150 var d = document.createElement("div");
2151 var a = inputElem("number", propObject, property, val[startIndex], startIndex);
2152 a.className = "col-md-3";
2154 a = inputElem("number", propObject, property, val[startIndex + 1], startIndex + 1);
2155 a.className = "col-md-3";
2157 a = inputElem("number", propObject, property, val[startIndex + 2], startIndex + 2);
2158 a.className = "col-md-3";
2160 a = inputElem("number", propObject, property, val[startIndex + 3], startIndex + 3);
2161 a.className = "col-md-3";
2167 * creates a document input element for an actor/shader's property
2169 function createInputElement(actorShader, propertyName, value) {
2170 // always4 ja columns
2172 var type = typeof value;
2175 if(type === "string") {
2176 e = inputElem("string", actorShader, propertyName, value);
2177 } else if(type === "number") {
2178 e = inputElem("number", actorShader, propertyName, value);
2179 } else if(type === "boolean") {
2180 e = inputElem("checkbox", actorShader, propertyName, value);
2182 var length = value.length;
2184 e = inputElem2("number", actorShader, propertyName, value, 0);
2185 } else if(length === 3) {
2186 e = inputElem3("number", actorShader, propertyName, value, 0);
2187 } else if(length === 4) {
2188 e = inputElem4("number", actorShader, propertyName, value, 0);
2189 } else if(length === 9) {
2190 e = createElement("div");
2191 e.appendChild( inputElem3("number", actorShader, propertyName, value, 0) );
2192 e.appendChild( inputElem3("number", actorShader, propertyName, value, 3) );
2193 e.appendChild( inputElem3("number", actorShader, propertyName, value, 6) );
2194 } else if(length === 16) {
2195 e = createElement("div");
2196 e.appendChild( inputElem4("number", actorShader, propertyName, value, 0) );
2197 e.appendChild( inputElem4("number", actorShader, propertyName, value, 4) );
2198 e.appendChild( inputElem4("number", actorShader, propertyName, value, 8) );
2199 e.appendChild( inputElem4("number", actorShader, propertyName, value, 12) );
2201 throw "should not happen";
2209 * Selects an actor by id
2211 function selectActor(id) { // from html tree
2214 eventHandler.selectActor(null);
2216 var root = dali.stage.getRootLayer();
2217 var actor = root.findChildById(id);
2219 eventHandler.selectActor(actor);
2221 root.delete(); // wrapper
2226 * Rebuild the document actor property display
2228 function rebuildTree() {
2231 var e = document.getElementById("tree");
2232 var count = e.children.length;
2233 for (var i = 0; i < count; i++) {
2234 e.removeChild(e.children[0]);
2237 // <ul class="nav nav-list">
2238 // <li><label class="tree-toggler nav-header">Header 1</label>
2240 var root = dali.stage.getRootLayer() ; // dali.stage.rootRotationActor;
2242 var recurse = function(parentElement, actor) {
2243 var children = actor.getChildren();
2247 for (var i = 0; i < children.length; ++i) {
2248 var child = children[i];
2250 if (child.name[0] !== "*") {
2252 var li = document.createElement("li");
2254 var a = document.createElement("a");
2255 a.href = "javascript:selectActor(" + child.getId() + ");";
2256 a.text = "(" + child.getId() + ") '" + child.name + "'";
2260 ul = document.createElement("ul");
2261 ul.className = "nav-tree";
2268 // finish with the child wrapper
2274 parentElement.appendChild(ul);
2281 root.delete(); // wrapper
2286 * Eventhandler class; Touch handling abstraction.
2288 * handling functions can be registered to get touch events
2290 function EventHandler() {
2295 this.mouse_buttons = 0;
2296 this.mouseDownPosition = [0, 0, 0];
2299 this.touchedActor = null; // set if actor is touched (left click)
2301 // this.selectedActor = null;
2302 this.mouseIsDown = 0;
2307 // handlers; use register("MouseDragStart", func); where for func(eventHandler)
2308 this.handlersMouseMove = []; // valid; touchedActor(can be null), mouseX, mouseY
2309 this.handlersMouseDrag = []; // valid; touchedActor(can be null), dragDx, dragDy
2310 this.handlersSelect = []; // valid; touchedActor(can be null), dragDx, dragDy
2311 this.handlersDeselect = []; // valid; touchedActor(can be null), dragDx, dragDy
2315 * Register a handler, ie register("MouseMove", moveFunc)
2317 EventHandler.prototype.register = function(name, handler) {
2319 var handlers = this["handlers" + name];
2320 if (!(handler in handlers)) {
2321 handlers.push(handler);
2326 * Unregister a handler
2328 EventHandler.prototype.unRegister = function(name, handler) {
2330 var handlers = this["handlers" + name];
2331 var index = handlers.index(handler);
2333 handlers.splice(index, 1);
2338 * update the mouse state
2340 EventHandler.prototype.updateMouseState = function(canvas, e) {
2342 var rect = canvas.getBoundingClientRect(); // in window
2343 this.mouseX = e.clientX - rect.left; // from window
2344 this.mouseY = e.clientY - (rect.bottom - rect.height);
2345 this.mouse_buttons = e.button; // 0|1|2 left|middle|rigtht
2351 EventHandler.prototype.mouseDown = function(canvas, e) {
2353 this.mouseIsDown = 1;
2354 this.updateMouseState(canvas, e);
2355 this.mouseDownPosition = [this.mouseX, this.mouseY, 0];
2356 var hitActor = dali.hitTest(this.mouseX, this.mouseY);
2359 if (this.touchedActor) {
2360 tid = this.touchedActor.getId();
2363 hid = hitActor.getId();
2368 this.handleEvent(this.handlersDeselect);
2369 this.touchedActor = null;
2373 this.selectActor(hitActor);
2375 // dali is 0==down,1==up,2==motion
2376 dali.sendMouseEvent(this.mouseX, this.mouseY, 0);
2377 // console.log("mouseDown", this.mouseX, this.mouseY, this.mouseIsDown, 0);
2381 * set the touchedActor
2383 EventHandler.prototype.selectActor = function(hitActor) {
2386 this.handleEvent(this.handlersDeselect);
2388 var layer = dali.stage.getRootLayer();
2389 if (hitActor.getId() === dali.stage.rootRotationActor.getId()) {
2390 // dont select our rotation actor
2393 // dont select the root layer
2394 if (hitActor.getId() === layer.getId()) {
2398 layer.delete(); // wrapper
2400 this.touchedActor = hitActor;
2402 if(this.touchedActor) {
2403 this.handleEvent(this.handlersDeselect);
2405 this.touchedActor = null;
2408 this.handleEvent(this.handlersSelect);
2412 * canvas mouse move handler
2414 EventHandler.prototype.mouseMove = function(canvas, e) {
2416 this.updateMouseState(canvas, e);
2418 if(this.mouseIsDown) {
2419 // if (this.touchedActor) {
2420 this.dragDx = (this.mouseX - this.mouseDownPosition[0]);
2421 this.dragDy = (this.mouseY - this.mouseDownPosition[1]);
2424 this.handleEvent(this.handlersMouseDrag);
2427 this.handleEvent(this.handlersMouseMove);
2429 // dali is 0==down,1==up,2==motion
2430 dali.sendMouseEvent(this.mouseX, this.mouseY, 2);
2431 // console.log("mouseMove", this.mouseX, this.mouseY, this.mouseIsDown, 2);
2435 * canvas mouse up handler
2437 EventHandler.prototype.mouseUp = function(canvas, e) {
2439 this.mouseIsDown = 0;
2440 this.updateMouseState(canvas, e);
2441 this.dragDx = (this.mouseX - this.mouseDownPosition[0]);
2442 this.dragDy = (this.mouseY - this.mouseDownPosition[1]);
2444 // dali is 0==down,1==up,2==motion
2445 dali.sendMouseEvent(this.mouseX, this.mouseY, 1);
2446 // console.log("mouseUp", this.mouseX, this.mouseY, this.mouseIsDown, 1);
2452 * canvas mouse wheel handler
2454 EventHandler.prototype.mouseWheel = function(canvas, e) {
2456 // multiples of +120 for up, -120 for down
2457 var clicks = e.wheelDelta / 120;
2459 var taskList = dali.stage.getRenderTaskList();
2460 var task = taskList.getTask(0);
2461 var cameraActor = task.getCameraActor();
2463 var fov = cameraActor.fieldOfView;
2464 cameraActor.fieldOfView = fov + (clicks / 180.0 * Math.PI);
2468 cameraActor.delete();
2469 // console.log(e.wheelDelta);
2473 * call given handlers
2475 EventHandler.prototype.handleEvent = function(handlers) {
2476 for (var i = 0, len = handlers.length; i < len; i++) {
2477 var handler = handlers[i];
2483 * canvas key down handler
2485 EventHandler.prototype.keyDown = function(canvas, e) {
2486 this.metaKey = e.metaKey;
2487 this.altKey = e.altKey;
2488 this.ctrlKey = e.ctrlKey;
2489 this.shiftKey = e.shiftKey;
2493 * canvas key up handler
2495 EventHandler.prototype.keyUp = function(canvas, e) {
2496 this.metaKey = e.metaKey;
2497 this.altKey = e.altKey;
2498 this.ctrlKey = e.ctrlKey;
2499 this.shiftKey = e.shiftKey;
2503 // Actor list helpers; applies function to all actors in the list
2506 doAll: function(actors, func) {
2507 for (var i = 0, len = actors.length; i < len; i++) {
2511 show: function(actors, visible) {
2512 this.doAll(actors, function(actor) {
2513 actor.visible = visible;
2516 delete: function(actors, visible) {
2517 this.doAll(actors, function(actor) {
2518 actor.delete = visible;
2521 add: function(actors, actor) {
2522 this.doAll(actors, function(a) {
2526 remove: function(actors, actor) {
2527 this.doAll(actors, function(a) {
2531 contains: function(actors, actor) {
2535 for (var i = 0, len = actors.length; i < len; i++) {
2536 if (actors[i].getId() == actor.getId()) {
2546 // Class for depth adornments
2548 function DepthAdornment() {
2550 this.attachedTo = null;
2551 this.actors = []; // array of 5 square attaced around and to back of actor to show depth
2553 for (var i = 0; i < 5; i++) { //
2555 var a = dali.createSolidColorActor([0.5, 0.5, 0.5, 1],
2556 false, [0, 0, 0, 1],
2558 a.name = "**_dali_adornment";
2559 this.actors.push(a);
2562 ActorList.show(this.actors, false);
2565 DepthAdornment.prototype.delete = function() {
2567 ActorList.delete(this.actors);
2571 DepthAdornment.prototype.attach = function(actor) {
2573 var newActor = true;
2574 if (this.attachedTo) {
2575 newActor = (actor.getId() !== this.attachedTo.getId());
2578 if (actor && newActor) {
2579 this.unattach(this.attachedTo);
2581 if(!ActorList.contains(this.actors, actor)) {
2582 this.__positionActors(actor);
2584 ActorList.add(this.actors, actor);
2586 ActorList.show(this.actors, true);
2588 this.attachedTo = actor;
2593 DepthAdornment.prototype.unattach = function() {
2595 if (this.attachedTo) {
2596 ActorList.show(this.actors, false);
2597 ActorList.remove(this.actors, this.attachedTo);
2598 this.attachedTo = null;
2602 DepthAdornment.prototype.reposition = function() {
2604 if (this.attachedTo) {
2605 this.__positionActors(this.attachedTo);
2609 DepthAdornment.prototype.__positionActors = function(actor) {
2612 s[2] = Math.max(s[2], 20); // pretend the actor is at least 20
2613 var halfw = s[0] / 2;
2614 var halfh = s[1] / 2;
2615 var halfd = s[2] / 2;
2617 this.actors[0].position = [-halfw, 0, -halfd];
2618 this.actors[0].orientation = [0, -90, 0];
2619 this.actors[0].size = [s[2], s[1], 1];
2621 this.actors[1].position = [+halfw, 0, -halfd];
2622 this.actors[1].orientation = [0, 90, 0];
2623 this.actors[1].size = [s[2], s[1], 1];
2625 this.actors[2].position = [0, -halfh, -halfd];
2626 this.actors[2].orientation = [90, 0, 0];
2627 this.actors[2].size = [s[0], s[2], 1];
2629 this.actors[3].position = [0, halfh, -halfd];
2630 this.actors[3].orientation = [-90, 0, 0];
2631 this.actors[3].size = [s[0], s[2], 1];
2633 // this.actors[4].position = [0, 0, -s[2]];
2634 // this.actors[4].orientation = [0, 0, 0];
2635 // this.actors[4].size = s;
2642 * Class for cursor adornments when displaying selected actor
2644 function Cursors() {
2648 this.attachedTo = null;
2649 this.resizers = []; // array of 8 small square resizers
2650 this.lines = []; // array of 4 bounding box lines
2651 this.lineColor = [0.5, 0.5, 0.5, 1];
2652 this.resizerColor = [0, 0, 0, 1];
2653 this.depthAdornments = new DepthAdornment();
2655 for (i = 0; i < 4; i++) { // lines
2656 a = dali.createSolidColorActor(this.lineColor, false, [0, 0, 0, 1], 0);
2657 a.name = "**_dali_adornment";
2661 for(i = 0; i < 8; i++) { // squares
2662 a = dali.createSolidColorActor(this.resizerColor, true, [1, 1, 1, 1], 1);
2663 a.name = "**_dali_adornment";
2664 this.resizers.push(a);
2665 this.resizers[i].size = [10, 10, 1];
2668 ActorList.show(this.lines, false);
2669 ActorList.show(this.resizers, false);
2674 Cursors.prototype.attach = function(actor) {
2678 if (this.attachedTo) {
2679 this.unattach(this.attachedTo);
2682 this.__positionActors(actor);
2684 ActorList.add(this.lines, actor);
2685 ActorList.add(this.resizers, actor);
2687 ActorList.show(this.lines, true);
2688 ActorList.show(this.resizers, true);
2690 this.depthAdornments.attach(actor);
2692 this.attachedTo = actor;
2696 Cursors.prototype.unattach = function(actor) {
2698 if (actor && this.attachedTo) {
2699 ActorList.show(this.lines, false);
2700 ActorList.show(this.resizers, false);
2702 ActorList.remove(this.lines, actor);
2703 ActorList.remove(this.resizers, actor);
2705 this.depthAdornments.unattach(actor);
2707 this.attachedTo = null;
2711 Cursors.prototype.reposition = function() {
2713 if (this.attachedTo) {
2714 this.__positionActors(this.attachedTo);
2715 this.depthAdornments.reposition();
2719 Cursors.prototype.__positionActors = function(actor) {
2722 var p = actor.position;
2723 var halfw = s[0] / 2;
2724 var halfh = s[1] / 2;
2726 this.lines[0].position = [0 - halfw, 0, 0];
2727 this.lines[0].size = [1, halfh * 2, 1];
2729 this.lines[1].position = [0, 0 - halfh, 0];
2730 this.lines[1].size = [halfw * 2, 1, 1];
2732 this.lines[2].position = [0 + halfw, 0, 0];
2733 this.lines[2].size = [1, halfh * 2, 1];
2735 this.lines[3].position = [0, 0 + halfh, 0];
2736 this.lines[3].size = [halfw * 2, 1, 1];
2738 // drag functions presumes order here is clockwise from top left
2740 this.resizers[0].position = [-halfw, +halfh, offsetZ];
2741 this.resizers[1].position = [0, +halfh, offsetZ];
2742 this.resizers[2].position = [+halfw, +halfh, offsetZ];
2743 this.resizers[3].position = [+halfw, 0, offsetZ];
2745 this.resizers[4].position = [+halfw, -halfh, offsetZ];
2746 this.resizers[5].position = [0, -halfh, offsetZ];
2747 this.resizers[6].position = [-halfw, -halfh, offsetZ];
2748 this.resizers[7].position = [-halfw, 0, offsetZ];
2753 function App(theEventHandler) {
2756 this.rootRotation = [0, 0, 0]; // in degrees
2757 this.cursors = new Cursors();
2758 // ActorWrapper CreateSolidColorActor(const Vector4 & color, bool border,
2759 // const Vector4 & borderColor,
2760 // const unsigned int borderSize)
2761 this.rootLayerIndicator = dali.createSolidColorActor(
2765 this.rootLayerIndicator.name = "**_dali_adornment";
2767 this.rootLayerIndicator.parentOrigin = [0.5, 0.5, 0.5];
2768 this.rootLayerIndicator.anchorPoint = [0.5, 0.5, 0.5];
2769 this.rootLayerIndicator.size = [250, 250, 1];
2770 this.rootLayerIndicator.position = [0, 0, 0];
2772 this.selectedActor = null;
2773 this.selectedActorSize = [0, 0, 0];
2774 this.selectedActorPosition = [0, 0, 0];
2776 this.__handleMouseDrag = function(eventHandler) {
2777 if (self.resizing) {
2778 if (self.selectedActor) {
2779 self.selectedActor.size = [
2780 self.selectedActorSize[0] + eventHandler.dragDx,
2781 self.selectedActorSize[1] + eventHandler.dragDy,
2782 self.selectedActorSize[2]
2784 self.cursors.reposition();
2787 // move the touched actor
2788 if (self.selectedActor) {
2789 if (eventHandler.mouse_buttons === 0) {
2790 self.selectedActor.position = [
2791 self.selectedActorPosition[0] + eventHandler.dragDx,
2792 self.selectedActorPosition[1] + eventHandler.dragDy,
2793 self.selectedActorPosition[2]
2795 } else if (eventHandler.mouse_buttons === 2) {
2796 self.selectedActor.position = [
2797 self.selectedActorPosition[0],
2798 self.selectedActorPosition[1], -(self.selectedActorPosition[2] + eventHandler.dragDy)
2804 // rotate on middle button
2805 if (eventHandler.mouse_buttons === 1) {
2806 self.rootRotation = [eventHandler.mouseDownPosition[1] - eventHandler.mouseY, -(eventHandler.mouseDownPosition[0] - eventHandler.mouseX),
2807 self.rootRotation[2]
2809 dali.stage.rootRotationActor.orientation = self.rootRotation;
2814 this.addActor = function(actor) {
2815 if (eventHandler.touchedActor) {
2816 eventHandler.touchedActor.add(actor);
2817 actor.position = [20,20,0]; // offset so new actor isnt right behind touched
2819 dali.stage.add(actor);
2826 this.__handleSelect = function(eventHandler) {
2827 if (eventHandler.mouse_buttons === 0) { // left click only selects actor
2828 var actor = eventHandler.touchedActor;
2829 self.selectedActor = actor;
2831 self.selectedActorPosition = actor.position;
2832 self.selectedActorSize = actor.size;
2834 self.selectedActorPosition = [0, 0, 0];
2835 self.selectedActorSize = [1, 1, 1];
2837 self.cursors.attach(self.selectedActor);
2838 dali.stage.add(self.rootLayerIndicator);
2839 onActorSelected(actor);
2843 this.__handleDeselect = function(eventHandler) {
2844 self.cursors.unattach(self.selectedActor);
2845 dali.stage.remove(self.rootLayerIndicator);
2849 eventHandler.register("MouseDrag", this.__handleMouseDrag);
2850 eventHandler.register("Select", this.__handleSelect);
2851 eventHandler.register("Deselect", this.__handleDeselect);
2854 // Monkey patch the stage object (to add to root object not the root layer for rotations)
2856 dali.stage.rootRotationActor = new dali.Actor();
2857 dali.stage.rootRotationActor.parentOrigin = [0.5, 0.5, 0.5];
2858 dali.stage.rootRotationActor.anchorPoint = [0.5, 0.5, 0.5];
2859 dali.stage.rootRotationActor.name = "app rotation actor";
2860 dali.stage.rootRotationActor.size = [100,100,1];
2861 dali.stage.add(dali.stage.rootRotationActor);
2863 dali.stage.add = function(actor) {
2864 dali.stage.rootRotationActor.add(actor);
2867 dali.stage.remove = function(actor) {
2868 dali.stage.rootRotationActor.remove(actor);
2877 var eventHandler = new EventHandler();
2878 var app = new App(eventHandler);
2879 var canvas = document.getElementById("canvas");
2881 function mouseDown(e) {
2883 eventHandler.mouseDown(canvas, e);
2886 function mouseUp(e) {
2888 eventHandler.mouseUp(canvas, e);
2891 function mouseMove(e) {
2893 eventHandler.mouseMove(canvas, e);
2896 function mouseWheel(e) {
2898 eventHandler.mouseWheel(canvas, e);
2901 function keyDown(e) {
2903 eventHandler.keyDown(canvas, e);
2908 eventHandler.keyUp(canvas, e);
2911 canvas.onmousemove = mouseMove;
2912 canvas.onmousedown = mouseDown;
2913 canvas.onmouseup = mouseUp;
2914 canvas.onwheel = mouseWheel;
2916 canvas.onkeydown = keyDown;
2917 canvas.onkeyup = keyUp;
2923 function runRandomAnimation(actor) {
2925 var a = new dali.Animation(0);
2928 a.animateTo(actor, "position", [300 * Math.random() - 150, 300 * Math.random() - 150, 0],
2930 a.animateTo(actor, "position", [0, 0, 0], "Linear", 3, 3);
2931 a.animateTo(actor, "rotation", [0, 0, 1, 720 * Math.random() - 360], "Linear", 0, 3);
2932 a.animateTo(actor, "rotation", [0, 0, 1, 0], "Linear", 3, 3);
2935 // a.delete(); // delete the animtion object but a.Play() keeps it running in Dali
2940 //------------------------------------------------------------------------------
2942 // application building helpers (pseudo DSL)
2944 //------------------------------------------------------------------------------
2945 var _whenBuilder = { // builder for when() function. mimicks dali builder
2949 propertyBuffers: {},
2959 function _actorId(a) { // return id from [object|string name|id]
2961 if( typeof a === "object" ) {
2963 } else if( typeof a === "string" ) {
2964 var child = dali.stage.findChildByName(a);
2965 return child.getId();
2972 * Builder namespace. Usage as singleton "build".
2974 dali.Builder = function() {
2976 this.data = _whenBuilder;
2983 dali.Builder.prototype.init = function() {
2984 var imageSize = 0.5; // half quad size
2985 this.propertyBuffer("imageVerts",
2986 {format: [ ["aPosition", dali.PropertyType.VECTOR3],
2987 ["aTexCoord", dali.PropertyType.VECTOR2] ],
2988 data: { "aPosition": [ [-imageSize, -imageSize, 0.0],
2989 [+imageSize, -imageSize, 0.0],
2990 [-imageSize, +imageSize, 0.0],
2991 [+imageSize, +imageSize, 0.0]
2993 "aTexCoord": [ [0, 0],
3002 this.propertyBuffer("imageIndices",
3003 { format: [ ["indices", dali.PropertyType.INTEGER]],
3004 data: { "indices": [0, 3, 1, 0, 2, 3] } } );
3006 this.geometry("imageGeometry", {vertices: ["imageVerts"],
3007 indices: "imageIndices",
3009 requiresSelfDepthTest: false} );
3011 this.shader("imageShader",
3013 "attribute mediump vec3 aPosition;\n" +
3014 "attribute mediump vec2 aTexCoord;\n" +
3015 "varying mediump vec2 vTexCoord;\n" +
3016 "uniform mediump vec3 uSize;\n" +
3017 "uniform mediump mat4 uMvpMatrix;\n" +
3019 "void main(void)\n" +
3021 " mediump vec4 vertexPosition = vec4(aPosition, 1.0);\n" +
3022 " vertexPosition.xyz *= uSize;\n" +
3023 " gl_Position = uMvpMatrix * vertexPosition;\n" +
3024 " vTexCoord = aTexCoord;\n" +
3029 "precision mediump float;\n" +
3030 "uniform sampler2D sTexture;\n" +
3031 "uniform mediump vec4 uColor;\n" +
3032 "varying mediump vec2 vTexCoord;\n" +
3036 " gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n" +
3043 var builtInImages = ["girl1","funnyface","ducks","field"];
3046 for(var i=0; i < builtInImages.length; i++)
3048 var imageName = builtInImages[i];
3050 var samplerName = "sampler_" + imageName;
3051 this.sampler(samplerName,
3052 { "minification-filter":0,
3053 "magnification-filter":0,
3056 "affects-transparency":false});
3058 var materialName ="material_" + imageName;
3059 this.material(materialName,
3063 uniform: "sTexture",
3064 sampler: samplerName
3067 shader: "imageShader"} );
3069 this.renderer("render_" + imageName,
3070 {geometry: "imageGeometry",
3071 material: materialName});
3080 dali.Builder.prototype.tag = function(actor, tag) {
3081 // tag an actor (multiple by seperated by space)
3083 var names = tag.split();
3084 var id = _actorId(actor);
3085 for(var i = 0; i < names.length; i++) {
3086 var name = names[i];
3087 if(!(name in _whenBuilder.tags)) {
3088 _whenBuilder.tags[name] = [];
3090 var nameIndex = _whenBuilder.tags[name].indexOf(id);
3092 _whenBuilder.tags[name].push( id );
3100 dali.Builder.prototype.unTag = function(actor, tag) {
3103 var names = tag.split();
3104 var id = _actorId(actor);
3105 for(var i = 0; i < names.length; i++) {
3106 var name = names[i];
3107 if( name in _whenBuilder.tags ) {
3108 var nameIndex = _whenBuilder.tags[name].indexOf(id);
3109 if(nameIndex >= 0) {
3110 _whenBuilder.tags[name].splice(nameIndex, 1);
3117 * Gets list of actors tagged by 'tag'
3119 dali.Builder.prototype.tagged = function(tag) {
3120 // return all tagged
3122 return _whenBuilder.tags[tag];
3126 * Returns actorIdArray with actorOrArray removed
3128 dali.Builder.prototype.excludeFrom = function(actorIdArray, actorOrArray)
3130 // return all except one
3134 if("length" in actorOrArray) {
3135 for(item in actorOrArray) {
3136 id = _actorId(item);
3140 id = _actorId(actorOrArray);
3145 for(item in actorIdArray) {
3146 if( !(item in excludes) ) {
3156 dali.Builder.prototype.path = function (d) {
3157 // Stores paths in builder
3158 // paths({name: {points: [[1,2,3],[4,5,6]], forward:[1,0,0]},
3159 // other:{points: [[1,2,3],[4,5,6]], forward:[1,0,0]}})
3162 for(var name in d) {
3163 var pathData = {point: [], forward: [1, 0, 0]};
3164 pathData = dali.mergeObjects(pathData, d[name]);
3165 var daliPath = new dali.Path();
3166 daliPath.points = pathData.points;
3167 dali.generateControlPoints(daliPath, pathData.curvature); // @todo remove magic number?
3168 _whenBuilder.paths[name] = daliPath;
3173 * Set style definition
3175 dali.Builder.prototype.style = function(name, d) {
3176 // Stores styles in builder
3177 // style(name, {property1:value, prop2,value})
3178 // style(other, {property1:value, prop2,value})
3181 _whenBuilder.styles[name] = d;
3185 // +------------------+ +---------------+
3186 // | PropertyBuffer | * * | Geometry |
3187 // +------------------+ -------- +---------------+
3188 // | format: | | vertex:PBuf |1 * +-----------+ +------------+
3189 // | name:v2,name:v3| | indices:PBuf +---------| Renderer | | Actor |
3190 // | data | | | +-----------+ * * +------------+
3191 // +------------------+ +---------------+ * | geom +---------| renderer(s)|
3192 // +----| material | | |
3193 // +-------------+ * * +----------+ 1 | | | | |
3194 // |Sampler +----------|Material +--------------+ +-----------+ +------------+
3195 // +-------------+ +----------+
3196 // |uniformName | * |sampler(s)|
3197 // |Image | +--|shader |
3198 // |Filter/wrap | | |facecull |
3199 // +-------------+ | |blendfunc |
3201 // +-----------------+ |
3203 // +-----------------+ 1 |
3204 // |program:vert,frag|---+
3206 // +-----------------+
3210 * Set template defintion
3212 dali.Builder.prototype.template = function(name, d) {
3213 // Stores templates in builder
3214 // template("name":{ "type": "ImageActor", property1:value, prop2,value})
3215 // template("other: { "type": "TextView", property1:value, prop2,value})
3217 _whenBuilder.templates[name] = d;
3222 * Set style definition
3224 dali.Builder.prototype.imageBuffer = function(name, d) {
3225 // stores imageBuffers
3226 // imageBuffers("buffer1", { bufferName: "" }
3229 _whenBuilder.imageBuffers[name] = d;
3233 * Set property buffer definition
3235 dali.Builder.prototype.propertyBuffer = function(name, d) {
3236 // stores PropertyBuffers
3237 // propertyBuffers("buffer1", { format: [ ["aPosition", dali.PropertyType.VECTOR2],
3238 // ["aTexCoord", dali.PropertyType.VECTOR2].
3239 // data: {aPosition: [-0.5,-0.5,],
3243 // aCol: [0.0, 0.0],
3249 _whenBuilder.propertyBuffers[name] = d;
3253 * Set geometry definition
3255 dali.Builder.prototype.geometry = function(name, d) {
3256 // stores geometry meshes
3257 // geometries("mesh1": { vertices: "buffer1",
3259 // type: "TRIANGLES",
3260 // requresDepthTest:false } )
3262 _whenBuilder.geometries[name] = d;
3266 * Set sample definition
3268 dali.Builder.prototype.sampler = function(name, d) {
3270 // samplers("sampler1", { "minification-filter":0,
3271 // "magnification-filter":0,
3274 // "affects-transparency":false})
3276 _whenBuilder.samplers[name] = d;
3280 * Set shader definition
3282 dali.Builder.prototype.shader = function(name, d) {
3284 // shaders("shader1", { vertex:"",
3288 _whenBuilder.shaders[name] = d;
3292 * Set material definition
3294 dali.Builder.prototype.material = function(name, d) {
3295 // stores materials meshes
3296 // materials({"mat1",{ textures: [
3297 // { image: animage,
3298 // uniform: "uTexture"
3299 // sampler: asampler
3302 // shader: "shader1",
3303 // faceCulling: "BACK",
3305 // blendFunc : {srcFactorRGBA, destFactorRGBA},
3306 // blendEquation : "",
3307 // blendColor : [1,0,0,1] } )
3310 var value; // check required things
3311 value = this.GetRequiredKey(d, "shader");
3312 this.GetRequiredKey(_whenBuilder.shaders, value); // must already exist
3314 // only support textures so must have textures section
3315 this.GetRequiredKey(d, "textures");
3318 for(i = 0; i < d.textures.length; i++)
3320 if(typeof(d.textures[i]) == "string")
3322 // the image must already exist
3323 value = this.GetRequiredKey(d.textures[i], "image");
3324 this.GetRequiredKey(_whenBuilder.imageBuffers, value);
3331 // value = this.GetRequiredKey(d, "textures");
3332 // this.GetRequiredKey(_whenBuilder.textures, value);
3333 _whenBuilder.materials[name] = d;
3337 * Set renderer definition
3339 dali.Builder.prototype.renderer = function(name, d) {
3341 // renderers("rend1", {"geometry": "geom1",
3342 // "material": "mat1",
3345 var value; // check required things
3346 value = this.GetRequiredKey(d, "geometry");
3347 this.GetRequiredKey(_whenBuilder.geometries, value); // must already exist
3348 value = this.GetRequiredKey(d, "material");
3349 this.GetRequiredKey(_whenBuilder.materials, value);
3351 _whenBuilder.renderers[name] = d;
3354 dali.Builder.prototype.createOrGetDaliPropertyBuffer = function(name) {
3356 consoleAssert(name in _whenBuilder.propertyBuffers, "property buffer not defined:" + name);
3358 if("daliObject" in _whenBuilder.propertyBuffers[name]) {
3359 ret = _whenBuilder.propertyBuffers[name].daliObject;
3361 var data = _whenBuilder.propertyBuffers[name];
3363 ret = dali.createPropertyBuffer(data);
3365 _whenBuilder.propertyBuffers[name].daliObject = ret;
3370 dali.Builder.prototype.createOrGetDaliGeometry = function(name) {
3372 consoleAssert(name in _whenBuilder.geometries, "geometry not defined:" + name);
3374 if("daliObject" in _whenBuilder.geometries[name]) {
3375 ret = _whenBuilder.geometries[name].daliObject;
3377 var data = _whenBuilder.geometries[name];
3379 ret = new dali.Geometry();
3381 for(var i = 0; i < data.vertices.length; i++) {
3382 ret.addVertexBuffer( this.createOrGetDaliPropertyBuffer(data.vertices[i] ) );
3385 ret.setIndexBuffer( this.createOrGetDaliPropertyBuffer(data.indices) );
3387 if("requiresSelfDepthTest" in data) {
3388 ret.setRequiresDepthTesting(data.requiresSelfDepthTest);
3391 _whenBuilder.geometries[name].daliObject = ret;
3396 dali.Builder.prototype.createOrGetDaliShader = function(name) {
3398 consoleAssert(name in _whenBuilder.shaders, "shader not defined:" + name);
3400 if("daliObject" in _whenBuilder.shaders[name]) {
3401 ret = _whenBuilder.shaders[name].daliObject;
3403 var data = _whenBuilder.shaders[name];
3405 ret = new dali.Shader(data.vertex,
3407 uiShaderTab.getDaliShaderHints(data.hints));
3409 _whenBuilder.shaders[name].daliObject = ret;
3415 dali.Builder.prototype.createOrGetDaliImage = function(name) {
3417 if(!(name in _whenBuilder.imageBuffers)) {
3418 _whenBuilder.imageBuffers[name] = {};
3422 if("daliObject" in _whenBuilder.imageBuffers[name]) {
3423 ret = _whenBuilder.imageBuffers[name].daliObject;
3425 // get images from the ui buffer
3426 ret = imageFromUiBuffer(name);
3427 _whenBuilder.imageBuffers[name].daliObject = ret;
3432 dali.Builder.prototype.createOrGetDaliSampler = function(name) {
3434 consoleAssert( name in _whenBuilder.samplers, "sampler not defined:" + name);
3436 if("daliObject" in _whenBuilder.samplers[name]) {
3437 ret = _whenBuilder.samplers[name].daliObject;
3439 var data = _whenBuilder.samplers[name];
3440 ret = new dali.Sampler();
3441 _whenBuilder.samplers[name].daliObject = ret;
3446 dali.Builder.prototype.createOrGetDaliMaterial = function(name) {
3448 consoleAssert( name in _whenBuilder.materials, "Material not defined:" + name);
3450 if("daliObject" in _whenBuilder.materials[name]) {
3451 ret = _whenBuilder.materials[name].daliObject;
3453 var data = _whenBuilder.materials[name];
3455 ret = new dali.Material(this.createOrGetDaliShader( data.shader ));
3457 for(var i = 0; i < data.textures.length; i++) {
3458 ret.addTexture( this.createOrGetDaliImage(data.textures[i].image),
3459 data.textures[i].uniform,
3460 this.createOrGetDaliSampler( data.textures[i].sampler ) );
3463 _whenBuilder.materials[name].daliObject = ret;
3468 dali.Builder.prototype.createOrGetDaliRenderer = function(name) {
3470 consoleAssert( name in _whenBuilder.renderers, "Renderer not defined:" + name);
3473 if("daliObject" in _whenBuilder.renderers[name]) {
3474 ret = _whenBuilder.renderers[name].daliObject;
3476 var data = _whenBuilder.renderers[name];
3478 ret = new dali.Renderer(this.createOrGetDaliGeometry(data.geometry),
3479 this.createOrGetDaliMaterial(data.material));
3481 _whenBuilder.renderers[name].daliObject = ret;
3486 dali.Builder.prototype.createActorTree = function(dictionary) {
3490 consoleAssert(typeof(dictionary) == "object", "createActorTree needs an object");
3492 if("type" in dictionary) {
3493 if( dictionary.type in dali ) {
3494 ret = new dali[ dictionary.type ]();
3495 } else if( dictionary.type in _whenBuilder.templates ) {
3496 var realType = _whenBuilder.templates[ dictionary.type ].type;
3497 ret = new dali[ realType ]();
3499 consoleAssert(0, "Cannot find type to create:" + dictionary.type);
3502 consoleAssert("render" in dictionary, "'type' or 'render needed to create dali object");
3503 ret = new dali.Actor();
3508 for(var prop in dictionary) {
3509 if( prop === "actors" ) {
3510 var actors = dictionary[prop];
3511 for(i = 0; i < actors.length; i++) {
3512 ret.add( this.createActorTree( actors[i] ) );
3514 } else if( prop === "tag" ) {
3515 tags.push(dictionary.tag);
3516 } else if( prop === "tags" ) {
3517 tags.concat(dictionary.tags);
3518 } else if( prop === "type" ) {
3520 } else if( prop === "render") {
3522 if(typeof(dictionary.render) == "string")
3524 renderer = this.createOrGetDaliRenderer(dictionary.render);
3525 ret.addRenderer(renderer);
3529 for(i = 0; i < dictionary.render.length; i++) {
3530 renderer = this.createOrGetDaliRenderer(dictionary.render[i]);
3531 ret.addRenderer(renderer);
3536 ret[prop] = dictionary[prop];
3541 for(i = 0; i < tags.length; i++) {
3542 this.tag(ret, tags[i]);
3550 * Adds actor defintions to stage.
3552 dali.Builder.prototype.stage = function(/* actor definition array */) {
3554 for(var i = 0; i < arguments.length; i++) {
3555 dali.stage.add( this.createActorTree( arguments[i] ) );
3560 * Adds actor defintions to stage.
3562 dali.Builder.prototype.addTo = function(/* toActor, actor_definition_array */) {
3564 consoleAssert(typeof(arguments[0]) == "string", "1st argument must be name");
3568 for(i = 1; i < arguments.length; i++) {
3569 consoleAssert(typeof(arguments[1]) == "object", "2nd and other arguments must be object");
3573 if( arguments[0] == "stage" ) {
3574 actor = dali.stage.getRootLayer();
3577 actor = dali.stage.getRootLayer().findChildByName( arguments[0] );
3578 consoleAssert(actor, "Cannot find actor:" + arguments[0]);
3581 for(i = 1; i < arguments.length; i++) {
3582 dali.stage.add( this.createActorTree( arguments[i] ) );
3587 * Adds actor defintions to stage.
3589 dali.Builder.prototype.GetRequiredKey = function(object, name, caller) {
3590 if( name in object )
3592 return object[name];
3596 consoleAssert(0, "Object is missing key:'" + name + "'\n" + JSON.stringify(object));
3601 dali.Builder.prototype.image = function(dictionary) {
3602 // image({name:"name"
3609 var name = this.GetRequiredKey(dictionary, "name");
3611 var shaderName = "imageShader";
3612 if("shader" in dictionary) {
3613 shaderName = dictionary.shader;
3615 var samplers = [name + "_sampler"];
3616 if("samplers" in dictionary) {
3617 samplers = dictionary.samplers;
3620 var samplername = name + "_sampler";
3622 d[samplername] = {};
3625 var matname = name + "_material";
3627 d[matname] = {shader: shaderName, textures: [ {image: this.GetRequiredKey(dictionary, "image"),
3628 uniform: "sTexture",
3629 sampler: samplername}]};
3632 var rendname = name + "_renderer";
3634 d[rendname] = {geometry: "imageGeometry", material: matname};
3637 // store imageBuffers if they are missing for image
3638 // (we're only using image data from browser buffers)
3639 if( !(dictionary.image in _whenBuilder.imageBuffers) ) { // add to _whenBuilder
3641 d[dictionary.image] = { bufferName: dictionary.image };
3642 this.imageBuffers(d);
3645 dictionary.type = "Actor";
3646 dictionary.renderers = [rendname];
3651 ////////////////////////////////////////////////////////////////////////////////
3653 // dali toy Builder singleton
3656 ////////////////////////////////////////////////////////////////////////////////
3657 var build = new dali.Builder();
3659 ////////////////////////////////////////////////////////////////////////////////
3663 ////////////////////////////////////////////////////////////////////////////////
3664 function _addTypeToDictionaryClosure(actorType) {
3666 return function(dictionary) {
3667 dictionary.type = actorType;
3672 // @ todo; why is this global?
3673 var HTML5Image = Image; // html5 also has "Image" which were about to overwrite
3674 var _registry = new dali.TypeRegistry();
3675 for(var _i = 0; _i < _registry.getTypeNameCount(); _i++) {
3676 var _typename = _registry.getTypeName(_i);
3677 this[_typename] = _addTypeToDictionaryClosure(_typename);
3680 function _actorArray(actorOrName) {
3682 if(typeof actorOrName === "string") {
3683 return [actorOrName];
3685 return [actorOrName.name];
3689 function _actorIdList(a) {
3693 for(var item in a) {
3694 ret.push( _actorId(item) );
3697 ret.push( _actorId(a) );
3703 function _functionName(fun) {
3705 var ret = fun.toString();
3706 ret = ret.substr("function ".length);
3707 ret = ret.substr(0, ret.indexOf("("));
3711 function _numberOrRaise(value, errorMessage) {
3713 if(typeof value === "number") {
3720 function _stringOrRaise(value, errorMessage) {
3722 if(typeof value === "string") {
3731 // to(value, delay, duration)
3732 // to(value, delay, duration, interpolation)
3735 // to([10,10,10], 0,3, "ease_in")),
3738 var ret = { animate: "animateTo",
3744 ret.value = arguments[0]; // property value
3745 if( arguments.length > 1 ) {
3746 ret.delay = _numberOrRaise(arguments[1], "Delay must be a number");
3748 if( arguments.length > 2 ) {
3749 ret.duration = _numberOrRaise(arguments[2], "Duration must be a number");
3751 if( arguments.length > 3 ) { // optional
3752 ret.alpha = arguments[3];
3759 // by(value, delay, duration)
3760 // by(value, delay, duration, interpolation)
3763 // by([10,10,10], 0,3, "ease_in")),
3766 var ret = { animate: "animateBy",
3772 ret.value = arguments[0]; // property value
3773 if( arguments.length > 1 ) {
3774 ret.delay = _numberOrRaise(arguments[1], "Delay must be a number");
3776 if( arguments.length > 2 ) {
3777 ret.duration = _numberOrRaise(arguments[2], "Duration must be a number");
3779 if( arguments.length > 3 ) { // optional
3780 ret.alpha = arguments[3];
3786 // between(fromValue, toValue)
3787 // between(fromValue, toValue, delay, duration)
3788 // between(fromValue, toValue, delay, duration, interpolation)
3790 // between([10,10,10], [100,10,10]
3791 // between([10,10,10], [100,10,10], 0,3, "ease_in")),
3792 function between() {
3794 var ret = { animate: "animateBy",
3801 ret.value = arguments[0]; // property value
3802 ret.value = arguments[1]; // property value
3803 if( arguments.length > 2 ) {
3804 ret.delay = _numberOrRaise(arguments[2], "Delay must be a number");
3806 if( arguments.length > 3 ) {
3807 ret.duration = _numberOrRaise(arguments[3], "Duration must be a number");
3810 if( arguments.length > 4 ) { // optional
3811 ret.alpha = arguments[4];
3818 // path(pathName, delay, duration)
3819 // path(pathName, delay, duration, interpolation)
3821 // path("path0", 0, 3, "linear")
3824 var ret = { animate: "path",
3831 ret.path = arguments[0]; // path
3832 if( arguments.length > 1 ) {
3833 ret.delay = _numberOrRaise(arguments[1], "Delay must be a number");
3835 if( arguments.length > 2 ) {
3836 ret.duration = _numberOrRaise(arguments[2], "Duration must be a number");
3839 if( arguments.length > 3 ) { // optional
3840 ret.alpha = arguments[3];
3845 // conditional animation
3846 // when("myimage", condition("touched", "inside", 0, 100),
3848 function condition(propertyName, conditionType, arg0, arg1)
3851 var ret = { actors: [],
3852 property: propertyName,
3853 type: conditionType,
3858 if(arg1 === undefined) {
3859 ret.arg1 = 0.0; // make a float for the c++ call (ignored if irrelevant)
3866 // set(actorOrListOrNone, signalName, animationDefition)
3868 // set("myimage", "size", to([10,10,10], 0,3, "ease_in"),
3869 // path(0,3, "ease_in", "path0"))
3870 // set("size", to([10,10,10], 0,3, "ease_in")),
3871 // between([0,0,0], [10,10,10], 0,3, "ease_in")))
3872 // set(tagged("scrollitem), "position", path(0,3, "ease_in", "path0")),
3873 // set(excludeFrom(tagged("scrollitem"), "myimage"), "position", path(0,3, "ease_in", "path0")),
3876 var ret = { action: "set",
3883 if( arguments.length === 3 ) { // then actor is specified somehow
3884 ret.actors = _actorArray( arguments[0] );
3885 ret.property = _stringOrRaise(arguments[1], "Property must be a string");
3887 } else if( arguments.length === 2 ) { // actor is self (indicated in 'when' call)
3888 ret.property = _stringOrRaise(arguments[0], "Property must be a string");
3891 throw "set needs 2 or 3 arguments";
3894 for(var i = index; i < arguments.length; i++) {
3895 ret.animation.push( arguments[i] );
3902 // call(function, arg0, arg1)
3905 // call(func, 10.0, "enable")
3908 var ret = { action: "call",
3913 ret.func = arguments[0];
3915 for(var i = 1; i < arguments.length; i++) {
3916 ret.arguments.push( arguments[i] );
3925 return [{ action: arguments[0],
3926 parameters: arguments[1]}];
3929 function _actorNameList()
3933 if(typeof arguments[0] === "function") {
3934 var lookup = arguments[0]();
3936 } else if(typeof arguments[0] === "object") {
3937 // or it can be the actual dali actor object
3938 names = _actorArray(arguments[0].name);
3939 } else if(typeof arguments[0] === "string") {
3940 // or arg0,arg1 are the actor property
3941 names = _actorArray(arguments[0]);
3943 return names; // presume already actor name list
3948 var _buildDescription = {animations:{}, templates:{}};
3950 function _animation(a) {
3954 return new dali.Animation(0);
3958 // function _makeActionCallback(func, args) {
3960 // return function(){
3962 // for(var i = 0; i < args.length; i++) {
3964 // if( d.action === "set" ) {
3965 // for(var ai = 0; ai < d.actors.length; ai++) {
3966 // if( d.property ) {
3967 // apply(_animation,
3968 // d.arguments[0].animate,
3970 // anim.push( [d.actors[ai]], d.property,
3975 // var ret = { action: "set",
3983 // func.apply(null, args);
3990 return { action: "loop",
3994 function endAction(action)
3997 return { action: "endAction",
4001 function disconnectAction(action)
4004 return { action: "disconnectAction",
4009 function _makeCallback(args) {
4013 var actors = _actorNameList( args[0] );
4014 // args[1] is signal name
4015 for(var i = 2; i < args.length; i++) {
4017 if(d.action === "call") {
4018 d.func.apply(null, d.arguments);
4019 } else if(d.action === "loop") {
4021 a.setLooping( d.value );
4022 } else if(d.action === "endAction") {
4024 a.setEndAction( d.value );
4025 } else if(d.action === "disconnectAction") {
4027 a.setDisconnectAction( d.value );
4028 } else if(d.action === "set") {
4029 if( d.actors.length ) {
4032 for(var actori = 0; actori < actors.length; actori++) {
4033 var actorName = actors[actori];
4034 var root = dali.stage.getRootLayer();
4035 var actor = root.findChildByName( actorName );
4037 for(var animi = 0; animi < d.animation.length; animi++) {
4038 var anim = d.animation[animi];
4039 var value = anim.value;
4040 if(typeof value === "function") { // can be a function
4043 if(anim.animate === "animateTo") {
4044 a.animateTo(actor, d.property, value, anim.alpha, anim.delay, anim.duration);
4045 } else if(anim.animate === "animateBy") {
4046 a.animateBy(actor, d.property, value, anim.alpha, anim.delay, anim.duration);
4047 } else if(anim.animate === "animatePath") {
4048 var pathData = anim.path;
4050 if(typeof pathData === "function") {
4051 pathData = pathData();
4053 if(typeof pathData === "string") {
4054 if(pathData in _whenBuilder.paths) {
4055 daliPath = _whenBuilder.paths[pathData];
4057 throw "Path not known";
4060 daliPath = new dali.Path();
4061 daliPath.points = pathData;
4062 dali.generateControlPoints(daliPath, 0.35); // @todo remove magic number?
4064 _animation(a).animatePath(actor, daliPath, anim.forward, anim.alpha, anim.delay, anim.duration);
4073 // animation support?
4074 // else if( d.action === "animate" ) {
4077 // actions support??
4078 // else if( d.action === "then" ) {
4079 // if( d.actors.length ) {
4080 // actors = d.actors;
4086 }; // closure function
4090 // doNow(<defaultActor>, ...)
4093 // call(myfunction),
4094 // call(myfunction, arg1),
4095 // and("animation-ends"),
4096 // set("myimage", "size", to([10,10,10]),
4097 // to([10,10,10], 0,3, "ease_in")),
4098 // path(0,3, "ease_in", "path0")),
4099 // between([0,0,0], [10,10,10], 0,3, "ease_in")),
4100 // to([0,0,0], 0, 3)
4101 // set(tagged("scrollitem), path(0,3, "ease_in", "path0")),
4102 // set(excludeFrom(tagged("scrollitem"), "myimage"), path(0,3, "ease_in", "path0")),
4103 // endAction("bake"),
4104 // discardAction("bake"),
4106 // then("myimage", "hide"),
4108 // then("play", "myanim"),
4109 // thenOnChild("myimage", "child", "hide"),
4111 // animateTo("position",
4113 function doNow(args) {
4115 var actor = args.shift();
4116 args.unshift(""); // signal name
4117 args.unshift(actor);
4118 var cb = _makeCallback.apply(null, args);
4122 function _makeSensibleTouched(func, state) { // dali giving all mouse events on touched signal --- is this correct?? @todo
4124 return function(actor, touchEvent){
4126 for(var i = 0; i < touchEvent.points.length; i++) {
4127 if(touchEvent.points[i].state === state) {
4133 func.apply( null, arguments);
4138 // function _connectToSignal(actors, signalName, func) {
4140 // var root = dali.stage.getRootLayer();
4143 // if( signalName === "touchedDown" ) { // fix as touched signal is really "mouseState"?
4144 // f = _makeSensibleTouchedDown(func);
4145 // signalName = "touched";
4148 // for(var ai = 0; ai < actors.length; ai++) {
4149 // var actor = root.findChildByName( actors[ai] );
4150 // actor.connect( signalName, f );
4155 // when("myimage", condition("touched", "inside", 0, 100),
4157 // when("myimage", "touched",
4158 // call(myfunction),
4159 // call(myfunction, arg1),
4160 // and("animation-ends"),
4161 // set("myimage", "size", to([10,10,10]),
4162 // to([10,10,10], 0,3, "ease_in")),
4163 // path(0,3, "ease_in", "path0")),
4164 // between([0,0,0], [10,10,10], 0,3, "ease_in")),
4165 // to([0,0,0], 0, 3)
4166 // set(tagged("scrollitem), path(0,3, "ease_in", "path0")),
4167 // set(excludeFrom(tagged("scrollitem"), "myimage"), path(0,3, "ease_in", "path0")),
4168 // endAction("bake"),
4169 // discardAction("bake"),
4171 // then("myimage", "hide"),
4173 // then("play", "myanim"),
4174 // thenOnChild("myimage", "child", "hide"),
4179 var actors, property, index;
4181 var condition = null;
4183 // arg0 can be an actor lookup function; returning an actor array
4184 actors = _actorNameList(arguments[0]);
4186 if(typeof arguments[1] === "string") {
4187 // if string then its a signal
4188 signal = arguments[1];
4190 // if object then its a condition
4191 condition = arguments[1];
4192 // actors can be null which means use the actors in when() call
4193 if(condition.actors === null) {
4194 condition.actor = actors[0];
4204 // _connectToSignal( actors, signal, _makeCallback(arguments) );
4205 root = dali.stage.getRootLayer();
4206 f = _makeCallback(arguments);
4208 if( signal === "touchedDown" ) { // fix as touched signal is really "mouseState"?
4209 f = _makeSensibleTouched(f, "Down");
4212 if( signal === "touchedUp" ) { // fix as touched signal is really "mouseState"?
4213 f = _makeSensibleTouched(f, "Up");
4216 if( signal === "touchedMotion" ) { // fix as touched signal is really "mouseState"?
4217 f = _makeSensibleTouched(f, "Motion");
4220 if( signal === "touchedLeave" ) { // fix as touched signal is really "mouseState"?
4221 f = _makeSensibleTouched(f, "Leave");
4224 if( signal === "touchedStationary" ) { // fix as touched signal is really "mouseState"?
4225 f = _makeSensibleTouched(f, "Stationary");
4228 if( signal === "touchedInterrupted" ) { // fix as touched signal is really "mouseState"?
4229 f = _makeSensibleTouched(f, "Interrupted");
4232 if( signal === "touchedLast" ) { // fix as touched signal is really "mouseState"?
4233 f = _makeSensibleTouched(f, "Last");
4237 for(ai = 0; ai < actors.length; ai++) {
4238 actor = root.findChildByName( actors[ai] );
4239 actor.connect( signal, f );
4244 // _connectToCondition( actors, condition, _makeCallback(arguments) );
4245 root = dali.stage.getRootLayer();
4246 f = _makeCallback(arguments);
4248 for(ai = 0; ai < actors.length; ai++) {
4249 actor = root.findChildByName( actors[ai] );
4250 actor.setPropertyNotification(condition.property,
4251 condition.type, condition.arg0, condition.arg1,
4256 // when("myimage", condition("touched", "inside", 0, 100),
4258 // when("myimage", "touched",
4260 // dali.ActorWrapper.prototype.connect = function(signalName, callback) {
4261 // if(d.action === "set") {
4262 // var animationActors = d.actors;
4263 // if( animationActors.length === 0 ) {
4264 // animationActors = actors;
4266 // var a = new dali.Animation(0);
4267 // // dali.AnimationWrapper.prototype.animateTo = function(object, propertyName, value, alphaFunction, delay, duration) {
4268 // //dali.AnimationWrapper.prototype.animateBy = function(object, propertyName, value, alphaFunction, delay, duration) {
4269 // //dali.AnimationWrapper.prototype.animatePath = function(object, pathObject, forward, alphaFunction, delay, duration) {
4270 // for(var ai =0; ai < animationActors.length; ai++) {
4271 // for(var animi =0; animi < d.animation; animi++) {
4272 // var animEntry = d.animation[animi];
4273 // if( d.animate == "animatePath") {
4274 // a.animatePath(animationActors[ai], animEntry.path, animEntry.forward, animEntry.alpha,
4275 // animEntry.delay, animEntry.duration);
4277 // } else if( d.animate == "animateBetween") {
4278 // a.animateBetween(animationActors[ai], d.property,
4279 // animEntry.fromValue, animEntry.toValue,
4280 // animEntry.alpha, animEntry.delay, animEntry.duration);
4282 // // call animateTo,animateBy,
4283 // a[animEntry.animate](animationActors[ai], d.property, animEntry.value, animEntry.alpha,
4284 // animEntry.delay, animEntry.duration);
4289 // var animiations = [];
4291 // for(var i = 2; i < arguments.length; i++) {
4292 // var d = arguments[i];
4293 // if( d.action === "set" ) {
4294 // // var ret = { action: "set",
4296 // // property: null,
4297 // // condition: null,
4300 // for(var ai = 0; ai < d.actors.length; ai++) {
4305 // for(var j = 0; j < d.length; j++) {
4306 // if(signal) { // then its signal actions
4308 // templates[actorName].signals.push(d[j]);
4309 // } else { // its property notifications
4310 // d.condition = condition;
4311 // d.property = property;
4312 // templates[actorName].notifications.push(d[j]);
4316 // // but we could also be specifying a property notification so...
4320 // if(typeof arguments[index] === "string") {
4321 // var lowerCase = arguments[index].toLowerCase();
4322 // if("insideoutsidegreaterthanlessthan".indexOf(lowerCase)) {
4323 // property = signal;
4325 // condition = lowerCase;
4327 // value = arguments[index];
4329 // if( condition === "inside" || condition === "outside" ) {
4330 // assert( value.length === 2, "Inside/Outside condition must specify min,max");
4331 // assert(typeof value[0] === "number" && typeof value[1] === "number", "Conditions must be numbers");
4333 // if(condition === "lessthan" || condition === "greaterthan") {
4334 // assert(value.length === 1, "LessThan/GreaterThan condition must specify one value");
4335 // assert(typeof value === "number", "Conditions must be numbers");
4340 // // The reset are objects created by the set or call function
4341 // var templates = _buildDescription.templates;
4343 // for( var actorName in actors ) {
4344 // // the other args come from functions that generate json
4345 // for(var i = index; i < arguments.length; i++) {
4346 // var d = arguments[i];
4347 // for(var j = 0; j < d.length; j++) {
4348 // if(signal) { // then its signal actions
4350 // templates[actorName].signals.push(d[j]);
4351 // } else { // its property notifications
4352 // d.condition = condition;
4353 // d.property = property;
4354 // templates[actorName].notifications.push(d[j]);
4363 // function animation() {
4366 // var name = arguments[0];
4368 // for(var i = 1; i < arguments.length; i++) {
4369 // var d = arguments[i];
4371 // if(d.length === undefined) { // then array from set
4374 // extend( anim, d );
4390 // image({filename:"animage,
4392 // tag: "scrollitem",
4395 // text({text:"sometext,
4396 // tag: "scrollitem",
4402 // when("myimage", condition("touched", "inside", 0, 100),
4404 // when("myimage", "touched",
4405 // call(myfunction),
4406 // call(myfunction, arg1),
4407 // and("animation-ends"),
4408 // set("myimage", "size", to([10,10,10]),
4409 // to([10,10,10], 0,3, "ease_in")),
4410 // path(0,3, "ease_in", "path0")),
4411 // between([0,0,0], [10,10,10], 0,3, "ease_in")),
4412 // to([0,0,0], 0, 3)
4413 // set(tagged("scrollitem), path(0,3, "ease_in", "path0")),
4414 // set(excludeFrom(tagged("scrollitem"), "myimage"), path(0,3, "ease_in", "path0")),
4415 // then("myimage", "hide"),
4417 // then("play", "myanim"),
4418 // thenOnChild("myimage", "child", "hide"),
4423 // on("myimage", "position", between(0, 100),
4427 //------------------------------------------------------------------------------
4428 // test helper functions
4429 //------------------------------------------------------------------------------
4432 var root = dali.stage.rootRotationActor;
4433 var children = root.getChildren();
4435 for (var i = 0, len = children.length; i < len; i++) {
4436 root.remove(children[i]);
4437 children[i].delete(); // delete the wrapper
4439 // root.delete(); // wrapper
4442 function square(color, size) {
4443 var a = dali.createSolidColorActor(color, 0, [0, 0, 0, 1], 0);
4448 function threeSquares() {
4449 var root = dali.stage.rootRotationActor;
4451 var a = square([1, 0, 0, 1], [200, 200, 0]);
4453 a.position = [-100, 0, -20];
4457 a = square([0, 1, 0, 1], [200, 200, 0]);
4459 a.position = [0, -100, -10];
4463 a = square([0, 0, 1, 1], [200, 200, 0]);
4465 a.position = [0, -100, 0];
4472 function threeSquares2() {
4473 var root = dali.stage.rootRotationActor;
4475 var red = square([1, 0, 0, 1], [200, 200, 0]);
4477 red.position = [-100, 0, 20];
4478 red.size = [10, 10, 0];
4481 var green = square([0, 1, 0, 1], [200, 200, 0]);
4482 green.name = "green";
4483 green.position = [0, -100, 0];
4484 green.orientation = [0, 0, 20];
4485 green.size = [200, 200, 0];
4487 var blue = square([0, 0, 1, 1], [200, 200, 0]);
4489 blue.position = [0, 0, 10];
4490 blue.parentOrigin = [0, 0, 0];
4491 blue.size = [100, 100, 0];
4495 red.delete(); // wrapper
4496 green.delete(); // wrapper
4497 blue.delete(); // wrapper
4502 function collectByName(collection) {
4503 var root = dali.stage.rootRotationActor;
4504 if (collection === undefined) {
4507 var op = function(actor) {
4509 collection[actor.name] = actor;
4514 dali.debug.depthVisit(root, op, true);
4521 return dali.stage.getRenderTaskList().getTask(0);
4525 return dali.stage.getRenderTaskList().getTask(1);
4529 return dali.stage.getRenderTaskList().getTask(2);
4532 function firstCamera() {
4533 return dali.stage.getRenderTaskList().getTask(0).getCameraActor();
4536 function secondCamera() {
4537 return dali.stage.getRenderTaskList().getTask(1).getCameraActor();
4540 function thirdCamera() {
4541 return dali.stage.getRenderTaskList().getTask(2).getCameraActor();
4544 function resize(w, h) {
4545 dali.setCanvasSize(w, h);
4548 function compareProperties(a1, a2) {
4549 var props1 = a1.getProperties();
4550 var props2 = a2.getProperties();
4551 var props = new Set();
4552 for (var i = 0, len = props1.size(); i < len; i++) {
4553 props.add(props1.get(i));
4556 for (i = 0, len = props2.size(); i < len; i++) {
4557 var n = props2.get(i);
4558 if (!props.has(n)) {
4559 console.log("A1 missing :" + n);
4563 var doit = function(item) {
4564 var v1 = a1[item]; // a1.getProperty(item);
4565 var v2 = a2[item]; // a2.getProperty(item);
4569 if (Array.isArray(v1)) {
4570 isSame = (v1.length === v2.length) && v1.every(function(element, index) {
4571 return element === v2[index];
4578 console.log(item + ": A1= " + v1 + " A2= " + v2);
4582 props.forEach(doit);
4585 var EPSILON = 0.005;
4587 function compareArrays(a, b) {
4589 if (Array.isArray(a) && Array.isArray(b)) {
4590 if (a.length === b.length) {
4591 for (var i = 0, len = a.length; i < len; i++) {
4592 if (Array.isArray(a[i])) {
4593 if (Array.isArray(b[i])) {
4594 if (!compareArrays(a[i], b[i])) {
4601 if (typeof (a[i]) === "number") {
4602 if (typeof (b[i]) !== "number") {
4605 if (Math.abs(a[i]) > Math.abs(b[i]) + EPSILON ||
4606 Math.abs(a[i]) < Math.abs(b[i]) - EPSILON) {
4611 if (a[i] !== b[i]) {
4623 function countAllProperties() {
4625 var tr = new dali.TypeRegistry();
4626 var names = tr.getTypeNames();
4627 for (var i = 0, len = names.size(); i < len; i++) {
4628 var ti = tr.getTypeInfo(names.get(i));
4629 var props = ti.getProperties();
4630 count += props.size();
4635 function native2ascii(str) {
4637 // really this function allows only GLSL permittable chars
4639 for (var i = 0; i < str.length; i++) {
4640 if ( 0x20 <= str.charCodeAt(i) && str.charCodeAt(i) <= 0x7E) {
4641 // normal characters
4642 out += str.charAt(i);
4643 } else if( 0x9 <= str.charCodeAt(i) && str.charCodeAt(i) <= 0xD) {
4644 // new lines and tabs
4645 out += str.charAt(i);
4652 var getGL = function() {
4653 return canvas.getContext("webgl");
4656 var getAnimation = function() {
4658 return animationList[animationSelectionIndex].animation;
4661 var getActor = function() {
4663 return eventHandler.touchedActor;
4667 //------------------------------------------------------------------------------
4669 //------------------------------------------------------------------------------
4674 Test.prototype.hierarchy = function() {
4676 console.log("test_hierarchy...");
4678 // function onTouched(actor) {
4679 // // console.log("touched " + actor.$$.ptr + " " + actor.position);
4680 // eventHandler.onTouched(actor);
4683 var actor = new dali.Actor();
4684 actor.parentOrigin = [0.5, 0.5, 0.5];
4685 actor.anchorPoint = [0.5, 0.5, 0.5];
4686 actor.text = "actor";
4687 actor.name = actor.text;
4688 actor.size = [100, 100, 1];
4689 actor.position = [0, 0, 10];
4690 dali.stage.add(actor);
4692 var hello = new dali.Actor();
4693 // hello.connect("touched", onTouched);
4694 hello.text = "hello";
4695 hello.name = hello.text;
4698 var hellochild = new dali.Actor();
4699 // hellochild.connect("touched", onTouched);
4700 hellochild.text = "hello-child";
4701 hellochild.name = hellochild.text;
4702 hello.add(hellochild);
4704 var hellochild2 = new dali.Actor();
4705 // hellochild2.connect("touched", onTouched);
4706 hellochild2.text = "hello-child2";
4707 hellochild2.name = hellochild2.text;
4708 hello.add(hellochild2);
4710 var hellochildchild = new dali.Actor();
4711 // hellochildchild.connect("touched", onTouched);
4712 hellochildchild.text = "hello-child-child1";
4713 hellochildchild.name = "hello-child-child1";
4714 hellochildchild.name = hellochildchild.text;
4715 hellochild.add(hellochildchild);
4718 var depthfirst = actor.findAllChildren();
4720 assert(actor.getChildCount() === 1);
4721 // assert(actor.getChildAt(0).text === "hello");
4722 // assert(actor.findChildByName("hello-child-child1").text = "hello-child-child1");
4723 // assert(hello.getParent().text === "actor");
4724 // assert(depthfirst[depthfirst.length - 1].text === "hello-child2");
4726 var directChildren = actor.directChildren();
4728 assert(directChildren.length === 1);
4729 assert(directChildren[0].getId() === hello.getId());
4731 actor.position = [100, 100, 0];
4733 var root = dali.stage.rootRotationActor;
4735 actor.remove(hello);
4736 assert(actor.getChildCount() === 0);
4739 assert(actor.getChildCount() === 1);
4741 var rootLayerCount = root.getChildCount();
4742 dali.stage.remove(actor); // check these don't assert
4743 assert(root.getChildCount() === rootLayerCount - 1);
4745 dali.stage.add(actor);
4746 assert(root.getChildCount() === rootLayerCount);
4748 assert(root.findChildByName("none") === null);
4750 // actor.connect("touched", onTouched);
4752 // var inserted = new dali.TextActor(); // TextActor no more RIP
4753 // inserted.parentOrigin = [0.5, 0.5, 0.5];
4754 // inserted.anchorPoint = [0.5, 0.5, 0.5];
4755 // inserted.text = "inserted";
4756 // inserted.name = inserted.text;
4757 // inserted.size = [100, 100, 1];
4758 // inserted.position = [0, 0, 50];
4759 // actor.insert(1, inserted);
4760 // assert(actor.getChildAt(1).text === "inserted");
4763 console.log(" -> ok test_hierarchy");
4766 Test.prototype.registerProperty = function() {
4768 console.log("test_registerPropery...");
4770 var root = s.rootRotationActor;
4772 var another = new dali.Actor();
4773 another.parentOrigin = [0.5, 0.5, 0.5];
4774 another.anchorPoint = [0.5, 0.5, 0.5];
4775 another.text = "peppa";
4776 another.name = another.text;
4777 another.size = [100, 100, 1];
4778 another.position = [-50, 100, 0];
4781 var c = root.getChildAt(root.getChildCount() - 1);
4782 //var n = c.getChildCount();
4783 var p = c.getParent();
4784 assert(p.getId() == root.getId());
4786 var matrix = c.worldMatrix;
4788 assert(matrix.length === 16);
4790 // todo - no longer supported (?)
4791 // another.registerProperty("data_output", true);
4792 // assert(another.getPropertyTypeFromName("data_output") === "BOOLEAN");
4793 // assert(another.data_output === true);
4794 // another.data_output = false;
4795 // assert(another.data_output === false);
4796 // dali.__updateOnce();
4797 // another.data_output = 2.5;
4798 // assert(another.data_output === 2.5);
4799 // assert(another.getPropertyTypeFromName("data_output") === "FLOAT");
4802 console.log(" -> ok test_registerPropery");
4805 Test.prototype.js_math = function() {
4806 console.log("test_js_math...");
4807 assert(dali.vectorLength([1, 2, 3, 4]) === Math.sqrt(1 * 1 + 2 * 2 + 3 * 3));
4808 assert(dali.vectorLengthSquared(dali.normalize([0, 0, 0, 1])) === 0);
4810 // for(var f=0; f < 6; f+=1)
4813 assert(1 === dali.vectorLengthSquared(dali.normalize([Math.cos(f) * 10.0,
4814 Math.cos(f + 1.0) * 10.0,
4815 Math.cos(f + 2.0) * 10.0,
4819 function assertArray(a, b, epsilon) {
4820 assert(a.length === b.length);
4821 for (var i = 0, len = a.length; i < len; ++i) {
4822 assert(a[i] > b[i] - epsilon && a[i] < b[i] + epsilon);
4826 assertArray(dali.axisAngleToQuaternion([1.0, 2.0, 3.0, Math.PI / 3.0, Math.PI / 2.0]), [0.189, 0.378, 0.567, 0.707], 0.001);
4828 assertArray(dali.quaternionToAxisAngle([1.1, 3.4, 2.7, 0.932]), [3.03, 9.38, 7.45, 0.74],
4831 assertArray(dali.vectorCross([0, 1, 0], [0, 0, 1]), [1, 0, 0], 0.001);
4833 assertArray(dali.vectorAdd([1, 2, 3], [2, 3, 4], [1, 1, 1]), [4, 6, 8], 0.001);
4835 var mq = dali.vectorAdd(dali.vectorCross([0.045, 0.443, 0.432], [0.612, 0.344, -0.144]),
4836 dali.vectorByScalar([0.612, 0.344, -0.144], 0.784),
4837 dali.vectorByScalar([0.045, 0.443, 0.432], 0.697));
4839 assertArray(dali.quatByQuat([0.045, 0.443, 0.432, 0.784], [0.612, 0.344, -0.144, 0.697]), [mq[0], mq[1], mq[2], (0.784 * 0.697) - dali.vectorDot([0.045, 0.443, 0.432], [0.612, 0.344, -0.144])],
4843 console.log(" -> ok test_js_math");
4846 Test.prototype.getset = function() {
4848 console.log("test_getset...");
4852 var actor = col.red;
4853 var p = actor.position;
4854 actor.position = [1, 1, 1];
4855 assert(compareArrays(actor.position, [1, 1, 1]));
4856 actor.position = [3, 3, 3];
4857 assert(compareArrays(actor.position, [3, 3, 3]));
4861 console.log(" -> ok test_getset");
4864 Test.prototype.animation_spline = function() {
4866 console.log("test_animation_spline...");
4870 var actor = col.red;
4872 var a = new dali.Animation(0);
4873 var path = new dali.Path();
4878 [190.0, -150.0, 0.0]
4881 assert(compareArrays(path.points, [
4884 [190.0, -150.0, 0.0]
4887 dali.generateControlPoints(path, 0.35);
4889 assert(compareArrays(path.controlPoints, [
4891 [-66.94940948486328, 76.16658020019531, 0],
4892 [101.31224060058594, 60.66832733154297, 0],
4897 a.animatePath(actor, path, [1, 0, 0], dali.AlphaFunction.LINEAR, 0, 3);
4900 function checkPos() {
4901 assert(actor.position = path.points[2]);
4906 console.log(" -> ok test_animation_spline");
4909 window.setTimeout(checkPos, 4000);
4912 Test.prototype.animation = function() {
4914 console.log("test_animation...");
4918 var actor = col.red;
4920 var a = new dali.Animation(0);
4922 a.animateTo(actor, "position", [20, 0, 0], dali.AlphaFunction.LINEAR, 0, 3);
4925 function checkAnimateBetween() {
4926 assert(actor.position = [0, 0, -30]);
4931 console.log(" -> ok test_animation");
4934 function checkAnimateBy() {
4935 assert(actor.position = [120, 100, 0]);
4938 a.animateBetween(actor,
4939 "position", [ [ 0, [10,20,30] ],
4940 [ 1.0,[0, 0, -30] ] ],
4946 window.setTimeout(checkAnimateBetween, 4000);
4949 function checkAnimateTo() {
4950 assert(actor.position = [20, 0, 0]);
4951 actor.position = [100, 100, 0];
4953 a.clear(); // var a = new dali.Animation(0);
4955 a.animateBy(actor, "position", [20, 0, 0], dali.AlphaFunction.LINEAR, 0, 3);
4958 window.setTimeout(checkAnimateBy, 4000);
4961 window.setTimeout(checkAnimateTo, 4000);
4964 Test.prototype.onePane = function() {
4965 var w = dali.canvas.width;
4966 var h = dali.canvas.height;
4967 var col = dali.getClearColor(0);
4969 dali.setFrontView(0, 0, 0, w, h);
4970 dali.setClearColor(0, col);
4973 Test.prototype.threePane = function() {
4974 var w = dali.canvas.width;
4975 var h = dali.canvas.height;
4977 dali.setClearColor(0, [0.4, 0, 0, 1]);
4978 dali.setClearColor(1, [0, 0.4, 0, 1]);
4979 dali.setClearColor(2, [0, 0, 0.4, 1]);
4980 dali.setFrontView(0, 0, 0, w / 2 - 5, h);
4981 dali.setTopView(1, w / 2, 0, w / 2, h / 2 - 5);
4982 dali.setRightView(2, w / 2, h / 2 + 5, w / 2, h / 2 - 5);
4985 Test.prototype.twoPane = function() {
4986 var w = dali.canvas.width;
4987 var h = dali.canvas.height;
4989 dali.setFrontView(0, 0, 0, w / 2 - 10, h);
4990 dali.setTopView(1, 210, 0, w / 2 - 10, h);
4991 dali.setClearColor(0, [0.4, 0, 0, 1]);
4992 dali.setClearColor(1, [0, 0.4, 0, 1]);
4995 Test.prototype.views = function() {
4997 console.log("test_views");
4999 var w = dali.canvas.width;
5000 var h = dali.canvas.height;
5001 var col = dali.getClearColor(0);
5006 dali.setFrontView(0, 0, 0, w, h);
5007 dali.setClearColor(0, col);
5012 dali.setClearColor(0, [0.4, 0, 0, 1]);
5013 dali.setClearColor(1, [0, 0.4, 0, 1]);
5014 dali.setClearColor(2, [0, 0, 0.4, 1]);
5015 dali.setFrontView(0, 0, 0, w / 2 - 5, h);
5016 dali.setTopView(1, w / 2, 0, w / 2, h / 2 - 5);
5017 dali.setRightView(2, w / 2, h / 2 + 5, w / 2, h / 2 - 5);
5019 window.setTimeout(one, 1000);
5024 dali.setFrontView(0, 0, 0, w / 2 - 10, h);
5025 dali.setTopView(1, 210, 0, w / 2 - 10, h);
5026 dali.setClearColor(0, [0.4, 0, 0, 1]);
5027 dali.setClearColor(1, [0, 0.4, 0, 1]);
5029 window.setTimeout(three, 1000);
5034 window.setTimeout(two, 1000);
5037 Test.prototype.blinking = function() {
5039 var layer = new dali.Layer();
5040 layer.name = "frameLayer";
5041 dali.stage.add(layer);
5043 var a = dali.createSolidColorActor([0.5, 0.5, 0.5, 1],
5044 false, [0, 0, 0, 1],
5046 a.size = [100,100,1];
5050 var camera = firstCamera();
5052 camera.position = [ camera.position[0]+10, camera.position[1]+20, camera.position[2] + 10 ];
5054 layer.delete(); // wrapper
5055 a.delete(); // wrapper
5056 camera.delete(); // wrapper
5059 Test.prototype.uniformMetaData = function() {
5060 for(var i = 0; i < shaderSources.length; i++) {
5061 console.log(dali.uniformMetaData(shaderSources[i].vertex, shaderSources[i].fragment));
5065 Test.prototype.signals = function() {
5067 console.log("test_signals...");
5069 function onStage() {
5070 console.log(" -> ok test signals");
5071 //eventHandler.onTouched(actor);
5074 var actor = new dali.Actor();
5075 actor.parentOrigin = [0.5, 0.5, 0.5];
5076 actor.anchorPoint = [0.5, 0.5, 0.5];
5077 actor.text = "actor";
5078 actor.name = actor.text;
5079 actor.size = [100, 100, 1];
5080 actor.position = [0, 0, 10];
5082 actor.connect("on-stage", onStage);
5084 dali.stage.add(actor);
5087 Test.prototype.shaderInfo = function() {
5089 var info = new dali.ShaderInfo();
5095 "attribute mediump vec3 aPosition;\n" +
5096 "attribute mediump vec2 aTexCoord;\n" +
5097 "varying mediump vec2 vTexCoord;\n" +
5098 "uniform mediump vec3 uSize;\n" +
5099 "// uniform mediump vec3 unusedUniform;\n" +
5100 "uniform mediump mat4 uModelView;\n" +
5101 "uniform mediump mat4 uProjection;\n" +
5103 "void main(void)\n" +
5105 " gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\n" +
5106 " gl_Position.xyz *= uSize;\n" +
5107 " vTexCoord = aTexCoord;\n" +
5110 fragment = "precision mediump float;\n" +
5112 "uniform sampler2D sTexture;\n" +
5113 "uniform mediump vec4 uMyColor; // {min:[0,0,0,0], max:[1,1,1,1]}\n" +
5114 "uniform mediump vec4 uColor;\n" +
5115 "varying mediump vec2 vTexCoord;\n" +
5119 " gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor * uMyColor;\n" +
5122 var canvas = document.createElement("canvas");
5123 var meta = info.fromCompilation(canvas.getContext("webgl"), vertex, fragment);
5125 var uniforms = { uSize: 1,
5132 assert(meta.hasError === false);
5134 var metaUniformName;
5137 for(name in uniforms) {
5139 for(metaUniformName in meta.uniforms) {
5140 if(metaUniformName === name) {
5145 assert(found, "missing:" + name);
5148 assert(compareArrays(meta.uniformUISpec.uMyColor.min, [0, 0, 0, 0]));
5149 assert(compareArrays(meta.uniformUISpec.uMyColor.max, [1, 1, 1, 1]));
5152 meta = info.fromRegEx(vertex, fragment);
5154 assert(meta.hasError === false);
5156 for(name in uniforms) {
5158 for(metaUniformName in meta.uniforms) {
5159 if(metaUniformName === name) {
5164 assert(found, "missing:" + name);
5167 assert(compareArrays(meta.uniformUISpec.uMyColor.min, [0, 0, 0, 0]));
5168 assert(compareArrays(meta.uniformUISpec.uMyColor.max, [1, 1, 1, 1]));
5170 console.log(" -> ok test shaderInfo");
5173 //------------------------------------------------------------------------------
5175 //------------------------------------------------------------------------------
5177 Test.prototype.regression = function() {
5180 this.registerProperty();
5184 this.animation_spline();
5185 // this.shadereffect1();
5191 Test.prototype.remote_execution = function() {
5196 Test.prototype.stacking = function() {
5199 eventHandler.selectActor( dali.stage.rootRotationActor );
5201 var a = dali.createSolidColorActor([1.0, 0.0, 0.0, 1.0],
5202 false, [0, 0, 0, 1],
5206 eventHandler.selectActor( a );
5208 var b = dali.createSolidColorActor([0.0, 0.0, 1.0, 1.0],
5209 false, [0, 0, 0, 1],
5213 a.sizeWidth = a.sizeHeight = 100;
5214 b.sizeWidth = b.sizeHeight = 50;
5222 var runTest = function(functionName) {
5227 dali.stage.setBackgroundColor([0.3, 0.3, 0.3, 1]);
5229 var test = dali[functionName]();
5233 if( !test.complete() )
5236 if( !test.complete() ) {
5237 window.setTimeout(checkPos, 500);
5239 console.log("test success");
5247 //------------------------------------------------------------------------------
5249 //------------------------------------------------------------------------------
5250 function animateShaderEffect2(actor) {
5252 var shader = new dali.ShaderEffect({
5253 vertex: shaderSource2.vertex,
5254 fragment: shaderSource2.fragment
5257 actor.setShaderEffect(shader);
5259 var final = [5, 5, 5, 1];
5261 var a = new dali.Animation(0);
5264 a.animateTo(shader, "weight", final, dali.AlphaFunction.LINEAR, 0, 3);
5273 var testfile = { // output from clara.io "Threejs scene output"
5275 "version": 4.3, // This isnt as its documented on threejs website
5276 "type": "Object", // and the general format looks more like format V3.
5277 "generator": "ObjectExporter"
5280 "uuid": "2f167add-e571-47c2-9da2-6f0e45cc1119",
5291 0.5, -0.5, -0.5, -0.5,
5294 0.5, -0.5, -0.5, -0.5, -0.5, -0.5,
5468 "uuid": "14D499F1-27EF-45BF-A457-FD24DAB11205",
5469 "type": "MeshPhongMaterial",
5471 "ambient": 11579568,
5476 "transparent": false,
5480 "uuid": "BFEFB48D-0E6E-46A6-8568-5E258BA17078",
5501 "uuid": "aa901bec-9e47-4b3b-bf3c-4efb0fe5d298",
5504 "geometry": "2f167add-e571-47c2-9da2-6f0e45cc1119",
5505 "material": "14D499F1-27EF-45BF-A457-FD24DAB11205",
5507 "receiveShadow": true,
5534 // Event/widget setup
5538 //------------------------------------------------------------------------------
5542 //------------------------------------------------------------------------------
5543 function rebuildDropdown(dropdownElement, db, dbStoreName, optionalItemDataFunc) {
5545 removeAllChildren(dropdownElement);
5547 var func = optionalItemDataFunc;
5549 func = function(name) {
5550 return [null, name];
5556 var names = db.getKeys(dbStoreName);
5558 for(var i = 0; i < names.length; i++) {
5559 li = document.createElement("li");
5560 var hrefText = func(names[i]);
5562 a = document.createElement("a");
5563 a.href = hrefText[0];
5564 a.text = hrefText[1];
5566 a = document.createElement("p");
5567 a.textContent = hrefText[1];
5570 dropdownElement.appendChild(li);
5575 //------------------------------------------------------------------------------
5579 //------------------------------------------------------------------------------
5584 self.modalQuestionYesFunction = null;
5585 self.modalQuestionNoFunction = null;
5587 var _modalQuestionYes = function() {
5588 if(self.modalQuestionYesFunction) {
5589 self.modalQuestionYesFunction();
5591 self.modalQuestionYesFunction = null;
5592 self.modalQuestionNoFunction = null;
5595 var _modalQuestionNo = function() {
5596 if(self.modalQuestionNo) {
5597 self.modalQuestionNo();
5599 self.modalQuestionYesFunction = null;
5600 self.modalQuestionNoFunction = null;
5603 var _modalInputOk = function() {
5604 if(self.modalInputOkFunction) {
5605 var input = $("#modalInputText")[0];
5606 self.modalInputOkFunction(input.value);
5608 self.modalInputOkFunction = null;
5609 self.modalInputCancelFunction = null;
5612 var _modalInputCancel = function() {
5613 if(self.modalInputCancel) {
5614 self.modalInputCancel();
5616 self.modalInputOkFunction = null;
5617 self.modalInputCancelFunction = null;
5620 $("#modalQuestionYes")[0].addEventListener("click", _modalQuestionYes);
5621 $("#modalQuestionNo")[0].addEventListener("click", _modalQuestionNo);
5623 self.modalInputYesFunction = null;
5624 self.modalInputNoFunction = null;
5626 $("#modalInputOk")[0].addEventListener("click", _modalInputOk);
5627 $("#modalInputCancel")[0].addEventListener("click", _modalInputCancel);
5631 UIApp.prototype.messageBoxHTML = function(innerHtmlText) {
5633 var modalBody = $("#modalCodeInfoBody")[0];
5634 removeAllChildren(modalBody);
5635 modalBody.innerHTML = innerHtmlText;
5636 $("#modalCodeInfo").modal("show");
5639 UIApp.prototype.messageBox = function(message) {
5641 this.messageBoxHTML("<p>" + message + "</p>");
5644 UIApp.prototype.questionBox = function(message, yesFunction, noFunction) {
5646 var modalBody = $("#modalQuestionBody")[0];
5647 removeAllChildren(modalBody);
5648 modalBody.innerHTML = "<p>" + message + "</p>";
5650 this.modalQuestionYesFunction = yesFunction;
5651 this.modalQuestionNoFunction = noFunction;
5653 $("#modalQuestion").modal("show");
5656 UIApp.prototype.codeInformationBox = function(code) {
5658 var modalBody = $("#modalCodeInfoBody")[0];
5659 removeAllChildren(modalBody);
5660 modalBody.innerHTML = "<pre>" + code + "</pre>";
5661 $("#modalCodeInfo").modal("show");
5664 UIApp.prototype.inputbox = function(message, okFunction, cancelFunction) {
5666 var modalBody = $("#modalInputBody")[0];
5667 removeAllChildren(modalBody);
5668 modalBody.innerHTML = "<p>" + message + "</p>";
5670 this.modalInputOkFunction = okFunction;
5671 this.modalInputCancelFunction = cancelFunction;
5673 $("#modalInput").modal("show");
5676 UIApp.prototype.getTypedBuffer = function(file, callback) {
5681 var reader = new FileReader();
5682 reader._theFilename = file.name;
5683 reader.onload = function(// e
5685 var uint8View = new Uint8Array(reader.result); // convert ArrayBuffer into a typed array?
5686 callback(file.name, uint8View);
5689 reader.readAsArrayBuffer(file);
5693 //------------------------------------------------------------------------------
5695 // Javascript UI Tab
5697 //------------------------------------------------------------------------------
5698 function UIJavascriptTab() {
5701 self.bufferPrepend = "Buffer Name:";
5703 this.addNewBuffer = function() {
5704 var alreadyExists = function() {
5705 self.addNewBuffer();
5708 var inputOk = function(name) {
5709 var data = database.readJavascript(name);
5711 uiApp.messageBox("Name already exsists", alreadyExists);
5713 var newData = {name: name, source: ""};
5714 database.writeJavascript(newData);
5715 self.rebuildDropdown(database);
5719 uiApp.inputbox("BufferName?", inputOk);
5723 this.renameBuffer = function() {
5724 var writeOK = function() {
5725 var openRequest = database.open();
5727 openRequest.onsuccess = function(event) {
5728 var db = event.target.result;
5729 self.rebuildDropdown(database);
5734 var inputOk = function(name) {
5735 var data = uiJavascriptTab.getData();
5737 database.writeJavascript(data, writeOK);
5740 uiApp.inputbox("BufferName?", inputOk);
5744 this.loadJavascript = function(name) {
5745 var data = database.readJavascript(name);
5748 var currentData = self.getData();
5750 database.writeJavascript(currentData);
5756 ace.require("ace/ext/language_tools");
5757 var editor = ace.edit("editorJavascript");
5759 var _thisFunctions = [];
5760 for(var attr in this) {
5761 if( !(attr.startsWith("_") || attr.startsWith("dynCall") || attr.startsWith("invoke") ) ) {
5762 if( typeof this[attr] === "function") {
5763 _thisFunctions.push( attr );
5769 getCompletions: function(theEditor, session, pos, prefix, callback) {
5771 if(prefix === "dali.") {
5773 if( !(attr.startsWith("_") || attr.startsWith("dynCall") || attr.startsWith("invoke") ) ) {
5774 if( typeof dali[attr] === "function") {
5775 wordlist.push( attr );
5780 wordlist = _thisFunctions;
5782 callback(null, wordlist.map(function(word) {
5792 editor.completers = [ myCompleter ];
5795 enableBasicAutocompletion: true,
5796 enableSnippets: true,
5797 enableLiveAutocompletion: true
5800 document.getElementById("btnJavascriptSourceJson").addEventListener(
5803 self.showModalJSON();
5806 document.getElementById("btnJavascriptClearRun").addEventListener(
5809 self.clearStageAndEval();
5812 document.getElementById("btnJavascriptRun").addEventListener(
5818 document.getElementById("btnJavascriptAddBuffer").addEventListener(
5821 self.addNewBuffer();
5824 document.getElementById("btnJavascriptRenameBuffer").addEventListener(
5827 self.renameBuffer();
5830 this.currentName = undefined;
5832 var names = database.readJavascriptNames();
5834 self.loadJavascript(names[0]); // load first javascript buffer
5839 UIJavascriptTab.prototype.getData = function() {
5841 var e = ace.edit("editorJavascript");
5842 var ascii = native2ascii(e.getSession().getValue());
5844 if(this.currentName !== undefined) {
5845 return { name: this.currentName,
5852 UIJavascriptTab.prototype.setData = function(data) {
5854 this.currentName = data.name;
5856 var editor = ace.edit("editorJavascript");
5857 editor.getSession().setValue(data.source);
5859 $("#textJavascriptName").html(this.bufferPrepend + data.name);
5863 UIJavascriptTab.prototype.showModalJSON = function() {
5865 var e = ace.edit("editorJavascript");
5866 var ascii = native2ascii(e.getSession().getValue());
5868 var lines = ascii.split("\n");
5870 var data = "{source:";
5872 for(var i = 0; i < lines.length; i++) {
5873 data += "\"" + lines[i].replace(/"/g, "\\\"") + "\\n\" +\n";
5878 // data = data.replace(/<([^ ]*)/g, "< $1"); // for loops are interpreted by browser as tags and dont print?
5880 // data = data.replace(/"/g, "\\\""); // for loops are interpreted by browser as tags and dont print?
5882 // data = data.replace(/<([^ ]*)/g, "< $1"); // for loops are interpreted by browser as tags and dont print?
5884 uiApp.codeInformationBox( data );
5888 UIJavascriptTab.prototype.clearStageAndEval = function() {
5890 var e = ace.edit("editorJavascript");
5891 var ascii = native2ascii(e.getSession().getValue());
5893 // as of ecma5 an indirect call like this is in global scope
5894 var globalEval = eval;
5898 UIJavascriptTab.prototype.eval = function() {
5900 var e = ace.edit("editorJavascript");
5901 var ascii = native2ascii(e.getSession().getValue());
5902 // as of ecma5 an indirect call like this is in global scope
5903 var globalEval = eval;
5907 UIJavascriptTab.prototype.rebuildDropdown = function(db) {
5909 rebuildDropdown( document.getElementById("javascriptDropDown"),
5913 return ["javascript:uiJavascriptTab.loadJavascript(\"" + name + "\")",
5920 //------------------------------------------------------------------------------
5924 //------------------------------------------------------------------------------
5927 * Get or create a dali image from the image buffer.
5929 * Global function for use in javascript buffers or the console.
5930 * @param {string} shader buffer name
5931 * @return {Object} dali.Image
5933 function imageFromUiBuffer(name) {
5935 var img = uiImageTab.getDaliImage(name);
5936 assert(img, "Could not find image:" + name);
5942 * Manages UI image tab.
5946 function UIImageTab() {
5949 this.imagesCreated = {}; // dali shader objects
5951 /********** methods **********/
5952 this.getBufferImageRGB = function(file, callback) {
5957 var img = new HTML5Image(); // the renamed Image()
5959 var objectUrl = window.URL.createObjectURL(file);
5961 img.onload = function( //e
5963 var imageCanvas = document.createElement("canvas");
5964 imageCanvas.width = img.width; // naturalWidth;
5965 imageCanvas.height = img.height; // naturalHeight;
5966 var context = imageCanvas.getContext("2d");
5967 context.drawImage(img, 0, 0 );
5968 var imageData = context.getImageData(0, 0, img.naturalWidth, img.naturalHeight); // <-ImageData
5969 callback(file.name, imageData);
5970 window.URL.revokeObjectURL(objectUrl);
5973 img.src = objectUrl;
5979 * Add new image data
5981 * @param {object} ImageData object
5983 this.addNewBuffer = function(imageData) {
5984 var alreadyExists = function() {
5985 self.addNewBuffer(imageData);
5988 var inputOk = function(name) {
5989 var oldData = database.readImage(name);
5991 uiApp.messageBox("Name already exsists", alreadyExists);
5993 database.writeImage(name, imageData);
5994 self.rebuildDropdown(database);
5998 uiApp.inputbox("BufferName?", inputOk);
6001 this.renameBuffer = function() {
6002 var inputOk = function(name) {
6003 var data = uiJavascriptTab.getData();
6005 database.writeJavascript(data);
6006 self.rebuildDropdown(database);
6009 uiApp.inputbox("BufferName?", inputOk);
6013 * Load image into the UI Image tab. (used for dynamically generated html dropdowns)
6015 * @param {string} name of image buffer
6017 this.loadImage = function(name) {
6018 self.setData( database.readImage(name) );
6021 /********** init **********/
6023 document.getElementById("btnImageAddBuffer").addEventListener(
6026 var fileInput = document.getElementById("btnImageAddBuffer");
6027 var file = fileInput.files[0];
6028 self.getBufferImageRGB(
6030 function(name, typedBuffer) {
6031 self.addNewBuffer(typedBuffer);
6036 document.getElementById("btnImageRenameBuffer").addEventListener(
6039 self.renameBuffer();
6042 var names = database.readImageNames();
6044 // load first image buffer
6045 self.setData( database.readImage(names[0]) );
6051 * Get or create a dali image from the image buffer.
6053 * @return {Object} dali.Image
6055 UIImageTab.prototype.getDaliImage = function(name) {
6057 if(name in this.imagesCreated) {
6058 return this.imagesCreated[name];
6060 var imageData = database.readImage(name);
6061 var uint8array = new Uint8Array(imageData.data);
6062 var image = new dali.BufferImage(uint8array, imageData.width, imageData.height, dali.PixelFormat.RGBA8888);
6063 this.imagesCreated[name] = image;
6068 UIImageTab.prototype.rebuildDropdown = function(db) {
6070 rebuildDropdown( document.getElementById("imageDropDown"),
6074 return ["javascript:uiImageTab.loadImage(\"" + name + "\")",
6080 UIImageTab.prototype.setData = function(data) {
6082 var imageViewCanvas = document.getElementById("imageViewCanvas"); // createElement("canvas");
6083 imageViewCanvas.width = data.width; // naturalWidth;
6084 imageViewCanvas.height = data.height; // naturalHeight;
6085 var context = imageViewCanvas.getContext("2d");
6086 context.putImageData( data, 0, 0 );
6090 //------------------------------------------------------------------------------
6094 //------------------------------------------------------------------------------
6096 * Get or create a dali shader from the shader buffer.
6098 * Global function for use in javascript buffers or the console.
6099 * @param {string} shader buffer name
6100 * @return {Object} dali.Shader
6102 function shaderFromUiBuffer(name) {
6104 var shader = uiShaderTab.getDaliShader(name);
6105 assert(shader, "Could not find/compile shader:" + name);
6109 function shaderInfoFromUiBuffer(name) {
6111 return uiShaderTab.getShaderInfo(name);
6115 * Manage shader UI tab events.
6116 * Holds dali shader objects created from shader buffers.
6119 * @return {Object} UIShaderTab
6121 function UIShaderTab() {
6124 this.bufferPrepend = "Buffer Name:";
6125 this.inhibitCheckAndUpdateShader = false;
6127 this.shadersCreated = {}; // dali shader objects
6128 document.getElementById("btnShaderAddBuffer").addEventListener(
6131 self.addNewBuffer();
6134 document.getElementById("btnShaderRenameBuffer").addEventListener(
6137 self.renameBuffer();
6140 document.getElementById("btnShaderSourceJSON").addEventListener(
6143 self.showModalJSON();
6146 document.getElementById("btnShaderSourceC").addEventListener(
6152 document.getElementById("btnShaderSourceJS").addEventListener(
6159 this.addNewBuffer = function() {
6160 var alreadyExists = function() {
6161 self.addNewBuffer();
6164 var inputOk = function(name) {
6165 var data = database.readJavascript(name);
6167 uiApp.messageBox("Name already exsists", alreadyExists);
6169 var newData = {name: name, fragment: "", vertex: "", hints: ""};
6170 database.writeShader(newData);
6171 self.rebuildDropDown(database);
6175 uiApp.inputbox("BufferName?", inputOk);
6179 this.renameBuffer = function() {
6180 var inputOk = function(name) {
6181 var data = self.getData();
6183 database.writeShader(data);
6184 $("#textShaderName").html(self.bufferPrepend + name);
6185 self.rebuildDropdown(database);
6188 uiApp.inputbox("BufferName?", inputOk);
6191 this.loadShader = function(name) {
6193 var data = database.readShader(name);
6196 var currentData = self.getData();
6198 database.writeShader(currentData);
6201 // so that we can change vertex & fragment as an atomic operation
6202 self.inhibitCheckAndUpdateShader = true;
6204 // otherwise this will trigger a checkAndUpdateShader() after
6205 // we've only changed the vertex shader (ie with mismatching fragment shader)
6208 self.inhibitCheckAndUpdateShader = false;
6210 self.checkAndUpdateShader();
6215 * Set the UI tab data of vertex/fragment strings.
6217 * @param {Object} shader data object
6219 this.setData = function(options) {
6225 vertex = options.vertex;
6226 fragment = options.fragment;
6227 hints = options.hints;
6229 $("#requiresSelfDepthTest").prop("checked", (hints.search("requiresSelfDepthTest") >= 0));
6230 $("#outputIsTransparent").prop("checked", (hints.search("outputIsTransparent") >= 0));
6231 $("#outputIsOpaque").prop("checked", (hints.search("outputIsOpaque") >= 0));
6232 $("#modifiesGeometry").prop("checked", (hints.search("modifiesGeometry") >= 0));
6234 // do this after setting up the checkboxes as it will trigger storing the checkbox state
6235 // in the actorIdToShaderSet map
6236 e = ace.edit("editorVertex");
6237 e.getSession().setValue(vertex);
6239 e = ace.edit("editorFragment");
6240 e.getSession().setValue(fragment);
6242 $("#textShaderName").html(self.bufferPrepend + options.name);
6246 var shaderTab = $("#tab2primary")[0];
6247 var lastClassName = shaderTab.className;
6248 window.setInterval( function() {
6249 var className = shaderTab.className;
6250 if (className !== lastClassName) {
6252 // an attempt to get the editboxes to display the correct content.
6253 // when you setValue() the content and they aren't visible then
6254 // they dont update properly until you click in the box
6256 var e = ace.edit("editorVertex");
6257 e.setShowInvisibles(true);
6258 e.setShowInvisibles(false);
6260 e = ace.edit("editorFragment");
6261 e.setShowInvisibles(true);
6262 e.setShowInvisibles(false);
6263 lastClassName = className;
6267 var names = database.readShaderNames();
6269 // load first image buffer
6270 self.setData( database.readShader(names[0]) );
6273 var editor = ace.edit("editorVertex");
6274 editor.getSession().addEventListener("change", function() {
6275 self.checkAndUpdateShader();
6278 editor = ace.edit("editorFragment");
6279 editor.getSession().addEventListener("change", function() {
6280 self.checkAndUpdateShader();
6286 * Get or create a dali shader from the shader buffer.
6288 * @return {Object} dali.Shader
6290 UIShaderTab.prototype.getDaliShader = function(name) {
6292 if(name in this.shadersCreated) {
6293 return this.shadersCreated[name].daliShader;
6296 var data = database.readShader(name);
6298 if(this.isCompilable(data)) {
6299 var daliShader = new dali.Shader(data.vertex,
6301 this.getDaliShaderHints(data.hints));
6303 var shaderInfo = new dali.ShaderInfo();
6304 var info = shaderInfo.fromCompilation( canvas.getContext("webgl"),
6308 for(name in info.uniformUISpec) {
6309 var metaData = info.uniformUISpec[name];
6310 if("default" in metaData) {
6311 // could provide automatic defaults
6312 daliShader.registerAnimatedProperty(name, metaData.default);
6317 this.shadersCreated[name] = data;
6318 this.shadersCreated[name].daliShader = daliShader;
6322 console.log("Requested shader could not be compiled:" + name);
6330 * Get info for a shader. See getInfo()
6332 * @return {Object} dali.Shader
6335 UIShaderTab.prototype.getShaderInfo = function(name) {
6337 var data = database.readShader(name);
6338 return this.getInfo(data);
6342 * Rebuild UI tab drop down selection.
6344 * @param {Object} Database
6346 UIShaderTab.prototype.rebuildDropdown = function(db) {
6348 rebuildDropdown( document.getElementById("shaderDropDown"),
6352 return ["javascript:uiShaderTab.loadShader(\"" + name + "\")",
6360 * Get the UI tab data with vertex/fragment strings.
6362 * @return {Object} shader data object
6364 UIShaderTab.prototype.getData = function() {
6366 var e = ace.edit("editorVertex");
6368 ret.name = $("#textShaderName").text().substr(this.bufferPrepend.length);
6369 ret.vertex = native2ascii(e.getSession().getValue());
6370 e = ace.edit("editorFragment");
6371 ret.fragment = native2ascii(e.getSession().getValue());
6374 if( $("#requiresSelfDepthTest")[0].checked ) {
6375 ret.hints += " requiresSelfDepthTest";
6377 if( $("#outputIsTransparent")[0].checked ) {
6378 ret.hints += " outputIsTransparent";
6380 if( $("#outputIsOpaque")[0].checked ) {
6381 ret.hints += " outputIsOpaque";
6383 if( $("#modifiesGeometry")[0].checked ) {
6384 ret.hints += " modifiesGeometry";
6391 * Get dali shader hints from hints string.
6393 * @param {string} hints string (space separated)
6394 * @return {integer} or'd hints to pass to Dali
6396 UIShaderTab.prototype.getDaliShaderHints = function(hintsString) {
6400 if(hintsString.search("requiresSelfDepthTest") >= 0) {
6401 ret += dali.ShaderHints.REQUIRES_SELF_DEPTH_TEST;
6403 if(hintsString.search("outputIsTransparent") >= 0) {
6404 ret += dali.ShaderHints.OUTPUT_IS_TRANSPARENT;
6406 if(hintsString.search("outputIsOpaque") >= 0) {
6407 ret += dali.ShaderHints.OUTPUT_IS_OPAQUE;
6409 if(hintsString.search("modifiesGeometry") >= 0) {
6410 ret += dali.ShaderHints.MODIFIES_GEOMETRY;
6416 * Get information on a shader
6417 * If hasError==true then attributes etc will be empty. ie it must compile.
6419 * Compile the shader with webGL. Query webGL for meta data.
6421 * @param {object} data object. {vertex:"", fragment:""}
6422 * @return {object} info metadata object
6424 * // attributes: [],
6426 * // attributeCount: 0,
6427 * // uniformCount: 0,
6428 * // hasError: false, // compiles without error
6429 * // vertexError: "",
6430 * // fragmentError: "",
6436 // uniform vec3 uMe; // gui:number, min:0, max:1, default: 0.5
6437 // uniform vec3 uMe; // gui:slider, min:0, max:1, default: 0.5
6438 // uniform vec3 uMe; // gui:color, min:[0,0,0,0] max:[1,1,1,1], default: [0,0,0,1]
6440 UIShaderTab.prototype.getInfo = function(data) {
6443 var canvas = document.getElementById("canvas");
6445 var info = new dali.ShaderInfo();
6447 return info.fromCompilation(canvas.getContext("webgl"),
6453 * Check a shader can compile. Shader given as data object with vertex/fragment buffers.
6455 * Compile the shader with webGL as a preprocess step to giving it to Dali.
6457 * @param {string} shader buffer name
6458 * @return {Boolean} true if the shader compiles ok.
6460 UIShaderTab.prototype.isCompilable = function(data) {
6462 var info = this.getInfo(data);
6463 return !info.hasError;
6468 * Check the shader in the UI tab can compile and if so update the saved dali.Shader object.
6469 * (Does not create the dali.Shader object)
6471 * For use on an event for continuous shader checking.
6473 * @param {string} shader buffer name
6474 * @return {Object} dali.Shader
6476 UIShaderTab.prototype.checkAndUpdateShader = function() {
6478 if(this.inhibitCheckAndUpdateShader) {
6482 var options = this.getData();
6484 var info = this.getInfo(options);
6486 if(!info.hasError) {
6487 if( options.name in this.shadersCreated ) {
6488 if("daliShader" in this.shadersCreated[options.name]) {
6489 // setting shader.program= doesn't seem to recompile the shader?
6490 // this.shadersCreated[options.name].daliShader.delete(); no delete; could be held elsewhere
6491 delete this.shadersCreated[options.name];
6496 var vertexPrepend = "";
6497 var fragmentPrepend = "";
6507 var textShaderErrors = $("#textShaderErrors");
6509 textShaderErrors.value = "";
6511 editor = ace.edit("editorVertex");
6512 if (info.hasError && info.vertexError) {
6513 editor.getSession().setOption("useWorker", false);
6514 textShaderErrors.value = "VERTEX:\n" + info.vertexError;
6515 errors = info.vertexError.split("\n");
6516 count = vertexPrepend.split("\n").length;
6517 for(i = 0; i < errors.length; i++) {
6519 description = errors[i].split(":");
6520 col = Number(description[1]);
6522 line = Number(description[2]);
6526 editor.getSession().setAnnotations([{row: line - count, column: col, text: errors[i], type: "error"}]);
6530 editor.getSession().setOption("useWorker", true);
6531 editor.getSession().setAnnotations([]);
6534 editor = ace.edit("editorFragment");
6535 if (info.hasError && info.fragmentError) {
6536 editor.getSession().setOption("useWorker", false);
6537 textShaderErrors.value += "FRAGMENT:\n" + info.fragmentError;
6538 errors = info.fragmentError.split("\n");
6539 count = fragmentPrepend.split("\n").length;
6540 for(i = 0; i < errors.length; i++) {
6542 description = errors[i].split(":");
6543 col = Number(description[1]);
6545 line = Number(description[2]);
6549 editor.getSession().setAnnotations([{row: line - count, column: col, text: errors[i], type: "error"}]);
6553 editor.getSession().setOption("useWorker", true);
6554 editor.getSession().setAnnotations([]);
6557 if(!info.hasError) {
6558 database.writeShader(options);
6564 UIShaderTab.prototype.showModalC = function() {
6567 var info = this.getData();
6569 var data = "#define MAKE_STRING(A)#A\n\n" +
6570 "std::string vertexShader = MAKE_STRING(\n";
6572 var lines = info.vertex.split("\n");
6573 for(i = 0; i < lines.length; i++) {
6574 data += lines[i] + "\n";
6578 data += "std::string fragShader = MAKE_STRING(\n";
6580 lines = info.fragment.split("\n");
6581 for(i = 0; i < lines.length; i++) {
6582 data += lines[i] + "\n";
6586 data += "ShaderEffect shaderEffect;\n" +
6587 "shaderEffect = ShaderEffect::New( vertexShader, fragmentShader,\n" +
6588 " ShaderEffect::ShaderHint( " + info.hints + " ) )\n";
6590 data = data.replace(/<([^ ]*)/g, "< $1"); // for loops are interpreted by browser as tags and dont print?
6592 uiApp.codeInformationBox( data );
6594 // data = data.replace(/</g, "<");
6595 // data = data.replace(/>/g, ">");
6597 // var myWindow = window.open("data:text/html," + encodeURIComponent(data));
6598 // // "_blank"); // , "width=00,height=100");
6599 // myWindow.focus();
6603 UIShaderTab.prototype.showModalJS = function() {
6606 var info = this.getData();
6608 var data = "var shaderOptions = {vertex:\n";
6610 var lines = info.vertex.split("\n");
6611 for(i = 0; i < lines.length; i++) {
6612 data += " \"" + lines[i] + "\\n\" +\n";
6616 data += " fragment:\n";
6617 lines = info.fragment.split("\n");
6618 for(i = 0; i < lines.length; i++) {
6619 data += " \"" + lines[i] + "\\n\" +\n";
6623 data += " geometryType: \"" + info.geometryType + "\",\n";
6624 data += " geometryHints: \"" + info.geometryHints + "\"\n";
6627 data = data.replace(/<([^ ]*)/g, "< $1"); // for loops are interpreted by browser as tags and dont print?
6628 // data = data.replace(/</g, "<");
6629 // data = data.replace(/>/g, ">");
6631 // var myWindow = window.open("data:text/html," + encodeURIComponent(data));
6632 // // "_blank"); // , "width=00,height=100");
6633 // myWindow.focus();
6635 var modalBody = $("#modalCodeInfoBody")[0];
6636 removeAllChildren(modalBody);
6637 modalBody.innerHTML = "<code><pre>" + data + "</pre></code>";
6638 $("#modalCodeInfo").modal("show");
6642 UIShaderTab.prototype.showModalJSON = function() {
6644 var info = this.getData();
6646 var hints = ""; // tbd
6648 var vertex = info.vertex.replace(/\n/g, "\\n");
6649 var fragment = info.fragment.replace(/\n/g, "\\n");
6651 var data = "{\"shader-effects\": {\n" +
6652 " \"" + "effect" + "\": {\n" +
6653 " \"program\": {\n" +
6654 " \"vertexPrefix\": \"\",\n" +
6655 " \"vertex\": \"" + vertex + "\",\n" +
6656 " \"fragmentPrefix\": \"\",\n" +
6657 " \"fragment\": \"" + fragment + "\"\n" +
6659 " \"geometry-hints\": \"" + hints + "\",\n" +
6660 " \"grid-density\": \"" + "0" + "\",\n" +
6662 " \"filename\": \"\"\n" +
6668 data = data.replace(/<([^ ]*)/g, "< $1"); // for loops are interpreted by browser as tags and dont print?
6670 uiApp.codeInformationBox( data );
6674 document.getElementById("btnRewriteDatabase").addEventListener("click", function(// e
6680 consoleLogSuccess("database.delete")();
6681 window.setTimeout(function () {
6682 window.location.reload(true); // forces a reload from the server
6685 consoleLogErrorEvent, // fail
6686 consoleLogErrorEvent // blocked
6692 window.setTimeout(initDB, 1000);
6695 function updateStatistics(eventHandler){
6698 var elem = $("#statistics")[0];
6700 var actor = eventHandler.touchedActor;
6702 var usedRootLayer = false;
6705 usedRootLayer = true;
6706 actor = dali.stage.getRootLayer();
6709 var rt = dali.stage.getRenderTaskList().getTask(0);
6713 xy = dali.screenToLocal(eventHandler.mouseX, eventHandler.mouseY,
6719 var screenxy = dali.worldToScreen(actor.position, rt);
6724 name = "Root Actor";
6730 if(eventHandler.mouseDownPosition) {
6731 px = eventHandler.mouseDownPosition[0].toFixed(prec);
6732 py = eventHandler.mouseDownPosition[1].toFixed(prec);
6735 elem.innerHTML = name + " (" + actor.getId() + ") '" + actor.name + "'" + "<br>" +
6736 "Screen:" + eventHandler.mouseX.toFixed(prec) + "," + eventHandler.mouseY.toFixed(prec) + "<br>" +
6737 name + " Screen To Local:" + xy[0].toFixed(prec) + "," + xy[1].toFixed(prec) + "<br>" +
6738 name + " To Screen:" + screenxy[0].toFixed(prec) + "," + screenxy[1].toFixed(prec) + "<br>" +
6739 name + " Drag dx/dy:" + eventHandler.dragDx.toFixed(prec) + "," + eventHandler.dragDy.toFixed(prec) + "<br>" +
6740 name + " pos:" + actor.position + "<br>"+
6741 name + " pos:" + px + "," + py + "<br>";
6743 if(usedRootLayer) { // dont delete eventHandler object
6744 actor.delete(); // wrapper
6747 rt.delete(); // wrapper
6752 $(".btn-toggle").click(function() {
6754 $(this).find(".btn").toggleClass("active");
6756 if($(this).find(".btn-primary").size() > 0) {
6757 $(this).find(".btn").toggleClass("btn-primary");
6760 $(this).find(".btn").toggleClass("btn-default");
6762 if(this.id === "loop") {
6763 var looping = $(this).find("#loopOn").hasClass("active");
6764 animationList[animationSelectionIndex].looping = looping;
6765 animationList[animationSelectionIndex].dirtyData = true;
6768 if(this.id === "endAction") {
6769 var bake = $(this).find("#endBake").hasClass("active");
6771 animationList[animationSelectionIndex].endAction = "Bake";
6773 animationList[animationSelectionIndex].endAction = "Discard";
6775 animationList[animationSelectionIndex].dirtyData = true;
6780 //------------------------------------------------------------------------------
6782 // Database; access to browser indexed db
6784 //------------------------------------------------------------------------------
6785 function Database() {
6787 this.currentVersion = 1;
6788 this.name = "dalitoy";
6792 this.copyDBStore = function(db, dbStoreName, andClose) {
6793 var tr = db.transaction([dbStoreName], "readonly");
6794 var store = tr.objectStore(dbStoreName);
6795 var cursor = store.openCursor();
6796 self.data[dbStoreName] = {};
6797 cursor.onsuccess = function(e) {
6798 var res = e.target.result; // another cursor
6800 self.data[dbStoreName][res.key] = res.value;
6808 cursor.onerror = consoleLogErrorEvent;
6811 this.initializeData = function(db) {
6812 self.copyDBStore(db, "javascript");
6813 self.copyDBStore(db, "images");
6814 self.copyDBStore(db, "shaders", true); // true to close db (last copy)
6820 Database.prototype.open = function() {
6822 return window.indexedDB.open(this.name, this.currentVersion);
6825 Database.prototype.delete = function(onsuccess, onerror, onblocked) {
6827 var req = window.indexedDB.deleteDatabase(this.name);
6828 req.onsuccess = onsuccess;
6829 req.onerror = onerror;
6830 req.onblocked = onblocked;
6834 Database.prototype.upgrade = function(db, oldVersion) {
6837 if (oldVersion < 1) {
6838 // Version 1 is the first version of the database.
6839 var store = db.createObjectStore("shaders", {keyPath: "name"});
6841 for(i = 0; i < shaderSources.length; i++) {
6842 store.put( shaderSources[i] );
6845 store = db.createObjectStore("javascript", {keyPath: "name"});
6846 for(i = 0; i < javascriptSources.length; i++) {
6847 store.put( javascriptSources[i] );
6850 store = db.createObjectStore("images");
6852 // default images in html page
6853 store.put( getStockImageData(1), "girl1" );
6854 store.put( getStockImageData(2), "funnyface" );
6855 store.put( getStockImageData(3), "ducks" );
6856 store.put( getStockImageData(4), "field" );
6860 Database.prototype.init = function() {
6864 if("indexedDB" in window) {
6865 var openRequest = this.open();
6867 openRequest.onupgradeneeded = function(event) {
6868 var db = event.target.result;
6869 database.upgrade(db, event.oldVersion);
6870 //self.initializeData(db);
6873 openRequest.onsuccess = function(event) {
6874 var db = event.target.result;
6875 self.initializeData(db);
6878 openRequest.onerror = consoleLogErrorEvent;
6884 Database.prototype.initTabs = function(jstab, imagetab, shadertab) {
6886 jstab.rebuildDropdown(this);
6887 imagetab.rebuildDropdown(this);
6888 shadertab.rebuildDropdown(this);
6891 Database.prototype.writeJavascript = function(data, callback) {
6894 this.data.javascript[data.name] = data;
6896 var openRequest = this.open();
6898 openRequest.onsuccess = function(event) {
6899 var db = event.target.result;
6900 var tr = db.transaction(["javascript"], "readwrite");
6901 var store = tr.objectStore("javascript");
6903 var ob = store.put(data);
6904 self.data.javascript[data.name] = data;
6906 ob.onsuccess = callback;
6907 // ob.onerror = errorCallback;
6908 ob.onerror = consoleLogErrorEvent;
6913 openRequest.onerror = consoleLogErrorEvent;
6917 Database.prototype.readJavascript = function(name) {
6919 return this.data.javascript[name];
6922 Database.prototype.readJavascriptNames = function() {
6924 return this.getKeys("javascript");
6927 Database.prototype.readKeys = function(dbStoreName, callback) {
6930 var openRequest = database.open();
6932 openRequest.onsuccess = function(event) {
6933 var db = event.target.result;
6934 var tr = db.transaction([dbStoreName], "readonly");
6935 var store = tr.objectStore(dbStoreName);
6936 var cursor = store.openCursor();
6938 cursor.onsuccess = function(e) {
6939 var res = e.target.result; // another cursor
6947 cursor.onerror = consoleLogErrorEvent;
6953 Database.prototype.getKeys = function(dbStoreName) {
6956 var o = this.data[dbStoreName];
6957 for(var name in o) {
6963 Database.prototype.writeShader = function(data) {
6967 this.data.shaders[data.name] = data;
6969 // write the indexDB too
6970 var openRequest = this.open();
6972 openRequest.onsuccess = function(event) {
6973 var db = event.target.result;
6974 var tr = db.transaction(["shaders"], "readwrite");
6975 var store = tr.objectStore("shaders");
6977 var ob = store.put(data);
6979 //ob.onsuccess = callback;
6980 ob.onerror = consoleLogErrorEvent;
6985 openRequest.onerror = consoleLogErrorEvent;
6989 Database.prototype.readShader = function(name) {
6991 return this.data.shaders[name];
6994 Database.prototype.readShaderNames = function() {
6996 return this.getKeys("shaders");
6999 Database.prototype.readObjectStore = function(objectStoreName, recordName, callback, errorCallback) {
7001 var openRequest = window.indexedDB.open(this.name, this.currentVersion);
7003 openRequest.onsuccess = function(event) {
7004 var db = event.target.result;
7006 var transaction = db.transaction([objectStoreName], "readonly");
7007 var objectStore = transaction.objectStore(objectStoreName);
7010 var ob = objectStore.get(recordName);
7012 ob.onsuccess = function(e) {
7013 // read with undefined is still a success (should probably do this with cursor?)
7014 if(e.target.result) {
7015 callback(e.target.result);
7021 ob.onerror = errorCallback;
7026 openRequest.onerror = errorCallback;
7030 Database.prototype.writeImage = function(name, data) {
7033 this.data.images[name] = data;
7035 var openRequest = this.open();
7037 openRequest.onsuccess = function(event) {
7038 var db = event.target.result;
7039 var tr = db.transaction(["images"], "readwrite");
7040 var store = tr.objectStore("images");
7042 var ob = store.put(data, name);
7044 //ob.onsuccess = callback;
7045 ob.onerror = consoleLogErrorEvent;
7050 openRequest.onerror = consoleLogErrorEvent;
7054 Database.prototype.readImage = function(name) {
7056 return this.data.images[name];
7059 Database.prototype.readImageNames = function() {
7061 return this.getKeys("images");
7064 //------------------------------------------------------------------------------
7066 // app init functions
7068 //------------------------------------------------------------------------------
7071 database = new Database();
7072 window.setTimeout(init, 500);
7078 // var root = dali.stage.getRootLayer();
7079 // root.name = "*" + root.name; // * at start means non selectable by convention
7080 // root.delete(); // wrapper
7082 // database = new Database();
7086 uiApp = new UIApp();
7088 uiJavascriptTab = new UIJavascriptTab();
7090 uiImageTab = new UIImageTab();
7092 uiShaderTab = new UIShaderTab();
7094 database.initTabs(uiJavascriptTab, uiImageTab, uiShaderTab);
7096 $("a[rel=popover]").tooltip();
7098 Object.defineProperty(dali, "shader", {
7100 configurable: false,
7106 Object.defineProperty(dali, "actor", {
7108 configurable: false,
7114 Object.defineProperty(dali, "animation", {
7116 configurable: false,
7118 return getAnimation();
7122 eventHandler.handlersMouseMove.push(updateStatistics);
7126 ////////////////////////////////////////////////////////////////////////////////////////////////////
7128 dali.postRenderFunction = undefined;