From 36c14de250289f7ad681017c9e60031a07357580 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 10 Mar 2015 13:11:39 -0700 Subject: [PATCH 1/8] Add rotation to facingAvatar billboard overlays --- interface/src/ui/overlays/BillboardOverlay.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 88c097575b..3e3e823737 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -58,6 +58,7 @@ void BillboardOverlay::render(RenderArgs* args) { // rotate about vertical to face the camera rotation = Application::getInstance()->getCamera()->getRotation(); rotation *= glm::angleAxis(glm::pi(), glm::vec3(0.0f, 1.0f, 0.0f)); + rotation *= getRotation(); } else { rotation = getRotation(); } From 5c9ec6bdcc727c6c6486696de66c3a70863d8740 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 12 Mar 2015 11:17:07 -0700 Subject: [PATCH 2/8] Add add/delete/rename/clear events to EntitiesScriptingInterface --- .../entities/src/EntityScriptingInterface.cpp | 19 +++++++++++++++++++ .../entities/src/EntityScriptingInterface.h | 7 ++++++- libraries/entities/src/EntityTree.cpp | 2 ++ libraries/entities/src/EntityTree.h | 1 + 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 5ef0db57ec..639798527a 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -35,6 +35,25 @@ bool EntityScriptingInterface::canAdjustLocks() { } +void EntityScriptingInterface::setEntityTree(EntityTree* modelTree) { + if (_entityTree) { + disconnect(_entityTree, &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); + disconnect(_entityTree, &EntityTree::deletingEntity, this, &EntityScriptingInterface::deletingEntity); + disconnect(_entityTree, &EntityTree::changingEntityID, this, &EntityScriptingInterface::changingEntityID); + disconnect(_entityTree, &EntityTree::clearingEntities, this, &EntityScriptingInterface::clearingEntities); + } + + _entityTree = modelTree; + + if (_entityTree) { + connect(_entityTree, &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); + connect(_entityTree, &EntityTree::deletingEntity, this, &EntityScriptingInterface::deletingEntity); + connect(_entityTree, &EntityTree::changingEntityID, this, &EntityScriptingInterface::changingEntityID); + connect(_entityTree, &EntityTree::clearingEntities, this, &EntityScriptingInterface::clearingEntities); + } +} + + EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& properties) { // The application will keep track of creatorTokenID diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index bac018f2ae..9300149a98 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -58,7 +58,7 @@ public: virtual NodeType_t getServerNodeType() const { return NodeType::EntityServer; } virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); } - void setEntityTree(EntityTree* modelTree) { _entityTree = modelTree; } + void setEntityTree(EntityTree* modelTree); EntityTree* getEntityTree(EntityTree*) { return _entityTree; } public slots: @@ -129,6 +129,11 @@ signals: void enterEntity(const EntityItemID& entityItemID); void leaveEntity(const EntityItemID& entityItemID); + void deletingEntity(const EntityItemID& entityID); + void addingEntity(const EntityItemID& entityID); + void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID); + void clearingEntities(); + private: void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index e952618c9f..e5a7fbee2f 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -37,6 +37,8 @@ EntityTreeElement* EntityTree::createNewElement(unsigned char * octalCode) { } void EntityTree::eraseAllOctreeElements(bool createNewRoot) { + emit clearingEntities(); + // this would be a good place to clean up our entities... if (_simulation) { _simulation->lock(); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 226bfa873a..5126682a99 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -163,6 +163,7 @@ signals: void addingEntity(const EntityItemID& entityID); void entityScriptChanging(const EntityItemID& entityItemID); void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID); + void clearingEntities(); private: From d82598327b1fd2dfde849bc34854f260539b43ff Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 12 Mar 2015 11:18:32 -0700 Subject: [PATCH 3/8] Add light overlays --- examples/editEntities.js | 29 ++++- examples/libraries/lightOverlayManager.js | 123 ++++++++++++++++++++++ 2 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 examples/libraries/lightOverlayManager.js diff --git a/examples/editEntities.js b/examples/editEntities.js index 689f73eed4..993e6cbb4d 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -29,12 +29,15 @@ Script.include([ "libraries/entityCameraTool.js", "libraries/gridTool.js", "libraries/entityList.js", + "libraries/lightOverlayManager.js", ]); var selectionDisplay = SelectionDisplay; var selectionManager = SelectionManager; var entityPropertyDialogBox = EntityPropertyDialogBox; +var lightOverlayManager = new LightOverlayManager(); + var cameraManager = new CameraManager(); var grid = Grid(); @@ -45,6 +48,7 @@ var entityListTool = EntityListTool(); selectionManager.addEventListener(function() { selectionDisplay.updateHandles(); + lightOverlayManager.updatePositions(); }); var windowDimensions = Controller.getViewportDimensions(); @@ -444,12 +448,31 @@ function rayPlaneIntersection(pickRay, point, normal) { function findClickedEntity(event) { var pickRay = Camera.computePickRay(event.x, event.y); - var foundIntersection = Entities.findRayIntersection(pickRay, true); // want precision picking + var entityResult = Entities.findRayIntersection(pickRay, true); // want precision picking + var lightResult = lightOverlayManager.findRayIntersection(pickRay); + lightResult.accurate = true; - if (!foundIntersection.accurate) { + var result; + + if (!entityResult.intersects && !lightResult.intersects) { + return null; + } else if (entityResult.intersects && !lightResult.intersects) { + result = entityResult; + } else if (!entityResult.intersects && lightResult.intersects) { + result = lightResult; + } else { + if (entityResult.distance < lightResult.distance) { + result = entityResult; + } else { + result = lightResult; + } + } + + if (!result.accurate) { return null; } - var foundEntity = foundIntersection.entityID; + + var foundEntity = result.entityID; if (!foundEntity.isKnownID) { var identify = Entities.identifyEntity(foundEntity); diff --git a/examples/libraries/lightOverlayManager.js b/examples/libraries/lightOverlayManager.js new file mode 100644 index 0000000000..1b90ee0a02 --- /dev/null +++ b/examples/libraries/lightOverlayManager.js @@ -0,0 +1,123 @@ +var POINT_LIGHT_URL = "http://s3.amazonaws.com/hifi-public/images/tools/point-light.svg"; +var SPOT_LIGHT_URL = "http://s3.amazonaws.com/hifi-public/images/tools/spot-light.svg"; + +LightOverlayManager = function() { + var self = this; + + // List of all created overlays + var allOverlays = []; + + // List of overlays not currently being used + var unusedOverlays = []; + + // Map from EntityItemID.id to overlay id + var entityOverlays = {}; + + // Map from EntityItemID.id to EntityItemID object + var entityIDs = {}; + + this.updatePositions = function(ids) { + for (var id in entityIDs) { + var entityID = entityIDs[id]; + var properties = Entities.getEntityProperties(entityID); + Overlays.editOverlay(entityOverlays[entityID.id], { + position: properties.position + }); + } + }; + + this.findRayIntersection = function(pickRay) { + var result = Overlays.findRayIntersection(pickRay); + var found = false; + + if (result.intersects) { + for (var id in entityOverlays) { + if (result.overlayID == entityOverlays[id]) { + result.entityID = entityIDs[id]; + found = true; + break; + } + } + + if (!found) { + result.intersects = false; + } + } + + return result; + }; + + // Allocate or get an unused overlay + function getOverlay() { + if (unusedOverlays.length == 0) { + var overlay = Overlays.addOverlay("billboard", { + }); + allOverlays.push(overlay); + } else { + var overlay = unusedOverlays.pop(); + }; + return overlay; + } + + function releaseOverlay(overlay) { + unusedOverlays.push(overlay); + Overlays.editOverlay(overlay, { visible: false }); + } + + function addEntity(entityID) { + var properties = Entities.getEntityProperties(entityID); + if (properties.type == "Light" && !(entityID.id in entityOverlays)) { + var overlay = getOverlay(); + entityOverlays[entityID.id] = overlay; + entityIDs[entityID.id] = entityID; + Overlays.editOverlay(overlay, { + position: properties.position, + url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL, + rotation: Quat.fromPitchYawRollDegrees(0, 0, 270), + visible: true, + alpha: 0.9, + color: { red: 255, green: 255, blue: 255 } + }); + } + } + + function deleteEntity(entityID) { + if (entityID.id in entityOverlays) { + releaseOverlay(entityOverlays[entityID.id]); + delete entityOverlays[entityID.id]; + } + } + + function changeEntityID(oldEntityID, newEntityID) { + entityOverlays[newEntityID.id] = entityOverlays[oldEntityID.id]; + entityIDs[newEntityID.id] = newEntityID; + + delete entityOverlays[oldEntityID.id]; + delete entityIDs[oldEntityID.id]; + } + + function clearEntities() { + for (var id in entityOverlays) { + releaseOverlay(entityOverlays[id]); + } + entityOverlays = {}; + entityIDs = {}; + } + + Entities.addingEntity.connect(addEntity); + Entities.changingEntityID.connect(changeEntityID); + Entities.deletingEntity.connect(deleteEntity); + Entities.clearingEntities.connect(clearEntities); + + // Add existing entities + var ids = Entities.findEntities(MyAvatar.position, 100); + for (var i = 0; i < ids.length; i++) { + addEntity(ids[i]); + } + + Script.scriptEnding.connect(function() { + for (var i = 0; i < allOverlays.length; i++) { + Overlays.deleteOverlay(allOverlays[i]); + } + }); +}; From ccbbba3def6d2c951936508dffb10a2afcd0fae6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 12 Mar 2015 11:18:42 -0700 Subject: [PATCH 4/8] Update light default dimensions --- examples/editEntities.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index 993e6cbb4d..cad086beb9 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -74,6 +74,8 @@ var DEFAULT_DIMENSIONS = { z: DEFAULT_DIMENSION }; +var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS); + var MENU_INSPECT_TOOL_ENABLED = "Inspect Tool"; var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select"; var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; @@ -333,8 +335,8 @@ var toolBar = (function () { if (position.x > 0 && position.y > 0 && position.z > 0) { placingEntityID = Entities.addEntity({ type: "Light", - position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS), - dimensions: DEFAULT_DIMENSIONS, + position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_LIGHT_DIMENSIONS), DEFAULT_LIGHT_DIMENSIONS), + dimensions: DEFAULT_LIGHT_DIMENSIONS, isSpotlight: false, diffuseColor: { red: 255, green: 255, blue: 255 }, ambientColor: { red: 255, green: 255, blue: 255 }, From c13ba4a31823e1046d33a5bc18927205ff288aa1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 12 Mar 2015 11:38:29 -0700 Subject: [PATCH 5/8] Add toggling of light visibility --- examples/editEntities.js | 1 + examples/libraries/lightOverlayManager.js | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index cad086beb9..81b62ac0f0 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -205,6 +205,7 @@ var toolBar = (function () { } } toolBar.selectTool(activeButton, isActive); + lightOverlayManager.setVisible(isActive); }; var RESIZE_INTERVAL = 50; diff --git a/examples/libraries/lightOverlayManager.js b/examples/libraries/lightOverlayManager.js index 1b90ee0a02..9fe451ee13 100644 --- a/examples/libraries/lightOverlayManager.js +++ b/examples/libraries/lightOverlayManager.js @@ -4,6 +4,8 @@ var SPOT_LIGHT_URL = "http://s3.amazonaws.com/hifi-public/images/tools/spot-ligh LightOverlayManager = function() { var self = this; + var visible = false; + // List of all created overlays var allOverlays = []; @@ -47,6 +49,15 @@ LightOverlayManager = function() { return result; }; + this.setVisible = function(isVisible) { + if (visible != isVisible) { + visible = isVisible; + for (var id in entityOverlays) { + Overlays.editOverlay(entityOverlays[id], { visible: visible }); + } + } + }; + // Allocate or get an unused overlay function getOverlay() { if (unusedOverlays.length == 0) { @@ -74,7 +85,7 @@ LightOverlayManager = function() { position: properties.position, url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL, rotation: Quat.fromPitchYawRollDegrees(0, 0, 270), - visible: true, + visible: visible, alpha: 0.9, color: { red: 255, green: 255, blue: 255 } }); From 4335a41002cf33cab9985be4ac5c1ac0de8430c7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 12 Mar 2015 11:38:51 -0700 Subject: [PATCH 6/8] Update editEntities to call setActive on init --- examples/editEntities.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/editEntities.js b/examples/editEntities.js index 81b62ac0f0..e787f71f0f 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -178,6 +178,7 @@ var toolBar = (function () { visible: true }); + that.setActive(false); } that.setActive = function(active) { From 165199c69d5ea0a013e9c169f8a0d8041cff8a26 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 12 Mar 2015 15:55:31 -0700 Subject: [PATCH 7/8] Update light overlay size --- examples/libraries/lightOverlayManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/libraries/lightOverlayManager.js b/examples/libraries/lightOverlayManager.js index 9fe451ee13..8032d77c49 100644 --- a/examples/libraries/lightOverlayManager.js +++ b/examples/libraries/lightOverlayManager.js @@ -87,6 +87,7 @@ LightOverlayManager = function() { rotation: Quat.fromPitchYawRollDegrees(0, 0, 270), visible: visible, alpha: 0.9, + scale: 0.5, color: { red: 255, green: 255, blue: 255 } }); } From a3c2df5c775dfc6cc1bc4b7669917212fbb018f5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 12 Mar 2015 16:16:29 -0700 Subject: [PATCH 8/8] Add menu option to turn on/off showing lights in edit mode --- examples/editEntities.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index fe91189404..72d4cfa0c1 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -79,10 +79,12 @@ var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS); var MENU_INSPECT_TOOL_ENABLED = "Inspect Tool"; var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select"; var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; +var MENU_SHOW_LIGHTS_IN_EDIT_MODE = "Show Lights in Edit Mode"; var SETTING_INSPECT_TOOL_ENABLED = "inspectToolEnabled"; var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect"; var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus"; +var SETTING_SHOW_LIGHTS_IN_EDIT_MODE = "showLightsInEditMode"; var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain." @@ -222,7 +224,7 @@ var toolBar = (function () { } } toolBar.selectTool(activeButton, isActive); - lightOverlayManager.setVisible(isActive); + lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); }; // Sets visibility of tool buttons, excluding the power button @@ -758,6 +760,8 @@ function setupModelMenus() { isCheckable: true, isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true" }); Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_AUTO_FOCUS_ON_SELECT, isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" }); + Menu.addMenuItem({ menuName: "View", menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE, afterItem: MENU_EASE_ON_FOCUS, + isCheckable: true, isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true" }); Entities.setLightsArePickable(false); } @@ -784,11 +788,13 @@ function cleanupModelMenus() { Menu.removeMenuItem("View", MENU_INSPECT_TOOL_ENABLED); Menu.removeMenuItem("View", MENU_AUTO_FOCUS_ON_SELECT); Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS); + Menu.removeMenuItem("View", MENU_SHOW_LIGHTS_IN_EDIT_MODE); } Script.scriptEnding.connect(function() { Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)); Settings.setValue(SETTING_EASE_ON_FOCUS, Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); + Settings.setValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); progressDialog.cleanup(); toolBar.cleanup(); @@ -865,6 +871,8 @@ function handeMenuEvent(menuItem) { } } else if (menuItem == "Entity List...") { entityListTool.toggleVisible(); + } else if (menuItem == MENU_SHOW_LIGHTS_IN_EDIT_MODE) { + lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); } tooltip.show(false); }