From 93516423bb9aeb87c887252f82967b7bd09b48fa Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 11 Jan 2019 21:32:18 +0100 Subject: [PATCH] zone visualizer prototype --- scripts/system/edit.js | 14 +- .../system/modules/entityShapeVisualizer.js | 209 ++++++++++++++++++ 2 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 scripts/system/modules/entityShapeVisualizer.js diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 84143f4c25..c6a30fe209 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -82,13 +82,18 @@ var selectionManager = SelectionManager; var PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg"); var POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg"); var SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg"); +var ZONE_URL = Script.resourcesPath() + "icons/create-icons/23-zone-01.svg"; -var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect'], function(entityID) { +var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect', 'Zone'], function(entityID) { var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']); if (properties.type === 'Light') { return { url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL, }; + } else if (properties.type === 'Zone') { + return { + url: ZONE_URL, + }; } else { return { url: PARTICLE_SYSTEM_URL, @@ -106,11 +111,15 @@ var gridTool = new GridTool({ }); gridTool.setVisible(false); +var EntityShapeVisualizer = Script.require('./modules/entityShapeVisualizer.js'); +var entityShapeVisualizer = new EntityShapeVisualizer(["Zone"]); + var entityListTool = new EntityListTool(shouldUseEditTabletApp); selectionManager.addEventListener(function () { selectionDisplay.updateHandles(); entityIconOverlayManager.updatePositions(); + entityShapeVisualizer.updateSelection(selectionManager.selections); }); var DEGREES_TO_RADIANS = Math.PI / 180.0; @@ -836,7 +845,7 @@ var toolBar = (function () { dialogWindow.fromQml.connect(fromQml); } }; - }; + } addButton("newModelButton", createNewEntityDialogButtonCallback("Model")); @@ -1492,6 +1501,7 @@ Script.scriptEnding.connect(function () { cleanupModelMenus(); tooltip.cleanup(); selectionDisplay.cleanup(); + entityShapeVisualizer.cleanup(); Entities.setLightsArePickable(originalLightsArePickable); Overlays.deleteOverlay(importingSVOImageOverlay); diff --git a/scripts/system/modules/entityShapeVisualizer.js b/scripts/system/modules/entityShapeVisualizer.js new file mode 100644 index 0000000000..5c91b1311c --- /dev/null +++ b/scripts/system/modules/entityShapeVisualizer.js @@ -0,0 +1,209 @@ +"use strict"; + +// entityShapeVisualizer.js +// +// Created by Thijs Wenker on 1/11/19 +// +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var SHAPETYPE_TO_SHAPE = { + "sphere": "Sphere", + "box": "Cube", + "ellipsoid": "Sphere", + "cylinder-y": "Cylinder", +}; + +function getEntityShapePropertiesForType(properties) { + switch (properties.type) { + case "Zone": + if (SHAPETYPE_TO_SHAPE[properties.shapeType]) { + return { + type: "Shape", + shape: SHAPETYPE_TO_SHAPE[properties.shapeType] + } + } else if (properties.shapeType === "compound") { + return { + type: "Model", + modelURL: properties.compoundShapeURL + } + } + break; + } + + // Default properties + return { + type: "Shape", + shape: "Cube" + } +} + +function getStringifiedEntityShapePropertiesForType(properties) { + return JSON.stringify(getEntityShapePropertiesForType(properties)); +} + +var REQUESTED_ENTITY_SHAPE_PROPERTIES = [ + 'type', 'shapeType', 'compoundShapeURL', 'localDimensions' +]; + +function EntityShape(entityID) { + this.entityID = entityID; + var properties = Entities.getEntityProperties(entityID, REQUESTED_ENTITY_SHAPE_PROPERTIES); + + this.previousPropertiesForTypeStringified = getStringifiedEntityShapePropertiesForType(properties); + + this.initialize(properties, this.previousPropertiesForTypeStringified); +} + +EntityShape.prototype = { + initialize: function(properties, propertiesForTypeStringified) { + // Create new instance of JS object: + var overlayProperties = JSON.parse(propertiesForTypeStringified); + + overlayProperties.localPosition = Vec3.ZERO; + overlayProperties.localRotation = Quat.IDENTITY; + overlayProperties.localDimensions = properties.localDimensions; + overlayProperties.canCastShadows = false; + overlayProperties.parentID = this.entityID; + overlayProperties.collisionless = true; + this.entity = Entities.addEntity(overlayProperties, "local"); + + console.warn("created " + this.entity); + console.warn("SHAPETYPE = " + properties.shapeType); + console.warn("SHAPE = " + Entities.getEntityProperties(this.entity, "shape").shape); + + + this.materialEntity = Entities.addEntity({ + type: "Material", + localPosition: Vec3.ZERO, + localRotation: Quat.IDENTITY, + localDimensions: properties.localDimensions, + parentID: this.entity, + priority: 1, + materialURL: "materialData", + materialData: JSON.stringify({ + materialVersion: 1, + materials: { + albedo: [0.0, 0.0, 7.0], + unlit: true, + opacity: 0.4 + } + }), + }, "local"); + + }, + + update: function() { + var properties = Entities.getEntityProperties(this.entityID, REQUESTED_ENTITY_SHAPE_PROPERTIES); + var propertiesForTypeStringified = getStringifiedEntityShapePropertiesForType(properties); + if (propertiesForTypeStringified !== this.previousPropertiesForTypeStringified) { + this.previousPropertiesForTypeStringified = propertiesForTypeStringified; + console.warn("Clearing old properties"); + this.clear(); + this.initialize(properties, propertiesForTypeStringified); + } else { + Entities.editEntity(this.entity, { + localDimensions: properties.localDimensions, + }); + } + + + + //this.previousProperties = Entities.getEntityProperties(this.entityID, REQUESTED_ENTITY_SHAPE_PROPERTIES); + + + console.warn(JSON.stringify(this.previousProperties)); + }, + clear: function() { + Entities.deleteEntity(this.materialEntity); + Entities.deleteEntity(this.entity); + } +}; + +function EntityShapeVisualizer(visualizedTypes) { + this.acceptedEntities = []; + this.ignoredEntities = []; + this.entityShapes = {}; + + this.visualizedTypes = visualizedTypes; +} + +EntityShapeVisualizer.prototype = { + addEntity: function(entityID, properties) { + if (this.entityShapes[entityID]) { + return; + } + this.entityShapes[entityID] = new EntityShape(entityID); + + }, + updateEntity: function(entityID) { + if (!this.entityShapes[entityID]) { + return; + } + this.entityShapes[entityID].update(); + }, + removeEntity: function(entityID) { + if (!this.entityShapes[entityID]) { + return; + } + this.entityShapes[entityID].clear(); + delete this.entityShapes[entityID]; + }, + cleanup: function() { + Object.keys(this.entityShapes).forEach(function(entityID) { + this.entityShapes[entityID].clear(); + }, this); + this.entityShapes = {}; + }, + updateSelection: function(selection) { + var qualifiedSelection = selection.filter(function(entityID) { + if (this.acceptedEntities.indexOf(entityID) !== -1) { + return true; + } + if (this.ignoredEntities.indexOf(entityID) !== -1) { + return false; + } + if (this.visualizedTypes.indexOf(Entities.getEntityProperties(entityID, "type").type) !== -1) { + this.acceptedEntities.push(entityID); + return true; + } + this.ignoredEntities.push(entityID); + return false; + }, this); + + + var newEntries = []; + var updateEntries = []; + + var currentEntries = Object.keys(this.entityShapes); + qualifiedSelection.forEach(function(entityID) { + if (currentEntries.indexOf(entityID) !== -1) { + updateEntries.push(entityID); + } else { + newEntries.push(entityID); + } + }); + + var deleteEntries = currentEntries.filter(function(entityID) { + return updateEntries.indexOf(entityID) === -1; + }); + + deleteEntries.forEach(function(entityID) { + console.warn("removing " + entityID); + this.removeEntity(entityID); + }, this); + + updateEntries.forEach(function(entityID) { + this.updateEntity(entityID); + }, this); + + newEntries.forEach(function(entityID) { + this.addEntity(entityID); + }, this); + } +}; + +module.exports = EntityShapeVisualizer;