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(\"touch\", 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 // mixColor : [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("touch", "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, touch){
4126 for(var i = 0; i < touch.points.length; i++) {
4127 if(touch.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 = "touch";
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("touch", "inside", 0, 100),
4157 // when("myimage", "touch",
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");
4233 for(ai = 0; ai < actors.length; ai++) {
4234 actor = root.findChildByName( actors[ai] );
4235 actor.connect( signal, f );
4240 // _connectToCondition( actors, condition, _makeCallback(arguments) );
4241 root = dali.stage.getRootLayer();
4242 f = _makeCallback(arguments);
4244 for(ai = 0; ai < actors.length; ai++) {
4245 actor = root.findChildByName( actors[ai] );
4246 actor.setPropertyNotification(condition.property,
4247 condition.type, condition.arg0, condition.arg1,
4252 // when("myimage", condition("touch", "inside", 0, 100),
4254 // when("myimage", "touch",
4256 // dali.ActorWrapper.prototype.connect = function(signalName, callback) {
4257 // if(d.action === "set") {
4258 // var animationActors = d.actors;
4259 // if( animationActors.length === 0 ) {
4260 // animationActors = actors;
4262 // var a = new dali.Animation(0);
4263 // // dali.AnimationWrapper.prototype.animateTo = function(object, propertyName, value, alphaFunction, delay, duration) {
4264 // //dali.AnimationWrapper.prototype.animateBy = function(object, propertyName, value, alphaFunction, delay, duration) {
4265 // //dali.AnimationWrapper.prototype.animatePath = function(object, pathObject, forward, alphaFunction, delay, duration) {
4266 // for(var ai =0; ai < animationActors.length; ai++) {
4267 // for(var animi =0; animi < d.animation; animi++) {
4268 // var animEntry = d.animation[animi];
4269 // if( d.animate == "animatePath") {
4270 // a.animatePath(animationActors[ai], animEntry.path, animEntry.forward, animEntry.alpha,
4271 // animEntry.delay, animEntry.duration);
4273 // } else if( d.animate == "animateBetween") {
4274 // a.animateBetween(animationActors[ai], d.property,
4275 // animEntry.fromValue, animEntry.toValue,
4276 // animEntry.alpha, animEntry.delay, animEntry.duration);
4278 // // call animateTo,animateBy,
4279 // a[animEntry.animate](animationActors[ai], d.property, animEntry.value, animEntry.alpha,
4280 // animEntry.delay, animEntry.duration);
4285 // var animiations = [];
4287 // for(var i = 2; i < arguments.length; i++) {
4288 // var d = arguments[i];
4289 // if( d.action === "set" ) {
4290 // // var ret = { action: "set",
4292 // // property: null,
4293 // // condition: null,
4296 // for(var ai = 0; ai < d.actors.length; ai++) {
4301 // for(var j = 0; j < d.length; j++) {
4302 // if(signal) { // then its signal actions
4304 // templates[actorName].signals.push(d[j]);
4305 // } else { // its property notifications
4306 // d.condition = condition;
4307 // d.property = property;
4308 // templates[actorName].notifications.push(d[j]);
4312 // // but we could also be specifying a property notification so...
4316 // if(typeof arguments[index] === "string") {
4317 // var lowerCase = arguments[index].toLowerCase();
4318 // if("insideoutsidegreaterthanlessthan".indexOf(lowerCase)) {
4319 // property = signal;
4321 // condition = lowerCase;
4323 // value = arguments[index];
4325 // if( condition === "inside" || condition === "outside" ) {
4326 // assert( value.length === 2, "Inside/Outside condition must specify min,max");
4327 // assert(typeof value[0] === "number" && typeof value[1] === "number", "Conditions must be numbers");
4329 // if(condition === "lessthan" || condition === "greaterthan") {
4330 // assert(value.length === 1, "LessThan/GreaterThan condition must specify one value");
4331 // assert(typeof value === "number", "Conditions must be numbers");
4336 // // The reset are objects created by the set or call function
4337 // var templates = _buildDescription.templates;
4339 // for( var actorName in actors ) {
4340 // // the other args come from functions that generate json
4341 // for(var i = index; i < arguments.length; i++) {
4342 // var d = arguments[i];
4343 // for(var j = 0; j < d.length; j++) {
4344 // if(signal) { // then its signal actions
4346 // templates[actorName].signals.push(d[j]);
4347 // } else { // its property notifications
4348 // d.condition = condition;
4349 // d.property = property;
4350 // templates[actorName].notifications.push(d[j]);
4359 // function animation() {
4362 // var name = arguments[0];
4364 // for(var i = 1; i < arguments.length; i++) {
4365 // var d = arguments[i];
4367 // if(d.length === undefined) { // then array from set
4370 // extend( anim, d );
4386 // image({filename:"animage,
4388 // tag: "scrollitem",
4391 // text({text:"sometext,
4392 // tag: "scrollitem",
4398 // when("myimage", condition("touch", "inside", 0, 100),
4400 // when("myimage", "touch",
4401 // call(myfunction),
4402 // call(myfunction, arg1),
4403 // and("animation-ends"),
4404 // set("myimage", "size", to([10,10,10]),
4405 // to([10,10,10], 0,3, "ease_in")),
4406 // path(0,3, "ease_in", "path0")),
4407 // between([0,0,0], [10,10,10], 0,3, "ease_in")),
4408 // to([0,0,0], 0, 3)
4409 // set(tagged("scrollitem), path(0,3, "ease_in", "path0")),
4410 // set(excludeFrom(tagged("scrollitem"), "myimage"), path(0,3, "ease_in", "path0")),
4411 // then("myimage", "hide"),
4413 // then("play", "myanim"),
4414 // thenOnChild("myimage", "child", "hide"),
4419 // on("myimage", "position", between(0, 100),
4423 //------------------------------------------------------------------------------
4424 // test helper functions
4425 //------------------------------------------------------------------------------
4428 var root = dali.stage.rootRotationActor;
4429 var children = root.getChildren();
4431 for (var i = 0, len = children.length; i < len; i++) {
4432 root.remove(children[i]);
4433 children[i].delete(); // delete the wrapper
4435 // root.delete(); // wrapper
4438 function square(color, size) {
4439 var a = dali.createSolidColorActor(color, 0, [0, 0, 0, 1], 0);
4444 function threeSquares() {
4445 var root = dali.stage.rootRotationActor;
4447 var a = square([1, 0, 0, 1], [200, 200, 0]);
4449 a.position = [-100, 0, -20];
4453 a = square([0, 1, 0, 1], [200, 200, 0]);
4455 a.position = [0, -100, -10];
4459 a = square([0, 0, 1, 1], [200, 200, 0]);
4461 a.position = [0, -100, 0];
4468 function threeSquares2() {
4469 var root = dali.stage.rootRotationActor;
4471 var red = square([1, 0, 0, 1], [200, 200, 0]);
4473 red.position = [-100, 0, 20];
4474 red.size = [10, 10, 0];
4477 var green = square([0, 1, 0, 1], [200, 200, 0]);
4478 green.name = "green";
4479 green.position = [0, -100, 0];
4480 green.orientation = [0, 0, 20];
4481 green.size = [200, 200, 0];
4483 var blue = square([0, 0, 1, 1], [200, 200, 0]);
4485 blue.position = [0, 0, 10];
4486 blue.parentOrigin = [0, 0, 0];
4487 blue.size = [100, 100, 0];
4491 red.delete(); // wrapper
4492 green.delete(); // wrapper
4493 blue.delete(); // wrapper
4498 function collectByName(collection) {
4499 var root = dali.stage.rootRotationActor;
4500 if (collection === undefined) {
4503 var op = function(actor) {
4505 collection[actor.name] = actor;
4510 dali.debug.depthVisit(root, op, true);
4517 return dali.stage.getRenderTaskList().getTask(0);
4521 return dali.stage.getRenderTaskList().getTask(1);
4525 return dali.stage.getRenderTaskList().getTask(2);
4528 function firstCamera() {
4529 return dali.stage.getRenderTaskList().getTask(0).getCameraActor();
4532 function secondCamera() {
4533 return dali.stage.getRenderTaskList().getTask(1).getCameraActor();
4536 function thirdCamera() {
4537 return dali.stage.getRenderTaskList().getTask(2).getCameraActor();
4540 function resize(w, h) {
4541 dali.setCanvasSize(w, h);
4544 function compareProperties(a1, a2) {
4545 var props1 = a1.getProperties();
4546 var props2 = a2.getProperties();
4547 var props = new Set();
4548 for (var i = 0, len = props1.size(); i < len; i++) {
4549 props.add(props1.get(i));
4552 for (i = 0, len = props2.size(); i < len; i++) {
4553 var n = props2.get(i);
4554 if (!props.has(n)) {
4555 console.log("A1 missing :" + n);
4559 var doit = function(item) {
4560 var v1 = a1[item]; // a1.getProperty(item);
4561 var v2 = a2[item]; // a2.getProperty(item);
4565 if (Array.isArray(v1)) {
4566 isSame = (v1.length === v2.length) && v1.every(function(element, index) {
4567 return element === v2[index];
4574 console.log(item + ": A1= " + v1 + " A2= " + v2);
4578 props.forEach(doit);
4581 var EPSILON = 0.005;
4583 function compareArrays(a, b) {
4585 if (Array.isArray(a) && Array.isArray(b)) {
4586 if (a.length === b.length) {
4587 for (var i = 0, len = a.length; i < len; i++) {
4588 if (Array.isArray(a[i])) {
4589 if (Array.isArray(b[i])) {
4590 if (!compareArrays(a[i], b[i])) {
4597 if (typeof (a[i]) === "number") {
4598 if (typeof (b[i]) !== "number") {
4601 if (Math.abs(a[i]) > Math.abs(b[i]) + EPSILON ||
4602 Math.abs(a[i]) < Math.abs(b[i]) - EPSILON) {
4607 if (a[i] !== b[i]) {
4619 function countAllProperties() {
4621 var tr = new dali.TypeRegistry();
4622 var names = tr.getTypeNames();
4623 for (var i = 0, len = names.size(); i < len; i++) {
4624 var ti = tr.getTypeInfo(names.get(i));
4625 var props = ti.getProperties();
4626 count += props.size();
4631 function native2ascii(str) {
4633 // really this function allows only GLSL permittable chars
4635 for (var i = 0; i < str.length; i++) {
4636 if ( 0x20 <= str.charCodeAt(i) && str.charCodeAt(i) <= 0x7E) {
4637 // normal characters
4638 out += str.charAt(i);
4639 } else if( 0x9 <= str.charCodeAt(i) && str.charCodeAt(i) <= 0xD) {
4640 // new lines and tabs
4641 out += str.charAt(i);
4648 var getGL = function() {
4649 return canvas.getContext("webgl");
4652 var getAnimation = function() {
4654 return animationList[animationSelectionIndex].animation;
4657 var getActor = function() {
4659 return eventHandler.touchedActor;
4663 //------------------------------------------------------------------------------
4665 //------------------------------------------------------------------------------
4670 Test.prototype.hierarchy = function() {
4672 console.log("test_hierarchy...");
4674 // function onTouched(actor) {
4675 // // console.log("touched " + actor.$$.ptr + " " + actor.position);
4676 // eventHandler.onTouched(actor);
4679 var actor = new dali.Actor();
4680 actor.parentOrigin = [0.5, 0.5, 0.5];
4681 actor.anchorPoint = [0.5, 0.5, 0.5];
4682 actor.text = "actor";
4683 actor.name = actor.text;
4684 actor.size = [100, 100, 1];
4685 actor.position = [0, 0, 10];
4686 dali.stage.add(actor);
4688 var hello = new dali.Actor();
4689 // hello.connect("touch", onTouched);
4690 hello.text = "hello";
4691 hello.name = hello.text;
4694 var hellochild = new dali.Actor();
4695 // hellochild.connect("touch", onTouched);
4696 hellochild.text = "hello-child";
4697 hellochild.name = hellochild.text;
4698 hello.add(hellochild);
4700 var hellochild2 = new dali.Actor();
4701 // hellochild2.connect("touch", onTouched);
4702 hellochild2.text = "hello-child2";
4703 hellochild2.name = hellochild2.text;
4704 hello.add(hellochild2);
4706 var hellochildchild = new dali.Actor();
4707 // hellochildchild.connect("touch", onTouched);
4708 hellochildchild.text = "hello-child-child1";
4709 hellochildchild.name = "hello-child-child1";
4710 hellochildchild.name = hellochildchild.text;
4711 hellochild.add(hellochildchild);
4714 var depthfirst = actor.findAllChildren();
4716 assert(actor.getChildCount() === 1);
4717 // assert(actor.getChildAt(0).text === "hello");
4718 // assert(actor.findChildByName("hello-child-child1").text = "hello-child-child1");
4719 // assert(hello.getParent().text === "actor");
4720 // assert(depthfirst[depthfirst.length - 1].text === "hello-child2");
4722 var directChildren = actor.directChildren();
4724 assert(directChildren.length === 1);
4725 assert(directChildren[0].getId() === hello.getId());
4727 actor.position = [100, 100, 0];
4729 var root = dali.stage.rootRotationActor;
4731 actor.remove(hello);
4732 assert(actor.getChildCount() === 0);
4735 assert(actor.getChildCount() === 1);
4737 var rootLayerCount = root.getChildCount();
4738 dali.stage.remove(actor); // check these don't assert
4739 assert(root.getChildCount() === rootLayerCount - 1);
4741 dali.stage.add(actor);
4742 assert(root.getChildCount() === rootLayerCount);
4744 assert(root.findChildByName("none") === null);
4746 // actor.connect("touch", onTouched);
4748 // var inserted = new dali.TextActor(); // TextActor no more RIP
4749 // inserted.parentOrigin = [0.5, 0.5, 0.5];
4750 // inserted.anchorPoint = [0.5, 0.5, 0.5];
4751 // inserted.text = "inserted";
4752 // inserted.name = inserted.text;
4753 // inserted.size = [100, 100, 1];
4754 // inserted.position = [0, 0, 50];
4755 // actor.insert(1, inserted);
4756 // assert(actor.getChildAt(1).text === "inserted");
4759 console.log(" -> ok test_hierarchy");
4762 Test.prototype.registerProperty = function() {
4764 console.log("test_registerPropery...");
4766 var root = s.rootRotationActor;
4768 var another = new dali.Actor();
4769 another.parentOrigin = [0.5, 0.5, 0.5];
4770 another.anchorPoint = [0.5, 0.5, 0.5];
4771 another.text = "peppa";
4772 another.name = another.text;
4773 another.size = [100, 100, 1];
4774 another.position = [-50, 100, 0];
4777 var c = root.getChildAt(root.getChildCount() - 1);
4778 //var n = c.getChildCount();
4779 var p = c.getParent();
4780 assert(p.getId() == root.getId());
4782 var matrix = c.worldMatrix;
4784 assert(matrix.length === 16);
4786 // todo - no longer supported (?)
4787 // another.registerProperty("data_output", true);
4788 // assert(another.getPropertyTypeFromName("data_output") === "BOOLEAN");
4789 // assert(another.data_output === true);
4790 // another.data_output = false;
4791 // assert(another.data_output === false);
4792 // dali.__updateOnce();
4793 // another.data_output = 2.5;
4794 // assert(another.data_output === 2.5);
4795 // assert(another.getPropertyTypeFromName("data_output") === "FLOAT");
4798 console.log(" -> ok test_registerPropery");
4801 Test.prototype.js_math = function() {
4802 console.log("test_js_math...");
4803 assert(dali.vectorLength([1, 2, 3, 4]) === Math.sqrt(1 * 1 + 2 * 2 + 3 * 3));
4804 assert(dali.vectorLengthSquared(dali.normalize([0, 0, 0, 1])) === 0);
4806 // for(var f=0; f < 6; f+=1)
4809 assert(1 === dali.vectorLengthSquared(dali.normalize([Math.cos(f) * 10.0,
4810 Math.cos(f + 1.0) * 10.0,
4811 Math.cos(f + 2.0) * 10.0,
4815 function assertArray(a, b, epsilon) {
4816 assert(a.length === b.length);
4817 for (var i = 0, len = a.length; i < len; ++i) {
4818 assert(a[i] > b[i] - epsilon && a[i] < b[i] + epsilon);
4822 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);
4824 assertArray(dali.quaternionToAxisAngle([1.1, 3.4, 2.7, 0.932]), [3.03, 9.38, 7.45, 0.74],
4827 assertArray(dali.vectorCross([0, 1, 0], [0, 0, 1]), [1, 0, 0], 0.001);
4829 assertArray(dali.vectorAdd([1, 2, 3], [2, 3, 4], [1, 1, 1]), [4, 6, 8], 0.001);
4831 var mq = dali.vectorAdd(dali.vectorCross([0.045, 0.443, 0.432], [0.612, 0.344, -0.144]),
4832 dali.vectorByScalar([0.612, 0.344, -0.144], 0.784),
4833 dali.vectorByScalar([0.045, 0.443, 0.432], 0.697));
4835 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])],
4839 console.log(" -> ok test_js_math");
4842 Test.prototype.getset = function() {
4844 console.log("test_getset...");
4848 var actor = col.red;
4849 var p = actor.position;
4850 actor.position = [1, 1, 1];
4851 assert(compareArrays(actor.position, [1, 1, 1]));
4852 actor.position = [3, 3, 3];
4853 assert(compareArrays(actor.position, [3, 3, 3]));
4857 console.log(" -> ok test_getset");
4860 Test.prototype.animation_spline = function() {
4862 console.log("test_animation_spline...");
4866 var actor = col.red;
4868 var a = new dali.Animation(0);
4869 var path = new dali.Path();
4874 [190.0, -150.0, 0.0]
4877 assert(compareArrays(path.points, [
4880 [190.0, -150.0, 0.0]
4883 dali.generateControlPoints(path, 0.35);
4885 assert(compareArrays(path.controlPoints, [
4887 [-66.94940948486328, 76.16658020019531, 0],
4888 [101.31224060058594, 60.66832733154297, 0],
4893 a.animatePath(actor, path, [1, 0, 0], dali.AlphaFunction.LINEAR, 0, 3);
4896 function checkPos() {
4897 assert(actor.position = path.points[2]);
4902 console.log(" -> ok test_animation_spline");
4905 window.setTimeout(checkPos, 4000);
4908 Test.prototype.animation = function() {
4910 console.log("test_animation...");
4914 var actor = col.red;
4916 var a = new dali.Animation(0);
4918 a.animateTo(actor, "position", [20, 0, 0], dali.AlphaFunction.LINEAR, 0, 3);
4921 function checkAnimateBetween() {
4922 assert(actor.position = [0, 0, -30]);
4927 console.log(" -> ok test_animation");
4930 function checkAnimateBy() {
4931 assert(actor.position = [120, 100, 0]);
4934 a.animateBetween(actor,
4935 "position", [ [ 0, [10,20,30] ],
4936 [ 1.0,[0, 0, -30] ] ],
4942 window.setTimeout(checkAnimateBetween, 4000);
4945 function checkAnimateTo() {
4946 assert(actor.position = [20, 0, 0]);
4947 actor.position = [100, 100, 0];
4949 a.clear(); // var a = new dali.Animation(0);
4951 a.animateBy(actor, "position", [20, 0, 0], dali.AlphaFunction.LINEAR, 0, 3);
4954 window.setTimeout(checkAnimateBy, 4000);
4957 window.setTimeout(checkAnimateTo, 4000);
4960 Test.prototype.onePane = function() {
4961 var w = dali.canvas.width;
4962 var h = dali.canvas.height;
4963 var col = dali.getClearColor(0);
4965 dali.setFrontView(0, 0, 0, w, h);
4966 dali.setClearColor(0, col);
4969 Test.prototype.threePane = function() {
4970 var w = dali.canvas.width;
4971 var h = dali.canvas.height;
4973 dali.setClearColor(0, [0.4, 0, 0, 1]);
4974 dali.setClearColor(1, [0, 0.4, 0, 1]);
4975 dali.setClearColor(2, [0, 0, 0.4, 1]);
4976 dali.setFrontView(0, 0, 0, w / 2 - 5, h);
4977 dali.setTopView(1, w / 2, 0, w / 2, h / 2 - 5);
4978 dali.setRightView(2, w / 2, h / 2 + 5, w / 2, h / 2 - 5);
4981 Test.prototype.twoPane = function() {
4982 var w = dali.canvas.width;
4983 var h = dali.canvas.height;
4985 dali.setFrontView(0, 0, 0, w / 2 - 10, h);
4986 dali.setTopView(1, 210, 0, w / 2 - 10, h);
4987 dali.setClearColor(0, [0.4, 0, 0, 1]);
4988 dali.setClearColor(1, [0, 0.4, 0, 1]);
4991 Test.prototype.views = function() {
4993 console.log("test_views");
4995 var w = dali.canvas.width;
4996 var h = dali.canvas.height;
4997 var col = dali.getClearColor(0);
5002 dali.setFrontView(0, 0, 0, w, h);
5003 dali.setClearColor(0, col);
5008 dali.setClearColor(0, [0.4, 0, 0, 1]);
5009 dali.setClearColor(1, [0, 0.4, 0, 1]);
5010 dali.setClearColor(2, [0, 0, 0.4, 1]);
5011 dali.setFrontView(0, 0, 0, w / 2 - 5, h);
5012 dali.setTopView(1, w / 2, 0, w / 2, h / 2 - 5);
5013 dali.setRightView(2, w / 2, h / 2 + 5, w / 2, h / 2 - 5);
5015 window.setTimeout(one, 1000);
5020 dali.setFrontView(0, 0, 0, w / 2 - 10, h);
5021 dali.setTopView(1, 210, 0, w / 2 - 10, h);
5022 dali.setClearColor(0, [0.4, 0, 0, 1]);
5023 dali.setClearColor(1, [0, 0.4, 0, 1]);
5025 window.setTimeout(three, 1000);
5030 window.setTimeout(two, 1000);
5033 Test.prototype.blinking = function() {
5035 var layer = new dali.Layer();
5036 layer.name = "frameLayer";
5037 dali.stage.add(layer);
5039 var a = dali.createSolidColorActor([0.5, 0.5, 0.5, 1],
5040 false, [0, 0, 0, 1],
5042 a.size = [100,100,1];
5046 var camera = firstCamera();
5048 camera.position = [ camera.position[0]+10, camera.position[1]+20, camera.position[2] + 10 ];
5050 layer.delete(); // wrapper
5051 a.delete(); // wrapper
5052 camera.delete(); // wrapper
5055 Test.prototype.uniformMetaData = function() {
5056 for(var i = 0; i < shaderSources.length; i++) {
5057 console.log(dali.uniformMetaData(shaderSources[i].vertex, shaderSources[i].fragment));
5061 Test.prototype.signals = function() {
5063 console.log("test_signals...");
5065 function onStage() {
5066 console.log(" -> ok test signals");
5067 //eventHandler.onTouched(actor);
5070 var actor = new dali.Actor();
5071 actor.parentOrigin = [0.5, 0.5, 0.5];
5072 actor.anchorPoint = [0.5, 0.5, 0.5];
5073 actor.text = "actor";
5074 actor.name = actor.text;
5075 actor.size = [100, 100, 1];
5076 actor.position = [0, 0, 10];
5078 actor.connect("on-stage", onStage);
5080 dali.stage.add(actor);
5083 Test.prototype.shaderInfo = function() {
5085 var info = new dali.ShaderInfo();
5091 "attribute mediump vec3 aPosition;\n" +
5092 "attribute mediump vec2 aTexCoord;\n" +
5093 "varying mediump vec2 vTexCoord;\n" +
5094 "uniform mediump vec3 uSize;\n" +
5095 "// uniform mediump vec3 unusedUniform;\n" +
5096 "uniform mediump mat4 uModelView;\n" +
5097 "uniform mediump mat4 uProjection;\n" +
5099 "void main(void)\n" +
5101 " gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\n" +
5102 " gl_Position.xyz *= uSize;\n" +
5103 " vTexCoord = aTexCoord;\n" +
5106 fragment = "precision mediump float;\n" +
5108 "uniform sampler2D sTexture;\n" +
5109 "uniform mediump vec4 uMyColor; // {min:[0,0,0,0], max:[1,1,1,1]}\n" +
5110 "uniform mediump vec4 uColor;\n" +
5111 "varying mediump vec2 vTexCoord;\n" +
5115 " gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor * uMyColor;\n" +
5118 var canvas = document.createElement("canvas");
5119 var meta = info.fromCompilation(canvas.getContext("webgl"), vertex, fragment);
5121 var uniforms = { uSize: 1,
5128 assert(meta.hasError === false);
5130 var metaUniformName;
5133 for(name in uniforms) {
5135 for(metaUniformName in meta.uniforms) {
5136 if(metaUniformName === name) {
5141 assert(found, "missing:" + name);
5144 assert(compareArrays(meta.uniformUISpec.uMyColor.min, [0, 0, 0, 0]));
5145 assert(compareArrays(meta.uniformUISpec.uMyColor.max, [1, 1, 1, 1]));
5148 meta = info.fromRegEx(vertex, fragment);
5150 assert(meta.hasError === false);
5152 for(name in uniforms) {
5154 for(metaUniformName in meta.uniforms) {
5155 if(metaUniformName === name) {
5160 assert(found, "missing:" + name);
5163 assert(compareArrays(meta.uniformUISpec.uMyColor.min, [0, 0, 0, 0]));
5164 assert(compareArrays(meta.uniformUISpec.uMyColor.max, [1, 1, 1, 1]));
5166 console.log(" -> ok test shaderInfo");
5169 //------------------------------------------------------------------------------
5171 //------------------------------------------------------------------------------
5173 Test.prototype.regression = function() {
5176 this.registerProperty();
5180 this.animation_spline();
5181 // this.shadereffect1();
5187 Test.prototype.remote_execution = function() {
5192 Test.prototype.stacking = function() {
5195 eventHandler.selectActor( dali.stage.rootRotationActor );
5197 var a = dali.createSolidColorActor([1.0, 0.0, 0.0, 1.0],
5198 false, [0, 0, 0, 1],
5202 eventHandler.selectActor( a );
5204 var b = dali.createSolidColorActor([0.0, 0.0, 1.0, 1.0],
5205 false, [0, 0, 0, 1],
5209 a.sizeWidth = a.sizeHeight = 100;
5210 b.sizeWidth = b.sizeHeight = 50;
5218 var runTest = function(functionName) {
5223 dali.stage.setBackgroundColor([0.3, 0.3, 0.3, 1]);
5225 var test = dali[functionName]();
5229 if( !test.complete() )
5232 if( !test.complete() ) {
5233 window.setTimeout(checkPos, 500);
5235 console.log("test success");
5243 //------------------------------------------------------------------------------
5245 //------------------------------------------------------------------------------
5246 function animateShaderEffect2(actor) {
5248 var shader = new dali.ShaderEffect({
5249 vertex: shaderSource2.vertex,
5250 fragment: shaderSource2.fragment
5253 actor.setShaderEffect(shader);
5255 var final = [5, 5, 5, 1];
5257 var a = new dali.Animation(0);
5260 a.animateTo(shader, "weight", final, dali.AlphaFunction.LINEAR, 0, 3);
5269 var testfile = { // output from clara.io "Threejs scene output"
5271 "version": 4.3, // This isnt as its documented on threejs website
5272 "type": "Object", // and the general format looks more like format V3.
5273 "generator": "ObjectExporter"
5276 "uuid": "2f167add-e571-47c2-9da2-6f0e45cc1119",
5287 0.5, -0.5, -0.5, -0.5,
5290 0.5, -0.5, -0.5, -0.5, -0.5, -0.5,
5464 "uuid": "14D499F1-27EF-45BF-A457-FD24DAB11205",
5465 "type": "MeshPhongMaterial",
5467 "ambient": 11579568,
5472 "transparent": false,
5476 "uuid": "BFEFB48D-0E6E-46A6-8568-5E258BA17078",
5497 "uuid": "aa901bec-9e47-4b3b-bf3c-4efb0fe5d298",
5500 "geometry": "2f167add-e571-47c2-9da2-6f0e45cc1119",
5501 "material": "14D499F1-27EF-45BF-A457-FD24DAB11205",
5503 "receiveShadow": true,
5530 // Event/widget setup
5534 //------------------------------------------------------------------------------
5538 //------------------------------------------------------------------------------
5539 function rebuildDropdown(dropdownElement, db, dbStoreName, optionalItemDataFunc) {
5541 removeAllChildren(dropdownElement);
5543 var func = optionalItemDataFunc;
5545 func = function(name) {
5546 return [null, name];
5552 var names = db.getKeys(dbStoreName);
5554 for(var i = 0; i < names.length; i++) {
5555 li = document.createElement("li");
5556 var hrefText = func(names[i]);
5558 a = document.createElement("a");
5559 a.href = hrefText[0];
5560 a.text = hrefText[1];
5562 a = document.createElement("p");
5563 a.textContent = hrefText[1];
5566 dropdownElement.appendChild(li);
5571 //------------------------------------------------------------------------------
5575 //------------------------------------------------------------------------------
5580 self.modalQuestionYesFunction = null;
5581 self.modalQuestionNoFunction = null;
5583 var _modalQuestionYes = function() {
5584 if(self.modalQuestionYesFunction) {
5585 self.modalQuestionYesFunction();
5587 self.modalQuestionYesFunction = null;
5588 self.modalQuestionNoFunction = null;
5591 var _modalQuestionNo = function() {
5592 if(self.modalQuestionNo) {
5593 self.modalQuestionNo();
5595 self.modalQuestionYesFunction = null;
5596 self.modalQuestionNoFunction = null;
5599 var _modalInputOk = function() {
5600 if(self.modalInputOkFunction) {
5601 var input = $("#modalInputText")[0];
5602 self.modalInputOkFunction(input.value);
5604 self.modalInputOkFunction = null;
5605 self.modalInputCancelFunction = null;
5608 var _modalInputCancel = function() {
5609 if(self.modalInputCancel) {
5610 self.modalInputCancel();
5612 self.modalInputOkFunction = null;
5613 self.modalInputCancelFunction = null;
5616 $("#modalQuestionYes")[0].addEventListener("click", _modalQuestionYes);
5617 $("#modalQuestionNo")[0].addEventListener("click", _modalQuestionNo);
5619 self.modalInputYesFunction = null;
5620 self.modalInputNoFunction = null;
5622 $("#modalInputOk")[0].addEventListener("click", _modalInputOk);
5623 $("#modalInputCancel")[0].addEventListener("click", _modalInputCancel);
5627 UIApp.prototype.messageBoxHTML = function(innerHtmlText) {
5629 var modalBody = $("#modalCodeInfoBody")[0];
5630 removeAllChildren(modalBody);
5631 modalBody.innerHTML = innerHtmlText;
5632 $("#modalCodeInfo").modal("show");
5635 UIApp.prototype.messageBox = function(message) {
5637 this.messageBoxHTML("<p>" + message + "</p>");
5640 UIApp.prototype.questionBox = function(message, yesFunction, noFunction) {
5642 var modalBody = $("#modalQuestionBody")[0];
5643 removeAllChildren(modalBody);
5644 modalBody.innerHTML = "<p>" + message + "</p>";
5646 this.modalQuestionYesFunction = yesFunction;
5647 this.modalQuestionNoFunction = noFunction;
5649 $("#modalQuestion").modal("show");
5652 UIApp.prototype.codeInformationBox = function(code) {
5654 var modalBody = $("#modalCodeInfoBody")[0];
5655 removeAllChildren(modalBody);
5656 modalBody.innerHTML = "<pre>" + code + "</pre>";
5657 $("#modalCodeInfo").modal("show");
5660 UIApp.prototype.inputbox = function(message, okFunction, cancelFunction) {
5662 var modalBody = $("#modalInputBody")[0];
5663 removeAllChildren(modalBody);
5664 modalBody.innerHTML = "<p>" + message + "</p>";
5666 this.modalInputOkFunction = okFunction;
5667 this.modalInputCancelFunction = cancelFunction;
5669 $("#modalInput").modal("show");
5672 UIApp.prototype.getTypedBuffer = function(file, callback) {
5677 var reader = new FileReader();
5678 reader._theFilename = file.name;
5679 reader.onload = function(// e
5681 var uint8View = new Uint8Array(reader.result); // convert ArrayBuffer into a typed array?
5682 callback(file.name, uint8View);
5685 reader.readAsArrayBuffer(file);
5689 //------------------------------------------------------------------------------
5691 // Javascript UI Tab
5693 //------------------------------------------------------------------------------
5694 function UIJavascriptTab() {
5697 self.bufferPrepend = "Buffer Name:";
5699 this.addNewBuffer = function() {
5700 var alreadyExists = function() {
5701 self.addNewBuffer();
5704 var inputOk = function(name) {
5705 var data = database.readJavascript(name);
5707 uiApp.messageBox("Name already exsists", alreadyExists);
5709 var newData = {name: name, source: ""};
5710 database.writeJavascript(newData);
5711 self.rebuildDropdown(database);
5715 uiApp.inputbox("BufferName?", inputOk);
5719 this.renameBuffer = function() {
5720 var writeOK = function() {
5721 var openRequest = database.open();
5723 openRequest.onsuccess = function(event) {
5724 var db = event.target.result;
5725 self.rebuildDropdown(database);
5730 var inputOk = function(name) {
5731 var data = uiJavascriptTab.getData();
5733 database.writeJavascript(data, writeOK);
5736 uiApp.inputbox("BufferName?", inputOk);
5740 this.loadJavascript = function(name) {
5741 var data = database.readJavascript(name);
5744 var currentData = self.getData();
5746 database.writeJavascript(currentData);
5752 ace.require("ace/ext/language_tools");
5753 var editor = ace.edit("editorJavascript");
5755 var _thisFunctions = [];
5756 for(var attr in this) {
5757 if( !(attr.startsWith("_") || attr.startsWith("dynCall") || attr.startsWith("invoke") ) ) {
5758 if( typeof this[attr] === "function") {
5759 _thisFunctions.push( attr );
5765 getCompletions: function(theEditor, session, pos, prefix, callback) {
5767 if(prefix === "dali.") {
5769 if( !(attr.startsWith("_") || attr.startsWith("dynCall") || attr.startsWith("invoke") ) ) {
5770 if( typeof dali[attr] === "function") {
5771 wordlist.push( attr );
5776 wordlist = _thisFunctions;
5778 callback(null, wordlist.map(function(word) {
5788 editor.completers = [ myCompleter ];
5791 enableBasicAutocompletion: true,
5792 enableSnippets: true,
5793 enableLiveAutocompletion: true
5796 document.getElementById("btnJavascriptSourceJson").addEventListener(
5799 self.showModalJSON();
5802 document.getElementById("btnJavascriptClearRun").addEventListener(
5805 self.clearStageAndEval();
5808 document.getElementById("btnJavascriptRun").addEventListener(
5814 document.getElementById("btnJavascriptAddBuffer").addEventListener(
5817 self.addNewBuffer();
5820 document.getElementById("btnJavascriptRenameBuffer").addEventListener(
5823 self.renameBuffer();
5826 this.currentName = undefined;
5828 var names = database.readJavascriptNames();
5830 self.loadJavascript(names[0]); // load first javascript buffer
5835 UIJavascriptTab.prototype.getData = function() {
5837 var e = ace.edit("editorJavascript");
5838 var ascii = native2ascii(e.getSession().getValue());
5840 if(this.currentName !== undefined) {
5841 return { name: this.currentName,
5848 UIJavascriptTab.prototype.setData = function(data) {
5850 this.currentName = data.name;
5852 var editor = ace.edit("editorJavascript");
5853 editor.getSession().setValue(data.source);
5855 $("#textJavascriptName").html(this.bufferPrepend + data.name);
5859 UIJavascriptTab.prototype.showModalJSON = function() {
5861 var e = ace.edit("editorJavascript");
5862 var ascii = native2ascii(e.getSession().getValue());
5864 var lines = ascii.split("\n");
5866 var data = "{source:";
5868 for(var i = 0; i < lines.length; i++) {
5869 data += "\"" + lines[i].replace(/"/g, "\\\"") + "\\n\" +\n";
5874 // data = data.replace(/<([^ ]*)/g, "< $1"); // for loops are interpreted by browser as tags and dont print?
5876 // data = data.replace(/"/g, "\\\""); // for loops are interpreted by browser as tags and dont print?
5878 // data = data.replace(/<([^ ]*)/g, "< $1"); // for loops are interpreted by browser as tags and dont print?
5880 uiApp.codeInformationBox( data );
5884 UIJavascriptTab.prototype.clearStageAndEval = function() {
5886 var e = ace.edit("editorJavascript");
5887 var ascii = native2ascii(e.getSession().getValue());
5889 // as of ecma5 an indirect call like this is in global scope
5890 var globalEval = eval;
5894 UIJavascriptTab.prototype.eval = function() {
5896 var e = ace.edit("editorJavascript");
5897 var ascii = native2ascii(e.getSession().getValue());
5898 // as of ecma5 an indirect call like this is in global scope
5899 var globalEval = eval;
5903 UIJavascriptTab.prototype.rebuildDropdown = function(db) {
5905 rebuildDropdown( document.getElementById("javascriptDropDown"),
5909 return ["javascript:uiJavascriptTab.loadJavascript(\"" + name + "\")",
5916 //------------------------------------------------------------------------------
5920 //------------------------------------------------------------------------------
5923 * Get or create a dali image from the image buffer.
5925 * Global function for use in javascript buffers or the console.
5926 * @param {string} shader buffer name
5927 * @return {Object} dali.Image
5929 function imageFromUiBuffer(name) {
5931 var img = uiImageTab.getDaliImage(name);
5932 assert(img, "Could not find image:" + name);
5938 * Manages UI image tab.
5942 function UIImageTab() {
5945 this.imagesCreated = {}; // dali shader objects
5947 /********** methods **********/
5948 this.getBufferImageRGB = function(file, callback) {
5953 var img = new HTML5Image(); // the renamed Image()
5955 var objectUrl = window.URL.createObjectURL(file);
5957 img.onload = function( //e
5959 var imageCanvas = document.createElement("canvas");
5960 imageCanvas.width = img.width; // naturalWidth;
5961 imageCanvas.height = img.height; // naturalHeight;
5962 var context = imageCanvas.getContext("2d");
5963 context.drawImage(img, 0, 0 );
5964 var imageData = context.getImageData(0, 0, img.naturalWidth, img.naturalHeight); // <-ImageData
5965 callback(file.name, imageData);
5966 window.URL.revokeObjectURL(objectUrl);
5969 img.src = objectUrl;
5975 * Add new image data
5977 * @param {object} ImageData object
5979 this.addNewBuffer = function(imageData) {
5980 var alreadyExists = function() {
5981 self.addNewBuffer(imageData);
5984 var inputOk = function(name) {
5985 var oldData = database.readImage(name);
5987 uiApp.messageBox("Name already exsists", alreadyExists);
5989 database.writeImage(name, imageData);
5990 self.rebuildDropdown(database);
5994 uiApp.inputbox("BufferName?", inputOk);
5997 this.renameBuffer = function() {
5998 var inputOk = function(name) {
5999 var data = uiJavascriptTab.getData();
6001 database.writeJavascript(data);
6002 self.rebuildDropdown(database);
6005 uiApp.inputbox("BufferName?", inputOk);
6009 * Load image into the UI Image tab. (used for dynamically generated html dropdowns)
6011 * @param {string} name of image buffer
6013 this.loadImage = function(name) {
6014 self.setData( database.readImage(name) );
6017 /********** init **********/
6019 document.getElementById("btnImageAddBuffer").addEventListener(
6022 var fileInput = document.getElementById("btnImageAddBuffer");
6023 var file = fileInput.files[0];
6024 self.getBufferImageRGB(
6026 function(name, typedBuffer) {
6027 self.addNewBuffer(typedBuffer);
6032 document.getElementById("btnImageRenameBuffer").addEventListener(
6035 self.renameBuffer();
6038 var names = database.readImageNames();
6040 // load first image buffer
6041 self.setData( database.readImage(names[0]) );
6047 * Get or create a dali image from the image buffer.
6049 * @return {Object} dali.Image
6051 UIImageTab.prototype.getDaliImage = function(name) {
6053 if(name in this.imagesCreated) {
6054 return this.imagesCreated[name];
6056 var imageData = database.readImage(name);
6057 var uint8array = new Uint8Array(imageData.data);
6058 var image = new dali.BufferImage(uint8array, imageData.width, imageData.height, dali.PixelFormat.RGBA8888);
6059 this.imagesCreated[name] = image;
6064 UIImageTab.prototype.rebuildDropdown = function(db) {
6066 rebuildDropdown( document.getElementById("imageDropDown"),
6070 return ["javascript:uiImageTab.loadImage(\"" + name + "\")",
6076 UIImageTab.prototype.setData = function(data) {
6078 var imageViewCanvas = document.getElementById("imageViewCanvas"); // createElement("canvas");
6079 imageViewCanvas.width = data.width; // naturalWidth;
6080 imageViewCanvas.height = data.height; // naturalHeight;
6081 var context = imageViewCanvas.getContext("2d");
6082 context.putImageData( data, 0, 0 );
6086 //------------------------------------------------------------------------------
6090 //------------------------------------------------------------------------------
6092 * Get or create a dali shader from the shader buffer.
6094 * Global function for use in javascript buffers or the console.
6095 * @param {string} shader buffer name
6096 * @return {Object} dali.Shader
6098 function shaderFromUiBuffer(name) {
6100 var shader = uiShaderTab.getDaliShader(name);
6101 assert(shader, "Could not find/compile shader:" + name);
6105 function shaderInfoFromUiBuffer(name) {
6107 return uiShaderTab.getShaderInfo(name);
6111 * Manage shader UI tab events.
6112 * Holds dali shader objects created from shader buffers.
6115 * @return {Object} UIShaderTab
6117 function UIShaderTab() {
6120 this.bufferPrepend = "Buffer Name:";
6121 this.inhibitCheckAndUpdateShader = false;
6123 this.shadersCreated = {}; // dali shader objects
6124 document.getElementById("btnShaderAddBuffer").addEventListener(
6127 self.addNewBuffer();
6130 document.getElementById("btnShaderRenameBuffer").addEventListener(
6133 self.renameBuffer();
6136 document.getElementById("btnShaderSourceJSON").addEventListener(
6139 self.showModalJSON();
6142 document.getElementById("btnShaderSourceC").addEventListener(
6148 document.getElementById("btnShaderSourceJS").addEventListener(
6155 this.addNewBuffer = function() {
6156 var alreadyExists = function() {
6157 self.addNewBuffer();
6160 var inputOk = function(name) {
6161 var data = database.readJavascript(name);
6163 uiApp.messageBox("Name already exsists", alreadyExists);
6165 var newData = {name: name, fragment: "", vertex: "", hints: ""};
6166 database.writeShader(newData);
6167 self.rebuildDropDown(database);
6171 uiApp.inputbox("BufferName?", inputOk);
6175 this.renameBuffer = function() {
6176 var inputOk = function(name) {
6177 var data = self.getData();
6179 database.writeShader(data);
6180 $("#textShaderName").html(self.bufferPrepend + name);
6181 self.rebuildDropdown(database);
6184 uiApp.inputbox("BufferName?", inputOk);
6187 this.loadShader = function(name) {
6189 var data = database.readShader(name);
6192 var currentData = self.getData();
6194 database.writeShader(currentData);
6197 // so that we can change vertex & fragment as an atomic operation
6198 self.inhibitCheckAndUpdateShader = true;
6200 // otherwise this will trigger a checkAndUpdateShader() after
6201 // we've only changed the vertex shader (ie with mismatching fragment shader)
6204 self.inhibitCheckAndUpdateShader = false;
6206 self.checkAndUpdateShader();
6211 * Set the UI tab data of vertex/fragment strings.
6213 * @param {Object} shader data object
6215 this.setData = function(options) {
6221 vertex = options.vertex;
6222 fragment = options.fragment;
6223 hints = options.hints;
6225 $("#requiresSelfDepthTest").prop("checked", (hints.search("requiresSelfDepthTest") >= 0));
6226 $("#outputIsTransparent").prop("checked", (hints.search("outputIsTransparent") >= 0));
6227 $("#outputIsOpaque").prop("checked", (hints.search("outputIsOpaque") >= 0));
6228 $("#modifiesGeometry").prop("checked", (hints.search("modifiesGeometry") >= 0));
6230 // do this after setting up the checkboxes as it will trigger storing the checkbox state
6231 // in the actorIdToShaderSet map
6232 e = ace.edit("editorVertex");
6233 e.getSession().setValue(vertex);
6235 e = ace.edit("editorFragment");
6236 e.getSession().setValue(fragment);
6238 $("#textShaderName").html(self.bufferPrepend + options.name);
6242 var shaderTab = $("#tab2primary")[0];
6243 var lastClassName = shaderTab.className;
6244 window.setInterval( function() {
6245 var className = shaderTab.className;
6246 if (className !== lastClassName) {
6248 // an attempt to get the editboxes to display the correct content.
6249 // when you setValue() the content and they aren't visible then
6250 // they dont update properly until you click in the box
6252 var e = ace.edit("editorVertex");
6253 e.setShowInvisibles(true);
6254 e.setShowInvisibles(false);
6256 e = ace.edit("editorFragment");
6257 e.setShowInvisibles(true);
6258 e.setShowInvisibles(false);
6259 lastClassName = className;
6263 var names = database.readShaderNames();
6265 // load first image buffer
6266 self.setData( database.readShader(names[0]) );
6269 var editor = ace.edit("editorVertex");
6270 editor.getSession().addEventListener("change", function() {
6271 self.checkAndUpdateShader();
6274 editor = ace.edit("editorFragment");
6275 editor.getSession().addEventListener("change", function() {
6276 self.checkAndUpdateShader();
6282 * Get or create a dali shader from the shader buffer.
6284 * @return {Object} dali.Shader
6286 UIShaderTab.prototype.getDaliShader = function(name) {
6288 if(name in this.shadersCreated) {
6289 return this.shadersCreated[name].daliShader;
6292 var data = database.readShader(name);
6294 if(this.isCompilable(data)) {
6295 var daliShader = new dali.Shader(data.vertex,
6297 this.getDaliShaderHints(data.hints));
6299 var shaderInfo = new dali.ShaderInfo();
6300 var info = shaderInfo.fromCompilation( canvas.getContext("webgl"),
6304 for(name in info.uniformUISpec) {
6305 var metaData = info.uniformUISpec[name];
6306 if("default" in metaData) {
6307 // could provide automatic defaults
6308 daliShader.registerAnimatedProperty(name, metaData.default);
6313 this.shadersCreated[name] = data;
6314 this.shadersCreated[name].daliShader = daliShader;
6318 console.log("Requested shader could not be compiled:" + name);
6326 * Get info for a shader. See getInfo()
6328 * @return {Object} dali.Shader
6331 UIShaderTab.prototype.getShaderInfo = function(name) {
6333 var data = database.readShader(name);
6334 return this.getInfo(data);
6338 * Rebuild UI tab drop down selection.
6340 * @param {Object} Database
6342 UIShaderTab.prototype.rebuildDropdown = function(db) {
6344 rebuildDropdown( document.getElementById("shaderDropDown"),
6348 return ["javascript:uiShaderTab.loadShader(\"" + name + "\")",
6356 * Get the UI tab data with vertex/fragment strings.
6358 * @return {Object} shader data object
6360 UIShaderTab.prototype.getData = function() {
6362 var e = ace.edit("editorVertex");
6364 ret.name = $("#textShaderName").text().substr(this.bufferPrepend.length);
6365 ret.vertex = native2ascii(e.getSession().getValue());
6366 e = ace.edit("editorFragment");
6367 ret.fragment = native2ascii(e.getSession().getValue());
6370 if( $("#requiresSelfDepthTest")[0].checked ) {
6371 ret.hints += " requiresSelfDepthTest";
6373 if( $("#outputIsTransparent")[0].checked ) {
6374 ret.hints += " outputIsTransparent";
6376 if( $("#outputIsOpaque")[0].checked ) {
6377 ret.hints += " outputIsOpaque";
6379 if( $("#modifiesGeometry")[0].checked ) {
6380 ret.hints += " modifiesGeometry";
6387 * Get dali shader hints from hints string.
6389 * @param {string} hints string (space separated)
6390 * @return {integer} or'd hints to pass to Dali
6392 UIShaderTab.prototype.getDaliShaderHints = function(hintsString) {
6396 if(hintsString.search("requiresSelfDepthTest") >= 0) {
6397 ret += dali.ShaderHints.REQUIRES_SELF_DEPTH_TEST;
6399 if(hintsString.search("outputIsTransparent") >= 0) {
6400 ret += dali.ShaderHints.OUTPUT_IS_TRANSPARENT;
6402 if(hintsString.search("outputIsOpaque") >= 0) {
6403 ret += dali.ShaderHints.OUTPUT_IS_OPAQUE;
6405 if(hintsString.search("modifiesGeometry") >= 0) {
6406 ret += dali.ShaderHints.MODIFIES_GEOMETRY;
6412 * Get information on a shader
6413 * If hasError==true then attributes etc will be empty. ie it must compile.
6415 * Compile the shader with webGL. Query webGL for meta data.
6417 * @param {object} data object. {vertex:"", fragment:""}
6418 * @return {object} info metadata object
6420 * // attributes: [],
6422 * // attributeCount: 0,
6423 * // uniformCount: 0,
6424 * // hasError: false, // compiles without error
6425 * // vertexError: "",
6426 * // fragmentError: "",
6432 // uniform vec3 uMe; // gui:number, min:0, max:1, default: 0.5
6433 // uniform vec3 uMe; // gui:slider, min:0, max:1, default: 0.5
6434 // uniform vec3 uMe; // gui:color, min:[0,0,0,0] max:[1,1,1,1], default: [0,0,0,1]
6436 UIShaderTab.prototype.getInfo = function(data) {
6439 var canvas = document.getElementById("canvas");
6441 var info = new dali.ShaderInfo();
6443 return info.fromCompilation(canvas.getContext("webgl"),
6449 * Check a shader can compile. Shader given as data object with vertex/fragment buffers.
6451 * Compile the shader with webGL as a preprocess step to giving it to Dali.
6453 * @param {string} shader buffer name
6454 * @return {Boolean} true if the shader compiles ok.
6456 UIShaderTab.prototype.isCompilable = function(data) {
6458 var info = this.getInfo(data);
6459 return !info.hasError;
6464 * Check the shader in the UI tab can compile and if so update the saved dali.Shader object.
6465 * (Does not create the dali.Shader object)
6467 * For use on an event for continuous shader checking.
6469 * @param {string} shader buffer name
6470 * @return {Object} dali.Shader
6472 UIShaderTab.prototype.checkAndUpdateShader = function() {
6474 if(this.inhibitCheckAndUpdateShader) {
6478 var options = this.getData();
6480 var info = this.getInfo(options);
6482 if(!info.hasError) {
6483 if( options.name in this.shadersCreated ) {
6484 if("daliShader" in this.shadersCreated[options.name]) {
6485 // setting shader.program= doesn't seem to recompile the shader?
6486 // this.shadersCreated[options.name].daliShader.delete(); no delete; could be held elsewhere
6487 delete this.shadersCreated[options.name];
6492 var vertexPrepend = "";
6493 var fragmentPrepend = "";
6503 var textShaderErrors = $("#textShaderErrors");
6505 textShaderErrors.value = "";
6507 editor = ace.edit("editorVertex");
6508 if (info.hasError && info.vertexError) {
6509 editor.getSession().setOption("useWorker", false);
6510 textShaderErrors.value = "VERTEX:\n" + info.vertexError;
6511 errors = info.vertexError.split("\n");
6512 count = vertexPrepend.split("\n").length;
6513 for(i = 0; i < errors.length; i++) {
6515 description = errors[i].split(":");
6516 col = Number(description[1]);
6518 line = Number(description[2]);
6522 editor.getSession().setAnnotations([{row: line - count, column: col, text: errors[i], type: "error"}]);
6526 editor.getSession().setOption("useWorker", true);
6527 editor.getSession().setAnnotations([]);
6530 editor = ace.edit("editorFragment");
6531 if (info.hasError && info.fragmentError) {
6532 editor.getSession().setOption("useWorker", false);
6533 textShaderErrors.value += "FRAGMENT:\n" + info.fragmentError;
6534 errors = info.fragmentError.split("\n");
6535 count = fragmentPrepend.split("\n").length;
6536 for(i = 0; i < errors.length; i++) {
6538 description = errors[i].split(":");
6539 col = Number(description[1]);
6541 line = Number(description[2]);
6545 editor.getSession().setAnnotations([{row: line - count, column: col, text: errors[i], type: "error"}]);
6549 editor.getSession().setOption("useWorker", true);
6550 editor.getSession().setAnnotations([]);
6553 if(!info.hasError) {
6554 database.writeShader(options);
6560 UIShaderTab.prototype.showModalC = function() {
6563 var info = this.getData();
6565 var data = "#define MAKE_STRING(A)#A\n\n" +
6566 "std::string vertexShader = MAKE_STRING(\n";
6568 var lines = info.vertex.split("\n");
6569 for(i = 0; i < lines.length; i++) {
6570 data += lines[i] + "\n";
6574 data += "std::string fragShader = MAKE_STRING(\n";
6576 lines = info.fragment.split("\n");
6577 for(i = 0; i < lines.length; i++) {
6578 data += lines[i] + "\n";
6582 data += "ShaderEffect shaderEffect;\n" +
6583 "shaderEffect = ShaderEffect::New( vertexShader, fragmentShader,\n" +
6584 " ShaderEffect::ShaderHint( " + info.hints + " ) )\n";
6586 data = data.replace(/<([^ ]*)/g, "< $1"); // for loops are interpreted by browser as tags and dont print?
6588 uiApp.codeInformationBox( data );
6590 // data = data.replace(/</g, "<");
6591 // data = data.replace(/>/g, ">");
6593 // var myWindow = window.open("data:text/html," + encodeURIComponent(data));
6594 // // "_blank"); // , "width=00,height=100");
6595 // myWindow.focus();
6599 UIShaderTab.prototype.showModalJS = function() {
6602 var info = this.getData();
6604 var data = "var shaderOptions = {vertex:\n";
6606 var lines = info.vertex.split("\n");
6607 for(i = 0; i < lines.length; i++) {
6608 data += " \"" + lines[i] + "\\n\" +\n";
6612 data += " fragment:\n";
6613 lines = info.fragment.split("\n");
6614 for(i = 0; i < lines.length; i++) {
6615 data += " \"" + lines[i] + "\\n\" +\n";
6619 data += " geometryType: \"" + info.geometryType + "\",\n";
6620 data += " geometryHints: \"" + info.geometryHints + "\"\n";
6623 data = data.replace(/<([^ ]*)/g, "< $1"); // for loops are interpreted by browser as tags and dont print?
6624 // data = data.replace(/</g, "<");
6625 // data = data.replace(/>/g, ">");
6627 // var myWindow = window.open("data:text/html," + encodeURIComponent(data));
6628 // // "_blank"); // , "width=00,height=100");
6629 // myWindow.focus();
6631 var modalBody = $("#modalCodeInfoBody")[0];
6632 removeAllChildren(modalBody);
6633 modalBody.innerHTML = "<code><pre>" + data + "</pre></code>";
6634 $("#modalCodeInfo").modal("show");
6638 UIShaderTab.prototype.showModalJSON = function() {
6640 var info = this.getData();
6642 var hints = ""; // tbd
6644 var vertex = info.vertex.replace(/\n/g, "\\n");
6645 var fragment = info.fragment.replace(/\n/g, "\\n");
6647 var data = "{\"shader-effects\": {\n" +
6648 " \"" + "effect" + "\": {\n" +
6649 " \"program\": {\n" +
6650 " \"vertexPrefix\": \"\",\n" +
6651 " \"vertex\": \"" + vertex + "\",\n" +
6652 " \"fragmentPrefix\": \"\",\n" +
6653 " \"fragment\": \"" + fragment + "\"\n" +
6655 " \"geometry-hints\": \"" + hints + "\",\n" +
6656 " \"grid-density\": \"" + "0" + "\",\n" +
6658 " \"filename\": \"\"\n" +
6664 data = data.replace(/<([^ ]*)/g, "< $1"); // for loops are interpreted by browser as tags and dont print?
6666 uiApp.codeInformationBox( data );
6670 document.getElementById("btnRewriteDatabase").addEventListener("click", function(// e
6676 consoleLogSuccess("database.delete")();
6677 window.setTimeout(function () {
6678 window.location.reload(true); // forces a reload from the server
6681 consoleLogErrorEvent, // fail
6682 consoleLogErrorEvent // blocked
6688 window.setTimeout(initDB, 1000);
6691 function updateStatistics(eventHandler){
6694 var elem = $("#statistics")[0];
6696 var actor = eventHandler.touchedActor;
6698 var usedRootLayer = false;
6701 usedRootLayer = true;
6702 actor = dali.stage.getRootLayer();
6705 var rt = dali.stage.getRenderTaskList().getTask(0);
6709 xy = dali.screenToLocal(eventHandler.mouseX, eventHandler.mouseY,
6715 var screenxy = dali.worldToScreen(actor.position, rt);
6720 name = "Root Actor";
6726 if(eventHandler.mouseDownPosition) {
6727 px = eventHandler.mouseDownPosition[0].toFixed(prec);
6728 py = eventHandler.mouseDownPosition[1].toFixed(prec);
6731 elem.innerHTML = name + " (" + actor.getId() + ") '" + actor.name + "'" + "<br>" +
6732 "Screen:" + eventHandler.mouseX.toFixed(prec) + "," + eventHandler.mouseY.toFixed(prec) + "<br>" +
6733 name + " Screen To Local:" + xy[0].toFixed(prec) + "," + xy[1].toFixed(prec) + "<br>" +
6734 name + " To Screen:" + screenxy[0].toFixed(prec) + "," + screenxy[1].toFixed(prec) + "<br>" +
6735 name + " Drag dx/dy:" + eventHandler.dragDx.toFixed(prec) + "," + eventHandler.dragDy.toFixed(prec) + "<br>" +
6736 name + " pos:" + actor.position + "<br>"+
6737 name + " pos:" + px + "," + py + "<br>";
6739 if(usedRootLayer) { // dont delete eventHandler object
6740 actor.delete(); // wrapper
6743 rt.delete(); // wrapper
6748 $(".btn-toggle").click(function() {
6750 $(this).find(".btn").toggleClass("active");
6752 if($(this).find(".btn-primary").size() > 0) {
6753 $(this).find(".btn").toggleClass("btn-primary");
6756 $(this).find(".btn").toggleClass("btn-default");
6758 if(this.id === "loop") {
6759 var looping = $(this).find("#loopOn").hasClass("active");
6760 animationList[animationSelectionIndex].looping = looping;
6761 animationList[animationSelectionIndex].dirtyData = true;
6764 if(this.id === "endAction") {
6765 var bake = $(this).find("#endBake").hasClass("active");
6767 animationList[animationSelectionIndex].endAction = "Bake";
6769 animationList[animationSelectionIndex].endAction = "Discard";
6771 animationList[animationSelectionIndex].dirtyData = true;
6776 //------------------------------------------------------------------------------
6778 // Database; access to browser indexed db
6780 //------------------------------------------------------------------------------
6781 function Database() {
6783 this.currentVersion = 1;
6784 this.name = "dalitoy";
6788 this.copyDBStore = function(db, dbStoreName, andClose) {
6789 var tr = db.transaction([dbStoreName], "readonly");
6790 var store = tr.objectStore(dbStoreName);
6791 var cursor = store.openCursor();
6792 self.data[dbStoreName] = {};
6793 cursor.onsuccess = function(e) {
6794 var res = e.target.result; // another cursor
6796 self.data[dbStoreName][res.key] = res.value;
6804 cursor.onerror = consoleLogErrorEvent;
6807 this.initializeData = function(db) {
6808 self.copyDBStore(db, "javascript");
6809 self.copyDBStore(db, "images");
6810 self.copyDBStore(db, "shaders", true); // true to close db (last copy)
6816 Database.prototype.open = function() {
6818 return window.indexedDB.open(this.name, this.currentVersion);
6821 Database.prototype.delete = function(onsuccess, onerror, onblocked) {
6823 var req = window.indexedDB.deleteDatabase(this.name);
6824 req.onsuccess = onsuccess;
6825 req.onerror = onerror;
6826 req.onblocked = onblocked;
6830 Database.prototype.upgrade = function(db, oldVersion) {
6833 if (oldVersion < 1) {
6834 // Version 1 is the first version of the database.
6835 var store = db.createObjectStore("shaders", {keyPath: "name"});
6837 for(i = 0; i < shaderSources.length; i++) {
6838 store.put( shaderSources[i] );
6841 store = db.createObjectStore("javascript", {keyPath: "name"});
6842 for(i = 0; i < javascriptSources.length; i++) {
6843 store.put( javascriptSources[i] );
6846 store = db.createObjectStore("images");
6848 // default images in html page
6849 store.put( getStockImageData(1), "girl1" );
6850 store.put( getStockImageData(2), "funnyface" );
6851 store.put( getStockImageData(3), "ducks" );
6852 store.put( getStockImageData(4), "field" );
6856 Database.prototype.init = function() {
6860 if("indexedDB" in window) {
6861 var openRequest = this.open();
6863 openRequest.onupgradeneeded = function(event) {
6864 var db = event.target.result;
6865 database.upgrade(db, event.oldVersion);
6866 //self.initializeData(db);
6869 openRequest.onsuccess = function(event) {
6870 var db = event.target.result;
6871 self.initializeData(db);
6874 openRequest.onerror = consoleLogErrorEvent;
6880 Database.prototype.initTabs = function(jstab, imagetab, shadertab) {
6882 jstab.rebuildDropdown(this);
6883 imagetab.rebuildDropdown(this);
6884 shadertab.rebuildDropdown(this);
6887 Database.prototype.writeJavascript = function(data, callback) {
6890 this.data.javascript[data.name] = data;
6892 var openRequest = this.open();
6894 openRequest.onsuccess = function(event) {
6895 var db = event.target.result;
6896 var tr = db.transaction(["javascript"], "readwrite");
6897 var store = tr.objectStore("javascript");
6899 var ob = store.put(data);
6900 self.data.javascript[data.name] = data;
6902 ob.onsuccess = callback;
6903 // ob.onerror = errorCallback;
6904 ob.onerror = consoleLogErrorEvent;
6909 openRequest.onerror = consoleLogErrorEvent;
6913 Database.prototype.readJavascript = function(name) {
6915 return this.data.javascript[name];
6918 Database.prototype.readJavascriptNames = function() {
6920 return this.getKeys("javascript");
6923 Database.prototype.readKeys = function(dbStoreName, callback) {
6926 var openRequest = database.open();
6928 openRequest.onsuccess = function(event) {
6929 var db = event.target.result;
6930 var tr = db.transaction([dbStoreName], "readonly");
6931 var store = tr.objectStore(dbStoreName);
6932 var cursor = store.openCursor();
6934 cursor.onsuccess = function(e) {
6935 var res = e.target.result; // another cursor
6943 cursor.onerror = consoleLogErrorEvent;
6949 Database.prototype.getKeys = function(dbStoreName) {
6952 var o = this.data[dbStoreName];
6953 for(var name in o) {
6959 Database.prototype.writeShader = function(data) {
6963 this.data.shaders[data.name] = data;
6965 // write the indexDB too
6966 var openRequest = this.open();
6968 openRequest.onsuccess = function(event) {
6969 var db = event.target.result;
6970 var tr = db.transaction(["shaders"], "readwrite");
6971 var store = tr.objectStore("shaders");
6973 var ob = store.put(data);
6975 //ob.onsuccess = callback;
6976 ob.onerror = consoleLogErrorEvent;
6981 openRequest.onerror = consoleLogErrorEvent;
6985 Database.prototype.readShader = function(name) {
6987 return this.data.shaders[name];
6990 Database.prototype.readShaderNames = function() {
6992 return this.getKeys("shaders");
6995 Database.prototype.readObjectStore = function(objectStoreName, recordName, callback, errorCallback) {
6997 var openRequest = window.indexedDB.open(this.name, this.currentVersion);
6999 openRequest.onsuccess = function(event) {
7000 var db = event.target.result;
7002 var transaction = db.transaction([objectStoreName], "readonly");
7003 var objectStore = transaction.objectStore(objectStoreName);
7006 var ob = objectStore.get(recordName);
7008 ob.onsuccess = function(e) {
7009 // read with undefined is still a success (should probably do this with cursor?)
7010 if(e.target.result) {
7011 callback(e.target.result);
7017 ob.onerror = errorCallback;
7022 openRequest.onerror = errorCallback;
7026 Database.prototype.writeImage = function(name, data) {
7029 this.data.images[name] = data;
7031 var openRequest = this.open();
7033 openRequest.onsuccess = function(event) {
7034 var db = event.target.result;
7035 var tr = db.transaction(["images"], "readwrite");
7036 var store = tr.objectStore("images");
7038 var ob = store.put(data, name);
7040 //ob.onsuccess = callback;
7041 ob.onerror = consoleLogErrorEvent;
7046 openRequest.onerror = consoleLogErrorEvent;
7050 Database.prototype.readImage = function(name) {
7052 return this.data.images[name];
7055 Database.prototype.readImageNames = function() {
7057 return this.getKeys("images");
7060 //------------------------------------------------------------------------------
7062 // app init functions
7064 //------------------------------------------------------------------------------
7067 database = new Database();
7068 window.setTimeout(init, 500);
7074 // var root = dali.stage.getRootLayer();
7075 // root.name = "*" + root.name; // * at start means non selectable by convention
7076 // root.delete(); // wrapper
7078 // database = new Database();
7082 uiApp = new UIApp();
7084 uiJavascriptTab = new UIJavascriptTab();
7086 uiImageTab = new UIImageTab();
7088 uiShaderTab = new UIShaderTab();
7090 database.initTabs(uiJavascriptTab, uiImageTab, uiShaderTab);
7092 $("a[rel=popover]").tooltip();
7094 Object.defineProperty(dali, "shader", {
7096 configurable: false,
7102 Object.defineProperty(dali, "actor", {
7104 configurable: false,
7110 Object.defineProperty(dali, "animation", {
7112 configurable: false,
7114 return getAnimation();
7118 eventHandler.handlersMouseMove.push(updateStatistics);
7122 ////////////////////////////////////////////////////////////////////////////////////////////////////
7124 dali.postRenderFunction = undefined;