janusweb 1.5.30 → 1.5.34

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 (84) hide show
  1. package/CHANGELOG +39 -0
  2. package/LICENSE +1 -1
  3. package/media/assets/janus-avatar-animations.glb +0 -0
  4. package/media/assets/janus-avatar-base.glb +0 -0
  5. package/media/assets/webui/apps/avatar/avatar.css +6 -2
  6. package/media/assets/webui/apps/avatar/avatar.js +99 -11
  7. package/media/assets/webui/apps/buttons/buttons.html +2 -2
  8. package/media/assets/webui/apps/buttons/buttons.js +3 -3
  9. package/media/assets/webui/apps/comms/comms.js +7 -4
  10. package/media/assets/webui/apps/comms/voip.js +133 -57
  11. package/media/assets/webui/apps/editor/codemirror/addon/hint/javascript-hint.js +162 -0
  12. package/media/assets/webui/apps/editor/codemirror/addon/hint/show-hint.css +36 -0
  13. package/media/assets/webui/apps/editor/codemirror/addon/hint/show-hint.js +529 -0
  14. package/media/assets/webui/apps/editor/codemirror/addon/hint/xml-hint.js +140 -0
  15. package/media/assets/webui/apps/editor/codemirror/keymap/vim.js +5734 -0
  16. package/media/assets/webui/apps/editor/codemirror/lib/codemirror.css +350 -0
  17. package/media/assets/webui/apps/editor/codemirror/lib/codemirror.js +9800 -0
  18. package/media/assets/webui/apps/editor/codemirror/lib/jmldark.css +33 -0
  19. package/media/assets/webui/apps/editor/codemirror/mode/css/css.js +864 -0
  20. package/media/assets/webui/apps/editor/codemirror/mode/htmlmixed/htmlmixed.js +153 -0
  21. package/media/assets/webui/apps/editor/codemirror/mode/javascript/javascript.js +942 -0
  22. package/media/assets/webui/apps/editor/codemirror/mode/xml/xml.js +413 -0
  23. package/media/assets/webui/apps/editor/editor.css +3 -0
  24. package/media/assets/webui/apps/editor/editor.js +409 -9
  25. package/media/assets/webui/apps/editor/editor.json +6 -3
  26. package/media/assets/webui/apps/inventory/inventory.html +7 -4
  27. package/media/assets/webui/apps/inventory/inventory.js +2 -2
  28. package/media/assets/webui/apps/locomotion/teleporter.js +10 -9
  29. package/media/assets/webui/apps/navigation/navigation.js +12 -12
  30. package/media/assets/webui/apps/settings/settings.html +1 -1
  31. package/media/assets/webui/apps/vfs/browserfs/browserfs.js +8 -0
  32. package/media/assets/webui/apps/vfs/vfs.css +52 -0
  33. package/media/assets/webui/apps/vfs/vfs.js +452 -0
  34. package/media/assets/webui/apps/vfs/vfs.json +10 -0
  35. package/media/assets/webui/apps/virtualgamepad/virtualgamepad.js +9 -7
  36. package/media/assets/webui/apps/xrmenu/xrmenu.js +13 -4
  37. package/media/assets/webui/default.json +2 -1
  38. package/media/assets/webui/none.json +1 -0
  39. package/media/assets/webui/themes/default.css +29 -2
  40. package/media/assets.json +2 -1
  41. package/media/index.html +1 -1
  42. package/media/lib/draco/README.md +32 -0
  43. package/media/lib/draco/draco_decoder.js +52 -0
  44. package/media/lib/draco/draco_decoder.wasm +0 -0
  45. package/media/lib/draco/draco_encoder.js +33 -0
  46. package/media/lib/draco/draco_wasm_wrapper.js +104 -0
  47. package/media/lib/draco/gltf/draco_decoder.js +48 -0
  48. package/media/lib/draco/gltf/draco_decoder.wasm +0 -0
  49. package/media/lib/draco/gltf/draco_encoder.js +33 -0
  50. package/media/lib/draco/gltf/draco_wasm_wrapper.js +104 -0
  51. package/media/lib/physx/physx.release.js +21 -0
  52. package/media/lib/physx/physx.release.wasm +0 -0
  53. package/media/manifest.json +5 -5
  54. package/media/service-worker.js +7 -0
  55. package/package.json +2 -9
  56. package/scripts/client.js +67 -46
  57. package/scripts/config.js +2 -0
  58. package/scripts/elements/linesegments.js +10 -3
  59. package/scripts/external/JanusFireboxParser.js +1 -0
  60. package/scripts/image.js +7 -1
  61. package/scripts/janusbase.js +104 -43
  62. package/scripts/janusghost.js +314 -16
  63. package/scripts/januslight.js +11 -2
  64. package/scripts/janusparagraph.js +8 -6
  65. package/scripts/janusparticle.js +26 -16
  66. package/scripts/janusplayer.js +126 -37
  67. package/scripts/janusweb.js +26 -2
  68. package/scripts/janusxrplayer.js +5 -3
  69. package/scripts/multiplayermanager.js +6 -4
  70. package/scripts/object.js +246 -88
  71. package/scripts/portal.js +23 -14
  72. package/scripts/remoteplayer.js +1 -25
  73. package/scripts/room.js +199 -77
  74. package/scripts/sound.js +8 -6
  75. package/scripts/text.js +13 -5
  76. package/scripts/translators/janusvfs.js +20 -0
  77. package/scripts/video.js +1 -1
  78. package/scripts/websurface.js +17 -3
  79. package/utils/build.sh +3 -0
  80. package/utils/init.sh +2 -2
  81. package/scripts/chat.js +0 -80
  82. package/scripts/ui.js +0 -265
  83. package/scripts/urlbar.js +0 -93
  84. package/templates/janusweb.tpl +0 -3
@@ -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,10 +51,12 @@ 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' },
56
58
  ongazeactivate: { type: 'callback' },
59
+ oncollision: { type: 'callback' },
57
60
  });
58
61
  this.lastframevalues = {
59
62
  position: new THREE.Vector3(0,0,0),
@@ -80,7 +83,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
80
83
  this.properties.orientation.copy(this.object.quaternion);
81
84
  return this.object;
82
85
  }
83
- if (this.renderorder) this.object.renderOrder = this.renderorder;
86
+ if (this.renderorder && this.object) this.object.renderOrder = this.renderorder;
84
87
  return new THREE.Object3D();
85
88
  }
86
89
  this.createChildren = function() {
@@ -120,7 +123,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
120
123
  this.refresh();
121
124
  }
122
125
  this.updateOpacity = function() {
123
- this.setOpacity(this.opacity);
126
+ this.setOpacity(this.opacity, this.transparent);
124
127
  },
125
128
  this.updateAlphaTest = function() {
126
129
  this.setAlphaTest(this.alphatest);
@@ -129,7 +132,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
129
132
  this.removeCollider();
130
133
  if (!(this.collidable || this.pickable) || !this.objects['dynamics']) return;
131
134
  var collision_id = this.collision_id || this.collider_id;
132
- var collision_scale = this.scale.clone();
135
+ var collision_scale = V().copy(this.scale);
133
136
  if (this.collision_scale) {
134
137
  collision_scale.multiply(this.collision_scale);
135
138
  }
@@ -154,7 +157,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
154
157
  } else if (collision_id == 'cylinder') {
155
158
  this.setCollider('cylinder', {height: 1, radius: .5, offset: new THREE.Vector3(0, 0.5, 0), trigger: this.collision_trigger});
156
159
  } else if (collision_id == 'capsule') {
157
- this.setCollider('capsule', {height: 1, radius: .5, offset: new THREE.Vector3(0, 0.5, 0), trigger: this.collision_trigger});
160
+ this.setCollider('capsule', {length: 1, radius: .5, offset: new THREE.Vector3(0, 0, 0), trigger: this.collision_trigger});
158
161
  } else {
159
162
  var colliderasset = this.getAsset('model', collision_id);
160
163
  if (colliderasset) {
@@ -174,24 +177,25 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
174
177
  let remove = [];
175
178
  collider.traverse(n => {
176
179
  // Ignore collider if it's too high-poly
177
- if (n instanceof THREE.Mesh && !((n.geometry instanceof THREE.BufferGeometry && n.geometry.attributes.position.count <= 65536) ||
178
- (n.geometry instanceof THREE.Geometry && n.geometry.vertices.length <= 65536))) {
179
- console.warn('Collider mesh rejected, too many polys!', collision_id, this, n, collider);
180
- elation.events.fire({type: 'thing_collider_rejected', element: this, data: {root: collider, mesh: n}});
181
- remove.push(n);
182
- } else {
183
- if (n.material) {
184
- n.material = new THREE.MeshPhongMaterial({
185
- color: collidercolor,
186
- opacity: .2,
187
- transparent: true,
188
- emissive: 0x444400,
189
- alphaTest: .01,
190
- depthTest: false,
191
- depthWrite: false
192
- });
180
+ if (n instanceof THREE.Mesh && n.geometry instanceof THREE.BufferGeometry) {
181
+ if (n.geometry.attributes.position.count > 65536) {
182
+ console.warn('Collider mesh rejected, too many polys!', collision_id, this, n, collider);
183
+ elation.events.fire({type: 'thing_collider_rejected', element: this, data: {root: collider, mesh: n}});
184
+ remove.push(n);
185
+ } else {
186
+ if (n.material) {
187
+ n.material = new THREE.MeshPhongMaterial({
188
+ color: collidercolor,
189
+ opacity: .2,
190
+ transparent: true,
191
+ emissive: 0x444400,
192
+ alphaTest: .01,
193
+ depthTest: false,
194
+ depthWrite: false
195
+ });
196
+ }
197
+ n.userData.thing = this;
193
198
  }
194
- n.userData.thing = this;
195
199
  }
196
200
  });
197
201
  if (remove.length > 0) {
@@ -205,8 +209,12 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
205
209
  //this.colliders.add(collider);
206
210
  processMeshCollider(collider);
207
211
  } else {
212
+ let meshColliderLoaded = false;
208
213
  elation.events.add(collider, 'asset_load', elation.bind(this, function(ev) {
209
- processMeshCollider(collider);
214
+ if (!meshColliderLoaded) {
215
+ processMeshCollider(collider);
216
+ }
217
+ meshColliderLoaded = true;
210
218
  }) );
211
219
  }
212
220
  }
@@ -223,7 +231,9 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
223
231
  }
224
232
  }
225
233
  this.createForces = function() {
226
- 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
+ }
227
237
  this.updateRotationSpeed();
228
238
  }
229
239
  this.updateRotationSpeed = function() {
@@ -286,7 +296,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
286
296
  }
287
297
  } else if (val instanceof THREE.Color) {
288
298
  if (defaultval instanceof THREE.Color) defaultval = defaultval.toArray();
289
- if (!('default' in propdef) || ('default' in propdef && !(val.r == defaultval[0] && val.g == defaultval[1] && val.b == defaultval[2]))) {
299
+ if (!('default' in propdef) || defaultval === null || ('default' in propdef && !(val.r == defaultval[0] && val.g == defaultval[1] && val.b == defaultval[2]))) {
290
300
  attrs[k] = val.toArray().map(n => Math.round(n * 10000) / 10000).join(' ');
291
301
  }
292
302
  } else if (val instanceof THREE.Euler) {
@@ -347,6 +357,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
347
357
  dynamicfriction:['property', 'dynamicfriction'],
348
358
  staticfriction:['property', 'staticfriction'],
349
359
  opacity: ['property', 'opacity'],
360
+ transparent: ['property', 'transparent'],
350
361
  alphatest: ['property', 'alphatest'],
351
362
  sync: ['property', 'sync'],
352
363
  autosync: ['property', 'autosync'],
@@ -372,6 +383,9 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
372
383
  rotate_deg_per_sec: [ 'property', 'rotate_deg_per_sec'],
373
384
  rotate_axis: [ 'property', 'rotate_axis'],
374
385
 
386
+ anim_id: ['property', 'anim_id'],
387
+ anim_transition_time: ['property', 'anim_transition_time'],
388
+
375
389
  fwd: ['property', 'zdir'],
376
390
  xdir: ['property', 'xdir'],
377
391
  ydir: ['property', 'ydir'],
@@ -708,7 +722,11 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
708
722
  }
709
723
  this.start = function() {
710
724
  if (!this.started) {
711
- 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
+ }
712
730
  this.started = true;
713
731
  }
714
732
  for (var k in this.children) {
@@ -725,7 +743,9 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
725
743
  }
726
744
  }
727
745
  if (this.started) {
728
- 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
+ }
729
749
  this.started = false;
730
750
  this.dispatchEvent({type: 'stop', bubbles: false});
731
751
  }
@@ -739,7 +759,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
739
759
  dir = new THREE.Vector3(),
740
760
  up = new THREE.Vector3();
741
761
  return function(ev) {
742
- let parent = this.parent;
762
+ let parent = this.properties.parent;
743
763
  let billboard = this.properties.billboard;
744
764
  if (billboard && parent) {
745
765
  //player.camera.localToWorld(playerpos.set(0,0,0));
@@ -896,7 +916,7 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
896
916
  }
897
917
 
898
918
  this.createObject = function(type, args, skipstart) {
899
- return room.createObject(type, args, this, !this.started);
919
+ return this.room.createObject(type, args, this, !this.started);
900
920
  }
901
921
  this.appendChild = function(obj) {
902
922
  var proxyobj = obj
@@ -934,8 +954,8 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
934
954
  realobj.stop();
935
955
  this.remove(realobj);
936
956
  this.updateScriptChildren();
937
- if (room.objects[obj.js_id]) {
938
- delete room.objects[obj.js_id];
957
+ if (this.room.objects[obj.js_id]) {
958
+ delete this.room.objects[obj.js_id];
939
959
  }
940
960
  }
941
961
  }
@@ -974,15 +994,16 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
974
994
  }
975
995
  }
976
996
  }
977
- this.setOpacity = function(opacity) {
978
- if (this.objects['3d'] && this.currentopacity != opacity) {
997
+ this.setOpacity = function(opacity, transparent) {
998
+ if (this.objects['3d'] && (this.currentopacity != opacity || this.currenttransparent !== transparent)) {
979
999
  this.currentopacity = opacity;
980
- this.traverseObjects(function(n) {
1000
+ this.currenttransparent = transparent;
1001
+ this.traverseObjects((n) => {
981
1002
  if (n.material) {
982
1003
  var m = (elation.utils.isArray(n.material) ? n.material : [n.material]);
983
1004
  for (var i = 0; i < m.length; i++) {
984
1005
  m[i].opacity = opacity;
985
- m[i].transparent = (opacity < 1);
1006
+ m[i].transparent = (transparent !== null ? transparent : opacity < 1);
986
1007
  if (m[i].transparent) {
987
1008
  m[i].alphaTest = this.alphatest;
988
1009
  }
@@ -1009,25 +1030,58 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
1009
1030
  }
1010
1031
  this.updateAnimation = function() {
1011
1032
  // Triggered whenever this.anim_id changes
1012
- this.setAnimation(this.anim_id);
1033
+ if (this.anim_id) {
1034
+ this.setAnimation(this.anim_id);
1035
+ } else if (this.activeanimation) {
1036
+ this.stopAnimation();
1037
+ }
1013
1038
  }
1014
1039
  this.setAnimation = function(anim_id) {
1015
- if (!this.activeanimation || anim_id != this.anim_id) {
1016
- if (!this.animationmixer) return;
1040
+ if (!this.started) return;
1041
+ if (!this.activeanimation || anim_id != this.activeanimation._clip.name) {
1042
+ if (!this.animationmixer) this.extractAnimations(this.objects['3d']);
1017
1043
  if (this.activeanimation) {
1018
1044
  //console.log('pause active animation', this.activeanimation);
1019
1045
  // TODO - interpolating between actions would make transitions smoother
1020
- this.activeanimation.stop();
1046
+ //this.activeanimation.stop();
1047
+ //this.activeanimation.fadeOut(.5);
1048
+ let oldaction = this.activeanimation;
1049
+ if (!this.fadetimers) this.fadetimers = {};
1050
+ let clipname = oldaction._clip.name;
1051
+ if (!this.fadetimers[clipname]) {
1052
+ // FIXME - for some reason, THREE.AnimationAction.fadeIn() / fadeOut() / etc are just causing the animations to stop, so we'll handle fading ourselves
1053
+ this.fadetimers[clipname] = setInterval(() => {
1054
+ oldaction.weight *= .95;
1055
+ if (oldaction.weight <= .001) {
1056
+ oldaction.weight = 0;
1057
+ oldaction.stop();
1058
+ clearTimeout(this.fadetimers[clipname]);
1059
+ this.fadetimers[clipname] = false;
1060
+ }
1061
+ }, 20);
1062
+ }
1021
1063
  }
1022
- if (this.animationactions && this.animationactions[anim_id]) {
1023
- var action = this.animationactions[anim_id];
1024
- //console.log('found action!', anim_id, action);
1064
+ if (this.animations && this.animations[anim_id]) {
1065
+ var action = this.animations[anim_id];
1066
+ let clipname = action._clip.name;
1067
+ if (this.fadetimers && this.fadetimers[clipname]) {
1068
+ clearTimeout(this.fadetimers[clipname]);
1069
+ this.fadetimers[clipname] = false;
1070
+ }
1071
+ action.weight = 1;
1072
+ action.reset();
1025
1073
  action.play();
1026
1074
  this.activeanimation = action;
1027
1075
  }
1028
1076
  this.anim_id = anim_id;
1029
1077
  }
1030
1078
  }
1079
+ this.stopAnimation = function() {
1080
+ if (this.activeanimation) {
1081
+ this.activeanimation.stop();
1082
+ this.activeanimation = false;
1083
+ }
1084
+ }
1031
1085
  this.dispatchEvent = function(event, target) {
1032
1086
  if (!event.element) event.element = target || this;
1033
1087
  if (!event.target) {
@@ -1315,9 +1369,10 @@ console.log('clone', props);
1315
1369
  }
1316
1370
  }
1317
1371
  this.setRoom = function(newroom, ischild) {
1318
- if (newroom._target) newroom = newroom._target; // If the proxy object is passed in, use its target instead
1372
+ if (newroom && newroom._target) newroom = newroom._target; // If the proxy object is passed in, use its target instead
1319
1373
 
1320
1374
  if (this.room !== newroom) {
1375
+ let oldroom = this.room;
1321
1376
  if (!ischild) {
1322
1377
  this.stop();
1323
1378
  }
@@ -1327,7 +1382,13 @@ console.log('clone', props);
1327
1382
  this.children[k].setRoom(newroom, true);
1328
1383
  }
1329
1384
  }
1330
- if (!ischild) {
1385
+ if (newroom && !ischild) {
1386
+ let roomproxy = (newroom._target ? newroom : newroom.getProxyObject()),
1387
+ objproxy = (this._target ? this : this.getProxyObject());
1388
+ if (!roomproxy.contains(objproxy)) {
1389
+ //newroom.add(this);
1390
+ roomproxy.appendChild(objproxy);
1391
+ }
1331
1392
  this.start();
1332
1393
  }
1333
1394
  }