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
@@ -155,13 +155,13 @@ elation.elements.define('janus.ui.editor.panel', class extends elation.elements.
155
155
  if (typeof room == 'undefined') return;
156
156
  if (!this.manipulator) {
157
157
  let view = janus.engine.client.view;
158
- this.manipulator = new THREE.TransformControls(view.actualcamera, view.container);
158
+ this.manipulator = new THREE.TransformControls(view.actualcamera, view.canvas);
159
159
 
160
160
  elation.events.add(this.manipulator, 'mouseDown', (ev) => {
161
161
  this.roomedit.transforming = true;
162
162
  this.editObjectShowInfo(this.roomedit.object);
163
163
  if (this.manipulator.object && this.manipulator.object.userData.thing) {
164
- //elation.events.fire({type: 'admin_edit_start', element: this, data: this.manipulator.object.userData.thing});
164
+ //elation.events.fire({type: 'admin_edit_start', element: this, data: this.manipulator.object.userData.thing});
165
165
  //player.disable();
166
166
  }
167
167
  });
@@ -271,7 +271,16 @@ console.log('set translation snap', ev.data, ev);
271
271
  janus.engine.systems.render.setdirty();
272
272
  }
273
273
  handleViewSourceClick(ev) {
274
- room.showDebug();
274
+ if (!this.sourcewindow) {
275
+ let win = elation.elements.create('ui-window', { append: document.body, center: true });
276
+ let editor = elation.elements.create('janus-ui-editor-source', { room: room });
277
+
278
+ win.setcontent(editor);
279
+ setTimeout(() => { win.center = false; }, 1500);
280
+ this.sourcewindow = win;
281
+ } else {
282
+ this.sourcewindow.show();
283
+ }
275
284
  }
276
285
  handleExportClick(ev) {
277
286
  let exporter = new THREE.GLTFExporter();
@@ -281,7 +290,7 @@ console.log('set translation snap', ev.data, ev);
281
290
  var url = window.URL.createObjectURL(filedata);
282
291
 
283
292
  let d = new Date(),
284
- ts = d.getFullYear() + (d.getMonth() + 1).toString().padStart(2, '0') + d.getDate().toString().padStart(2, '0') + d.getHours().toString().padStart(2, '0') + d.getMinutes().toString().padStart(2, '0') + d.getSeconds().toString().padStart(2, '0')
293
+ ts = d.getFullYear() + (d.getMonth() + 1).toString().padStart(2, '0') + d.getDate().toString().padStart(2, '0') + d.getHours().toString().padStart(2, '0') + d.getMinutes().toString().padStart(2, '0') + d.getSeconds().toString().padStart(2, '0');
285
294
 
286
295
  var a = document.createElement('A');
287
296
  a.style.display = 'none';
@@ -433,7 +442,7 @@ console.log('set translation snap', ev.data, ev);
433
442
  editObjectCloneWireframe(obj, parent, material, constrain) {
434
443
  let newobj = null;
435
444
  if (obj instanceof THREE.Mesh) {
436
- newobj = new THREE.Mesh(obj.geometry, material)
445
+ newobj = new THREE.Mesh(obj.geometry, material);
437
446
  newobj.matrixAutoUpdate = false;
438
447
  newobj.matrix.copy(obj.matrix);
439
448
  //newobj.matrixWorld.copy(obj.matrix);
@@ -694,7 +703,7 @@ obj.opacity = obj.opacity;
694
703
  if ('min' in attrdef && 'max' in attrdef) {
695
704
  min = attrdef.min;
696
705
  max = attrdef.max;
697
- amount *= (max - min) / divisor;
706
+ amount *= (max - min) / divisor;
698
707
  } else {
699
708
  amount /= divisor;
700
709
  }
@@ -1104,11 +1113,14 @@ console.log('change color', obj.col, vec);
1104
1113
  }
1105
1114
  }
1106
1115
  this.history.push({type: 'addobjects', objects: objects});
1116
+ /*
1107
1117
  if (janus.engine.systems.admin.hidden) {
1108
1118
  janus.engine.systems.controls.requestPointerLock();
1109
1119
  }
1120
+ */
1110
1121
  }
1111
1122
  handleThingAdd(ev) {
1123
+ console.log('[editor] scene added a thing', ev);
1112
1124
  setTimeout(() => {
1113
1125
  this.scenetree.refreshList();
1114
1126
  }, 0);
@@ -1134,7 +1146,7 @@ console.log('change color', obj.col, vec);
1134
1146
  sync: true,
1135
1147
  pos: new elation.physics.vector3().copy(player.vectors.cursor_pos),
1136
1148
  persist: true
1137
- }
1149
+ };
1138
1150
  if (trimmedurl.length > 0) {
1139
1151
  var schemeidx = trimmedurl.indexOf(':');
1140
1152
  if (schemeidx != -1) {
@@ -1217,14 +1229,26 @@ console.log('change color', obj.col, vec);
1217
1229
  // handle them (eg, video). However, CORS is a nightmare, and most servers don't whitelist Range headers.
1218
1230
 
1219
1231
  // If mime type detection fails, we could also check for known signatures in the first 1k of data, but we don't do that here yet
1232
+ if (false) {
1220
1233
  let proxiedurl = url;
1221
- if (elation.engine.assets.corsproxy && !url.match(/^https?:\/\/localhost/) && !url.match(/^data:/)) {
1234
+ if (elation.engine.assets.corsproxy && !url.match(/^https?:\/\/localhost/) && !url.match(/^data:/) && !url.match(/^janus-vfs:/)) {
1222
1235
  proxiedurl = elation.engine.assets.corsproxy + url;
1223
1236
  }
1224
1237
  fetch(proxiedurl, { headers: { /*'Range': 'bytes=0-1023'}*/ }}).then(res => resolve(res.headers.get('content-type')))
1225
1238
  .catch((e) => {
1226
1239
  reject();
1227
1240
  });
1241
+ } else {
1242
+ elation.engine.assetdownloader.fetchURL(url).then(ev => {
1243
+ let res = ev.target;
1244
+ if (res.headers) {
1245
+ resolve(res.headers.get('content-type'));
1246
+ } else {
1247
+ // FIXME - no headers, unknown type
1248
+ resolve();
1249
+ }
1250
+ });
1251
+ }
1228
1252
  });
1229
1253
  }
1230
1254
  loadObjectFromJML(jml) {
@@ -1239,7 +1263,8 @@ console.log('change color', obj.col, vec);
1239
1263
  args = {
1240
1264
  id: name,
1241
1265
  pos: player.vectors.cursor_pos.clone(),
1242
- sync: true
1266
+ sync: true,
1267
+ persist: true,
1243
1268
  },
1244
1269
  assetargs = {
1245
1270
  id: name,
@@ -1508,6 +1533,381 @@ elation.elements.define('janus.ui.editor.scenetree', class extends elation.eleme
1508
1533
  elation.events.fire({type: 'select', element: this, data: ev.data.value.getProxyObject()});
1509
1534
  }
1510
1535
  });
1536
+ elation.elements.define('janus.ui.editor.source', class extends elation.elements.base {
1537
+ async create() {
1538
+ await janus.ui.apps.default.apps.editor.loadScriptsAndCSS([
1539
+ './codemirror/addon/hint/show-hint.js',
1540
+ './codemirror/addon/hint/xml-hint.js',
1541
+ './codemirror/addon/hint/javascript-hint.js',
1542
+ './codemirror/keymap/vim.js',
1543
+ ], [
1544
+ './codemirror/addon/hint/show-hint.css',
1545
+ ]);
1546
+ await room.loadComponentList();
1547
+ this.jmlhints = this.buildJMLMap();
1548
+
1549
+ this.tabs = elation.elements.create('ui-tabs', { append: this });
1550
+ //let roomtab = elation.elements.create('ui-tab', { append: this.tabs, label: 'Room Markup' });
1551
+ let roomedit = elation.elements.create('janus-ui-editor-source-file', { append: this.tabs, label: 'Room Markup', source: room.getRoomSource(), hints: this.jmlhints });
1552
+
1553
+ if (room.roomassets.script) {
1554
+ for (let k in room.roomassets.script) {
1555
+ let scriptasset = room.roomassets.script[k];
1556
+ //let scripttab = elation.elements.create('ui-tab', { append: this.tabs, label: k });
1557
+ let scriptedit = elation.elements.create('janus-ui-editor-source-file', { append: this.tabs, label: k, source: scriptasset.code, mode: 'javascript' });
1558
+ }
1559
+ }
1560
+ }
1561
+ buildJMLMap() {
1562
+ let tagMap = {};
1563
+ for (let tag in janus.customElements) tagMap[tag] = janus.customElements[tag];
1564
+ for (let tag in room.customElements) tagMap[tag] = room.customElements[tag];
1565
+ let allTags = Object.keys(tagMap).sort();
1566
+
1567
+ let hints = {
1568
+ "!top": ["janus-viewer"],
1569
+ "fireboxroom": {
1570
+ children: ['assets', 'room'],
1571
+ },
1572
+ "janus-viewer": {
1573
+ children: ['assets', 'room'],
1574
+ },
1575
+ 'assets': {
1576
+ children: ['assetimage', 'assetobject', 'assetfont', 'assetwebsurface', 'assetscript', 'assetsound', 'assetvideo', 'assetshader', 'assetghost'],
1577
+ },
1578
+ 'room': {
1579
+ attrs: {},
1580
+ children: allTags,
1581
+ },
1582
+ 'assetimage': {
1583
+ attrs: this.getAssetAttributes('image'),
1584
+ },
1585
+ 'assetobject': {
1586
+ attrs: this.getAssetAttributes('model'),
1587
+ },
1588
+ 'assetfont': {
1589
+ attrs: this.getAssetAttributes('font'),
1590
+ },
1591
+ 'assetwebsurface': {
1592
+ attrs: {
1593
+ id: null,
1594
+ src: null,
1595
+ },
1596
+ },
1597
+ 'assetscript': {
1598
+ attrs: this.getAssetAttributes('script'),
1599
+ },
1600
+ 'assetsound': {
1601
+ attrs: this.getAssetAttributes('sound'),
1602
+ },
1603
+ 'assetvideo': {
1604
+ attrs: this.getAssetAttributes('video'),
1605
+ },
1606
+ 'assetshader': {
1607
+ attrs: this.getAssetAttributes('shader'),
1608
+ },
1609
+ 'assetghost': {
1610
+ attrs: {
1611
+ id: null,
1612
+ src: null,
1613
+ },
1614
+ }
1615
+ };
1616
+ hints.Room = hints.room;
1617
+ hints.FireBoxRoom = hints.fireboxroom;
1618
+ hints.Assets = hints.assets;
1619
+ hints.AssetImage = hints.assetimage;
1620
+ hints.AssetObject = hints.assetobject;
1621
+ hints.AssetFont = hints.assetfont;
1622
+ hints.AssetWebsurface = hints.assetwebsurface;
1623
+ hints.AssetScript = hints.assetscript;
1624
+ hints.AssetSound = hints.assetsound;
1625
+ hints.AssetVideo = hints.assetvideo;
1626
+ hints.AssetShader = hints.assetshader;
1627
+ hints.AssetGhost = hints.assetghost;
1628
+
1629
+ let roomattrs = this.getAttributes({classname: 'janusroom'}, room);
1630
+ let roomattrkeys = Object.keys(roomattrs).sort();
1631
+ roomattrkeys.forEach(attrname => {
1632
+ if (attrname != 'requires') { // We'll handle <room require="..."> as a special case, partly because of the name mismatch and partly so we can autosuggest components from the repository
1633
+ let attr = roomattrs[attrname];
1634
+ hints['room'].attrs[attrname] = (attr.type == 'boolean' || attr.types == 'bool' ? ['true', 'false'] : null);
1635
+ } else {
1636
+ hints['room'].attrs.require = Object.keys(room.componentrepository).sort();;
1637
+ }
1638
+ });
1639
+
1640
+ hints['room'].attrDelims = { require: ' ' };
1641
+
1642
+ for (let i = 0; i < allTags.length; i++) {
1643
+ let tag = allTags[i],
1644
+ tagdef = tagMap[tag];
1645
+ let attrs = this.getAttributes(tagdef);
1646
+
1647
+ hints[tag] = {
1648
+ attrs: {},
1649
+ children: allTags,
1650
+ };
1651
+ hints[elation.utils.camelize('.' + tag)] = hints[tag]; // capitalize first letter of tag, mapped to the all-lowercase tag definition
1652
+
1653
+ let attrkeys = Object.keys(attrs).sort();
1654
+ attrkeys.forEach(attrname => {
1655
+ let attr = attrs[attrname];
1656
+ hints[tag].attrs[attrname] = (attr.type == 'boolean' || attr.types == 'bool' ? ['true', 'false'] : null);
1657
+ });
1658
+ }
1659
+
1660
+ // Autocomplete asset ids of various types
1661
+ hints.object.attrs.id =
1662
+ hints.object.attrs.collision_id =
1663
+ hints.particle.attrs.emitter_id =
1664
+ cm => this.getAssetSuggestions('model');
1665
+
1666
+ hints.object.attrs.image_id =
1667
+ hints.object.attrs.normalmap_id =
1668
+ hints.object.attrs.roughness_id =
1669
+ hints.object.attrs.metalness_id =
1670
+ hints.object.attrs.displacementmap_id =
1671
+ hints.object.attrs.emissive_id =
1672
+ hints.object.attrs.alphamap_id =
1673
+ hints.object.attrs.envmap_id =
1674
+ hints.object.attrs.lmap_id =
1675
+ hints.object.attrs.lmap_id =
1676
+ hints.image.attrs.id =
1677
+ hints.image3d.attrs.id =
1678
+ hints.particle.attrs.image_id =
1679
+ hints.link.attrs.thumb_id =
1680
+ hints.room.attrs.skybox_up_id =
1681
+ hints.room.attrs.skybox_down_id =
1682
+ hints.room.attrs.skybox_left_id =
1683
+ hints.room.attrs.skybox_right_id =
1684
+ hints.room.attrs.skybox_front_id =
1685
+ hints.room.attrs.skybox_back_id =
1686
+ hints.room.attrs.skybox_equi =
1687
+ cm => this.getAssetSuggestions('image');
1688
+
1689
+ hints.object.attrs.video_id =
1690
+ hints.video.attrs.video_id =
1691
+ cm => this.getAssetSuggestions('video');
1692
+
1693
+ hints.object.attrs.shader_id =
1694
+ hints.link.attrs.shader_id =
1695
+ cm => this.getAssetSuggestions('shader');
1696
+
1697
+ hints.text.attrs.font = cm => this.getAssetSuggestions('font');
1698
+ hints.sound.attrs.id = cm => this.getAssetSuggestions('sound');
1699
+
1700
+ hints.object.attrs.cull_face =
1701
+ hints.paragraph.attrs.cull_face =
1702
+ ['back', 'front', 'none'];
1703
+
1704
+ hints.object.blend_src =
1705
+ hints.object.blend_dest =
1706
+ ['zero', 'one', 'src_color', 'dst_color', 'src_alpha', 'dst_alpha', 'one_minus_src_color', 'one_minus_src_alpha', 'one_minus_dst_color', 'one_minus_dst_alpha'];
1707
+
1708
+ hints.room.attrs.fog_mode = ['linear', 'exp', 'exp2'];
1709
+ hints.room.attrs.tonemapping_type = Object.keys(room.toneMappingTypes);
1710
+
1711
+ return hints;
1712
+ }
1713
+ getAssetSuggestions(assettype) {
1714
+ let hints = [];
1715
+ if (janus.assetpack.assetmap[assettype]) Array.prototype.push.apply(hints, Object.keys(janus.assetpack.assetmap[assettype]));
1716
+ if (room.assetpack && room.assetpack.assetmap[assettype]) Array.prototype.push.apply(hints, Object.keys(room.assetpack.assetmap[assettype]));
1717
+
1718
+ return hints.sort();
1719
+ }
1720
+ getAttributes(objdef, bindobj) {
1721
+ console.log('parse the object', objdef);
1722
+ let elationThing = elation.engine.things[objdef.classname];
1723
+ let allProperties = this.parseThingProperties(elationThing, null, bindobj);
1724
+
1725
+ if (!(objdef.class instanceof Function)) {
1726
+ for (let attrname in objdef.class) {
1727
+ let attr = objdef.class[attrname];
1728
+ let attrtype = (attr === true || attr === false ? 'boolean' : 'whatever');
1729
+ allProperties.properties[attrname] = { type: attrtype };
1730
+ allProperties.proxies[attrname] = ['property', attrname];
1731
+ }
1732
+ }
1733
+
1734
+ let attrs = {};
1735
+ if (allProperties) {
1736
+ for (let k in allProperties.proxies) {
1737
+ let p = allProperties.proxies[k];
1738
+ if (p[0] == 'property' && allProperties.properties[p[1]]) {
1739
+ let attr = allProperties.properties[p[1]];
1740
+ if (attr.type != 'object') { // Skip object types, since they're generally only used internally
1741
+ attrs[k] = attr;
1742
+ }
1743
+ } else if (p[0] == 'callback') {
1744
+ attrs[k] = { type: 'callback' };
1745
+ }
1746
+ }
1747
+ }
1748
+ return attrs;
1749
+ }
1750
+ getAssetAttributes(assetname) {
1751
+ let attrs = {},
1752
+ props = this.parseAssetProperties(assetname);
1753
+ let propkeys = Object.keys(props).sort();
1754
+ for (let i = 0; i < propkeys.length; i++) {
1755
+ attrs[propkeys[i]] = (props[propkeys[i]].type == 'boolean' ? ['true', 'false'] : null);
1756
+ }
1757
+ return attrs;
1758
+ }
1759
+ parseAssetProperties(assetname) {
1760
+ let props = {};
1761
+ if (elation.engine.assets[assetname]) {
1762
+ let prot = elation.engine.assets[assetname].prototype;
1763
+ let exclude = ['assettype', 'assetpack', 'instances', 'baseurl', 'preview', 'loaded', 'size', 'proxy', 'sourceurl', 'author', 'license', 'description', 'frames', 'canvas', 'rawimage', 'texture', 'video'];
1764
+ for (let k in prot) {
1765
+ if (typeof prot[k] != 'function' && exclude.indexOf(k) == -1) {
1766
+ let attrtype = (prot[k] === true || prot[k] === false ? 'boolean' : 'whatever');
1767
+ let propname = (k == 'name' ? 'id' : k);
1768
+ props[propname] = { type: attrtype };
1769
+ }
1770
+ }
1771
+ }
1772
+ return props;
1773
+ }
1774
+ parseThingProperties(thing, props, bindobj) {
1775
+ if (!props) props = {
1776
+ properties: {},
1777
+ proxies: {}
1778
+ };
1779
+
1780
+ if (thing.extendclassdef) {
1781
+ let parentThing = thing.extendclassdef;
1782
+ this.parseThingProperties(parentThing, props);
1783
+ }
1784
+
1785
+ let mProps = thing.classdef.toString().match(/defineProperties\(({.*?})\)/ms);
1786
+ let mProxies = thing.classdef.toString().match(/(new elation\.proxy\(this, |_proxydefs = )({.*?})[;|\)]/ms);
1787
+ (elation.bind(bindobj || this, function() {
1788
+ if (mProps) {
1789
+ let propmap;
1790
+ eval('propmap = ' + mProps[1]);
1791
+ for (let k in propmap) props.properties[k] = propmap[k];
1792
+ }
1793
+ if (mProxies) {
1794
+ let proxymap;
1795
+ eval('proxymap = ' + mProxies[2]);
1796
+ for (let k in proxymap) props.proxies[k] = proxymap[k];
1797
+ }
1798
+ }))();
1799
+ return props;
1800
+ }
1801
+ });
1802
+ elation.elements.define('janus.ui.editor.source.file', class extends elation.elements.ui.tab {
1803
+ init() {
1804
+ super.init();
1805
+ this.defineAttributes({
1806
+ source: { type: 'string' },
1807
+ filename: { type: 'string', default: 'New File' },
1808
+ mode: { type: 'string', default: 'xml' },
1809
+ hints: { type: 'object' },
1810
+ });
1811
+ }
1812
+ create() {
1813
+ this.filename = this.label;
1814
+
1815
+ this.initCodemirror();
1816
+ elation.events.add(this.parentNode, 'tabselect', ev => { this.codemirror.refresh(); setTimeout(() => { this.codemirror.focus(); }, 0); });
1817
+ }
1818
+ async initCodemirror() {
1819
+ if (!CodeMirror.modes[this.mode]) {
1820
+ await janus.ui.apps.default.apps.editor.loadScriptsAndCSS([`./codemirror/mode/${this.mode}/${this.mode}.js`]);
1821
+ }
1822
+
1823
+ this.codemirror = CodeMirror(this, {
1824
+ value: this.source,
1825
+ mode: this.mode,
1826
+ lineNumbers: true,
1827
+ extraKeys: {
1828
+ 'Ctrl-S': () => this.handleSave(),
1829
+ 'Ctrl-Space':(cm) => { CodeMirror.showHint(cm, CodeMirror.hint[this.mode]); },
1830
+ 'Ctrl-Alt-V':(cm) => {
1831
+ if (cm.state.keyMaps.indexOf(CodeMirror.keyMap.vim) != -1) {
1832
+ // FIXME - removing the keymap doesn't actually work, the bindings stay active
1833
+ cm.removeKeyMap(CodeMirror.keyMap.vim);
1834
+ } else {
1835
+ cm.addKeyMap(CodeMirror.keyMap.vim);
1836
+ }
1837
+ cm.refresh();
1838
+ },
1839
+ },
1840
+ hintOptions: {
1841
+ autohint: true,
1842
+ schemaInfo: this.hints,
1843
+ matchInMiddle: true,
1844
+ },
1845
+ });
1846
+ console.log('editor hints', this.hints);
1847
+ this.codemirror.on('change', (ev) => this.handleEditContentChange(ev));
1848
+ this.codemirror.on('change', (ev) => this.handleEditContentChange(ev));
1849
+
1850
+ let skipKeyCodes = [
1851
+ 8, // backspace
1852
+ 9, // tab
1853
+ 13, // enter
1854
+ 16, // shift
1855
+ 17, // ctrl
1856
+ 18, // alt
1857
+ 27, // esc
1858
+ //32, // space
1859
+ 33, // pgup
1860
+ 34, // pgdn
1861
+ 35, // home
1862
+ 36, // end
1863
+ 37, // left
1864
+ 38, // up
1865
+ 39, // right
1866
+ 40, // down
1867
+ 46, // delete
1868
+
1869
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, // 0-9
1870
+ 186, // ;
1871
+ 189, // -
1872
+ 219, // {
1873
+ 221, // }
1874
+ ];
1875
+ if (this.mode == 'javascript') {
1876
+ skipKeyCodes.push(32); // space
1877
+ skipKeyCodes.push(187); // =
1878
+ } else if (this.mode == 'xml') {
1879
+ skipKeyCodes.push(190); // . and >
1880
+ }
1881
+ this.codemirror.on("keyup", function (cm, event) {
1882
+ if ((!cm.state.completionActive && /*Enables keyboard navigation in autocomplete list*/
1883
+ !event.ctrlKey && !event.altKey &&
1884
+ skipKeyCodes.indexOf(event.keyCode) == -1)) { /*Enter - do not open autocomplete list just after item has been selected in it*/
1885
+ CodeMirror.commands.autocomplete(cm, null, {completeSingle: false});
1886
+ }
1887
+ });
1888
+ }
1889
+ handleSave() {
1890
+ this.source = this.codemirror.getValue();
1891
+ this.label = this.filename;
1892
+ }
1893
+ handleEditContentChange(ev) {
1894
+ //console.log('it changed', ev);
1895
+ let newsource = this.codemirror.getValue();
1896
+ this.dirty = (newsource != this.source);
1897
+ if (this.dirty) {
1898
+ this.label = '*' + this.filename;
1899
+ } else {
1900
+ this.label = this.filename;
1901
+ }
1902
+ if (this.updatetimer) {
1903
+ clearTimeout(this.updatetimer);
1904
+ }
1905
+ this.updatetimer = setTimeout(() => {
1906
+ room.updateSource(newsource);
1907
+ this.updatetimer = false;
1908
+ }, 500);
1909
+ }
1910
+ });
1511
1911
 
1512
1912
  class ColorTransform extends THREE.Object3D {
1513
1913
 
@@ -3,10 +3,13 @@
3
3
  "janus.ui.editor.panel": "./editor-panel.html",
4
4
  "janus.ui.editor.object.info": "./editor-object-info.html"
5
5
  },
6
- "scripts": ["./editor.js", "./editor-properties.js"],
7
- "css": ["./editor.css"],
6
+ "scripts": ["./editor.js", "./editor-properties.js", "./codemirror/lib/codemirror.js"],
7
+ "css": ["./editor.css", "./codemirror/lib/codemirror.css", "./codemirror/lib/jmldark.css"],
8
8
  "components": [
9
- "janus-ui-editor-panel"
9
+ "janus-ui-editor-panel",
10
+ "janus-ui-editor-objectinfo",
11
+ "janus-ui-editor-scenetree",
12
+ "janus-ui-editor-source"
10
13
  ]
11
14
  }
12
15
 
@@ -37,6 +37,7 @@
37
37
  <ui-tab label="Room Assets">
38
38
  <janus-ui-inventory-roomassets></janus-ui-inventory-roomassets>
39
39
  </ui-tab>
40
+ <!-- Disabled Google Poly - maybe one day ICOSA Gallery or someone else will offer the old Google Blocks API again
40
41
  <ui-tab label="Google Poly">
41
42
  <ui-flexpanel id="poly" vertical>
42
43
  <ui-input noflex placeholder="Search for Google Poly models" onaccept="let models = document.getElementById('models'); models.apiargs.keywords = this.value; delete models.apiargs.pageToken; document.getElementById('itemlist').clear(); models.load(); pagination.disabled = false;"></ui-input>
@@ -44,16 +45,18 @@
44
45
  <ui-button noflex id="pagination" onclick="let models = document.getElementById('models'); if (models.rawdata.nextPageToken) { models.apiargs.pageToken = models.rawdata.nextPageToken; models.append(); } else { this.disabled = true; }">Load More</ui-button>
45
46
  </ui-flexpanel>
46
47
  </ui-tab>
47
-
48
+ -->
48
49
  <ui-tab label="Vesta">
49
50
  <h3>Vesta integration coming soon!</h3>
50
51
  <p>When it's ready, you'll be able to access assets you've stored on your Vesta account, and bring them with you anywhere you go.</p>
51
52
  <p><a href="https://vesta.janusvr.com/">Sign up for a vesta account today</a></p>
52
53
  </ui-tab>
53
54
  <ui-tab label="Import">
54
- <h3>Did you know?</h3>
55
- <p>You can drag 3d models, images, videos, and sounds into Janus rooms from other websites, or even your local hard drive!</p>
56
- <p>Just select the files, drag them over, and drop them into the world. Then use our in-world editing tools to place it where you want it to be.</p>
55
+ <div>
56
+ <h3>Did you know!?</h3>
57
+ <p>You can drag 3d models, images, videos, and sounds into Janus rooms from other websites, or even your local hard drive!</p>
58
+ <p>Just select the files, drag them over, and drop them into the world. Then use our in-world editing tools to place it where you want it to be.</p>
59
+ </div>
57
60
  </ui-tab>
58
61
  </ui-tabs>
59
62
 
@@ -6,7 +6,7 @@ elation.elements.define('janus.ui.inventory', class extends elation.elements.bas
6
6
  console.log('INVENTORY ELEMENTS', elements);
7
7
  if (elements.primitives) {
8
8
  elation.events.add(elements.primitives, 'select', (ev) => this.handlePrimitiveSelect(ev));
9
- elation.events.add(elements.polyobjects, 'select', (ev) => this.handleAssetSelect(ev));
9
+ //elation.events.add(elements.polyobjects, 'select', (ev) => this.handleAssetSelect(ev));
10
10
  }
11
11
  }
12
12
  addSource(name, collection) {
@@ -68,7 +68,7 @@ elation.elements.define('janus.ui.inventory.roomassets.list', class extends elat
68
68
  this.list.setItems(this.getAssetList());
69
69
  }
70
70
  getAssetList() {
71
- if (room.assetpack.assetmap[this.assettype]) {
71
+ if (room.assetpack && room.assetpack.assetmap[this.assettype]) {
72
72
  return room.assetpack.assetmap[this.assettype];
73
73
  }
74
74
  return {};
@@ -18,7 +18,7 @@ janus.registerElement('locomotion_teleporter', {
18
18
  shadow: false,
19
19
  shadow_cast: false,
20
20
  shadow_receive: false,
21
- renderorder: 20,
21
+ renderorder: 51,
22
22
  depth_test: false,
23
23
  depth_write: false,
24
24
  });
@@ -31,7 +31,7 @@ janus.registerElement('locomotion_teleporter', {
31
31
  shadow: false,
32
32
  shadow_cast: false,
33
33
  shadow_receive: false,
34
- renderorder: 10,
34
+ renderorder: 50,
35
35
  });
36
36
  this.pointer = this.marker.createObject('Object', {
37
37
  id: 'pyramid',
@@ -44,6 +44,7 @@ janus.registerElement('locomotion_teleporter', {
44
44
  shadow: false,
45
45
  shadow_cast: false,
46
46
  shadow_receive: false,
47
+ renderorder: 52,
47
48
  });
48
49
  /*
49
50
  this.light = this.createObject('Light', {
@@ -82,7 +83,7 @@ janus.registerElement('locomotion_teleporter', {
82
83
  depth_write: false,
83
84
  shadow_cast: false,
84
85
  shadow_receive: false,
85
- renderorder: 100,
86
+ renderorder: 1000,
86
87
  visible: false,
87
88
  });
88
89
 
@@ -124,8 +125,8 @@ janus.registerElement('locomotion_teleporter', {
124
125
  });
125
126
  this.activateControlContext('teleporter');
126
127
 
127
- room.addEventListener('mousedown', (ev) => this.handleMouseDown(ev));
128
- room.addEventListener('mouseup', (ev) => this.handleMouseUp(ev));
128
+ //room.addEventListener('mousedown', (ev) => this.handleMouseDown(ev));
129
+ //room.addEventListener('mouseup', (ev) => this.handleMouseUp(ev));
129
130
  elation.events.add(janus._target, 'room_change', (ev) => this.handleRoomChange(ev));
130
131
  },
131
132
  update() {
@@ -153,7 +154,7 @@ janus.registerElement('locomotion_teleporter', {
153
154
  let laserpoints = this.laser.positions;
154
155
  // Trace our arc in steps, performing a raytrace at each step
155
156
  for (i = 0; i < segments; i++) {
156
- let t = (i + 1) * duration / segments
157
+ let t = (i + 1) * duration / segments;
157
158
  dir.copy(v0);
158
159
  speed = dir.length();
159
160
  dir.divideScalar(speed);
@@ -184,7 +185,7 @@ janus.registerElement('locomotion_teleporter', {
184
185
  }
185
186
  }
186
187
  this.laser.updateLine();
187
- if (this.laser.room !== room) room.appendChild(this.laser);
188
+ if (this.laser.room !== room._target) room.appendChild(this.laser);
188
189
  this.pointer.orientation._target.setFromEuler(new THREE.Euler(Math.PI/2, this.teleportangle, 0, "YXZ"));
189
190
  } else {
190
191
  if (this.shroud.visible) {
@@ -327,8 +328,8 @@ janus.registerElement('locomotion_teleporter', {
327
328
  if (!room.teleport) return;
328
329
  this.visible = true;
329
330
  this.particles.visible = true;
330
- if (this.laser.room !== room) room.appendChild(this.laser);
331
- if (this.particles.room !== room) room.appendChild(this.particles);
331
+ if (this.laser.room !== room._target) room.appendChild(this.laser);
332
+ if (this.particles.room !== room._target) room.appendChild(this.particles);
332
333
  this.laser.visible = true;
333
334
  this.active = true;
334
335
  this.particles.start();