janusweb 1.5.47 → 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
  });
@@ -209,8 +209,10 @@ elation.elements.define('janus-comms-chat', class extends elation.elements.base
209
209
  }
210
210
  });
211
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); });
212
213
  // FIXME - first element with the current design is a <detail> element, but this is fragile if that changes
213
214
  this.elements[0].addEventListener('toggle', (ev) => this.elements.chatinput.focus());
215
+ this.updateRoom(room);
214
216
  }
215
217
  scrollToBottom() {
216
218
  setTimeout(() => {
@@ -219,7 +221,7 @@ elation.elements.define('janus-comms-chat', class extends elation.elements.base
219
221
  }
220
222
  handleUserJoined(ev) {
221
223
  var data = ev.data;
222
- if (!this.elements.chatmessages) return;
224
+ if (!this.elements || !this.elements.chatmessages) return;
223
225
  this.elements.chatmessages.add({
224
226
  timestamp: new Date().getTime(),
225
227
  type: 'join',
@@ -302,6 +304,9 @@ if (!this.elements.chatmessages) return;
302
304
  }
303
305
  this.elements.unread.count = this.numunread;
304
306
  }
307
+ updateRoom(newroom) {
308
+ this.elements.toggle.open = !newroom.private;
309
+ }
305
310
  });
306
311
 
307
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.47",
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,
@@ -446,7 +446,7 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
446
446
  }
447
447
  });
448
448
  } else {
449
- let armature = sourcecontainer.getObjectByName('Armature');
449
+ let armature = sourcecontainer.getObjectByName('Armature') || sourcecontainer;
450
450
  newclip.tracks.forEach(track => {
451
451
  track.name = track.name.replace('mixamorig', '');
452
452
  let p = track.name.split('.');
@@ -528,6 +528,8 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
528
528
  var xdir = new THREE.Vector3(),
529
529
  ydir = new THREE.Vector3(),
530
530
  zdir = new THREE.Vector3(),
531
+ flip = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI, 0));
532
+ origin = new THREE.Vector3(),
531
533
  matrix = new THREE.Matrix4(),
532
534
  q1 = new THREE.Quaternion();
533
535
  return function(movedata) {
@@ -550,16 +552,11 @@ elation.require(['janusweb.janusbase', 'engine.things.leapmotion'], function() {
550
552
  if (this.head) {
551
553
  ydir.fromArray(parser.getVectorValue(movedata.up_dir, [0,1,0]));
552
554
  zdir.fromArray(parser.getVectorValue(movedata.view_dir, [0,0,1]));
553
- xdir.crossVectors(zdir, ydir);
554
-
555
- xdir.crossVectors(zdir, ydir).normalize();
556
- zdir.crossVectors(xdir, ydir).normalize();
557
-
558
- matrix.makeBasis(xdir, ydir, zdir);
555
+ matrix.lookAt(origin, zdir, ydir);
559
556
  q1.setFromRotationMatrix(matrix);
560
- this.head.properties.orientation.copy(this.orientation).invert().multiply(q1);
557
+ this.head.properties.orientation.copy(this.orientation).invert().multiply(q1).multiply(flip);
561
558
  if (this.body && this.headaction) {
562
- this.setHeadOrientation(this.head.orientation);
559
+ this.setHeadOrientation(this.head.orientation, true);
563
560
  }
564
561
  if (movedata.head_pos && this.face) {
565
562
  var headpos = this.head.properties.position;
@@ -863,7 +860,7 @@ return;
863
860
  let track = headaction._clip.tracks[0];
864
861
  if (track) {
865
862
  track.values[0] = orientation.x * (invert ? -1 : 1);
866
- track.values[1] = orientation.y * (invert ? -1 : 1);
863
+ track.values[1] = orientation.y * (invert ? 1 : -1);
867
864
  track.values[2] = orientation.z * (invert ? -1 : 1);
868
865
  track.values[3] = orientation.w; // * (invert ? -1 : 1);
869
866
  }
@@ -880,7 +877,7 @@ return;
880
877
  this.blinktimer = setTimeout(() => {
881
878
  this.blinktimer = false;
882
879
  this.blink();
883
- }, 2500 + Math.random() * 8500);
880
+ }, 250 + Math.random() * 10000);
884
881
  }
885
882
  }
886
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,
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;