├── 64.png
├── README.md
├── arcontroller.js
├── index.html
└── lib
├── awe-jsartoolkit-dependencies.js
├── awe-loader-min.js
├── awe-loader.js
├── awe-standard-dependencies.js
├── awe-standard-object_clicked.js
├── awe-standard-window_resized.js
├── awe-standard.js
├── awe-v8.js
├── awe.geo_ar.js
├── awe.marker_ar.js
└── underscore-min.js
/64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sitepoint-editors/ARLIFXController/7152e8e40b5a28ef4735cee0257e53a65c954b9c/64.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | AR LIFX Controller
2 | ========
3 |
4 | An augmented reality controller to control LIFX lightbulbs using awe.js, the browser and IFTTT.
5 |
6 | If you make something neat from this code, please do let me know! I'm on Twitter at @thatpatrickguy, or you can find me at http://www.patrickcatanzariti.com.
7 |
8 | PatCat
9 |
--------------------------------------------------------------------------------
/arcontroller.js:
--------------------------------------------------------------------------------
1 | window.addEventListener('load', function() {
2 | var menu_open = false;
3 |
4 | window.awe.init({
5 | device_type: awe.AUTO_DETECT_DEVICE_TYPE,
6 | settings: {
7 | container_id: 'container',
8 | fps: 30,
9 | default_camera_position: { x:0, y:0, z:0 },
10 | default_lights: [{
11 | id: 'point_light',
12 | type: 'point',
13 | color: 0xFFFFFF
14 | }]
15 | },
16 | ready: function() {
17 | awe.util.require([
18 | {
19 | capabilities: ['gum','webgl'],
20 | files: [
21 | ['lib/awe-standard-dependencies.js', 'lib/awe-standard.js'],
22 | 'lib/awe-standard-window_resized.js',
23 | 'lib/awe-standard-object_clicked.js',
24 | 'lib/awe-jsartoolkit-dependencies.js',
25 | 'lib/awe.marker_ar.js'
26 | ],
27 | success: function() {
28 | window.awe.setup_scene();
29 |
30 | // Points of Interest
31 | awe.pois.add({id: 'marker', position: {x: 0, y: 0, z: 10000}, visible: false});
32 |
33 | // Projections
34 | awe.projections.add({
35 | id: 'wormhole',
36 | geometry: {shape: 'plane', height: 400, width: 400},
37 | position: {x: 0, y: 0, z: 0},
38 | rotation: {x: 90, z: 45},
39 | material: {
40 | type: 'phong',
41 | color: 0x000000
42 | }
43 | }, {poi_id: 'marker'});
44 |
45 | awe.projections.add({
46 | id: 'ar_button_one',
47 | geometry: {shape: 'cube', x: 60, y: 30, z: 5},
48 | rotation: {y: 45},
49 | position: {x: -5, y: -31, z: -5},
50 | material: {
51 | type: 'phong',
52 | color: 0xFF0000
53 | }
54 | }, {poi_id: 'marker'});
55 |
56 | awe.projections.add({
57 | id: 'ar_button_two',
58 | geometry: {shape: 'cube', x: 60, y: 30, z: 5},
59 | rotation: {y: 45},
60 | position: {x: -5, y: -31, z: -5},
61 | material: {
62 | type: 'phong',
63 | color: 0xFF6600
64 | }
65 | }, {poi_id: 'marker'});
66 |
67 | awe.projections.add({
68 | id: 'ar_button_three',
69 | geometry: {shape: 'cube', x: 110, y: 30, z: 5},
70 | rotation: {y: 45},
71 | position: {x: -5, y: -31, z: -5},
72 | material: {
73 | type: 'phong',
74 | color: 0xFFFF00
75 | }
76 | }, {poi_id: 'marker'});
77 |
78 | awe.projections.add({
79 | id: 'ar_button_four',
80 | geometry: {shape: 'cube', x: 150, y: 30, z: 5},
81 | rotation: {y: 45},
82 | position: {x: -5, y: -31, z: -5},
83 | material: {
84 | type: 'phong',
85 | color: 0xFFFFFF
86 | }
87 | }, {poi_id: 'marker'});
88 |
89 | awe.projections.add({
90 | id: 'ar_button_five',
91 | geometry: {shape: 'cube', x: 180, y: 30, z: 5},
92 | rotation: {y: 45},
93 | position: {x: -5, y: -31, z: -5},
94 | material: {
95 | type: 'phong',
96 | color: 0x00FF00
97 | }
98 | }, {poi_id: 'marker'});
99 |
100 | awe.projections.add({
101 | id: 'ar_button_six',
102 | geometry: {shape: 'cube', x: 150, y: 30, z: 5},
103 | rotation: {y: 45},
104 | position: {x: -5, y: -31, z: -5},
105 | material: {
106 | type: 'phong',
107 | color: 0x0080FF
108 | }
109 | }, {poi_id: 'marker'});
110 |
111 | awe.projections.add({
112 | id: 'ar_button_seven',
113 | geometry: {shape: 'cube', x: 100, y: 30, z: 5},
114 | rotation: {y: 45},
115 | position: {x: -5, y: -31, z: -5},
116 | material: {
117 | type: 'phong',
118 | color: 0x8000FF
119 | }
120 | }, {poi_id: 'marker'});
121 |
122 | awe.events.add([{
123 | id: 'ar_tracking_marker',
124 | device_types: {
125 | pc: 1,
126 | android: 1
127 | },
128 | register: function(handler) {
129 | window.addEventListener('ar_tracking_marker', handler, false);
130 | },
131 | unregister: function(handler) {
132 | window.removeEventListener('ar_tracking_marker', handler, false);
133 | },
134 | handler: function(event) {
135 | if (event.detail) {
136 | if (event.detail['64']) {
137 | awe.pois.update({
138 | data: {
139 | visible: true,
140 | position: {x: 0, y: 0, z: 0},
141 | matrix: event.detail['64'].transform
142 | },
143 | where: {
144 | id: 'marker'
145 | }
146 | });
147 | awe.projections.update({
148 | data: {
149 | visible: true
150 | },
151 | where: {
152 | id: 'wormhole'
153 | }
154 | });
155 | } else if (menu_open) {
156 | awe.projections.update({
157 | data: {
158 | visible: false
159 | },
160 | where: {
161 | id: 'wormhole'
162 | }
163 | });
164 | }
165 | else {
166 | awe.pois.update({
167 | data: {
168 | visible: false
169 | },
170 | where: {
171 | id: 'marker'
172 | }
173 | });
174 | }
175 | awe.scene_needs_rendering = 1;
176 | }
177 | }
178 | }]);
179 |
180 | window.addEventListener('object_clicked', function(e) {
181 | switch (e.detail.projection_id) {
182 | case 'wormhole':
183 | if (!menu_open) {
184 | awe.projections.update({
185 | data: {
186 | animation: {
187 | duration: 1
188 | },
189 | position: {y: 35}
190 | },
191 | where: {id: 'ar_button_one'}
192 | });
193 |
194 | awe.projections.update({
195 | data: {
196 | animation: {
197 | duration: 1
198 | },
199 | position: {y: 70}
200 | },
201 | where: {id: 'ar_button_two'}
202 | });
203 |
204 | awe.projections.update({
205 | data: {
206 | animation: {
207 | duration: 1
208 | },
209 | position: {y: 105}
210 | },
211 | where: {id: 'ar_button_three'}
212 | });
213 |
214 | awe.projections.update({
215 | data: {
216 | animation: {
217 | duration: 1
218 | },
219 | position: {y: 140}
220 | },
221 | where: {id: 'ar_button_four'}
222 | });
223 |
224 | awe.projections.update({
225 | data: {
226 | animation: {
227 | duration: 1
228 | },
229 | position: {y: 175}
230 | },
231 | where: {id: 'ar_button_five'}
232 | });
233 |
234 | awe.projections.update({
235 | data: {
236 | animation: {
237 | duration: 1
238 | },
239 | position: {y: 210}
240 | },
241 | where: {id: 'ar_button_six'}
242 | });
243 |
244 | awe.projections.update({
245 | data: {
246 | animation: {
247 | duration: 1
248 | },
249 | position: {y: 245}
250 | },
251 | where: {id: 'ar_button_seven'}
252 | });
253 | } else {
254 | awe.projections.update({
255 | data: {
256 | animation: {
257 | duration: 1
258 | },
259 | position: {y: -31}
260 | },
261 | where: {id: 'ar_button_one'}
262 | });
263 |
264 | awe.projections.update({
265 | data: {
266 | animation: {
267 | duration: 1
268 | },
269 | position: {y: -31}
270 | },
271 | where: {id: 'ar_button_two'}
272 | });
273 |
274 | awe.projections.update({
275 | data: {
276 | animation: {
277 | duration: 1
278 | },
279 | position: {y: -31}
280 | },
281 | where: {id: 'ar_button_three'}
282 | });
283 |
284 | awe.projections.update({
285 | data: {
286 | animation: {
287 | duration: 1
288 | },
289 | position: {y: -31}
290 | },
291 | where: {id: 'ar_button_four'}
292 | });
293 |
294 | awe.projections.update({
295 | data: {
296 | animation: {
297 | duration: 1
298 | },
299 | position: {y: -31}
300 | },
301 | where: {id: 'ar_button_five'}
302 | });
303 |
304 | awe.projections.update({
305 | data: {
306 | animation: {
307 | duration: 1
308 | },
309 | position: {y: -31}
310 | },
311 | where: {id: 'ar_button_six'}
312 | });
313 |
314 | awe.projections.update({
315 | data: {
316 | animation: {
317 | duration: 1
318 | },
319 | position: {y: -31}
320 | },
321 | where: {id: 'ar_button_seven'}
322 | });
323 | }
324 |
325 | menu_open = !menu_open;
326 | break;
327 | case 'ar_button_one':
328 | case 'ar_button_two':
329 | case 'ar_button_three':
330 | case 'ar_button_four':
331 | case 'ar_button_five':
332 | case 'ar_button_six':
333 | case 'ar_button_seven':
334 | var request = new XMLHttpRequest();
335 | request.open('GET', 'http://maker.ifttt.com/trigger/'+e.detail.projection_id+'/with/key/yourkeyhere', true);
336 |
337 | request.onload = function() {
338 | if (request.status >= 200 && request.status < 400) {
339 | var data = JSON.parse(request.responseText);
340 | console.log(data);
341 | }
342 | };
343 |
344 | request.send();
345 | break;
346 | }
347 | }, false);
348 | } // success()
349 | },
350 | {
351 | capabilities: [],
352 | success: function() {
353 | document.body.innerHTML = '
Try this demo in the latest version of Chrome or Firefox on a PC or Android device
';
354 | }
355 | }
356 | ]); // awe.util.require()
357 | } // ready()
358 | }); // window.awe.init()
359 | }); // load
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | AR LIFX Controller
5 |
6 |
7 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/lib/awe-loader-min.js:
--------------------------------------------------------------------------------
1 | /* MIT License */var V8_CONFIG={default_id_field:"id",default_output_format:"js",debug:false,};function awe_v8(){var ID_FIELD="id";try{if(V8_CONFIG.default_id_field!==undefined){ID_FIELD=V8_CONFIG.default_id_field;}}
2 | catch(e){}
3 | var OUTPUT_FORMAT="js";try{if(V8_CONFIG.default_output_format!==undefined){OUTPUT_FORMAT=V8_CONFIG.default_output_format;}}
4 | catch(e){}
5 | var awe_v8_object=new awe_v8_template();var _return=function(return_flag,return_values,errors,output_format){if(output_format===undefined){output_format=OUTPUT_FORMAT;}
6 | if(output_format=="soapjr"){var return_object={HEAD:{},BODY:[]};if(return_flag){if(typeof(return_values)==="object"&&return_values.length!==undefined){return_object.BODY=return_values;}
7 | else{return_object.BODY=[return_values];}
8 | return_object.HEAD.result=1;return return_object;}
9 | else{return_object.HEAD.result=0;if(errors!==undefined&&Object.keys(errors).length){for(var i in errors){if(Object.keys(errors[i]).length){return_object.HEAD.errors[i]=errors[i];}}}
10 | return return_object;}}
11 | else{if(return_flag){return return_values;}
12 | else{return undefined;}}};function _add(data,io,errors){if(io==undefined){throw"io undefined";}
13 | if(data[io[ID_FIELD]]!==undefined){errors.BODY[ID_FIELD]={code:500,message:ID_FIELD+" already exists ("+io[ID_FIELD]+")",};throw ID_FIELD+" already exists ("+io[ID_FIELD]+")";}
14 | else{data[io[ID_FIELD]]=io;return io[ID_FIELD];}};function awe_v8_template(){var data={};if(V8_CONFIG.debug!==undefined){this.debug=V8_CONFIG.debug;}
15 | else{this.debug=false;}
16 | if(V8_CONFIG.debug_verbose!==undefined){this.debug_verbose=V8_CONFIG.debug;}
17 | else{this.debug_verbose=0;}
18 | this.get_data=function(){return data;}
19 | this.constructor.prototype.list=function(BODY,HEAD){if(BODY===undefined){BODY={};}
20 | if(HEAD===undefined){HEAD={};}
21 | var return_values=[];var return_flag=true;var errors={HEAD:{},BODY:{}};var output_format=undefined;if(HEAD!==undefined&&HEAD.output_format!==undefined){output_format=HEAD.output_format;}
22 | try{var page=0;var limit=undefined;var order_by=ID_FIELD;var order_type="alphabetic";var order_direction="asc";var data_array=[];for(var i in data){data_array.push(data[i]);}
23 | if(HEAD!==undefined){if(HEAD.page!==undefined&&typeof(HEAD.page)=="number"){page=HEAD.page-1;}
24 | if(HEAD.limit!==undefined&&typeof(HEAD.limit)=="number"){limit=HEAD.limit;}
25 | if(HEAD.order_by!==undefined&&typeof(HEAD.order_by)=="string"){order_by=HEAD.order_by;}
26 | if(HEAD.order_type!==undefined&&HEAD.order_type=="numeric"){order_type="numeric";}
27 | if(HEAD.order_direction!==undefined&&HEAD.order_direction=="desc"){order_direction="desc";}}
28 | var sort_function=function(A,B){var a=undefined;var b=undefined;if(order_type=="alphabetic"){if(A[order_by]!==undefined&&typeof(A[order_by])=="string"){a=A[order_by].toLowerCase();}
29 | if(B[order_by]!==undefined&&typeof(B[order_by])=="string"){b=B[order_by].toLowerCase();}
30 | if(order_direction=="asc"){if(a==undefined&&b!==undefined){return 0;}
31 | else if(a==undefined){return 1;}
32 | else if(b==undefined){return-1}
33 | else{if(ab){return 1;}
35 | else{return 0;}}}
36 | else{if(a==undefined&&b!==undefined){return 0;}
37 | else if(a==undefined){return-1;}
38 | else if(b==undefined){return 1}
39 | else{if(a>b){return-1;}
40 | else if(a0)){for(var i in BODY){var a=_add(data,BODY[i],errors);if(a){return_values.push(a);}
68 | else{throw"add failed";}}}
69 | else{var a=_add(data,BODY,errors)
70 | if(a){return_values.push(a);}
71 | else{throw"add failed";}}}
72 | catch(e){this.error_handler(e);return_flag=false;}
73 | if(return_values.length==0){return _return(return_flag,{},errors,output_format);}
74 | else if(return_values.length==1){return _return(return_flag,{id:return_values[0]},errors,output_format);}
75 | else{return _return(return_flag,{id:return_values},errors,output_format);}};this.constructor.prototype.view=function(BODY,HEAD){if(BODY==undefined){BODY={};}
76 | if(HEAD==undefined){HEAD={};}
77 | var return_value=undefined;var return_flag=true;var errors={HEAD:{},BODY:{}};var output_format=undefined;if(HEAD!==undefined&&HEAD.output_format!==undefined){output_format=HEAD.output_format;}
78 | try{if(typeof(BODY)=="string"&&data[BODY]!==undefined){return data[BODY].hasOwnProperty('value')?data[BODY].value:data[BODY];}
79 | else if(BODY!==undefined&&BODY.id!==undefined&&data[BODY.id]){return_value=data[BODY.id].hasOwnProperty('value')?data[BODY.id].value:data[BODY.id];}
80 | else{errors.BODY.id={code:500,message:BODY.id+" does not exist",};throw BODY.id+" does not exist";}}
81 | catch(e){this.error_handler(e);return_flag=false;}
82 | return _return(return_flag,return_value,errors);};this.constructor.prototype.update=function(BODY,HEAD){if(BODY==undefined){BODY={};}
83 | if(HEAD==undefined){HEAD={};}
84 | var return_values=HEAD.fields_updated||[];var return_flag=true;var errors={HEAD:{},BODY:{}};var output_format=undefined;if(HEAD!==undefined&&HEAD.output_format!==undefined){output_format=HEAD.output_format;}
85 | try{if(BODY==undefined){errors.BODY={code:500,message:"missing BODY object",};throw"missing BODY object";}
86 | if(BODY.data==undefined){errors.BODY.data={code:500,message:"missing 'data' clause in BODY object",};throw"missing 'data' clause in BODY object";}
87 | if(BODY.where==undefined){errors.BODY.where={code:500,message:"missing 'where' clause in BODY object",};throw"missing 'where' clause in BODY object";}
88 | if(BODY.where[ID_FIELD]!==undefined){if(HEAD.strict){if(data[BODY.where[ID_FIELD]]==undefined){errors.BODY[BODY.where[ID_FIELD]]={code:500,message:ID_FIELD+" doesn't exist ("+BODY.where[ID_FIELD]+")",};throw ID_FIELD+" doesn't exist ("+BODY.where[ID_FIELD]+")";}}
89 | for(var i in BODY.data){if(i!=ID_FIELD){if(!data[BODY.where[ID_FIELD]]){data[BODY.where[ID_FIELD]]={};data[BODY.where[ID_FIELD]][ID_FIELD]=BODY.where[ID_FIELD];}
90 | data[BODY.where[ID_FIELD]][i]=BODY.data[i];return_values.push(i);}}}
91 | else{errors.BODY.where={code:500,message:"where."+ID_FIELD+" required",};throw"where."+ID_FIELD+" required";}}
92 | catch(e){this.error_handler(e);return_flag=false;}
93 | return _return(return_flag,{fields_updated:return_values},errors,output_format);};this.constructor.prototype.delete=function(BODY,HEAD){if(BODY==undefined){BODY={};}
94 | if(HEAD==undefined){HEAD={};}
95 | var return_values=[];var return_flag=true;var errors={HEAD:{},BODY:{}};var output_format=undefined;if(HEAD!==undefined&&HEAD.output_format!==undefined){output_format=HEAD.output_format;}
96 | try{if(BODY!==undefined&&typeof(BODY.id)=="string"||typeof(BODY.id)=="number"){if(BODY!==undefined&&data[BODY.id]!==undefined){delete(data[BODY.id]);return_values.push(BODY.id);}
97 | else{errors.BODY.id={code:500,message:BODY.id+" does not exist",};throw BODY.id+" does not exist";}}
98 | else{for(var id in BODY.id){if(BODY.id[id]!==undefined&&data[BODY.id[id]]!==undefined){delete(data[BODY.id[id]]);return_values.push(BODY.id[id]);}
99 | else{errors.BODY[BODY.id[id]]={code:500,message:BODY.id[id]+" does not exist"};throw BODY.id[id]+" does not exist";}}}}
100 | catch(e){this.error_handler(e);return_flag=false;}
101 | if(return_values.length==0){return _return(return_flag,{},errors,output_format);}
102 | else if(return_values.length==1){return _return(return_flag,{id:return_values[0]},errors,output_format);}
103 | else{return _return(return_flag,{id:return_values},errors,output_format);}};this.constructor.prototype.report=function(BODY,HEAD){if(BODY==undefined){BODY={};}
104 | if(HEAD==undefined){HEAD={};}
105 | var return_value={count:0,fields:{},};var return_flag=true;var errors={HEAD:{},BODY:{}};var output_format=undefined;if(HEAD!==undefined&&HEAD.output_format!==undefined){output_format=HEAD.output_format;}
106 | try{if(data==undefined){errors.HEAD.data={code:500,message:"internal data invalid"};throw"internal data invalid";}
107 | for(var i in data){for(var k in data[i]){if(return_value.fields[k]==undefined){return_value.fields[k]=1;}
108 | else{return_value.fields[k]++;}}
109 | return_value.count++;}}
110 | catch(e){this.error_handler(e);return_flag=false;}
111 | return _return(return_flag,return_value,errors,output_format);};this.constructor.prototype.error_handler=function(e,debug){if(debug||this.debug){if(e.code&&e.message){console.log("ERROR: "+e.code);console.log(e.message);}
112 | else{console.log("ERROR");console.log(e);}
113 | if(this.debug_verbose>0){console.log("CALLER");console.log(arguments.callee.caller);}
114 | if(this.debug_verbose>2){console.log(arguments.callee.caller.toString());}}};this.constructor.prototype.toString=function(){return'awe_v8_object'};return this;};return awe_v8_object;}
115 | (function(window){var this_awe;var _audio_context;if(!window.awe){function awe(){var initialized=false;this.constructor.prototype.capabilities=new awe_v8();this.constructor.prototype.settings=new awe_v8();this.settings.add([{id:'debug',value:false,},{id:'geo',value:{get_location:false,}},{id:'auto_start',value:false,},{id:'renderer',value:'webgl',},{id:'start_video_stream',value:false,},{id:'fps',value:60,},{id:'default_lights',value:[{id:'spot_light',type:'spot',color:0xFFFFFF,intensity:3,distance:1000,position:{x:0,y:300,z:100},target:{x:0,y:0,z:100},cast_shadow:true,},],},]);this.constructor.prototype.events=new awe_v8();this.constructor.prototype.events.add=function(BODY,HEAD){if(!BODY){BODY={};}
116 | if(!HEAD){HEAD={};}
117 | try{var result=this.constructor.prototype.add.call(this,BODY,HEAD);if(Array.isArray(result.id)){for(var i in result.id){var event_handler=this.constructor.prototype.view.call(this,result.id[i]);if(event_handler){if(!event_handler.device_types||Object.keys(event_handler.device_types).length==0||event_handler.device_types[this_awe.device_type()]){event_handler.register(event_handler.handler);}}}}
118 | else{var event_handler=this.constructor.prototype.view.call(this,result.id);if(!event_handler.device_types||Object.keys(event_handler.device_types).length==0||event_handler.device_types[this_awe.device_type()]){event_handler.register(event_handler.handler);}}}
119 | catch(e){this.error_handler(e);}
120 | return result;}
121 | this.constructor.prototype.events.delete=function(BODY,HEAD){if(!BODY){BODY={};}
122 | if(!HEAD){HEAD={};}
123 | if(typeof BODY=='string'||typeof BODY=='number'){event_handler=this_awe.events.view(BODY);BODY={id:BODY};}
124 | else if(BODY.id){event_handler=this_awe.events.view(BODY.id);}
125 | if(event_handler){event_handler.unregister(event_handler.handler);}
126 | return this.constructor.prototype.delete.call(this,BODY,HEAD);}
127 | this.constructor.prototype.pois=new awe_v8();this.constructor.prototype.plugins=new awe_v8();this.constructor.prototype.plugins.add=function(BODY,HEAD){if(!BODY){BODY={};}
128 | if(!HEAD){HEAD={};}
129 | try{var result=this.constructor.prototype.add.call(this,BODY,HEAD);if(initialized){if(Array.isArray(result.id)){for(var i in result.id){var plugin=this.constructor.prototype.view.call(this,result.id[i]);if(plugin.auto_register===undefined||plugin.auto_register===true){plugin.register(plugin.data);}}}
130 | else{var plugin=this.constructor.prototype.view.call(this,result.id);if(plugin.auto_register===undefined||plugin.auto_register===true){plugin.register(plugin.data);}}}}
131 | catch(e){this.error_handler(e);}
132 | return result;}
133 | this.constructor.prototype.plugins.delete=function(BODY,HEAD){if(!BODY){BODY={};}
134 | if(!HEAD){HEAD={};}
135 | if(typeof BODY=='string'||typeof BODY=='number'){plugin=this_awe.plugins.view(BODY);BODY={id:BODY};}
136 | else if(BODY.id){plugin=this_awe.plugins.view(BODY.id);}
137 | if(plugin){plugin.unregister(plugin.data);}
138 | return this.constructor.prototype.delete.call(this,BODY,HEAD);}
139 | this.constructor.prototype.error_handler=function(e,debug){if(debug||this.debug){if(e.code&&e.message){console.log('ERROR: '+e.code);console.log(e.message);}
140 | else{console.log('ERROR');console.log(e);}
141 | if(this.debug_verbose>0){console.log('CALLER');console.log(arguments.callee.caller);}
142 | if(this.debug_verbose>2){console.log(arguments.callee.caller.toString());}}};this.constructor.prototype.init=function(io){if(initialized){console.log('awe was already initialized.');return;}
143 | if(!io){io={};}
144 | if(io.settings){for(var key in io.settings){try{if(this_awe.settings.view(key)!==undefined){this_awe.settings.update({data:{value:io.settings[key],},where:{id:key,}});}
145 | else{this_awe.settings.add({id:key,value:io.settings[key],});}}
146 | catch(e){}}}
147 | if(this_awe.settings.view('debug')){this.debug=this_awe.settings.view('debug');}
148 | else{this.debug=true;}
149 | if(this_awe.settings.view('debug_verbose')){this.debug_verbose=this_awe.settings.view('debug_verbose');}
150 | else{this.debug_verbose=1;}
151 | if(io.device_type!==undefined){if(io.device_type===true){var device_type='unsupported';var ua=navigator.userAgent;if(ua.match(/ipad/i)){device_type='ipad';}
152 | else if(ua.match(/iphone/i)){device_type='iphone';}
153 | else if(ua.match(/android/i)){device_type='android';}
154 | else if(ua.match(/(win|os x|linux)/i)){device_type='pc';}
155 | this_awe.settings.update({data:{value:device_type},where:{id:'device_type'}});}
156 | else{this_awe.settings.update({data:{value:io.device_type,},where:{id:'device_type',}});}}
157 | this_awe.detect_capabilities(function(){var plugins=this_awe.plugins.list();for(var i in plugins){plugins[i].register(plugins[i]);}
158 | if(io.ready){try{io.ready();}
159 | catch(e){}}
160 | var event=new CustomEvent('awe_ready');window.dispatchEvent(event);if(this_awe.settings.view('auto_start')){this_awe.setup_scene();}
161 | initialized=true;});};this.constructor.prototype.detect_capabilities=function(done){var io={},asynch_count=3,defaults={ajax:false,geo:false,lat:undefined,lon:undefined,gyro:false,motion:false,audio:false,gum:false,webgl:false,css3d:false,storage:false,sockets:false};var finished=function(){asynch_count--;if(asynch_count===0){var io_array=[];for(prop in io){io_array.push({id:prop,value:io[prop]});}
162 | this_awe.capabilities.add(io_array);if(done&&typeof(done)=='function'){done();}}};for(prop in defaults){if(!io[prop]){io[prop]=defaults[prop];}}
163 | if(!!window.XMLHttpRequest||!!window.XMLHttpRequest2){io.ajax=true;}
164 | if(!!navigator.geolocation){io.geo=true;if(this_awe.settings.view('geo')){if(this_awe.settings.view('geo.get_location')){navigator.geolocation.getCurrentPosition(function(position){this_awe.capabilities.update({data:{value:position.coords.latitude},where:{id:'lat'}});this_awe.capabilities.update({data:{value:position.coords.longitude},where:{id:'lon'}});});}}}
165 | if(!!window.DeviceOrientationEvent){var s1=function(e){if(e.alpha!==null){io.gyro=true;}
166 | window.removeEventListener('deviceorientation',s1,true);finished();}
167 | window.addEventListener('deviceorientation',s1,true);if(this_awe.device_type()=='pc'){setTimeout(function(){if(!io.gyro){finished();}},5000);}}
168 | else{finished();}
169 | if(!!window.DeviceMotionEvent){var s2=function(e){if(e.acceleration!==null){io.motion=true;}
170 | window.removeEventListener('devicemotion',s2,true);finished();}
171 | window.addEventListener('devicemotion',s2,true);if(this_awe.device_type()=='pc'){setTimeout(function(){if(!io.motion){finished();}},5000);}}
172 | else{finished();}
173 | if(this_awe.util.get_user_media){io.gum=true;}
174 | if(!!window.AudioContext){_audio_context=new AudioContext();}
175 | else if(!!window.webkitAudioContext){_audio_context=new webkitAudioContext();}
176 | if(_audio_context){io.audio=true;this_awe.util.audio_context=_audio_context;}
177 | if(!!document.createElement('canvas').getContext('experimental-webgl')||!!document.createElement('canvas').getContext('webgl')){io.webgl=true;}
178 | var tmp_div=document.createElement('div');if(tmp_div.style.WebkitTransformStyle){tmp_div.style.WebkitTransformStyle='preserve-3d';if(tmp_div.style.WebkitTransformStyle=='preserve-3d'){io.css3d=true;}}
179 | else if(tmp_div.style.transformStyle){tmp_div.style.transformStyle='preserve-3d';if(tmp_div.style.transformStyle=='preserve-3d'){io.css3d=true;}}
180 | if(!!window.localStorage){io.storage=true;}
181 | if(!!window.WebSocket||!!window.MozWebSocket||!!window.WebkitWebSocket||!!window.OWebSocket||!!window.msWebSocket||!!window.KhtmlWebSocket){io.sockets=true;}
182 | finished();};this.constructor.prototype.device_type=function(){var device_type;try{device_type=this.settings.view('device_type');}
183 | catch(e){};return device_type;};this.constructor.prototype.ready=function(){return initialized;}
184 | return this;};function _reset_load_file_queue(){return{error_called:false,success_called:false,queue:[],status:{},};}
185 | var _load_file_queue=_reset_load_file_queue();function _require(io){_load_file_queue=_reset_load_file_queue();if(Array.isArray(io)){for(var obj in io){if(io[obj].capabilities&&io[obj].files){if(!io[obj].success||typeof io[obj].success!=='function'){io[obj].success=function(){}}
186 | if(!io[obj].error||typeof io[obj].error!=='function'){io[obj].error=function(){console.log('required scripts load failed');}}
187 | if(Array.isArray(io[obj].capabilities)){var requirements_valid=true;for(var test in io[obj].capabilities){if(!this_awe.capabilities.view(io[obj].capabilities[test])){requirements_valid=false;}}
188 | if(requirements_valid){if(Array.isArray(io[obj].files)){_load_file_queue.queue=io[obj].files;_load_file_queue.success=io[obj].success;_load_file_queue.error=io[obj].error;_process_load_file_queue();}
189 | else{_load_file('script',{src:io[obj].files},io[obj].success,io[obj].error);}
190 | break;}}
191 | else{throw'require is not an array';}}}}}
192 | function _process_load_file_queue(){var is_loading=_is_loading();if(is_loading.failed){if(!_load_file_queue.error_called){_load_file_queue.error_called=true;try{_load_file_queue.error();}
193 | catch(e){}
194 | _load_file_queue=_reset_load_file_queue();}
195 | return;}
196 | else if(!is_loading.loading){if(Array.isArray(_load_file_queue.queue)&&_load_file_queue.queue.length>0){if(Array.isArray(_load_file_queue.queue[0])){for(var f in _load_file_queue.queue[0]){var file=_load_file_queue.queue[0][f];_load_file_queue.status[file]=0
197 | _load_file('script',{src:file},function(e){var file=this.getAttribute("src");_load_file_queue.status[file]=1;_process_load_file_queue();},function(e){var file=this.getAttribute("src");_load_file_queue.status[file]=-1;_process_load_file_queue();});}
198 | _load_file_queue.queue.splice(0,1);}
199 | else{var file=_load_file_queue.queue[0];_load_file_queue.queue.splice(0,1);_load_file_queue.status[file]=0;_load_file('script',{src:file},function(e){var file=this.getAttribute("src");_load_file_queue.status[file]=1;_process_load_file_queue();},function(e){var file=this.getAttribute("src");_load_file_queue.status[file]=-1;_process_load_file_queue();});}
200 | var is_loading=_is_loading();if(is_loading.failed){if(!_load_file_queue.error_called){_load_file_queue.error_called=true;try{_load_file_queue.error();}
201 | catch(e){}
202 | _load_file_queue=_reset_load_file_queue();}}}
203 | else{if(!_load_file_queue.success_called){_load_file_queue.success_called=true;try{_load_file_queue.success();}
204 | catch(e){}
205 | _load_file_queue=_reset_load_file_queue();}}}}
206 | function _is_loading(){var loading=false;var failed=false;for(var f in _load_file_queue.status){if(_load_file_queue.status[f]==-1){failed=true;}
207 | else if(_load_file_queue.status[f]==0){loading=true;;}}
208 | return{loading:loading,failed:failed};}
209 | function _load_file(type,attributes,success,error){try{var file=document.createElement(type);for(var i in attributes){file.setAttribute(i,attributes[i]);}
210 | if(success&&typeof(success)=='function'){file.onload=success;}
211 | if(error&&typeof(error)=='function'){file.onerror=error;}
212 | document.querySelector('head').appendChild(file);}
213 | catch(e){};}
214 | var _get_user_media=undefined,_connect_stream_to_src=function(){};if(navigator.getUserMedia){_get_user_media=navigator.getUserMedia.bind(navigator);_connect_stream_to_src=function(media_stream,media_element){media_element.srcObject=media_stream;media_element.play();};}
215 | else if(navigator.mozGetUserMedia){_get_user_media=navigator.mozGetUserMedia.bind(navigator);_connect_stream_to_src=function(media_stream,media_element){media_element.mozSrcObject=media_stream;media_element.play();};}
216 | else if(navigator.webkitGetUserMedia){_get_user_media=navigator.webkitGetUserMedia.bind(navigator);_connect_stream_to_src=function(media_stream,media_element){media_element.src=webkitURL.createObjectURL(media_stream);media_element.play();};}
217 | function _clean_object(object,list_of_keys){var keys={};for(var key in list_of_keys){keys[list_of_keys[key]]=1;}
218 | for(var key in object){if(!keys[key]){delete object[key];}}
219 | return object;}
220 | var util={require:_require,get_user_media:_get_user_media,connect_stream_to_src:_connect_stream_to_src,clean_object:_clean_object,};window.awe=new awe();this_awe=window.awe;this_awe.util=util;this_awe.AUTO_DETECT_DEVICE_TYPE=true;}})(window);
--------------------------------------------------------------------------------
/lib/awe-loader.js:
--------------------------------------------------------------------------------
1 | // BEGIN FILE: awe_v8.js
2 | // See: https://github.com/buildar/awe.js/blob/master/awe_v8.js
3 | /*
4 |
5 | The MIT License
6 |
7 | Copyright (c) 2013 Rob Manson, http://buildAR.com. All rights reserved.
8 |
9 | Permission is hereby granted, free of charge, to any person obtaining a copy
10 | of this software and associated documentation files (the "Software"), to deal
11 | in the Software without restriction, including without limitation the rights
12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | copies of the Software, and to permit persons to whom the Software is
14 | furnished to do so, subject to the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be included in
17 | all copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | THE SOFTWARE.
26 |
27 |
28 | What is awe_v8.js?
29 | ------------------
30 |
31 | It's a simple datastore template that makes it easy to store, manage and
32 | extend collections of javascript object in a consistent way.
33 |
34 | Trust me, it's funkier than that sounds! 8)
35 |
36 |
37 | Why is it called awe_v8?
38 | ------------------------
39 |
40 | Each datastore by default is designed to support a standard set of "8 verbs".
41 |
42 | - search
43 | - list
44 | - add
45 | - view
46 | - edit
47 | - update
48 | - delete
49 | - report
50 |
51 | Through the magical process of simplification this translates in a subset of
52 | "6 implemented methods".
53 |
54 | - list
55 | - add
56 | - view
57 | - update
58 | - delete
59 | - report
60 |
61 | search and edit are simply UIs that drive one of these 6 methods.
62 |
63 | e.g. edit -> update or search -> list
64 |
65 |
66 | How are errors handled?
67 | -----------------------
68 |
69 | In simple js mode a method call either returns undefined for an error or
70 | either an object or an array of 0 or more objects.
71 |
72 |
73 | How do you use awe_v8?
74 | ----------------------
75 |
76 | // create a awe_v8 datastore
77 | var my_datastore = new awe_v8();
78 |
79 | // add one object to your datastore
80 | console.log("add an object (return new id)");
81 | my_datastore.add({
82 | id: "test",
83 | some_data: "blah"
84 | });
85 |
86 | // add multiple objects to your datastore in one go
87 | console.log("add several objects (return new ids)");
88 | my_datastore.add([
89 | {
90 | id: "test2",
91 | some_data: "blahdeblah"
92 | },
93 | {
94 | new_param: 99,
95 | id: "test3",
96 | some_data: "hrmok"
97 | },
98 | ]);
99 |
100 | // list all objects currently in your datastore
101 | console.log("list all objects (return all objects)");
102 | my_datastore.list();
103 |
104 | // list all objects in SOAPjr format (see separate documentation for SOAPjr API)
105 | console.log("list all objects (return all objects in SOAPjr)");
106 | my_datastore.list({}, { output_format:"soapjr" });
107 |
108 | // view one object
109 | console.log("view an object (return one object)");
110 | my_datastore.view("test"); // simple
111 | my_datastore.view({ id: "test" }); // clear
112 | my_datastore.view({ id: "test" }, { output_format:"js" }); // explicit
113 |
114 | // update one object
115 | console.log("update an object (return updated fields)");
116 | my_datastore.update({
117 | data: {
118 | new_param: 34,
119 | some_data: "new_data",
120 | },
121 | where: {
122 | id: "test",
123 | }
124 | });
125 |
126 | // search for objects that fuzzy match a pattern
127 | console.log("list fuzzy matches (return roughly matching objects)");
128 | my_datastore.list({ id: "test" }, { limit: 10 });
129 |
130 | // search for objects that exactly match a pattern
131 | console.log("list exact matches (return exactly matching objects)");
132 | my_datastore.list({ exact: { id: "test2" } });
133 |
134 | // delete one object
135 | console.log("delete an object (return deleted ids)");
136 | my_datastore.delete({ id: "test2" });
137 |
138 | // report metadata about this datastore
139 | console.log("report overview info (return a summary)");
140 | my_datastore.report();
141 |
142 | */
143 |
144 | // override this to customise how you want your awe_v8 template to behave
145 | var V8_CONFIG = {
146 | default_id_field: "id",
147 | default_output_format: "js",
148 | debug: false,
149 | };
150 |
151 | // below here is the template awe_v8 object implementation
152 | function awe_v8() {
153 | var ID_FIELD = "id";
154 | try {
155 | if (V8_CONFIG.default_id_field !== undefined) {
156 | ID_FIELD = V8_CONFIG.default_id_field;
157 | }
158 | }
159 | catch(e) { /* TODO */ }
160 | var OUTPUT_FORMAT = "js";
161 | try {
162 | if (V8_CONFIG.default_output_format !== undefined) {
163 | OUTPUT_FORMAT = V8_CONFIG.default_output_format;
164 | }
165 | }
166 | catch(e) { /* TODO */ }
167 | var awe_v8_object = new awe_v8_template();
168 | var _return = function(return_flag, return_values, errors, output_format) {
169 | if (output_format === undefined) {
170 | output_format = OUTPUT_FORMAT;
171 | }
172 | if (output_format == "soapjr") {
173 | var return_object = {
174 | HEAD: {},
175 | BODY: []
176 | };
177 | if (return_flag) {
178 | if (typeof(return_values) === "object" && return_values.length !== undefined) {
179 | return_object.BODY = return_values;
180 | }
181 | else {
182 | return_object.BODY = [return_values];
183 | }
184 | return_object.HEAD.result = 1;
185 | return return_object;
186 | }
187 | else {
188 | return_object.HEAD.result = 0;
189 | if (errors !== undefined && Object.keys(errors).length) {
190 | for (var i in errors) {
191 | if (Object.keys(errors[i]).length) {
192 |
193 | return_object.HEAD.errors[i] = errors[i];
194 | }
195 | }
196 | }
197 | return return_object;
198 | }
199 | }
200 | else {
201 | if (return_flag) {
202 | return return_values;
203 | }
204 | else {
205 | return undefined;
206 | }
207 | }
208 | };
209 | function _add(data, io, errors) {
210 | if (io == undefined) {
211 | throw "io undefined";
212 | }
213 | if (data[io[ID_FIELD]] !== undefined) {
214 | errors.BODY[ID_FIELD] = {
215 | code: 500,
216 | message: ID_FIELD+" already exists ("+io[ID_FIELD]+")",
217 | };
218 | throw ID_FIELD+" already exists ("+io[ID_FIELD]+")";
219 | }
220 | else {
221 | data[io[ID_FIELD]] = io;
222 | return io[ID_FIELD];
223 | }
224 | };
225 | function awe_v8_template() {
226 | var data = {};
227 | if (V8_CONFIG.debug !== undefined) {
228 | this.debug = V8_CONFIG.debug;
229 | }
230 | else {
231 | this.debug = false;
232 | }
233 | if (V8_CONFIG.debug_verbose !== undefined) {
234 | this.debug_verbose = V8_CONFIG.debug;
235 | }
236 | else {
237 | this.debug_verbose = 0;
238 | }
239 | this.get_data = function(){
240 | return data;
241 | }
242 |
243 | this.constructor.prototype.list = function(BODY, HEAD){
244 | if (BODY === undefined) { BODY = {}; }
245 | if (HEAD === undefined) { HEAD = {}; }
246 | var return_values = [];
247 | var return_flag = true;
248 | var errors = { HEAD:{}, BODY:{} };
249 | var output_format = undefined;
250 | if (HEAD !== undefined && HEAD.output_format !== undefined) {
251 | output_format = HEAD.output_format;
252 | }
253 | try {
254 | var page = 0;
255 | var limit = undefined;
256 | var order_by = ID_FIELD;
257 | var order_type = "alphabetic";
258 | var order_direction = "asc";
259 | var data_array = [];
260 | for (var i in data) {
261 | data_array.push(data[i]);
262 | }
263 | if (HEAD !== undefined) {
264 | if (HEAD.page !== undefined && typeof(HEAD.page) == "number") {
265 | page = HEAD.page-1;
266 | }
267 | if (HEAD.limit !== undefined && typeof(HEAD.limit) == "number") {
268 | limit = HEAD.limit;
269 | }
270 | if (HEAD.order_by !== undefined && typeof(HEAD.order_by) == "string") {
271 | order_by = HEAD.order_by;
272 | }
273 | if (HEAD.order_type !== undefined && HEAD.order_type == "numeric") {
274 | order_type = "numeric";
275 | }
276 | if (HEAD.order_direction !== undefined && HEAD.order_direction == "desc") {
277 | order_direction = "desc";
278 | }
279 | }
280 | var sort_function = function(A, B) {
281 | var a = undefined;
282 | var b = undefined;
283 | if (order_type == "alphabetic") {
284 | if (A[order_by] !== undefined && typeof(A[order_by]) == "string") {
285 | a = A[order_by].toLowerCase();
286 | }
287 | if (B[order_by] !== undefined && typeof(B[order_by]) == "string") {
288 | b = B[order_by].toLowerCase();
289 | }
290 | if (order_direction == "asc") {
291 | if (a == undefined && b !== undefined) {
292 | return 0;
293 | }
294 | else if (a == undefined) {
295 | return 1;
296 | }
297 | else if (b == undefined) {
298 | return -1
299 | }
300 | else {
301 | if (a < b) {
302 | return -1;
303 | }
304 | else if (a > b) {
305 | return 1;
306 | }
307 | else {
308 | return 0;
309 | }
310 | }
311 | }
312 | else {
313 | if (a == undefined && b !== undefined) {
314 | return 0;
315 | }
316 | else if (a == undefined) {
317 | return -1;
318 | }
319 | else if (b == undefined) {
320 | return 1
321 | }
322 | else {
323 | if (a > b) {
324 | return -1;
325 | }
326 | else if (a < b) {
327 | return 1;
328 | }
329 | else {
330 | return 0;
331 | }
332 | }
333 | }
334 | }
335 | else {
336 | if (A[order_by] !== undefined && typeof(A[order_by]) == "number") {
337 | a = A[order_by];
338 | }
339 | if (B[order_by] !== undefined && typeof(B[order_by]) == "number") {
340 | b = B[order_by];
341 | }
342 | if (order_direction == "asc") {
343 | if (a == undefined && b == undefined) {
344 | return 0
345 | }
346 | else if (a == undefined) {
347 | return 1;
348 | }
349 | else if (b == undefined) {
350 | return -1;
351 | }
352 | else {
353 | return a-b;
354 | }
355 | }
356 | else {
357 | if (a == undefined && b == undefined) {
358 | return 0
359 | }
360 | else if (a == undefined) {
361 | return 1;
362 | }
363 | else if (b == undefined) {
364 | return -1;
365 | }
366 | else {
367 | return b-a;
368 | }
369 | }
370 | }
371 | };
372 | for (var i in data_array) {
373 | if (BODY == undefined || BODY.length == 0) {
374 | return_values.push(data_array[i]);
375 | }
376 | else if (BODY !== undefined && BODY.exact !== undefined) {
377 | var a = undefined;
378 | var b = undefined;
379 | var match = 0;
380 | for (var m in BODY.exact) {
381 | a = data_array[i][m];
382 | b = BODY.exact[m];
383 | if (a == b) {
384 | match = 1;
385 | }
386 | }
387 | if (match) {
388 | return_values.push(data_array[i]);
389 | }
390 | }
391 | else {
392 | var match = 1;
393 | for (var m in BODY) {
394 | if (data_array[i][m] !== undefined && typeof(data_array[i][m]) == "string") {
395 | a = data_array[i][m].toLowerCase();
396 | }
397 | if (BODY[m] !== undefined && typeof(BODY[m]) == "string") {
398 | b = BODY[m].toLowerCase();
399 | }
400 | if (a !== undefined && b !== undefined) {
401 | var r = a.match(b);
402 | if (r == undefined) {
403 | match = 0;
404 | }
405 | }
406 | else {
407 | match = 0;
408 | }
409 | }
410 | if (match) {
411 | return_values.push(data_array[i]);
412 | }
413 | }
414 | }
415 | return_values = return_values.sort(sort_function);
416 | if (limit !== undefined) {
417 | var start = limit*page;
418 | var end = limit*(page+1);
419 | return_values = return_values.slice(start,end);
420 | }
421 | }
422 | catch(e) {
423 | this.error_handler(e);
424 | return_flag = false;
425 | }
426 | /* NOTE: commented out to make it more forgiving - maybe move to config
427 | if (!(return_values.length > 0)) {
428 | return_flag = false;
429 | errors.BODY.io = {
430 | code: 500,
431 | message: "object does not exist",
432 | };
433 | }
434 | */
435 | return _return(return_flag, return_values, errors, output_format);
436 | };
437 |
438 | this.constructor.prototype.add = function(BODY, HEAD) {
439 | if (BODY == undefined) { BODY = {}; }
440 | if (HEAD == undefined) { HEAD = {}; }
441 | var return_values = [];
442 | var return_flag = true;
443 | var errors = { HEAD:{}, BODY:{} };
444 | var output_format = undefined;
445 | if (HEAD !== undefined) {
446 | if (HEAD.output_format !== undefined) {
447 | output_format = HEAD.output_format;
448 | }
449 | if (HEAD.replace_all !== undefined && HEAD.replace_all) {
450 | data = {};
451 | }
452 | }
453 | try {
454 | /* NOTE: commented out to make it more forgiving - maybe move to config
455 | if (BODY == undefined) {
456 | errors.BODY = {
457 | code: 500,
458 | message: "BODY object invalid (undefined)",
459 | };
460 | throw "BODY object invalid (undefined)";
461 | }
462 | */
463 | if (typeof(BODY) == "string") {
464 | errors.BODY = {
465 | code: 500,
466 | message: "BODY object invalid (string)",
467 | };
468 | throw "BODY object invalid (string)";
469 | }
470 | if (typeof(BODY) == "number") {
471 | errors.BODY = {
472 | code: 500,
473 | message: "BODY object invalid (number)",
474 | };
475 | throw "BODY object invalid (number)";
476 | }
477 | if ((Array.isArray && Array.isArray(BODY)) || (BODY[ID_FIELD] == undefined && BODY.length > 0)) {
478 | for (var i in BODY) {
479 | var a = _add(data, BODY[i], errors);
480 | if (a) {
481 | return_values.push(a); // if this fails will it still push something? yes, undefined
482 | }
483 | else {
484 | throw "add failed";
485 | }
486 | }
487 | }
488 | else {
489 | var a = _add(data, BODY, errors)
490 | if (a) {
491 | return_values.push(a); // if this fails will it still push something? yes, undefined
492 | }
493 | else {
494 | throw "add failed";
495 | }
496 | }
497 | }
498 | catch(e) {
499 | this.error_handler(e);
500 | return_flag = false;
501 | }
502 | if (return_values.length == 0) {
503 | return _return(return_flag, {}, errors, output_format);
504 | }
505 | else if (return_values.length == 1) {
506 | return _return(return_flag, { id: return_values[0] }, errors, output_format);
507 | }
508 | else {
509 | return _return(return_flag, { id: return_values }, errors, output_format);
510 | }
511 | };
512 |
513 | this.constructor.prototype.view = function(BODY, HEAD) {
514 | if (BODY == undefined) { BODY = {}; }
515 | if (HEAD == undefined) { HEAD = {}; }
516 | var return_value = undefined;
517 | var return_flag = true;
518 | var errors = { HEAD:{}, BODY:{} };
519 | var output_format = undefined;
520 | if (HEAD !== undefined && HEAD.output_format !== undefined) {
521 | output_format = HEAD.output_format;
522 | }
523 | try {
524 | if (typeof(BODY) == "string" && data[BODY] !== undefined) {
525 | return data[BODY].hasOwnProperty('value') ? data[BODY].value : data[BODY];
526 | }
527 | else if (BODY !== undefined && BODY.id !== undefined && data[BODY.id]) {
528 | return_value = data[BODY.id].hasOwnProperty('value') ? data[BODY.id].value : data[BODY.id];
529 | }
530 | else {
531 | errors.BODY.id = {
532 | code: 500,
533 | message: BODY.id+" does not exist",
534 | };
535 | throw BODY.id+" does not exist";
536 | }
537 | }
538 | catch(e) {
539 | this.error_handler(e);
540 | return_flag = false;
541 | }
542 | return _return(return_flag, return_value, errors);
543 | };
544 |
545 | this.constructor.prototype.update = function(BODY, HEAD) {
546 | if (BODY == undefined) { BODY = {}; }
547 | if (HEAD == undefined) { HEAD = {}; }
548 | var return_values = HEAD.fields_updated || [];
549 | var return_flag = true;
550 | var errors = { HEAD:{}, BODY:{} };
551 | var output_format = undefined;
552 | if (HEAD !== undefined && HEAD.output_format !== undefined) {
553 | output_format = HEAD.output_format;
554 | }
555 | try {
556 | if (BODY == undefined) {
557 | errors.BODY = {
558 | code: 500,
559 | message: "missing BODY object",
560 | };
561 | throw "missing BODY object";
562 | }
563 | if (BODY.data == undefined) {
564 | errors.BODY.data = {
565 | code: 500,
566 | message: "missing 'data' clause in BODY object",
567 | };
568 | throw "missing 'data' clause in BODY object";
569 | }
570 | if (BODY.where == undefined) {
571 | errors.BODY.where = {
572 | code: 500,
573 | message: "missing 'where' clause in BODY object",
574 | };
575 | throw "missing 'where' clause in BODY object";
576 | }
577 | if (BODY.where[ID_FIELD] !== undefined) {
578 | if (HEAD.strict) {
579 | if (data[BODY.where[ID_FIELD]] == undefined) {
580 | errors.BODY[BODY.where[ID_FIELD]] = {
581 | code: 500,
582 | message: ID_FIELD+" doesn't exist ("+BODY.where[ID_FIELD]+")",
583 | };
584 | throw ID_FIELD+" doesn't exist ("+BODY.where[ID_FIELD]+")";
585 | }
586 | }
587 | for (var i in BODY.data) {
588 | if (i != ID_FIELD) {
589 | if (!data[BODY.where[ID_FIELD]]) {
590 | data[BODY.where[ID_FIELD]] = {};
591 | data[BODY.where[ID_FIELD]][ID_FIELD] = BODY.where[ID_FIELD];
592 | }
593 | data[BODY.where[ID_FIELD]][i] = BODY.data[i];
594 | return_values.push(i);
595 | }
596 | }
597 | }
598 | else {
599 | errors.BODY.where = {
600 | code: 500,
601 | message: "where."+ID_FIELD+" required",
602 | };
603 | throw "where."+ID_FIELD+" required";
604 | }
605 | }
606 | catch(e) {
607 | this.error_handler(e);
608 | return_flag = false;
609 | }
610 | return _return(return_flag, { fields_updated: return_values }, errors, output_format);
611 | };
612 |
613 | this.constructor.prototype.delete = function(BODY, HEAD) {
614 | if (BODY == undefined) { BODY = {}; }
615 | if (HEAD == undefined) { HEAD = {}; }
616 | var return_values = [];
617 | var return_flag = true;
618 | var errors = { HEAD:{}, BODY:{} };
619 | var output_format = undefined;
620 | if (HEAD !== undefined && HEAD.output_format !== undefined) {
621 | output_format = HEAD.output_format;
622 | }
623 | try {
624 | if (BODY !== undefined && typeof(BODY.id) == "string" || typeof(BODY.id) == "number") {
625 | if (BODY !== undefined && data[BODY.id] !== undefined) {
626 | delete(data[BODY.id]);
627 | return_values.push(BODY.id);
628 | }
629 | else {
630 | errors.BODY.id = {
631 | code: 500,
632 | message: BODY.id+" does not exist",
633 | };
634 | throw BODY.id+" does not exist";
635 | }
636 | }
637 | else {
638 | for (var id in BODY.id) {
639 | if (BODY.id[id] !== undefined && data[BODY.id[id]] !== undefined) {
640 | delete(data[BODY.id[id]]);
641 | return_values.push(BODY.id[id]);
642 | }
643 | else {
644 | errors.BODY[BODY.id[id]] = {
645 | code: 500,
646 | message: BODY.id[id]+" does not exist"
647 | };
648 | throw BODY.id[id]+" does not exist";
649 | }
650 | }
651 | }
652 | }
653 | catch(e) {
654 | this.error_handler(e);
655 | return_flag = false;
656 | }
657 | if (return_values.length == 0) {
658 | return _return(return_flag, {}, errors, output_format);
659 | }
660 | else if (return_values.length == 1) {
661 | return _return(return_flag, { id: return_values[0] }, errors, output_format);
662 | }
663 | else {
664 | return _return(return_flag, { id: return_values }, errors, output_format);
665 | }
666 | };
667 |
668 | this.constructor.prototype.report = function(BODY, HEAD) {
669 | if (BODY == undefined) { BODY = {}; }
670 | if (HEAD == undefined) { HEAD = {}; }
671 | var return_value = {
672 | count: 0,
673 | fields: {},
674 | };
675 | var return_flag = true;
676 | var errors = { HEAD:{}, BODY:{} };
677 | var output_format = undefined;
678 | if (HEAD !== undefined && HEAD.output_format !== undefined) {
679 | output_format = HEAD.output_format;
680 | }
681 | try {
682 | if (data == undefined) {
683 | errors.HEAD.data = {
684 | code: 500,
685 | message: "internal data invalid"
686 | };
687 | throw "internal data invalid";
688 | }
689 | for (var i in data) {
690 | for (var k in data[i]) {
691 | if (return_value.fields[k] == undefined) {
692 | return_value.fields[k] = 1;
693 | }
694 | else {
695 | return_value.fields[k]++;
696 | }
697 | }
698 | return_value.count++;
699 | }
700 | }
701 | catch(e) {
702 | this.error_handler(e);
703 | return_flag = false;
704 | }
705 | return _return(return_flag, return_value, errors, output_format);
706 | };
707 |
708 |
709 | this.constructor.prototype.error_handler = function(e, debug) {
710 | if (debug || this.debug) {
711 | if (e.code && e.message) {
712 | console.log("ERROR: "+e.code);
713 | console.log(e.message);
714 | }
715 | else {
716 | console.log("ERROR");
717 | console.log(e);
718 | }
719 | if (this.debug_verbose > 0) {
720 | console.log("CALLER");
721 | console.log(arguments.callee.caller);
722 | }
723 | if (this.debug_verbose > 2) {
724 | console.log(arguments.callee.caller.toString());
725 | }
726 | }
727 | };
728 |
729 | this.constructor.prototype.toString = function() {
730 | return 'awe_v8_object'
731 | };
732 |
733 | return this;
734 | };
735 | return awe_v8_object;
736 | }
737 | // END FILE: awe_v8.js
738 |
739 | // BEGIN FILE: awe-loader.js file
740 | /*
741 |
742 | The MIT License
743 |
744 | Copyright (c) 2013 Rob Manson & Malgorzata Wierzbicka, http://buildAR.com.
745 | All rights reserved.
746 |
747 | Permission is hereby granted, free of charge, to any person obtaining a copy
748 | of this software and associated documentation files (the "Software"), to deal
749 | in the Software without restriction, including without limitation the rights
750 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
751 | copies of the Software, and to permit persons to whom the Software is
752 | furnished to do so, subject to the following conditions:
753 |
754 | The above copyright notice and this permission notice shall be included in
755 | all copies or substantial portions of the Software.
756 |
757 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
758 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
759 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
760 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
761 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
762 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
763 | THE SOFTWARE.
764 |
765 | */
766 |
767 | (function(window) {
768 | var this_awe;
769 | var _audio_context;
770 | if (!window.awe) {
771 | function awe() {
772 | var initialized = false;
773 |
774 | this.constructor.prototype.capabilities = new awe_v8();
775 |
776 | this.constructor.prototype.settings = new awe_v8();
777 | // set default settings
778 | // NOTE: override this in your code to customize how you want your awe.js app to behave
779 |
780 | this.settings.add([
781 | {
782 | id: 'debug',
783 | value: false,
784 | },
785 | {
786 | id: 'geo',
787 | value:{
788 | get_location: false,
789 | }
790 | },
791 | {
792 | id: 'auto_start',
793 | value: false,
794 | },
795 | {
796 | id: 'renderer',
797 | value: 'webgl',
798 | },
799 | {
800 | id: 'start_video_stream',
801 | value: false,
802 | },
803 | {
804 | id: 'fps',
805 | value: 60,
806 | },
807 | {
808 | id: 'default_lights',
809 | value: [
810 | {
811 | id: 'spot_light',
812 | type: 'spot',
813 | color: 0xFFFFFF,
814 | intensity: 3,
815 | distance: 1000,
816 | position: { x:0, y:300, z:100 },
817 | target: { x:0, y:0, z:100 },
818 | cast_shadow: true,
819 | },
820 | ],
821 | },
822 | ]);
823 |
824 | this.constructor.prototype.events = new awe_v8();
825 | this.constructor.prototype.events.add = function(BODY, HEAD) {
826 | if (!BODY) { BODY = {}; }
827 | if (!HEAD) { HEAD = {}; }
828 | try {
829 | var result = this.constructor.prototype.add.call(this, BODY, HEAD); // super
830 | if (Array.isArray(result.id)) {
831 | for (var i in result.id) {
832 | var event_handler = this.constructor.prototype.view.call(this, result.id[i]);
833 | if (event_handler) {
834 | if (!event_handler.device_types || Object.keys(event_handler.device_types).length == 0 || event_handler.device_types[this_awe.device_type()]) {
835 | event_handler.register(event_handler.handler);
836 | }
837 | }
838 | }
839 | }
840 | else {
841 | var event_handler = this.constructor.prototype.view.call(this, result.id);
842 | if (!event_handler.device_types || Object.keys(event_handler.device_types).length == 0 || event_handler.device_types[this_awe.device_type()]) {
843 | event_handler.register(event_handler.handler);
844 | }
845 | }
846 | }
847 | catch(e) {
848 | this.error_handler(e);
849 | }
850 | return result;
851 | }
852 | this.constructor.prototype.events.delete = function(BODY, HEAD) {
853 | if (!BODY) { BODY = {}; }
854 | if (!HEAD) { HEAD = {}; }
855 |
856 | if (typeof BODY == 'string' || typeof BODY == 'number') {
857 | event_handler = this_awe.events.view(BODY);
858 | BODY = { id: BODY };
859 | }
860 | else if (BODY.id) {
861 | event_handler = this_awe.events.view(BODY.id);
862 | }
863 | if (event_handler) {
864 | event_handler.unregister(event_handler.handler);
865 | }
866 | return this.constructor.prototype.delete.call(this, BODY, HEAD); // super
867 | }
868 |
869 | this.constructor.prototype.pois = new awe_v8();
870 |
871 | this.constructor.prototype.plugins = new awe_v8();
872 | this.constructor.prototype.plugins.add = function(BODY, HEAD) {
873 | if (!BODY) { BODY = {}; }
874 | if (!HEAD) { HEAD = {}; }
875 | try {
876 | var result = this.constructor.prototype.add.call(this, BODY, HEAD); // super
877 | if (initialized) {
878 | if (Array.isArray(result.id)) {
879 | for (var i in result.id) {
880 | var plugin = this.constructor.prototype.view.call(this, result.id[i]);
881 | if (plugin.auto_register === undefined || plugin.auto_register === true) {
882 | plugin.register(plugin.data);
883 | }
884 | }
885 | }
886 | else {
887 | var plugin = this.constructor.prototype.view.call(this, result.id);
888 | if (plugin.auto_register === undefined || plugin.auto_register === true) {
889 | plugin.register(plugin.data);
890 | }
891 | }
892 | }
893 | }
894 | catch(e) {
895 | this.error_handler(e);
896 | }
897 | return result;
898 | }
899 | this.constructor.prototype.plugins.delete = function(BODY, HEAD) {
900 | if (!BODY) { BODY = {}; }
901 | if (!HEAD) { HEAD = {}; }
902 | // tear down plugin
903 | if (typeof BODY == 'string' || typeof BODY == 'number') {
904 | plugin = this_awe.plugins.view(BODY);
905 | BODY = { id: BODY };
906 | }
907 | else if (BODY.id) {
908 | plugin = this_awe.plugins.view(BODY.id);
909 | }
910 | if (plugin) {
911 | plugin.unregister(plugin.data);
912 | }
913 | return this.constructor.prototype.delete.call(this, BODY, HEAD); // super
914 | }
915 |
916 | this.constructor.prototype.error_handler = function(e, debug) {
917 | if (debug || this.debug) {
918 | if (e.code && e.message) {
919 | console.log('ERROR: '+e.code);
920 | console.log(e.message);
921 | }
922 | else {
923 | console.log('ERROR');
924 | console.log(e);
925 | }
926 | if (this.debug_verbose > 0) {
927 | console.log('CALLER');
928 | console.log(arguments.callee.caller);
929 | }
930 | if (this.debug_verbose > 2) {
931 | console.log(arguments.callee.caller.toString());
932 | }
933 | }
934 | };
935 |
936 | this.constructor.prototype.init = function(io) {
937 | if (initialized) {
938 | console.log('awe was already initialized.');
939 | return;
940 | }
941 | if (!io) { io = {}; }
942 |
943 |
944 | if (io.settings) {
945 | for (var key in io.settings) {
946 | try {
947 | if (this_awe.settings.view(key) !== undefined) {
948 | this_awe.settings.update({
949 | data: {
950 | value: io.settings[key],
951 | },
952 | where: {
953 | id: key,
954 | }
955 | });
956 | }
957 | else {
958 | this_awe.settings.add({
959 | id: key,
960 | value: io.settings[key],
961 | });
962 | }
963 | }
964 | catch(e) { /* TODO */ }
965 | }
966 | }
967 |
968 | if (this_awe.settings.view('debug')) {
969 | this.debug = this_awe.settings.view('debug');
970 | }
971 | else {
972 | this.debug = true;
973 | }
974 | if (this_awe.settings.view('debug_verbose')) {
975 | this.debug_verbose = this_awe.settings.view('debug_verbose');
976 | }
977 | else {
978 | this.debug_verbose = 1;
979 | }
980 |
981 | if (io.device_type !== undefined) {
982 | if (io.device_type === true) {
983 | var device_type = 'unsupported';
984 | var ua = navigator.userAgent;
985 | if (ua.match(/ipad/i)) {
986 | device_type = 'ipad';
987 | }
988 | else if (ua.match(/iphone/i)) {
989 | device_type = 'iphone';
990 | }
991 | else if (ua.match(/android/i)) {
992 | device_type = 'android';
993 | // NOTE: may differentiate more here
994 | }
995 | else if (ua.match(/(win|os x|linux)/i)) {
996 | device_type = 'pc';
997 | }
998 | this_awe.settings.update({
999 | data: {
1000 | value: device_type
1001 | },
1002 | where: {
1003 | id: 'device_type'
1004 | }
1005 | });
1006 | }
1007 | else {
1008 | this_awe.settings.update({
1009 | data:{
1010 | value: io.device_type,
1011 | },
1012 | where:{
1013 | id: 'device_type',
1014 | }
1015 | });
1016 | }
1017 | }
1018 |
1019 | this_awe.detect_capabilities(function() {
1020 | var plugins = this_awe.plugins.list();
1021 | for (var i in plugins) {
1022 | plugins[i].register(plugins[i]);
1023 | }
1024 | if (io.ready) {
1025 | try {
1026 | io.ready();
1027 | }
1028 | catch(e) { /* TODO */ }
1029 | }
1030 | var event = new CustomEvent('awe_ready');
1031 | window.dispatchEvent(event);
1032 | if (this_awe.settings.view('auto_start')) {
1033 | this_awe.setup_scene();
1034 | }
1035 | initialized = true;
1036 | });
1037 | };
1038 |
1039 | this.constructor.prototype.detect_capabilities = function(done) {
1040 | var io = {},
1041 | asynch_count = 3,
1042 | defaults = {
1043 | ajax : false, // is ajax supported
1044 | geo : false, // is geo supported
1045 | lat: undefined, // only populated once location requested
1046 | lon: undefined, // only populated once location requested
1047 | gyro : false, // is orientation supported
1048 | motion : false, // is motion supported
1049 | audio : false, // is web audio supported
1050 | gum: false, // is camera/microphone access supported
1051 | webgl: false, // is webgl supported
1052 | css3d: false, // is css3d supported
1053 | storage : false, // is local storage supported
1054 | sockets : false // are web sockets supported
1055 | };
1056 |
1057 | var finished = function() {
1058 | asynch_count--;
1059 | if (asynch_count === 0) {
1060 | var io_array = [];
1061 | for (prop in io) {
1062 | io_array.push({ id:prop, value:io[prop] });
1063 | }
1064 | this_awe.capabilities.add(io_array);
1065 | if (done && typeof(done) == 'function') {
1066 | done();
1067 | }
1068 | }
1069 | };
1070 |
1071 | for (prop in defaults) {
1072 | if (!io[prop]) {
1073 | io[prop] = defaults[prop];
1074 | }
1075 | }
1076 |
1077 | // services (ajax) enabled
1078 | if (!!window.XMLHttpRequest || !!window.XMLHttpRequest2) {
1079 | io.ajax = true;
1080 | }
1081 |
1082 | // geo enabled
1083 | if (!!navigator.geolocation) {
1084 | io.geo = true;
1085 | if (this_awe.settings.view('geo')) {
1086 | if (this_awe.settings.view('geo.get_location')) {
1087 | navigator.geolocation.getCurrentPosition(function(position) {
1088 | this_awe.capabilities.update({ data: { value: position.coords.latitude }, where: { id: 'lat' } });
1089 | this_awe.capabilities.update({ data: { value: position.coords.longitude }, where: { id: 'lon' } });
1090 | });
1091 | }
1092 | }
1093 | }
1094 |
1095 | // orientation enabled
1096 | if (!!window.DeviceOrientationEvent) {
1097 | var s1 = function(e) {
1098 | if (e.alpha !== null) {
1099 | io.gyro = true;
1100 | }
1101 | window.removeEventListener('deviceorientation', s1, true);
1102 | finished();
1103 | }
1104 | window.addEventListener('deviceorientation', s1, true);
1105 | // in case event handler never returns - eg. on a pc
1106 | if (this_awe.device_type() == 'pc') {
1107 | setTimeout(function() {
1108 | if (!io.gyro) {
1109 | finished();
1110 | }
1111 | }, 5000);
1112 | }
1113 | }
1114 | else {
1115 | finished();
1116 | }
1117 |
1118 | // motion enabled
1119 | if (!!window.DeviceMotionEvent) {
1120 | var s2 = function(e) {
1121 | if (e.acceleration !== null) {
1122 | io.motion = true;
1123 | }
1124 | window.removeEventListener('devicemotion', s2, true);
1125 | finished();
1126 | }
1127 | window.addEventListener('devicemotion', s2, true);
1128 | // in case event handler never returns - eg. on a pc
1129 | if (this_awe.device_type() == 'pc') {
1130 | setTimeout(function() {
1131 | if (!io.motion) {
1132 | finished();
1133 | }
1134 | }, 5000);
1135 | }
1136 | }
1137 | else {
1138 | finished();
1139 | }
1140 |
1141 | // getUserMedia microphone & camera access enabled
1142 | if (this_awe.util.get_user_media) {
1143 | io.gum = true;
1144 | }
1145 |
1146 | // web audio enabled
1147 | if (!!window.AudioContext) {
1148 | _audio_context = new AudioContext();
1149 | }
1150 | else if (!!window.webkitAudioContext) {
1151 | _audio_context = new webkitAudioContext();
1152 | }
1153 | if (_audio_context) {
1154 | io.audio = true;
1155 | this_awe.util.audio_context = _audio_context;
1156 | }
1157 |
1158 | // webgl enabled
1159 | if (!!document.createElement('canvas').getContext('experimental-webgl') || !!document.createElement('canvas').getContext('webgl')) {
1160 | io.webgl = true;
1161 | }
1162 |
1163 | var tmp_div = document.createElement('div');
1164 | if (tmp_div.style.WebkitTransformStyle) {
1165 | tmp_div.style.WebkitTransformStyle = 'preserve-3d';
1166 | if (tmp_div.style.WebkitTransformStyle == 'preserve-3d') {
1167 | io.css3d = true;
1168 | }
1169 | }
1170 | else if (tmp_div.style.transformStyle) {
1171 | tmp_div.style.transformStyle = 'preserve-3d';
1172 | if (tmp_div.style.transformStyle == 'preserve-3d') {
1173 | io.css3d = true;
1174 | }
1175 | }
1176 |
1177 | // localstorage enabled
1178 | if (!!window.localStorage) {
1179 | io.storage = true;
1180 | }
1181 |
1182 | // websockets enabled
1183 | if (!!window.WebSocket || !!window.MozWebSocket || !!window.WebkitWebSocket || !!window.OWebSocket || !!window.msWebSocket || !!window.KhtmlWebSocket) {
1184 | io.sockets = true;
1185 | }
1186 |
1187 | finished();
1188 | };
1189 |
1190 | this.constructor.prototype.device_type = function() {
1191 | var device_type;
1192 | try {
1193 | device_type = this.settings.view('device_type');
1194 | }
1195 | catch(e) { /* TODO */ };
1196 | return device_type;
1197 | };
1198 |
1199 | this.constructor.prototype.ready = function() {
1200 | return initialized;
1201 | }
1202 |
1203 | return this;
1204 | };
1205 |
1206 | function _reset_load_file_queue() {
1207 | return {
1208 | error_called: false,
1209 | success_called: false,
1210 | queue: [],
1211 | status: {},
1212 | };
1213 | }
1214 |
1215 | var _load_file_queue = _reset_load_file_queue();
1216 | function _require(io) {
1217 | _load_file_queue = _reset_load_file_queue();
1218 | if (Array.isArray(io)) {
1219 | for (var obj in io) {
1220 | if (io[obj].capabilities && io[obj].files) {
1221 | if (!io[obj].success || typeof io[obj].success !== 'function') {
1222 | io[obj].success = function() { /* TODO */ }
1223 | }
1224 | if (!io[obj].error || typeof io[obj].error !== 'function') {
1225 | io[obj].error = function() { console.log('required scripts load failed'); }
1226 | }
1227 | if (Array.isArray(io[obj].capabilities)) {
1228 | var requirements_valid = true;
1229 | for (var test in io[obj].capabilities) {
1230 | if (!this_awe.capabilities.view(io[obj].capabilities[test])) {
1231 | requirements_valid = false;
1232 | }
1233 | }
1234 | if (requirements_valid) {
1235 | if (Array.isArray(io[obj].files)) {
1236 | _load_file_queue.queue = io[obj].files;
1237 | _load_file_queue.success = io[obj].success;
1238 | _load_file_queue.error = io[obj].error;
1239 | _process_load_file_queue();
1240 | }
1241 | else {
1242 | _load_file(
1243 | 'script',
1244 | { src: io[obj].files },
1245 | io[obj].success,
1246 | io[obj].error
1247 | );
1248 | }
1249 | break;
1250 | }
1251 | }
1252 | else {
1253 | throw 'require is not an array';
1254 | }
1255 | }
1256 | }
1257 | }
1258 | }
1259 |
1260 | function _process_load_file_queue() {
1261 | var is_loading = _is_loading();
1262 | if (is_loading.failed) {
1263 | if (!_load_file_queue.error_called) {
1264 | _load_file_queue.error_called = true;
1265 | try {
1266 | _load_file_queue.error();
1267 | }
1268 | catch(e) { /* TODO */ }
1269 | _load_file_queue = _reset_load_file_queue();
1270 | }
1271 | return;
1272 | }
1273 | else if (!is_loading.loading) {
1274 | if (Array.isArray(_load_file_queue.queue) && _load_file_queue.queue.length > 0) {
1275 | if (Array.isArray(_load_file_queue.queue[0])) {
1276 | for (var f in _load_file_queue.queue[0]) {
1277 | var file = _load_file_queue.queue[0][f];
1278 | _load_file_queue.status[file] = 0
1279 | _load_file(
1280 | 'script',
1281 | { src: file },
1282 | function(e) {
1283 | var file = this.getAttribute("src");
1284 | _load_file_queue.status[file] = 1;
1285 | _process_load_file_queue();
1286 | },
1287 | function(e) {
1288 | var file = this.getAttribute("src");
1289 | _load_file_queue.status[file] = -1;
1290 | _process_load_file_queue();
1291 | }
1292 | );
1293 | }
1294 | _load_file_queue.queue.splice(0, 1);
1295 | }
1296 | else {
1297 | var file = _load_file_queue.queue[0];
1298 | _load_file_queue.queue.splice(0, 1);
1299 | _load_file_queue.status[file] = 0;
1300 | _load_file(
1301 | 'script',
1302 | { src: file },
1303 | function(e) {
1304 | var file = this.getAttribute("src");
1305 | _load_file_queue.status[file] = 1;
1306 | _process_load_file_queue();
1307 | },
1308 | function(e) {
1309 | var file = this.getAttribute("src");
1310 | _load_file_queue.status[file] = -1;
1311 | _process_load_file_queue();
1312 | }
1313 | );
1314 | }
1315 | var is_loading = _is_loading();
1316 | if (is_loading.failed) {
1317 | if (!_load_file_queue.error_called) {
1318 | _load_file_queue.error_called = true;
1319 | try {
1320 | _load_file_queue.error();
1321 | }
1322 | catch(e) { /* TODO */ }
1323 | _load_file_queue = _reset_load_file_queue();
1324 | }
1325 | }
1326 | }
1327 | else {
1328 | if (!_load_file_queue.success_called) {
1329 | _load_file_queue.success_called = true;
1330 | try {
1331 | _load_file_queue.success();
1332 | }
1333 | catch(e) { /* TODO */ }
1334 | _load_file_queue = _reset_load_file_queue();
1335 | }
1336 | }
1337 | }
1338 | }
1339 |
1340 | function _is_loading() {
1341 | var loading = false;
1342 | var failed = false;
1343 | for (var f in _load_file_queue.status) {
1344 | if (_load_file_queue.status[f] == -1) {
1345 | failed = true;
1346 | }
1347 | else if (_load_file_queue.status[f] == 0) {
1348 | loading = true;;
1349 | }
1350 | }
1351 | return { loading: loading, failed: failed };
1352 | }
1353 |
1354 | function _load_file(type, attributes, success, error) {
1355 | try {
1356 | var file = document.createElement(type);
1357 | for (var i in attributes) {
1358 | file.setAttribute(i, attributes[i]);
1359 | }
1360 | if (success && typeof(success) == 'function') {
1361 | file.onload = success;
1362 | }
1363 | if (error && typeof(error) == 'function') {
1364 | file.onerror = error;
1365 | }
1366 | document.querySelector('head').appendChild(file);
1367 | }
1368 | catch(e) { /* TODO */ };
1369 | }
1370 |
1371 | var _get_user_media = undefined,
1372 | _connect_stream_to_src = function() {};
1373 |
1374 | if (navigator.getUserMedia) { // WebRTC 1.0 standard compliant browser
1375 | _get_user_media = navigator.getUserMedia.bind(navigator);
1376 | _connect_stream_to_src = function(media_stream, media_element) {
1377 | media_element.srcObject = media_stream;
1378 | media_element.play();
1379 | };
1380 | }
1381 | else if (navigator.mozGetUserMedia) { // early firefox webrtc implementation
1382 | _get_user_media = navigator.mozGetUserMedia.bind(navigator);
1383 | _connect_stream_to_src = function(media_stream, media_element) {
1384 | media_element.mozSrcObject = media_stream;
1385 | media_element.play();
1386 | };
1387 | }
1388 | else if (navigator.webkitGetUserMedia) { // early webkit webrtc implementation
1389 | _get_user_media = navigator.webkitGetUserMedia.bind(navigator);
1390 | _connect_stream_to_src = function(media_stream, media_element) {
1391 | media_element.src = webkitURL.createObjectURL(media_stream);
1392 | media_element.play();
1393 | };
1394 | }
1395 |
1396 | function _clean_object(object, list_of_keys) {
1397 | var keys = {};
1398 | for (var key in list_of_keys) {
1399 | keys[list_of_keys[key]] = 1;
1400 | }
1401 | for (var key in object) {
1402 | if (!keys[key]) {
1403 | delete object[key];
1404 | }
1405 | }
1406 | return object;
1407 | }
1408 |
1409 | var util = {
1410 | require: _require,
1411 | get_user_media: _get_user_media,
1412 | connect_stream_to_src: _connect_stream_to_src,
1413 | clean_object: _clean_object,
1414 | };
1415 |
1416 | window.awe = new awe();
1417 | this_awe = window.awe;
1418 | this_awe.util = util;
1419 |
1420 | this_awe.AUTO_DETECT_DEVICE_TYPE = true;
1421 | }
1422 | })(window);
1423 | // END FILE: awe-loader.js file
1424 |
--------------------------------------------------------------------------------
/lib/awe-standard-object_clicked.js:
--------------------------------------------------------------------------------
1 | (function(awe) {
2 | var mouse = {};
3 | var projector = new THREE.Projector();
4 | var ray = new THREE.Raycaster();
5 | awe.plugins.add([{
6 | id: 'object_clicked',
7 | auto_register: true,
8 | register: function(){
9 | awe.events.add([
10 | {
11 | id: 'click',
12 | register: function(handler) {
13 | window.addEventListener('click', handler, false);
14 | },
15 | unregister: function(handler){
16 | window.removeEventListener('click', handler, false);
17 | },
18 | handler: function(e) {
19 | var click_handling = awe.settings.view("click_handling");
20 | if (click_handling === undefined || click_handling == true) {
21 | var camera = awe.pov();
22 | mouse.x = (e.clientX/window.innerWidth) * 2 - 1;
23 | mouse.y = -(e.clientY/window.innerHeight) * 2 + 1;
24 | var mouse_vector = new THREE.Vector3(mouse.x, mouse.y, 1);
25 | projector.unprojectVector(mouse_vector, camera);
26 | var direction = mouse_vector.sub(camera.position).normalize();
27 | ray.set(camera.position, direction);
28 | var intersects = ray.intersectObjects(awe.projections.list({ type:'clickable' }), true);
29 | if (intersects.length) {
30 | var mesh = _get_clicked_projection(intersects[0].object);
31 | if (mesh && mesh.projection_id) {
32 | intersects[0].projection_id = mesh.projection_id;
33 | var event = new CustomEvent('object_clicked', { detail:intersects[0] });
34 | window.dispatchEvent(event);
35 | }
36 | }
37 | }
38 | }
39 | }
40 | ]);
41 | },
42 | unregister: function(){
43 | awe.events.delete('click');
44 | }
45 | }]);
46 | function _get_clicked_projection(mesh) {
47 | if (mesh.projection_id == undefined) {
48 | if (mesh.parent == undefined) {
49 | return undefined;
50 | } else {
51 | return _get_clicked_projection(mesh.parent);
52 | }
53 | } else {
54 | return mesh;
55 | }
56 | }
57 | })(window.awe);
58 |
--------------------------------------------------------------------------------
/lib/awe-standard-window_resized.js:
--------------------------------------------------------------------------------
1 | (function(awe) {
2 | awe.plugins.add([{
3 | id: 'window_resized',
4 | auto_register: true,
5 | register: function(){
6 | awe.events.add([
7 | {
8 | id: 'resize',
9 | device_types: {
10 | pc: 1
11 | },
12 | register: function(handler) {
13 | window.addEventListener('resize', handler, false);
14 | },
15 | unregister: function(handler){
16 | window.removeEventListener('resize', handler, false);
17 | },
18 | handler: function(e) {
19 | aspect_ratio = window.innerWidth / window.innerHeight;
20 | awe.pov().aspect = aspect_ratio;
21 | awe.pov().updateProjectionMatrix();
22 | awe.renderer().setSize(window.innerWidth, window.innerHeight);
23 | awe.scene_needs_rendering = 1;
24 | }
25 | }
26 | ]);
27 | },
28 | unregister: function(){
29 | awe.events.delete('resize');
30 | }
31 | }]);
32 | })(window.awe);
33 |
--------------------------------------------------------------------------------
/lib/awe-standard.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | The MIT License
4 |
5 | Copyright (c) 2013 Rob Manson & Malgorzata Wierzbicka, http://buildAR.com.
6 | All rights reserved.
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in
16 | all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | THE SOFTWARE.
25 |
26 | */
27 |
28 | (function(window) {
29 | var this_awe;
30 | var _clickable_objects = [];
31 | if (window.awe) {
32 | this_awe = window.awe;
33 |
34 | this_awe.constructor.prototype.renderers = new awe_v8();
35 | this_awe.constructor.prototype.renderers.add = function(BODY, HEAD) {
36 | if (!BODY) { BODY = {}; }
37 | if (!HEAD) { HEAD = {}; }
38 | if (this_awe.settings.view('renderer')) {
39 | if (this_awe.capabilities.view("webgl") && this_awe.settings.view('renderer') == 'webgl') {
40 | var antialias = this_awe.settings.view('antialias') || true;
41 | var renderer = new THREE.WebGLRenderer({ antialias: antialias });
42 | var shadows = this_awe.settings.view('shadows') || false;
43 | // spotlight is required to add shadows!
44 | // see https://github.com/mrdoob/three.js/issues/748
45 | if (shadows) {
46 | renderer.shadowMapEnabled = shadows;
47 | var shadow_map_type = this_awe.settings.view('shadow_map_type') || "pcf_soft";
48 | if (shadow_map_type == "basic") {
49 | renderer.shadowMapType = THREE.BasicShadowMap;
50 | } else if (shadow_map_type == "pcf") {
51 | renderer.shadowMapType = THREE.PCFShadowMap;
52 | } else if (shadow_map_type == "pcf_soft") {
53 | renderer.shadowMapType = THREE.PCFSoftShadowMap;
54 | } else {
55 | throw { code: 500, message: 'shadow_map_type unsupported' };
56 | }
57 | }
58 | }
59 | else if (this_awe.settings.view('renderer') == 'css3d' || !this_awe.capabilities.view("webgl")) {
60 | if (this_awe.capabilities.view({ id: 'css3d' })) {
61 | var renderer = new THREE.CSS3DRenderer();
62 | }
63 | else {
64 | throw { code: 500, message: 'three.js css3d renderer creation failed' };
65 | }
66 | }
67 | if (!renderer) {
68 | throw { code: 500, message: 'three.js renderer creation failed' };
69 | }
70 | else {
71 | var l = this.constructor.prototype.list().length;
72 | renderer.setSize(window.outerWidth, window.outerHeight);
73 | var awe_canvas = renderer.domElement;
74 | awe_canvas.id = 'awe_canvas-'+l;
75 | if (this_awe.settings.view('canvas_style')) {
76 | try {
77 | for (var i in this_awe.settings.view('canvas_style')) {
78 | awe_canvas.style[i] = this_awe.settings.view('canvas_style')[i];
79 | }
80 | }
81 | catch(e) { /* TODO */ };
82 | }
83 | else {
84 | awe_canvas.style.position = 'absolute';
85 | awe_canvas.style.top = '0px';
86 | awe_canvas.style.left = '0px';
87 | awe_canvas.style.width = '100%';
88 | awe_canvas.style.height = '100%';
89 | }
90 | if (BODY.container_id && document.getElementById(BODY.container_id)) {
91 | document.getElementById(BODY.container_id).appendChild(awe_canvas);
92 | }
93 | else if (this_awe.settings.view('container_id') && document.getElementById(this_awe.settings.view('container_id'))) {
94 | document.getElementById(this_awe.settings.view('container_id')).appendChild(awe_canvas);
95 | }
96 | else {
97 | document.body.appendChild(awe_canvas);
98 | }
99 | }
100 | }
101 | else {
102 | throw { code: 500, message: 'three.js renderer not defined' };
103 | }
104 | BODY.value = renderer;
105 | this_awe.scene_needs_rendering = 1;
106 | return this.constructor.prototype.add.call(this, BODY, HEAD); // super
107 | }
108 |
109 | this_awe.constructor.prototype.renderer = function() {
110 | return this_awe.renderers.view({ id: 'default' });
111 | };
112 |
113 | this_awe.constructor.prototype.lights = new awe_v8();
114 | this_awe.constructor.prototype.lights.add = function(BODY, HEAD) {
115 | if (!BODY) { BODY = {}; }
116 | if (!HEAD) { HEAD = {}; }
117 | var id = BODY.id || "light-"+new Date().getTime()+'-'+Math.round(Math.random()*1000);
118 | delete BODY.id;
119 | if (!BODY.color) {
120 | BODY.color = 0x404040;
121 | }
122 | var light = new THREE.AmbientLight(BODY.color);
123 | if (BODY.intensity) {
124 | light.intensity = BODY.intensity;
125 | }
126 | switch (BODY.type) {
127 | case 'area':
128 | light = new THREE.AreaLight(BODY.color);
129 | break;
130 | case 'directional':
131 | light = new THREE.DirectionalLight(BODY.color);
132 | break;
133 | case 'hemisphere':
134 | light = new THREE.HemisphereLight(BODY.color);
135 | if (BODY.ground_color) {
136 | light.groundColor = BODY.ground_color;
137 | }
138 | break;
139 | case 'point':
140 | light = new THREE.PointLight(BODY.color);
141 | if (BODY.distance) {
142 | light.distance = BODY.distance;
143 | }
144 | break;
145 | case 'spot':
146 | light = new THREE.SpotLight(BODY.color);
147 | break;
148 | }
149 |
150 | if (light.position && BODY.position && typeof(BODY.position) == 'object') {
151 | for (var p in BODY.position) {
152 | light.position[p] = BODY.position[p];
153 | }
154 | }
155 | if (light.target && light.target.position && BODY.target && typeof(BODY.target) == 'object') {
156 | for (var p in BODY.target) {
157 | light.target.position[p] = BODY.target[p];
158 | }
159 | }
160 | if (BODY.cast_shadow) {
161 | light.castShadow = BODY.cast_shadow;
162 | }
163 | this_awe.scene().add(light);
164 | this_awe.scene_needs_rendering = 1;
165 | return this.constructor.prototype.add.call(this, { id: id, value: light }); // super
166 | }
167 |
168 | this_awe.constructor.prototype.video_streams = new awe_v8();
169 | this_awe.constructor.prototype.video_streams.add = function(BODY, HEAD) {
170 | if (this_awe.capabilities.view('gum')) {
171 | if (!BODY) { BODY = {}; }
172 | if (!HEAD) { HEAD = {}; }
173 | try {
174 | var self = this,
175 | video_id = 'video_stream-'+(new Date()).getTime(),
176 | width = 640, // TODO should be based on viewport width
177 | height = 480, // TODO should be based on viewport height
178 | video = document.createElement('video');
179 |
180 | video.setAttribute('id', video_id);
181 | video.setAttribute('autoplay', true);
182 |
183 | BODY.video_element = video;
184 | var result = this.constructor.prototype.add.call(this, BODY, HEAD); // super
185 |
186 | // if many sources try to get the environemt-facing camera
187 | var go = function(video_source_id){
188 | var options = {
189 | video: true
190 | };
191 | if (video_source_id) {
192 | options.video = {
193 | optional: [{ facingMode: "environment" }, {sourceId: video_source_id}]
194 | };
195 | }
196 | this_awe.util.get_user_media(options,
197 | function(stream) {
198 | video.setAttribute('width', '100%');
199 | video.setAttribute('height', '100%');
200 | document.body.appendChild(video);
201 | video.style.position = 'absolute';
202 | video.style.top = '-999em';
203 | video.style.left = '-999em';
204 | video.style.height = '100%';
205 | video.style.width = '100%';
206 |
207 | BODY.stream = stream;
208 | self.constructor.prototype.update.call(this, {data: {stream: stream}, where: {id: BODY.id}}, HEAD); // super
209 | this_awe.util.connect_stream_to_src(stream, video);
210 |
211 | var event = new CustomEvent('gum_ready');
212 | window.dispatchEvent(event);
213 | },
214 | function(e) {
215 | var event = new CustomEvent('gum_error');
216 | window.dispatchEvent(event);
217 | }
218 | );
219 | }
220 |
221 | if (window.MediaStreamTrack && window.MediaStreamTrack.getSources) {
222 | MediaStreamTrack.getSources(function(source_infos) {
223 | var selected_source = null;
224 | for (var i = 0; i != source_infos.length; ++i) {
225 | var source_info = source_infos[i];
226 | if (source_info.kind === 'video') {
227 | if (!selected_source || (source_info.facing && source_info.facing == "environment")) {
228 | selected_source = source_info.id;
229 | }
230 | }
231 | }
232 | go(selected_source);
233 | });
234 | }
235 | else {
236 | go();
237 | }
238 | }
239 | catch(e) {
240 | console.log(e);
241 | }
242 | return result;
243 | }
244 | else {
245 | throw { code: 500, message: 'video streams not supported by this browser' };
246 | }
247 | }
248 | this_awe.constructor.prototype.video_streams.delete = function(BODY, HEAD) {
249 | if (this_awe.capabilities.view('gum')) {
250 | if (!BODY) { BODY = {}; }
251 | if (!HEAD) { HEAD = {}; }
252 | try {
253 | if (typeof BODY == 'string' || typeof BODY == 'number') {
254 | video_stream = this.constructor.prototype.view(BODY);
255 | BODY = { id: BODY };
256 | }
257 | else if (BODY.id) {
258 | video_stream = this.constructor.prototype.view(BODY.id);
259 | }
260 | if (video_stream && video_stream.stream) {
261 | video_stream.stream.stop()
262 | }
263 | return this.constructor.prototype.delete.call(this, BODY, HEAD); // super
264 | }
265 | catch(e) {
266 | console.log(e);
267 | }
268 | }
269 | };
270 |
271 | this_awe.constructor.prototype.video_stream = function() {
272 | return this_awe.video_streams.view({ id: 'default' });
273 | };
274 |
275 | this_awe.constructor.prototype.scenes = new awe_v8();
276 | this_awe.constructor.prototype.scenes.add = function(BODY, HEAD) {
277 | if (!BODY) { BODY = {}; }
278 | if (!HEAD) { HEAD = {}; }
279 | var scene = new THREE.Scene();
280 | BODY.value = scene;
281 | this_awe.scene_needs_rendering = 1;
282 | return this.constructor.prototype.add.call(this, BODY, HEAD); // super
283 | }
284 |
285 | this_awe.constructor.prototype.scene = function() {
286 | return this_awe.scenes.view({ id: 'default' });
287 | };
288 | this_awe.constructor.prototype.scene.stringify = function() {
289 | // TODO walk the scene and stringify to JSON
290 | }
291 |
292 | this_awe.constructor.prototype.povs = new awe_v8();
293 | this_awe.constructor.prototype.povs.add = function(BODY, HEAD) {
294 | if (!BODY) { BODY = {}; }
295 | if (!HEAD) { HEAD = {}; }
296 | var fov = this_awe.settings.view('fov') || 65; // ~fov of ios devices - TODO: should set default based on device_type or ideally camera introspection
297 | var near = this_awe.settings.view('near') || 1;
298 | var far = this_awe.settings.view('far') || 10000;
299 | var renderer = this_awe.renderer();
300 | var aspect_ratio = renderer.domElement.clientWidth / renderer.domElement.clientHeight;
301 | if (BODY.renderer_id) {
302 | renderer = awe.renderers.view(BODY.renderer_id) || this_awe.renderer();
303 | if (renderer) {
304 | aspect_ratio = renderer.domElement.clientWidth / renderer.domElement.clientHeight;
305 | }
306 | }
307 | delete(BODY.renderer_id);
308 |
309 | var pov = new THREE.PerspectiveCamera(
310 | fov,
311 | aspect_ratio,
312 | near,
313 | far
314 | );
315 | if (!this_awe.settings.view('default_camera_position')) {
316 | this_awe.settings.add({
317 | id: 'default_camera_position',
318 | value: { x:0, y:0, z:0 },
319 | });
320 | }
321 | var position = _extend({x:0, y:0, z:0}, this_awe.settings.view('default_camera_position'));
322 | pov.position.set(position.x, position.y, position.z);
323 | pov.lookAt(this_awe.origin);
324 |
325 | pov.constructor.prototype.look_at_projection = function(projection_name) {
326 | var projection = this_awe.projections.view(projection_name);
327 | var origin_position = projection.mesh.parent.position;
328 | var projection_position = projection.mesh.position;
329 | var position = {};
330 | for (var p in origin_position) {
331 | position[p] = origin_position[p]+projection_position[p];
332 | }
333 | this.lookAt(position);
334 | _map_audio_listener_to_pov();
335 | this_awe.scene_needs_rendering = 1;
336 | };
337 |
338 | pov.constructor.prototype.look_at_poi = function(poi) {
339 | this.lookAt(this_awe.pois.view(poi).origin.mesh.position);
340 | _map_audio_listener_to_pov();
341 | this_awe.scene_needs_rendering = 1;
342 | };
343 |
344 | pov.constructor.prototype.look_at = function(position) {
345 | this.lookAt(new THREE.Vector3(position.x, position.y, position.z));
346 | _map_audio_listener_to_pov();
347 | this_awe.scene_needs_rendering = 1;
348 | };
349 |
350 | BODY.value = pov;
351 | this_awe.scene().add(pov);
352 | this_awe.scene_needs_rendering = 1;
353 |
354 | return this.constructor.prototype.add.call(this, BODY, HEAD); // super
355 | }
356 |
357 | this_awe.constructor.prototype.povs.update = function(BODY, HEAD) {
358 | if (!BODY) { BODY = {}; }
359 | if (!HEAD) { HEAD = {}; }
360 | if (BODY.data && BODY.where && BODY.where.id) {
361 | var fields_updated = [];
362 | if (BODY.data.position) {
363 | fields_updated.push('position');
364 | var position = this_awe.pov().position;
365 | for (var p in BODY.data.position) {
366 | position[p] = BODY.data.position[p];
367 | }
368 | if (this_awe.capabilities.view("audio")) {
369 | this_awe.util.audio_context.listener.setPosition(position.x, position.y, position.z);
370 | }
371 | }
372 | if (BODY.data.scale) { fields_updated.push('scale'); }
373 | if (BODY.data.rotation) {
374 | fields_updated.push('rotation');
375 | _map_audio_listener_to_pov();
376 | }
377 | if (fields_updated.length) {
378 | HEAD.fields_updated = fields_updated;
379 | }
380 | if(BODY.data.animation && parseFloat(BODY.data.animation.duration) > 0) {
381 | _tween(_extend({
382 | mesh: this_awe.projections.view(BODY.where.id).mesh, // TODO this is a bug so need to refactor tweening to support pov().position
383 | end_state: BODY.data
384 | }, BODY.data.animation));
385 | }
386 | else {
387 | _update_mesh_io(BODY.data, this_awe.pov());
388 | }
389 | this_awe.scene_needs_rendering = 1;
390 | }
391 | return this.constructor.prototype.update.call(this, BODY, HEAD); // super
392 | };
393 |
394 | this_awe.constructor.prototype.pov = function() {
395 | return this_awe.povs.view({ id: 'default' });
396 | };
397 |
398 | this_awe.constructor.prototype.pois = new awe_v8();
399 | this_awe.constructor.prototype.pois.add = function(BODY, HEAD) {
400 | if (!BODY) { BODY = {}; }
401 | if (!HEAD) { HEAD = {}; }
402 | var id = new Date().getTime()+'-'+Math.round(Math.random()*1000);
403 | if (!BODY.id) {
404 | BODY.id = 'poi-'+id;
405 | }
406 | var projections = [];
407 | if (BODY.projections && Array.isArray(BODY.projections)) {
408 | projections = BODY.projections;
409 | delete BODY.projections;
410 | }
411 | var origin_id = 'projection-'+id+'-origin';
412 | var projection_io = {};
413 | var result = this.constructor.prototype.add.call(this, BODY, HEAD); // super
414 | var poi = this_awe.pois.view(BODY.id);
415 | this_awe.projections.add({
416 | id: origin_id,
417 | position: BODY.position || { x: 0, y: 0, z: 0 },
418 | scale: BODY.scale || { x: 1, y: 1, z: 1 },
419 | rotation: { x: 0, y: 0, z: 0 },
420 | geometry: { shape: 'sphere', radius: 0.1 },
421 | }, { poi_id: BODY.id, is_origin: true });
422 | poi.origin = this_awe.projections.view(origin_id);
423 | if (!poi.projections) {
424 | poi.projections = [];
425 | }
426 | for (var projection in projections) {
427 | projection_io = projections[projection];
428 | if (!projection_io.id) {
429 | projection_io.id = 'projection-'+id;
430 | }
431 | this_awe.projections.add(projection_io, { poi_id: BODY.id });
432 | }
433 | return result;
434 | };
435 | this_awe.constructor.prototype.pois.update = function(BODY, HEAD) {
436 | if (!BODY) { BODY = {}; }
437 | if (!HEAD) { HEAD = {}; }
438 | if (BODY.data && BODY.where && BODY.where.id) {
439 | var fields_updated = [];
440 | if (BODY.data.position) { fields_updated.push('position'); }
441 | if (BODY.data.scale) { fields_updated.push('scale'); }
442 | if (BODY.data.rotation) { fields_updated.push('rotation'); }
443 | if (fields_updated.length) {
444 | HEAD.fields_updated = fields_updated;
445 | }
446 | if(BODY.data.animation && parseFloat(BODY.data.animation.duration) > 0) {
447 | _tween(_extend({
448 | mesh: this_awe.pois.view(BODY.where.id).origin.mesh,
449 | end_state: BODY.data
450 | }, BODY.data.animation));
451 | }
452 | else {
453 | _update_mesh_io(BODY.data, this_awe.pois.view(BODY.where.id).origin.mesh);
454 | this_awe.scene_needs_rendering = 1;
455 | }
456 | }
457 | return this.constructor.prototype.update.call(this, BODY, HEAD); // super
458 | };
459 | this_awe.constructor.prototype.pois.delete = function(BODY, HEAD) {
460 | if (!BODY) { BODY = {}; }
461 | if (!HEAD) { HEAD = {}; }
462 | var projection;
463 | if (typeof BODY == 'string' || typeof BODY == 'number') {
464 | poi = this_awe.pois.view(BODY);
465 | BODY = { id: BODY };
466 | }
467 | else if (BODY.id) {
468 | poi = this_awe.pois.view(BODY.id);
469 | }
470 | if (poi.origin.mesh) {
471 | this_awe.scene().remove(poi.origin.mesh);
472 | }
473 | if (poi.projections) {
474 | for (var i in poi.projections) {
475 | this_awe.projections.delete(poi.projections[i]);
476 | }
477 | }
478 | this_awe.scene_needs_rendering = 1;
479 | return this.constructor.prototype.delete.call(this, BODY, HEAD); // super
480 | };
481 |
482 | this_awe.constructor.prototype.projections = new awe_v8();
483 | this_awe.constructor.prototype.projections.list = function(BODY, HEAD) {
484 | if (!BODY) { BODY = {}; }
485 | if (!HEAD) { HEAD = {}; }
486 | if (BODY.type && BODY.type === "clickable") {
487 | return _clickable_objects;
488 | } else {
489 | return this.constructor.prototype.list.call(this, BODY, HEAD); // super
490 | }
491 | }
492 | this_awe.constructor.prototype.projections.add = function(BODY, HEAD) {
493 | if (!BODY) { BODY = {}; }
494 | if (!HEAD) { HEAD = {}; }
495 | var geometry, material, mesh, parent;
496 | if (!BODY.id) {
497 | throw 'BODY.id required';
498 | }
499 | if (this_awe.projections.view(BODY.id)) {
500 | throw 'BODY.id already exists';
501 | }
502 | if (HEAD.parent && HEAD.parent.object_id && HEAD.parent.object_type && this_awe[HEAD.parent.object_type+'s'] && ''+this_awe[HEAD.parent.object_type+'s'] == 'awe_v8_object') {
503 | try {
504 | parent = this_awe[HEAD.parent.object_type+'s'].view(HEAD.parent.object_id);
505 | }
506 | catch(e) {}
507 | }
508 | else if (HEAD.poi_id) {
509 | parent = this_awe.pois.view(HEAD.poi_id);
510 | }
511 | if (!parent) {
512 | throw 'HEAD.poi_id or HEAD.parent required';
513 | }
514 | if (!BODY.material) {
515 | BODY.material = {};
516 | }
517 | if (!BODY.texture) {
518 | BODY.texture = {};
519 | }
520 | if (BODY.sound) {
521 | if (this_awe.capabilities.view("audio")) {
522 | if (BODY.sound.path == undefined) {
523 | throw "sound path required";
524 | }
525 | BODY.sound.source = this_awe.util.audio_context.createBufferSource();
526 | BODY.sound.panner = this_awe.util.audio_context.createPanner();
527 | BODY.sound.source.connect(BODY.sound.panner);
528 | BODY.sound.panner.connect(this_awe.util.audio_context.destination);
529 | BODY.sound.panner.refDistance = 100;
530 | var position = { x:0, y:0, z:0 };
531 | if (BODY.position !== undefined) {
532 | for (var p in BODY.position) {
533 | position[p] = BODY.position[p];
534 | }
535 | }
536 | BODY.sound.panner.setPosition(position.x, position.y, position.z);
537 | this_awe.sounds.add(BODY.sound);
538 | }
539 | }
540 | if (BODY.geometry) {
541 | if (BODY.geometry.shape) {
542 | var shape = _validate_shape(BODY.geometry);
543 | switch(BODY.geometry.shape) {
544 | case 'cube':
545 | geometry = new THREE.CubeGeometry(shape.x, shape.y, shape.z);
546 | break;
547 | case 'sphere':
548 | geometry = new THREE.SphereGeometry(shape.radius, shape.widthSegments, shape.heightSegments, shape.phiStart, shape.phiLength, shape.thetaStart, shape.thetaLength);
549 | break;
550 | case 'cylinder':
551 | geometry = new THREE.CylinderGeometry(shape.radiusTop, shape.radiusBottom, shape.height, shape.radiusSegments, shape.heightSegments, shape.openEnded);
552 | break;
553 | case 'lathe':
554 | geometry = new THREE.LatheGeometry(shape.points, shape.segments, shape.phiStart, shape.phiLength);
555 | break;
556 | case 'octahedron':
557 | geometry = new THREE.OctahedronGeometry(shape.radius, shape.detail);
558 | break;
559 | case 'plane':
560 | geometry = new THREE.PlaneGeometry(shape.width, shape.height, shape.widthSegments, shape.heightSegments)
561 | break;
562 | case 'tetrahedron':
563 | geometry = new THREE.TetrahedronGeometry(shape.radius, shape.detail);
564 | break;
565 | case 'text':
566 | geometry = new THREE.TextGeometry(shape.text, shape.parameters)
567 | break;
568 | case 'torus':
569 | geometry = new THREE.TorusGeometry(shape.radius, shape.tube, shape.radialSegments, shape.tubularSegments, shape.arc);
570 | break;
571 | case 'torusknot':
572 | geometry = new THREE.TorusKnotGeometry(shape.radius, shape.tube, shape.radialSegments, shape.tubularSegments, shape.p, shape.q, shape.heightScale);
573 | break;
574 | case 'tube':
575 | geometry = new THREE.TubeGeometry(shape.path, shape.segments, shape.radius, shape.radiusSegments, shape.closed, shape.debug)
576 | break;
577 | default:
578 | geometry = new THREE.CubeGeometry(10,10,10);
579 | }
580 | if (geometry) {
581 | var texture, material;
582 | if (BODY.texture.path) {
583 | if (BODY.geometry.x) {
584 | BODY.texture.width = BODY.geometry.x;
585 | }
586 | if (BODY.geometry.y) {
587 | BODY.texture.height = BODY.geometry.y;
588 | }
589 | var texture_id = this_awe.textures.add(BODY.texture);
590 | if (BODY.texture.color) {
591 | BODY.material.color = BODY.texture.color;
592 | }
593 | BODY.material.map = this_awe.textures.view(texture_id);
594 | }
595 | var material_id = this_awe.materials.add(BODY.material);
596 | var material = this_awe.materials.view(material_id);
597 | mesh = new THREE.Mesh(geometry, material);
598 | this_awe.scene_needs_rendering = 1;
599 | }
600 | }
601 | else if (BODY.geometry.path) {
602 | var loader;
603 | if (BODY.material.path) {
604 | loader = new THREE.OBJMTLLoader();
605 | loader.load(BODY.geometry.path, BODY.material.path, function(mesh) {
606 | BODY.mesh = _update_mesh_io(BODY, mesh, true);
607 | if (parent.origin) {
608 | parent.origin.mesh.add(BODY.mesh);
609 | }
610 | else {
611 | parent.add(BODY.mesh);
612 | }
613 | var _clickable_id = _clickable_objects.length;
614 | BODY.mesh.projection_id = BODY.id;
615 | _clickable_objects.push(BODY.mesh);
616 | this_awe.projections.update({ data:{ _clickable_object_id:_clickable_id }, where:{ id:BODY.id } });
617 | this_awe.scene_needs_rendering = 1;
618 | this_awe.scene_needs_rendering = 1;
619 | var event = new CustomEvent('projection_loaded', { detail: BODY.id });
620 | window.dispatchEvent(event);
621 | });
622 | }
623 | else {
624 | loader = new THREE.OBJLoader();
625 | var texture;
626 | if (BODY.texture.path) {
627 | if (BODY.geometry.x) {
628 | BODY.texture.width = BODY.geometry.x;
629 | }
630 | if (BODY.geometry.y) {
631 | BODY.texture.height = BODY.geometry.y;
632 | }
633 | var texture_id = this_awe.textures.add(BODY.texture);
634 | texture = this_awe.textures.view(texture_id);
635 | }
636 | else {
637 | var texture_id = this_awe.textures.add();
638 | texture = this_awe.textures.view(texture_id);
639 | }
640 | loader.load(BODY.geometry.path, function (mesh) {
641 | mesh.traverse(function (child) {
642 | if ( child instanceof THREE.Mesh ) {
643 | child.material.map = texture;
644 | }
645 | });
646 | BODY.mesh = _update_mesh_io(BODY, mesh, true);
647 | if (parent.origin) {
648 | parent.origin.mesh.add(BODY.mesh);
649 | }
650 | else {
651 | parent.add(BODY.mesh);
652 | }
653 |
654 | var _clickable_id = _clickable_objects.length;
655 | BODY.mesh.projection_id = BODY.id;
656 | _clickable_objects.push(BODY.mesh);
657 | this_awe.projections.update({ data:{ _clickable_object_id:_clickable_id }, where:{ id:BODY.id } });
658 | this_awe.scene_needs_rendering = 1;
659 | var event = new CustomEvent('projection_loaded', { detail: BODY.id });
660 | window.dispatchEvent(event);
661 | });
662 | }
663 | return this.constructor.prototype.add.call(this, BODY, HEAD); // super
664 | }
665 | else {
666 | geometry = new THREE.CubeGeometry(10,10,10);
667 | var material_id = this_awe.materials.add(BODY.material);
668 | var material = this_awe.materials.view(material_id);
669 | mesh = new THREE.Mesh(geometry, material);
670 | this_awe.scene_needs_rendering = 1;
671 | }
672 | }
673 | BODY.mesh = _update_mesh_io(BODY, mesh, true);
674 | if (BODY.scale) {
675 | for (var p in BODY.scale) {
676 | BODY.mesh.scale[p] = BODY.scale[p];
677 | }
678 | }
679 | var result = this.constructor.prototype.add.call(this, BODY, HEAD); // super
680 | var projection = this_awe.projections.view(BODY.id);
681 | if (HEAD.is_origin) {
682 | this_awe.scene().add(BODY.mesh);
683 | }
684 | else {
685 | var _clickable_id = _clickable_objects.length;
686 | BODY.mesh.projection_id = result.id;
687 | _clickable_objects.push(BODY.mesh);
688 | this_awe.projections.update({ data:{ _clickable_object_id:_clickable_id }, where:{ id:result.id } });
689 |
690 | if (parent.origin) {
691 | parent.origin.mesh.add(BODY.mesh);
692 | }
693 | else {
694 | parent.add(BODY.mesh);
695 | }
696 | }
697 | if (!parent.projections) {
698 | parent.projections = [];
699 | }
700 | parent.projections.push(projection.id);
701 | var event = new CustomEvent('projection_loaded', {detail: BODY.id});
702 | window.dispatchEvent(event);
703 | return result;
704 | };
705 | this_awe.constructor.prototype.projections.view = function(BODY, HEAD) {
706 | if (!BODY) { BODY = {}; }
707 | if (!HEAD) { HEAD = {}; }
708 | var projection = this.constructor.prototype.view.call(this, BODY, HEAD); // super
709 | if (projection) {
710 | projection.position = {
711 | x: projection.mesh.position.x,
712 | y: projection.mesh.position.y,
713 | z: projection.mesh.position.z,
714 | };
715 | projection.scale = {
716 | x: projection.mesh.scale.x,
717 | y: projection.mesh.scale.y,
718 | z: projection.mesh.scale.z,
719 | };
720 | projection.rotation = {
721 | x: THREE.Math.radToDeg(projection.mesh.rotation.x),
722 | y: THREE.Math.radToDeg(projection.mesh.rotation.y),
723 | z: THREE.Math.radToDeg(projection.mesh.rotation.z),
724 | };
725 | }
726 | return projection;
727 | };
728 | this_awe.constructor.prototype.projections.update = function(BODY, HEAD) {
729 | if (!BODY) { BODY = {}; }
730 | if (!HEAD) { HEAD = {}; }
731 | if (BODY.data && BODY.where && BODY.where.id) {
732 | var fields_updated = [];
733 | if (BODY.data.position) { fields_updated.push('position'); }
734 | if (BODY.data.scale) { fields_updated.push('scale'); }
735 | if (BODY.data.rotation) { fields_updated.push('rotation'); }
736 | if (fields_updated.length) {
737 | HEAD.fields_updated = fields_updated;
738 | }
739 | if(BODY.data.animation && parseFloat(BODY.data.animation.duration) > 0) {
740 | _tween(_extend({
741 | mesh: this_awe.projections.view(BODY.where.id).mesh,
742 | end_state: BODY.data
743 | }, BODY.data.animation));
744 | }
745 | else {
746 | BODY.mesh = _update_mesh_io(BODY.data, this_awe.projections.view(BODY.where.id).mesh);
747 | }
748 | }
749 | return this.constructor.prototype.update.call(this, BODY, HEAD); // super
750 | };
751 | this_awe.constructor.prototype.projections.delete = function(BODY, HEAD) {
752 | if (!BODY) { BODY = {}; }
753 | if (!HEAD) { HEAD = {}; }
754 | var projection;
755 | if (typeof BODY == 'string' || typeof BODY == 'number') {
756 | projection = this_awe.projections.view(BODY);
757 | BODY = { id: BODY };
758 | }
759 | else if (BODY.id) {
760 | projection = this_awe.projections.view(BODY.id);
761 | }
762 | if (projection.mesh) {
763 | this_awe.scene().remove(projection.mesh);
764 | _clickable_objects.splice(projection._clickable_object_id, 1);
765 | this_awe.scene_needs_rendering = 1;
766 | }
767 | return this.constructor.prototype.delete.call(this, BODY, HEAD); // super
768 | };
769 |
770 | this_awe.constructor.prototype.textures = new awe_v8();
771 | this_awe.constructor.prototype.textures.add = function(BODY, HEAD) {
772 | if (!BODY) { BODY = {}; }
773 | if (!HEAD) { HEAD = {}; }
774 | var id = "texture-"+new Date().getTime()+'-'+Math.round(Math.random()*1000);
775 | var texture = new THREE.Texture();
776 | if (BODY.path) {
777 | var path = undefined;
778 | var v = document.createElement('video');
779 | if (Array.isArray(BODY.path)) {
780 | for (var p in BODY.path) {
781 | var tmp_path = BODY.path[p];
782 | var suffix = tmp_path.match(/\.(webm|mp4|ogg|ogv)/i);
783 | if (suffix) {
784 | if (suffix[1].toLowerCase() == "ogv") {
785 | suffix[1] = "ogg";
786 | }
787 | var can_play = v.canPlayType("video/"+suffix[1].toLowerCase());
788 | if (can_play == "probably" || can_play == "maybe") {
789 | path = BODY.path[p];
790 | break;
791 | }
792 | }
793 | }
794 | } else if (BODY.path.match(/\.(webm|mp4|ogg|ogv)/i)) {
795 | path = BODY.path;
796 | }
797 | if (path) {
798 | if (BODY.width) {
799 | v.width = BODY.width;
800 | }
801 | else {
802 | v.width = 320;
803 | }
804 | if (BODY.height) {
805 | v.height = BODY.height;
806 | }
807 | else {
808 | v.height = 240;
809 | }
810 | v.src = path;
811 | var autoplay = true;
812 | if (BODY.autoplay !== undefined) {
813 | autoplay = BODY.autoplay;
814 | }
815 | v.autoplay = autoplay;
816 | v.load();
817 | if (autoplay) {
818 | v.play();
819 | }
820 | if (BODY.loop !== undefined) {
821 | v.loop = BODY.loop;
822 | }
823 | if (BODY.muted !== undefined) {
824 | v.muted = BODY.muted;
825 | }
826 |
827 | var c = document.createElement('canvas');
828 | c.width = v.width;
829 | c.height = v.height;
830 |
831 | var cc = c.getContext('2d');
832 | texture = new THREE.Texture(c);
833 | texture.video = v;
834 | texture.cc = cc;
835 | }
836 | else if (BODY.path.match(/^camerastream$/i)) {
837 | var v = this_awe.video_stream().video_element;
838 | if (BODY.width) {
839 | v.width = BODY.width;
840 | }
841 | else {
842 | v.width = 320;
843 | }
844 | if (BODY.height) {
845 | v.height = BODY.height;
846 | }
847 | else {
848 | v.height = 240;
849 | }
850 | v.autoplay = true;
851 | v.play();
852 | this_awe.util.connect_stream_to_src(this_awe.video_stream().stream, v);
853 |
854 | var c = document.createElement('canvas');
855 | c.width = v.width;
856 | c.height = v.height;
857 |
858 | var cc = c.getContext('2d');
859 | texture = new THREE.Texture(c);
860 | texture.video = v;
861 | texture.cc = cc;
862 | }
863 | else {
864 | texture = THREE.ImageUtils.loadTexture(BODY.path, undefined, function() {
865 | this_awe.scene_needs_rendering = 1;
866 | });
867 | }
868 | return this.constructor.prototype.add.call(this, { id: id, value: texture }); // super
869 | }
870 | else {
871 | throw { code: 500, message: 'texture.path required' };
872 | }
873 | }
874 |
875 | this_awe.constructor.prototype.materials = new awe_v8();
876 | this_awe.constructor.prototype.materials.add = function(BODY, HEAD) {
877 | if (!BODY) { BODY = {}; }
878 | if (!HEAD) { HEAD = {}; }
879 | var id = BODY.id || "material-"+new Date().getTime()+'-'+Math.round(Math.random()*1000);
880 | delete BODY.id;
881 | var type = BODY.type || 'basic';
882 | delete BODY.type;
883 | if (!BODY.wireframe) {
884 | BODY.wireframe = false;
885 | }
886 | if (!BODY.color) {
887 | BODY.color = 0x404040;
888 | }
889 | var side = THREE.DoubleSide;
890 | if (BODY.side) {
891 | if (BODY.side == "front") {
892 | side = THREE.FrontSide;
893 | }
894 | else if (BODY.side == "back") {
895 | side = THREE.BackSide;
896 | }
897 | delete BODY.side;
898 | }
899 | if (!BODY.overdraw) {
900 | BODY.overdraw = true;
901 | }
902 | var material = new THREE.MeshBasicMaterial(BODY);
903 | switch(type) {
904 | case 'phong':
905 | if (!BODY.shading) {
906 | BODY.shading = THREE.SmoothShading;
907 | }
908 | material = new THREE.MeshPhongMaterial(BODY);
909 | break;
910 | case 'lambert':
911 | material = new THREE.MeshLambertMaterial(BODY);
912 | break;
913 | case 'shader':
914 | material = new THREE.ShaderMaterial(BODY);
915 | break;
916 | case 'sprite':
917 | material = new THREE.SpriteMaterial(BODY);
918 | break;
919 | case 'sprite_canvas':
920 | material = new THREE.SpriteCanvasMaterial(BODY);
921 | break;
922 | }
923 | material.side = side;
924 | return this.constructor.prototype.add.call(this, { id: id, value: material }); // super
925 | }
926 |
927 | this_awe.constructor.prototype.sounds = new awe_v8();
928 | this_awe.constructor.prototype.sounds.add = function(BODY, HEAD) {
929 | if (this_awe.capabilities.view("audio")) {
930 | if (!BODY) { BODY = {}; }
931 | if (!HEAD) { HEAD = {}; }
932 | var id = BODY.id || "sound-"+new Date().getTime()+'-'+Math.round(Math.random()*1000);
933 | delete BODY.id;
934 | if (BODY.autoplay == undefined) {
935 | BODY.autoplay = true;
936 | }
937 | _load_sound(BODY);
938 | return this.constructor.prototype.add.call(this, { id: id, value: BODY }); // super
939 | }
940 | }
941 |
942 | this_awe.constructor.prototype.tween_functions = new awe_v8();
943 | this_awe.constructor.prototype.tween_functions.add({
944 | id: 'linear',
945 | value: function(io) {
946 | return io.step/io.steps_total;
947 | }
948 | });
949 |
950 | this_awe.constructor.prototype.setup_scene = function(io) {
951 | this.origin = new THREE.Vector3(0,0,0);
952 | this_awe.renderers.add({ id: 'default' });
953 | this_awe.scenes.add({ id: 'default' });
954 | this_awe.povs.add({ id: 'default' });
955 | if (this_awe.settings.view('start_video_stream')) {
956 | this_awe.setup_stream();
957 | }
958 | var lights = this_awe.lights.list();
959 | if (!lights.length) {
960 | var default_lights = this_awe.settings.view('default_lights');
961 | if (default_lights && Array.isArray(default_lights)) {
962 | for (var i=0,l=default_lights.length;i min_ts && count <= max_ts) {
1557 | step = j;
1558 | transform.add(tr);
1559 | }
1560 | }
1561 | transform_data.advancement = max_ts;
1562 | if (!isNaN(step) && step != transform_data.current_step) {
1563 | try {
1564 | var current_transform = _get_mesh_state(mesh);
1565 | var n = transform.data();
1566 | _update_mesh_io(_extend({}, transform_data.steps[step].transform), mesh);
1567 | this_awe.scene_needs_rendering = 1;
1568 | transform_data.current_step = step;
1569 | // step callback
1570 | if (transform_data.step_callback && typeof(transform_data.step_callback) == 'function') {
1571 | transform_data.step_callback({
1572 | mesh: mesh,
1573 | step: step,
1574 | steps_total: steps_total
1575 | });
1576 | }
1577 | }
1578 | catch(e) {
1579 | this_awe.error_handler(e);
1580 | }
1581 | }
1582 | if (step && step == transform_data.steps.length-1) {
1583 | if (!isNaN(transform_data.repeat) && transform_data.repeat > 1) {
1584 | transform_data.repeat--;
1585 | var start_state = _extend({}, transform_data.start_state);
1586 | _update_mesh_io(start_state, mesh);
1587 | transform_data.advancement = 0;
1588 | delete(transform_data.current_step);
1589 | if (transform_data.end_callback && typeof(transform_data.end_callback) == 'function') {
1590 | transform_data.end_callback({
1591 | mesh: mesh
1592 | });
1593 | }
1594 | }
1595 | else if (!parseInt(transform_data.persist, 10)) {
1596 | var start_state = _extend({}, transform_data.start_state);
1597 | _update_mesh_io(start_state, mesh);
1598 | _finish_tween(mesh.id);
1599 | }
1600 | else {
1601 | _update_mesh_io(_extend({}, transform_data.end_state), mesh);
1602 | _finish_tween(mesh_id);
1603 | }
1604 | }
1605 | }
1606 | }
1607 |
1608 | this_awe.render();
1609 |
1610 | requestAnimationFrame(function() {
1611 | _tick();
1612 | var event = new CustomEvent('tick');
1613 | window.dispatchEvent(event);
1614 | });
1615 | }
1616 | catch(e) {
1617 | this_awe.error_handler(e);
1618 | }
1619 | }
1620 |
1621 | this_awe.util.extend = _extend;
1622 | } else {
1623 | throw "awe does not exist";
1624 | }
1625 | })(window);
1626 |
--------------------------------------------------------------------------------
/lib/awe-v8.js:
--------------------------------------------------------------------------------
1 | // BEGIN FILE: awe_v8.js
2 | /*
3 |
4 | The MIT License
5 |
6 | Copyright (c) 2013 Rob Manson, http://buildAR.com. All rights reserved.
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in
16 | all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | THE SOFTWARE.
25 |
26 |
27 | What is awe_v8.js?
28 | ------------------
29 |
30 | It's a simple datastore template that makes it easy to store, manage and
31 | extend collections of javascript object in a consistent way.
32 |
33 | Trust me, it's funkier than that sounds! 8)
34 |
35 |
36 | Why is it called awe_v8?
37 | -----------------------
38 |
39 | Each datastore by default is designed to support a standard set of "8 verbs".
40 |
41 | - search
42 | - list
43 | - add
44 | - view
45 | - edit
46 | - update
47 | - delete
48 | - report
49 |
50 | Through the magical process of simplification this translates in a subset of
51 | "6 implemented methods".
52 |
53 | - list
54 | - add
55 | - view
56 | - update
57 | - delete
58 | - report
59 |
60 | search and edit are simply UIs that drive one of these 6 methods.
61 |
62 | e.g. edit -> update or search -> list
63 |
64 |
65 | How are errors handled?
66 | -----------------------
67 |
68 | In simple js mode a method call either returns undefined for an error or
69 | either an object or an array of 0 or more objects.
70 |
71 |
72 | How do you use awe_v8?
73 | ----------------------
74 |
75 | // create a awe_v8 datastore
76 | var my_datastore = new awe_v8();
77 |
78 | // add one object to your datastore
79 | console.log("add an object (return new id)");
80 | my_datastore.add({
81 | id: "test",
82 | some_data: "blah"
83 | });
84 |
85 | // add multiple objects to your datastore in one go
86 | console.log("add several objects (return new ids)");
87 | my_datastore.add([
88 | {
89 | id: "test2",
90 | some_data: "blahdeblah"
91 | },
92 | {
93 | new_param: 99,
94 | id: "test3",
95 | some_data: "hrmok"
96 | },
97 | ]);
98 |
99 | // list all objects currently in your datastore
100 | console.log("list all objects (return all objects)");
101 | my_datastore.list();
102 |
103 | // list all objects in SOAPjr format (see separate documentation for SOAPjr API)
104 | console.log("list all objects (return all objects in SOAPjr)");
105 | my_datastore.list({}, { output_format:"soapjr" });
106 |
107 | // view one object
108 | console.log("view an object (return one object)");
109 | my_datastore.view("test"); // simple
110 | my_datastore.view({ id: "test" }); // clear
111 | my_datastore.view({ id: "test" }, { output_format:"js" }); // explicit
112 |
113 | // update one object
114 | console.log("update an object (return updated fields)");
115 | my_datastore.update({
116 | data: {
117 | new_param: 34,
118 | some_data: "new_data",
119 | },
120 | where: {
121 | id: "test",
122 | }
123 | });
124 |
125 | // search for objects that fuzzy match a pattern
126 | console.log("list fuzzy matches (return roughly matching objects)");
127 | my_datastore.list({ id: "test" }, { limit: 10 });
128 |
129 | // search for objects that exactly match a pattern
130 | console.log("list exact matches (return exactly matching objects)");
131 | my_datastore.list({ exact: { id: "test2" } });
132 |
133 | // delete one object
134 | console.log("delete an object (return deleted ids)");
135 | my_datastore.delete({ id: "test2" });
136 |
137 | // report metadata about this datastore
138 | console.log("report overview info (return a summary)");
139 | my_datastore.report();
140 |
141 | */
142 |
143 | // override this to customise how you want your awe_v8 template to behave
144 | var V8_CONFIG = {
145 | default_id_field: "id",
146 | default_output_format: "js",
147 | debug: false,
148 | };
149 |
150 | // below here is the template awe_v8 object implementation
151 | function awe_v8() {
152 | var ID_FIELD = "id";
153 | try {
154 | if (V8_CONFIG.default_id_field !== undefined) {
155 | ID_FIELD = V8_CONFIG.default_id_field;
156 | }
157 | }
158 | catch(e) { /* TODO */ }
159 | var OUTPUT_FORMAT = "js";
160 | try {
161 | if (V8_CONFIG.default_output_format !== undefined) {
162 | OUTPUT_FORMAT = V8_CONFIG.default_output_format;
163 | }
164 | }
165 | catch(e) { /* TODO */ }
166 | var awe_v8_object = new awe_v8_template();
167 | var _return = function(return_flag, return_values, errors, output_format) {
168 | if (output_format === undefined) {
169 | output_format = OUTPUT_FORMAT;
170 | }
171 | if (output_format == "soapjr") {
172 | var return_object = {
173 | HEAD: {},
174 | BODY: []
175 | };
176 | if (return_flag) {
177 | if (typeof(return_values) === "object" && return_values.length !== undefined) {
178 | return_object.BODY = return_values;
179 | }
180 | else {
181 | return_object.BODY = [return_values];
182 | }
183 | return_object.HEAD.result = 1;
184 | return return_object;
185 | }
186 | else {
187 | return_object.HEAD.result = 0;
188 | if (errors !== undefined && Object.keys(errors).length) {
189 | for (var i in errors) {
190 | if (Object.keys(errors[i]).length) {
191 |
192 | return_object.HEAD.errors[i] = errors[i];
193 | }
194 | }
195 | }
196 | return return_object;
197 | }
198 | }
199 | else {
200 | if (return_flag) {
201 | return return_values;
202 | }
203 | else {
204 | return undefined;
205 | }
206 | }
207 | };
208 | function _add(data, io, errors) {
209 | if (io == undefined) {
210 | throw "io undefined";
211 | }
212 | if (data[io[ID_FIELD]] !== undefined) {
213 | errors.BODY[ID_FIELD] = {
214 | code: 500,
215 | message: ID_FIELD+" already exists ("+io[ID_FIELD]+")",
216 | };
217 | throw ID_FIELD+" already exists ("+io[ID_FIELD]+")";
218 | }
219 | else {
220 | data[io[ID_FIELD]] = io;
221 | return io[ID_FIELD];
222 | }
223 | };
224 | function awe_v8_template() {
225 | var data = {};
226 | if (V8_CONFIG.debug !== undefined) {
227 | this.debug = V8_CONFIG.debug;
228 | }
229 | else {
230 | this.debug = false;
231 | }
232 | if (V8_CONFIG.debug_verbose !== undefined) {
233 | this.debug_verbose = V8_CONFIG.debug;
234 | }
235 | else {
236 | this.debug_verbose = 0;
237 | }
238 | this.get_data = function(){
239 | return data;
240 | }
241 |
242 | this.constructor.prototype.list = function(BODY, HEAD){
243 | if (BODY === undefined) { BODY = {}; }
244 | if (HEAD === undefined) { HEAD = {}; }
245 | var return_values = [];
246 | var return_flag = true;
247 | var errors = { HEAD:{}, BODY:{} };
248 | var output_format = undefined;
249 | if (HEAD !== undefined && HEAD.output_format !== undefined) {
250 | output_format = HEAD.output_format;
251 | }
252 | try {
253 | var page = 0;
254 | var limit = undefined;
255 | var order_by = ID_FIELD;
256 | var order_type = "alphabetic";
257 | var order_direction = "asc";
258 | var data_array = [];
259 | for (var i in data) {
260 | data_array.push(data[i]);
261 | }
262 | if (HEAD !== undefined) {
263 | if (HEAD.page !== undefined && typeof(HEAD.page) == "number") {
264 | page = HEAD.page-1;
265 | }
266 | if (HEAD.limit !== undefined && typeof(HEAD.limit) == "number") {
267 | limit = HEAD.limit;
268 | }
269 | if (HEAD.order_by !== undefined && typeof(HEAD.order_by) == "string") {
270 | order_by = HEAD.order_by;
271 | }
272 | if (HEAD.order_type !== undefined && HEAD.order_type == "numeric") {
273 | order_type = "numeric";
274 | }
275 | if (HEAD.order_direction !== undefined && HEAD.order_direction == "desc") {
276 | order_direction = "desc";
277 | }
278 | }
279 | var sort_function = function(A, B) {
280 | var a = undefined;
281 | var b = undefined;
282 | if (order_type == "alphabetic") {
283 | if (A[order_by] !== undefined && typeof(A[order_by]) == "string") {
284 | a = A[order_by].toLowerCase();
285 | }
286 | if (B[order_by] !== undefined && typeof(B[order_by]) == "string") {
287 | b = B[order_by].toLowerCase();
288 | }
289 | if (order_direction == "asc") {
290 | if (a == undefined && b !== undefined) {
291 | return 0;
292 | }
293 | else if (a == undefined) {
294 | return 1;
295 | }
296 | else if (b == undefined) {
297 | return -1
298 | }
299 | else {
300 | if (a < b) {
301 | return -1;
302 | }
303 | else if (a > b) {
304 | return 1;
305 | }
306 | else {
307 | return 0;
308 | }
309 | }
310 | }
311 | else {
312 | if (a == undefined && b !== undefined) {
313 | return 0;
314 | }
315 | else if (a == undefined) {
316 | return -1;
317 | }
318 | else if (b == undefined) {
319 | return 1
320 | }
321 | else {
322 | if (a > b) {
323 | return -1;
324 | }
325 | else if (a < b) {
326 | return 1;
327 | }
328 | else {
329 | return 0;
330 | }
331 | }
332 | }
333 | }
334 | else {
335 | if (A[order_by] !== undefined && typeof(A[order_by]) == "number") {
336 | a = A[order_by];
337 | }
338 | if (B[order_by] !== undefined && typeof(B[order_by]) == "number") {
339 | b = B[order_by];
340 | }
341 | if (order_direction == "asc") {
342 | if (a == undefined && b == undefined) {
343 | return 0
344 | }
345 | else if (a == undefined) {
346 | return 1;
347 | }
348 | else if (b == undefined) {
349 | return -1;
350 | }
351 | else {
352 | return a-b;
353 | }
354 | }
355 | else {
356 | if (a == undefined && b == undefined) {
357 | return 0
358 | }
359 | else if (a == undefined) {
360 | return 1;
361 | }
362 | else if (b == undefined) {
363 | return -1;
364 | }
365 | else {
366 | return b-a;
367 | }
368 | }
369 | }
370 | };
371 | for (var i in data_array) {
372 | if (BODY == undefined || BODY.length == 0) {
373 | return_values.push(data_array[i]);
374 | }
375 | else if (BODY !== undefined && BODY.exact !== undefined) {
376 | var a = undefined;
377 | var b = undefined;
378 | var match = 0;
379 | for (var m in BODY.exact) {
380 | a = data_array[i][m];
381 | b = BODY.exact[m];
382 | if (a == b) {
383 | match = 1;
384 | }
385 | }
386 | if (match) {
387 | return_values.push(data_array[i]);
388 | }
389 | }
390 | else {
391 | var match = 1;
392 | for (var m in BODY) {
393 | if (data_array[i][m] !== undefined && typeof(data_array[i][m]) == "string") {
394 | a = data_array[i][m].toLowerCase();
395 | }
396 | if (BODY[m] !== undefined && typeof(BODY[m]) == "string") {
397 | b = BODY[m].toLowerCase();
398 | }
399 | if (a !== undefined && b !== undefined) {
400 | var r = a.match(b);
401 | if (r == undefined) {
402 | match = 0;
403 | }
404 | }
405 | else {
406 | match = 0;
407 | }
408 | }
409 | if (match) {
410 | return_values.push(data_array[i]);
411 | }
412 | }
413 | }
414 | return_values = return_values.sort(sort_function);
415 | if (limit !== undefined) {
416 | var start = limit*page;
417 | var end = limit*(page+1);
418 | return_values = return_values.slice(start,end);
419 | }
420 | }
421 | catch(e) {
422 | this.error_handler(e);
423 | return_flag = false;
424 | }
425 | /* NOTE: commented out to make it more forgiving - maybe move to config
426 | if (!(return_values.length > 0)) {
427 | return_flag = false;
428 | errors.BODY.io = {
429 | code: 500,
430 | message: "object does not exist",
431 | };
432 | }
433 | */
434 | return _return(return_flag, return_values, errors, output_format);
435 | };
436 |
437 | this.constructor.prototype.add = function(BODY, HEAD) {
438 | if (BODY == undefined) { BODY = {}; }
439 | if (HEAD == undefined) { HEAD = {}; }
440 | var return_values = [];
441 | var return_flag = true;
442 | var errors = { HEAD:{}, BODY:{} };
443 | var output_format = undefined;
444 | if (HEAD !== undefined) {
445 | if (HEAD.output_format !== undefined) {
446 | output_format = HEAD.output_format;
447 | }
448 | if (HEAD.replace_all !== undefined && HEAD.replace_all) {
449 | data = {};
450 | }
451 | }
452 | try {
453 | /* NOTE: commented out to make it more forgiving - maybe move to config
454 | if (BODY == undefined) {
455 | errors.BODY = {
456 | code: 500,
457 | message: "BODY object invalid (undefined)",
458 | };
459 | throw "BODY object invalid (undefined)";
460 | }
461 | */
462 | if (typeof(BODY) == "string") {
463 | errors.BODY = {
464 | code: 500,
465 | message: "BODY object invalid (string)",
466 | };
467 | throw "BODY object invalid (string)";
468 | }
469 | if (typeof(BODY) == "number") {
470 | errors.BODY = {
471 | code: 500,
472 | message: "BODY object invalid (number)",
473 | };
474 | throw "BODY object invalid (number)";
475 | }
476 | if ((Array.isArray && Array.isArray(BODY)) || (BODY[ID_FIELD] == undefined && BODY.length > 0)) {
477 | for (var i in BODY) {
478 | var a = _add(data, BODY[i], errors);
479 | if (a) {
480 | return_values.push(a); // if this fails will it still push something? yes, undefined
481 | }
482 | else {
483 | throw "add failed";
484 | }
485 | }
486 | }
487 | else {
488 | var a = _add(data, BODY, errors)
489 | if (a) {
490 | return_values.push(a); // if this fails will it still push something? yes, undefined
491 | }
492 | else {
493 | throw "add failed";
494 | }
495 | }
496 | }
497 | catch(e) {
498 | this.error_handler(e);
499 | return_flag = false;
500 | }
501 | if (return_values.length == 0) {
502 | return _return(return_flag, {}, errors, output_format);
503 | }
504 | else if (return_values.length == 1) {
505 | return _return(return_flag, { id: return_values[0] }, errors, output_format);
506 | }
507 | else {
508 | return _return(return_flag, { id: return_values }, errors, output_format);
509 | }
510 | };
511 |
512 | this.constructor.prototype.view = function(BODY, HEAD) {
513 | if (BODY == undefined) { BODY = {}; }
514 | if (HEAD == undefined) { HEAD = {}; }
515 | var return_value = undefined;
516 | var return_flag = true;
517 | var errors = { HEAD:{}, BODY:{} };
518 | var output_format = undefined;
519 | if (HEAD !== undefined && HEAD.output_format !== undefined) {
520 | output_format = HEAD.output_format;
521 | }
522 | try {
523 | if (typeof(BODY) == "string" && data[BODY] !== undefined) {
524 | return data[BODY].hasOwnProperty('value') ? data[BODY].value : data[BODY];
525 | }
526 | else if (BODY !== undefined && BODY.id !== undefined && data[BODY.id]) {
527 | return_value = data[BODY.id].hasOwnProperty('value') ? data[BODY.id].value : data[BODY.id];
528 | }
529 | else {
530 | errors.BODY.id = {
531 | code: 500,
532 | message: BODY.id+" does not exist",
533 | };
534 | throw BODY.id+" does not exist";
535 | }
536 | }
537 | catch(e) {
538 | this.error_handler(e);
539 | return_flag = false;
540 | }
541 | return _return(return_flag, return_value, errors);
542 | };
543 |
544 | this.constructor.prototype.update = function(BODY, HEAD) {
545 | if (BODY == undefined) { BODY = {}; }
546 | if (HEAD == undefined) { HEAD = {}; }
547 | var return_values = HEAD.fields_updated || [];
548 | var return_flag = true;
549 | var errors = { HEAD:{}, BODY:{} };
550 | var output_format = undefined;
551 | if (HEAD !== undefined && HEAD.output_format !== undefined) {
552 | output_format = HEAD.output_format;
553 | }
554 | try {
555 | if (BODY == undefined) {
556 | errors.BODY = {
557 | code: 500,
558 | message: "missing BODY object",
559 | };
560 | throw "missing BODY object";
561 | }
562 | if (BODY.data == undefined) {
563 | errors.BODY.data = {
564 | code: 500,
565 | message: "missing 'data' clause in BODY object",
566 | };
567 | throw "missing 'data' clause in BODY object";
568 | }
569 | if (BODY.where == undefined) {
570 | errors.BODY.where = {
571 | code: 500,
572 | message: "missing 'where' clause in BODY object",
573 | };
574 | throw "missing 'where' clause in BODY object";
575 | }
576 | if (BODY.where[ID_FIELD] !== undefined) {
577 | if (HEAD.strict) {
578 | if (data[BODY.where[ID_FIELD]] == undefined) {
579 | errors.BODY[BODY.where[ID_FIELD]] = {
580 | code: 500,
581 | message: ID_FIELD+" doesn't exist ("+BODY.where[ID_FIELD]+")",
582 | };
583 | throw ID_FIELD+" doesn't exist ("+BODY.where[ID_FIELD]+")";
584 | }
585 | }
586 | for (var i in BODY.data) {
587 | if (i != ID_FIELD) {
588 | if (!data[BODY.where[ID_FIELD]]) {
589 | data[BODY.where[ID_FIELD]] = {};
590 | data[BODY.where[ID_FIELD]][ID_FIELD] = BODY.where[ID_FIELD];
591 | }
592 | data[BODY.where[ID_FIELD]][i] = BODY.data[i];
593 | return_values.push(i);
594 | }
595 | }
596 | }
597 | else {
598 | errors.BODY.where = {
599 | code: 500,
600 | message: "where."+ID_FIELD+" required",
601 | };
602 | throw "where."+ID_FIELD+" required";
603 | }
604 | }
605 | catch(e) {
606 | this.error_handler(e);
607 | return_flag = false;
608 | }
609 | return _return(return_flag, { fields_updated: return_values }, errors, output_format);
610 | };
611 |
612 | this.constructor.prototype.delete = function(BODY, HEAD) {
613 | if (BODY == undefined) { BODY = {}; }
614 | if (HEAD == undefined) { HEAD = {}; }
615 | var return_values = [];
616 | var return_flag = true;
617 | var errors = { HEAD:{}, BODY:{} };
618 | var output_format = undefined;
619 | if (HEAD !== undefined && HEAD.output_format !== undefined) {
620 | output_format = HEAD.output_format;
621 | }
622 | try {
623 | if (BODY !== undefined && typeof(BODY.id) == "string" || typeof(BODY.id) == "number") {
624 | if (BODY !== undefined && data[BODY.id] !== undefined) {
625 | delete(data[BODY.id]);
626 | return_values.push(BODY.id);
627 | }
628 | else {
629 | errors.BODY.id = {
630 | code: 500,
631 | message: BODY.id+" does not exist",
632 | };
633 | throw BODY.id+" does not exist";
634 | }
635 | }
636 | else {
637 | for (var id in BODY.id) {
638 | if (BODY.id[id] !== undefined && data[BODY.id[id]] !== undefined) {
639 | delete(data[BODY.id[id]]);
640 | return_values.push(BODY.id[id]);
641 | }
642 | else {
643 | errors.BODY[BODY.id[id]] = {
644 | code: 500,
645 | message: BODY.id[id]+" does not exist"
646 | };
647 | throw BODY.id[id]+" does not exist";
648 | }
649 | }
650 | }
651 | }
652 | catch(e) {
653 | this.error_handler(e);
654 | return_flag = false;
655 | }
656 | if (return_values.length == 0) {
657 | return _return(return_flag, {}, errors, output_format);
658 | }
659 | else if (return_values.length == 1) {
660 | return _return(return_flag, { id: return_values[0] }, errors, output_format);
661 | }
662 | else {
663 | return _return(return_flag, { id: return_values }, errors, output_format);
664 | }
665 | };
666 |
667 | this.constructor.prototype.report = function(BODY, HEAD) {
668 | if (BODY == undefined) { BODY = {}; }
669 | if (HEAD == undefined) { HEAD = {}; }
670 | var return_value = {
671 | count: 0,
672 | fields: {},
673 | };
674 | var return_flag = true;
675 | var errors = { HEAD:{}, BODY:{} };
676 | var output_format = undefined;
677 | if (HEAD !== undefined && HEAD.output_format !== undefined) {
678 | output_format = HEAD.output_format;
679 | }
680 | try {
681 | if (data == undefined) {
682 | errors.HEAD.data = {
683 | code: 500,
684 | message: "internal data invalid"
685 | };
686 | throw "internal data invalid";
687 | }
688 | for (var i in data) {
689 | for (var k in data[i]) {
690 | if (return_value.fields[k] == undefined) {
691 | return_value.fields[k] = 1;
692 | }
693 | else {
694 | return_value.fields[k]++;
695 | }
696 | }
697 | return_value.count++;
698 | }
699 | }
700 | catch(e) {
701 | this.error_handler(e);
702 | return_flag = false;
703 | }
704 | return _return(return_flag, return_value, errors, output_format);
705 | };
706 |
707 |
708 | this.constructor.prototype.error_handler = function(e, debug) {
709 | if (debug || this.debug) {
710 | if (e.code && e.message) {
711 | console.log("ERROR: "+e.code);
712 | console.log(e.message);
713 | }
714 | else {
715 | console.log("ERROR");
716 | console.log(e);
717 | }
718 | if (this.debug_verbose > 0) {
719 | console.log("CALLER");
720 | console.log(arguments.callee.caller);
721 | }
722 | if (this.debug_verbose > 2) {
723 | console.log(arguments.callee.caller.toString());
724 | }
725 | }
726 | };
727 |
728 | this.constructor.prototype.toString = function() {
729 | return 'awe_v8_object'
730 | };
731 |
732 | return this;
733 | };
734 | return awe_v8_object;
735 | }
736 | // END FILE: awe_v8.js
737 |
--------------------------------------------------------------------------------
/lib/awe.geo_ar.js:
--------------------------------------------------------------------------------
1 | (function(awe) {
2 | var container = document.getElementById('container');
3 | var background_video;
4 |
5 | function resize_video() {
6 | if (background_video) {
7 | var video = awe.video_stream().video_element;
8 | var w = video.videoWidth,
9 | h = video.videoHeight;
10 | var cnt_h = container.clientHeight,
11 | cnt_w = container.clientWidth,
12 | wrapper_aspect_ratio = cnt_w / cnt_h,
13 | video_aspect_ratio = w / h
14 |
15 | // stretch the video to cover the background entirely and center it
16 | if (wrapper_aspect_ratio > video_aspect_ratio) {
17 | background_video.setAttribute('width', cnt_w);
18 | background_video.setAttribute('height', cnt_w / video_aspect_ratio);
19 | background_video.style.marginLeft = (-cnt_w/2)+'px';
20 | }
21 | else {
22 | background_video.setAttribute('height', cnt_h);
23 | background_video.setAttribute('width', cnt_h * video_aspect_ratio);
24 | background_video.style.marginLeft = (-cnt_h * video_aspect_ratio / 2)+'px';
25 | }
26 | }
27 | aspectRatio = window.innerWidth / window.innerHeight;
28 | awe.pov().aspect = aspectRatio;
29 | awe.pov().updateProjectionMatrix();
30 | awe.renderer().setSize(window.innerWidth, window.innerHeight);
31 | awe.scene_needs_rendering = 1;
32 | }
33 |
34 | awe.plugins.add([{
35 | id: 'geo_ar',
36 | auto_register: true,
37 | register: function(plugin_data){
38 | // add video stream
39 | awe.setup_stream();
40 | awe.events.add([
41 | {
42 | id: 'video_stream',
43 | device_types: {
44 | android: 1,
45 | pc: 1
46 | },
47 | register: function(handler) {
48 | window.addEventListener('gum_ready', handler, false);
49 | },
50 | unregister: function(handler){
51 | window.removeEventListener('gum_ready', handler, false);
52 | },
53 | handler: function(e) {
54 | var video = awe.video_stream();
55 | background_video = document.createElement('video');
56 | background_video.setAttribute('width', window.innerWidth);
57 | background_video.setAttribute('height', window.innerHeight);
58 | background_video.setAttribute('autoplay', 'true');
59 | background_video.style.position = 'absolute';
60 | background_video.style.left = '50%';
61 | background_video.style.marginLeft = (-window.innerWidth/2)+'px';
62 | background_video.style.top = '0px';
63 | background_video.style.zIndex = '-1';
64 | container.appendChild(background_video);
65 | awe.util.connect_stream_to_src(awe.video_stream().stream, background_video);
66 | background_video.addEventListener('play',resize_video, false);
67 | setTimeout(function() {
68 | resize_video();
69 | }, 1000);
70 | }
71 | }
72 | ]);
73 |
74 | // toDeg() is a Number object extension courtesy http://www.movable-type.co.uk/scripts/latlong.html
75 | if (typeof Number.prototype.toDeg == 'undefined') {
76 | Number.prototype.toDeg = function() {
77 | return this * 180 / Math.PI;
78 | };
79 | }
80 | if (typeof Number.prototype.toRad == 'undefined') {
81 | Number.prototype.toRad = function() {
82 | return this * Math.PI / 180;
83 | };
84 | }
85 |
86 | awe.events.add({
87 | id: 'deviceorientation',
88 | device_types: {
89 | pc: 1,
90 | android: 1
91 | },
92 | register: function(handler) {
93 | window.addEventListener('deviceorientation', handler, false);
94 | },
95 | unregister: function(handler){
96 | window.removeEventListener('deviceorientation', handler, false);
97 | },
98 | handler: function(e) {
99 | var alpha = e.alpha,
100 | beta = e.beta,
101 | gamma = e.gamma,
102 | x = 0,
103 | y = 0,
104 | z = 0;
105 |
106 | if ((beta > 30 && beta < 150) || // device is generally upright (portrait)
107 | (beta < -30 && beta > -150)) { // device is generally upright but inverted (portrait)
108 | x = beta+90;
109 | y = (alpha+gamma)%360;
110 | z = 180;
111 | } else { // device is generally not-upright (landscape)
112 | if (gamma < 0 && gamma > -90) { // rotation below horizon
113 | x = -gamma-90;
114 | } else { // rotation above horizon
115 | x = 90-gamma;
116 | }
117 | y = (alpha+gamma+180)%360;
118 | }
119 |
120 | awe.povs.update({
121 | data: {
122 | euler_order: 'YZX',
123 | rotation: {
124 | x: x,
125 | y: y,
126 | z: z,
127 | }
128 | },
129 | where: {
130 | id: 'default'
131 | }
132 | });
133 | }
134 | });
135 |
136 | awe.events.add([
137 | {
138 | id: 'resize_screen',
139 | device_types: {
140 | pc: 1,
141 | android: 1
142 | },
143 | register: function(handler) {
144 | window.addEventListener('resize', handler, false);
145 | },
146 | unregister: function(handler){
147 | window.removeEventListener('resize', handler, false);
148 | },
149 | handler: function(e) {
150 | resize_video();
151 | }
152 | }
153 | ]);
154 | },
155 | unregister: function(plugin_data){
156 | awe.events.delete('resize_screen');
157 | awe.events.delete('deviceorientation');
158 | awe.events.delete('video_stream');
159 | }
160 | }]);
161 | })(window.awe);
162 |
--------------------------------------------------------------------------------
/lib/awe.marker_ar.js:
--------------------------------------------------------------------------------
1 | (function(awe) {
2 | var threshold = 98;
3 | var width = 640;
4 | var height = 480;
5 | var video = document.createElement('video');
6 | var last_time = 0;
7 | var tracking_enabled = false, background_video, canvas, ctx, video_stream, detector, raster, param, resultMat, tmp = new Float32Array(16), pov_projection_matrix, pov_projection_matrix2;
8 |
9 | function resize_video() { // jsartoolkit specific resize function
10 | if (awe.device_type() == 'android' && navigator.userAgent.match(/firefox/i)) {
11 | // NOTE: This is borken - not quite sure what firefox is doing here 8/
12 | var aspect_ratio = window.innerWidth / window.innerHeight,
13 | h, w;
14 | if (window.innerHeight > window.innerWidth) {
15 | w = window.innerWidth;
16 | h = window.innerHeight / aspect_ratio;
17 | }
18 | else {
19 | h = window.innerHeight;
20 | w = window.innerWidth / aspect_ratio;
21 | }
22 | if (background_video) {
23 | background_video.setAttribute('height', h);
24 | background_video.setAttribute('width', w);
25 | background_video.style.left = '0px';
26 | }
27 | awe.renderer().setSize(w, h);
28 | awe.renderer().domElement.style.left = '0px';
29 | awe.pov().aspect = aspect_ratio;
30 | }
31 | else {
32 | var aspect_ratio = width / height,
33 | h, w;
34 | if (window.innerHeight > window.innerWidth) {
35 | h = window.innerHeight;
36 | w = h * aspect_ratio;
37 | }
38 | else {
39 | w = window.innerWidth;
40 | h = w / aspect_ratio;
41 | }
42 | if (background_video) {
43 | background_video.setAttribute('height', h);
44 | background_video.setAttribute('width', w);
45 | background_video.style.marginLeft = -w/2 + 'px';
46 | background_video.style.left = '50%';
47 | }
48 | awe.renderer().setSize(w, h);
49 | awe.renderer().domElement.style.left = '50%';
50 | awe.renderer().domElement.style.marginLeft = -w/2 + 'px';
51 | awe.pov().aspect = aspect_ratio;
52 | }
53 | awe.pov().updateProjectionMatrix();
54 | if (pov_projection_matrix2) {
55 | awe.pov().projectionMatrix.fromArray(pov_projection_matrix2);
56 | }
57 | awe.scene_needs_rendering = 1;
58 | }
59 |
60 | THREE.Matrix4.prototype.setFromArray = function(m){
61 | return this.set(
62 | m[0],m[4],m[8],m[12],
63 | m[1],m[5],m[9],m[13],
64 | m[2],m[6],m[10],m[14],
65 | m[3],m[7],m[11],m[15]
66 | );
67 | };
68 |
69 | function copy_matrix(src, dst){
70 | dst[0] = src.m00;
71 | dst[1] = -src.m10;
72 | dst[2] = src.m20;
73 | dst[3] = 0;
74 | dst[4] = src.m02;
75 | dst[5] = -src.m12;
76 | dst[6] = src.m22;
77 | dst[7] = 0;
78 | dst[8] = -src.m01;
79 | dst[9] = src.m11;
80 | dst[10] = -src.m21;
81 | dst[11] = 0;
82 | dst[12] = src.m03;
83 | dst[13] = -src.m13;
84 | dst[14] = src.m23;
85 | dst[15] = 1;
86 | }
87 |
88 | function add_ar_events(){
89 | awe.events.add([{
90 | id: 'video_stream',
91 | device_types: {
92 | android: 1,
93 | pc: 1
94 | },
95 | register: function(handler) {
96 | window.addEventListener('gum_ready', handler, false);
97 | },
98 | unregister: function(handler){
99 | window.removeEventListener('gum_ready', handler, false);
100 | },
101 | handler: function(e) {
102 | canvas = document.createElement('canvas');
103 | canvas.id = "ar_canvas";
104 | canvas.width = width/2;
105 | canvas.height = height/2;
106 | canvas.style.display = "none";
107 | document.body.appendChild(canvas);
108 | ctx = canvas.getContext('2d');
109 | raster = new NyARRgbRaster_Canvas2D(canvas);
110 | param = new FLARParam(width/2,height/2);
111 | resultMat = new NyARTransMatResult();
112 | detector = new FLARMultiIdMarkerDetector(param,120);
113 | detector.setContinueMode(true);
114 | param.copyCameraMatrix(tmp,10,10000);
115 | pov_projection_matrix = awe.pov().projectionMatrix.toArray();
116 | awe.pov().projectionMatrix.setFromArray(tmp);
117 | pov_projection_matrix2 = awe.pov().projectionMatrix.toArray();
118 | video_stream = awe.video_stream();
119 | video = video_stream.video_element;
120 | video.width = width;
121 | video.height = height;
122 | background_video = document.createElement('video');
123 | background_video.setAttribute('width', window.innerWidth);
124 | background_video.setAttribute('height', window.innerHeight);
125 | background_video.setAttribute('autoplay', 'true');
126 | background_video.style.position = 'absolute';
127 | background_video.style.left = '0px';
128 | background_video.style.top = '0px';
129 | background_video.style.zIndex = '-1';
130 | container.appendChild(background_video);
131 | awe.util.connect_stream_to_src(video_stream.stream, background_video);
132 | background_video.addEventListener('play', function(){
133 | resize_video();
134 | tracking_enabled = true;
135 | }, false);
136 | }
137 | },
138 | {
139 | id: 'ar_tracking',
140 | device_types: {
141 | pc: 1,
142 | android: 1
143 | },
144 | register: function(handler) {
145 | window.addEventListener('tick', handler, false);
146 | awe.scene_needs_rendering = 1;
147 | },
148 | unregister: function(handler){
149 | window.removeEventListener('tick', handler, false);
150 | },
151 | handler: function(event) {
152 | if (!tracking_enabled) {
153 | return;
154 | }
155 | var video = video_stream.video_element;
156 | if (!video) {
157 | return;
158 | }
159 | if (video.ended) { video.play(); }
160 | if (video.paused) { return; }
161 | if (window.paused) { return; }
162 | if (video.currentTime == last_time) { return; }
163 | last_time = video.currentTime;
164 | try {
165 | ctx.drawImage(video, 0, 0, width/2, height/2);
166 | } catch(e) { /* TODO */ }
167 | canvas.changed = true;
168 | var detected_count = detector.detectMarkerLite(raster, threshold);
169 | var event_data = {};
170 | for (var i=0; i=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=b(e,i,4);var o=!k(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=x(r,e);for(var u=O(t),i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t,r){return function(e,u,i){var o=0,a=O(e);if("number"==typeof i)n>0?o=i>=0?i:Math.max(i+a,o):a=i>=0?Math.min(i+1,a):i+a+1;else if(r&&i&&a)return i=r(e,u),e[i]===u?i:-1;if(u!==u)return i=t(l.call(e,o,a),m.isNaN),i>=0?i+o:-1;for(i=n>0?o:a-1;i>=0&&a>i;i+=n)if(e[i]===u)return i;return-1}}function e(n,t){var r=I.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||a,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=I[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var u=this,i=u._,o=Array.prototype,a=Object.prototype,c=Function.prototype,f=o.push,l=o.slice,s=a.toString,p=a.hasOwnProperty,h=Array.isArray,v=Object.keys,g=c.bind,y=Object.create,d=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):u._=m,m.VERSION="1.8.3";var b=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},x=function(n,t,r){return null==n?m.identity:m.isFunction(n)?b(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return x(n,t,1/0)};var _=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var f=o[c];t&&r[f]!==void 0||(r[f]=i[f])}return r}},j=function(n){if(!m.isObject(n))return{};if(y)return y(n);d.prototype=n;var t=new d;return d.prototype=null,t},w=function(n){return function(t){return null==t?void 0:t[n]}},A=Math.pow(2,53)-1,O=w("length"),k=function(n){var t=O(n);return"number"==typeof t&&t>=0&&A>=t};m.each=m.forEach=function(n,t,r){t=b(t,r);var e,u;if(k(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=k(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=x(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(x(t)),r)},m.every=m.all=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r,e){return k(n)||(n=m.values(n)),("number"!=typeof r||e)&&(r=0),m.indexOf(n,t,r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=k(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(k(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=x(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=x(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=F(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=F(function(n,t,r){n[r]=t}),m.countBy=F(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):k(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:k(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=x(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var S=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=O(n);a>o;o++){var c=n[o];if(k(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=S(c,t,r));var f=0,l=c.length;for(u.length+=l;l>f;)u[i++]=c[f++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return S(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=x(r,e));for(var u=[],i=[],o=0,a=O(n);a>o;o++){var c=n[o],f=r?r(c,o,n):c;t?(o&&i===f||u.push(c),i=f):r?m.contains(i,f)||(i.push(f),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(S(arguments,!0,!0))},m.intersection=function(n){for(var t=[],r=arguments.length,e=0,u=O(n);u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=S(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,O).length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=O(n);u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=x(r,e,1);for(var u=r(t),i=0,o=O(n);o>i;){var a=Math.floor((i+o)/2);r(n[a])i;i++,n+=r)u[i]=n;return u};var E=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=j(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(g&&n.bind===g)return g.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return E(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var f=m.now();a||r.leading!==!1||(a=f);var l=t-(f-a);return e=this,u=arguments,0>=l||l>t?(o&&(clearTimeout(o),o=null),a=f,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,l)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var f=m.now()-o;t>f&&f>=0?e=setTimeout(c,t-f):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var f=r&&!e;return e||(e=setTimeout(c,t)),f&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),I=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(v)return v(n);var t=[];for(var r in n)m.has(n,r)&&t.push(r);return M&&e(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var r in n)t.push(r);return M&&e(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=_(m.allKeys),m.extendOwn=m.assign=_(m.keys),m.findKey=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=b(t,r)):(u=S(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var f=u[a],l=o[f];e(l,f,o)&&(i[f]=l)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(S(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=_(m.allKeys,!0),m.create=function(n,t){var r=j(n);return t&&m.extendOwn(r,t),r},m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var N=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=s.call(n);if(u!==s.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!N(n[c],t[c],r,e))return!1}else{var f,l=m.keys(n);if(c=l.length,m.keys(t).length!==c)return!1;for(;c--;)if(f=l[c],!m.has(t,f)||!N(n[f],t[f],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return N(n,t)},m.isEmpty=function(n){return null==n?!0:k(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=h||function(n){return"[object Array]"===s.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return s.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===s.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&p.call(n,t)},m.noConflict=function(){return u._=i,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=w,m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=b(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var B={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},T=m.invert(B),R=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=R(B),m.unescape=R(T),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var q=0;m.uniqueId=function(n){var t=++q+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var K=/(.)^/,z={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\u2028|\u2029/g,L=function(n){return"\\"+z[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||K).source,(t.interpolate||K).source,(t.evaluate||K).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(D,L),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},f=t.variable||"obj";return c.source="function("+f+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var P=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return f.apply(n,arguments),P(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=o[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],P(this,r)}}),m.each(["concat","join","slice"],function(n){var t=o[n];m.prototype[n]=function(){return P(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this);
6 | //# sourceMappingURL=underscore-min.map
--------------------------------------------------------------------------------