janusweb 1.5.33 → 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.
- package/CHANGELOG +39 -0
- package/media/assets/webui/apps/avatar/avatar.js +2 -1
- package/media/assets/webui/apps/comms/voip.js +2 -4
- package/media/assets/webui/apps/editor/codemirror/addon/hint/javascript-hint.js +162 -0
- package/media/assets/webui/apps/editor/codemirror/addon/hint/show-hint.css +36 -0
- package/media/assets/webui/apps/editor/codemirror/addon/hint/show-hint.js +529 -0
- package/media/assets/webui/apps/editor/codemirror/addon/hint/xml-hint.js +140 -0
- package/media/assets/webui/apps/editor/codemirror/keymap/vim.js +5734 -0
- package/media/assets/webui/apps/editor/codemirror/lib/codemirror.css +350 -0
- package/media/assets/webui/apps/editor/codemirror/lib/codemirror.js +9800 -0
- package/media/assets/webui/apps/editor/codemirror/lib/jmldark.css +33 -0
- package/media/assets/webui/apps/editor/codemirror/mode/css/css.js +864 -0
- package/media/assets/webui/apps/editor/codemirror/mode/htmlmixed/htmlmixed.js +153 -0
- package/media/assets/webui/apps/editor/codemirror/mode/javascript/javascript.js +942 -0
- package/media/assets/webui/apps/editor/codemirror/mode/xml/xml.js +413 -0
- package/media/assets/webui/apps/editor/editor.css +3 -0
- package/media/assets/webui/apps/editor/editor.js +407 -9
- package/media/assets/webui/apps/editor/editor.json +6 -3
- package/media/assets/webui/apps/inventory/inventory.js +1 -1
- package/media/assets/webui/apps/locomotion/teleporter.js +1 -1
- package/media/assets/webui/apps/navigation/navigation.js +12 -12
- package/media/assets/webui/apps/vfs/browserfs/browserfs.js +8 -0
- package/media/assets/webui/apps/vfs/vfs.css +52 -0
- package/media/assets/webui/apps/vfs/vfs.js +452 -0
- package/media/assets/webui/apps/vfs/vfs.json +10 -0
- package/media/assets/webui/default.json +2 -1
- package/media/assets/webui/themes/default.css +29 -2
- package/package.json +2 -9
- package/scripts/client.js +64 -44
- package/scripts/elements/linesegments.js +5 -2
- package/scripts/janusbase.js +21 -9
- package/scripts/janusghost.js +0 -1
- package/scripts/janusparagraph.js +5 -3
- package/scripts/janusparticle.js +11 -12
- package/scripts/janusplayer.js +2 -2
- package/scripts/janusweb.js +21 -2
- package/scripts/janusxrplayer.js +3 -0
- package/scripts/multiplayermanager.js +3 -3
- package/scripts/object.js +159 -82
- package/scripts/portal.js +2 -3
- package/scripts/room.js +86 -44
- package/scripts/sound.js +0 -1
- package/scripts/text.js +10 -2
- package/scripts/translators/janusvfs.js +20 -0
- package/scripts/video.js +1 -1
- package/scripts/websurface.js +11 -2
|
@@ -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.
|
|
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
|
-
|
|
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
|
}
|
|
@@ -1111,6 +1120,7 @@ console.log('change color', obj.col, vec);
|
|
|
1111
1120
|
*/
|
|
1112
1121
|
}
|
|
1113
1122
|
handleThingAdd(ev) {
|
|
1123
|
+
console.log('[editor] scene added a thing', ev);
|
|
1114
1124
|
setTimeout(() => {
|
|
1115
1125
|
this.scenetree.refreshList();
|
|
1116
1126
|
}, 0);
|
|
@@ -1136,7 +1146,7 @@ console.log('change color', obj.col, vec);
|
|
|
1136
1146
|
sync: true,
|
|
1137
1147
|
pos: new elation.physics.vector3().copy(player.vectors.cursor_pos),
|
|
1138
1148
|
persist: true
|
|
1139
|
-
}
|
|
1149
|
+
};
|
|
1140
1150
|
if (trimmedurl.length > 0) {
|
|
1141
1151
|
var schemeidx = trimmedurl.indexOf(':');
|
|
1142
1152
|
if (schemeidx != -1) {
|
|
@@ -1219,14 +1229,26 @@ console.log('change color', obj.col, vec);
|
|
|
1219
1229
|
// handle them (eg, video). However, CORS is a nightmare, and most servers don't whitelist Range headers.
|
|
1220
1230
|
|
|
1221
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) {
|
|
1222
1233
|
let proxiedurl = url;
|
|
1223
|
-
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:/)) {
|
|
1224
1235
|
proxiedurl = elation.engine.assets.corsproxy + url;
|
|
1225
1236
|
}
|
|
1226
1237
|
fetch(proxiedurl, { headers: { /*'Range': 'bytes=0-1023'}*/ }}).then(res => resolve(res.headers.get('content-type')))
|
|
1227
1238
|
.catch((e) => {
|
|
1228
1239
|
reject();
|
|
1229
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
|
+
}
|
|
1230
1252
|
});
|
|
1231
1253
|
}
|
|
1232
1254
|
loadObjectFromJML(jml) {
|
|
@@ -1241,7 +1263,8 @@ console.log('change color', obj.col, vec);
|
|
|
1241
1263
|
args = {
|
|
1242
1264
|
id: name,
|
|
1243
1265
|
pos: player.vectors.cursor_pos.clone(),
|
|
1244
|
-
sync: true
|
|
1266
|
+
sync: true,
|
|
1267
|
+
persist: true,
|
|
1245
1268
|
},
|
|
1246
1269
|
assetargs = {
|
|
1247
1270
|
id: name,
|
|
@@ -1510,6 +1533,381 @@ elation.elements.define('janus.ui.editor.scenetree', class extends elation.eleme
|
|
|
1510
1533
|
elation.events.fire({type: 'select', element: this, data: ev.data.value.getProxyObject()});
|
|
1511
1534
|
}
|
|
1512
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
|
+
});
|
|
1513
1911
|
|
|
1514
1912
|
class ColorTransform extends THREE.Object3D {
|
|
1515
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
|
|
|
@@ -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 {};
|
|
@@ -154,7 +154,7 @@ janus.registerElement('locomotion_teleporter', {
|
|
|
154
154
|
let laserpoints = this.laser.positions;
|
|
155
155
|
// Trace our arc in steps, performing a raytrace at each step
|
|
156
156
|
for (i = 0; i < segments; i++) {
|
|
157
|
-
let t = (i + 1) * duration / segments
|
|
157
|
+
let t = (i + 1) * duration / segments;
|
|
158
158
|
dir.copy(v0);
|
|
159
159
|
speed = dir.length();
|
|
160
160
|
dir.divideScalar(speed);
|
|
@@ -16,12 +16,12 @@ elation.elements.define('janus.ui.navigation', class extends elation.elements.ui
|
|
|
16
16
|
getClient() {
|
|
17
17
|
var node = this;
|
|
18
18
|
while (node && node !== document) {
|
|
19
|
-
if (node
|
|
20
|
-
return
|
|
19
|
+
if (node instanceof elation.elements.janusweb.client) {
|
|
20
|
+
return node;
|
|
21
21
|
}
|
|
22
|
-
node = node.parentNode
|
|
22
|
+
node = node.parentNode;
|
|
23
23
|
}
|
|
24
|
-
return
|
|
24
|
+
return document.querySelector('janusweb-client');
|
|
25
25
|
}
|
|
26
26
|
updateCurrentURL() {
|
|
27
27
|
var room = this.janusweb.currentroom;
|
|
@@ -86,12 +86,12 @@ elation.elements.define('janus.ui.statusindicator', class extends elation.elemen
|
|
|
86
86
|
getClient() {
|
|
87
87
|
var node = this;
|
|
88
88
|
while (node && node !== document) {
|
|
89
|
-
if (node
|
|
90
|
-
return
|
|
89
|
+
if (node instanceof elation.elements.janusweb.client) {
|
|
90
|
+
return node;
|
|
91
91
|
}
|
|
92
|
-
node = node.parentNode
|
|
92
|
+
node = node.parentNode;
|
|
93
93
|
}
|
|
94
|
-
return
|
|
94
|
+
return document.querySelector('janusweb-client');
|
|
95
95
|
}
|
|
96
96
|
updateCurrentURL(room) {
|
|
97
97
|
if (!room && this.janusweb.currentroom) {
|
|
@@ -334,12 +334,12 @@ elation.elements.define('janus.ui.urlbar', class extends elation.elements.ui.pan
|
|
|
334
334
|
getClient() {
|
|
335
335
|
var node = this;
|
|
336
336
|
while (node && node !== document) {
|
|
337
|
-
if (node
|
|
338
|
-
return
|
|
337
|
+
if (node instanceof elation.elements.janusweb.client) {
|
|
338
|
+
return node;
|
|
339
339
|
}
|
|
340
|
-
node = node.parentNode
|
|
340
|
+
node = node.parentNode;
|
|
341
341
|
}
|
|
342
|
-
return
|
|
342
|
+
return document.querySelector('janusweb-client');
|
|
343
343
|
}
|
|
344
344
|
updateRoom() {
|
|
345
345
|
// Remove listeners from previous room
|