mirror of
https://github.com/overte-org/community-apps.git
synced 2025-04-25 13:32:57 +02:00
Merge pull request #9 from AleziaKurdis/app-lightBulb
Add the "Light Bulb Generator" app
This commit is contained in:
commit
b86532f43e
8 changed files with 507 additions and 0 deletions
BIN
applications/lightBulb/FiraSans-SemiBold.ttf
Normal file
BIN
applications/lightBulb/FiraSans-SemiBold.ttf
Normal file
Binary file not shown.
33
applications/lightBulb/LIGHT_BULB.json
Normal file
33
applications/lightBulb/LIGHT_BULB.json
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"DataVersion": 0,
|
||||||
|
"Entities": [
|
||||||
|
{
|
||||||
|
"type": "Sphere",
|
||||||
|
"name": "LIGHT_BULB",
|
||||||
|
"locked": false,
|
||||||
|
"dimensions": {
|
||||||
|
"x": 0.06,
|
||||||
|
"y": 0.06,
|
||||||
|
"z": 0.06
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0,
|
||||||
|
"w": 1
|
||||||
|
},
|
||||||
|
"grab": {
|
||||||
|
"grabbable": false
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"red": 255,
|
||||||
|
"green": 255,
|
||||||
|
"blue": 255
|
||||||
|
},
|
||||||
|
"userData": "{\"lightIntensity\":5,\"lightSpotCutOff\": 30,\"lightRange\": 10}",
|
||||||
|
"script": "https://aleziakurdis.github.io/lightBulb/lightBulb.js"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Id": "{5cbb14bf-ca6c-4aa9-bcfa-1a53c8438669}",
|
||||||
|
"Version": 133
|
||||||
|
}
|
143
applications/lightBulb/app-lightBulb.js
Normal file
143
applications/lightBulb/app-lightBulb.js
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
"use strict";
|
||||||
|
//
|
||||||
|
// app-lightBulb.js
|
||||||
|
//
|
||||||
|
// Created by Alezia Kurdis, April 23rd 2022.
|
||||||
|
// Copyright 2022 Overte e.V.
|
||||||
|
//
|
||||||
|
// Application to generate light bulbs.
|
||||||
|
//
|
||||||
|
// 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-lightBulb.js";
|
||||||
|
var ROOT = Script.resolvePath('').split(jsMainFileName)[0];
|
||||||
|
|
||||||
|
var intensity = 5;
|
||||||
|
var angle = 30;
|
||||||
|
var range = 10;
|
||||||
|
var wOrH = "white";
|
||||||
|
var hue = 30;
|
||||||
|
|
||||||
|
var APP_NAME = "BULB";
|
||||||
|
var APP_URL = ROOT + "lightBulb.html";
|
||||||
|
var APP_ICON_INACTIVE = ROOT + "icon_inactive.png";
|
||||||
|
var APP_ICON_ACTIVE = ROOT + "icon_active.png";
|
||||||
|
var LIGHT_BULB_SCRIPT = ROOT + "lightBulb.js";
|
||||||
|
var appStatus = false;
|
||||||
|
|
||||||
|
var channel = "com.overte.app.lightBulb";
|
||||||
|
var timestamp = 0;
|
||||||
|
var INTERCALL_DELAY = 200; //0.3 sec
|
||||||
|
|
||||||
|
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
|
||||||
|
tablet.screenChanged.connect(onScreenChanged);
|
||||||
|
|
||||||
|
var button = tablet.addButton({
|
||||||
|
text: APP_NAME,
|
||||||
|
icon: APP_ICON_INACTIVE,
|
||||||
|
activeIcon: APP_ICON_ACTIVE
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function clicked(){
|
||||||
|
if (appStatus === true) {
|
||||||
|
tablet.webEventReceived.disconnect(onAppWebEventReceived);
|
||||||
|
tablet.gotoHomeScreen();
|
||||||
|
appStatus = false;
|
||||||
|
}else{
|
||||||
|
tablet.gotoWebScreen(APP_URL + "?woh=" + wOrH + "&hue=" + hue + "&int=" + intensity + "&ang=" + angle + "&ran=" + range);
|
||||||
|
tablet.webEventReceived.connect(onAppWebEventReceived);
|
||||||
|
appStatus = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.editProperties({
|
||||||
|
isActive: appStatus
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
button.clicked.connect(clicked);
|
||||||
|
|
||||||
|
|
||||||
|
function onAppWebEventReceived(message) {
|
||||||
|
var d = new Date();
|
||||||
|
var n = d.getTime();
|
||||||
|
|
||||||
|
var messageObj = JSON.parse(message);
|
||||||
|
if (messageObj.channel === channel) {
|
||||||
|
if (messageObj.action === "GEN_LIGHT_BULB" && (n - timestamp) > INTERCALL_DELAY) {
|
||||||
|
d = new Date();
|
||||||
|
timestamp = d.getTime();
|
||||||
|
|
||||||
|
intensity = messageObj.lightIntensity;
|
||||||
|
angle = messageObj.lightSpotCutOff;
|
||||||
|
range = messageObj.lightRange;
|
||||||
|
wOrH = messageObj.colorMode;
|
||||||
|
hue = messageObj.hue;
|
||||||
|
|
||||||
|
generatelightBulb(messageObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onScreenChanged(type, url) {
|
||||||
|
if (type === "Web" && url.indexOf(APP_URL) !== -1) {
|
||||||
|
appStatus = true;
|
||||||
|
} else {
|
||||||
|
appStatus = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.editProperties({
|
||||||
|
isActive: appStatus
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
|
||||||
|
if (appStatus) {
|
||||||
|
tablet.gotoHomeScreen();
|
||||||
|
tablet.webEventReceived.disconnect(onMoreAppWebEventReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
tablet.screenChanged.disconnect(onScreenChanged);
|
||||||
|
tablet.removeButton(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generatelightBulb(data) {
|
||||||
|
|
||||||
|
var id = Entities.addEntity({
|
||||||
|
"type": "Sphere",
|
||||||
|
"name": "LIGHT_BULB",
|
||||||
|
"locked": false,
|
||||||
|
"dimensions": {
|
||||||
|
"x": 0.06,
|
||||||
|
"y": 0.06,
|
||||||
|
"z": 0.06
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0,
|
||||||
|
"w": 1
|
||||||
|
},
|
||||||
|
"position": Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -2 })),
|
||||||
|
"grab": {
|
||||||
|
"grabbable": false
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"red": data.color.red,
|
||||||
|
"green": data.color.green,
|
||||||
|
"blue": data.color.blue
|
||||||
|
},
|
||||||
|
"userData": "{\"lightIntensity\":" + data.lightIntensity + ",\"lightSpotCutOff\": " + data.lightSpotCutOff + ",\"lightRange\": " + data.lightRange + "}",
|
||||||
|
"script": LIGHT_BULB_SCRIPT
|
||||||
|
}, "domain");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
||||||
|
}());
|
BIN
applications/lightBulb/icon_active.png
Normal file
BIN
applications/lightBulb/icon_active.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
applications/lightBulb/icon_inactive.png
Normal file
BIN
applications/lightBulb/icon_inactive.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
211
applications/lightBulb/lightBulb.html
Normal file
211
applications/lightBulb/lightBulb.html
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<!--
|
||||||
|
lightBulb.html
|
||||||
|
|
||||||
|
Created by Alezia Kurdis, April 23rd 2022.
|
||||||
|
Copyright 2022 Overte e.V.
|
||||||
|
|
||||||
|
HTML UI for an application to generate light bulbs.
|
||||||
|
|
||||||
|
Distributed under the Apache License, Version 2.0.
|
||||||
|
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<script>
|
||||||
|
//Parameters
|
||||||
|
|
||||||
|
function findGetParameter(parameterName) {
|
||||||
|
var result = null,
|
||||||
|
tmp = [];
|
||||||
|
var items = location.search.substr(1).split("&");
|
||||||
|
for (var index = 0; index < items.length; index++) {
|
||||||
|
tmp = items[index].split("=");
|
||||||
|
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
var channel = "com.overte.app.lightBulb";
|
||||||
|
|
||||||
|
//Paths
|
||||||
|
var thisPageName = "lightBulb.html";
|
||||||
|
var currentPath = window.location.protocol + "//" + window.location.host + window.location.pathname;
|
||||||
|
var ROOTPATH = currentPath.replace(thisPageName, "");
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: FiraSans-SemiBold;
|
||||||
|
src: url(FiraSans-SemiBold.ttf);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: #363842;
|
||||||
|
font-family: FiraSans-SemiBold;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-decoration: none;
|
||||||
|
font-style: normal;
|
||||||
|
font-variant: normal;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#colorPreview {
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1px solid #000000;
|
||||||
|
width: 100px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>LIGHT BULB GENERATOR</h1><hr>
|
||||||
|
Color: <br>
|
||||||
|
<table><tr><td>
|
||||||
|
<div id = "colorPreview"></div>
|
||||||
|
</td><td>
|
||||||
|
<input type = "radio" id="colorWhite" name="colorType" onclick="setColor();" value = "white" checked>White<br>
|
||||||
|
<input type = "radio" id="colorHue" name="colorType" onclick="setColor();" value = "hue">Hue <input id="hue" type="number" size = "5" value="30" onchange='setColor();'>°
|
||||||
|
</td></tr></table>
|
||||||
|
<br><br>
|
||||||
|
Intensity: <input id="intensity" type="number" size = "5" value="5" onchange='setColor();'><br><br>
|
||||||
|
Beam angle: <input id="beamAngle" type="number" size = "5" value="30" onchange='setColor();'>°<br><br>
|
||||||
|
Range: <input id="range" type="number" size = "5" value="10" onchange='setColor();'>m<br><br><br>
|
||||||
|
|
||||||
|
<button onClick='genLightBulb();'>GENERATE A LIGHT BULB</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function setColor() {
|
||||||
|
var color;
|
||||||
|
|
||||||
|
var hue = parseInt(document.getElementById("hue").value, 10)/360;
|
||||||
|
if (document.getElementById("colorWhite").checked) {
|
||||||
|
color = hslToRgb(hue, 1, 1);
|
||||||
|
} else {
|
||||||
|
color = hslToRgb(hue, 1, 0.5);
|
||||||
|
}
|
||||||
|
var h = parseInt(document.getElementById("hue").value,10);
|
||||||
|
if (h >= 720 || h < -720) {
|
||||||
|
document.getElementById("hue").value = 0;
|
||||||
|
} else if (h < 0) {
|
||||||
|
document.getElementById("hue").value = h + 360;
|
||||||
|
} else if (h >= 360) {
|
||||||
|
document.getElementById("hue").value = h - 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("colorPreview").style.backgroundColor = "rgb(" + color[0] + ", " + color[1] + ", " + color[2] + ")";
|
||||||
|
|
||||||
|
var i = parseInt(document.getElementById("intensity").value,10);
|
||||||
|
if (i < 0) {
|
||||||
|
document.getElementById("intensity").value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var a = parseInt(document.getElementById("beamAngle").value,10);
|
||||||
|
if (a < 0) {
|
||||||
|
document.getElementById("beamAngle").value = 0;
|
||||||
|
}
|
||||||
|
if (a >= 180) {
|
||||||
|
document.getElementById("beamAngle").value = 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
var r = parseInt(document.getElementById("range").value,10);
|
||||||
|
if (r < 0) {
|
||||||
|
document.getElementById("range").value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function genLightBulb(){
|
||||||
|
var hue = parseInt(document.getElementById("hue").value, 10)/360;
|
||||||
|
var colorMode = "white";
|
||||||
|
if (document.getElementById("colorWhite").checked) {
|
||||||
|
color = hslToRgb(hue, 1, 1);
|
||||||
|
} else {
|
||||||
|
color = hslToRgb(hue, 1, 0.6);
|
||||||
|
colorMode = "hue";
|
||||||
|
}
|
||||||
|
var lightColor = {"red": color[0], "green": color[1], "blue": color[2]};
|
||||||
|
|
||||||
|
var intensity = parseInt(document.getElementById("intensity").value,10);
|
||||||
|
var beamAngle = parseInt(document.getElementById("beamAngle").value,10);
|
||||||
|
var range = parseInt(document.getElementById("range").value,10);
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
"action": "GEN_LIGHT_BULB",
|
||||||
|
"channel": channel,
|
||||||
|
"color": lightColor,
|
||||||
|
"lightIntensity": intensity,
|
||||||
|
"lightSpotCutOff": beamAngle,
|
||||||
|
"lightRange": range,
|
||||||
|
"colorMode": colorMode,
|
||||||
|
"hue": parseInt(document.getElementById("hue").value, 10)
|
||||||
|
};
|
||||||
|
|
||||||
|
EventBridge.emitWebEvent(JSON.stringify(data));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)];
|
||||||
|
}
|
||||||
|
|
||||||
|
//Reading paramaters and apply them
|
||||||
|
var parameter = findGetParameter("woh");
|
||||||
|
if(parameter === null){parameter = "white";}
|
||||||
|
if (parameter === "white") {
|
||||||
|
document.getElementById("colorWhite").checked = true;
|
||||||
|
document.getElementById("colorHue").checked = false;
|
||||||
|
} else {
|
||||||
|
document.getElementById("colorWhite").checked = false;
|
||||||
|
document.getElementById("colorHue").checked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
parameter = findGetParameter("hue");
|
||||||
|
document.getElementById("hue").value = parseInt(parameter, 10);
|
||||||
|
|
||||||
|
parameter = findGetParameter("int");
|
||||||
|
document.getElementById("intensity").value = parseInt(parameter, 10);
|
||||||
|
|
||||||
|
parameter = findGetParameter("ang");
|
||||||
|
document.getElementById("beamAngle").value = parseInt(parameter, 10);
|
||||||
|
|
||||||
|
parameter = findGetParameter("ran");
|
||||||
|
document.getElementById("range").value = parseInt(parameter, 10);
|
||||||
|
setColor();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
111
applications/lightBulb/lightBulb.js
Normal file
111
applications/lightBulb/lightBulb.js
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
"use strict";
|
||||||
|
//
|
||||||
|
// lightBulb.js
|
||||||
|
//
|
||||||
|
// Created by Alezia Kurdis, July 14th, 2021.
|
||||||
|
// Copyright 2022 Overte e.V.
|
||||||
|
//
|
||||||
|
// Turn a shape to a light bulb.
|
||||||
|
//
|
||||||
|
// 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 ROOT = Script.resolvePath('').split("lightBulb.js")[0];
|
||||||
|
var DEG_TO_RAD = Math.PI/180;
|
||||||
|
var lightID = Uuid.NULL;
|
||||||
|
var materialID = Uuid.NULL;
|
||||||
|
|
||||||
|
this.preload = function(entityID) {
|
||||||
|
|
||||||
|
var properties = Entities.getEntityProperties(entityID, ["renderWithZones", "color", "userData"]);
|
||||||
|
var renderWithZones = properties.renderWithZones;
|
||||||
|
var color = properties.color;
|
||||||
|
var userData = JSON.parse(properties.userData);
|
||||||
|
|
||||||
|
var lightIntensity = userData.lightIntensity ? userData.lightIntensity : 5;
|
||||||
|
var lightSpotCutOff = userData.lightSpotCutOff ? userData.lightSpotCutOff : 30;
|
||||||
|
var lightRange = userData.lightRange ? userData.lightRange : 10;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
lightID = Entities.addEntity({
|
||||||
|
"parentID": entityID,
|
||||||
|
"renderWithZones": renderWithZones,
|
||||||
|
"locked": false,
|
||||||
|
"localPosition": {"x": 0.0, "y": 0.0, "z": 0.0},
|
||||||
|
"localRotation": {
|
||||||
|
"x": -0.7071,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0,
|
||||||
|
"w": 0.7071
|
||||||
|
},
|
||||||
|
"name": "bulb-light",
|
||||||
|
"grab": {
|
||||||
|
"grabbable": false
|
||||||
|
},
|
||||||
|
"type": "Light",
|
||||||
|
"dimensions": {
|
||||||
|
"x": lightRange * 2,
|
||||||
|
"y": lightRange * 2,
|
||||||
|
"z": lightRange * 2
|
||||||
|
},
|
||||||
|
"color": color,
|
||||||
|
"intensity": lightIntensity,
|
||||||
|
"falloffRadius": 1,
|
||||||
|
"isSpotlight": true,
|
||||||
|
"visible": true,
|
||||||
|
"exponent": 1,
|
||||||
|
"cutoff": lightSpotCutOff
|
||||||
|
},"local");
|
||||||
|
|
||||||
|
var sumColorCompnent = (color.red/255) +(color.green/255) +(color.blue/255);
|
||||||
|
if (sumColorCompnent === 0) {
|
||||||
|
sumColorCompnent = 0.001;
|
||||||
|
}
|
||||||
|
var bloomFactor = 9 / sumColorCompnent;
|
||||||
|
|
||||||
|
var materialContent = {
|
||||||
|
"materialVersion": 1,
|
||||||
|
"materials": [
|
||||||
|
{
|
||||||
|
"name": "bulb",
|
||||||
|
"albedo": [1, 1, 1],
|
||||||
|
"metallic": 1,
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 1,
|
||||||
|
"emissive": [(color.red/255) * bloomFactor, (color.green/255) * bloomFactor, (color.blue/255) * bloomFactor],
|
||||||
|
"scattering": 0,
|
||||||
|
"unlit": false,
|
||||||
|
"cullFaceMode": "CULL_NONE",
|
||||||
|
"model": "hifi_pbr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
materialID = Entities.addEntity({
|
||||||
|
"type": "Material",
|
||||||
|
"parentID": entityID,
|
||||||
|
"renderWithZones": renderWithZones,
|
||||||
|
"locked": false,
|
||||||
|
"localPosition": {"x": 0.0, "y": 0.2, "z": 0.0},
|
||||||
|
"name": "bulb-material",
|
||||||
|
"materialURL": "materialData",
|
||||||
|
"priority": 1,
|
||||||
|
"materialData": JSON.stringify(materialContent)
|
||||||
|
},"local");
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
this.unload = function(entityID) {
|
||||||
|
//Termination proces
|
||||||
|
if (lightID !== Uuid.NULL) {
|
||||||
|
Entities.deleteEntity(lightID);
|
||||||
|
}
|
||||||
|
if (materialID !== Uuid.NULL) {
|
||||||
|
Entities.deleteEntity(materialID);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})
|
|
@ -117,6 +117,15 @@ var metadata = { "applications":
|
||||||
"icon": "odometer/appicon_i.png",
|
"icon": "odometer/appicon_i.png",
|
||||||
"caption": "ODOMETER"
|
"caption": "ODOMETER"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"isActive": true,
|
||||||
|
"directory": "lightBulb",
|
||||||
|
"name": "Light Bulb Generator",
|
||||||
|
"description": "Generate rapidly a visible glowing light source with its light beam.",
|
||||||
|
"jsfile": "lightBulb/app-lightBulb.js",
|
||||||
|
"icon": "lightBulb/icon_inactive.png",
|
||||||
|
"caption": "BULB"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"isActive": true,
|
"isActive": true,
|
||||||
"directory": "aaswitcher",
|
"directory": "aaswitcher",
|
||||||
|
|
Loading…
Reference in a new issue