janusweb 1.5.42 → 1.5.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG +23 -0
  2. package/css/janusweb.css +7 -2
  3. package/media/assets/webui/apps/buttons/buttons.js +17 -3
  4. package/media/assets/webui/apps/comms/comms.css +1 -1
  5. package/media/assets/webui/apps/comms/comms.js +1 -1
  6. package/media/assets/webui/apps/comms/voip.css +12 -3
  7. package/media/assets/webui/apps/comms/voip.js +16 -6
  8. package/media/assets/webui/apps/editor/editor.css +1 -0
  9. package/media/assets/webui/apps/editor/editor.js +19 -12
  10. package/media/assets/webui/apps/locomotion/teleporter.js +11 -4
  11. package/media/assets/webui/apps/xrmenu/images/audio-settings.png +0 -0
  12. package/media/assets/webui/apps/xrmenu/xrmenu-assets.json +2 -1
  13. package/media/assets/webui/apps/xrmenu/xrmenu.js +142 -40
  14. package/media/assets/webui/themes/default.css +42 -0
  15. package/package.json +2 -2
  16. package/scripts/client.js +12 -1
  17. package/scripts/config.js +1 -1
  18. package/scripts/elements/outliner.js +7 -1
  19. package/scripts/external/JanusClientConnection.js +14 -8
  20. package/scripts/image.js +1 -1
  21. package/scripts/janusbase.js +49 -27
  22. package/scripts/janusghost.js +14 -10
  23. package/scripts/januslight.js +46 -4
  24. package/scripts/janusparticle.js +116 -13
  25. package/scripts/janusplayer.js +97 -22
  26. package/scripts/janusweb.js +18 -5
  27. package/scripts/janusxrplayer.js +117 -17
  28. package/scripts/object.js +75 -31
  29. package/scripts/parts.js +1 -1
  30. package/scripts/portal.js +21 -10
  31. package/scripts/remoteplayer.js +3 -2
  32. package/scripts/room.js +159 -49
  33. package/scripts/text.js +7 -4
  34. package/scripts/websurface.js +3 -3
package/scripts/room.js CHANGED
@@ -5,6 +5,18 @@ elation.require([
5
5
  'janusweb.sound', 'janusweb.januslight', 'janusweb.janusparticle', 'janusweb.janusghost',
6
6
  'janusweb.translators.bookmarks', 'janusweb.translators.reddit', 'janusweb.translators.error', 'janusweb.translators.blank', 'janusweb.translators.default', 'janusweb.translators.dat', 'janusweb.translators.janusvfs'
7
7
  ], function() {
8
+ let roomTranslators = false;
9
+ function initRoomTranslators() {
10
+ roomTranslators = {
11
+ '^janus-vfs:': elation.janusweb.translators.janusvfs({janus: janus}),
12
+ '^about:blank$': elation.janusweb.translators.blank({janus: janus}),
13
+ '^bookmarks$': elation.janusweb.translators.bookmarks({janus: janus}),
14
+ '^dat:': elation.janusweb.translators.dat({janus: janus}),
15
+ '^https?:\/\/(www\.)?reddit.com': elation.janusweb.translators.reddit({janus: janus}),
16
+ '^error$': elation.janusweb.translators.error({janus: janus}),
17
+ '^default$': elation.janusweb.translators.default({janus: janus})
18
+ };
19
+ }
8
20
  elation.component.add('engine.things.janusroom', function() {
9
21
  this.postinit = function() {
10
22
  elation.engine.things.janusroom.extendclass.postinit.call(this);
@@ -27,6 +39,7 @@ elation.require([
27
39
  'baseurl': { type: 'string', default: false },
28
40
  'source': { type: 'string' },
29
41
  'skybox': { type: 'boolean', default: true, set: this.toggleSkybox },
42
+ 'skybox_intensity': { type: 'float', set: this.setSkybox, default: 1.0 },
30
43
  'skybox_equi': { type: 'string', set: this.setSkybox },
31
44
  'skybox_left_id': { type: 'string', set: this.setSkybox },
32
45
  'skybox_right_id': { type: 'string', set: this.setSkybox },
@@ -68,7 +81,7 @@ elation.require([
68
81
  'server': { type: 'string' },
69
82
  'port': { type: 'int' },
70
83
  'rate': { type: 'int', default: 200 },
71
- 'voip': { type: 'string', default: 'janus' },
84
+ 'voip': { type: 'string', default: 'none' },
72
85
  'voipid': { type: 'string' },
73
86
  'voiprange': { type: 'float', default: 1 },
74
87
  'voipserver': { type: 'string', default: 'voip.janusxr.org' },
@@ -79,17 +92,13 @@ elation.require([
79
92
  'requires': { type: 'string' },
80
93
  'onload': { type: 'string' },
81
94
  'sync': { type: 'boolean', default: false },
82
- 'pointerlock': { type: 'boolean', default: true },
95
+ 'pointerlock': { type: 'boolean', default: true, set: this.updatePointerLock },
83
96
  });
84
- this.translators = {
85
- '^janus-vfs:': elation.janusweb.translators.janusvfs({janus: this.janus}),
86
- '^about:blank$': elation.janusweb.translators.blank({janus: this.janus}),
87
- '^bookmarks$': elation.janusweb.translators.bookmarks({janus: this.janus}),
88
- '^dat:': elation.janusweb.translators.dat({janus: this.janus}),
89
- '^https?:\/\/(www\.)?reddit.com': elation.janusweb.translators.reddit({janus: this.janus}),
90
- '^error$': elation.janusweb.translators.error({janus: this.janus}),
91
- '^default$': elation.janusweb.translators.default({janus: this.janus})
92
- };
97
+
98
+ if (!roomTranslators) {
99
+ initRoomTranslators();
100
+ }
101
+
93
102
  this.spawnpoint = new THREE.Object3D();
94
103
  this.roomsrc = '';
95
104
  this.changes = {};
@@ -113,6 +122,7 @@ elation.require([
113
122
  this.customElements = {};
114
123
  this.unknownElements = {};
115
124
  this.eventlistenerproxies = {};
125
+ this.pendingScriptMap = {};
116
126
 
117
127
  // FIXME - binding functions to this instance so we can unbind events later. Should be done at a lower level
118
128
  this.onRoomEdit = elation.bind(this, this.onRoomEdit);
@@ -138,6 +148,7 @@ elation.require([
138
148
  let hashidx = this.url.indexOf('#');
139
149
  if (hashidx != -1) {
140
150
  this.urlhash = this.url.substr(hashidx+1);
151
+ this.setHash(this.urlhash)
141
152
  this.url = this.url.substr(0, hashidx);
142
153
  }
143
154
  this.roomid = md5(this.url);
@@ -148,6 +159,8 @@ elation.require([
148
159
  this.loadFromSource(this.source);
149
160
  }
150
161
  elation.events.add(this, 'thing_remove', elation.bind(this, this.onThingRemove));
162
+
163
+ document.addEventListener('visibilitychange', ev => this.handleVisibilityChange());
151
164
  }
152
165
  this.createChildren = function() {
153
166
  this.collidable = false;
@@ -208,13 +221,13 @@ elation.require([
208
221
  }
209
222
  }
210
223
  this.setActive = function() {
224
+ this.active = true;
211
225
  this.setSkybox();
212
226
  this.setFog();
213
227
  this.updateBloom();
214
228
  this.updateToneMapping();
215
229
  this.setNearFar();
216
230
  this.setPlayerPosition();
217
- this.active = true;
218
231
  elation.events.fire({element: this, type: 'room_active', data: this});
219
232
  }
220
233
  this.setPlayerPosition = function(pos, orientation) {
@@ -274,7 +287,7 @@ elation.require([
274
287
  let obj = this.getObjectById(this.urlhash);
275
288
  if (obj) {
276
289
  obj.localToWorld(spawnpoint.position.set(0,0,0));
277
- spawnpoint.orientation.setFromRotationMatrix(obj.objects['3d'].matrixWorld);
290
+ spawnpoint.orientation.setFromRotationMatrix(obj.objects['3d'].matrixWorld.lookAt(spawnpoint.position, obj.localToWorld(V(0,0,1)), obj.localToWorld(V(0,1,0).sub(spawnpoint.position))));
278
291
  }
279
292
  }
280
293
  return spawnpoint;
@@ -307,9 +320,11 @@ elation.require([
307
320
  elation.events.add(equi, 'asset_load', ev => {
308
321
  this.skyboxtexture = ev.target._texture;
309
322
  this.skyboxtexture.mapping = THREE.EquirectangularReflectionMapping;
323
+ this.skyboxtexture.encoding = THREE.sRGBEncoding;
310
324
  if (this.janus.currentroom === this) {
311
325
  this.skyboxobj.setTexture(this.skyboxtexture);
312
326
  }
327
+ elation.events.fire({element: this, type: 'skybox_update'});
313
328
  });
314
329
  equi.getInstance();
315
330
  } else if (hasSkybox) {
@@ -470,13 +485,17 @@ elation.require([
470
485
  }
471
486
  }
472
487
  this.updateToneMapping = function() {
473
- this.engine.systems.render.renderer.toneMapping = this.toneMappingTypes[this.tonemapping_type] || 0;
474
- this.engine.systems.render.renderer.toneMappingExposure = this.tonemapping_exposure;
475
- this.refresh();
488
+ if (this.active) {
489
+ this.engine.systems.render.renderer.toneMapping = this.toneMappingTypes[this.tonemapping_type] || 0;
490
+ this.engine.systems.render.renderer.toneMappingExposure = this.tonemapping_exposure;
491
+ this.refresh();
492
+ }
476
493
  }
477
494
  this.setNearFar = function() {
478
- this.engine.client.player.camera.camera.near = this.properties.near_dist;
479
- this.engine.client.player.camera.camera.far = this.properties.far_dist;
495
+ if (this.active) {
496
+ this.engine.client.player.camera.camera.near = this.properties.near_dist;
497
+ this.engine.client.player.camera.camera.far = this.properties.far_dist;
498
+ }
480
499
  }
481
500
  this.showDebug = function() {
482
501
  this.engine.client.player.disable();
@@ -619,7 +638,7 @@ elation.require([
619
638
  this.loadFromSource(data);
620
639
  }),
621
640
  failurecallback: elation.bind(this, function(xhr) {
622
- var translator = this.translators['^error$'];
641
+ var translator = roomTranslators['^error$'];
623
642
  translator.exec({janus: this.properties.janus, room: this, error: xhr.status || 404})
624
643
  .then(elation.bind(this, function(objs) {
625
644
  var datapath = elation.config.get('janusweb.datapath', '/media/janusweb');
@@ -679,7 +698,7 @@ elation.require([
679
698
  //this.parseerror = false;
680
699
  elation.events.fire({element: this, type: 'room_load_processed'});
681
700
  elation.events.fire({type: 'janus_room_load', element: this});
682
- if (this.pendingassets.length == 0) {
701
+ if (this.pendingassets.length == 0 && !this.completed) {
683
702
  setTimeout(() => elation.events.fire({element: this, type: 'room_load_complete'}), 0);
684
703
  }
685
704
  } catch (e) {
@@ -885,9 +904,9 @@ elation.require([
885
904
  // If no reciprocal link was found, spawn one so we can find our way back
886
905
  let linkrot = new EulerDegrees();
887
906
  linkrot.radians.copy(this.spawnpoint.rotation);
888
- //linkrot.x *= THREE.Math.RAD2DEG;
907
+ //linkrot.x *= THREE.MathUtils.RAD2DEG;
889
908
  linkrot.y = linkrot.y + 180;
890
- //linkrot.z *= THREE.Math.RAD2DEG;
909
+ //linkrot.z *= THREE.MathUtils.RAD2DEG;
891
910
  let linkpos = this.spawnpoint.localToWorld(V(0,0,player.fatness/2));
892
911
  this.createObject('link', {
893
912
  pos: linkpos,
@@ -973,7 +992,6 @@ elation.require([
973
992
 
974
993
  if (assets.scripts) {
975
994
  this.pendingScripts = 0;
976
- this.pendingScriptMap = {};
977
995
  this.loadScripts(assets.scripts);
978
996
  }
979
997
 
@@ -1024,11 +1042,11 @@ elation.require([
1024
1042
  });
1025
1043
  }
1026
1044
  this.getTranslator = function(url) {
1027
- var keys = Object.keys(this.translators);
1045
+ var keys = Object.keys(roomTranslators);
1028
1046
  for (var i = 0; i < keys.length; i++) {
1029
1047
  var re = new RegExp(keys[i]);
1030
1048
  if (url.match(re)) {
1031
- return this.translators[keys[i]];
1049
+ return roomTranslators[keys[i]];
1032
1050
  }
1033
1051
  }
1034
1052
  // TODO - implement default page handling as translator
@@ -1064,7 +1082,7 @@ elation.require([
1064
1082
 
1065
1083
  if (this.audionodes) {
1066
1084
  this.audionodes.gain.connect(this.audionodes.listener.getInput());
1067
- console.log('connect room audio to graph', this.audionodes.gain, this.audionodes.listener.getInput(), this);
1085
+ //console.log('connect room audio to graph', this.audionodes.gain, this.audionodes.listener.getInput(), this);
1068
1086
  this.fadeAudioIn(2);
1069
1087
  }
1070
1088
  this.engine.systems.controls.pointerLockEnabled = this.pointerlock;
@@ -1508,6 +1526,7 @@ console.log('connect room audio to graph', this.audionodes.gain, this.audionodes
1508
1526
  type: args.type,
1509
1527
  format: args.format,
1510
1528
  hls: args.hls,
1529
+ proxy: args.proxy,
1511
1530
  baseurl: this.baseurl
1512
1531
  });
1513
1532
  }
@@ -1753,10 +1772,12 @@ console.log('connect room audio to graph', this.audionodes.gain, this.audionodes
1753
1772
  this.pendingassets.splice(idx, 1);
1754
1773
  if (this.pendingassets.length == 0) {
1755
1774
  this.applyingEdits = false;
1756
- setTimeout(elation.bind(this, function() {
1757
- this.completed = true;
1758
- elation.events.fire({element: this, type: 'room_load_complete'});
1759
- }), 0);
1775
+ if (!this.completed) {
1776
+ setTimeout(elation.bind(this, function() {
1777
+ this.completed = true;
1778
+ elation.events.fire({element: this, type: 'room_load_complete'});
1779
+ }), 0);
1780
+ }
1760
1781
  }
1761
1782
  }
1762
1783
  }
@@ -1877,6 +1898,10 @@ console.log('connect room audio to graph', this.audionodes.gain, this.audionodes
1877
1898
  }
1878
1899
  }
1879
1900
  */
1901
+ // FIXME - hack to disable XR rendering while room is still loading. this can be handled better.
1902
+ if (this.engine.systems.render.views.xr && this.engine.systems.render.renderer.xr.isPresenting) {
1903
+ this.engine.systems.render.views.xr.enabled = this.completed;
1904
+ }
1880
1905
  this.janus.scriptframeargs[0] = ev.data.delta * 1000;
1881
1906
  elation.events.fire({element: this, type: 'janusweb_script_frame', data: ev.data.delta});
1882
1907
  elation.events.fire({element: this, type: 'janusweb_script_frame_end', data: ev.data.delta});
@@ -2069,8 +2094,10 @@ console.log('connect room audio to graph', this.audionodes.gain, this.audionodes
2069
2094
  sync: ['property', 'sync'],
2070
2095
  js_id: ['property', 'roomid'],
2071
2096
  pickable: ['property', 'pickable'],
2097
+ audionodes: ['property', 'audionodes'],
2072
2098
 
2073
2099
  skybox: ['property', 'skybox'],
2100
+ skybox_intensity: ['property', 'skybox_intensity'],
2074
2101
  skybox_equi: ['property', 'skybox_equi'],
2075
2102
  skybox_left_id: ['property', 'skybox_left_id'],
2076
2103
  skybox_right_id:['property', 'skybox_right_id'],
@@ -2166,29 +2193,72 @@ console.log('connect room audio to graph', this.audionodes.gain, this.audionodes
2166
2193
  //changestr += this.currentroom.changes[id];
2167
2194
  var change = this.changes[id];
2168
2195
  var real = this.getObjectFromProxy(change);
2196
+ let propdefs = real._thingdef.properties,
2197
+ proxydefs = change._proxydefs;
2169
2198
  if (real) {
2170
- var xmltype = typemap[real.type] || 'Object';
2199
+ var xmltype = false;
2200
+ if (room.customElements) {
2201
+ for (let k in room.customElements) {
2202
+ if (room.customElements[k].classname == real.type) {
2203
+ xmltype = k;
2204
+ break;
2205
+ }
2206
+ }
2207
+ }
2208
+ if (!xmltype) {
2209
+ if (real.type in janus.customElements) {
2210
+ xmltype = real.type;
2211
+ }
2212
+ }
2213
+ if (!xmltype) {
2214
+ xmltype = typemap[real.type] || 'Object';
2215
+ }
2171
2216
  let xmlnode = xmldoc.createElement(xmltype);
2172
2217
 
2173
2218
  var attrs = Object.keys(change);
2174
2219
  for (var i = 0; i < attrs.length; i++) {
2175
2220
  var k = attrs[i];
2176
2221
 
2222
+ let propdef = propdefs[proxydefs[k][1]];
2223
+
2177
2224
  if (ignoreattributes.indexOf(k) != -1) continue;
2178
2225
 
2226
+ let defaultval = (propdef ? propdef.default : null);
2179
2227
  var val = change[k];
2180
- if (val instanceof THREE.Vector2 ||
2181
- val instanceof THREE.Quaternion ||
2182
- val instanceof THREE.Vector3) {
2183
- val = val.toArray().map(function(n) { return (+n).toFixed(4); }).join(' ');
2228
+ if (val instanceof THREE.Vector2) {
2229
+ if (defaultval instanceof THREE.Vector2) defaultval = defaultval.toArray();
2230
+ //if (!('default' in propdef) || ('default' in propdef && !(val.x == defaultval[0] && val.y == defaultval[1]))) {
2231
+ val = val.toArray().map(function(n) { return (+n).toFixed(4); }).join(' ');
2232
+ //} else {
2233
+ // val = null;
2234
+ //}
2235
+ } else if (val instanceof THREE.Quaternion) {
2236
+ //if (defaultval instanceof THREE.Quaternion) defaultval = defaultval.toArray();
2237
+ //if (!('default' in propdef) || ('default' in propdef && !(val.x == defaultval[0] && val.y == defaultval[1] && val.z == defaultval[2] && val.w == defaultval[3]))) {
2238
+ val = val.toArray().map(function(n) { return (+n).toFixed(4); }).join(' ');
2239
+ //} else {
2240
+ // val = null;
2241
+ //}
2242
+ } else if (val instanceof THREE.Vector3) {
2243
+ if (defaultval instanceof THREE.Vector3) defaultval = defaultval.toArray();
2244
+ //if (!('default' in propdef) || ('default' in propdef && !(val.x == defaultval[0] && val.y == defaultval[1] && val.z == defaultval[2]))) {
2245
+ val = val.toArray().map(function(n) { return (+n).toFixed(4); }).join(' ');
2246
+ //} else {
2247
+ // val = null;
2248
+ //}
2184
2249
  } else if (val instanceof THREE.Euler) {
2185
- val = [val.x.toFixed(4), val.y.toFixed(4), val.z.toFixed(4)].join(' ');
2250
+ if (defaultval instanceof THREE.Euler) defaultval = defaultval.toArray();
2251
+ //if (!('default' in propdef) || ('default' in propdef && !(val.x == defaultval[0] && val.y == defaultval[1] && val.z == defaultval[2]))) {
2252
+ val = [val.x.toFixed(4), val.y.toFixed(4), val.z.toFixed(4)].join(' ');
2253
+ //} else {
2254
+ // val = null;
2255
+ //}
2186
2256
  } else if (val instanceof THREE.Color) {
2187
- if (k == 'col' && real.colorIsDefault) {
2188
- val = null;
2189
- } else {
2257
+ //if (k == 'col' && real.colorIsDefault) {
2258
+ // val = null;
2259
+ //} else {
2190
2260
  val = val.toArray().map(function(n) { return +n.toFixed(4); }).join(' ');
2191
- }
2261
+ //}
2192
2262
  } else if (elation.utils.isString(val) && val.indexOf('blob:') == 0) {
2193
2263
  var xhr = new XMLHttpRequest();
2194
2264
 
@@ -2211,6 +2281,15 @@ console.log('connect room audio to graph', this.audionodes.gain, this.audionodes
2211
2281
  }
2212
2282
  val = 'data:image/png;base64,' + btoa(binary);
2213
2283
  */
2284
+ } else if (elation.utils.isArray(val)) {
2285
+ //if ('default' in propdef && val.length == 0) {
2286
+ // FIXME - this assumes if a default array is provided, it's probably empty. This may not always be true.
2287
+ // val = null;
2288
+ //}
2289
+ } else {
2290
+ //if ('default' in propdef && val == defaultval) {
2291
+ // val = null;
2292
+ //}
2214
2293
  }
2215
2294
 
2216
2295
  if (val !== null && val !== undefined && typeof val != 'function') {
@@ -2403,7 +2482,7 @@ console.log('connect room audio to graph', this.audionodes.gain, this.audionodes
2403
2482
  } else if (val instanceof THREE.Euler) {
2404
2483
  if (defaultval instanceof THREE.Euler) defaultval = defaultval.toArray();
2405
2484
  if (!('default' in propdef) || ('default' in propdef && !(val.x == defaultval[0] && val.y == defaultval[1] && val.z == defaultval[2]))) {
2406
- objectsrc += ' ' + k + '="' + val.toArray().slice(0, 3).map(n => Math.round((n * THREE.Math.RAD2DEG) * 10000) / 10000).join(' ') + '"';
2485
+ objectsrc += ' ' + k + '="' + val.toArray().slice(0, 3).map(n => Math.round((n * THREE.MathUtils.RAD2DEG) * 10000) / 10000).join(' ') + '"';
2407
2486
  }
2408
2487
  } else if (val instanceof THREE.Quaternion) {
2409
2488
  if (defaultval instanceof THREE.Quaternion) defaultval = defaultval.toArray();
@@ -2512,10 +2591,11 @@ console.log('connect room audio to graph', this.audionodes.gain, this.audionodes
2512
2591
  _ray = new THREE.Raycaster();
2513
2592
  _ray.params.Line.threshold = 3;
2514
2593
  _ray.params.Points.threshold = 3;
2515
- return function(dir, pos, classname, maxdist) {
2594
+ return function(dir, pos, classname, maxdist, colliderroot=null) {
2516
2595
  _ray.set(pos, dir);
2517
2596
  _ray.far = maxdist || Infinity;
2518
- var intersections = _ray.intersectObject(this.colliders, true);
2597
+ if (!colliderroot) colliderroot = this.colliders;
2598
+ var intersections = _ray.intersectObject(colliderroot, true);
2519
2599
  var hits = [];
2520
2600
  if (classname) {
2521
2601
  for (var i = 0; i < intersections.length; i++) {
@@ -2598,17 +2678,19 @@ console.log('connect room audio to graph', this.audionodes.gain, this.audionodes
2598
2678
  });
2599
2679
  if (!this.loaded && this.pendingScripts) {
2600
2680
  // We're still waiting for the room to finish loading, so wait for the room_load_complete event before checking if we need to load anything else
2601
- this.addEventListener('room_load_complete', (ev) => {
2681
+ let func = (ev) => {
2602
2682
  // Room and all of its assets have finished loading. If our required component still isn't available, check the master package list and autoload if possible
2603
2683
  if (!finished) {
2604
2684
  this.loadComponentList().then(components => {
2605
2685
  if (components[k]) {
2606
2686
  this.loadNewAsset('script', { src: components[k].url, override: { room: this.getProxyObject() } });
2607
2687
  this._target.loadScripts([{src: components[k].url}]);
2688
+ this.removeEventListener('room_load_complete', func);
2608
2689
  }
2609
2690
  });
2610
2691
  }
2611
- });
2692
+ }
2693
+ this.addEventListener('room_load_complete', func);
2612
2694
  } else {
2613
2695
  // Room is already loaded and scripts are processed - we still don't know about this component, so load it up
2614
2696
  this.loadComponentList().then(components => {
@@ -2645,12 +2727,13 @@ console.log('connect room audio to graph', this.audionodes.gain, this.audionodes
2645
2727
  }
2646
2728
  this.dispatchEvent = function(event, target) {
2647
2729
  let firedev = elation.events.fire({element: this, target: target || event.target, event: event});
2648
- /*
2649
2730
  if (!event.element) event.element = target || this;
2650
2731
  var handlerfn = 'on' + event.type;
2651
- if (this[handlerfn]) {
2652
- this.executeCallback(this[handlerfn], event);
2732
+ let proxy = this.getProxyObject();
2733
+ if (proxy[handlerfn] && typeof proxy[handlerfn] == 'function') {
2734
+ proxy.executeCallback(proxy[handlerfn], event);
2653
2735
  }
2736
+ /*
2654
2737
  let firedev = elation.events.fire(event);
2655
2738
  let returnValue = true;
2656
2739
  firedev.forEach(e => returnValue &= e.returnValue);
@@ -2660,6 +2743,17 @@ console.log('dispatch to parent', event, this, event.target);
2660
2743
  }
2661
2744
  */
2662
2745
  }
2746
+ this.executeCallback = function(callback, args) {
2747
+ if (callback instanceof Function) {
2748
+ callback(args);
2749
+ } else if (elation.utils.isString(callback)) {
2750
+ (function(fn) {
2751
+ var event = args;
2752
+ return eval(callback);
2753
+ }).call(this.getProxyObject(), callback);
2754
+
2755
+ }
2756
+ }
2663
2757
  this.handleDelayedSound = function(ev) {
2664
2758
  // TODO - implement some visual indicator that this room is trying to play sound but was temporarily blocked
2665
2759
  }
@@ -2741,7 +2835,7 @@ console.log('dispatch to parent', event, this, event.target);
2741
2835
  ctx = this.audionodes.listener.context;
2742
2836
  //gain.gain.setValueAtTime(0, ctx.currentTime);
2743
2837
  gain.gain.cancelScheduledValues(ctx.currentTime);
2744
- gain.gain.linearRampToValueAtTime(0, ctx.currentTime);
2838
+ gain.gain.linearRampToValueAtTime(gain.gain.value, ctx.currentTime);
2745
2839
  gain.gain.linearRampToValueAtTime(value, ctx.currentTime + time);
2746
2840
  }
2747
2841
  }
@@ -2870,6 +2964,22 @@ console.log('unknown material', mat);
2870
2964
  }
2871
2965
  return stats;
2872
2966
  }
2967
+ this.updatePointerLock = function() {
2968
+ this.engine.systems.controls.pointerLockEnabled = this.pointerlock;
2969
+ }
2970
+ this.handleVisibilityChange = function(ev) {
2971
+ if (this.audionodes) {
2972
+ if (document.visibilityState == 'visible') {
2973
+ if (this.audioFadeTimer) clearTimeout(this.audioFadeTimer);
2974
+ if (this.audionodes.gain.gain.value < 1) {
2975
+ this.fadeAudioIn(1);
2976
+ }
2977
+ } else {
2978
+ if (this.audioFadeTimer) clearTimeout(this.audioFadeTimer);
2979
+ this.audioFadeTimer = setTimeout(() => this.fadeAudioOut(10), 10000);
2980
+ }
2981
+ }
2982
+ }
2873
2983
  }, elation.engine.things.generic);
2874
2984
  });
2875
2985
 
package/scripts/text.js CHANGED
@@ -2,7 +2,6 @@ elation.require(['engine.things.label'], function() {
2
2
  elation.component.add('engine.things.janustext', function() {
3
3
  this.postinit = function() {
4
4
  elation.engine.things.janustext.extendclass.postinit.call(this);
5
- this.frameupdates = [];
6
5
  this.textcache = this.engine.getScratchObject('textcache');
7
6
  this.defineProperties({
8
7
  'text': { type: 'string', default: '', refreshGeometry: true },
@@ -14,7 +13,8 @@ elation.require(['engine.things.label'], function() {
14
13
  'zalign': { type: 'string', default: 'back', refreshGeometry: true },
15
14
  'emissive': { type: 'color', default: 0x000000 },
16
15
  'opacity': { type: 'float', default: 1.0 },
17
- 'depthTest': { type: 'bool', default: true },
16
+ 'depth_write': { type: 'bool', default: true },
17
+ 'depth_test': { type: 'bool', default: true },
18
18
  'thickness': { type: 'float', refreshGeometry: true },
19
19
  'segments': { type: 'int', default: 6, refreshGeometry: true },
20
20
  'bevel': { type: 'bool', default: false, refreshGeometry: true },
@@ -29,7 +29,6 @@ elation.require(['engine.things.label'], function() {
29
29
  'wireframe': { type: 'boolean', default: false, set: this.updateMaterial, comment: 'Wireframe rendering' },
30
30
  });
31
31
  this.emptygeometry = new THREE.BufferGeometry();
32
- elation.events.add(this.engine, 'engine_frame', elation.bind(this, this.handleFrameUpdates));
33
32
  }
34
33
  this.createObject3D = function() {
35
34
  this.objects['3d'] = new THREE.Object3D();
@@ -82,6 +81,9 @@ elation.require(['engine.things.label'], function() {
82
81
  this.mesh = mesh;
83
82
  }
84
83
  this.objects['3d'].add(mesh);
84
+ setTimeout(() => {
85
+ //this.setCollider('box', this.getBoundingBox(true));
86
+ }, 0);
85
87
  this.refresh();
86
88
  }
87
89
  this.createTextMaterial = function() {
@@ -91,7 +93,8 @@ elation.require(['engine.things.label'], function() {
91
93
  transparent: this.properties.opacity < 1,
92
94
  emissive: this.properties.emissive,
93
95
  flatShading: false,
94
- depthTest: this.properties.depthTest,
96
+ depthTest: this.depth_test,
97
+ depthWrite: this.depth_write,
95
98
  reflectivity: .5,
96
99
  wireframe: this.wireframe,
97
100
  };
@@ -45,7 +45,7 @@ elation.require(['engine.things.generic'], function() {
45
45
  elation.events.add(this, 'click', elation.bind(this, this.click));
46
46
  }
47
47
  this.createObject3D = function() {
48
- var plane = new THREE.PlaneBufferGeometry(1,1);
48
+ var plane = new THREE.PlaneGeometry(1,1);
49
49
 
50
50
  var mat = new THREE.MeshBasicMaterial({
51
51
  color: 0x000000,
@@ -113,7 +113,7 @@ elation.require(['engine.things.generic'], function() {
113
113
  if (!this.active) {
114
114
  var canvas = this.engine.client.view.rendersystem.renderer.domElement;
115
115
  canvas.style.pointerEvents = 'none';
116
- canvas.style.position = 'absolute';
116
+ //canvas.style.position = 'absolute';
117
117
  this.engine.systems.controls.releasePointerLock();
118
118
  this.active = true;
119
119
  this.selectionmaterial.color.copy(this.activecolor);
@@ -127,7 +127,7 @@ setTimeout(elation.bind(this, function() {
127
127
  if (this.active) {
128
128
  var canvas = this.engine.client.view.rendersystem.renderer.domElement;
129
129
  canvas.style.pointerEvents = 'all';
130
- canvas.style.position = 'static';
130
+ //canvas.style.position = 'static';
131
131
  this.engine.systems.controls.requestPointerLock();
132
132
  ev.stopPropagation();
133
133
  ev.preventDefault();