janusweb 1.5.33 → 1.5.37

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 (47) hide show
  1. package/CHANGELOG +39 -0
  2. package/media/assets/webui/apps/avatar/avatar.js +2 -1
  3. package/media/assets/webui/apps/comms/voip.js +2 -4
  4. package/media/assets/webui/apps/editor/codemirror/addon/hint/javascript-hint.js +162 -0
  5. package/media/assets/webui/apps/editor/codemirror/addon/hint/show-hint.css +36 -0
  6. package/media/assets/webui/apps/editor/codemirror/addon/hint/show-hint.js +529 -0
  7. package/media/assets/webui/apps/editor/codemirror/addon/hint/xml-hint.js +140 -0
  8. package/media/assets/webui/apps/editor/codemirror/keymap/vim.js +5734 -0
  9. package/media/assets/webui/apps/editor/codemirror/lib/codemirror.css +350 -0
  10. package/media/assets/webui/apps/editor/codemirror/lib/codemirror.js +9800 -0
  11. package/media/assets/webui/apps/editor/codemirror/lib/jmldark.css +33 -0
  12. package/media/assets/webui/apps/editor/codemirror/mode/css/css.js +864 -0
  13. package/media/assets/webui/apps/editor/codemirror/mode/htmlmixed/htmlmixed.js +153 -0
  14. package/media/assets/webui/apps/editor/codemirror/mode/javascript/javascript.js +942 -0
  15. package/media/assets/webui/apps/editor/codemirror/mode/xml/xml.js +413 -0
  16. package/media/assets/webui/apps/editor/editor.css +3 -0
  17. package/media/assets/webui/apps/editor/editor.js +407 -9
  18. package/media/assets/webui/apps/editor/editor.json +6 -3
  19. package/media/assets/webui/apps/inventory/inventory.js +1 -1
  20. package/media/assets/webui/apps/locomotion/teleporter.js +1 -1
  21. package/media/assets/webui/apps/navigation/navigation.js +12 -12
  22. package/media/assets/webui/apps/vfs/browserfs/browserfs.js +8 -0
  23. package/media/assets/webui/apps/vfs/vfs.css +52 -0
  24. package/media/assets/webui/apps/vfs/vfs.js +452 -0
  25. package/media/assets/webui/apps/vfs/vfs.json +10 -0
  26. package/media/assets/webui/default.json +2 -1
  27. package/media/assets/webui/themes/default.css +29 -2
  28. package/package.json +2 -9
  29. package/scripts/client.js +64 -44
  30. package/scripts/elements/linesegments.js +5 -2
  31. package/scripts/janusbase.js +21 -9
  32. package/scripts/janusghost.js +0 -1
  33. package/scripts/janusparagraph.js +5 -3
  34. package/scripts/janusparticle.js +11 -12
  35. package/scripts/janusplayer.js +4 -4
  36. package/scripts/janusweb.js +21 -2
  37. package/scripts/janusxrplayer.js +3 -0
  38. package/scripts/multiplayermanager.js +3 -3
  39. package/scripts/object.js +159 -82
  40. package/scripts/portal.js +3 -5
  41. package/scripts/room.js +86 -44
  42. package/scripts/sound.js +0 -1
  43. package/scripts/text.js +10 -2
  44. package/scripts/translators/janusvfs.js +20 -0
  45. package/scripts/video.js +1 -1
  46. package/scripts/websurface.js +11 -2
  47. package/utils/init.sh +1 -1
package/scripts/client.js CHANGED
@@ -1,5 +1,4 @@
1
- elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient', 'engine.things.light_directional', 'engine.things.light_point', 'janusweb.janusweb', 'janusweb.chat', 'janusweb.janusplayer', 'janusweb.janusxrplayer', 'janusweb.external.document-register-element', 'janusweb.ui.main'], function() {
2
-
1
+ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.assets', 'engine.things.light_ambient', 'engine.things.light_directional', 'engine.things.light_point', 'janusweb.janusweb', 'janusweb.chat', 'janusweb.janusplayer', 'janusweb.janusxrplayer', 'janusweb.external.document-register-element', 'janusweb.ui.main', 'elements.elements'], function() {
3
2
  // If getCurrentScript returns non-null here, then it means we're in release mode
4
3
  var clientScript = elation.utils.getCurrentScript();
5
4
 
@@ -12,7 +11,7 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
12
11
  var homepage = elation.utils.any(args.homepage, elation.config.get('janusweb.homepage'), document.location.href);
13
12
  var corsproxy = elation.utils.any(args.corsproxy, elation.config.get('engine.assets.corsproxy'), document.location.href);
14
13
  var container = elation.utils.any(args.container, document.body);
15
- var fullsize = (container == document.body);
14
+ var fullsize = elation.utils.any(args.fullsize, container == document.body);
16
15
 
17
16
  if (elation.config.get('serviceworker.enabled') && 'serviceWorker' in navigator) {
18
17
  var workerscript = elation.config.get('serviceworker.script', 'service-worker.js');
@@ -58,7 +57,7 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
58
57
  document.head.appendChild(link);
59
58
  elation.html.addclass(document.body, 'dark');
60
59
  elation.html.addclass(document.body, 'janusweb');
61
- var janusweb = elation.janusweb.client({
60
+ var janusweb = elation.elements.create('janusweb.client', {
62
61
  append: container,
63
62
  homepage: homepage,
64
63
  corsproxy: corsproxy,
@@ -67,6 +66,7 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
67
66
  showchat: elation.utils.any(args.showchat, true),
68
67
  usevoip: elation.utils.any(args.usevoip, false),
69
68
  resolution: args.resolution,
69
+ fullsize: fullsize,
70
70
  url: args.url,
71
71
  networking: args.networking,
72
72
  autoload: args.autoload,
@@ -82,13 +82,31 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
82
82
  elation.events.add(janusweb.engine, 'engine_start', function() { resolve(janusweb); });
83
83
  });
84
84
  });
85
- elation.component.add('janusweb.client', function() {
86
- this.initEngine = function() {
85
+ elation.elements.define('janusweb.client', class extends elation.elements.engine.client {
86
+ init() {
87
+ super.init();
88
+ this.defineAttributes({
89
+ corsproxy: { type: 'string' },
90
+ homepage: { type: 'string' },
91
+ url: { type: 'string' },
92
+ uiconfig: { type: 'string' },
93
+ shownavigation: { type: 'boolean', default: true },
94
+ showchat: { type: 'boolean', default: true },
95
+ networking: { type: 'boolean', default: true },
96
+ usevoip: { type: 'boolean', default: false },
97
+ autoload: { type: 'boolean', default: true },
98
+ urltemplate: { type: 'string' },
99
+ server: { type: 'string' },
100
+ avatarsrc: { type: 'string' },
101
+ muted: { type: 'boolean', default: false },
102
+ });
103
+ }
104
+ initEngine() {
87
105
  this.initLoader();
88
106
 
89
107
  var hashargs = elation.url();
90
108
 
91
- this.enginecfg.stats = this.args.stats;
109
+ //this.enginecfg.stats = this.args.stats;
92
110
 
93
111
  this.enginecfg.systems = [];
94
112
  this.enginecfg.systems.push("controls");
@@ -102,7 +120,8 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
102
120
  this.enginecfg.systems.push("sound");
103
121
  this.enginecfg.crosshair = false;
104
122
  this.enginecfg.picking = true;
105
- this.enginecfg.useWebVRPolyfill = elation.utils.any(this.args.useWebVRPolyfill, true);
123
+ this.enginecfg.fullsize = this.fullsize && this.fullsize != 'false'; // FIXME - type coersion should be doing this
124
+ //this.enginecfg.useWebVRPolyfill = elation.utils.any(this.args.useWebVRPolyfill, true);
106
125
 
107
126
  if ('xr' in navigator) {
108
127
  navigator.xr.addEventListener('sessiongranted', (ev) => {
@@ -110,7 +129,7 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
110
129
  });
111
130
  }
112
131
  }
113
- this.initButtons = function() {
132
+ initButtons() {
114
133
  this.sharebutton = elation.ui.button({classname: 'janusweb_sharing', label: 'Share'});
115
134
  this.sharedialog = elation.engine.sharing({append: document.body, client: this, anchor: this.sharebutton});
116
135
  elation.events.add(this.sharebutton, 'ui_button_click', elation.bind(this.sharedialog, this.sharedialog.showShareDialog));
@@ -126,21 +145,21 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
126
145
 
127
146
  elation.events.add(document, 'pointerlockchange', elation.bind(this, function() { this.setUIActive(document.pointerLockElement === null); }));
128
147
  }
129
- this.initWorld = function() {
148
+ initWorld() {
130
149
  var things = this.world.load({
131
150
  name: 'janusweb',
132
151
  type: 'janusweb',
133
152
  properties: {
134
- corsproxy: elation.utils.any(this.args.corsproxy, elation.config.get('engine.assets.corsproxy')),
153
+ corsproxy: elation.utils.any(this.corsproxy, elation.config.get('engine.assets.corsproxy')),
135
154
  datapath: elation.config.get('janusweb.datapath'),
136
- homepage: this.args.homepage,
137
- url: this.args.url,
138
- showchat: this.args.showchat,
139
- networking: this.args.networking,
140
- autoload: this.args.autoload,
141
- urltemplate: this.args.urltemplate,
142
- server: this.args.server,
143
- muted: this.args.muted,
155
+ homepage: this.homepage,
156
+ url: this.url,
157
+ showchat: this.showchat,
158
+ networking: this.networking,
159
+ autoload: this.autoload,
160
+ //urltemplate: this.urltemplate,
161
+ server: this.server,
162
+ muted: this.muted,
144
163
  }
145
164
  });
146
165
  this.janusweb = things.children.janusweb;
@@ -151,22 +170,21 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
151
170
  height: 1.8,
152
171
  movespeed: 5000,
153
172
  collidable: true,
154
- usevoip: this.args.usevoip,
155
- avatarsrc: this.args.avatarsrc,
173
+ usevoip: this.usevoip,
174
+ avatarsrc: this.avatarsrc,
156
175
  staticfriction: 2,
157
176
  dynamicfriction: 1.9,
158
177
  });
159
178
  elation.events.add(this.engine.systems.render, 'render_view_add', (ev) => this.handleRenderViewAdd(ev));
160
179
 
161
- this.shownavigation = elation.utils.any(this.args.shownavigation, true);
162
180
  var datapath = elation.config.get('janusweb.datapath', '/media/janusweb');
163
- this.uiconfig = elation.utils.any(this.player.getSetting('uiconfig'), this.args.uiconfig, datapath + (datapath[datapath.length-1] != '/' ? '/' : '') + 'assets/webui/default.json');
181
+ this.uiconfig = elation.utils.any(this.player.getSetting('uiconfig'), this.uiconfig, datapath + (datapath[datapath.length-1] != '/' ? '/' : '') + 'assets/webui/default.json');
164
182
  if (this.shownavigation) {
165
183
  this.createUI();
166
184
  }
167
185
  this.view.pickingactive = true;
168
186
 
169
- let overlay = this.container.parentNode.querySelector('janus-overlay');
187
+ let overlay = this.parentNode.querySelector('janus-overlay');
170
188
  if (overlay) {
171
189
  this.overlay = overlay;
172
190
  }
@@ -174,16 +192,16 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
174
192
  elation.engine.assets.initTextureLoaders(this.engine.systems.render, elation.config.get('janusweb.datapath') + 'lib/basis/');
175
193
  elation.engine.assets.setDracoPath(elation.config.get('janusweb.datapath') + 'lib/draco/');
176
194
  }
177
- this.createUI = function() {
195
+ createUI() {
178
196
  if (!this.ui) {
179
197
  this.ui = elation.elements.create('janus.ui.main', {
180
- append: this.view,
198
+ append: this,
181
199
  client: this,
182
200
  config: this.uiconfig
183
201
  });
184
202
  }
185
203
  }
186
- this.initLoader = function() {
204
+ initLoader() {
187
205
  var loader = document.getElementsByClassName('engine_loading')[0];
188
206
  if (loader) {
189
207
  var logo = loader.getElementsByTagName('svg')[0];
@@ -197,12 +215,12 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
197
215
  elation.events.add(this.engine, 'engine_start', elation.bind(this, this.handleEngineStart));
198
216
  }
199
217
  }
200
- this.handleEngineStart = function(ev) {
218
+ handleEngineStart(ev) {
201
219
  if (this.loadingscreen) {
202
220
  this.loadingscreen.container.parentNode.removeChild(this.loadingscreen.container);
203
221
  }
204
222
  }
205
- this.handleEngineError = function(ev) {
223
+ handleEngineError(ev) {
206
224
  console.log('omg error!', ev);
207
225
  if (this.loadingscreen) {
208
226
  this.loadingscreen.label.innerHTML = 'Error!';
@@ -213,9 +231,9 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
213
231
  var errordiv = elation.html.create({tag: 'pre', append: this.loadingscreen.container, content: msg, classname: 'janusweb_error'});
214
232
  }
215
233
  }
216
- this.showMenu = function() {
234
+ showMenu() {
217
235
  }
218
- this.setUIActive = function(active) {
236
+ setUIActive(active) {
219
237
  if (active) {
220
238
  if (this.ui) this.ui.enable();
221
239
  if (this.buttons) this.buttons.enable();
@@ -224,12 +242,12 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
224
242
  if (this.buttons) this.buttons.disable();
225
243
  }
226
244
  }
227
- this.showAbout = function() {
245
+ showAbout() {
228
246
  var aboutwin = elation.ui.window({append: document.body, center: true, title: 'About JanusWeb'});
229
247
  var frame = elation.ui.iframe({src: 'http://github.com/jbaicoianu/janusweb/', classname: 'janusweb_about'});
230
248
  aboutwin.setcontent(frame);
231
249
  }
232
- this.toggleFullscreen = function(ev, updateOnly) {
250
+ toggleFullscreen(ev, updateOnly) {
233
251
  var view = this.view;
234
252
  if (!updateOnly && view && (typeof ev == 'undefined' || ev.value == 1 || typeof ev.value == 'undefined')) {
235
253
  view.toggleFullscreen();
@@ -244,7 +262,7 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
244
262
  }
245
263
  }
246
264
  }
247
- this.configureOptions = function() {
265
+ configureOptions() {
248
266
  if (!this.configmenu) {
249
267
  var configpanel = elation.janusweb.configuration({client: this});
250
268
  this.configmenu = elation.ui.window({
@@ -261,10 +279,10 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
261
279
  }
262
280
  this.configmenu.show();
263
281
  }
264
- this.registerElement = function(tagname, classobj, extendclass) {
282
+ registerElement(tagname, classobj, extendclass) {
265
283
  this.janusweb.registerElement(tagname, classobj, extendclass);
266
284
  }
267
- this.handleRenderViewAdd = function(ev) {
285
+ handleRenderViewAdd(ev) {
268
286
  let view = ev.data;
269
287
  if (view.xrsession && !this.xrplayer) {
270
288
  this.xrplayer = this.player.createObject('xrplayer', {
@@ -273,14 +291,14 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
273
291
  });
274
292
  }
275
293
  }
276
- }, elation.engine.client);
294
+ });
277
295
 
278
296
  if (typeof customElements != 'undefined') {
279
297
  elation.elements.define('janus.viewer', class extends elation.elements.base {
280
298
  init() {
281
299
  super.init();
282
300
  this.defineAttributes({
283
- fullscreen: { type: 'boolean', default: true },
301
+ fullsize: { type: 'boolean', default: true },
284
302
  autostart: { type: 'boolean', default: true },
285
303
  src: { type: 'string' },
286
304
  corsproxy: { type: 'string' },
@@ -305,11 +323,12 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
305
323
  }
306
324
  document.body.addEventListener('click', start);
307
325
  }
326
+ this.style.overflow = 'hidden';
308
327
  }
309
328
  getClientArgs() {
310
- var fullscreen = this.fullscreen,
311
- width = (this.fullscreen ? window.innerWidth : this.width),
312
- height = (this.fullscreen ? window.innerHeight : this.height);
329
+ var fullsize = this.fullsize,
330
+ width = (this.fullsize ? window.innerWidth : this.width),
331
+ height = (this.fullsize ? window.innerHeight : this.height);
313
332
  var args = {
314
333
  url: this.getRoomURL(),
315
334
  homepage: this.homepage || this.src,
@@ -321,6 +340,7 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
321
340
  avatarsrc: this.avatarsrc,
322
341
  uiconfig: this.uiconfig,
323
342
  container: this,
343
+ fullsize: this.fullsize,
324
344
  };
325
345
  return args;
326
346
  }
@@ -338,9 +358,9 @@ elation.require(['engine.engine', 'engine.assets', 'engine.things.light_ambient'
338
358
  create() {
339
359
  if (this.iframe) return;
340
360
  var iframe = document.createElement('iframe');
341
- var fullscreen = this.fullscreen;
342
- iframe.width = (this.fullscreen ? window.innerWidth : this.width);
343
- iframe.height = (this.fullscreen ? window.innerHeight : this.height);
361
+ var fullsize = this.fullsize;
362
+ iframe.width = (this.fullsize ? window.innerWidth : this.width);
363
+ iframe.height = (this.fullsize ? window.innerHeight : this.height);
344
364
  iframe.setAttribute('allowvr', 'yes');
345
365
  iframe.setAttribute('allowfullscreen', true);
346
366
  iframe.setAttribute('allow', 'vr');
@@ -6,6 +6,7 @@ elation.require(['janusweb.janusbase'], function() {
6
6
  linewidth: 1,
7
7
  depth_write: true,
8
8
  depth_test: true,
9
+ fog: true,
9
10
 
10
11
  create() {
11
12
 
@@ -33,16 +34,18 @@ elation.require(['janusweb.janusbase'], function() {
33
34
  let lineobj = new THREE.LineSegments(geo, new THREE.LineBasicMaterial({
34
35
  vertexColors: THREE.VertexColors,
35
36
  opacity: this.opacity,
36
- transparent: (this.opacity < 1),
37
+ transparent: (this.transparent !== null ? this.transparent : this.opacity < 1),
37
38
  depthWrite: this.depth_write,
38
39
  depthTest: this.depth_test,
39
40
  linewidth: this.linewidth,
41
+ fog: this.fog,
40
42
  }));
43
+ lineobj.renderOrder = this.renderorder;
41
44
  this.objects['3d'].add(lineobj);
42
45
  if (this.pickable || this.collidable) {
43
46
  //this.colliders.add(lineobj.clone());
44
47
  }
45
- lineobj.userData.thing = this;
48
+ lineobj.userData.thing = this._target || this;
46
49
  this.geometry = geo;
47
50
  this.lineobj = lineobj;
48
51
  }
@@ -19,6 +19,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
19
19
  js_id: { type: 'string' },
20
20
  color: { type: 'color', default: this.defaultcolor, set: this.updateColor, comment: 'Object color' },
21
21
  opacity: { type: 'float', default: 1.0, set: this.updateOpacity, min: 0, max: 1, comment: 'Object translucency, from 0..1' },
22
+ transparent: { type: 'bool', default: null, set: this.updateOpacity, comment: 'Override object transparency autodetection' },
22
23
  alphatest: { type: 'float', default: 0.05, set: this.updateAlphaTest, min: 0, max: 1 },
23
24
  fwd: { type: 'vector3', default: new THREE.Vector3(0,0,1), set: this.pushFrameUpdate, comment: 'Forward vector (zdir == fwd)' },
24
25
  xdir: { type: 'vector3', default: new THREE.Vector3(1,0,0), set: this.pushFrameUpdate, comment: 'Left vector' },
@@ -50,6 +51,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
50
51
  billboard: { type: 'string', default: '' },
51
52
  hasposition: { type: 'boolean', default: true },
52
53
  gazetime: { type: 'float' },
54
+ static: { type: 'boolean', default: false },
53
55
  ongazeenter: { type: 'callback' },
54
56
  ongazeleave: { type: 'callback' },
55
57
  ongazeprogress: { type: 'callback' },
@@ -81,7 +83,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
81
83
  this.properties.orientation.copy(this.object.quaternion);
82
84
  return this.object;
83
85
  }
84
- if (this.renderorder) this.object.renderOrder = this.renderorder;
86
+ if (this.renderorder && this.object) this.object.renderOrder = this.renderorder;
85
87
  return new THREE.Object3D();
86
88
  }
87
89
  this.createChildren = function() {
@@ -121,7 +123,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
121
123
  this.refresh();
122
124
  }
123
125
  this.updateOpacity = function() {
124
- this.setOpacity(this.opacity);
126
+ this.setOpacity(this.opacity, this.transparent);
125
127
  },
126
128
  this.updateAlphaTest = function() {
127
129
  this.setAlphaTest(this.alphatest);
@@ -229,7 +231,9 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
229
231
  }
230
232
  }
231
233
  this.createForces = function() {
232
- elation.events.add(this.objects.dynamics, 'physics_collide', elation.bind(this, this.handleCollision));
234
+ if (this.collidable && !this.collision_trigger) {
235
+ elation.events.add(this.objects.dynamics, 'physics_collide', elation.bind(this, this.handleCollision));
236
+ }
233
237
  this.updateRotationSpeed();
234
238
  }
235
239
  this.updateRotationSpeed = function() {
@@ -353,6 +357,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
353
357
  dynamicfriction:['property', 'dynamicfriction'],
354
358
  staticfriction:['property', 'staticfriction'],
355
359
  opacity: ['property', 'opacity'],
360
+ transparent: ['property', 'transparent'],
356
361
  alphatest: ['property', 'alphatest'],
357
362
  sync: ['property', 'sync'],
358
363
  autosync: ['property', 'autosync'],
@@ -717,7 +722,11 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
717
722
  }
718
723
  this.start = function() {
719
724
  if (!this.started) {
720
- elation.events.add(this.room, 'janusweb_script_frame_end', this.handleFrameUpdates);
725
+ if (!this.static) {
726
+ elation.events.add(this.room, 'janusweb_script_frame_end', this.handleFrameUpdates);
727
+ } else {
728
+ this.handleFrameUpdates({data: {dt: 0}});
729
+ }
721
730
  this.started = true;
722
731
  }
723
732
  for (var k in this.children) {
@@ -734,7 +743,9 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
734
743
  }
735
744
  }
736
745
  if (this.started) {
737
- elation.events.remove(this.room, 'janusweb_script_frame_end', this.handleFrameUpdates);
746
+ if (!this.static) {
747
+ elation.events.remove(this.room, 'janusweb_script_frame_end', this.handleFrameUpdates);
748
+ }
738
749
  this.started = false;
739
750
  this.dispatchEvent({type: 'stop', bubbles: false});
740
751
  }
@@ -983,15 +994,16 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
983
994
  }
984
995
  }
985
996
  }
986
- this.setOpacity = function(opacity) {
987
- if (this.objects['3d'] && this.currentopacity != opacity) {
997
+ this.setOpacity = function(opacity, transparent) {
998
+ if (this.objects['3d'] && (this.currentopacity != opacity || this.currenttransparent !== transparent)) {
988
999
  this.currentopacity = opacity;
989
- this.traverseObjects(function(n) {
1000
+ this.currenttransparent = transparent;
1001
+ this.traverseObjects((n) => {
990
1002
  if (n.material) {
991
1003
  var m = (elation.utils.isArray(n.material) ? n.material : [n.material]);
992
1004
  for (var i = 0; i < m.length; i++) {
993
1005
  m[i].opacity = opacity;
994
- m[i].transparent = (opacity < 1);
1006
+ m[i].transparent = (transparent !== null ? transparent : opacity < 1);
995
1007
  if (m[i].transparent) {
996
1008
  m[i].alphaTest = this.alphatest;
997
1009
  }
@@ -97,7 +97,6 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
97
97
  size: .1,
98
98
  thickness: .03,
99
99
  align: 'center',
100
- collidable: false,
101
100
  text: name,
102
101
  pos: this.userid_pos,
103
102
  pickable: false,
@@ -13,7 +13,7 @@ elation.require(['janusweb.janusbase'], function() {
13
13
  depth_write: { type: 'boolean', default: true },
14
14
  depth_test: { type: 'boolean', default: true },
15
15
  collision_id: { type: 'string', default: 'cube' },
16
- collision_scale: { type: 'vector3', default: V(1, 1, .02) },
16
+ collision_scale: { type: 'vector3', default: V(.5, .5, .02) },
17
17
  shadow: { type: 'boolean', default: true, set: this.updateMaterial },
18
18
  shadow_receive: { type: 'boolean', default: true, set: this.updateMaterial, comment: 'Receive shadows from self and other objects' },
19
19
  shadow_cast: { type: 'boolean', default: true, set: this.updateMaterial, comment: 'Cast shadows onto self and other objects' },
@@ -29,8 +29,10 @@ elation.require(['janusweb.janusbase'], function() {
29
29
  return mesh;
30
30
  }
31
31
  this.createForces = function() {
32
- this.setCollider('box', { min: V(-1, -1, -.01), max: V(1, 1, .01) });
32
+ this.setCollider('box', { min: V(-.8, -.8, -.01), max: V(.8, .8, .01) });
33
+ //this.collision_id = 'cube';
33
34
  }
35
+ this.updateColliderFromGeometry = function() { }
34
36
  this.createMaterial = function() {
35
37
  var texture = this.createTexture();
36
38
  var sidemap = {
@@ -115,7 +117,7 @@ elation.require(['janusweb.janusbase'], function() {
115
117
  texture.needsUpdate = true;
116
118
  this.refresh();
117
119
  }
118
- }
120
+ };
119
121
  this.currentImage = img;
120
122
  img.src = url;
121
123
  this.refresh();
@@ -39,7 +39,6 @@ elation.require(['janusweb.janusbase'], function() {
39
39
  opacity: { type: 'float', default: 1.0, set: this.updateMaterial },
40
40
  fade_in: { type: 'float', default: 1.0 },
41
41
  fade_out: { type: 'float', default: 1.0 },
42
- duration: { type: 'float', default: 1.0 },
43
42
  particle_scale: { type: 'vector3', default: [1, 1, 1], set: this.updateMaterial},
44
43
  particle_vel: { type: 'vector3', default: [0, 0, 0]},
45
44
  particle_accel: { type: 'vector3', default: [0, 0, 0]},
@@ -52,8 +51,8 @@ elation.require(['janusweb.janusbase'], function() {
52
51
  refreshrate: { type: 'int', default: 30 },
53
52
  blend_src: { type: 'string', default: 'src_alpha', set: this.updateMaterial },
54
53
  blend_dest: { type: 'string', default: 'one_minus_src_alpha', set: this.updateMaterial },
55
- depthwrite: { type: 'bool', default: false },
56
- depthtest: { type: 'bool', default: true },
54
+ depth_write: { type: 'bool', default: false },
55
+ depth_test: { type: 'bool', default: true },
57
56
  });
58
57
  this.particles = [];
59
58
  this.emitted = 0;
@@ -72,7 +71,7 @@ elation.require(['janusweb.janusbase'], function() {
72
71
  this.updateParticles = elation.bind(this, this.updateParticles); // FIXME - hack, this should happen at the lower level of all components
73
72
  }
74
73
  this.createObject3D = function() {
75
- var geo = this.geometry = new THREE.BufferGeometry()
74
+ var geo = this.geometry = new THREE.BufferGeometry();
76
75
 
77
76
  var texture = null,
78
77
  textureasset = null;
@@ -132,8 +131,8 @@ elation.require(['janusweb.janusbase'], function() {
132
131
  //blending: THREE.AdditiveBlending,
133
132
  transparent: true,
134
133
  alphaTest: .001,
135
- depthWrite: this.depthwrite,
136
- depthTest: this.depthtest,
134
+ depthWrite: this.depth_write,
135
+ depthTest: this.depth_test,
137
136
  } );
138
137
 
139
138
  this.material = mat;
@@ -290,8 +289,8 @@ elation.require(['janusweb.janusbase'], function() {
290
289
  elapsed = now - this.lasttime,
291
290
  endtime = now + this.duration * 1000,
292
291
  emitted = 0,
293
- startpoint = this.currentpoint;
294
- spawncount = this.rate * elapsed / 1000;
292
+ startpoint = this.currentpoint,
293
+ spawncount = this.rate * elapsed / 1000,
295
294
  count = this.count,
296
295
  loop = this.loop;
297
296
 
@@ -329,7 +328,7 @@ elation.require(['janusweb.janusbase'], function() {
329
328
  if (!geo.boundingSphere) {
330
329
  geo.computeBoundingSphere();
331
330
  } else {
332
- let currentBoundingRadius = geo.boundingSphere.radius
331
+ let currentBoundingRadius = geo.boundingSphere.radius;
333
332
  if (this.boundingRadiusSq > currentBoundingRadius * currentBoundingRadius) {
334
333
  geo.boundingSphere.radius = Math.sqrt(this.boundingRadiusSq) + .1;
335
334
  }
@@ -408,7 +407,7 @@ elation.require(['janusweb.janusbase'], function() {
408
407
  var randomInRange = function(range) {
409
408
  //return (Math.random() - .5) * range;
410
409
  return Math.random() * range;
411
- }
410
+ };
412
411
  let pointpos = point.pos;
413
412
  pointpos.set(randomInRange(rand_pos.x), randomInRange(rand_pos.y), randomInRange(rand_pos.z));
414
413
  if (this.emitpoints) {
@@ -532,8 +531,8 @@ elation.require(['janusweb.janusbase'], function() {
532
531
  count: [ 'property', 'count'],
533
532
  duration: [ 'property', 'duration'],
534
533
  opacity: [ 'property', 'opacity'],
535
- depthwrite: [ 'property', 'depthwrite'],
536
- depthtest: [ 'property', 'depthtest'],
534
+ depth_write: [ 'property', 'depth_write'],
535
+ depth_test: [ 'property', 'depth_test'],
537
536
  play: [ 'function', 'start'],
538
537
  };
539
538
  }
@@ -368,10 +368,10 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
368
368
  if (typeof playerpos.z == 'undefined' || isNaN(playerpos.z)) playerpos.z = 0;
369
369
  this.objects['3d'].updateMatrix();
370
370
  this.objects['3d'].updateMatrixWorld();
371
- this.objects['3d'].matrixWorld.extractBasis(v.xdir, v.ydir, v.zdir)
371
+ this.objects['3d'].matrixWorld.extractBasis(v.xdir, v.ydir, v.zdir);
372
372
  }
373
373
  if (this.head) {
374
- this.head.objects['3d'].matrixWorld.extractBasis(v.view_xdir, v.view_ydir, v.view_zdir)
374
+ this.head.objects['3d'].matrixWorld.extractBasis(v.view_xdir, v.view_ydir, v.view_zdir);
375
375
  v.head_pos.setFromMatrixPosition(this.head.objects['3d'].matrixWorld);
376
376
  v.view_zdir.negate();
377
377
  }
@@ -491,7 +491,7 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
491
491
  avatar_src: 'data:text/plain,' + encodeURIComponent(avatar),
492
492
  showlabel: false,
493
493
  //pos: V(0, -this.fatness, 0),
494
- rotation: V(0, 180, 0),
494
+ //rotation: V(0, 180, 0),
495
495
  renderorder: 101,
496
496
  });
497
497
  this.ghost.orientation.set(0,1,0,0);
@@ -655,7 +655,7 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
655
655
  avatar_src: 'data:text/plain,' + encodeURIComponent(avatar),
656
656
  showlabel: false,
657
657
  //pos: V(0, -this.fatness, 0),
658
- rotation: V(0, 180, 0),
658
+ //rotation: V(0, 180, 0),
659
659
  renderorder: 101,
660
660
  });
661
661
 
@@ -101,7 +101,7 @@ elation.require([
101
101
  if (this.urltemplate) {
102
102
  dust.filters.stripunsafe = function(s) {
103
103
  return s.replace(/:\//g, '');
104
- }
104
+ };
105
105
  elation.template.add('janusweb.url', this.urltemplate);
106
106
  }
107
107
  this.initScripting();
@@ -157,6 +157,7 @@ elation.require([
157
157
  userid: ['property', 'userId'],
158
158
  avatarlighting: ['property', 'settings.avatarlighting'],
159
159
  ui: ['property', 'engine.client.ui'],
160
+ currentroom: ['property', 'currentroom'],
160
161
 
161
162
  hmd: ['accessor', 'isVRActive'],
162
163
 
@@ -172,6 +173,7 @@ elation.require([
172
173
  load: ['function', 'navigateTo'],
173
174
  setActiveRoom: ['function', 'setActiveRoom'],
174
175
  preload: ['function', 'preload'],
176
+ createRoom: ['function', 'createRoom'],
175
177
  navhome: ['function', 'navigateHome'],
176
178
  chatsend: ['function', 'sendChatMessage'],
177
179
  sync: ['function', 'currentroom.sync'],
@@ -412,6 +414,23 @@ elation.require([
412
414
  this.preload = function(url, stripreferrer) {
413
415
  return this.load(url, false, null, stripreferrer);
414
416
  }
417
+ this.createRoom = function(url, makeactive=true) {
418
+ let newroom = this.spawn('janusroom', url, {
419
+ url: url,
420
+ janus: this,
421
+ corsproxy: this.corsproxy,
422
+ deferload: true
423
+ });
424
+
425
+ this.rooms[newroom.roomid] = newroom;
426
+ //console.log('made new room', url, room);
427
+ this.loading = false;
428
+ if (newroom && makeactive) {
429
+ this.setActiveRoom(newroom);
430
+ }
431
+ this.initScripting();
432
+ return newroom.getProxyObject();
433
+ }
415
434
  this.getFixedURL = function(url) {
416
435
  // Our 'clean' client URLs don't contain a : because many services have problems parsing them
417
436
  var m = url.match(/^(https?)\/\/?(.*)$/i);
@@ -511,7 +530,7 @@ elation.require([
511
530
  }
512
531
  this.handleRoomEditOther = function(data) {
513
532
  var roomId = data.roomId,
514
- movedata = data.position;
533
+ movedata = data.position,
515
534
  edit = movedata.room_edit,
516
535
  del = movedata.room_delete;
517
536
 
@@ -562,6 +562,7 @@ elation.require(['engine.things.generic', 'janusweb.external.webxr-input-profile
562
562
  lighting: false,
563
563
  opacity: .5,
564
564
  cull_face: 'none',
565
+ billboard: 'y',
565
566
  });
566
567
  this.raycaster = this.createObject('raycaster', {});
567
568
  this.raycaster.addEventListener('raycastenter', (ev) => this.handleRaycastEnter(ev));
@@ -572,6 +573,8 @@ elation.require(['engine.things.generic', 'janusweb.external.webxr-input-profile
572
573
  this.worldToLocal(this.laser.positions[1].copy(endpoint));
573
574
  this.laser.updateLine();
574
575
  this.cursor.pos.copy(endpoint);
576
+ let cursorscale = player.head.distanceTo(endpoint) / 12;
577
+ this.cursor.scale.set(cursorscale, cursorscale, cursorscale);
575
578
  //this.cursor.zdir = normal;
576
579
  if (this.cursor.room !== room._target) room.appendChild(this.cursor);
577
580
  //this.cursor.zdir.copy(player.view_dir).multiplyScalar(-1);
@@ -180,7 +180,7 @@ console.log('[MultiplayerManager] set active room:', room, this.activeroom);
180
180
  dir: (-tmpVecZ.x) + ' ' + (-tmpVecZ.y) + ' ' + (-tmpVecZ.z),
181
181
  up_dir: '0 1 0',
182
182
  //view_dir: this.tmpVecZ.toArray().join(' ')
183
- }
183
+ };
184
184
  if (head) {
185
185
  //this.tmpMat.makeRotationFromQuaternion(head.properties.orientation);
186
186
  tmpMat.copy(head.objects['3d'].matrixWorld);
@@ -230,8 +230,8 @@ console.log('[MultiplayerManager] set active room:', room, this.activeroom);
230
230
  //console.log('[MultiplayerManager] player update', moveData);
231
231
  if (this.avatarNeedsUpdate || player.avatarNeedsUpdate) {
232
232
  moveData.avatar = player.getCurrentAvatarData().replace(/"/g, "^");
233
- this.avatarNeedsUpdate = false
234
- player.avatarNeedsUpdate = false
233
+ this.avatarNeedsUpdate = false;
234
+ player.avatarNeedsUpdate = false;
235
235
  } else if (moveData.avatar) {
236
236
  delete moveData.avatar;
237
237
  }