community-apps/applications/blocks/Blocks.js
Basinsky 5ee48797ec
Initial commit (#31)
* Create blocks

* Delete blocks

* Create Blocks.js

* Add files via upload

* Update Blocks.js

* Update metadata.js
2021-09-12 16:20:22 -04:00

658 lines
24 KiB
JavaScript

//
// Blocks.js
//
// created by Basinsky on 09/12/21
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
var isShiftPressed = false;
var isControlPressed = false;
var isAltPressed = false;
var newPosition;
var newDirection;
var hoverID;
var webPageID;
var hoverProps = {};
var originalPosition;
var objectSize;
var STEP_SIZE = 0.01;
var reset = false;
var RESET_TIME = 100;
var SEARCH_RADIUS = 100;
var LOCATION_ROOT_URL = Script.resolvePath(".");
var ICON_LIBRARY_URL = LOCATION_ROOT_URL + "Icons/Blocks-icons.json";
var ICON_URL = LOCATION_ROOT_URL + "Icons/";
var allOverlays = [];
var iconLibrary = Script.require(ICON_LIBRARY_URL + "?" + Date.now());
var ICON_SIZE = 40;
var iconSelection = 0;
var icon;
var ICON_HORIZONTAL_ANCHOR = 50;
var ICON_VERTICAL_ANCHOR = 70;
var ICON_SHOW_TIME = 500;// ms
var UPDATE_TIME = 50; // ms
var isRunning = false;
var colorsIDs = [];
var isXPressed = false;
var isYPressed = false;
var isZPressed = false;
var currentDirection = "Y";
var directionID;
var mainLoop;
var keys = [];
var UIkeys = ["x","X","y","Y","z","Z","ALT","SHIFT","CONTROL","DELETE"];
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
var button;
button = tablet.addButton({
icon: LOCATION_ROOT_URL + "blocks-inactive.svg?" + Date.now(),
activeIcon: LOCATION_ROOT_URL + "blocks-active.svg?" + Date.now(),
text: "BLOCKS",
sortOrder: 12
});
var screenSize = Controller.getViewportDimensions();
Script.include("/~/system/libraries/toolBars.js");
var colorToolBar = new ToolBar(ICON_HORIZONTAL_ANCHOR,ICON_VERTICAL_ANCHOR, ToolBar.VERTICAL, "placeBlocks-colorToolbar");
var LIST_NAME = "SelectionExample",
ITEM_TYPE = "entity",
HIGHLIGHT_STYLE = {
outlineUnoccludedColor: { red: 0, green: 255, blue: 255 },
outlineUnoccludedAlpha: 0.8,
outlineOccludedColor: { red: 0, green: 255, blue: 255 },
outlineOccludedAlpha: 0.8,
outlineWidth: 2
};
Selection.enableListHighlight(LIST_NAME, HIGHLIGHT_STYLE);
Script.setInterval(function () {
reset = true;
}, RESET_TIME);
// functions
function prefetchIcons() {
for (var t = 0; t < iconLibrary.iconData.length; t++) {
if (iconLibrary.iconData[t].inactive !== null) {
TextureCache.prefetch(iconLibrary.iconData[t].inactive);
TextureCache.prefetch(iconLibrary.iconData[t].active);
}
}
}
function createMainloop() {
mainLoop = Script.setInterval(function () {
if (isRunning) {
if (hoverID) {
if (isControlPressed) {
HIGHLIGHT_STYLE = {
outlineUnoccludedColor: { red: 0, green: 255, blue: 255 },
outlineUnoccludedAlpha: 0.8,
outlineOccludedColor: { red: 0, green: 255, blue: 255 },
outlineOccludedAlpha: 0.8,
outlineWidth: 2
};
}
if (isAltPressed) {
HIGHLIGHT_STYLE = {
outlineUnoccludedColor: { red: 255, green: 255, blue: 0 },
outlineUnoccludedAlpha: 0.8,
outlineOccludedColor: { red: 255, green: 255, blue: 0 },
outlineOccludedAlpha: 0.8,
outlineWidth: 2
};
}
if (isShiftPressed) {
HIGHLIGHT_STYLE = {
outlineUnoccludedColor: { red: 255, green: 0, blue: 255 },
outlineUnoccludedAlpha: 0.8,
outlineOccludedColor: { red: 255, green: 0, blue: 255 },
outlineOccludedAlpha: 0.8,
outlineWidth: 2
};
}
Selection.enableListHighlight(LIST_NAME, HIGHLIGHT_STYLE);
if (isShiftPressed || isAltPressed || isControlPressed) {
Selection.clearSelectedItemsList(LIST_NAME);
Selection.addToSelectedItemsList(LIST_NAME, ITEM_TYPE, hoverID);
if (currentDirection === "X") {
addDirection(hoverID,"X");
}
if (currentDirection === "Y") {
addDirection(hoverID,"Y");
}
if (currentDirection === "Z") {
addDirection(hoverID,"Z");
}
} else {
if (directionID) {
Entities.deleteEntity(directionID);
}
Selection.clearSelectedItemsList(LIST_NAME);
}
}
}
}, UPDATE_TIME);
}
function loadColors() {
for (var i = 0; i < iconLibrary.iconData.length; i++) {
if (iconLibrary.iconData[i].type === "color") {
icon = JSON.parse(iconLibrary.iconData[i].color);
}
}
}
function addIcons() {
if (colorToolBar === undefined) {
colorToolBar = new ToolBar(ICON_HORIZONTAL_ANCHOR,
ICON_VERTICAL_ANCHOR,
ToolBar.VERTICAL,
"placeBlocks-colorToolbar");
}
var overlayID;
for (var t = 0; t < iconLibrary.iconData.length; t++) {
if (iconLibrary.iconData[t].inactive !== null) {
if (iconLibrary.iconData[t].type === "color") {
overlayID = colorToolBar.addTool({
x: 0,
y: 0,
width: ICON_SIZE,
height: ICON_SIZE,
imageURL: LOCATION_ROOT_URL + "Icons/" + iconLibrary.iconData[t].inactive,
alpha: 1,
visible: true
});
colorsIDs.push(overlayID);
}
if (iconLibrary.iconData[t].type === "action") {
overlayID = colorToolBar.addTool({
x: 0,
y: 0,
width: ICON_SIZE,
height: ICON_SIZE,
imageURL: LOCATION_ROOT_URL + "Icons/" + iconLibrary.iconData[t].inactive,
alpha: 1,
visible: true
});
colorsIDs.push(overlayID);
}
}
}
}
function deleteAll() {
var allEnts = Entities.findEntities(MyAvatar.position,SEARCH_RADIUS);
for (var k in allEnts) {
var deleteProps = Entities.getEntityProperties(allEnts[k]);
if (deleteProps.name === "buildSystem" && deleteProps.description === MyAvatar.displayName) {
if (MyAvatar.displayName !== "anonymous") {
Entities.deleteEntity(deleteProps.id);
}
}
}
}
function addDirection(currentBlockID,dir) {
var directionRotation;
var directionColor;
var directionDimensions;
if (directionID) {
Entities.deleteEntity(directionID);
}
if (dir === "X") {
directionRotation = Quat.fromPitchYawRollRadians(0,0,Math.PI/2);
directionColor = {r: 255,g: 0,b: 0};
directionDimensions = {x: 0.003,y: 100,z: 0.003};
}
if (dir === "Y") {
directionRotation = Quat.fromPitchYawRollRadians(0,0,0);
directionColor = {r: 0,g: 255,b: 0};
directionDimensions = {x: 0.003,y: 100,z: 0.003};
}
if (dir === "Z") {
directionRotation = Quat.fromPitchYawRollRadians(Math.PI/2,0,0);
directionColor = {r: 0,g: 0,b: 255};
directionDimensions = {x: 0.003,y: 100,z: 0.003};
}
directionID = Entities.addEntity({
type: "Shape",
shape: "Cylinder",
name: "y-axis",
parentID: currentBlockID,
localPosition: {x: 0,y: 0,z: 0},
localRotation: directionRotation,
lifetime: 3,
color: directionColor,
alpha: 1,
dimensions: directionDimensions,
ignoreForCollisions: true,
userData: "{ \"grabbableKey\": { \"grabbable\": false, \"triggerable\": false}}"
},"local");
}
function newBlock() {
var cubePos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.7, z: -2 }));
Entities.addEntity({
type: "Box",
name: "buildSystem",
description: MyAvatar.displayName,
position: cubePos,
color: { r: 50, g: 50, b: 50 },
rotation: MyAvatar.orientation,
dimensions: { x: 0.1, y: 0.1, z: 0.1 },
grab: {triggerable: true,grabbable: false},
lifetime: -1
});
}
function deleteBlock() {
if (hoverID) {
var deleteProps = Entities.getEntityProperties(hoverID);
if (deleteProps.name === "buildSystem" && deleteProps.description === MyAvatar.displayName) {
Entities.deleteEntity(hoverID);
}
}
}
function showHelpPage() {
var METERS_TO_INCHES = 39.3701;
webPageID = Entities.addEntity({
type: "Web",
name: "blocks-help",
sourceUrl: LOCATION_ROOT_URL + "Blocks-help.html",
position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.8, z: -1.4 })),
rotation: MyAvatar.orientation,
dimensions: {
x: 0.7,
y: 1,
z: 0.01
},
dpi: 1920 / (3 * METERS_TO_INCHES),
lifetime: 60 // Delete after 5 minutes.
});
}
// events
function wheelEvent(event) {
if (isRunning) {
if (hoverID) {
var currentProps = Entities.getEntityProperties(hoverID);
var newDir;
var newDim;
var newPos;
var newRot;
var direction = 1;
if (event.delta > 0) {
direction = 1;
} else {
direction = -1;
}
if (isShiftPressed) {
if (currentDirection === "X") {
if (direction > 0) {
newDim =
{
x: currentProps.dimensions.x + STEP_SIZE,
y: currentProps.dimensions.y,
z: currentProps.dimensions.z
};
} else {
newDim =
{
x: currentProps.dimensions.x - STEP_SIZE,
y: currentProps.dimensions.y,
z: currentProps.dimensions.z
};
}
}
if (currentDirection === "Y") {
if (direction > 0) {
newDim =
{
x: currentProps.dimensions.x,
y: currentProps.dimensions.y + STEP_SIZE,
z: currentProps.dimensions.z
};
} else {
newDim =
{
x: currentProps.dimensions.x,
y: currentProps.dimensions.y - STEP_SIZE,
z: currentProps.dimensions.z
};
}
}
if (currentDirection === "Z") {
if (direction > 0) {
newDim =
{
x: currentProps.dimensions.x,
y: currentProps.dimensions.y,
z: currentProps.dimensions.z + STEP_SIZE
};
} else {
newDim =
{
x: currentProps.dimensions.x,
y: currentProps.dimensions.y,
z: currentProps.dimensions.z - STEP_SIZE
};
}
}
Entities.editEntity(hoverID,{
dimensions: newDim
});
}
if (isControlPressed) {
if (currentDirection === "X") {
newRot = Quat.multiply(currentProps.rotation, Quat.fromPitchYawRollDegrees(5 * direction,0,0));
}
if (currentDirection === "Y") {
newRot = Quat.multiply(currentProps.rotation, Quat.fromPitchYawRollDegrees(0,5 * direction,0));
}
if (currentDirection === "Z") {
newRot = Quat.multiply(currentProps.rotation, Quat.fromPitchYawRollDegrees(0,0,5 * direction));
}
Entities.editEntity(hoverID,{
rotation: newRot
});
}
if (isAltPressed) {
if (currentDirection === "X") {
newDir = {
x: direction * STEP_SIZE ,
y: 0 ,
z: 0 };
newPos = Vec3.sum(currentProps.position, Vec3.multiplyQbyV(currentProps.rotation, newDir));
}
if (currentDirection === "Y") {
newDir = {
x: 0 ,
y: direction * STEP_SIZE ,
z: 0 };
newPos = Vec3.sum(currentProps.position, Vec3.multiplyQbyV(currentProps.rotation, newDir));
}
if (currentDirection === "Z") {
newDir = {
x: 0,
y: 0,
z: direction * STEP_SIZE };
newPos = Vec3.sum(currentProps.position, Vec3.multiplyQbyV(currentProps.rotation, newDir));
}
Entities.editEntity(hoverID,{
position: newPos
});
}
}
}
}
function mousePressEvent(event) {
if (isRunning) {
var overlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
var clickedIcon = colorToolBar.clicked(overlay);
if (colorsIDs.indexOf(clickedIcon) !== -1) {
if (iconLibrary.iconData[iconSelection].type === "color") {
colorToolBar.setImageURL(ICON_URL +
iconLibrary.iconData[iconSelection].inactive,colorsIDs[iconSelection]);
if (colorToolBar.clicked(clickedIcon)) {
iconSelection = clickedIcon;
colorToolBar.setImageURL(ICON_URL +
iconLibrary.iconData[clickedIcon].active,clickedIcon);
}
}
if (iconLibrary.iconData[iconSelection].type === "action") {
iconSelection = clickedIcon;
if (iconLibrary.iconData[iconSelection].name === "newblock") {
newBlock();
Script.setTimeout(function () {
colorToolBar.setImageURL(ICON_URL +
iconLibrary.iconData[iconSelection].inactive,colorsIDs[iconSelection]);
colorToolBar.setImageURL(ICON_URL +
iconLibrary.iconData[0].active,colorsIDs[0]);
iconSelection = 0;
}, ICON_SHOW_TIME);
}
if (iconLibrary.iconData[iconSelection].name === "deleteall") {
deleteAll();
Script.setTimeout(function () {
colorToolBar.setImageURL(ICON_URL +
iconLibrary.iconData[iconSelection].inactive,colorsIDs[iconSelection]);
colorToolBar.setImageURL(ICON_URL +
iconLibrary.iconData[0].active,colorsIDs[0]);
iconSelection = 0;
}, ICON_SHOW_TIME);
}
if (iconLibrary.iconData[iconSelection].name === "help") {
showHelpPage();
Script.setTimeout(function () {
colorToolBar.setImageURL(ICON_URL +
iconLibrary.iconData[iconSelection].inactive,colorsIDs[iconSelection]);
colorToolBar.setImageURL(ICON_URL +
iconLibrary.iconData[0].active,colorsIDs[0]);
iconSelection = 0;
}, ICON_SHOW_TIME);
}
}
}
}
}
function hoverOverEntity(entityID) {
if (isRunning) {
if (entityID !== hoverID || hoverID === undefined) {
hoverProps = Entities.getEntityProperties (entityID);
if (hoverProps.name === "buildSystem") {
hoverID = entityID;
} else {
hoverID = undefined;
}
}
}
}
function mousePressOnEntity(entityID, event) {
if (isRunning) {
var objectProps = {};
if (event.isPrimaryButton && reset) {
reset = false;
objectProps = Entities.getEntityProperties(entityID);
if (objectProps.type === "Box" && objectProps.name === "buildSystem") {
var newPosition = objectProps.position;
originalPosition = objectProps.position;
objectSize = objectProps.dimensions;
var objectRot = objectProps.rotation;
var surfaceNormal = event.normal;
var mainAxisFront = Quat.getFront(objectRot);
var mainAxisRight = Quat.getRight(objectRot);
var mainAxisUp = Quat.getUp(objectRot);
var directionz = 0;
var directiony = 0;
var directionx = 0;
var dotFront = Vec3.dot(surfaceNormal,mainAxisFront);
var dotRight = Vec3.dot(surfaceNormal,mainAxisRight);
var dotUp = Vec3.dot(surfaceNormal,mainAxisUp);
if (Math.abs(dotRight) > 0.98) {
if (dotRight > 0) {
directionx = objectProps.dimensions.x;
} else {
directionx = -objectProps.dimensions.x;
}
}
if (Math.abs(dotUp) > 0.98) {
if (dotUp > 0) {
directiony = objectProps.dimensions.y;
} else {
directiony = -objectProps.dimensions.y;
}
}
if (Math.abs(dotFront) > 0.98) {
if (dotFront > 0) {
directionz = -objectProps.dimensions.z;
} else {
directionz = objectProps.dimensions.z;
}
}
newDirection = { x: directionx, y: directiony, z: directionz };
newPosition = Vec3.sum(originalPosition, Vec3.multiplyQbyV(objectRot, newDirection));
if (iconLibrary.iconData[iconSelection].type === "color") {
var iconColor = JSON.parse(iconLibrary.iconData[iconSelection].color);
hoverID = Entities.addEntity({
type: "Box",
name: "buildSystem",
description: MyAvatar.displayName,
position: newPosition,
color: iconColor,
rotation: objectRot,
dimensions: objectSize,
grab: {triggerable: true,grabbable: false},
lifetime: -1
});
}
}
if (objectProps.type === "Web" && objectProps.name === "blocks-help") {
Entities.deleteEntity(objectProps.id);
}
}
if (event.isMiddleButton) {
if (hoverID) {
var deleteProps = Entities.getEntityProperties(hoverID);
if (deleteProps.name === "buildSystem" && deleteProps.description === MyAvatar.displayName) {
Entities.deleteEntity(hoverID);
}
}
}
}
}
function keyPressEvent(event) {
if (isRunning) {
if (keys.indexOf(event.text) === -1) {
if (UIkeys.indexOf(event.text) !== -1) {
keys.push(event.text);
}
}
if (keys.indexOf("DELETE") !== -1) {
deleteBlock();
}
if (keys.indexOf("SHIFT") !== -1) {
Controller.captureWheelEvents();
isShiftPressed = true;
}
if (keys.indexOf("CONTROL") !== -1) {
Controller.captureWheelEvents();
isControlPressed = true;
}
if (keys.indexOf("ALT") !== -1) {
Controller.captureWheelEvents();
isAltPressed = true;
}
if (keys.indexOf("x") !== -1 || keys.indexOf("X") !== -1) {
isXPressed = true;
currentDirection = "X";
}
if (keys.indexOf("y") !== -1 || keys.indexOf("Y") !== -1) {
isYPressed = true;
currentDirection = "Y";
}
if (keys.indexOf("z") !== -1 || keys.indexOf("Z") !== -1) {
isZPressed = true;
currentDirection = "Z";
}
}
}
function keyReleaseEvent(event) {
if (isRunning) {
keys = [];
if (event.text === "SHIFT") {
Controller.releaseWheelEvents();
isShiftPressed = false;
}
if (event.text === "CONTROL") {
Controller.releaseWheelEvents();
isControlPressed = false;
}
if (event.text === "ALT") {
Controller.releaseWheelEvents();
isAltPressed = false;
}
}
}
function cleanUp() {
Selection.removeListFromMap(LIST_NAME);
if (webPageID) {
Entities.deleteEntity(webPageID);
}
webPageID = undefined;
if (colorToolBar !== undefined) {
colorToolBar.cleanup();
}
colorToolBar = undefined;
if (mainLoop) {
Script.clearInterval(mainLoop);
}
if (isRunning) {
Controller.keyPressEvent.disconnect(keyPressEvent);
Controller.keyReleaseEvent.disconnect(keyReleaseEvent);
Controller.wheelEvent.disconnect(wheelEvent);
Controller.mousePressEvent.disconnect(mousePressEvent);
Entities.hoverOverEntity.disconnect(hoverOverEntity);
Entities.mousePressOnEntity.disconnect(mousePressOnEntity);
}
allOverlays = [];
colorsIDs = [];
}
Script.scriptEnding.connect(function () {
cleanUp();
button.clicked.disconnect(onClicked);
if (tablet) {
tablet.removeButton(button);
}
});
function onClicked() {
if (isRunning) {
tablet.gotoHomeScreen();
cleanUp();
isRunning = false;
button.editProperties({ isActive: false });
} else {
isRunning = true;
button.editProperties({ isActive: true });
loadColors();
addIcons();
createMainloop();
Controller.keyPressEvent.connect(keyPressEvent);
Controller.keyReleaseEvent.connect(keyReleaseEvent);
Controller.wheelEvent.connect(wheelEvent);
Controller.mousePressEvent.connect(mousePressEvent);
Entities.hoverOverEntity.connect(hoverOverEntity);
Entities.mousePressOnEntity.connect(mousePressOnEntity);
}
}
prefetchIcons();
button.clicked.connect(onClicked);