janusweb 1.5.50 → 1.5.52

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.
@@ -344,6 +344,7 @@ ui-window>.ui_window_content {
344
344
  }
345
345
  ui-window>ui-window-content {
346
346
  order: 1;
347
+ position: relative;
347
348
  }
348
349
  ui-window[scrollable]>ui-window-content {
349
350
  overflow: auto;
@@ -1087,7 +1088,7 @@ ui-treeview ui-list {
1087
1088
  margin: 0 0 0 .3em;
1088
1089
  padding-left: .8em;
1089
1090
  -webkit-user-select: none;
1090
- -webkit-tap-highlight-color: rgba(0,0,0,0);
1091
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
1091
1092
  }
1092
1093
  ui-treeview>ui-list {
1093
1094
  border-left: 0;
@@ -1122,7 +1123,7 @@ ui-treeview ui-treeviewitem>ui-text:hover {
1122
1123
  ui-treeview ui-treeviewitem.state_selected>ui-text {
1123
1124
  color: #0f0;
1124
1125
  }
1125
- ui-treeview ul li.state_selected,
1126
+ ui-treeview ul li.state_selected,
1126
1127
  ui-treeview ul li.state_hover li.state_selected {
1127
1128
  max-height: none;
1128
1129
  }
@@ -1284,3 +1285,93 @@ ui-image-picker canvas {
1284
1285
  display: inline-block;
1285
1286
  vertical-align: top;
1286
1287
  }
1288
+
1289
+ /* <ui-wizard> */
1290
+ ui-wizard {
1291
+ display: flex;
1292
+ flex-direction: column;
1293
+ flex: 1;
1294
+ }
1295
+ ui-wizard[type="paginate"]>ui-wizard-step {
1296
+ display: none;
1297
+ opacity: 0;
1298
+ transition: opacity 500ms linear;
1299
+ flex: 1;
1300
+ }
1301
+ ui-wizard[step=""]>ui-wizard-backbutton,
1302
+ ui-wizard[step="1"]>ui-wizard-backbutton {
1303
+ display: none;
1304
+ }
1305
+ /* Up to 10 steps - wizards with more steps should probably be split up some */
1306
+ ui-wizard[type="paginate"][step=""]>ui-wizard-step:nth-of-type(1),
1307
+ ui-wizard[type="paginate"][step="1"]>ui-wizard-step:nth-of-type(1),
1308
+ ui-wizard[type="paginate"][step="2"]>ui-wizard-step:nth-of-type(2),
1309
+ ui-wizard[type="paginate"][step="3"]>ui-wizard-step:nth-of-type(3),
1310
+ ui-wizard[type="paginate"][step="4"]>ui-wizard-step:nth-of-type(4),
1311
+ ui-wizard[type="paginate"][step="5"]>ui-wizard-step:nth-of-type(5),
1312
+ ui-wizard[type="paginate"][step="6"]>ui-wizard-step:nth-of-type(6),
1313
+ ui-wizard[type="paginate"][step="7"]>ui-wizard-step:nth-of-type(7),
1314
+ ui-wizard[type="paginate"][step="8"]>ui-wizard-step:nth-of-type(8),
1315
+ ui-wizard[type="paginate"][step="9"]>ui-wizard-step:nth-of-type(9),
1316
+ ui-wizard[type="paginate"][step="10"]>ui-wizard-step:nth-of-type(10) {
1317
+ display: flex;
1318
+ opacity: 1;
1319
+ flex: 1;
1320
+ flex-direction: column;
1321
+ }
1322
+ ui-wizard-step>section {
1323
+ padding: 0 .5em 0 .5em;
1324
+ }
1325
+ ui-wizard[type="paginate"] ui-wizard-pagination {
1326
+ display: grid;
1327
+ grid-template-columns: 50% 50%;
1328
+ align-items: center;
1329
+ justify-items: center;
1330
+ }
1331
+ ui-wizard[type="paginate"] ui-wizard-pagination ui-button.back {
1332
+ grid-column-start: 1;
1333
+ }
1334
+ ui-wizard[type="paginate"] ui-wizard-pagination ui-button.next {
1335
+ grid-column-start: 2;
1336
+ }
1337
+ ui-wizard-navigation {
1338
+ display: flex;
1339
+ flex-direction: row;
1340
+ }
1341
+ ui-wizard-navigation ui-buttonbar {
1342
+ width: 100%;
1343
+ }
1344
+ ui-wizard-navigation ui-buttonbar ui-button {
1345
+ margin: 0;
1346
+ position: relative;
1347
+ clip-path: polygon(0 0, 120% 0%, 120% 100%, 0 100%, 1lh 50%);
1348
+ padding-left: 1lh;
1349
+ }
1350
+ ui-wizard-navigation ui-buttonbar ui-button:first-child {
1351
+ clip-path: none;
1352
+ border-radius: 0;
1353
+ }
1354
+ ui-wizard-navigation ui-buttonbar ui-button::after {
1355
+ width:0;
1356
+ height: 0;
1357
+ content: '';
1358
+ display: block;
1359
+ position: absolute;
1360
+ right: calc(-1lh + 1px);
1361
+ border-top: 1lh solid transparent;
1362
+ border-bottom: 1lh solid transparent;
1363
+ border-left: 1lh solid var(--logo-green);
1364
+ top: 0;
1365
+ }
1366
+ ui-wizard-navigation ui-buttonbar ui-button:last-child::after {
1367
+ display: none;
1368
+ }
1369
+ ui-wizard-navigation ui-buttonbar ui-button[disabled]::after {
1370
+ border-left: 1lh solid #666;
1371
+ }
1372
+ ui-wizard-navigation ui-buttonbar ui-button.state_active {
1373
+ background: white;
1374
+ }
1375
+ ui-wizard-navigation ui-buttonbar ui-button.state_active::after {
1376
+ border-left: 1lh solid white;
1377
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "janusweb",
3
3
  "description": "Web client for JanusVR worlds",
4
- "version": "1.5.50",
4
+ "version": "1.5.52",
5
5
  "main": "scripts/janusweb.js",
6
6
  "author": "James Baicoianu",
7
7
  "license": "MIT",
package/scripts/client.js CHANGED
@@ -12,6 +12,7 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
12
12
  var corsproxy = elation.utils.any(args.corsproxy && args.corsproxy != 'false', elation.config.get('engine.assets.corsproxy'), document.location.href);
13
13
  var container = elation.utils.any(args.container, document.body);
14
14
  var fullsize = elation.utils.any(args.fullsize && args.fullsize != 'false', container == document.body);
15
+ var thirdperson = elation.utils.any(args.thirdperson && args.thirdperson != 'false', false);
15
16
 
16
17
  if (elation.config.get('serviceworker.enabled') && 'serviceWorker' in navigator) {
17
18
  var workerscript = elation.config.get('serviceworker.script', 'service-worker.js');
@@ -83,6 +84,7 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
83
84
  tracking: usetracking,
84
85
  trackingid: trackingid,
85
86
  avatarsrc: args.avatarsrc,
87
+ thirdperson: thirdperson,
86
88
  });
87
89
  return new Promise(function(resolve, reject) {
88
90
  elation.events.add(janusweb.engine, 'engine_start', function() { resolve(janusweb); });
@@ -106,6 +108,8 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
106
108
  server: { type: 'string' },
107
109
  avatarsrc: { type: 'string' },
108
110
  muted: { type: 'boolean', default: false },
111
+ thirdperson: { type: 'boolean', default: false },
112
+ autofullscreen: { type: 'boolean', default: false },
109
113
  });
110
114
  }
111
115
  initEngine() {
@@ -139,11 +143,13 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
139
143
  window.scrollTo(0, 1);
140
144
  });
141
145
  window.addEventListener('touchend', ev => {
142
- // FIXME - useragent hack isn't the best way of handling this, but it beats getting stuck in non-immersive fullscreen mode while in a VR headset
143
- if (navigator.userAgent.indexOf('OculusBrowser') != -1) {
144
- this.startXR();
145
- } else if (!this.view.isFullscreen()) {
146
- this.toggleFullscreen({value: 1});
146
+ if (ev.target == this.engine.systems.render.renderer.domElement) {
147
+ // FIXME - useragent hack isn't the best way of handling this, but it beats getting stuck in non-immersive fullscreen mode while in a VR headset
148
+ if (navigator.userAgent.indexOf('OculusBrowser') != -1) {
149
+ this.startXR();
150
+ } else if (this.autofullscreen && !this.view.isFullscreen()) {
151
+ this.toggleFullscreen({value: 1});
152
+ }
147
153
  }
148
154
  });
149
155
  }
@@ -192,6 +198,7 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
192
198
  avatarsrc: this.avatarsrc,
193
199
  staticfriction: 2,
194
200
  dynamicfriction: 1.9,
201
+ cameraview: (this.thirdperson ? 'thirdperson' : 'firstperson'),
195
202
  });
196
203
  elation.events.add(this.engine.systems.render, 'render_view_add', (ev) => this.handleRenderViewAdd(ev));
197
204
 
@@ -266,13 +273,20 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
266
273
  var frame = elation.ui.iframe({src: 'http://github.com/jbaicoianu/janusweb/', classname: 'janusweb_about'});
267
274
  aboutwin.setcontent(frame);
268
275
  }
276
+ isFullscreen() {
277
+ return document.fullscreenElement === this;
278
+ }
269
279
  toggleFullscreen(ev, updateOnly) {
270
- var view = this.view;
271
- if (!updateOnly && view && (typeof ev == 'undefined' || ev.value == 1 || typeof ev.value == 'undefined')) {
272
- view.toggleFullscreen();
280
+ let isfullscreen = this.isFullscreen();
281
+ if (!updateOnly && (typeof ev == 'undefined' || ev.value == 1 || typeof ev.value == 'undefined')) {
282
+ if (!isfullscreen) {
283
+ this.parentNode.requestFullscreen();
284
+ } else {
285
+ document.exitFullscreen();
286
+ }
273
287
  }
274
288
  if (this.fullscreenbutton) {
275
- if (view.isFullscreen()) {
289
+ if (isfullscreen) {
276
290
  this.fullscreenbutton.addclass('state_fullscreen');
277
291
  this.fullscreenbutton.setLabel('Shrink');
278
292
  } else {
@@ -331,6 +345,7 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
331
345
  uiconfig: { type: 'string', default: false },
332
346
  showui: { type: 'boolean', default: true },
333
347
  shownavigation: { type: 'boolean', default: true },
348
+ thirdperson: { type: 'boolean', default: false },
334
349
  });
335
350
  }
336
351
  create() {
@@ -357,13 +372,14 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
357
372
  trackingid: this.trackingid,
358
373
  networking: this.networking,
359
374
  corsproxy: this.corsproxy,
360
- //resolution: width + 'x' + height,
375
+ resolution: width + 'x' + height,
361
376
  showui: this.showui && this.showui != 'false',
362
377
  shownavigation: this.shownavigation,
363
378
  avatarsrc: this.avatarsrc,
364
379
  uiconfig: this.uiconfig,
365
380
  container: this,
366
381
  fullsize: this.fullsize,
382
+ thirdperson: this.thirdperson && this.thirdperson != 'false',
367
383
  };
368
384
  return args;
369
385
  }
@@ -474,8 +490,13 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
474
490
  elation.elements.define('janus.overlay', class extends elation.elements.base {
475
491
  init() {
476
492
  super.init();
477
- elation.events.add(this.player, 'player_enable', ev => { this.hide(); });
478
- elation.events.add(this.player, 'player_disable', ev => { this.show(); });
493
+ this.defineAttributes({
494
+ autotoggle: { type: 'bool', default: false }
495
+ });
496
+ if (this.autotoggle) {
497
+ elation.events.add(this.player, 'player_enable', ev => { this.hide(); });
498
+ elation.events.add(this.player, 'player_disable', ev => { this.show(); });
499
+ }
479
500
  }
480
501
  show() {
481
502
  super.show();
@@ -484,15 +505,17 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
484
505
  }
485
506
  elation.events.fire({type: 'overlay_show', element: this});
486
507
  }
487
- hide() {
508
+ hide(remove=true) {
488
509
  super.hide();
489
510
  elation.events.fire({type: 'overlay_hide', element: this});
490
- setTimeout(() => {
491
- if (this.parentNode) {
492
- this.oldparent = this.parentNode;
493
- this.parentNode.removeChild(this);
494
- }
495
- }, 1000);
511
+ if (remove) {
512
+ setTimeout(() => {
513
+ if (this.parentNode) {
514
+ this.oldparent = this.parentNode;
515
+ this.parentNode.removeChild(this);
516
+ }
517
+ }, 1000);
518
+ }
496
519
  }
497
520
  });
498
521
  }
@@ -32,7 +32,7 @@ elation.require(['janusweb.janusbase'], function() {
32
32
  if (!this.geometry) {
33
33
  let geo = new THREE.BufferGeometry();
34
34
  let lineobj = new THREE.LineSegments(geo, new THREE.LineBasicMaterial({
35
- vertexColors: THREE.VertexColors,
35
+ vertexColors: true,
36
36
  opacity: this.opacity,
37
37
  transparent: (this.transparent !== null ? this.transparent : this.opacity < 1),
38
38
  depthWrite: this.depth_write,
@@ -320,6 +320,7 @@ JanusClientConnection.prototype.connect = function() {
320
320
  this.error = '';
321
321
  this._websocket = new WebSocket(this._host, 'binary');
322
322
  this.status = 1;
323
+ this.active = false;
323
324
  this.loggedin = false;
324
325
  this.loggingin = false;
325
326
  this.msgQueue = [];
@@ -336,7 +337,7 @@ JanusClientConnection.prototype.connect = function() {
336
337
  this._websocket.onclose = function() {
337
338
  this.status = 0;
338
339
  this.dispatchEvent({type: 'disconnect'});
339
- if (!this.pendingReconnect) {
340
+ if (this.active) {
340
341
  this.reconnect();
341
342
  }
342
343
  }.bind(this);
@@ -354,6 +355,8 @@ JanusClientConnection.prototype.reconnect = function(force) {
354
355
  console.log('Reconnecting...');
355
356
  this.connect();
356
357
  }
358
+ } else {
359
+ console.log('reconnect attempted too soon', this.lastattempt, now, this.reconnectdelay);
357
360
  }
358
361
  }
359
362
  JanusClientConnection.prototype.disconnect = function() {
@@ -392,7 +395,7 @@ JanusClientConnection.prototype.setUserId = function(userId) {
392
395
  };
393
396
 
394
397
  JanusClientConnection.prototype.send = function(msg) {
395
- if (this._websocket.readyState == 3) {
398
+ if (this._websocket.readyState > 1) {
396
399
  this.msgQueue.push(msg);
397
400
  if (!this.pendingReconnect) {
398
401
  this.reconnect();
@@ -84,6 +84,7 @@ JanusFireboxParser.prototype.parseAssets = function(xml, baseurl, datapath) {
84
84
  reverse3d: n.reverse3d,
85
85
  tex_linear: n.tex_linear,
86
86
  equi: n.equi,
87
+ srgb: n.srgb,
87
88
  });
88
89
  });
89
90
  videoassets.forEach(function(n) {
@@ -370,7 +370,8 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
370
370
  visible: ['property', 'visible'],
371
371
  //tagName: ['property', 'tag'],
372
372
  billboard: ['property', 'billboard'],
373
- className: ['property', 'className'],
373
+ 'class': ['property', 'className'],
374
+ classname: ['property', 'className'],
374
375
  classList: ['property', 'classList'],
375
376
  gazetime: ['property', 'gazetime'],
376
377
  layers: ['property', 'layers'],
@@ -1410,6 +1411,12 @@ console.log('clone', props);
1410
1411
  roomproxy.appendChild(objproxy);
1411
1412
  }
1412
1413
  this.start();
1414
+ } else if (!newroom && !ischild) {
1415
+ let oldroomproxy = (oldroom._target ? oldroom : oldroom.getProxyObject()),
1416
+ objproxy = (this._target ? this : this.getProxyObject());
1417
+ if (oldroomproxy.contains(objproxy)) {
1418
+ oldroomproxy.removeChild(objproxy);
1419
+ }
1413
1420
  }
1414
1421
  }
1415
1422
  }
@@ -293,22 +293,10 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
293
293
  if (pos) this.body.pos = pos;
294
294
  this.body.start();
295
295
  if (scale && this.body) this.body.scale.fromArray(scale);
296
-
297
- elation.events.add(this, 'load', ev => {
298
- if (this.body.modelasset) {
299
- if (this.body.modelasset.loaded) {
300
- this.loadAnimations();
301
- if (this.animation_extras) {
302
- this.loadAnimationExtras();
303
- }
304
- } else {
305
- elation.events.add(this.body.modelasset, 'asset_load_complete', () => {
306
- this.loadAnimations();
307
- if (this.animation_extras) {
308
- this.loadAnimationExtras();
309
- }
310
- });
311
- }
296
+ elation.events.add(this.body.modelasset, 'asset_load', ev => {
297
+ this.loadAnimations();
298
+ if (this.animation_extras) {
299
+ this.loadAnimationExtras();
312
300
  }
313
301
  // FIXME - this prevents avatars from being culled, which prevents our default mesh from disappearing but also means we lose out on possible performance optimizations in rooms with lots of avatars
314
302
  this.objects['3d'].traverse(n => {
@@ -419,7 +407,7 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
419
407
  //newclip = THREE.SkeletonUtils.retargetClip(destmesh, sourcemesh, newclip, {useFirstFramePosition: true});
420
408
  //console.log('retarget it!', newclip, destmesh, sourcemesh);
421
409
  newclip.tracks.forEach(track => {
422
- let [name, property] = track.name.split('.');
410
+ let [name, property] = track.name.replace('mixamorig:', '').split('.');
423
411
  let srcbone = sourcemesh.skeleton.getBoneByName(name);
424
412
  let dstbone = destmesh.skeleton.getBoneByName(name);
425
413
  if (dstbone) {
@@ -717,15 +705,17 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
717
705
  }
718
706
  }
719
707
  }
720
- this.body.addEventListener('load', ev => {
721
- for (let i = 0; i < potentialAttachments.length; i++) {
722
- let obj = potentialAttachments[i];
723
- if (obj.js_id in this.body.parts) {
724
- this.body.parts[obj.js_id].add(obj);
725
- this.applyAvatarMaterial(obj, 3);
708
+ if (this.body) {
709
+ this.body.addEventListener('load', ev => {
710
+ for (let i = 0; i < potentialAttachments.length; i++) {
711
+ let obj = potentialAttachments[i];
712
+ if (obj.js_id in this.body.parts) {
713
+ this.body.parts[obj.js_id].add(obj);
714
+ this.applyAvatarMaterial(obj, 3);
715
+ }
726
716
  }
727
- }
728
- });
717
+ });
718
+ }
729
719
  }
730
720
  }
731
721
  }
@@ -7,7 +7,7 @@ elation.require(['janusweb.janusbase'], function() {
7
7
  light_directional: { type: 'bool', default: false, set: this.updateLight },
8
8
  light_range: { type: 'float', default: 0, set: this.updateLight, min: 0, comment: 'Max distance at which light can affect objects' },
9
9
  light_intensity: { type: 'float', default: 10, set: this.updateLight, comment: 'Light brightness' },
10
- light_cone_angle: { type: 'float', default: 0, set: this.updateLight, min: 0, max: 1, comment: 'Light cone shape. 0 = directional, 1 = point light, anything inbetween is a spotlight' },
10
+ light_cone_angle: { type: 'float', default: 0, set: this.updateLight, min: 0, max: 1, comment: 'Light cone shape. 0 = point light, 1 = directional, anything inbetween is a spotlight' },
11
11
  light_cone_exponent: { type: 'float', default: 1, set: this.updateLight },
12
12
  light_penumbra: { type: 'float', default: 1, set: this.updateLight, min: 0, max: 1, comment: 'Spotlight fall-off. 0 is crisp, 1 is smooth' },
13
13
  light_decay: { type: 'float', default: 2, set: this.updateLight, comment: 'The amount the light dims along the distance of the light. Default is 1. For physically correct lighting, set this to 2.' },
@@ -17,6 +17,7 @@ elation.require(['janusweb.janusbase'], function() {
17
17
  light_shadow_far: { type: 'float', set: this.updateLight },
18
18
  light_shadow_bias: { type: 'float', default: .0001, set: this.updateLight },
19
19
  light_shadow_radius: { type: 'float', default: 2.5, set: this.updateLight },
20
+ light_shadow_size: { type: 'int', default: 512, set: this.updateLight },
20
21
  light_helper: { type: 'boolean', default: false, set: this.updateLightHelper },
21
22
  light_style: { type: 'string', default: '' },
22
23
  light_style_fps: { type: 'float', default: 10 },
@@ -196,6 +197,7 @@ elation.require(['janusweb.janusbase'], function() {
196
197
  this.light.shadow.camera.fov = 90;
197
198
  this.light.shadow.mapSize.set(shadowSize, shadowSize);
198
199
  this.light.shadow.bias = this.light_shadow_bias;
200
+ this.light.shadow.mapSize.set(this.light_shadow_size, this.light_shadow_size);
199
201
 
200
202
  // directional light shadow parameters
201
203
  let d = this.light_range;
@@ -256,6 +258,7 @@ elation.require(['janusweb.janusbase'], function() {
256
258
  light_shadow_far: [ 'property', 'light_shadow_far'],
257
259
  light_shadow_bias: [ 'property', 'light_shadow_bias'],
258
260
  light_shadow_radius: [ 'property', 'light_shadow_radius'],
261
+ light_shadow_size: [ 'property', 'light_shadow_size'],
259
262
  color_temperature: [ 'property', 'color_temperature'],
260
263
  };
261
264
  }
@@ -420,6 +420,7 @@ elation.require(['janusweb.janusbase'], function() {
420
420
  pointpos.add(this.emitter_pos);
421
421
 
422
422
  point.opacity = this.opacity;
423
+ point.active = 0;
423
424
 
424
425
  var vel = point.vel,
425
426
  accel = point.accel,
@@ -37,6 +37,7 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
37
37
  avatarsrc: { type: 'string' },
38
38
  cameraview: { type: 'string', default: 'firstperson' },
39
39
  camerazoom: { type: 'float', default: 0 },
40
+ cameraheight: { type: 'float', default: 0 },
40
41
  cameraangle: { type: 'float', default: 0 },
41
42
  decouplehead: { type: 'boolean', default: false },
42
43
  });
@@ -148,12 +149,19 @@ document.body.dispatchEvent(click);
148
149
  this.getAvatarData().then(d => this.currentavatar = d);
149
150
  this.morphtargetchanges = {};
150
151
  this.eventlistenerproxies = {};
152
+
153
+ if (this.cameraview == 'thirdperson') {
154
+ this.camerazoom = 2;
155
+ this.cameraheight = .25;
156
+ }
157
+ this.updateCamera();
158
+ this.handleFrameUpdates = elation.bind(this, this.handleFrameUpdates);
151
159
  }
152
160
  this.createChildren = function() {
153
161
  elation.engine.things.janusplayer.extendclass.createChildren.call(this);
154
162
 
155
- this.cursor = new THREE.Sprite(new THREE.SpriteMaterial({color: 0xffffff, depthTest: false, depthWrite: false, transparent: true, map: null, fog: false}));
156
- this.cursor.renderOrder = 100;
163
+ this.cursor = new THREE.Sprite(new THREE.SpriteMaterial({color: 0xffffff, depthTest: false, depthWrite: false, transparent: true, map: null, fog: false, transparent: true}));
164
+ this.cursor.renderOrder = 500;
157
165
  this.engine.systems.world.scene['world-3d'].add(this.cursor);
158
166
 
159
167
 
@@ -169,6 +177,7 @@ document.body.dispatchEvent(click);
169
177
  }
170
178
  });
171
179
 
180
+ this.updateCamera();
172
181
  this.updateCollider();
173
182
  }
174
183
  this.enable = function() {
@@ -307,7 +316,7 @@ document.body.dispatchEvent(click);
307
316
  this.ghost.setHeadOrientation(_tmpquat.multiplyQuaternions(this.neck.orientation._target, this.head.orientation._target), true);
308
317
  if (this.ghost._target.head) {
309
318
  //this.ghost._target.face.position.copy(this.head.position);
310
- this.ghost.head.orientation.copy(this.head.orientation).multiply(this.neck.orientation);;
319
+ this.ghost._target.head.orientation.copy(this.head.orientation).multiply(this.neck.orientation);;
311
320
  }
312
321
  }
313
322
  }
@@ -643,11 +652,13 @@ document.body.dispatchEvent(click);
643
652
  hand1_p3: ['property', 'hands.right.p3'],
644
653
  hand1_p4: ['property', 'hands.right.p4'],
645
654
  url: ['property', 'parent.currentroom.url'],
655
+ ghost: ['property', 'ghost'],
646
656
 
647
657
  collision_radius: ['property', 'collision_radius'],
648
658
 
649
659
  currentavatar: ['property', 'currentavatar'],
650
660
  defaultanimation: ['property', 'defaultanimation'],
661
+ eventlistenerproxies: ['property', 'eventlistenerproxies'],
651
662
 
652
663
  localToWorld: ['function', 'localToWorld'],
653
664
  worldToLocal: ['function', 'worldToLocal'],
@@ -735,12 +746,12 @@ document.body.dispatchEvent(click);
735
746
 
736
747
  if (this.jumping) {
737
748
  animid = 'jump';
738
- } else if (this.controlstate.move_left) {
739
- animid = (running ? 'run' : 'walk_left');
740
- } else if (this.controlstate.move_right) {
741
- animid = (running ? 'run' : 'walk_right');
749
+ } else if (this.controlstate.move_left && Math.abs(this.controlstate.move_left) > .15) {
750
+ animid = (running ? 'run' : (this.controlstate.move_left > 0 ? 'walk_left' : 'walk_right'));
751
+ } else if (this.controlstate.move_right && Math.abs(this.controlstate.move_right) > .15) {
752
+ animid = (running ? 'run' : (this.controlstate.move_right > 0 ? 'walk_right' : 'walk_left'));
742
753
  } else if (this.controlstate.move_forward) {
743
- animid = (running ? 'run' : 'walk');
754
+ animid = (running ? 'run' : (this.controlstate.move_forward > 0 ? 'walk' : 'walk_back'));
744
755
  } else if (this.controlstate.move_backward) {
745
756
  animid = (running ? 'run' : 'walk_back');
746
757
  } else if (document.activeElement && this.properties.janus.chat && document.activeElement === this.properties.janus.chat.input.inputelement) {
@@ -1109,9 +1120,6 @@ document.body.dispatchEvent(click);
1109
1120
  }
1110
1121
  };
1111
1122
  })();
1112
- this.dispatchEvent = function(event, target) {
1113
- let firedev = elation.events.fire(event);
1114
- }
1115
1123
  this.lookAt = function(other, up, turnhead) {
1116
1124
  if (!up) up = new THREE.Vector3(0,1,0);
1117
1125
  if (!other) return;
@@ -1224,17 +1232,25 @@ document.body.dispatchEvent(click);
1224
1232
  this.toggleCamera = function(ev) {
1225
1233
  if (ev.value == 1) {
1226
1234
  if (this.cameraview == 'firstperson') {
1227
- this.cameraview = 'thirdperson';
1228
- this.cameraangle = 0;
1229
- this.camerazoom = 2;
1235
+ this.setCameraView('thirdperson');
1230
1236
  } else {
1231
- this.cameraview = 'firstperson';
1232
- this.cameraangle = 0;
1233
- this.camerazoom = 0;
1237
+ this.setCameraView('firstperson');
1234
1238
  }
1235
- this.updateCamera();
1236
1239
  }
1237
1240
  }
1241
+ this.setCameraView = function(cameraview) {
1242
+ this.cameraview = cameraview;
1243
+ if (this.cameraview == 'thirdperson') {
1244
+ this.cameraangle = 0;
1245
+ this.camerazoom = 2;
1246
+ this.cameraheight = .25;
1247
+ } else if (this.cameraview == 'firstperson') {
1248
+ this.cameraangle = 0;
1249
+ this.camerazoom = 0;
1250
+ this.cameraheight = 0;
1251
+ }
1252
+ this.updateCamera();
1253
+ }
1238
1254
  this.zoomView = function(amount, ev) {
1239
1255
  if (this.cameraview == 'thirdperson') {
1240
1256
  //this.camera.position.z -= amount / 10;
@@ -1253,6 +1269,7 @@ document.body.dispatchEvent(click);
1253
1269
  this.camera.fov = this.fov;
1254
1270
  this.camera.position.z = Math.cos(this.cameraangle) * this.camerazoom;
1255
1271
  this.camera.position.x = Math.sin(this.cameraangle) * this.camerazoom;
1272
+ this.camera.position.y = this.cameraheight;
1256
1273
  this.camera.orientation.setFromEuler(new THREE.Euler(0, this.cameraangle, 0));
1257
1274
  }
1258
1275
  }
@@ -1295,8 +1312,9 @@ document.body.dispatchEvent(click);
1295
1312
  let returnValue = true;
1296
1313
  firedev.forEach(e => returnValue &= e.returnValue);
1297
1314
  if (event.bubbles !== false && returnValue && this.parent && this.parent.dispatchEvent) {
1298
- event.element = this.parent;
1299
- this.parent.dispatchEvent(event);
1315
+ let ev = elation.events.clone(event);
1316
+ ev.element = this.parent;
1317
+ this.parent.dispatchEvent(ev);
1300
1318
  }
1301
1319
  }
1302
1320
  this.addEventListenerProxy = function(name, handler, bubble) {
@@ -1327,5 +1345,14 @@ document.body.dispatchEvent(click);
1327
1345
  }
1328
1346
  }
1329
1347
  }
1348
+ this.attachObject = function(attachpoint, obj) {
1349
+ if (this.ghost && this.ghost.body) {
1350
+ if (attachpoint in this.ghost.body.parts) {
1351
+ this.ghost.body.parts[attachpoint].add(obj);
1352
+ }
1353
+ return obj;
1354
+ }
1355
+ return false;
1356
+ }
1330
1357
  }, elation.engine.things.player);
1331
1358
  });
@@ -156,6 +156,7 @@ console.log('[MultiplayerManager] set active room:', room, this.activeroom);
156
156
  var oldserver = this.getServerForRoom(this.activeroom);
157
157
  //oldserver.leave_room(room.url);
158
158
  oldserver.unsubscribe(room.url);
159
+ oldserver.active = false;
159
160
  }
160
161
 
161
162
  // Tell the server we're now in the new room
@@ -165,6 +166,7 @@ console.log('[MultiplayerManager] set active room:', room, this.activeroom);
165
166
  var partymode = this.player.party_mode && room.party_mode;
166
167
  server.subscribe(room.url);
167
168
  server.enter_room(room.url, partymode);
169
+ server.active = true;
168
170
  }
169
171
  }
170
172
  this.getJanusOrientation = (function() {
package/scripts/object.js CHANGED
@@ -109,7 +109,7 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
109
109
  object = this.object;
110
110
  setTimeout(() => { this.handleLoad(); this.assignTextures(); }, 100);
111
111
  } else if (this.janusid) {
112
- var asset = this.getAsset('model', this.janusid, true);
112
+ var asset = this.modelasset = this.getAsset('model', this.janusid, true);
113
113
  this.dispatchEvent({type: 'loadstart'});
114
114
  if (asset) {
115
115
  if (asset.loaded) {
@@ -1140,7 +1140,7 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
1140
1140
  }
1141
1141
  }
1142
1142
  this.isUsingPBR = function() {
1143
- return this.lighting && elation.utils.any(this.room.pbr, elation.config.get('janusweb.materials.pbr'));
1143
+ return this.lighting && elation.utils.any(this.room && this.room.pbr, elation.config.get('janusweb.materials.pbr'));
1144
1144
  }
1145
1145
  this.isUsingToonShader = function() {
1146
1146
  return this.lighting && elation.utils.any(this.room.toon, elation.config.get('janusweb.materials.toon'));
package/scripts/parts.js CHANGED
@@ -27,7 +27,7 @@ elation.require([], function() {
27
27
  if (!this._proxies[name]) {
28
28
  var rootobject = this._object._target || this._object;
29
29
  //console.log('replace the part', name, part.rotation, part.parent, part);
30
- this._parts[name] = elation.engine.things.janusobject({
30
+ let newpart = this._parts[name] = elation.engine.things.janusobject({
31
31
  type: 'janusobject',
32
32
  id: rootobject.id + '_parts_' + name,
33
33
  name: name,
@@ -35,10 +35,14 @@ elation.require([], function() {
35
35
  engine: this._object.engine,
36
36
  properties: {
37
37
  object: object,
38
+ parent: this._object,
38
39
  rotation: [object.rotation.x * THREE.MathUtils.RAD2DEG, object.rotation.y * THREE.MathUtils.RAD2DEG, object.rotation.z * THREE.MathUtils.RAD2DEG],
39
40
  room: rootobject.room
40
41
  }
41
42
  });
43
+ if (this._object.colliders && newpart.colliders) {
44
+ this._object.colliders.add(newpart.colliders);
45
+ }
42
46
  // TODO - set up object hierarchy here
43
47
  this._proxies[name] = this._parts[name].getProxyObject();
44
48
  this._proxies[name].start();