janusweb 1.5.46 → 1.5.48

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.
@@ -189,12 +189,14 @@ elation.elements.define('janus-button-start', class extends elation.elements.ui.
189
189
  }
190
190
  onclick(ev) {
191
191
  janus.engine.systems.sound.enableSound();
192
- janus.engine.systems.controls.requestPointerLock();
193
192
  if (room.objects.scroller) {
194
193
  room.objects.scroller.disable();
195
194
  }
196
- //player.flying = false;
197
- player.enable();
195
+ if (room.pointerlock) {
196
+ janus.engine.systems.controls.requestPointerLock();
197
+ //player.flying = false;
198
+ player.enable();
199
+ }
198
200
  //janus.ui.show();
199
201
  }
200
202
  });
@@ -102,7 +102,7 @@ elation.elements.define('janus-comms-userlist', class extends elation.elements.u
102
102
  elation.events.add(this.janusweb, 'room_load_start', (ev) => { this.updateRoom(ev.data); });
103
103
  elation.events.add(this.janusweb.network, 'janusweb_user_joined,janusweb_user_left,janusweb_user_disconnected', (ev) => this.updateUsers());
104
104
  setTimeout(() => {
105
- this.updateUsers();
105
+ //this.updateUsers();
106
106
  this.updateRoom(room);
107
107
  }, 100);
108
108
  }
@@ -117,8 +117,10 @@ elation.elements.define('janus-comms-userlist', class extends elation.elements.u
117
117
  }
118
118
  updateRoom(room) {
119
119
  this.room = room;
120
- this.innerHTML = '';
121
- this.elements = elation.elements.fromTemplate('janus.comms.userlist', this);
120
+ //this.innerHTML = '';
121
+ if (!this.elements) {
122
+ this.elements = elation.elements.fromTemplate('janus.comms.userlist', this);
123
+ }
122
124
  this.userlist_room = this.userlist_room;
123
125
  this.userlist_online = this.userlist_online;
124
126
  this.userlist_friends = this.userlist_friends;
@@ -135,11 +137,12 @@ elation.elements.define('janus-comms-userlist', class extends elation.elements.u
135
137
  if (!janus.network) return;
136
138
  var remoteplayers = janus.network.remoteplayers;
137
139
  var users = Object.keys(remoteplayers);
138
- users.unshift(player.userid);
140
+ //users.unshift(player.userid);
139
141
 
140
142
  if (this.elements.roomusers) {
141
143
  this.elements.roomusers.value = users.length;
142
144
  }
145
+ this.userlist_room = this.querySelector('ui-list[name="userlist_room"]');
143
146
  if (this.userlist_room) {
144
147
  this.userlist_room.setItems(users);
145
148
  }
@@ -206,8 +209,10 @@ elation.elements.define('janus-comms-chat', class extends elation.elements.base
206
209
  }
207
210
  });
208
211
  elation.events.add(janus._target, 'clientprint', (ev) => this.handleClientPrint(ev.data));
212
+ elation.events.add(this.janusweb, 'room_load_start', (ev) => { this.updateRoom(ev.data); });
209
213
  // FIXME - first element with the current design is a <detail> element, but this is fragile if that changes
210
214
  this.elements[0].addEventListener('toggle', (ev) => this.elements.chatinput.focus());
215
+ this.updateRoom(room);
211
216
  }
212
217
  scrollToBottom() {
213
218
  setTimeout(() => {
@@ -216,7 +221,7 @@ elation.elements.define('janus-comms-chat', class extends elation.elements.base
216
221
  }
217
222
  handleUserJoined(ev) {
218
223
  var data = ev.data;
219
- if (!this.elements.chatmessages) return;
224
+ if (!this.elements || !this.elements.chatmessages) return;
220
225
  this.elements.chatmessages.add({
221
226
  timestamp: new Date().getTime(),
222
227
  type: 'join',
@@ -299,6 +304,9 @@ if (!this.elements.chatmessages) return;
299
304
  }
300
305
  this.elements.unread.count = this.numunread;
301
306
  }
307
+ updateRoom(newroom) {
308
+ this.elements.toggle.open = !newroom.private;
309
+ }
302
310
  });
303
311
 
304
312
  elation.elements.define('janus-comms-voip', class extends elation.elements.base {
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.46",
4
+ "version": "1.5.48",
5
5
  "main": "scripts/janusweb.js",
6
6
  "author": "James Baicoianu",
7
7
  "license": "MIT",
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "elation-engine": ">=0.9.114",
22
- "uglify-es": "*"
22
+ "uglify-js": "*"
23
23
  },
24
24
  "keywords": [
25
25
  "elation",
package/scripts/client.js CHANGED
@@ -65,6 +65,7 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
65
65
  append: container,
66
66
  homepage: homepage,
67
67
  corsproxy: corsproxy,
68
+ showui: (args.showui && args.showui != "false"),
68
69
  shownavigation: (args.shownavigation && args.shownavigation != "false"),
69
70
  uiconfig: args.uiconfig,
70
71
  showchat: elation.utils.any(args.showchat, true),
@@ -95,6 +96,7 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
95
96
  homepage: { type: 'string' },
96
97
  url: { type: 'string' },
97
98
  uiconfig: { type: 'string' },
99
+ showui: { type: 'boolean' },
98
100
  shownavigation: { type: 'boolean', default: true },
99
101
  showchat: { type: 'boolean', default: true },
100
102
  networking: { type: 'boolean', default: true },
@@ -195,7 +197,7 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
195
197
 
196
198
  var datapath = elation.config.get('janusweb.datapath', '/media/janusweb');
197
199
  this.uiconfig = elation.utils.any(this.player.getSetting('uiconfig'), this.uiconfig, datapath + (datapath[datapath.length-1] != '/' ? '/' : '') + 'assets/webui/default.json');
198
- if (this.shownavigation) {
200
+ if (this.showui && this.shownavigation) {
199
201
  this.createUI();
200
202
  }
201
203
  this.view.pickingactive = true;
@@ -327,6 +329,7 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
327
329
  networking: { type: 'boolean', default: true },
328
330
  avatarsrc: { type: 'string', default: false },
329
331
  uiconfig: { type: 'string', default: false },
332
+ showui: { type: 'boolean', default: true },
330
333
  shownavigation: { type: 'boolean', default: true },
331
334
  });
332
335
  }
@@ -355,6 +358,7 @@ elation.require(['elements.elements', 'elements', 'engine.engine', 'engine.asset
355
358
  networking: this.networking,
356
359
  corsproxy: this.corsproxy,
357
360
  //resolution: width + 'x' + height,
361
+ showui: this.showui && this.showui != 'false',
358
362
  shownavigation: this.shownavigation,
359
363
  avatarsrc: this.avatarsrc,
360
364
  uiconfig: this.uiconfig,
@@ -69,19 +69,31 @@ elation.require(['janusweb.janusbase'], function() {
69
69
  },
70
70
  select(object) {
71
71
  this.selected = object;
72
+ if (!this.meshes) return;
72
73
  if (!object) {
73
74
  this.deselect();
74
75
  return;
75
76
  }
76
77
  let objmeshes = [], skinnedmeshes = [];
77
- object.traverseObjects(n => {
78
- if (n instanceof THREE.Mesh && n.material !== this.outlinematerial) {
79
- if (n.isSkinnedMesh)
80
- skinnedmeshes.push(n);
81
- else
82
- objmeshes.push(n);
83
- }
84
- });
78
+ if (object instanceof THREE.Object3D) {
79
+ object.traverse(n => {
80
+ if (n instanceof THREE.Mesh && n.material !== this.outlinematerial) {
81
+ if (n.isSkinnedMesh)
82
+ skinnedmeshes.push(n);
83
+ else
84
+ objmeshes.push(n);
85
+ }
86
+ });
87
+ } else {
88
+ object.traverseObjects(n => {
89
+ if (n instanceof THREE.Mesh && n.material !== this.outlinematerial) {
90
+ if (n.isSkinnedMesh)
91
+ skinnedmeshes.push(n);
92
+ else
93
+ objmeshes.push(n);
94
+ }
95
+ });
96
+ }
85
97
  // Create and update regular Meshes
86
98
  let meshIdx = 0;
87
99
  for (; meshIdx < objmeshes.length; meshIdx++) {
@@ -119,6 +131,7 @@ elation.require(['janusweb.janusbase'], function() {
119
131
  this.refresh();
120
132
  },
121
133
  deselect() {
134
+ if (!this.meshes) return;
122
135
  for (let meshIdx = 0; meshIdx < this.meshes.length; meshIdx++) {
123
136
  this.meshes[meshIdx].geometry = null;
124
137
  if (this.meshes[meshIdx].parent) {
@@ -57,6 +57,9 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
57
57
  ongazeprogress: { type: 'callback' },
58
58
  ongazeactivate: { type: 'callback' },
59
59
  oncollision: { type: 'callback' },
60
+ onmouseover: { type: 'callback' },
61
+ onmouseout: { type: 'callback' },
62
+ onmousemove: { type: 'callback' },
60
63
  });
61
64
  this.lastframevalues = {
62
65
  position: new THREE.Vector3(0,0,0),
@@ -467,11 +470,13 @@ elation.require(['engine.things.generic', 'utils.template', 'janusweb.parts'], f
467
470
  //} else if (v === true || v === false) {
468
471
  // propertydefs[k] = {type: 'boolean', default: v };
469
472
  } else if (v instanceof THREE.Vector3) {
470
- propertydefs[k] = {type: 'vector3', default: v };
473
+ propertydefs[k] = {type: 'vector3', default: v.clone() };
471
474
  } else if (v instanceof THREE.Color) {
472
- propertydefs[k] = {type: 'color', default: v };
475
+ propertydefs[k] = {type: 'color', default: v.clone() };
473
476
  } else if (v instanceof THREE.Euler) {
474
- propertydefs[k] = {type: 'euler', default: v };
477
+ propertydefs[k] = {type: 'euler', default: v.clone() };
478
+ } else if (typeof v == 'boolean') {
479
+ propertydefs[k] = {type: 'boolean', default: v };
475
480
  } else {
476
481
  propertydefs[k] = {type: 'object', default: v };
477
482
  }
@@ -286,7 +286,7 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
286
286
  this.body = this.createObject('object', {
287
287
  id: bodyid,
288
288
  //orientation: new THREE.Quaternion().setFromEuler(new THREE.Euler(0,Math.PI,0)),
289
- //rotation: V(0, 180, 0),
289
+ rotation: V(0, 180, 0),
290
290
  lighting: this.lighting,
291
291
  //cull_face: 'none'
292
292
  opacity: 0.9999,
@@ -393,7 +393,6 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
393
393
  sourcecontainer.traverse(n => { /*console.log(' - ', n); */ if (n instanceof THREE.SkinnedMesh && n.skeleton) sourcemesh = n; });
394
394
  }
395
395
  this.objects['3d'].traverse(n => { if (n instanceof THREE.SkinnedMesh && n.skeleton) destmesh = n; });
396
- //console.log('RETARGET ANI*MATION', clip, sourcemesh, destmesh, sourcecontainer);
397
396
  let remove = [];
398
397
  if (this.body && this.body.modelasset && this.body.modelasset.vrm) {
399
398
  let vrm = this.body.modelasset.vrm;
@@ -432,7 +431,6 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
432
431
  let [name, property] = track.name.split('.');
433
432
  let srcbone = sourcemesh.skeleton.getBoneByName(name);
434
433
  let dstbone = destmesh.skeleton.getBoneByName(name);
435
- //console.log(' - fix track', name, property, track, srcbone, dstbone);
436
434
  if (dstbone) {
437
435
  let scale = srcbone.position.length() / dstbone.position.length();
438
436
  if (property == 'position') {
@@ -447,6 +445,41 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
447
445
  remove.push(track);
448
446
  }
449
447
  });
448
+ } else {
449
+ let armature = sourcecontainer.getObjectByName('Armature') || sourcecontainer;
450
+ newclip.tracks.forEach(track => {
451
+ track.name = track.name.replace('mixamorig', '');
452
+ let p = track.name.split('.');
453
+ if (p[1] == 'position') {
454
+ for (let i = 0; i < track.values.length / 3; i++) {
455
+ track.values[i * 3] *= armature.scale.x;
456
+ track.values[i * 3 + 1] *= armature.scale.y;
457
+ track.values[i * 3 + 2] *= armature.scale.z;
458
+ }
459
+ }
460
+ if (p[0] == 'Hips') {
461
+ if (p[1] == 'position') {
462
+ let v = new THREE.Vector3();
463
+ for (let i = 0; i < track.values.length / 3; i++) {
464
+ v.set(track.values[i * 3], track.values[i * 3 + 1], track.values[i * 3 + 2]).applyQuaternion(armature.quaternion);
465
+ //console.log('position rotation', v, [track.values[i * 3], track.values[i * 3 + 1], track.values[i * 3 + 2]], track);
466
+ track.values[i * 3] = v.x;
467
+ track.values[i * 3 + 1] = v.y;
468
+ track.values[i * 3 + 2] = v.z;
469
+ }
470
+ } else if (p[1] == 'quaternion') {
471
+ //console.log('apply rotation', track);
472
+ let q = new THREE.Quaternion();
473
+ for (let i = 0; i < track.values.length / 4; i++) {
474
+ q.set(track.values[i * 4], track.values[i * 4 + 1], track.values[i * 4 + 2], track.values[i * 4 + 3]).premultiply(armature.quaternion);
475
+ track.values[i * 4] = q.x;
476
+ track.values[i * 4 + 1] = q.y;
477
+ track.values[i * 4 + 2] = q.z;
478
+ track.values[i * 4 + 3] = q.w;
479
+ }
480
+ }
481
+ }
482
+ });
450
483
  }
451
484
  remove.forEach(track => {
452
485
  let idx = newclip.tracks.indexOf(track);
@@ -495,6 +528,8 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
495
528
  var xdir = new THREE.Vector3(),
496
529
  ydir = new THREE.Vector3(),
497
530
  zdir = new THREE.Vector3(),
531
+ flip = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI, 0));
532
+ origin = new THREE.Vector3(),
498
533
  matrix = new THREE.Matrix4(),
499
534
  q1 = new THREE.Quaternion();
500
535
  return function(movedata) {
@@ -517,16 +552,11 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
517
552
  if (this.head) {
518
553
  ydir.fromArray(parser.getVectorValue(movedata.up_dir, [0,1,0]));
519
554
  zdir.fromArray(parser.getVectorValue(movedata.view_dir, [0,0,1]));
520
- xdir.crossVectors(zdir, ydir);
521
-
522
- xdir.crossVectors(zdir, ydir).normalize();
523
- zdir.crossVectors(xdir, ydir).normalize();
524
-
525
- matrix.makeBasis(xdir, ydir, zdir);
555
+ matrix.lookAt(origin, zdir, ydir);
526
556
  q1.setFromRotationMatrix(matrix);
527
- this.head.properties.orientation.copy(this.orientation).invert().multiply(q1);
557
+ this.head.properties.orientation.copy(this.orientation).invert().multiply(q1).multiply(flip);
528
558
  if (this.body && this.headaction) {
529
- this.setHeadOrientation(this.head.orientation);
559
+ this.setHeadOrientation(this.head.orientation, true);
530
560
  }
531
561
  if (movedata.head_pos && this.face) {
532
562
  var headpos = this.head.properties.position;
@@ -830,7 +860,7 @@ return;
830
860
  let track = headaction._clip.tracks[0];
831
861
  if (track) {
832
862
  track.values[0] = orientation.x * (invert ? -1 : 1);
833
- track.values[1] = orientation.y * (invert ? -1 : 1);
863
+ track.values[1] = orientation.y * (invert ? 1 : -1);
834
864
  track.values[2] = orientation.z * (invert ? -1 : 1);
835
865
  track.values[3] = orientation.w; // * (invert ? -1 : 1);
836
866
  }
@@ -847,7 +877,7 @@ return;
847
877
  this.blinktimer = setTimeout(() => {
848
878
  this.blinktimer = false;
849
879
  this.blink();
850
- }, 2500 + Math.random() * 8500);
880
+ }, 250 + Math.random() * 10000);
851
881
  }
852
882
  }
853
883
  this.setSpeakingVolume = function(volume) {
@@ -303,10 +303,10 @@ document.body.dispatchEvent(click);
303
303
  }
304
304
  }
305
305
  if (this.ghost && !this.decouplehead) {
306
- this.ghost.setHeadOrientation(this.head.orientation, true);
306
+ this.ghost.setHeadOrientation(_tmpquat.multiplyQuaternions(this.neck.orientation._target, this.head.orientation._target), true);
307
307
  if (this.ghost._target.head) {
308
308
  //this.ghost._target.face.position.copy(this.head.position);
309
- this.ghost.head.orientation.copy(this.head.orientation).invert();
309
+ this.ghost.head.orientation.copy(this.head.orientation).multiply(this.neck.orientation);;
310
310
  }
311
311
  }
312
312
  }
@@ -510,10 +510,10 @@ document.body.dispatchEvent(click);
510
510
  avatar_src: 'data:text/plain,' + encodeURIComponent(avatar),
511
511
  showlabel: false,
512
512
  //pos: V(0, -this.fatness, 0),
513
- rotation: V(0, 180, 0),
513
+ //rotation: V(0, 180, 0),
514
514
  renderorder: 101,
515
515
  });
516
- this.ghost.orientation.set(0,1,0,0);
516
+ //this.ghost.orientation.set(0,1,0,0);
517
517
  }
518
518
  });
519
519
  this.visible = true;
@@ -702,7 +702,7 @@ document.body.dispatchEvent(click);
702
702
  avatar_src: 'data:text/plain,' + encodeURIComponent(avatar),
703
703
  showlabel: false,
704
704
  //pos: V(0, -this.fatness, 0),
705
- rotation: V(0, 180, 0),
705
+ //rotation: V(0, 180, 0),
706
706
  renderorder: 101,
707
707
  });
708
708
 
@@ -1004,6 +1004,7 @@ document.body.dispatchEvent(click);
1004
1004
  }
1005
1005
  this.handleTouchStart = function(ev) {
1006
1006
  //if (!this.enabled) return;
1007
+ if (!room.pointerlock) return;
1007
1008
  let halfscreenwidth = window.innerWidth / 2;
1008
1009
  this.enabled = true;
1009
1010
  for (let i = 0; i < ev.changedTouches.length; i++) {
@@ -1021,6 +1022,7 @@ document.body.dispatchEvent(click);
1021
1022
  this.cancelTouchMovement(ev);
1022
1023
  }
1023
1024
  this.handleTouchMove = function(ev) {
1025
+ if (!room.pointerlock) return;
1024
1026
  if (ev.defaultPrevented) return;
1025
1027
  //if (ev.touches.length == 1) {
1026
1028
  //var touchindex = this.touchindex;
@@ -1106,7 +1108,34 @@ document.body.dispatchEvent(click);
1106
1108
  this.dispatchEvent = function(event, target) {
1107
1109
  let firedev = elation.events.fire(event);
1108
1110
  }
1109
- this.lookAt = function(other, up) {
1111
+ this.lookAt = function(other, up, turnhead) {
1112
+ if (!up) up = new THREE.Vector3(0,1,0);
1113
+ if (!other) return;
1114
+ var otherpos = false;
1115
+ if (other.properties && other.properties.position) {
1116
+ otherpos = other.localToWorld(new THREE.Vector3());
1117
+ } else if (other instanceof THREE.Object3D) {
1118
+ if (!otherpos) otherpos = new THREE.Vector3();
1119
+ other.getWorldPosition(otherpos);
1120
+ } else if (other instanceof THREE.Vector3) {
1121
+ otherpos = other.clone();
1122
+ }
1123
+ var thispos = this.head.localToWorld(new THREE.Vector3());
1124
+
1125
+ if (otherpos) {
1126
+ var dir = thispos.clone().sub(otherpos).normalize();
1127
+ if (turnhead) {
1128
+ this.head.properties.orientation.setFromEuler(new THREE.Euler(-Math.asin(dir.y), Math.atan2(dir.x, dir.z), 0, 'XYZ'));
1129
+ } else {
1130
+ this.properties.orientation.setFromEuler(new THREE.Euler(0, Math.atan2(dir.x, dir.z), 0));
1131
+ this.head.properties.orientation.setFromEuler(new THREE.Euler(-Math.asin(dir.y), 0, 0));
1132
+ }
1133
+ this.refresh();
1134
+ room.refresh();
1135
+ this.engine.systems.render.setdirty();
1136
+ }
1137
+ }
1138
+ this.turnTo = function(other, up) {
1110
1139
  if (!up) up = new THREE.Vector3(0,1,0);
1111
1140
  var otherpos = false;
1112
1141
  if (other.properties && other.properties.position) {
@@ -1119,7 +1148,7 @@ document.body.dispatchEvent(click);
1119
1148
  if (otherpos) {
1120
1149
  var dir = thispos.clone().sub(otherpos).normalize();
1121
1150
  this.properties.orientation.setFromEuler(new THREE.Euler(0, Math.atan2(dir.x, dir.z), 0));
1122
- this.head.properties.orientation.setFromEuler(new THREE.Euler(-Math.asin(dir.y), 0, 0));
1151
+ //this.head.properties.orientation.setFromEuler(new THREE.Euler(-Math.asin(dir.y), 0, 0));
1123
1152
  this.refresh();
1124
1153
  room.refresh();
1125
1154
  this.engine.systems.render.setdirty();
@@ -1223,19 +1252,28 @@ document.body.dispatchEvent(click);
1223
1252
  this.camera.orientation.setFromEuler(new THREE.Euler(0, this.cameraangle, 0));
1224
1253
  }
1225
1254
  }
1255
+ this.hasAnimation = function(anim_id) {
1256
+ return anim_id in this.ghost.body.animations;
1257
+ }
1258
+ this.getAnimation = function(anim_id) {
1259
+ if (this.hasAnimation(anim_id)) {
1260
+ return this.ghost.body.animations[anim_id];
1261
+ }
1262
+ return false;
1263
+ }
1226
1264
  this.setAnimationSequence = function(sequence) {
1227
- let t = 0;
1228
- let currentanimation = this.defaultanimation;
1229
- let body = this.ghost.body;
1230
- sequence.forEach(clipname => {
1231
- let anim = body.animations[clipname];
1265
+ let cumtime = 0;
1266
+ for (let i = 0; i < sequence.length; i++) {
1267
+ let anim_id = sequence[i];
1268
+ let anim = this.getAnimation(anim_id);
1269
+ anim.loop = (i == sequence.length - 1 ? THREE.LoopRepeat : THREE.LoopOnce);
1270
+ anim.clampWhenFinished = !(i == sequence.length - 1);
1232
1271
  if (anim) {
1233
1272
  let clip = anim.getClip();
1234
- setTimeout(() => { this.defaultanimation = clipname; }, t * 1000);
1235
- t += clip.duration;
1273
+ setTimeout(() => this.defaultanimation = anim_id, cumtime * 1000);
1274
+ cumtime += clip.duration;
1236
1275
  }
1237
- });
1238
- setTimeout(() => { this.defaultanimation = currentanimation; }, t * 1000);
1276
+ }
1239
1277
  }
1240
1278
  }, elation.engine.things.player);
1241
1279
  });
@@ -62,6 +62,7 @@ elation.require([
62
62
  url: { type: 'string', default: false },
63
63
  homepage: { type: 'string', default: "" },
64
64
  corsproxy: { type: 'string', default: '' },
65
+ showui: { type: 'boolean', default: true },
65
66
  shownavigation: { type: 'boolean', default: true },
66
67
  showchat: { type: 'boolean', default: true },
67
68
  datapath: { type: 'string', default: '/media/janusweb' },
@@ -177,7 +177,7 @@ console.log('[MultiplayerManager] set active room:', room, this.activeroom);
177
177
  tmpMat.makeRotationFromQuaternion(player.properties.orientation);
178
178
  tmpMat.extractBasis(tmpVecX, tmpVecY, tmpVecZ);
179
179
  var ret = {
180
- dir: (-tmpVecZ.x) + ' ' + (-tmpVecZ.y) + ' ' + (-tmpVecZ.z),
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
  };
package/scripts/object.js CHANGED
@@ -1126,10 +1126,9 @@ elation.require(['janusweb.janusbase', 'janusweb.websurface'], function() {
1126
1126
  if (this.objects['3d']) {
1127
1127
  this.traverseObjects(n => {
1128
1128
  if (n.material) {
1129
- n.material.color = this.properties.color;
1130
-
1131
1129
  var m = (elation.utils.isArray(n.material) ? n.material : [n.material]);
1132
1130
  for (var i = 0; i < m.length; i++) {
1131
+ m[i].color = this.properties.color;
1133
1132
  m[i].opacity = this.opacity;
1134
1133
  m[i].transparent = (textureasset && textureasset.hasalpha) || m[i].opacity < 1;
1135
1134
  if (m[i].transparent) {
@@ -41,12 +41,14 @@ elation.component.add('engine.things.remoteplayer', function() {
41
41
  'janus': this.janus,
42
42
  'room': this.room
43
43
  });
44
+ /*
44
45
  this.head = this.spawn('janusbase', this.properties.player_name + '_head', {
45
46
  'position': [0,1.4,0],
46
47
  'parent': this,
47
48
  'janus': this.janus,
48
49
  'room': this.room
49
50
  });
51
+ */
50
52
  /*
51
53
  this.face = this.head.spawn('maskgenerator', this.properties.player_name + '_mask', {
52
54
  'seed': this.properties.player_name,
@@ -141,7 +143,7 @@ elation.component.add('engine.things.remoteplayer', function() {
141
143
  this.setVolume = async function(volume) {
142
144
  if (this.mouth) {
143
145
  if (!this.mouth.audio) {
144
- await this.mout.createAudio(null, listener);
146
+ await this.mouth.createAudio(null, listener);
145
147
  }
146
148
  this.mouth.audio.gain.gain.value = volume;
147
149
  }
package/scripts/room.js CHANGED
@@ -93,6 +93,7 @@ elation.require([
93
93
  'onload': { type: 'string' },
94
94
  'sync': { type: 'boolean', default: false },
95
95
  'pointerlock': { type: 'boolean', default: true, set: this.updatePointerLock },
96
+ 'players': { type: 'object', get: this.getRoomPlayers }
96
97
  });
97
98
 
98
99
  if (!roomTranslators) {
@@ -317,16 +318,26 @@ elation.require([
317
318
  var assets = [];
318
319
  if (this.skybox_equi) {
319
320
  let equi = this.getAsset('image', this.skybox_equi);
320
- elation.events.add(equi, 'asset_load', ev => {
321
- this.skyboxtexture = ev.target._texture;
321
+ if (equi.loaded) {
322
+ this.skyboxtexture = equi.getInstance();
322
323
  this.skyboxtexture.mapping = THREE.EquirectangularReflectionMapping;
323
324
  this.skyboxtexture.encoding = THREE.sRGBEncoding;
324
325
  if (this.janus.currentroom === this) {
325
326
  this.skyboxobj.setTexture(this.skyboxtexture);
326
327
  }
327
328
  elation.events.fire({element: this, type: 'skybox_update'});
328
- });
329
- equi.getInstance();
329
+ } else {
330
+ elation.events.add(equi, 'asset_load', ev => {
331
+ this.skyboxtexture = ev.target._texture;
332
+ this.skyboxtexture.mapping = THREE.EquirectangularReflectionMapping;
333
+ this.skyboxtexture.encoding = THREE.sRGBEncoding;
334
+ if (this.janus.currentroom === this) {
335
+ this.skyboxobj.setTexture(this.skyboxtexture);
336
+ }
337
+ elation.events.fire({element: this, type: 'skybox_update'});
338
+ });
339
+ equi.getInstance();
340
+ }
330
341
  } else if (hasSkybox) {
331
342
  assets = [
332
343
  this.getAsset('image', this.skybox_right_id || 'black'),
@@ -2049,7 +2060,7 @@ elation.require([
2049
2060
  var hashargs = elation.url();
2050
2061
  var host = elation.utils.any(this.server, hashargs['janus.server'], elation.config.get('janusweb.network.host')),
2051
2062
  port = elation.utils.any(this.port, hashargs['janus.port'], elation.config.get('janusweb.network.port'), 5567);
2052
- this._server = this.janusweb.getConnection(host, port, this.url);
2063
+ this._server = this.janus.network.getServerForRoom(this);
2053
2064
  }
2054
2065
  return this._server;
2055
2066
  }
@@ -2117,6 +2128,7 @@ elation.require([
2117
2128
  voipid: ['property', 'voipid'],
2118
2129
  voiprange: ['property', 'voiprange'],
2119
2130
  voipserver: ['property', 'voipserver'],
2131
+ players: ['property', 'players'],
2120
2132
 
2121
2133
  localToWorld: ['function', 'localToWorld'],
2122
2134
  worldToLocal: ['function', 'worldToLocal'],
@@ -2797,6 +2809,7 @@ console.log('dispatch to parent', event, this, event.target);
2797
2809
  child.die();
2798
2810
  }
2799
2811
  }
2812
+ elation.events.fire({type: 'janus_room_unload', element: this});
2800
2813
  }
2801
2814
  this.getAudioNodes = function() {
2802
2815
  return new Promise(async (resolve, reject) => {
@@ -2980,6 +2993,15 @@ console.log('unknown material', mat);
2980
2993
  }
2981
2994
  }
2982
2995
  }
2996
+ this.getRoomPlayers = function() {
2997
+ let players = {};
2998
+ for (let k in janus.network.remoteplayers) {
2999
+ if (this.janus.network.remoteplayers[k].room === this) {
3000
+ players[k] = this.janus.network.remoteplayers[k];
3001
+ }
3002
+ }
3003
+ return players;
3004
+ }
2983
3005
  }, elation.engine.things.generic);
2984
3006
  });
2985
3007
 
package/scripts/sound.js CHANGED
@@ -17,7 +17,8 @@ elation.require(['janusweb.janusbase'], function() {
17
17
  starttime: { type: 'float', default: 0.0, set: this.updateSound },
18
18
  distancemodel: { type: 'string', default: 'inverse', set: this.updateSound },
19
19
  rolloff: { type: 'float', default: 1.0, set: this.updateSound },
20
- rect: { type: 'string', set: this.updateSound }
20
+ rect: { type: 'string', set: this.updateSound },
21
+ stream: { type: 'boolean', default: false}
21
22
  });
22
23
  this.playing = false;
23
24
  //Object.defineProperty(this, 'playing', { get: function() { if (this.audio) return this.audio.isPlaying; return false; } });
@@ -86,22 +87,37 @@ elation.require(['janusweb.janusbase'], function() {
86
87
  this.audio.onEnded = elation.bind(this, this.updatePlaying);
87
88
  elation.events.add(this.audio.buffer, 'playing,pause,ended', elation.bind(this, this.updatePlaying));
88
89
  if (src) {
89
- if (soundcache[src]) {
90
- this.audio.setBuffer(soundcache[src]);
91
- if (this.auto_play || this.singleshot || this.playStarted) {
92
- this.play();
90
+ if (this.stream) {
91
+ let audio = new Audio(src);
92
+ audio.src = src;
93
+ let source = audio.captureStream();
94
+ audio.addEventListener('playing', ev => {
95
+ this.audio.setMediaStreamSource(source);
96
+ console.log('ahh', audio, this.audio);
97
+ this.audio.connect();
98
+ //this.audio.play();
99
+ });
100
+ if (this.auto_play || sound.auto_play) {
101
+ audio.play();
93
102
  }
94
103
  } else {
95
- var loader = new THREE.AudioLoader();
96
- loader.load(src, elation.bind(this, function(buffer) {
97
- if (buffer) {
98
- soundcache[src] = buffer;
99
- this.audio.setBuffer(buffer);
100
- if ((this.auto_play || this.singleshot || this.playStarted) && this.room == this.janus.currentroom) {
101
- this.play();
102
- }
104
+ if (soundcache[src]) {
105
+ this.audio.setBuffer(soundcache[src]);
106
+ if (this.auto_play || this.singleshot || this.playStarted) {
107
+ this.play();
103
108
  }
104
- }));
109
+ } else {
110
+ var loader = new THREE.AudioLoader();
111
+ loader.load(src, elation.bind(this, function(buffer) {
112
+ if (buffer) {
113
+ soundcache[src] = buffer;
114
+ this.audio.setBuffer(buffer);
115
+ if ((this.auto_play || this.singleshot || this.playStarted) && this.room == this.janus.currentroom) {
116
+ this.play();
117
+ }
118
+ }
119
+ }));
120
+ }
105
121
  }
106
122
  } else if (sound && sound.buffer) {
107
123
  soundcache[src] = sound.buffer;