mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 18:21:16 +02:00
Add support for teleport, delete, and filtering in entity list
This commit is contained in:
parent
ce60a410cf
commit
9e8458edd9
3 changed files with 171 additions and 44 deletions
|
@ -2,13 +2,30 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="style.css">
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
|
<script src="list.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var entities = {};
|
var entities = {};
|
||||||
var selectedEntities = [];
|
var selectedEntities = [];
|
||||||
|
var currentSortColumn = 'type';
|
||||||
|
var currentSortOrder = 'asc';
|
||||||
|
var entityList = null;
|
||||||
|
var refreshEntityListTimer = null;
|
||||||
|
var ASC_STRING = ' ▾';
|
||||||
|
var DESC_STRING = ' ▴';
|
||||||
|
|
||||||
function loaded() {
|
function loaded() {
|
||||||
elEntityTable = document.getElementById("entity-table");
|
elEntityTable = document.getElementById("entity-table");
|
||||||
|
elEntityTableBody = document.getElementById("entity-table-body");
|
||||||
elRefresh = document.getElementById("refresh");
|
elRefresh = document.getElementById("refresh");
|
||||||
|
elDelete = document.getElementById("delete");
|
||||||
|
elTeleport = document.getElementById("teleport");
|
||||||
|
|
||||||
|
document.getElementById("entity-type").onclick = function() {
|
||||||
|
setSortColumn('type');
|
||||||
|
};
|
||||||
|
document.getElementById("entity-url").onclick = function() {
|
||||||
|
setSortColumn('url');
|
||||||
|
};
|
||||||
|
|
||||||
function onRowClicked(e) {
|
function onRowClicked(e) {
|
||||||
var id = this.dataset.entityId;
|
var id = this.dataset.entityId;
|
||||||
|
@ -40,14 +57,17 @@
|
||||||
|
|
||||||
function addEntity(id, type, url) {
|
function addEntity(id, type, url) {
|
||||||
if (entities[id] === undefined) {
|
if (entities[id] === undefined) {
|
||||||
|
var urlParts = url.split('/');
|
||||||
|
var filename = urlParts[urlParts.length - 1];
|
||||||
|
|
||||||
var el = document.createElement('tr');
|
var el = document.createElement('tr');
|
||||||
el.setAttribute('id', 'entity_' + id);
|
el.setAttribute('id', 'entity_' + id);
|
||||||
el.innerHTML += "<td>" + type + "</td>";
|
el.innerHTML += "<td class='type'>" + type + "</td>";
|
||||||
el.innerHTML += "<td>" + url + "</td>";
|
el.innerHTML += "<td class='url' title='" + url + "'><div class='outer'><div class='inner'>" + filename + "</div></div></td>";
|
||||||
el.dataset.entityId = id;
|
el.dataset.entityId = id;
|
||||||
el.onclick = onRowClicked;
|
el.onclick = onRowClicked;
|
||||||
el.ondblclick = onRowDoubleClicked;
|
el.ondblclick = onRowDoubleClicked;
|
||||||
elEntityTable.appendChild(el);
|
elEntityTableBody.appendChild(el);
|
||||||
|
|
||||||
// Add element to local dict
|
// Add element to local dict
|
||||||
entities[id] = {
|
entities[id] = {
|
||||||
|
@ -55,43 +75,94 @@
|
||||||
name: id,
|
name: id,
|
||||||
el: el,
|
el: el,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (refreshEntityListTimer) {
|
||||||
|
clearTimeout(refreshEntityListTimer);
|
||||||
|
}
|
||||||
|
refreshEntityListTimer = setTimeout(refreshEntityListObject, 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeEntity(id) {
|
function removeEntity(id) {
|
||||||
if (entities[id] !== undefined) {
|
if (entities[id] !== undefined) {
|
||||||
elEntityTable.removeChild(entities[id].el);
|
elEntityTableBody.removeChild(entities[id].el);
|
||||||
delete entities[id];
|
delete entities[id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearEntities() {
|
function clearEntities() {
|
||||||
for (id in entities) {
|
for (id in entities) {
|
||||||
elEntityTable.removeChild(entities[id].el);
|
elEntityTableBody.removeChild(entities[id].el);
|
||||||
}
|
}
|
||||||
entities = {};
|
entities = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
elRefresh.onclick = function() {
|
var elSortOrder = {
|
||||||
|
type: document.querySelector('#entity-type .sort-order'),
|
||||||
|
url: document.querySelector('#entity-url .sort-order'),
|
||||||
|
}
|
||||||
|
function setSortColumn(column) {
|
||||||
|
if (currentSortColumn == column) {
|
||||||
|
currentSortOrder = currentSortOrder == "asc" ? "desc" : "asc";
|
||||||
|
} else {
|
||||||
|
elSortOrder[currentSortColumn].style.display = 'none';
|
||||||
|
elSortOrder[column].style.display = 'inline';
|
||||||
|
currentSortColumn = column;
|
||||||
|
currentSortOrder = "asc";
|
||||||
|
}
|
||||||
|
console.log(currentSortColumn, currentSortOrder);
|
||||||
|
elSortOrder[column].innerHTML = currentSortOrder == "asc" ? ASC_STRING : DESC_STRING;
|
||||||
|
entityList.sort(currentSortColumn, { order: currentSortOrder });
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshEntities() {
|
||||||
clearEntities();
|
clearEntities();
|
||||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'refresh' }));
|
EventBridge.emitWebEvent(JSON.stringify({ type: 'refresh' }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function refreshEntityListObject() {
|
||||||
|
refreshEntityListTimer = null;
|
||||||
|
entityList = new List('entity-list', { valueNames: ['type', 'url']});
|
||||||
|
entityList.sort(currentSortColumn, { order: currentSortOrder });
|
||||||
|
entityList.search(document.getElementById("filter").value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSelectedEntities(selectedEntities) {
|
||||||
|
var notFound = false;
|
||||||
|
for (var id in entities) {
|
||||||
|
entities[id].el.className = '';
|
||||||
|
}
|
||||||
|
for (var i = 0; i < selectedEntities.length; i++) {
|
||||||
|
var id = selectedEntities[i];
|
||||||
|
if (id in entities) {
|
||||||
|
var entity = entities[id];
|
||||||
|
entity.el.className = 'selected';
|
||||||
|
} else {
|
||||||
|
notFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return notFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
elRefresh.onclick = function() {
|
||||||
|
refreshEntities();
|
||||||
|
}
|
||||||
|
elTeleport.onclick = function() {
|
||||||
|
EventBridge.emitWebEvent(JSON.stringify({ type: 'teleport' }));
|
||||||
|
}
|
||||||
|
elDelete.onclick = function() {
|
||||||
|
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
|
||||||
|
refreshEntities();
|
||||||
|
}
|
||||||
|
|
||||||
if (window.EventBridge !== undefined) {
|
if (window.EventBridge !== undefined) {
|
||||||
EventBridge.scriptEventReceived.connect(function(data) {
|
EventBridge.scriptEventReceived.connect(function(data) {
|
||||||
data = JSON.parse(data);
|
data = JSON.parse(data);
|
||||||
|
|
||||||
if (data.type == "selectionUpdate") {
|
if (data.type == "selectionUpdate") {
|
||||||
selectedEntities = data.selectedIDs;
|
var notFound = updateSelectedEntities(data.selectedIDs);
|
||||||
for (var id in entities) {
|
if (notFound) {
|
||||||
entities[id].el.className = '';
|
refreshEntities();
|
||||||
}
|
|
||||||
for (var i = 0; i < data.selectedIDs.length; i++) {
|
|
||||||
var id = data.selectedIDs[i];
|
|
||||||
if (id in entities) {
|
|
||||||
var entity = entities[id];
|
|
||||||
entity.el.className = 'selected';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (data.type == "update") {
|
} else if (data.type == "update") {
|
||||||
var newEntities = data.entities;
|
var newEntities = data.entities;
|
||||||
|
@ -99,27 +170,42 @@
|
||||||
var id = newEntities[i].id;
|
var id = newEntities[i].id;
|
||||||
addEntity(id, newEntities[i].type, newEntities[i].url);
|
addEntity(id, newEntities[i].type, newEntities[i].url);
|
||||||
}
|
}
|
||||||
|
updateSelectedEntities(data.selectedIDs);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// var _id = 0;
|
||||||
|
// setInterval(function() {
|
||||||
|
// for(var i = 0; i < 2; i++) {
|
||||||
|
// addEntity(_id, ['Model', 'Light'][i], 'http' + _id);
|
||||||
|
// _id++;
|
||||||
|
// }
|
||||||
|
// }, 5000);
|
||||||
|
setTimeout(refreshEntities, 1);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body onload='loaded();'>
|
<body onload='loaded();'>
|
||||||
<div>
|
<div>
|
||||||
<button id="refresh">Refresh</button>
|
<input type="button" id="refresh" value="Refresh"></button>
|
||||||
|
<input type="button" id="teleport" value="Teleport"></button>
|
||||||
|
<input type="button" id="delete" style="background-color: rgb(244, 64, 64); float: right" value="Delete"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table id="entity-table">
|
<div id="entity-list">
|
||||||
<thead>
|
<input type="text" class="search" id="filter" placeholder="Filter" />
|
||||||
<tr>
|
<table id="entity-table">
|
||||||
<th id="entity-type">Type</th>
|
<thead>
|
||||||
<th id="entity-url">URL</th>
|
<tr>
|
||||||
</tr>
|
<th id="entity-type">Type <span class="sort-order" style="display: inline"> ▾</span></th>
|
||||||
</thead>
|
<th id="entity-url">URL <span class="sort-order" style="display: none"> ▾</span></th>
|
||||||
<tbody id="entity-table-body">
|
</tr>
|
||||||
</tbody>
|
</thead>
|
||||||
</table>
|
<tbody class="list" id="entity-table-body">
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -114,6 +114,7 @@ table#entity-table {
|
||||||
|
|
||||||
#entity-table tr {
|
#entity-table tr {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
border-bottom: 1px solid #e5e5e5;
|
||||||
}
|
}
|
||||||
|
|
||||||
#entity-table tr.selected {
|
#entity-table tr.selected {
|
||||||
|
@ -133,14 +134,18 @@ table#entity-table {
|
||||||
border: 0px black solid;
|
border: 0px black solid;
|
||||||
word-wrap: nowrap;
|
word-wrap: nowrap;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
#entity-table td.url {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
th#entity-type {
|
th#entity-type {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
th#entity-url {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
div.input-area {
|
div.input-area {
|
||||||
|
@ -186,3 +191,20 @@ table#properties-table {
|
||||||
col#col-label {
|
col#col-label {
|
||||||
width: 130px;
|
width: 130px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.outer {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
div.inner {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
|
||||||
|
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
|
@ -24,10 +24,38 @@ EntityListTool = function(opts) {
|
||||||
type: 'selectionUpdate',
|
type: 'selectionUpdate',
|
||||||
selectedIDs: selectedIDs,
|
selectedIDs: selectedIDs,
|
||||||
};
|
};
|
||||||
|
print("Sending: " + JSON.stringify(data));
|
||||||
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
|
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function sendUpdate() {
|
||||||
|
var entities = [];
|
||||||
|
var ids = Entities.findEntities(MyAvatar.position, 100);
|
||||||
|
for (var i = 0; i < ids.length; i++) {
|
||||||
|
var id = ids[i];
|
||||||
|
var properties = Entities.getEntityProperties(id);
|
||||||
|
entities.push({
|
||||||
|
id: id.id,
|
||||||
|
type: properties.type,
|
||||||
|
url: properties.type == "Model" ? properties.modelURL : "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectedIDs = [];
|
||||||
|
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||||
|
selectedIDs.push(selectionManager.selections[i].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
type: "update",
|
||||||
|
entities: entities,
|
||||||
|
selectedIDs: selectedIDs,
|
||||||
|
};
|
||||||
|
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
webView.eventBridge.webEventReceived.connect(function(data) {
|
webView.eventBridge.webEventReceived.connect(function(data) {
|
||||||
|
print("Got: " + data);
|
||||||
data = JSON.parse(data);
|
data = JSON.parse(data);
|
||||||
if (data.type == "selectionUpdate") {
|
if (data.type == "selectionUpdate") {
|
||||||
var ids = data.entityIds;
|
var ids = data.entityIds;
|
||||||
|
@ -46,22 +74,13 @@ EntityListTool = function(opts) {
|
||||||
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
|
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
|
||||||
}
|
}
|
||||||
} else if (data.type == "refresh") {
|
} else if (data.type == "refresh") {
|
||||||
var entities = [];
|
sendUpdate();
|
||||||
var ids = Entities.findEntities(MyAvatar.position, 100);
|
} else if (data.type == "teleport") {
|
||||||
for (var i = 0; i < ids.length; i++) {
|
if (selectionManager.hasSelection()) {
|
||||||
var id = ids[i];
|
MyAvatar.position = selectionManager.worldPosition;
|
||||||
var properties = Entities.getEntityProperties(id);
|
|
||||||
entities.push({
|
|
||||||
id: id.id,
|
|
||||||
type: properties.type,
|
|
||||||
url: properties.type == "Model" ? properties.modelURL : "",
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
var data = {
|
} else if (data.type == "delete") {
|
||||||
type: "update",
|
deleteSelectedEntities();
|
||||||
entities: entities,
|
|
||||||
};
|
|
||||||
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue