janusweb 1.5.29 → 1.5.33

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 (60) hide show
  1. package/LICENSE +1 -1
  2. package/media/assets/janus-avatar-animations.glb +0 -0
  3. package/media/assets/janus-avatar-base.glb +0 -0
  4. package/media/assets/webui/apps/avatar/avatar.css +6 -2
  5. package/media/assets/webui/apps/avatar/avatar.js +97 -10
  6. package/media/assets/webui/apps/buttons/buttons.html +2 -2
  7. package/media/assets/webui/apps/buttons/buttons.js +3 -3
  8. package/media/assets/webui/apps/comms/comms.js +7 -4
  9. package/media/assets/webui/apps/comms/voip.js +138 -55
  10. package/media/assets/webui/apps/editor/editor.js +2 -0
  11. package/media/assets/webui/apps/inventory/inventory.html +7 -4
  12. package/media/assets/webui/apps/inventory/inventory.js +1 -1
  13. package/media/assets/webui/apps/locomotion/teleporter.js +9 -8
  14. package/media/assets/webui/apps/settings/settings.html +1 -1
  15. package/media/assets/webui/apps/virtualgamepad/virtualgamepad.js +9 -7
  16. package/media/assets/webui/apps/xrmenu/xrmenu.js +13 -4
  17. package/media/assets/webui/none.json +1 -0
  18. package/media/assets.json +2 -1
  19. package/media/index.html +1 -1
  20. package/media/lib/draco/README.md +32 -0
  21. package/media/lib/draco/draco_decoder.js +52 -0
  22. package/media/lib/draco/draco_decoder.wasm +0 -0
  23. package/media/lib/draco/draco_encoder.js +33 -0
  24. package/media/lib/draco/draco_wasm_wrapper.js +104 -0
  25. package/media/lib/draco/gltf/draco_decoder.js +48 -0
  26. package/media/lib/draco/gltf/draco_decoder.wasm +0 -0
  27. package/media/lib/draco/gltf/draco_encoder.js +33 -0
  28. package/media/lib/draco/gltf/draco_wasm_wrapper.js +104 -0
  29. package/media/lib/physx/physx.release.js +21 -0
  30. package/media/lib/physx/physx.release.wasm +0 -0
  31. package/media/manifest.json +5 -5
  32. package/media/service-worker.js +7 -0
  33. package/package.json +1 -1
  34. package/scripts/client.js +4 -3
  35. package/scripts/config.js +2 -0
  36. package/scripts/elements/linesegments.js +5 -1
  37. package/scripts/external/JanusFireboxParser.js +1 -0
  38. package/scripts/image.js +7 -1
  39. package/scripts/janusbase.js +83 -34
  40. package/scripts/janusghost.js +314 -15
  41. package/scripts/januslight.js +11 -2
  42. package/scripts/janusparagraph.js +3 -3
  43. package/scripts/janusparticle.js +16 -5
  44. package/scripts/janusplayer.js +124 -35
  45. package/scripts/janusweb.js +5 -0
  46. package/scripts/janusxrplayer.js +2 -3
  47. package/scripts/multiplayermanager.js +3 -1
  48. package/scripts/object.js +106 -10
  49. package/scripts/portal.js +28 -12
  50. package/scripts/remoteplayer.js +1 -25
  51. package/scripts/room.js +116 -36
  52. package/scripts/sound.js +8 -5
  53. package/scripts/text.js +3 -3
  54. package/scripts/websurface.js +6 -1
  55. package/utils/build.sh +3 -0
  56. package/utils/init.sh +2 -2
  57. package/scripts/chat.js +0 -80
  58. package/scripts/ui.js +0 -265
  59. package/scripts/urlbar.js +0 -93
  60. package/templates/janusweb.tpl +0 -3
@@ -66,15 +66,15 @@ elation.require(['janusweb.janusbase'], function() {
66
66
  if (!this.canvas || !this.texture) return;
67
67
  var ctx = this.canvas.getContext('2d'),
68
68
  texture = this.texture;
69
- this.canvas.width = 512;
70
- this.canvas.height = 512;
69
+ this.canvas.width = 1024;
70
+ this.canvas.height = 1024;
71
71
  var text_col = '#' + this.text_col.getHexString(),
72
72
  back_col = 'rgba(' + (this.back_col.r * 255) + ', ' + (this.back_col.g * 255) + ', ' + (this.back_col.b * 255) + ', ' + this.back_alpha + ')';
73
73
  var basestyle = 'font-family: sans-serif;' +
74
74
  'font-size: ' + this.font_size + 'px;' +
75
75
  'color: ' + text_col + ';' +
76
76
  'background: ' + back_col + ';' +
77
- 'max-width: 502px;' +
77
+ 'max-width: 1014px;' +
78
78
  'padding: 5px;';
79
79
 
80
80
  // We need to sanitize our HTML in case someone provides us with malformed markup.
@@ -67,6 +67,7 @@ elation.require(['janusweb.janusbase'], function() {
67
67
  this.collidable = false;
68
68
  this.boundingRadiusSq = 0;
69
69
  this.boundingSphereWorld = new THREE.Sphere();
70
+ this.furthestPoint = new THREE.Vector3();
70
71
  this.lastrefresh = 0;
71
72
  this.updateParticles = elation.bind(this, this.updateParticles); // FIXME - hack, this should happen at the lower level of all components
72
73
  }
@@ -324,11 +325,19 @@ elation.require(['janusweb.janusbase'], function() {
324
325
  // We also rate limit here, so if nothing else in the scene is changing, we
325
326
  // render at a lower fps
326
327
  this.localToWorld(this.boundingSphereWorld.center.set(0,0,0));
327
- if (!this.objects['3d'].geometry.boundingSphere) {
328
- this.objects['3d'].geometry.computeBoundingSphere();
328
+ let geo = this.objects['3d'].geometry;
329
+ if (!geo.boundingSphere) {
330
+ geo.computeBoundingSphere();
331
+ } else {
332
+ let currentBoundingRadius = geo.boundingSphere.radius
333
+ if (this.boundingRadiusSq > currentBoundingRadius * currentBoundingRadius) {
334
+ geo.boundingSphere.radius = Math.sqrt(this.boundingRadiusSq) + .1;
335
+ }
329
336
  }
330
- this.boundingSphereWorld.radius = this.objects['3d'].geometry.boundingSphere.radius;
337
+
338
+ this.boundingSphereWorld.radius = geo.boundingSphere.radius;
331
339
  if (player.viewfrustum.intersectsSphere(this.boundingSphereWorld) && now - this.lastrefresh > (1000 / this.refreshrate)) {
340
+
332
341
  this.refresh();
333
342
  this.lastrefresh = now;
334
343
  }
@@ -341,11 +350,14 @@ elation.require(['janusweb.janusbase'], function() {
341
350
  var lengthSq = vec.lengthSq();
342
351
  if (lengthSq > this.boundingRadiusSq) {
343
352
  this.boundingRadiusSq = lengthSq;
353
+ this.furthestPoint.copy(vec);
354
+ /*
344
355
  var geo = this.objects['3d'].geometry;
345
356
  if (!geo.boundingSphere) {
346
357
  geo.boundingSphere = new THREE.Sphere();
347
358
  }
348
359
  geo.boundingSphere.radius = Math.sqrt(lengthSq);
360
+ */
349
361
  }
350
362
  }
351
363
  }
@@ -461,8 +473,7 @@ elation.require(['janusweb.janusbase'], function() {
461
473
  mesh.traverse(function(n) {
462
474
  if (n && n.geometry) {
463
475
  var geo = n.geometry;
464
- if (geo instanceof THREE.Geometry) {
465
- } else if (geo instanceof THREE.BufferGeometry) {
476
+ if (geo instanceof THREE.BufferGeometry) {
466
477
  var positions = geo.attributes.position.array;
467
478
  for (var i = 0; i < positions.length; i += 3) {
468
479
  vertices.push(new THREE.Vector3(positions[i] * scale.x, positions[i+1] * scale.y, positions[i+2] * scale.z));
@@ -2,7 +2,18 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
2
2
  elation.requireCSS('janusweb.janusplayer');
3
3
 
4
4
  elation.component.add('engine.things.janusplayer', function() {
5
- this.defaultavatar = '<FireBoxRoom>\n <Assets>\n <AssetObject id="screen" src="https://web.janusxr.org/media/assets/hoverscreen.obj" mtl="https://web.janusxr.org/media/assets/hoverscreen.mtl" />\n </Assets>\n <Room>\n <Ghost id="januswebuser" col="#ffffff" lighting="true" head_pos="0 1.4 0" body_id="" eye_pos="0 1.6 0" userid_pos="0 0.5 0" cull_face="back" screen_name="screen_Cube.004">\n <Object id="screen" js_id="head" />\n </Ghost>\n </Room>\n</FireBoxRoom>'
5
+ //this.defaultavatar = '<FireBoxRoom>\n <Assets>\n <AssetObject id="screen" src="https://web.janusxr.org/media/assets/hoverscreen.obj" mtl="https://web.janusxr.org/media/assets/hoverscreen.mtl" />\n </Assets>\n <Room>\n <Ghost id="januswebuser" col="#ffffff" lighting="true" head_pos="0 1.4 0" body_id="" eye_pos="0 1.6 0" userid_pos="0 0.5 0" cull_face="back" screen_name="screen_Cube.004">\n <Object id="screen" js_id="head" />\n </Ghost>\n </Room>\n</FireBoxRoom>'
6
+ this.defaultavatar = `
7
+ <FireBoxRoom>
8
+ <assets>
9
+ <assetobject id="body" src="http://www.baicoianu.com/~bai/janusweb/test/janus-avatar-base.glb" />
10
+ <assetobject id="avatar_animations" src="http://www.baicoianu.com/~bai/janusweb/test/janus-avatar-animations.glb" />
11
+ </assets>
12
+ <room>
13
+ <ghost scale=".01 .01 .01" col="#e0d5a1" body_id="body" bone_head="head" />
14
+ </room>
15
+ </FireBoxRoom>
16
+ `;
6
17
 
7
18
  this.postinit = function() {
8
19
  elation.engine.things.janusplayer.extendclass.postinit.call(this);
@@ -15,9 +26,12 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
15
26
  cursor_visible: {type: 'boolean', default: true, set: this.toggleCursorVisibility},
16
27
  cursor_opacity: {type: 'float', default: 1.0, set: this.toggleCursorVisibility},
17
28
  usevoip: {type: 'boolean', default: false },
29
+ defaultanimation: {type: 'string', default: 'idle' },
18
30
  collision_radius: {type: 'float', default: .25, set: this.updateCollider},
19
31
  party_mode: { type: 'boolean', set: this.updatePartyMode },
20
32
  avatarsrc: { type: 'string' },
33
+ cameraview: { type: 'string', default: 'firstperson' },
34
+ decouplehead: { type: 'boolean', default: false },
21
35
  });
22
36
 
23
37
  var controllerconfig = this.getSetting('controls.settings');
@@ -32,7 +46,9 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
32
46
  elation.events.add(this.engine.client.view.container, 'touchend', elation.bind(this, this.handleTouchEnd));
33
47
 
34
48
  this.controlstate2 = this.engine.systems.controls.addContext('janusplayer', {
35
- 'voip_active': ['keyboard_v,keyboard_shift_v', elation.bind(this, this.activateVOIP)],
49
+ 'toggle_view': ['keyboard_v,keyboard_shift_v', elation.bind(this, this.toggleCamera)],
50
+ 'zoom_out': ['mouse_wheel_down', ev => this.zoomView(-1)],
51
+ 'zoom_in': ['mouse_wheel_up', ev => this.zoomView(1)],
36
52
  //'browse_back': ['gamepad_any_button_4', elation.bind(this, this.browseBack)],
37
53
  //'browse_forward': ['gamepad_any_button_5', elation.bind(this, this.browseForward)],
38
54
  });
@@ -100,7 +116,7 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
100
116
  elation.events.add(this.engine.client.container, 'mousedown', elation.bind(this, this.updateMouseStatus));
101
117
  elation.events.add(this.engine.client.container, 'mouseup', elation.bind(this, this.updateMouseStatus));
102
118
 
103
- elation.events.add(this.room, 'mouseover,mouseout', elation.bind(this, this.updateCursorStyle));
119
+ this.updateCursorStyle = elation.bind(this, this.updateCursorStyle);
104
120
 
105
121
  this.touchcache = {
106
122
  positions: []
@@ -122,11 +138,13 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
122
138
 
123
139
  this.getAvatarData().then(avatar => {;
124
140
  if (avatar && false) { // FIXME - self avatar is buggy so it's disabled
141
+ /*
125
142
  this.ghost = this.createObject('ghost', {
126
143
  ghost_id: this.getUsername(),
127
144
  avatar_src: 'data:text/plain,' + encodeURIComponent(avatar),
128
145
  showlabel: false
129
146
  });
147
+ */
130
148
  }
131
149
  });
132
150
 
@@ -264,14 +282,11 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
264
282
  }
265
283
  }
266
284
  }
267
- if (this.ghost) {
285
+ if (this.ghost && !this.decouplehead) {
286
+ this.ghost.setHeadOrientation(this.head.orientation, true);
268
287
  if (this.ghost._target.head) {
269
288
  //this.ghost._target.face.position.copy(this.head.position);
270
- this.ghost.head.orientation.copy(this.head.orientation);
271
- }
272
- if (this.ghost._target.body) {
273
- //this.ghost._target.body.position.copy(this.body.position);
274
- //this.ghost._target.body.orientation.copy(this.body.orientation);
289
+ this.ghost.head.orientation.copy(this.head.orientation).invert();
275
290
  }
276
291
  }
277
292
  }
@@ -280,6 +295,10 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
280
295
  if (this.lookAtLERPtime) {
281
296
  this.updateLookAtLERP();
282
297
  }
298
+ if (this.ghost && this.ghost.body) {
299
+ let animid = this.getAnimationID();
300
+ this.ghost.body.anim_id = animid;
301
+ }
283
302
  }
284
303
  this.updateCursor = (function() {
285
304
  var _tmpvec = new THREE.Vector3();
@@ -375,6 +394,21 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
375
394
  this.gaze.fired = true;
376
395
  }
377
396
  }
397
+ if (this.controlstate.jump && !this.jumping) {
398
+ let jumptime = 1;
399
+ if (this.ghost && this.ghost.body.animations && this.ghost.body.animations.jump) {
400
+ let jumpanim = this.ghost.body.animations.jump;
401
+ let jumpclip = jumpanim.getClip();
402
+
403
+ jumpanim.loop = THREE.LoopOnce;
404
+
405
+ if (jumpclip) {
406
+ jumptime = jumpclip.duration;
407
+ }
408
+ this.jumping = true;
409
+ setTimeout(() => this.jumping = false, (jumptime * 1000) * .8);
410
+ }
411
+ }
378
412
  }
379
413
  this.updateMouseStatus = function(ev) {
380
414
  if (ev.type == 'mousedown' && ev.button === 0) {
@@ -412,10 +446,15 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
412
446
  }
413
447
  this.setRoom = function(newroom) {
414
448
  if (this.room) {
449
+ let oldroomproxy = this.room.getProxyObject();
450
+ oldroomproxy.removeEventListener('mouseover', this.updateCursorStyle);
451
+ oldroomproxy.removeEventListener('mouseout', this.updateCursorStyle);
415
452
  this.room.part();
416
453
  }
417
454
  this.room = newroom;
418
455
  this.room.join();
456
+
457
+ /*
419
458
  if (!this.gazecaster) {
420
459
  this.gazecaster = newroom.createObject('raycaster', {persist: false});
421
460
  this.head.add(this.gazecaster._target);
@@ -426,6 +465,11 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
426
465
  } else {
427
466
  this.gazecaster.setRoom(newroom);
428
467
  }
468
+ */
469
+ let newroomproxy = newroom.getProxyObject();
470
+ newroomproxy.addEventListener('mouseover', this.updateCursorStyle);
471
+ newroomproxy.addEventListener('mouseout', this.updateCursorStyle);
472
+
429
473
  if (!this.cursors) {
430
474
  this.cursors = {
431
475
  'default': janus.getAsset('image', 'cursor_crosshair'),
@@ -435,25 +479,27 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
435
479
  'dot_active': janus.getAsset('image', 'cursor_dot_active'),
436
480
  };
437
481
  }
438
- if (!this.room.selfavatar && this.ghost) {
439
- this.ghost.die();
440
- this.ghost = false;
441
- this.visible = false;
442
- } else if (!this.ghost && this.room.selfavatar) {
482
+ newroom.appendChild(this.getProxyObject());
483
+ if (this.ghost) {
484
+ this.ghost.setRoom(newroom);
485
+ } else if (!this.ghost) { // && this.room.selfavatar) {
443
486
  // FIXME - self avatar is buggy so it's disabled
444
487
  this.getAvatarData().then(avatar => {
445
488
  if (avatar) {
446
489
  this.ghost = this.createObject('ghost', {
447
490
  ghost_id: this.getUsername(),
448
491
  avatar_src: 'data:text/plain,' + encodeURIComponent(avatar),
449
- showlabel: false
492
+ showlabel: false,
493
+ //pos: V(0, -this.fatness, 0),
494
+ rotation: V(0, 180, 0),
495
+ renderorder: 101,
450
496
  });
497
+ this.ghost.orientation.set(0,1,0,0);
451
498
  }
452
499
  });
453
500
  this.visible = true;
454
501
  }
455
502
 
456
- newroom.appendChild(this.getProxyObject());
457
503
  for (let k in this.children) {
458
504
  if (this.children[k].setRoom) {
459
505
  this.children[k].setRoom(room);
@@ -553,6 +599,9 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
553
599
 
554
600
  collision_radius: ['property', 'collision_radius'],
555
601
 
602
+ currentavatar: ['property', 'currentavatar'],
603
+ defaultanimation: ['property', 'defaultanimation'],
604
+
556
605
  localToWorld: ['function', 'localToWorld'],
557
606
  worldToLocal: ['function', 'worldToLocal'],
558
607
  appendChild: ['function', 'appendChild'],
@@ -601,15 +650,13 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
601
650
  if (this.ghost) {
602
651
  this.ghost.die();
603
652
  }
604
- this.getAvatarData().then(avatardata => {
605
- // FIXME - self avatar is broken and weird right now, so it's disabled
606
- if (avatardata && this.room.selfavatar) {
607
- this.ghost = this.createObject('ghost', {
608
- ghost_id: this.getUsername(),
609
- avatar_src: 'data:text/plain,' + encodeURIComponent(avatardata),
610
- showlabel: false
611
- });
612
- }
653
+ this.ghost = this.createObject('ghost', {
654
+ ghost_id: this.getUsername(),
655
+ avatar_src: 'data:text/plain,' + encodeURIComponent(avatar),
656
+ showlabel: false,
657
+ //pos: V(0, -this.fatness, 0),
658
+ rotation: V(0, 180, 0),
659
+ renderorder: 101,
613
660
  });
614
661
 
615
662
  return setting;
@@ -632,17 +679,19 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
632
679
  return voipdata;
633
680
  }
634
681
  this.getAnimationID = function() {
635
- var animid = 'idle';
636
- if (this.controlstate.run) {
637
- animid = 'run';
638
- } else if (this.controlstate.move_forward) {
639
- animid = 'walk';
682
+ var animid = this.defaultanimation;
683
+ let running = this.controlstate.run;
684
+
685
+ if (this.jumping) {
686
+ animid = 'jump';
640
687
  } else if (this.controlstate.move_left) {
641
- animid = 'walk_left';
688
+ animid = (running ? 'run' : 'walk_left');
642
689
  } else if (this.controlstate.move_right) {
643
- animid = 'walk_right';
690
+ animid = (running ? 'run' : 'walk_right');
691
+ } else if (this.controlstate.move_forward) {
692
+ animid = (running ? 'run' : 'walk');
644
693
  } else if (this.controlstate.move_backward) {
645
- animid = 'walk_back';
694
+ animid = (running ? 'run' : 'walk_back');
646
695
  } else if (document.activeElement && this.properties.janus.chat && document.activeElement === this.properties.janus.chat.input.inputelement) {
647
696
  animid = 'type';
648
697
  } else if (this.hasVoipData()) {
@@ -737,10 +786,9 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
737
786
  }
738
787
  this.updateCursorStyle = function(ev) {
739
788
  var vrdisplay = this.engine.systems.render.views.main.vrdisplay;
740
- var obj = ev.target || ev.element;
789
+ var obj = ev.element;
741
790
  var proxyobj = (obj.getProxyObject ? obj.getProxyObject() : obj);
742
791
 
743
-
744
792
  if (obj && proxyobj && (ev.type == 'mouseover' || ev.type == 'mousemove') && (
745
793
  obj.onclick ||
746
794
  elation.events.hasEventListener(obj, 'click') ||
@@ -793,8 +841,15 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
793
841
  this.updateCollider = function() {
794
842
  if (this.objects['dynamics']) {
795
843
  if (this.collision_radius > 0) {
844
+ /*
796
845
  this.setCollider('sphere', {
797
846
  radius: this.collision_radius,
847
+ });
848
+ */
849
+ this.pickable = false;
850
+ this.setCollider('capsule', {
851
+ radius: this.collision_radius,
852
+ length: 1,
798
853
  offset: V(0, this.collision_radius, 0)
799
854
  });
800
855
  } else {
@@ -1036,6 +1091,40 @@ elation.require(['engine.things.player', 'janusweb.external.JanusVOIP', 'ui.butt
1036
1091
  round: true,
1037
1092
  shader_id: 'defaultportal',
1038
1093
  });
1094
+
1095
+ // FIXME - should only set this if we have an active portal animation, and we should use the animation's duration for our timeout
1096
+ this.defaultanimation = 'portal';
1097
+ setTimeout(() => this.defaultanimation = 'idle', 3000);
1098
+ }
1099
+ this.toggleCamera = function(ev) {
1100
+ if (ev.value == 1) {
1101
+ if (this.cameraview == 'firstperson') {
1102
+ this.cameraview = 'thirdperson';
1103
+ this.camera.position.z = 2;
1104
+ } else {
1105
+ this.cameraview = 'firstperson';
1106
+ this.camera.position.z = 0;
1107
+ }
1108
+ }
1109
+ }
1110
+ this.zoomView = function(amount) {
1111
+ if (this.cameraview == 'thirdperson') {
1112
+ this.camera.position.z -= amount / 10;
1113
+ }
1114
+ }
1115
+ this.setAnimationSequence = function(sequence) {
1116
+ let t = 0;
1117
+ let currentanimation = this.defaultanimation;
1118
+ let body = this.ghost.body;
1119
+ sequence.forEach(clipname => {
1120
+ let anim = body.animations[clipname];
1121
+ if (anim) {
1122
+ let clip = anim.getClip();
1123
+ setTimeout(() => { this.defaultanimation = clipname; }, t * 1000);
1124
+ t += clip.duration;
1125
+ }
1126
+ });
1127
+ setTimeout(() => { this.defaultanimation = currentanimation; }, t * 1000);
1039
1128
  }
1040
1129
  }, elation.engine.things.player);
1041
1130
  });
@@ -170,6 +170,8 @@ elation.require([
170
170
  navback: ['function', 'navigateBack'],
171
171
  navforward: ['function', 'navigateForward'],
172
172
  load: ['function', 'navigateTo'],
173
+ setActiveRoom: ['function', 'setActiveRoom'],
174
+ preload: ['function', 'preload'],
173
175
  navhome: ['function', 'navigateHome'],
174
176
  chatsend: ['function', 'sendChatMessage'],
175
177
  sync: ['function', 'currentroom.sync'],
@@ -407,6 +409,9 @@ elation.require([
407
409
  this.load(url, true, null, referrer === false);
408
410
  }
409
411
  }
412
+ this.preload = function(url, stripreferrer) {
413
+ return this.load(url, false, null, stripreferrer);
414
+ }
410
415
  this.getFixedURL = function(url) {
411
416
  // Our 'clean' client URLs don't contain a : because many services have problems parsing them
412
417
  var m = url.match(/^(https?)\/\/?(.*)$/i);
@@ -316,10 +316,9 @@ elation.require(['engine.things.generic', 'janusweb.external.webxr-input-profile
316
316
  const minNode = motionControllerRoot.getObjectByName(visualResponse.minNodeName);
317
317
  const maxNode = motionControllerRoot.getObjectByName(visualResponse.maxNodeName);
318
318
 
319
- THREE.Quaternion.slerp(
319
+ valueNode.quaternion.slerp(
320
320
  minNode.quaternion,
321
321
  maxNode.quaternion,
322
- valueNode.quaternion,
323
322
  visualResponse.value
324
323
  );
325
324
 
@@ -574,7 +573,7 @@ elation.require(['engine.things.generic', 'janusweb.external.webxr-input-profile
574
573
  this.laser.updateLine();
575
574
  this.cursor.pos.copy(endpoint);
576
575
  //this.cursor.zdir = normal;
577
- if (this.cursor.room !== room) room.appendChild(this.cursor);
576
+ if (this.cursor.room !== room._target) room.appendChild(this.cursor);
578
577
  //this.cursor.zdir.copy(player.view_dir).multiplyScalar(-1);
579
578
  //this.cursor.zdir = normal;
580
579
  this.cursor.visible = true;
@@ -319,9 +319,9 @@ console.log('[MultiplayerManager] part', room.url);
319
319
  var roomId = data.roomId;
320
320
 
321
321
  var room = this.rooms[roomId] || this.activeroom;
322
- console.log('[MultiplayerManager] spawn remote guy', userId, roomId, room);
323
322
 
324
323
  var spawnpos = (data.position && data.position.pos ? data.position.pos.split(" ").map(parseFloat) : [0,0,0]);
324
+ //console.log('[MultiplayerManager] spawn remote guy', userId, roomId, room, spawnpos);
325
325
  this.remoteplayers[userId] = room.spawn('remoteplayer', userId, { position: spawnpos, player_id: userId, player_name: userId, pickable: false, collidable: false, janus: this.janusweb, room: room});
326
326
  var remote = this.remoteplayers[userId];
327
327
 
@@ -330,6 +330,7 @@ console.log('[MultiplayerManager] spawn remote guy', userId, roomId, room);
330
330
 
331
331
  // If a new player spawned, let's send an avatar update ASAP
332
332
  this.updateAvatar();
333
+ remote.start();
333
334
  return remote;
334
335
  }
335
336
  this.updateAvatar = function() {
@@ -390,6 +391,7 @@ console.log('[MultiplayerManager] spawn remote guy', userId, roomId, room);
390
391
 
391
392
  if (remote.room !== room) {
392
393
  remote.setRoom(room);
394
+ remote.start();
393
395
  }
394
396
 
395
397
  remote.updateData(movedata);
package/scripts/object.js CHANGED
@@ -111,6 +111,8 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
111
111
  //this.properties.collidable = false;
112
112
 
113
113
  //this.updateColliderFromGeometry(new THREE.BoxGeometry(1,1,1));
114
+
115
+ elation.events.add(this.room, 'skybox_update', ev => this.updateSkybox());
114
116
  }
115
117
  this.createForces = function() {
116
118
  elation.engine.things.janusobject.extendclass.createForces.call(this);
@@ -150,6 +152,13 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
150
152
  }), 0);
151
153
  this.jsparts.updateParts();
152
154
  this.assetloaded = true;
155
+ if (this.modelasset) {
156
+ this.initAnimations(this.modelasset.animations);
157
+ if (this.animations && this.anim_id && this.animations[this.anim_id]) {
158
+ console.log('start animation', this);
159
+ this.animations[this.anim_id].play();
160
+ }
161
+ }
153
162
  if (this.loadingindicator) {
154
163
  this.loadingindicator.die();
155
164
  }
@@ -177,6 +186,9 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
177
186
  if (videoasset) {
178
187
  this.videoasset = videoasset;
179
188
  texture = videoasset.getInstance();
189
+ if (!texture.image) {
190
+ videoasset.load();
191
+ }
180
192
  if (videoasset.sbs3d) {
181
193
  //texture.repeat.set(0.5, 1);
182
194
  this.texture_repeat.set(0.5, 1);
@@ -276,6 +288,11 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
276
288
  this.refresh();
277
289
  }
278
290
  }
291
+ if (this.animationmixer) {
292
+ //this.animationmixer.setTime(new Date().getTime() / 1000);
293
+ this.animationmixer.update(ev.data);
294
+ this.refresh();
295
+ }
279
296
  }
280
297
  this.assignTextures = function() {
281
298
  //console.log('assign textures', this.name, this.objects['3d']);
@@ -316,6 +333,18 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
316
333
  if (!modelasset || modelasset.name != this.janusid) {
317
334
  modelasset = this.getAsset('model', this.janusid, true);
318
335
  this.modelasset = modelasset;
336
+
337
+ if (modelasset.animations) {
338
+ this.initAnimations(modelasset.animations);
339
+ if (this.anim_id) {
340
+ if (modelasset && modelasset.loaded) {
341
+ this.setAnimation(this.anim_id);
342
+ } else {
343
+ elation.events.add(modelasset, 'asset_load', () => this.setAnimation(this.anim_id));
344
+ }
345
+ }
346
+ }
347
+
319
348
  }
320
349
  if (modelasset.tex) {
321
350
  image_id = modelasset.tex;
@@ -557,8 +586,6 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
557
586
  blend_dest = srcfactors[this.properties.blend_dest];
558
587
  }
559
588
 
560
- this.extractAnimations(this.objects['3d']);
561
-
562
589
  var scene = this.engine.systems.world.scene['world-3d'];
563
590
  if (!this.hasalpha) this.hasalpha = {};
564
591
  var hasalpha = this.hasalpha;
@@ -907,6 +934,8 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
907
934
  if (oldmat.color) {
908
935
  m.color.copy(oldmat.color);
909
936
  }
937
+ m.transmission = oldmat.transmission;
938
+ m.transmissionMap = oldmat.transmissionMap;
910
939
  m.transparent = m.opacity < 1;
911
940
  m.alphaTest = oldmat.alphaTest;
912
941
  m.skinning = oldmat.skinning;
@@ -915,10 +944,18 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
915
944
  if (oldmat.metalnessMap !== undefined) m.metalnessMap = oldmat.metalnessMap;
916
945
  if (oldmat.roughness !== undefined) m.roughness = oldmat.roughness;
917
946
  if (oldmat.roughnessMap !== undefined) m.roughnessMap = oldmat.roughnessMap;
918
- if (oldmat.clearCoat !== undefined) m.clearCoat = oldmat.clearCoar;
919
- if (oldmat.clearCoatRoughness !== undefined) m.clearCoatRoughness = oldmat.clearCoatRoughness;
947
+ if (oldmat.clearcoat !== undefined) m.clearcoat = oldmat.clearcoat;
948
+ if (oldmat.clearcoatMap !== undefined) m.clearcoatMap = oldmat.clearcoatMap;
949
+ if (oldmat.clearcoatRoughness !== undefined) m.clearcoatcoughness = oldmat.clearcoatRoughness;
950
+ if (oldmat.clearcoatRoughnessMap !== undefined) m.clearcoatRoughnessMap = oldmat.clearcoatRoughnessMap;
951
+ if (oldmat.clearcoatNormalMap !== undefined) m.clearcoatNormalMap = oldmat.clearcoatNormalMap;
952
+ if (oldmat.clearcoatNormalScale !== undefined) m.clearcoatNormalScale = oldmat.clearcoatNormalScale;
953
+ if (oldmat.attenuationTint !== undefined) m.attenuationTint = oldmat.attenuationTint;
954
+ if (oldmat.attenuationDistance !== undefined) m.attenuationDistance = oldmat.attenuationDistance;
955
+ if (oldmat.thickness !== undefined) m.thickness = oldmat.thickness;
956
+ if (oldmat.thicknessMap !== undefined) m.thicknessMap = oldmat.thicknessMap;
920
957
 
921
- m.reflectivity = (oldmat.reflectivity !== undefined ? oldmat.reflectivity : .5);
958
+ //m.reflectivity = (oldmat.reflectivity !== undefined ? oldmat.reflectivity : .5);
922
959
 
923
960
  if (oldmat.roughnessMap !== undefined) {
924
961
  m.roughnessMap = oldmat.roughnessMap;
@@ -943,17 +980,29 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
943
980
  */
944
981
 
945
982
  if (this.shader_chunk_replace) {
946
- let chunkreplace = this.shader_chunk_replace;
983
+ let chunkreplace = (elation.utils.isString(this.shader_chunk_replace) ? JSON.parse(this.shader_chunk_replace) : this.shader_chunk_replace);
947
984
  m.onBeforeCompile = function(shader) {
948
985
  for (let oldchunkname in chunkreplace) {
949
986
  let newchunkname = chunkreplace[oldchunkname];
950
987
  shader.vertexShader = shader.vertexShader.replace('#include <' + oldchunkname + '>', '#include <' + newchunkname + '>');
988
+ shader.fragmentShader = shader.fragmentShader.replace('#include <' + oldchunkname + '>', '#include <' + newchunkname + '>');
951
989
  }
952
990
  }
953
991
  }
954
992
  }
955
993
  return m;
956
994
  }
995
+ this.updateSkybox = function() {
996
+ let envMap = (this.isUsingPBR() ? this.getEnvmap() : null);
997
+ this.traverseObjects(n => {
998
+ if (n.material) {
999
+ let materials = (elation.utils.isArray(n.material) ? n.material : [n.material]);
1000
+ materials.forEach(m => {
1001
+ m.envMap = envMap;
1002
+ });
1003
+ }
1004
+ });
1005
+ }
957
1006
  this.updateColor = function() {
958
1007
  elation.engine.things.janusobject.extendclass.updateColor.call(this);
959
1008
 
@@ -1118,16 +1167,28 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
1118
1167
  if (this.videoasset && this.videotexture && !this.image_id) {
1119
1168
  var texture = this.videotexture;
1120
1169
  var video = texture.image;
1121
- if (video) {
1170
+ /*
1171
+ if (video && !video.playing) {
1122
1172
  video.src = this.videoasset.src;
1123
1173
  if (this.lastVideoTime) {
1124
1174
  video.currentTime = this.lastVideoTime;
1125
1175
  }
1126
1176
  }
1127
- this.videoasset.play();
1177
+ */
1178
+ //this.videoasset.play();
1128
1179
  //console.log('reload video', video.src, this.videoasset.hls, this.videoasset.auto_play);
1129
- if (!video.playing && this.videoasset.auto_play) {
1130
- video.play();
1180
+ if (video.paused) {
1181
+ if (this.videoasset.auto_play) {
1182
+ video.play()
1183
+ .then(() => console.log('Video autoplay start', video))
1184
+ .catch(e => {
1185
+ var strerr = e.toString();
1186
+ if (strerr.indexOf('NotSupportedError') == 0 && this.hls !== false) {
1187
+ console.log('Attempting to init hls', this.videoasset)
1188
+ this.videoasset.initHLS();
1189
+ }
1190
+ });
1191
+ }
1131
1192
  } else if (video.muted) {
1132
1193
  video.muted = false;
1133
1194
  video.play();
@@ -1238,6 +1299,41 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
1238
1299
  this.video.volume = this.gain;
1239
1300
  }
1240
1301
  }
1302
+ this.extractMorphTargets = function() {
1303
+ this.objects['3d'].traverse(n => {
1304
+ if (n.morphTargetDictionary && n.morphTargetInfluences && n.morphTargetInfluences.length > 0) {
1305
+ this.morphtargets = n.morphTargetDictionary;
1306
+ this.morphtargetInfluences = n.morphTargetInfluences;
1307
+ }
1308
+ });
1309
+ }
1310
+ this.setMorphTargetInfluence = function(name, value) {
1311
+ if (typeof this.morphtargets == 'undefined') {
1312
+ this.extractMorphTargets();
1313
+ }
1314
+
1315
+ if (this.morphtargets && name in this.morphtargets) {
1316
+ this.morphtargetInfluences[this.morphtargets[name]] = value;
1317
+ }
1318
+ }
1319
+ this.applyPosition = function(pos) {
1320
+ if (!this.modelasset) this.assignTextures();
1321
+
1322
+ let mat4 = new THREE.Matrix4().makeTranslation(+pos.x, +pos.y, +pos.z);
1323
+ if (this.modelasset && this.modelasset.loaded) {
1324
+ // FIXME - should we handle the case where the object is already loaded and we want to modify its origin?
1325
+ // Currently we do nothing, so we don't double-apply
1326
+ } else {
1327
+ elation.events.add(this.modelasset, 'asset_load', ev => {
1328
+ this.objects['3d'].traverse(n => {
1329
+ if (n instanceof THREE.Mesh) {
1330
+ n.geometry.applyMatrix4(mat4);
1331
+ }
1332
+ });
1333
+ });
1334
+ }
1335
+
1336
+ }
1241
1337
  this.getProxyObject = function(classdef) {
1242
1338
  if (!this._proxyobject) {
1243
1339
  this._proxyobject = elation.engine.things.janusobject.extendclass.getProxyObject.call(this, classdef);