mirror of
https://github.com/AleziaKurdis/Overte-community-apps.git
synced 2025-04-06 00:53:09 +02:00
548 lines
20 KiB
JavaScript
548 lines
20 KiB
JavaScript
//
|
|
// app-domainMapper.js
|
|
//
|
|
// Created by Alezia Kurdis, March 4th 2024.
|
|
// Copyright 2024, Overte e.V.
|
|
//
|
|
// Overte Application to generate a map of the occupied area in a domain by generating a 3d representation.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
(function() {
|
|
var jsMainFileName = "app-domainMapper.js";
|
|
var ROOT = Script.resolvePath('').split(jsMainFileName)[0];
|
|
|
|
var APP_ICON_INACTIVE = ROOT + "icon_inactive_white.png";
|
|
var ICON_CAPTION_COLOR = "#FFFFFF";
|
|
if (ROOT.substr(0, 4) !== "http") {
|
|
APP_ICON_INACTIVE = ROOT + "icon_inactive_green.png";
|
|
ICON_CAPTION_COLOR = "#00FF00";
|
|
}
|
|
var APP_ICON_ACTIVE = ROOT + "icon_active.png";
|
|
var APP_NAME = "DOMAP";
|
|
var appStatus = false;
|
|
|
|
var UPDATE_TIMER_INTERVAL = 5000; // 5 sec
|
|
var processTimer = 0;
|
|
|
|
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
|
|
|
var domainMapID = Uuid.NULL;
|
|
var displayPosition = null;
|
|
var FULL_DOMAIN_SCAN_RADIUS = 27713;
|
|
var DOMAIN_SIZE = 32768;
|
|
var DOMAIN_MAP_SIZE = 4; //in meters
|
|
|
|
var button = tablet.addButton({
|
|
text: APP_NAME,
|
|
icon: APP_ICON_INACTIVE,
|
|
activeIcon: APP_ICON_ACTIVE,
|
|
captionColor: ICON_CAPTION_COLOR
|
|
});
|
|
|
|
function clicked(){
|
|
var colorCaption;
|
|
if (appStatus === true) {
|
|
clearDomainMap();
|
|
colorCaption = ICON_CAPTION_COLOR;
|
|
appStatus = false;
|
|
Script.update.disconnect(myTimer);
|
|
displayPosition = null;
|
|
}else{
|
|
drawDomainMap();
|
|
colorCaption = "#000000";
|
|
appStatus = true;
|
|
Script.update.connect(myTimer);
|
|
}
|
|
|
|
button.editProperties({
|
|
isActive: appStatus,
|
|
captionColor: colorCaption
|
|
});
|
|
}
|
|
|
|
function myTimer(deltaTime) {
|
|
var today = new Date();
|
|
if ((today.getTime() - processTimer) > UPDATE_TIMER_INTERVAL ) {
|
|
|
|
drawDomainMap();
|
|
|
|
today = new Date();
|
|
processTimer = today.getTime();
|
|
}
|
|
}
|
|
|
|
function makeUnlit(id) {
|
|
var materialData = "{\n \"materialVersion\": 1,\n \"materials\": [\n {\n \"name\": \"0\",\n \"defaultFallthrough\": true,\n \"unlit\": true,\n \"model\": \"hifi_pbr\"\n }\n ]\n}";
|
|
var materialEntityID = Entities.addEntity({
|
|
"type": "Material",
|
|
"parentID": id,
|
|
"localPosition": {"x": 0, "y": 0, "z": 0},
|
|
"name": "Unlit-material",
|
|
"parentMaterialName": "0",
|
|
"materialURL": "materialData",
|
|
"priority": 1,
|
|
"materialMappingMode": "uv",
|
|
"ignorePickIntersection": true,
|
|
"materialData": materialData
|
|
}, "local");
|
|
}
|
|
|
|
function drawDomainMap() {
|
|
var i, id, properties;
|
|
var domainName = location.hostname;
|
|
if (domainName === "") {
|
|
domainName = "SERVERLESS";
|
|
}
|
|
|
|
var zones = Entities.findEntitiesByType("Zone", {"x": 0, "y": 0, "z": 0}, FULL_DOMAIN_SCAN_RADIUS);
|
|
if (displayPosition === null) {
|
|
displayPosition = Vec3.sum(MyAvatar.feetPosition, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: DOMAIN_MAP_SIZE/2, z: - DOMAIN_MAP_SIZE }));
|
|
}
|
|
clearDomainMap();
|
|
domainMapID = Entities.addEntity({
|
|
"name": "DOMAIN MAP - " + domainName,
|
|
"type": "Shape",
|
|
"shape": "Cube",
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": DOMAIN_MAP_SIZE, "y": DOMAIN_MAP_SIZE, "z": DOMAIN_MAP_SIZE},
|
|
"position": displayPosition,
|
|
"color": {"red": 255, "green": 255, "blue": 255},
|
|
"alpha": 0.05,
|
|
"canCastShadow": false,
|
|
"collisionless": true,
|
|
"primitiveMode": "solid"
|
|
}, "local");
|
|
makeUnlit(domainMapID);
|
|
|
|
id = Entities.addEntity({
|
|
"name": "DOMAIN MAP FRAME - " + domainName,
|
|
"type": "Shape",
|
|
"parentID": domainMapID,
|
|
"shape": "Cube",
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": DOMAIN_MAP_SIZE, "y": DOMAIN_MAP_SIZE, "z": DOMAIN_MAP_SIZE},
|
|
"localPosition": {"x": 0, "y": 0, "z": 0},
|
|
"color": {"red": 255, "green": 255, "blue": 255},
|
|
"alpha": 1,
|
|
"canCastShadow": false,
|
|
"collisionless": true,
|
|
"primitiveMode": "lines"
|
|
}, "local");
|
|
makeUnlit(id);
|
|
|
|
id = Entities.addEntity({
|
|
"name": "DOMAINE NAME",
|
|
"type": "Text",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 4, "y": 0.5, "z": 0.01},
|
|
"localPosition": {"x": 0, "y": (DOMAIN_MAP_SIZE/2) + 0.7, "z": 0},
|
|
"text": domainName,
|
|
"lineHeight": 0.25,
|
|
"textColor": {"red": 255, "green": 255, "blue": 255},
|
|
"textAlpha": 0.8,
|
|
"backgroundAlpha": 0,
|
|
"unlit": true,
|
|
"alignment": "center",
|
|
"billboardMode": "full",
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
|
|
id = Entities.addEntity({
|
|
"name": "X AXIS",
|
|
"type": "Shape",
|
|
"shape": "Cylinder",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 0.02, "y": DOMAIN_MAP_SIZE, "z": 0.02},
|
|
"localPosition": {"x": 0, "y": 0, "z": 0},
|
|
"localRotation": Quat.fromVec3Degrees({"x": 0, "y": 0, "z": 90}),
|
|
"color": {"red": 255, "green": 0, "blue": 0},
|
|
"alpha": 0.8,
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
makeUnlit(id);
|
|
|
|
id = Entities.addEntity({
|
|
"name": "Y AXIS",
|
|
"type": "Shape",
|
|
"shape": "Cylinder",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 0.02, "y": DOMAIN_MAP_SIZE, "z": 0.02},
|
|
"localPosition": {"x": 0, "y": 0, "z": 0},
|
|
"localRotation": Quat.fromVec3Degrees({"x": 0, "y": 0, "z": 0}),
|
|
"color": {"red": 0, "green": 255, "blue": 0},
|
|
"alpha": 0.8,
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
makeUnlit(id);
|
|
|
|
id = Entities.addEntity({
|
|
"name": "Z AXIS",
|
|
"type": "Shape",
|
|
"shape": "Cylinder",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 0.02, "y": DOMAIN_MAP_SIZE, "z": 0.02},
|
|
"localPosition": {"x": 0, "y": 0, "z": 0},
|
|
"localRotation": Quat.fromVec3Degrees({"x": 90, "y": 0, "z": 0}),
|
|
"color": {"red": 0, "green": 0, "blue": 255},
|
|
"alpha": 0.8,
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
makeUnlit(id);
|
|
|
|
id = Entities.addEntity({
|
|
"name": "+X",
|
|
"type": "Text",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 0.3, "y": 0.2, "z": 0.01},
|
|
"localPosition": {"x": (DOMAIN_MAP_SIZE/2) + 0.3, "y": 0, "z": 0},
|
|
"text": "+X",
|
|
"lineHeight": 0.15,
|
|
"textColor": {"red": 255, "green": 0, "blue": 0},
|
|
"textAlpha": 0.8,
|
|
"backgroundAlpha": 0,
|
|
"unlit": true,
|
|
"alignment": "center",
|
|
"billboardMode": "full",
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
|
|
id = Entities.addEntity({
|
|
"name": "-X",
|
|
"type": "Text",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 0.3, "y": 0.2, "z": 0.01},
|
|
"localPosition": {"x": (-DOMAIN_MAP_SIZE/2) - 0.3, "y": 0, "z": 0},
|
|
"text": "-X",
|
|
"lineHeight": 0.15,
|
|
"textColor": {"red": 255, "green": 0, "blue": 0},
|
|
"textAlpha": 0.8,
|
|
"backgroundAlpha": 0,
|
|
"unlit": true,
|
|
"alignment": "center",
|
|
"billboardMode": "full",
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
|
|
id = Entities.addEntity({
|
|
"name": "+Y",
|
|
"type": "Text",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 0.3, "y": 0.2, "z": 0.01},
|
|
"localPosition": {"x": 0, "y": (DOMAIN_MAP_SIZE/2) + 0.3, "z": 0},
|
|
"text": "+Y",
|
|
"lineHeight": 0.15,
|
|
"textColor": {"red": 0, "green": 255, "blue": 0},
|
|
"textAlpha": 0.8,
|
|
"backgroundAlpha": 0,
|
|
"unlit": true,
|
|
"alignment": "center",
|
|
"billboardMode": "full",
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
|
|
id = Entities.addEntity({
|
|
"name": "-Y",
|
|
"type": "Text",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 0.3, "y": 0.2, "z": 0.01},
|
|
"localPosition": {"x": 0, "y": (-DOMAIN_MAP_SIZE/2) - 0.3, "z": 0},
|
|
"text": "-Y",
|
|
"lineHeight": 0.15,
|
|
"textColor": {"red": 0, "green": 255, "blue": 0},
|
|
"textAlpha": 0.8,
|
|
"backgroundAlpha": 0,
|
|
"unlit": true,
|
|
"alignment": "center",
|
|
"billboardMode": "full",
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
|
|
id = Entities.addEntity({
|
|
"name": "+Z",
|
|
"type": "Text",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 0.3, "y": 0.2, "z": 0.01},
|
|
"localPosition": {"x": 0, "y": 0, "z": (DOMAIN_MAP_SIZE/2) + 0.3},
|
|
"text": "+Z",
|
|
"lineHeight": 0.15,
|
|
"textColor": {"red": 0, "green": 0, "blue": 255},
|
|
"textAlpha": 0.8,
|
|
"backgroundAlpha": 0,
|
|
"unlit": true,
|
|
"alignment": "center",
|
|
"billboardMode": "full",
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
|
|
id = Entities.addEntity({
|
|
"name": "-Z",
|
|
"type": "Text",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 0.3, "y": 0.2, "z": 0.01},
|
|
"localPosition": {"x": 0, "y": 0, "z": (-DOMAIN_MAP_SIZE/2) - 0.3},
|
|
"text": "-Z",
|
|
"lineHeight": 0.15,
|
|
"textColor": {"red": 0, "green": 0, "blue": 255},
|
|
"textAlpha": 0.8,
|
|
"backgroundAlpha": 0,
|
|
"unlit": true,
|
|
"alignment": "center",
|
|
"billboardMode": "full",
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
|
|
if (zones.length > 0) {
|
|
var margins = 0;
|
|
var color;
|
|
for (i = 0; i < zones.length; i++) {
|
|
properties = Entities.getEntityProperties(zones[i], ["position", "dimensions", "name", "rotation"]);
|
|
color = getColorFromID(zones[i]);
|
|
id = Entities.addEntity({
|
|
"name": "Zone - " + properties.name,
|
|
"type": "Shape",
|
|
"shape": "Cube",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {
|
|
"x": DOMAIN_MAP_SIZE * (properties.dimensions.x/DOMAIN_SIZE),
|
|
"y": DOMAIN_MAP_SIZE * (properties.dimensions.y/DOMAIN_SIZE),
|
|
"z": DOMAIN_MAP_SIZE * (properties.dimensions.z/DOMAIN_SIZE)
|
|
},
|
|
"localPosition": {
|
|
"x": (DOMAIN_MAP_SIZE/2) * (properties.position.x/(DOMAIN_SIZE/2)),
|
|
"y": (DOMAIN_MAP_SIZE/2) * (properties.position.y/(DOMAIN_SIZE/2)),
|
|
"z": (DOMAIN_MAP_SIZE/2) * (properties.position.z/(DOMAIN_SIZE/2))
|
|
},
|
|
"localRotation": properties.rotation,
|
|
"color": color,
|
|
"alpha": 0.1,
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
makeUnlit(id);
|
|
|
|
id = Entities.addEntity({
|
|
"name": "Zone Frame - " + properties.name,
|
|
"type": "Shape",
|
|
"shape": "Cube",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {
|
|
"x": DOMAIN_MAP_SIZE * (properties.dimensions.x/DOMAIN_SIZE),
|
|
"y": DOMAIN_MAP_SIZE * (properties.dimensions.y/DOMAIN_SIZE),
|
|
"z": DOMAIN_MAP_SIZE * (properties.dimensions.z/DOMAIN_SIZE)
|
|
},
|
|
"localPosition": {
|
|
"x": (DOMAIN_MAP_SIZE/2) * (properties.position.x/(DOMAIN_SIZE/2)),
|
|
"y": (DOMAIN_MAP_SIZE/2) * (properties.position.y/(DOMAIN_SIZE/2)),
|
|
"z": (DOMAIN_MAP_SIZE/2) * (properties.position.z/(DOMAIN_SIZE/2))
|
|
},
|
|
"localRotation": properties.rotation,
|
|
"color": color,
|
|
"alpha": 1,
|
|
"canCastShadow": false,
|
|
"collisionless": true,
|
|
"primitiveMode": "lines"
|
|
}, "local");
|
|
makeUnlit(id);
|
|
|
|
var lineHight = DOMAIN_MAP_SIZE * (getTheLargestAxisDimension(properties.dimensions)/DOMAIN_SIZE) * 0.2;
|
|
if (lineHight > 0.08) {
|
|
lineHight = 0.08;
|
|
}
|
|
if (lineHight < 0.01) {
|
|
lineHight = 0.01;
|
|
}
|
|
|
|
margins = (0.09 - lineHight)/2;
|
|
id = Entities.addEntity({
|
|
"name": "Zone Name - " + properties.name,
|
|
"type": "Text",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 4, "y": 0.1, "z": 0.01},
|
|
"localPosition": {
|
|
"x": (DOMAIN_MAP_SIZE/2) * (properties.position.x/(DOMAIN_SIZE/2)),
|
|
"y": ((DOMAIN_MAP_SIZE/2) * (properties.position.y/(DOMAIN_SIZE/2))) + ((DOMAIN_MAP_SIZE * (properties.dimensions.y/DOMAIN_SIZE))/2) + lineHight,
|
|
"z": (DOMAIN_MAP_SIZE/2) * (properties.position.z/(DOMAIN_SIZE/2))
|
|
},
|
|
"text": properties.name,
|
|
"lineHeight": lineHight,
|
|
"textColor": color,
|
|
"textAlpha": 0.8,
|
|
"backgroundAlpha": 0,
|
|
"topMargin": margins,
|
|
"bottomMargin": margins,
|
|
"unlit": true,
|
|
"alignment": "center",
|
|
"billboardMode": "full",
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
}
|
|
}
|
|
|
|
var avatarIDs = AvatarManager.getAvatarsInRange({"x": 0, "y": 0, "z": 0}, FULL_DOMAIN_SCAN_RADIUS);
|
|
if (avatarIDs.length > 0) {
|
|
var avatarColor, avatarName;
|
|
for (i = 0; i < avatarIDs.length; i++) {
|
|
properties = AvatarManager.getAvatar(avatarIDs[i]);
|
|
avatarColor = {"red": 0, "green": 128, "blue": 255};
|
|
avatarName = properties.sessionDisplayName;
|
|
if (properties.sessionUUID === MyAvatar.sessionUUID) {
|
|
avatarName = "YOU";
|
|
avatarColor = {"red": 255, "green": 32, "blue": 0};
|
|
}
|
|
|
|
id = Entities.addEntity({
|
|
"name": "AVATAR - " + avatarName,
|
|
"type": "Shape",
|
|
"parentID": domainMapID,
|
|
"shape": "Sphere",
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 0.003, "y": 0.003, "z": 0.003},
|
|
"localPosition": {
|
|
"x": (DOMAIN_MAP_SIZE/2) * (properties.position.x/(DOMAIN_SIZE/2)),
|
|
"y": (DOMAIN_MAP_SIZE/2) * (properties.position.y/(DOMAIN_SIZE/2)),
|
|
"z": (DOMAIN_MAP_SIZE/2) * (properties.position.z/(DOMAIN_SIZE/2))
|
|
},
|
|
"color": avatarColor,
|
|
"alpha": 0.8,
|
|
"canCastShadow": false,
|
|
"collisionless": true,
|
|
"primitiveMode": "solid"
|
|
}, "local");
|
|
makeUnlit(id);
|
|
|
|
lineHight = 0.006;
|
|
margins = 0;
|
|
id = Entities.addEntity({
|
|
"name": "Avatar Name - " + avatarName,
|
|
"type": "Text",
|
|
"parentID": domainMapID,
|
|
"grab": {"grabbable": false },
|
|
"dimensions": {"x": 4, "y": 0.01, "z": 0.01},
|
|
"localPosition": {
|
|
"x": (DOMAIN_MAP_SIZE/2) * (properties.position.x/(DOMAIN_SIZE/2)),
|
|
"y": ((DOMAIN_MAP_SIZE/2) * (properties.position.y/(DOMAIN_SIZE/2))) + lineHight,
|
|
"z": (DOMAIN_MAP_SIZE/2) * (properties.position.z/(DOMAIN_SIZE/2))
|
|
},
|
|
"text": avatarName,
|
|
"lineHeight": lineHight,
|
|
"textColor": avatarColor,
|
|
"textAlpha": 0.8,
|
|
"backgroundAlpha": 0,
|
|
"topMargin": margins,
|
|
"bottomMargin": margins,
|
|
"unlit": true,
|
|
"alignment": "center",
|
|
"billboardMode": "full",
|
|
"canCastShadow": false,
|
|
"collisionless": true
|
|
}, "local");
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
function getTheLargestAxisDimension(dimensions) {
|
|
var largest = dimensions.x;
|
|
if (dimensions.y > largest) { largest = dimensions.y; }
|
|
if (dimensions.z > largest) { largest = dimensions.z; }
|
|
return largest;
|
|
}
|
|
|
|
function getColorFromID(id) {
|
|
var score = getStringScore(id);
|
|
var hue = (score % 360) / 360;
|
|
var coloration = hslToRgb(hue, 1, 0.6);
|
|
return {"red": coloration[0], "green": coloration[1], "blue": coloration[2]};
|
|
}
|
|
|
|
function getStringScore(str) {
|
|
var score = 0;
|
|
for (var j = 0; j < str.length; j++){
|
|
score += str.charCodeAt(j);
|
|
}
|
|
return score;
|
|
}
|
|
|
|
/*
|
|
* Converts an HSL color value to RGB. Conversion formula
|
|
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
|
|
* Assumes h, s, and l are contained in the set [0, 1] and
|
|
* returns r, g, and b in the set [0, 255].
|
|
*
|
|
* @param {number} h The hue
|
|
* @param {number} s The saturation
|
|
* @param {number} l The lightness
|
|
* @return {Array} The RGB representation
|
|
*/
|
|
function hslToRgb(h, s, l){
|
|
var r, g, b;
|
|
|
|
if(s == 0){
|
|
r = g = b = l; // achromatic
|
|
}else{
|
|
var hue2rgb = function hue2rgb(p, q, t){
|
|
if(t < 0) t += 1;
|
|
if(t > 1) t -= 1;
|
|
if(t < 1/6) return p + (q - p) * 6 * t;
|
|
if(t < 1/2) return q;
|
|
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
|
return p;
|
|
}
|
|
|
|
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
var p = 2 * l - q;
|
|
r = hue2rgb(p, q, h + 1/3);
|
|
g = hue2rgb(p, q, h);
|
|
b = hue2rgb(p, q, h - 1/3);
|
|
}
|
|
|
|
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
|
|
}
|
|
|
|
function clearDomainMap() {
|
|
if (domainMapID !== Uuid.NULL) {
|
|
Entities.deleteEntity(domainMapID);
|
|
domainMapID = Uuid.NULL;
|
|
}
|
|
}
|
|
|
|
button.clicked.connect(clicked);
|
|
|
|
function cleanup() {
|
|
|
|
if (appStatus) {
|
|
clearDomainMap();
|
|
Script.update.disconnect(myTimer);
|
|
}
|
|
|
|
tablet.removeButton(button);
|
|
}
|
|
|
|
Script.scriptEnding.connect(cleanup);
|
|
}());
|