From ce5ee429617caa63cfbee068eba08ed8b6e95e97 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Feb 2017 10:07:46 -0800 Subject: [PATCH 01/23] Update LightOverlayManager to work with particles --- scripts/system/edit.js | 18 +++++++++++-- ...Manager.js => entityIconOverlayManager.js} | 26 ++++++++++++------- 2 files changed, 32 insertions(+), 12 deletions(-) rename scripts/system/libraries/{lightOverlayManager.js => entityIconOverlayManager.js} (80%) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index a440fec1ac..d195864ed6 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -33,13 +33,27 @@ Script.include([ "libraries/gridTool.js", "libraries/entityList.js", "particle_explorer/particleExplorerTool.js", - "libraries/lightOverlayManager.js" + "libraries/entityIconOverlayManager.js" ]); var selectionDisplay = SelectionDisplay; var selectionManager = SelectionManager; -var lightOverlayManager = new LightOverlayManager(); +const PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg"); +const POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg"); +const SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg"); +var lightOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect'], function(entityID) { + var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']); + if (properties.type === 'Light') { + return { + url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL, + } + } else { + return { + url: PARTICLE_SYSTEM_URL, + } + } +}); var cameraManager = new CameraManager(); diff --git a/scripts/system/libraries/lightOverlayManager.js b/scripts/system/libraries/entityIconOverlayManager.js similarity index 80% rename from scripts/system/libraries/lightOverlayManager.js rename to scripts/system/libraries/entityIconOverlayManager.js index 2d3618096b..aafb0725f3 100644 --- a/scripts/system/libraries/lightOverlayManager.js +++ b/scripts/system/libraries/entityIconOverlayManager.js @@ -1,7 +1,4 @@ -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() { +EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) { var self = this; var visible = false; @@ -79,24 +76,33 @@ LightOverlayManager = function() { } function addEntity(entityID) { - var properties = Entities.getEntityProperties(entityID); - if (properties.type == "Light" && !(entityID in entityOverlays)) { + var properties = Entities.getEntityProperties(entityID, ['position', 'type']); + if (entityTypes.indexOf(properties.type) > -1 && !(entityID in entityOverlays)) { var overlay = getOverlay(); entityOverlays[entityID] = overlay; entityIDs[entityID] = entityID; - Overlays.editOverlay(overlay, { + var overlayProperties = { position: properties.position, - url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL, rotation: Quat.fromPitchYawRollDegrees(0, 0, 270), visible: visible, alpha: 0.9, scale: 0.5, + drawInFront: true, + isFacingAvatar: true, color: { red: 255, green: 255, blue: 255 } - }); + }; + if (getOverlayPropertiesFunc) { + var customProperties = getOverlayPropertiesFunc(entityID, properties); + for (var key in customProperties) { + overlayProperties[key] = customProperties[key]; + } + } + print("overlay:", properties.type, JSON.stringify(overlayProperties)); + Overlays.editOverlay(overlay, overlayProperties); } } @@ -130,4 +136,4 @@ LightOverlayManager = function() { Overlays.deleteOverlay(allOverlays[i]); } }); -}; \ No newline at end of file +}; From 86116aaad7ba4ef035a078081c3ead090f4c80d4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Feb 2017 10:20:24 -0800 Subject: [PATCH 02/23] Update light/particel icons to be shown by default in edit mode --- scripts/system/edit.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index d195864ed6..d77b5804c8 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -96,13 +96,13 @@ var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS); 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 MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "Show Lights and Particle Systems in Edit Mode"; var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones 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 SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "showLightsAndParticlesInEditMode"; var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode"; @@ -520,7 +520,7 @@ var toolBar = (function () { toolBar.writeProperty("shown", false); toolBar.writeProperty("shown", true); } - lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); + lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); }; @@ -959,18 +959,18 @@ function setupModelMenus() { }); Menu.addMenuItem({ menuName: "Edit", - menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE, + menuItemName: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, afterItem: MENU_EASE_ON_FOCUS, isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) === "true", + isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) !== "false", grouping: "Advanced" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, - afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE, + afterItem: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) === "true", + isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) !== "false", grouping: "Advanced" }); @@ -1001,7 +1001,7 @@ function cleanupModelMenus() { Menu.removeMenuItem("Edit", MENU_AUTO_FOCUS_ON_SELECT); Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS); - Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_IN_EDIT_MODE); + Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE); Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE); } @@ -1009,7 +1009,7 @@ Script.scriptEnding.connect(function () { toolBar.setActive(false); 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)); + Settings.setValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); progressDialog.cleanup(); @@ -1297,8 +1297,8 @@ function handeMenuEvent(menuItem) { selectAllEtitiesInCurrentSelectionBox(false); } else if (menuItem === "Select All Entities Touching Box") { selectAllEtitiesInCurrentSelectionBox(true); - } else if (menuItem === MENU_SHOW_LIGHTS_IN_EDIT_MODE) { - lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); + } else if (menuItem === MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) { + lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); } else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) { Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); } From 42d518fafbfd10ec2426a6bbeef8fb793838e6cf Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Feb 2017 10:24:55 -0800 Subject: [PATCH 03/23] Remove debug log in entityIconOverlayManager --- scripts/system/libraries/entityIconOverlayManager.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/system/libraries/entityIconOverlayManager.js b/scripts/system/libraries/entityIconOverlayManager.js index aafb0725f3..2623b6d6cb 100644 --- a/scripts/system/libraries/entityIconOverlayManager.js +++ b/scripts/system/libraries/entityIconOverlayManager.js @@ -101,7 +101,6 @@ EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) { overlayProperties[key] = customProperties[key]; } } - print("overlay:", properties.type, JSON.stringify(overlayProperties)); Overlays.editOverlay(overlay, overlayProperties); } } From dbcd7fd9e9479ccb136640a89c86582e962777d9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Feb 2017 10:31:44 -0800 Subject: [PATCH 04/23] Fix light icon overlay not updating to represent light type --- scripts/system/libraries/entityIconOverlayManager.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/system/libraries/entityIconOverlayManager.js b/scripts/system/libraries/entityIconOverlayManager.js index 2623b6d6cb..ec86057ab0 100644 --- a/scripts/system/libraries/entityIconOverlayManager.js +++ b/scripts/system/libraries/entityIconOverlayManager.js @@ -19,9 +19,16 @@ EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) { for (var id in entityIDs) { var entityID = entityIDs[id]; var properties = Entities.getEntityProperties(entityID); - Overlays.editOverlay(entityOverlays[entityID], { + var overlayProperties = { position: properties.position - }); + }; + if (getOverlayPropertiesFunc) { + var customProperties = getOverlayPropertiesFunc(entityID, properties); + for (var key in customProperties) { + overlayProperties[key] = customProperties[key]; + } + } + Overlays.editOverlay(entityOverlays[entityID], overlayProperties); } }; From c2564800dc50d7afcf1c2f3a41fd1bedb13fee06 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 22 Feb 2017 15:18:08 -0800 Subject: [PATCH 05/23] Add edit.js particle + light icons --- .../system/assets/images/icon-particles.svg | 29 ++++++++++ .../system/assets/images/icon-point-light.svg | 57 +++++++++++++++++++ .../system/assets/images/icon-spot-light.svg | 37 ++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 scripts/system/assets/images/icon-particles.svg create mode 100644 scripts/system/assets/images/icon-point-light.svg create mode 100644 scripts/system/assets/images/icon-spot-light.svg diff --git a/scripts/system/assets/images/icon-particles.svg b/scripts/system/assets/images/icon-particles.svg new file mode 100644 index 0000000000..5e0105d7cd --- /dev/null +++ b/scripts/system/assets/images/icon-particles.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + diff --git a/scripts/system/assets/images/icon-point-light.svg b/scripts/system/assets/images/icon-point-light.svg new file mode 100644 index 0000000000..896c35b63b --- /dev/null +++ b/scripts/system/assets/images/icon-point-light.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/assets/images/icon-spot-light.svg b/scripts/system/assets/images/icon-spot-light.svg new file mode 100644 index 0000000000..ac2f87bb27 --- /dev/null +++ b/scripts/system/assets/images/icon-spot-light.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From b7783dcffe4c5bbf9e4cc2649be57ed505dfc0c4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 13 Mar 2017 11:26:34 -0700 Subject: [PATCH 06/23] Update edit.js light/particle overlays to be clickable when behind something --- scripts/system/edit.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index d77b5804c8..2f7e0fabd7 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -594,18 +594,12 @@ function findClickedEntity(event) { var result; - if (!entityResult.intersects && !lightResult.intersects) { - return null; - } else if (entityResult.intersects && !lightResult.intersects) { - result = entityResult; - } else if (!entityResult.intersects && lightResult.intersects) { + if (lightResult.intersects) { result = lightResult; + } else if (entityResult.intersects) { + result = entityResult; } else { - if (entityResult.distance < lightResult.distance) { - result = entityResult; - } else { - result = lightResult; - } + return null; } if (!result.accurate) { From d4ade8278c1d4f8305c3b02ccdc153f3ccfc5ad0 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 13 Mar 2017 11:27:12 -0700 Subject: [PATCH 07/23] Fix js linting errors in entityIconOverlayManager.js --- .../libraries/entityIconOverlayManager.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/scripts/system/libraries/entityIconOverlayManager.js b/scripts/system/libraries/entityIconOverlayManager.js index ec86057ab0..7f7a293bc3 100644 --- a/scripts/system/libraries/entityIconOverlayManager.js +++ b/scripts/system/libraries/entityIconOverlayManager.js @@ -1,6 +1,6 @@ -EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) { - var self = this; +/* globals EntityIconOverlayManager:true */ +EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) { var visible = false; // List of all created overlays @@ -38,7 +38,7 @@ EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) { if (result.intersects) { for (var id in entityOverlays) { - if (result.overlayID == entityOverlays[id]) { + if (result.overlayID === entityOverlays[id]) { result.entityID = entityIDs[id]; found = true; break; @@ -54,7 +54,7 @@ EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) { }; this.setVisible = function(isVisible) { - if (visible != isVisible) { + if (visible !== isVisible) { visible = isVisible; for (var id in entityOverlays) { Overlays.editOverlay(entityOverlays[id], { @@ -66,12 +66,13 @@ EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) { // Allocate or get an unused overlay function getOverlay() { - if (unusedOverlays.length == 0) { - var overlay = Overlays.addOverlay("image3d", {}); + var overlay; + if (unusedOverlays.length === 0) { + overlay = Overlays.addOverlay("image3d", {}); allOverlays.push(overlay); } else { - var overlay = unusedOverlays.pop(); - }; + overlay = unusedOverlays.pop(); + } return overlay; } From 9880d40cfbaee075a2177ae684724c0677e5ffec Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 13 Mar 2017 14:38:56 -0700 Subject: [PATCH 08/23] Update edit.js light icons to now use the name entityIcon --- scripts/system/edit.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 2f7e0fabd7..acf22018b8 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -42,7 +42,7 @@ var selectionManager = SelectionManager; const PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg"); const POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg"); const SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg"); -var lightOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect'], function(entityID) { +var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect'], function(entityID) { var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']); if (properties.type === 'Light') { return { @@ -67,7 +67,7 @@ var entityListTool = new EntityListTool(); selectionManager.addEventListener(function () { selectionDisplay.updateHandles(); - lightOverlayManager.updatePositions(); + entityIconOverlayManager.updatePositions(); }); const KEY_P = 80; //Key code for letter p used for Parenting hotkey. @@ -520,7 +520,7 @@ var toolBar = (function () { toolBar.writeProperty("shown", false); toolBar.writeProperty("shown", true); } - lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); + entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); }; @@ -585,8 +585,8 @@ function findClickedEntity(event) { } var entityResult = Entities.findRayIntersection(pickRay, true); // want precision picking - var lightResult = lightOverlayManager.findRayIntersection(pickRay); - lightResult.accurate = true; + var iconResult = entityIconOverlayManager.findRayIntersection(pickRay); + iconResult.accurate = true; if (pickZones) { Entities.setZonesArePickable(false); @@ -594,8 +594,8 @@ function findClickedEntity(event) { var result; - if (lightResult.intersects) { - result = lightResult; + if (iconResult.intersects) { + result = iconResult; } else if (entityResult.intersects) { result = entityResult; } else { @@ -1292,7 +1292,7 @@ function handeMenuEvent(menuItem) { } else if (menuItem === "Select All Entities Touching Box") { selectAllEtitiesInCurrentSelectionBox(true); } else if (menuItem === MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) { - lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); + entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); } else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) { Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); } From 8a1bd781f083a42dab34ba93fb713d0f041e3872 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 13 Mar 2017 14:44:14 -0700 Subject: [PATCH 09/23] Fix overlay findRayIntersection not properly handing multiple drawInFront overlays --- interface/src/ui/overlays/Overlays.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index ad7fbd6cc2..2b52f0817e 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -431,7 +431,9 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, thisFace, thisSurfaceNormal, thisExtraInfo)) { bool isDrawInFront = thisOverlay->getDrawInFront(); - if (thisDistance < bestDistance && (!bestIsFront || isDrawInFront)) { + if ((bestIsFront && isDrawInFront && thisDistance < bestDistance) + || (!bestIsFront && (isDrawInFront || thisDistance < bestDistance))) { + bestIsFront = isDrawInFront; bestDistance = thisDistance; result.intersects = true; From 8246dbafabe8e529688c572ba253af0033211f44 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 13 Mar 2017 15:15:36 -0700 Subject: [PATCH 10/23] Update particle explorer to work outside of entity list --- scripts/system/edit.js | 74 +++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index acf22018b8..42ebb1b8db 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -68,6 +68,44 @@ var entityListTool = new EntityListTool(); selectionManager.addEventListener(function () { selectionDisplay.updateHandles(); entityIconOverlayManager.updatePositions(); + + // Update particle explorer + var needToDestroyParticleExplorer = false; + if (selectionManager.selections.length === 1) { + var selectedEntityID = selectionManager.selections[0]; + if (selectedEntityID === selectedParticleEntityID) { + return; + } + var type = Entities.getEntityProperties(selectedEntityID, "type").type; + if (type === "ParticleEffect") { + // Destroy the old particles web view first + particleExplorerTool.destroyWebView(); + particleExplorerTool.createWebView(); + var properties = Entities.getEntityProperties(selectedEntityID); + var particleData = { + messageType: "particle_settings", + currentProperties: properties + }; + selectedParticleEntityID = selectedEntityID; + particleExplorerTool.setActiveParticleEntity(selectedParticleEntityID); + + particleExplorerTool.webView.webEventReceived.connect(function (data) { + data = JSON.parse(data); + if (data.messageType === "page_loaded") { + particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData)); + } + }); + } else { + needToDestroyParticleExplorer = true; + } + } else { + needToDestroyParticleExplorer = true; + } + + if (needToDestroyParticleExplorer && selectedParticleEntityID !== null) { + selectedParticleEntityID = null; + particleExplorerTool.destroyWebView(); + } }); const KEY_P = 80; //Key code for letter p used for Parenting hotkey. @@ -1192,7 +1230,7 @@ function parentSelectedEntities() { } function deleteSelectedEntities() { if (SelectionManager.hasSelection()) { - selectedParticleEntity = 0; + selectedParticleEntityID = null; particleExplorerTool.destroyWebView(); SelectionManager.saveProperties(); var savedProperties = []; @@ -1967,43 +2005,13 @@ var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace"); var propertiesTool = new PropertiesTool(); var particleExplorerTool = new ParticleExplorerTool(); -var selectedParticleEntity = 0; +var selectedParticleEntityID = null; entityListTool.webView.webEventReceived.connect(function (data) { data = JSON.parse(data); - if(data.type === 'parent') { + if (data.type === 'parent') { parentSelectedEntities(); } else if(data.type === 'unparent') { unparentSelectedEntities(); - } else if (data.type === "selectionUpdate") { - var ids = data.entityIds; - if (ids.length === 1) { - if (Entities.getEntityProperties(ids[0], "type").type === "ParticleEffect") { - if (JSON.stringify(selectedParticleEntity) === JSON.stringify(ids[0])) { - // This particle entity is already selected, so return - return; - } - // Destroy the old particles web view first - particleExplorerTool.destroyWebView(); - particleExplorerTool.createWebView(); - var properties = Entities.getEntityProperties(ids[0]); - var particleData = { - messageType: "particle_settings", - currentProperties: properties - }; - selectedParticleEntity = ids[0]; - particleExplorerTool.setActiveParticleEntity(ids[0]); - - particleExplorerTool.webView.webEventReceived.connect(function (data) { - data = JSON.parse(data); - if (data.messageType === "page_loaded") { - particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData)); - } - }); - } else { - selectedParticleEntity = 0; - particleExplorerTool.destroyWebView(); - } - } } }); From 2302b157f2abd4004112db4682b440e97ecef3d7 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 17 Mar 2017 21:06:50 +0100 Subject: [PATCH 11/23] Boppo script for welcome area (will be in marketplace later) --- .../marketplace/boppo/boppoClownEntity.js | 80 ++++ .../marketplace/boppo/boppoServer.js | 299 ++++++++++++ .../marketplace/boppo/clownGloveDispenser.js | 154 +++++++ .../marketplace/boppo/createElBoppo.js | 426 ++++++++++++++++++ .../marketplace/boppo/lookAtEntity.js | 98 ++++ 5 files changed, 1057 insertions(+) create mode 100644 unpublishedScripts/marketplace/boppo/boppoClownEntity.js create mode 100644 unpublishedScripts/marketplace/boppo/boppoServer.js create mode 100644 unpublishedScripts/marketplace/boppo/clownGloveDispenser.js create mode 100644 unpublishedScripts/marketplace/boppo/createElBoppo.js create mode 100644 unpublishedScripts/marketplace/boppo/lookAtEntity.js diff --git a/unpublishedScripts/marketplace/boppo/boppoClownEntity.js b/unpublishedScripts/marketplace/boppo/boppoClownEntity.js new file mode 100644 index 0000000000..ef01e47f6f --- /dev/null +++ b/unpublishedScripts/marketplace/boppo/boppoClownEntity.js @@ -0,0 +1,80 @@ +// +// boppoClownEntity.js +// +// Created by Thijs Wenker on 3/15/17. +// Copyright 2017 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 +// + +/* globals BoppoClownEntity:true LookAtTarget */ + +(function() { + var SFX_PREFIX = 'http://hifi-content.s3-us-west-1.amazonaws.com/caitlyn/production/elBoppo/sfx/'; + var CHANNEL_PREFIX = 'io.highfidelity.boppo_server_'; + var PUNCH_SOUNDS = [ + 'punch_1.wav', + 'punch_2.wav' + ]; + var PUNCH_COOLDOWN = 300; + + Script.include(Script.resolvePath('lookAtEntity.js?v2')); + + BoppoClownEntity = function() { + var _this, + _entityID, + _boppoUserData, + _lookAtTarget, + _punchSounds = [], + _lastPlayedPunch = {}; + + var getOwnBoppoUserData = function() { + try { + return JSON.parse(Entities.getEntityProperties(_entityID, ['userData']).userData).Boppo; + } catch (e) { + // e + } + return {}; + }; + + BoppoClownEntity = function () { + _this = this; + PUNCH_SOUNDS.forEach(function(punch) { + _punchSounds.push(SoundCache.getSound(SFX_PREFIX + punch)); + }); + }; + + BoppoClownEntity.prototype = { + preload: function(entityID) { + _entityID = entityID; + _boppoUserData = getOwnBoppoUserData(); + _lookAtTarget = new LookAtTarget(_entityID); + }, + collisionWithEntity: function(boppoEntity, collidingEntity, collisionInfo) { + if (collisionInfo.type === 0 && + Entities.getEntityProperties(collidingEntity, ['name']).name.indexOf('Boxing Glove ') === 0) { + + if (_lastPlayedPunch[collidingEntity] === undefined || + Date.now() - _lastPlayedPunch[collidingEntity] > PUNCH_COOLDOWN) { + + // If boxing glove detected here: + Messages.sendMessage(CHANNEL_PREFIX + _boppoUserData.gameParentID, 'hit'); + + _lookAtTarget.lookAtByAction(); + var randomPunchIndex = Math.floor(Math.random() * _punchSounds.length); + Audio.playSound(_punchSounds[randomPunchIndex], { + position: collisionInfo.contactPoint + }); + _lastPlayedPunch[collidingEntity] = Date.now(); + } + } + } + + }; + + return new BoppoClownEntity(); + }; + + return new BoppoClownEntity(); +}); diff --git a/unpublishedScripts/marketplace/boppo/boppoServer.js b/unpublishedScripts/marketplace/boppo/boppoServer.js new file mode 100644 index 0000000000..ebe938c043 --- /dev/null +++ b/unpublishedScripts/marketplace/boppo/boppoServer.js @@ -0,0 +1,299 @@ +// +// boppoServer.js +// +// Created by Thijs Wenker on 3/15/17. +// Copyright 2017 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 +// + +/* globals BoppoServer:true */ + +(function() { + var SFX_PREFIX = 'http://hifi-content.s3-us-west-1.amazonaws.com/caitlyn/production/elBoppo/sfx/'; + var CLOWN_LAUGHS = [ + 'clown_laugh_1.wav', + 'clown_laugh_2.wav', + 'clown_laugh_3.wav', + 'clown_laugh_4.wav' + ]; + var TICK_TOCK_SOUND = 'ticktock%20-%20tock.wav'; + var BOXING_RING_BELL_START = 'boxingRingBell.wav'; + var BOXING_RING_BELL_END = 'boxingRingBell-end.wav'; + var BOPPO_MUSIC = 'boppoMusic.wav'; + var CHANNEL_PREFIX = 'io.highfidelity.boppo_server_'; + var MESSAGE_HIT = 'hit'; + var MESSAGE_ENTER_ZONE = 'enter-zone'; + var MESSAGE_UNLOAD_FIX = 'unload-fix'; + // don't set the search radius too high, it might remove boppo's from other nearby instances + var BOPPO_SEARCH_RADIUS = 4.0; + + var MILLISECONDS_PER_SECOND = 1000; + // Make sure the entities are loaded at startup (TODO: more solid fix) + var LOAD_TIMEOUT = 5000; + var SECONDS_PER_MINUTE = 60; + var DEFAULT_PLAYTIME = 30; // seconds + var BASE_TEN = 10; + var TICK_TOCK_FROM = 3; // seconds + var COOLDOWN_TIME_MS = MILLISECONDS_PER_SECOND * 3; + + BoppoServer = function() { + var _this, + _isInitialized = false, + _clownLaughs = [], + _musicInjector, + _music, + _laughingInjector, + _tickTockSound, + _boxingBellRingStart, + _boxingBellRingEnd, + _entityID, + _boppoClownID, + _channel, + _boppoEntities, + _isGameRunning, + _updateInterval, + _timeLeft, + _hits, + _coolDown; + + var getOwnBoppoUserData = function() { + try { + return JSON.parse(Entities.getEntityProperties(_entityID, ['userData']).userData).Boppo; + } catch (e) { + // e + } + return {}; + }; + + var updateBoppoEntities = function() { + Entities.getChildrenIDs(_entityID).forEach(function(entityID) { + try { + var userData = JSON.parse(Entities.getEntityProperties(entityID, ['userData']).userData); + if (userData.Boppo.type !== undefined) { + _boppoEntities[userData.Boppo.type] = entityID; + } + } catch (e) { + // e + } + }); + }; + + var clearUntrackedBoppos = function() { + var position = Entities.getEntityProperties(_entityID, ['position']).position; + Entities.findEntities(position, BOPPO_SEARCH_RADIUS).forEach(function(entityID) { + try { + if (JSON.parse(Entities.getEntityProperties(entityID, ['userData']).userData).Boppo.type === 'boppo') { + Entities.deleteEntity(entityID); + } + } catch (e) { + // e + } + }); + }; + + var updateTimerDisplay = function() { + if (_boppoEntities['timer']) { + var secondsString = _timeLeft % SECONDS_PER_MINUTE; + if (secondsString < BASE_TEN) { + secondsString = '0' + secondsString; + } + var minutesString = Math.floor(_timeLeft / SECONDS_PER_MINUTE); + Entities.editEntity(_boppoEntities['timer'], { + text: minutesString + ':' + secondsString + }); + } + }; + + var updateScoreDisplay = function() { + if (_boppoEntities['score']) { + Entities.editEntity(_boppoEntities['score'], { + text: 'SCORE: ' + _hits + }); + } + }; + + var playSoundAtBoxingRing = function(sound, properties) { + var _properties = properties ? properties : {}; + _properties['position'] = Entities.getEntityProperties(_entityID, ['position']).position; + // play beep + return Audio.playSound(sound, _properties); + }; + + var onUpdate = function() { + _timeLeft--; + + if (_timeLeft > 0 && _timeLeft <= TICK_TOCK_FROM) { + // play beep + playSoundAtBoxingRing(_tickTockSound); + } + if (_timeLeft === 0) { + if (_musicInjector !== undefined && _musicInjector.isPlaying()) { + _musicInjector.stop(); + _musicInjector = undefined; + } + playSoundAtBoxingRing(_boxingBellRingEnd); + _isGameRunning = false; + Script.clearInterval(_updateInterval); + _updateInterval = null; + _coolDown = true; + Script.setTimeout(function() { + _coolDown = false; + _this.resetBoppo(); + }, COOLDOWN_TIME_MS); + } + updateTimerDisplay(); + }; + + var onMessage = function(channel, message, sender) { + if (channel === _channel) { + if (message === MESSAGE_HIT) { + _this.hit(); + } else if (message === MESSAGE_ENTER_ZONE && !_isGameRunning) { + _this.resetBoppo(); + } else if (message === MESSAGE_UNLOAD_FIX && _isInitialized) { + _this.unload(); + } + } + }; + + BoppoServer = function () { + _this = this; + _hits = 0; + _boppoClownID = null; + _coolDown = false; + CLOWN_LAUGHS.forEach(function(clownLaugh) { + _clownLaughs.push(SoundCache.getSound(SFX_PREFIX + clownLaugh)); + }); + _tickTockSound = SoundCache.getSound(SFX_PREFIX + TICK_TOCK_SOUND); + _boxingBellRingStart = SoundCache.getSound(SFX_PREFIX + BOXING_RING_BELL_START); + _boxingBellRingEnd = SoundCache.getSound(SFX_PREFIX + BOXING_RING_BELL_END); + _music = SoundCache.getSound(SFX_PREFIX + BOPPO_MUSIC); + _boppoEntities = {}; + }; + + BoppoServer.prototype = { + preload: function(entityID) { + _entityID = entityID; + _channel = CHANNEL_PREFIX + entityID; + + Messages.sendLocalMessage(_channel, MESSAGE_UNLOAD_FIX); + Script.setTimeout(function() { + clearUntrackedBoppos(); + updateBoppoEntities(); + Messages.subscribe(_channel); + Messages.messageReceived.connect(onMessage); + _this.resetBoppo(); + _isInitialized = true; + }, LOAD_TIMEOUT); + }, + resetBoppo: function() { + if (_boppoClownID !== null) { + print('deleting boppo: ' + _boppoClownID); + Entities.deleteEntity(_boppoClownID); + } + var boppoBaseProperties = Entities.getEntityProperties(_entityID, ['position', 'rotation']); + _boppoClownID = Entities.addEntity({ + angularDamping: 0.0, + collisionSoundURL: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/51460__andre-rocha-nascimento__basket-ball-01-bounce.wav', + collisionsWillMove: true, + compoundShapeURL: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/bopo_phys.obj', + damping: 1.0, + density: 10000, + dimensions: { + x: 1.2668079137802124, + y: 2.0568051338195801, + z: 0.88563752174377441 + }, + dynamic: 1.0, + friction: 1.0, + gravity: { + x: 0, + y: -25, + z: 0 + }, + modelURL: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/elBoppo3_VR.fbx', + name: 'El Boppo the Punching Bag Clown', + registrationPoint: { + x: 0.5, + y: 0, + z: 0.3 + }, + restitution: 0.99, + rotation: boppoBaseProperties.rotation, + position: Vec3.sum(boppoBaseProperties.position, + Vec3.multiplyQbyV(boppoBaseProperties.rotation, { + x: 0.08666179329156876, + y: -1.5698202848434448, + z: 0.1847127377986908 + })), + script: Script.resolvePath('boppoClownEntity.js'), + shapeType: 'compound', + type: 'Model', + userData: JSON.stringify({ + lookAt: { + targetID: _boppoEntities['lookAtThis'], + disablePitch: true, + disableYaw: false, + disableRoll: true, + clearDisabledAxis: true, + rotationOffset: { x: 0.0, y: 180.0, z: 0.0} + }, + Boppo: { + type: 'boppo', + gameParentID: _entityID + }, + grabbableKey: { + grabbable: false + } + }) + }); + updateBoppoEntities(); + _boppoEntities['boppo'] = _boppoClownID; + }, + laugh: function() { + if (_laughingInjector !== undefined && _laughingInjector.isPlaying()) { + return; + } + var randomLaughIndex = Math.floor(Math.random() * _clownLaughs.length); + _laughingInjector = Audio.playSound(_clownLaughs[randomLaughIndex], { + position: Entities.getEntityProperties(_boppoClownID, ['position']).position + }); + }, + hit: function() { + if (_coolDown) { + return; + } + if (!_isGameRunning) { + var boxingRingBoppoData = getOwnBoppoUserData(); + _updateInterval = Script.setInterval(onUpdate, MILLISECONDS_PER_SECOND); + _timeLeft = boxingRingBoppoData.playTimeSeconds ? parseInt(boxingRingBoppoData.playTimeSeconds) : + DEFAULT_PLAYTIME; + _isGameRunning = true; + _hits = 0; + playSoundAtBoxingRing(_boxingBellRingStart); + _musicInjector = playSoundAtBoxingRing(_music, {loop: true, volume: 0.6}); + } + _hits++; + updateTimerDisplay(); + updateScoreDisplay(); + _this.laugh(); + }, + unload: function() { + print('unload called'); + if (_updateInterval) { + Script.clearInterval(_updateInterval); + } + Messages.messageReceived.connect(onMessage); + Messages.unsubscribe(_channel); + Entities.deleteEntity(_boppoClownID); + print('endOfUnload'); + } + }; + + return new BoppoServer(); + }; + + return new BoppoServer(); +}); diff --git a/unpublishedScripts/marketplace/boppo/clownGloveDispenser.js b/unpublishedScripts/marketplace/boppo/clownGloveDispenser.js new file mode 100644 index 0000000000..42675d609a --- /dev/null +++ b/unpublishedScripts/marketplace/boppo/clownGloveDispenser.js @@ -0,0 +1,154 @@ +// +// clownGloveDispenser.js +// +// Created by Thijs Wenker on 8/2/16. +// Copyright 2016 High Fidelity, Inc. +// +// Based on examples/winterSmashUp/targetPractice/shooterPlatform.js +// +// 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 _this = this; + + var CHANNEL_PREFIX = 'io.highfidelity.boppo_server_'; + + var leftBoxingGlove = undefined; + var rightBoxingGlove = undefined; + + var inZone = false; + + var wearGloves = function() { + leftBoxingGlove = Entities.addEntity({ + position: MyAvatar.position, + collisionsWillMove: true, + dimensions: { + x: 0.24890634417533875, + y: 0.28214839100837708, + z: 0.21127720177173615 + }, + dynamic: true, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + modelURL: "http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/LFT_glove_VR3.fbx", + name: "Boxing Glove - Left", + registrationPoint: { + x: 0.5, + y: 0, + z: 0.5 + }, + shapeType: "simple-hull", + type: "Model", + userData: JSON.stringify({ + grabbableKey: { + invertSolidWhileHeld: true + }, + wearable: { + joints: { + LeftHand: [ + {x: 0, y: 0.0, z: 0.02 }, + Quat.fromVec3Degrees({x: 0, y: 0, z: 0}) + ] + } + } + }) + }); + Messages.sendLocalMessage('Hifi-Hand-Grab', JSON.stringify({hand: 'left', entityID: leftBoxingGlove})); + // Allows teleporting while glove is wielded + Messages.sendLocalMessage('Hifi-Teleport-Ignore-Add', leftBoxingGlove); + + rightBoxingGlove = Entities.addEntity({ + position: MyAvatar.position, + collisionsWillMove: true, + dimensions: { + x: 0.24890634417533875, + y: 0.28214839100837708, + z: 0.21127720177173615 + }, + dynamic: true, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + modelURL: "http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/RT_glove_VR2.fbx", + name: "Boxing Glove - Right", + registrationPoint: { + x: 0.5, + y: 0, + z: 0.5 + }, + shapeType: "simple-hull", + type: "Model", + userData: JSON.stringify({ + grabbableKey: { + invertSolidWhileHeld: true + }, + wearable: { + joints: { + RightHand: [ + {x: 0, y: 0.0, z: 0.02 }, + Quat.fromVec3Degrees({x: 0, y: 0, z: 0}) + ] + } + } + }) + }); + Messages.sendLocalMessage('Hifi-Hand-Grab', JSON.stringify({hand: 'right', entityID: rightBoxingGlove})); + // Allows teleporting while glove is wielded + Messages.sendLocalMessage('Hifi-Teleport-Ignore-Add', rightBoxingGlove); + }; + + var cleanUpGloves = function() { + if (leftBoxingGlove !== undefined) { + Entities.deleteEntity(leftBoxingGlove); + leftBoxingGlove = undefined; + } + if (rightBoxingGlove !== undefined) { + Entities.deleteEntity(rightBoxingGlove); + rightBoxingGlove = undefined; + } + }; + + var wearGlovesIfHMD = function() { + // cleanup your old gloves if they're still there (unlikely) + cleanUpGloves(); + if (HMD.active) { + wearGloves(); + } + }; + + _this.preload = function(entityID) { + HMD.displayModeChanged.connect(function() { + if (inZone) { + wearGlovesIfHMD(); + } + }); + }; + + _this.unload = function() { + cleanUpGloves(); + }; + + _this.enterEntity = function(entityID) { + inZone = true; + print('entered boxing glove dispenser entity'); + wearGlovesIfHMD(); + + // Reset boppo if game is not running: + var parentID = Entities.getEntityProperties(entityID, ['parentID']).parentID; + Messages.sendMessage(CHANNEL_PREFIX + parentID, 'enter-zone'); + }; + + _this.leaveEntity = function(entityID) { + inZone = false; + cleanUpGloves(); + }; + + _this.unload = _this.leaveEntity; +}); diff --git a/unpublishedScripts/marketplace/boppo/createElBoppo.js b/unpublishedScripts/marketplace/boppo/createElBoppo.js new file mode 100644 index 0000000000..6bef9bc0fd --- /dev/null +++ b/unpublishedScripts/marketplace/boppo/createElBoppo.js @@ -0,0 +1,426 @@ +// +// createElBoppo.js +// +// Created by Thijs Wenker on 3/17/17. +// Copyright 2017 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 +// + +/* globals SCRIPT_IMPORT_PROPERTIES */ + +var MODELS_PATH = 'http://hifi-content.s3.amazonaws.com/DomainContent/Welcome%20Area/production/models/boxingRing/'; +var SCRIPT_PATH = this.isCleanupAndSpawnScript ? + 'http://s3-us-west-1.amazonaws.com/hifi-content/thoys/dev/2017/elBoppo/' : + Script.resolvePath(''); +var WANT_CLEANUP_ON_SCRIPT_ENDING = false; + +var getCreatePosition = function() { + // can either return position defined by resetScript or avatar position + if (this.isCleanupAndSpawnScript) { + return SCRIPT_IMPORT_PROPERTIES.rootPosition; + } + return Vec3.sum(MyAvatar.position, {x: 1, z: -2}); +}; + +var boxingRing = Entities.addEntity({ + dimensions: { + x: 4.0584001541137695, + y: 4.0418000221252441, + z: 3.0490000247955322 + }, + modelURL: MODELS_PATH + 'assembled/boppoBoxingRingAssembly.fbx', + name: 'Boxing Ring Assembly', + rotation: { + w: 0.9996337890625, + x: -1.52587890625e-05, + y: -0.026230275630950928, + z: -4.57763671875e-05 + }, + position: getCreatePosition(), + scriptTimestamp: 1489612158459, + serverScripts: SCRIPT_PATH + 'boppoServer.js', + shapeType: 'static-mesh', + type: 'Model', + userData: JSON.stringify({ + Boppo: { + type: 'boxingring', + playTimeSeconds: 15 + } + }) +}); + +var boppoEntities = [ + { + dimensions: { + x: 0.36947935819625854, + y: 0.25536194443702698, + z: 0.059455446898937225 + }, + modelURL: MODELS_PATH + 'boxingGameSign/boppoSignFrame.fbx', + parentID: boxingRing, + localPosition: { + x: -1.0251024961471558, + y: 0.51661628484725952, + z: -1.1176263093948364 + }, + rotation: { + w: 0.996856689453125, + x: 0.013321161270141602, + y: 0.0024566650390625, + z: 0.078049898147583008 + }, + shapeType: 'box', + type: 'Model' + }, + { + dimensions: { + x: 0.33255371451377869, + y: 0.1812121719121933, + z: 0.0099999997764825821 + }, + lineHeight: 0.125, + name: 'Boxing Ring - High Score Board', + parentID: boxingRing, + localPosition: { + x: -1.0239436626434326, + y: 0.52212876081466675, + z: -1.0971509218215942 + }, + rotation: { + w: 0.9876401424407959, + x: 0.013046503067016602, + y: 0.0012359619140625, + z: 0.15605401992797852 + }, + text: '0:00', + textColor: { + blue: 0, + green: 0, + red: 255 + }, + type: 'Text', + userData: JSON.stringify({ + Boppo: { + type: 'timer' + } + }) + }, + { + dimensions: { + x: 0.50491130352020264, + y: 0.13274604082107544, + z: 0.0099999997764825821 + }, + lineHeight: 0.090000003576278687, + name: 'Boxing Ring - Score Board', + parentID: boxingRing, + localPosition: { + x: -0.77596306800842285, + y: 0.37797555327415466, + z: -1.0910623073577881 + }, + rotation: { + w: 0.9518122673034668, + x: 0.004237703513354063, + y: -0.0010041374480351806, + z: 0.30455198884010315 + }, + text: 'SCORE: 0', + textColor: { + blue: 0, + green: 0, + red: 255 + }, + type: 'Text', + userData: JSON.stringify({ + Boppo: { + type: 'score' + } + }) + }, + { + dimensions: { + x: 0.58153259754180908, + y: 0.1884911060333252, + z: 0.059455446898937225 + }, + modelURL: MODELS_PATH + 'boxingGameSign/boppoSignFrame.fbx', + parentID: boxingRing, + localPosition: { + x: -0.78200173377990723, + y: 0.35684797167778015, + z: -1.108180046081543 + }, + rotation: { + w: 0.97814905643463135, + x: 0.0040436983108520508, + y: -0.0005645751953125, + z: 0.20778214931488037 + }, + shapeType: 'box', + type: 'Model' + }, + { + dimensions: { + x: 4.1867804527282715, + y: 3.5065803527832031, + z: 5.6845207214355469 + }, + name: 'El Boppo the Clown boxing area & glove maker', + parentID: boxingRing, + localPosition: { + x: -0.012308252975344658, + y: 0.054641719907522202, + z: 0.98782551288604736 + }, + rotation: { + w: 1, + x: -1.52587890625e-05, + y: -1.52587890625e-05, + z: -1.52587890625e-05 + }, + script: SCRIPT_PATH + 'clownGloveDispenser.js', + shapeType: 'box', + type: 'Zone', + visible: false + }, + { + color: { + blue: 255, + green: 5, + red: 255 + }, + dimensions: { + x: 0.20000000298023224, + y: 0.20000000298023224, + z: 0.20000000298023224 + }, + name: 'LookAtBox', + parentID: boxingRing, + localPosition: { + x: -0.1772226095199585, + y: -1.7072629928588867, + z: 1.3122396469116211 + }, + rotation: { + w: 0.999969482421875, + x: 1.52587890625e-05, + y: 0.0043793916702270508, + z: 1.52587890625e-05 + }, + shape: 'Cube', + type: 'Box', + userData: JSON.stringify({ + Boppo: { + type: 'lookAtThis' + } + }) + }, + { + color: { + blue: 209, + green: 157, + red: 209 + }, + dimensions: { + x: 1.6913000345230103, + y: 1.2124500274658203, + z: 0.2572999894618988 + }, + name: 'boppoBackBoard', + parentID: boxingRing, + localPosition: { + x: -0.19500596821308136, + y: -1.1044719219207764, + z: -0.55993378162384033 + }, + rotation: { + w: 0.9807126522064209, + x: -0.19511711597442627, + y: 0.0085297822952270508, + z: 0.0016937255859375 + }, + shape: 'Cube', + type: 'Box', + visible: false + }, + { + color: { + blue: 0, + green: 0, + red: 255 + }, + dimensions: { + x: 1.8155574798583984, + y: 0.92306196689605713, + z: 0.51203572750091553 + }, + name: 'boppoBackBoard', + parentID: boxingRing, + localPosition: { + x: -0.11036647111177444, + y: -0.051978692412376404, + z: -0.79054081439971924 + }, + rotation: { + w: 0.9807431697845459, + x: 0.19505608081817627, + y: 0.0085602998733520508, + z: -0.0017547607421875 + }, + shape: 'Cube', + type: 'Box', + visible: false + }, + { + color: { + blue: 209, + green: 157, + red: 209 + }, + dimensions: { + x: 1.9941408634185791, + y: 1.2124500274658203, + z: 0.2572999894618988 + }, + name: 'boppoBackBoard', + localPosition: { + x: 0.69560068845748901, + y: -1.3840068578720093, + z: 0.059689953923225403 + }, + rotation: { + w: 0.73458456993103027, + x: -0.24113833904266357, + y: -0.56545358896255493, + z: -0.28734266757965088 + }, + shape: 'Cube', + type: 'Box', + visible: false + }, + { + color: { + blue: 82, + green: 82, + red: 82 + }, + dimensions: { + x: 8.3777303695678711, + y: 0.87573593854904175, + z: 7.9759469032287598 + }, + parentID: boxingRing, + localPosition: { + x: -0.38302639126777649, + y: -2.121284008026123, + z: 0.3699878454208374 + }, + rotation: { + w: 0.70711839199066162, + x: -7.62939453125e-05, + y: 0.70705735683441162, + z: -1.52587890625e-05 + }, + shape: 'Triangle', + type: 'Shape' + }, + { + color: { + blue: 209, + green: 157, + red: 209 + }, + dimensions: { + x: 1.889795184135437, + y: 0.86068248748779297, + z: 0.2572999894618988 + }, + name: 'boppoBackBoard', + parentID: boxingRing, + localPosition: { + x: -0.95167744159698486, + y: -1.4756947755813599, + z: -0.042313352227210999 + }, + rotation: { + w: 0.74004733562469482, + x: -0.24461740255355835, + y: 0.56044864654541016, + z: 0.27998781204223633 + }, + shape: 'Cube', + type: 'Box', + visible: false + }, + { + color: { + blue: 0, + green: 0, + red: 255 + }, + dimensions: { + x: 4.0720257759094238, + y: 0.50657749176025391, + z: 1.4769613742828369 + }, + name: 'boppo-stepsRamp', + parentID: boxingRing, + localPosition: { + x: -0.002939039608463645, + y: -1.9770187139511108, + z: 2.2165381908416748 + }, + rotation: { + w: 0.99252307415008545, + x: 0.12184333801269531, + y: -1.52587890625e-05, + z: -1.52587890625e-05 + }, + shape: 'Cube', + type: 'Box', + visible: false + }, + { + color: { + blue: 150, + green: 150, + red: 150 + }, + cutoff: 90, + dimensions: { + x: 5.2220535278320312, + y: 5.2220535278320312, + z: 5.2220535278320312 + }, + falloffRadius: 2, + intensity: 15, + name: 'boxing ring light', + parentID: boxingRing, + localPosition: { + x: -1.4094564914703369, + y: -0.36021926999092102, + z: 0.81797939538955688 + }, + rotation: { + w: 0.9807431697845459, + x: 1.52587890625e-05, + y: -0.19520866870880127, + z: -1.52587890625e-05 + }, + type: 'Light' + } +]; + +boppoEntities.forEach(function(entityProperties) { + entityProperties['parentID'] = boxingRing; + Entities.addEntity(entityProperties); +}); + +if (WANT_CLEANUP_ON_SCRIPT_ENDING) { + Script.scriptEnding.connect(function() { + Entities.deleteEntity(boxingRing); + }); +} diff --git a/unpublishedScripts/marketplace/boppo/lookAtEntity.js b/unpublishedScripts/marketplace/boppo/lookAtEntity.js new file mode 100644 index 0000000000..ba072814f2 --- /dev/null +++ b/unpublishedScripts/marketplace/boppo/lookAtEntity.js @@ -0,0 +1,98 @@ +// +// lookAtTarget.js +// +// Created by Thijs Wenker on 3/15/17. +// Copyright 2017 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 +// + +/* globals LookAtTarget:true */ + +LookAtTarget = function(sourceEntityID) { + /* private variables */ + var _this, + _options, + _sourceEntityID, + _sourceEntityProperties, + REQUIRED_PROPERTIES = ['position', 'rotation', 'userData'], + LOOK_AT_TAG = 'lookAtTarget'; + + LookAtTarget = function(sourceEntityID) { + _this = this; + _sourceEntityID = sourceEntityID; + _this.updateOptions(); + }; + + /* private functions */ + var updateEntitySourceProperties = function() { + _sourceEntityProperties = Entities.getEntityProperties(_sourceEntityID, REQUIRED_PROPERTIES); + }; + + var getUpdatedActionProperties = function() { + return { + targetRotation: _this.getLookAtRotation(), + angularTimeScale: 0.1, + ttl: 10 + }; + }; + + var getNewActionProperties = function() { + var newActionProperties = getUpdatedActionProperties(); + newActionProperties.tag = LOOK_AT_TAG; + return newActionProperties; + }; + + LookAtTarget.prototype = { + /* public functions */ + updateOptions: function() { + updateEntitySourceProperties(); + _options = JSON.parse(_sourceEntityProperties.userData).lookAt; + }, + getTargetPosition: function() { + return Entities.getEntityProperties(_options.targetID).position; + }, + getLookAtRotation: function() { + _this.updateOptions(); + + var newRotation = Quat.lookAt(_sourceEntityProperties.position, _this.getTargetPosition(), Vec3.UP); + if (_options.rotationOffset !== undefined) { + newRotation = Quat.multiply(newRotation, Quat.fromVec3Degrees(_options.rotationOffset)); + } + if (_options.disablePitch || _options.disableYaw || _options.disablePitch) { + var disabledAxis = _options.clearDisabledAxis ? Vec3.ZERO : + Quat.safeEulerAngles(_sourceEntityProperties.rotation); + var newEulers = Quat.safeEulerAngles(newRotation); + newRotation = Quat.fromVec3Degrees({ + x: _options.disablePitch ? disabledAxis.x : newEulers.x, + y: _options.disableYaw ? disabledAxis.y : newEulers.y, + z: _options.disableRoll ? disabledAxis.z : newEulers.z + }); + } + return newRotation; + }, + lookAtDirectly: function() { + Entities.editEntity(_sourceEntityID, {rotation: _this.getLookAtRotation()}); + }, + lookAtByAction: function() { + var actionIDs = Entities.getActionIDs(_sourceEntityID); + var actionFound = false; + actionIDs.forEach(function(actionID) { + if (actionFound) { + return; + } + var actionArguments = Entities.getActionArguments(_sourceEntityID, actionID); + if (actionArguments.tag === LOOK_AT_TAG) { + actionFound = true; + Entities.updateAction(_sourceEntityID, actionID, getUpdatedActionProperties()); + } + }); + if (!actionFound) { + Entities.addAction('spring', _sourceEntityID, getNewActionProperties()); + } + } + }; + + return new LookAtTarget(sourceEntityID); +}; From febe25511b12fc1830448a3cca1790653bdf7a86 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 17 Mar 2017 21:10:06 +0100 Subject: [PATCH 12/23] teleport.js - ignore entity support (for boxing gloves) --- scripts/system/controllers/teleport.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index c058f046db..e56562a18a 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -85,6 +85,7 @@ function Trigger(hand) { } var coolInTimeout = null; +var ignoredEntities = []; var TELEPORTER_STATES = { IDLE: 'idle', @@ -239,11 +240,11 @@ function Teleporter() { // We might hit an invisible entity that is not a seat, so we need to do a second pass. // * In the second pass we pick against visible entities only. // - var intersection = Entities.findRayIntersection(pickRay, true, [], [this.targetEntity], false, true); + var intersection = Entities.findRayIntersection(pickRay, true, ignoredEntities, [this.targetEntity], false, true); var teleportLocationType = getTeleportTargetType(intersection); if (teleportLocationType === TARGET.INVISIBLE) { - intersection = Entities.findRayIntersection(pickRay, true, [], [this.targetEntity], true, true); + intersection = Entities.findRayIntersection(pickRay, true, ignoredEntities, [this.targetEntity], true, true); teleportLocationType = getTeleportTargetType(intersection); } @@ -513,7 +514,7 @@ function cleanup() { Script.scriptEnding.connect(cleanup); var isDisabled = false; -var handleHandMessages = function(channel, message, sender) { +var handleTeleportMessages = function(channel, message, sender) { var data; if (sender === MyAvatar.sessionUUID) { if (channel === 'Hifi-Teleport-Disabler') { @@ -529,12 +530,20 @@ var handleHandMessages = function(channel, message, sender) { if (message === 'none') { isDisabled = false; } - + } else if (channel === 'Hifi-Teleport-Ignore-Add' && !Uuid.isNull(message) && ignoredEntities.indexOf(message) === -1) { + ignoredEntities.push(message); + } else if (channel === 'Hifi-Teleport-Ignore-Remove' && !Uuid.isNull(message)) { + var removeIndex = ignoredEntities.indexOf(message); + if (removeIndex > -1) { + ignoredEntities.splice(removeIndex, 1); + } } } } Messages.subscribe('Hifi-Teleport-Disabler'); -Messages.messageReceived.connect(handleHandMessages); +Messages.subscribe('Hifi-Teleport-Ignore-Add'); +Messages.subscribe('Hifi-Teleport-Ignore-Remove'); +Messages.messageReceived.connect(handleTeleportMessages); }()); // END LOCAL_SCOPE From bdabc21d57a65a218961fa42c050da147c79b3e2 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 18 Mar 2017 00:12:13 +0100 Subject: [PATCH 13/23] fix path issue --- .../marketplace/boppo/createElBoppo.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/unpublishedScripts/marketplace/boppo/createElBoppo.js b/unpublishedScripts/marketplace/boppo/createElBoppo.js index 6bef9bc0fd..362527e5f5 100644 --- a/unpublishedScripts/marketplace/boppo/createElBoppo.js +++ b/unpublishedScripts/marketplace/boppo/createElBoppo.js @@ -11,11 +11,15 @@ /* globals SCRIPT_IMPORT_PROPERTIES */ var MODELS_PATH = 'http://hifi-content.s3.amazonaws.com/DomainContent/Welcome%20Area/production/models/boxingRing/'; -var SCRIPT_PATH = this.isCleanupAndSpawnScript ? - 'http://s3-us-west-1.amazonaws.com/hifi-content/thoys/dev/2017/elBoppo/' : - Script.resolvePath(''); var WANT_CLEANUP_ON_SCRIPT_ENDING = false; +var getScriptPath = function(localPath) { + if (this.isCleanupAndSpawnScript) { + return 'http://s3-us-west-1.amazonaws.com/hifi-content/thoys/dev/2017/elBoppo/' + localPath; + } + return Script.resolvePath(localPath); +}; + var getCreatePosition = function() { // can either return position defined by resetScript or avatar position if (this.isCleanupAndSpawnScript) { @@ -40,7 +44,7 @@ var boxingRing = Entities.addEntity({ }, position: getCreatePosition(), scriptTimestamp: 1489612158459, - serverScripts: SCRIPT_PATH + 'boppoServer.js', + serverScripts: getScriptPath('boppoServer.js'), shapeType: 'static-mesh', type: 'Model', userData: JSON.stringify({ @@ -181,7 +185,7 @@ var boppoEntities = [ y: -1.52587890625e-05, z: -1.52587890625e-05 }, - script: SCRIPT_PATH + 'clownGloveDispenser.js', + script: getScriptPath('clownGloveDispenser.js'), shapeType: 'box', type: 'Zone', visible: false From 535d4f5deaa8fa24ca43f03e85536641004018e1 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 18 Mar 2017 00:57:50 +0100 Subject: [PATCH 14/23] fixup links --- unpublishedScripts/marketplace/boppo/boppoClownEntity.js | 2 +- unpublishedScripts/marketplace/boppo/boppoServer.js | 8 ++++---- .../marketplace/boppo/clownGloveDispenser.js | 4 ++-- unpublishedScripts/marketplace/boppo/createElBoppo.js | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/unpublishedScripts/marketplace/boppo/boppoClownEntity.js b/unpublishedScripts/marketplace/boppo/boppoClownEntity.js index ef01e47f6f..cf0e157a18 100644 --- a/unpublishedScripts/marketplace/boppo/boppoClownEntity.js +++ b/unpublishedScripts/marketplace/boppo/boppoClownEntity.js @@ -11,7 +11,7 @@ /* globals BoppoClownEntity:true LookAtTarget */ (function() { - var SFX_PREFIX = 'http://hifi-content.s3-us-west-1.amazonaws.com/caitlyn/production/elBoppo/sfx/'; + var SFX_PREFIX = 'https://hifi-content.s3-us-west-1.amazonaws.com/caitlyn/production/elBoppo/sfx/'; var CHANNEL_PREFIX = 'io.highfidelity.boppo_server_'; var PUNCH_SOUNDS = [ 'punch_1.wav', diff --git a/unpublishedScripts/marketplace/boppo/boppoServer.js b/unpublishedScripts/marketplace/boppo/boppoServer.js index ebe938c043..1abc5a135c 100644 --- a/unpublishedScripts/marketplace/boppo/boppoServer.js +++ b/unpublishedScripts/marketplace/boppo/boppoServer.js @@ -11,7 +11,7 @@ /* globals BoppoServer:true */ (function() { - var SFX_PREFIX = 'http://hifi-content.s3-us-west-1.amazonaws.com/caitlyn/production/elBoppo/sfx/'; + var SFX_PREFIX = 'https://hifi-content.s3-us-west-1.amazonaws.com/caitlyn/production/elBoppo/sfx/'; var CLOWN_LAUGHS = [ 'clown_laugh_1.wav', 'clown_laugh_2.wav', @@ -196,9 +196,9 @@ var boppoBaseProperties = Entities.getEntityProperties(_entityID, ['position', 'rotation']); _boppoClownID = Entities.addEntity({ angularDamping: 0.0, - collisionSoundURL: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/51460__andre-rocha-nascimento__basket-ball-01-bounce.wav', + collisionSoundURL: 'https://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/51460__andre-rocha-nascimento__basket-ball-01-bounce.wav', collisionsWillMove: true, - compoundShapeURL: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/bopo_phys.obj', + compoundShapeURL: 'https://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/bopo_phys.obj', damping: 1.0, density: 10000, dimensions: { @@ -213,7 +213,7 @@ y: -25, z: 0 }, - modelURL: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/elBoppo3_VR.fbx', + modelURL: 'https://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/elBoppo3_VR.fbx', name: 'El Boppo the Punching Bag Clown', registrationPoint: { x: 0.5, diff --git a/unpublishedScripts/marketplace/boppo/clownGloveDispenser.js b/unpublishedScripts/marketplace/boppo/clownGloveDispenser.js index 42675d609a..cd0a0c0614 100644 --- a/unpublishedScripts/marketplace/boppo/clownGloveDispenser.js +++ b/unpublishedScripts/marketplace/boppo/clownGloveDispenser.js @@ -35,7 +35,7 @@ y: -9.8, z: 0 }, - modelURL: "http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/LFT_glove_VR3.fbx", + modelURL: "https://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/LFT_glove_VR3.fbx", name: "Boxing Glove - Left", registrationPoint: { x: 0.5, @@ -76,7 +76,7 @@ y: -9.8, z: 0 }, - modelURL: "http://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/RT_glove_VR2.fbx", + modelURL: "https://hifi-content.s3.amazonaws.com/caitlyn/production/elBoppo/RT_glove_VR2.fbx", name: "Boxing Glove - Right", registrationPoint: { x: 0.5, diff --git a/unpublishedScripts/marketplace/boppo/createElBoppo.js b/unpublishedScripts/marketplace/boppo/createElBoppo.js index 362527e5f5..4df6a2acda 100644 --- a/unpublishedScripts/marketplace/boppo/createElBoppo.js +++ b/unpublishedScripts/marketplace/boppo/createElBoppo.js @@ -10,12 +10,12 @@ /* globals SCRIPT_IMPORT_PROPERTIES */ -var MODELS_PATH = 'http://hifi-content.s3.amazonaws.com/DomainContent/Welcome%20Area/production/models/boxingRing/'; +var MODELS_PATH = 'https://hifi-content.s3.amazonaws.com/DomainContent/Welcome%20Area/production/models/boxingRing/'; var WANT_CLEANUP_ON_SCRIPT_ENDING = false; var getScriptPath = function(localPath) { if (this.isCleanupAndSpawnScript) { - return 'http://s3-us-west-1.amazonaws.com/hifi-content/thoys/dev/2017/elBoppo/' + localPath; + return 'https://hifi-content.s3.amazonaws.com/DomainContent/Welcome%20Area/Scripts/boppo/' + localPath; } return Script.resolvePath(localPath); }; From a8740614e23db29b5e6c7a67ea18e0e9c8533e6e Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 18 Mar 2017 01:22:06 +0100 Subject: [PATCH 15/23] CR Fixes --- scripts/system/controllers/teleport.js | 4 ++-- unpublishedScripts/marketplace/boppo/boppoClownEntity.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index e56562a18a..1c6c9af272 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -240,11 +240,11 @@ function Teleporter() { // We might hit an invisible entity that is not a seat, so we need to do a second pass. // * In the second pass we pick against visible entities only. // - var intersection = Entities.findRayIntersection(pickRay, true, ignoredEntities, [this.targetEntity], false, true); + var intersection = Entities.findRayIntersection(pickRay, true, [], [this.targetEntity].concat(ignoredEntities), false, true); var teleportLocationType = getTeleportTargetType(intersection); if (teleportLocationType === TARGET.INVISIBLE) { - intersection = Entities.findRayIntersection(pickRay, true, ignoredEntities, [this.targetEntity], true, true); + intersection = Entities.findRayIntersection(pickRay, true, [], [this.targetEntity].concat(ignoredEntities), true, true); teleportLocationType = getTeleportTargetType(intersection); } diff --git a/unpublishedScripts/marketplace/boppo/boppoClownEntity.js b/unpublishedScripts/marketplace/boppo/boppoClownEntity.js index cf0e157a18..2fa4441e52 100644 --- a/unpublishedScripts/marketplace/boppo/boppoClownEntity.js +++ b/unpublishedScripts/marketplace/boppo/boppoClownEntity.js @@ -19,7 +19,7 @@ ]; var PUNCH_COOLDOWN = 300; - Script.include(Script.resolvePath('lookAtEntity.js?v2')); + Script.include('lookAtEntity.js'); BoppoClownEntity = function() { var _this, From b60534a85567cb61b32dfce5f9b52595586acd38 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sun, 19 Mar 2017 14:00:56 +0100 Subject: [PATCH 16/23] - fix for multiple boppo's appearing after ESS restart (disconnect from message event instead of connect) - default volume for sounds coming from ESS --- unpublishedScripts/marketplace/boppo/boppoServer.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/unpublishedScripts/marketplace/boppo/boppoServer.js b/unpublishedScripts/marketplace/boppo/boppoServer.js index 1abc5a135c..28690c0a00 100644 --- a/unpublishedScripts/marketplace/boppo/boppoServer.js +++ b/unpublishedScripts/marketplace/boppo/boppoServer.js @@ -26,6 +26,9 @@ var MESSAGE_HIT = 'hit'; var MESSAGE_ENTER_ZONE = 'enter-zone'; var MESSAGE_UNLOAD_FIX = 'unload-fix'; + + var DEFAULT_SOUND_VOLUME = 0.6; + // don't set the search radius too high, it might remove boppo's from other nearby instances var BOPPO_SEARCH_RADIUS = 4.0; @@ -116,6 +119,9 @@ var playSoundAtBoxingRing = function(sound, properties) { var _properties = properties ? properties : {}; + if (_properties['volume'] === undefined) { + _properties['volume'] = DEFAULT_SOUND_VOLUME; + } _properties['position'] = Entities.getEntityProperties(_entityID, ['position']).position; // play beep return Audio.playSound(sound, _properties); @@ -285,7 +291,7 @@ if (_updateInterval) { Script.clearInterval(_updateInterval); } - Messages.messageReceived.connect(onMessage); + Messages.messageReceived.disconnect(onMessage); Messages.unsubscribe(_channel); Entities.deleteEntity(_boppoClownID); print('endOfUnload'); From df644edde4f2048276201bc648f1438e67b85547 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 20 Mar 2017 09:45:50 -0700 Subject: [PATCH 17/23] Fix hand controller not able to select light/particle icons --- scripts/system/edit.js | 2 +- scripts/system/libraries/entitySelectionTool.js | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 42ebb1b8db..fb5a3c2f73 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -42,7 +42,7 @@ var selectionManager = SelectionManager; const PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg"); const POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg"); const SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg"); -var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect'], function(entityID) { +entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect'], function(entityID) { var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']); if (properties.type === 'Light') { return { diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index d68a525458..a8c4300fbe 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -1032,10 +1032,12 @@ SelectionDisplay = (function() { var pickRay = controllerComputePickRay(); if (pickRay) { var entityIntersection = Entities.findRayIntersection(pickRay, true); - - + var iconIntersection = entityIconOverlayManager.findRayIntersection(pickRay); var overlayIntersection = Overlays.findRayIntersection(pickRay); - if (entityIntersection.intersects && + + if (iconIntersection.intersects) { + selectionManager.setSelections([iconIntersection.entityID]); + } else if (entityIntersection.intersects && (!overlayIntersection.intersects || (entityIntersection.distance < overlayIntersection.distance))) { if (HMD.tabletID === entityIntersection.entityID) { From 20022ebdc881d0884873b85e536373e31e255773 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 15 Mar 2017 17:44:35 -0700 Subject: [PATCH 18/23] use deleteLater for ESS script engine on nodeKilled --- assignment-client/src/scripts/EntityScriptServer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index f674ab006c..a47919bdd7 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -395,7 +395,8 @@ void EntityScriptServer::selectAudioFormat(const QString& selectedCodecName) { void EntityScriptServer::resetEntitiesScriptEngine() { auto engineName = QString("about:Entities %1").arg(++_entitiesScriptEngineCount); - auto newEngine = QSharedPointer(new ScriptEngine(ScriptEngine::ENTITY_SERVER_SCRIPT, NO_SCRIPT, engineName)); + auto newEngine = QSharedPointer(new ScriptEngine(ScriptEngine::ENTITY_SERVER_SCRIPT, NO_SCRIPT, engineName), + &ScriptEngine::deleteLater); auto webSocketServerConstructorValue = newEngine->newFunction(WebSocketServerClass::constructor); newEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue); From a4d72c4e6766208ea323a2a8fe323758fe99234c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 16 Mar 2017 10:29:22 -0700 Subject: [PATCH 19/23] make AudioScriptingInterface a Dependency --- .../src/scripts/EntityScriptServer.cpp | 2 ++ interface/src/Application.cpp | 21 ++++++++++--------- .../src/AudioScriptingInterface.cpp | 5 ----- .../src/AudioScriptingInterface.h | 9 +++++--- libraries/script-engine/src/ScriptEngine.cpp | 6 +++++- 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index a47919bdd7..cea2d24534 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -58,6 +58,8 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig DependencyManager::registerInheritance(); + DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 02fe2a2dd3..9157bb7144 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -740,23 +740,24 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } }); - auto& audioScriptingInterface = AudioScriptingInterface::getInstance(); + auto audioScriptingInterface = DependencyManager::set(); connect(audioThread, &QThread::started, audioIO.data(), &AudioClient::start); connect(audioIO.data(), &AudioClient::destroyed, audioThread, &QThread::quit); connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater); connect(audioIO.data(), &AudioClient::muteToggled, this, &Application::audioMuteToggled); - connect(audioIO.data(), &AudioClient::mutedByMixer, &audioScriptingInterface, &AudioScriptingInterface::mutedByMixer); - connect(audioIO.data(), &AudioClient::receivedFirstPacket, &audioScriptingInterface, &AudioScriptingInterface::receivedFirstPacket); - connect(audioIO.data(), &AudioClient::disconnected, &audioScriptingInterface, &AudioScriptingInterface::disconnected); + connect(audioIO.data(), &AudioClient::mutedByMixer, audioScriptingInterface.data(), &AudioScriptingInterface::mutedByMixer); + connect(audioIO.data(), &AudioClient::receivedFirstPacket, audioScriptingInterface.data(), &AudioScriptingInterface::receivedFirstPacket); + connect(audioIO.data(), &AudioClient::disconnected, audioScriptingInterface.data(), &AudioScriptingInterface::disconnected); connect(audioIO.data(), &AudioClient::muteEnvironmentRequested, [](glm::vec3 position, float radius) { auto audioClient = DependencyManager::get(); + auto audioScriptingInterface = DependencyManager::get(); auto myAvatarPosition = DependencyManager::get()->getMyAvatar()->getPosition(); float distance = glm::distance(myAvatarPosition, position); bool shouldMute = !audioClient->isMuted() && (distance < radius); if (shouldMute) { audioClient->toggleMute(); - AudioScriptingInterface::getInstance().environmentMuted(); + audioScriptingInterface->environmentMuted(); } }); @@ -1181,10 +1182,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // set the local loopback interface for local sounds AudioInjector::setLocalAudioInterface(audioIO.data()); - AudioScriptingInterface::getInstance().setLocalAudioInterface(audioIO.data()); - connect(audioIO.data(), &AudioClient::noiseGateOpened, &AudioScriptingInterface::getInstance(), &AudioScriptingInterface::noiseGateOpened); - connect(audioIO.data(), &AudioClient::noiseGateClosed, &AudioScriptingInterface::getInstance(), &AudioScriptingInterface::noiseGateClosed); - connect(audioIO.data(), &AudioClient::inputReceived, &AudioScriptingInterface::getInstance(), &AudioScriptingInterface::inputReceived); + audioScriptingInterface->setLocalAudioInterface(audioIO.data()); + connect(audioIO.data(), &AudioClient::noiseGateOpened, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateOpened); + connect(audioIO.data(), &AudioClient::noiseGateClosed, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateClosed); + connect(audioIO.data(), &AudioClient::inputReceived, audioScriptingInterface.data(), &AudioScriptingInterface::inputReceived); this->installEventFilter(this); @@ -1949,7 +1950,7 @@ void Application::initializeUi() { // For some reason there is already an "Application" object in the QML context, // though I can't find it. Hence, "ApplicationInterface" rootContext->setContextProperty("ApplicationInterface", this); - rootContext->setContextProperty("Audio", &AudioScriptingInterface::getInstance()); + rootContext->setContextProperty("Audio", DependencyManager::get().data()); rootContext->setContextProperty("AudioStats", DependencyManager::get()->getStats().data()); rootContext->setContextProperty("AudioScope", DependencyManager::get().data()); diff --git a/libraries/script-engine/src/AudioScriptingInterface.cpp b/libraries/script-engine/src/AudioScriptingInterface.cpp index fcc1f201f9..8452494d95 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.cpp +++ b/libraries/script-engine/src/AudioScriptingInterface.cpp @@ -19,11 +19,6 @@ void registerAudioMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, soundSharedPointerToScriptValue, soundSharedPointerFromScriptValue); } -AudioScriptingInterface& AudioScriptingInterface::getInstance() { - static AudioScriptingInterface staticInstance; - return staticInstance; -} - AudioScriptingInterface::AudioScriptingInterface() : _localAudioInterface(NULL) { diff --git a/libraries/script-engine/src/AudioScriptingInterface.h b/libraries/script-engine/src/AudioScriptingInterface.h index 6cce78d48f..e97bc329c6 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.h +++ b/libraries/script-engine/src/AudioScriptingInterface.h @@ -14,18 +14,20 @@ #include #include +#include #include class ScriptAudioInjector; -class AudioScriptingInterface : public QObject { +class AudioScriptingInterface : public QObject, public Dependency { Q_OBJECT -public: - static AudioScriptingInterface& getInstance(); + SINGLETON_DEPENDENCY +public: void setLocalAudioInterface(AbstractAudioInterface* audioInterface) { _localAudioInterface = audioInterface; } protected: + // this method is protected to stop C++ callers from calling, but invokable from script Q_INVOKABLE ScriptAudioInjector* playSound(SharedSoundPointer sound, const AudioInjectorOptions& injectorOptions = AudioInjectorOptions()); @@ -42,6 +44,7 @@ signals: private: AudioScriptingInterface(); + AbstractAudioInterface* _localAudioInterface; }; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 3e4e070717..1b3d5057f5 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -627,6 +627,9 @@ void ScriptEngine::init() { qScriptRegisterMetaType(this, qWSCloseCodeToScriptValue, qWSCloseCodeFromScriptValue); qScriptRegisterMetaType(this, wscReadyStateToScriptValue, wscReadyStateFromScriptValue); + // NOTE: You do not want to end up creating new instances of singletons here. They will be on the ScriptEngine thread + // and are likely to be unusable if we "reset" the ScriptEngine by creating a new one (on a whole new thread). + registerGlobalObject("Script", this); { @@ -638,7 +641,8 @@ void ScriptEngine::init() { resetModuleCache(); } - registerGlobalObject("Audio", &AudioScriptingInterface::getInstance()); + registerGlobalObject("Audio", DependencyManager::get().data()); + registerGlobalObject("Entities", entityScriptingInterface.data()); registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); From c63a2c9cda223f8eeba2ed13c3dbf778ba57cd2b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 16 Mar 2017 15:07:54 -0700 Subject: [PATCH 20/23] remove requirement of ScriptEngine in ScriptEngines slots --- libraries/script-engine/src/ScriptEngine.cpp | 8 ++++---- libraries/script-engine/src/ScriptEngine.h | 8 ++++---- libraries/script-engine/src/ScriptEngines.cpp | 20 +++++-------------- libraries/script-engine/src/ScriptEngines.h | 10 +++++----- 4 files changed, 18 insertions(+), 28 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 1b3d5057f5..a5c94c1bb4 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -464,17 +464,17 @@ void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) { void ScriptEngine::scriptErrorMessage(const QString& message) { qCCritical(scriptengine) << qPrintable(message); - emit errorMessage(message); + emit errorMessage(message, getFilename()); } void ScriptEngine::scriptWarningMessage(const QString& message) { qCWarning(scriptengine) << message; - emit warningMessage(message); + emit warningMessage(message, getFilename()); } void ScriptEngine::scriptInfoMessage(const QString& message) { qCInfo(scriptengine) << message; - emit infoMessage(message); + emit infoMessage(message, getFilename()); } // Even though we never pass AnimVariantMap directly to and from javascript, the queued invokeMethod of @@ -1351,7 +1351,7 @@ QUrl ScriptEngine::resourcesPath() const { } void ScriptEngine::print(const QString& message) { - emit printedMessage(message); + emit printedMessage(message, getFilename()); } // Script.require.resolve -- like resolvePath, but performs more validation and throws exceptions on invalid module identifiers (for consistency with Node.js) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 95f377d92b..5ea8d052e9 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -236,10 +236,10 @@ signals: void scriptEnding(); void finished(const QString& fileNameString, ScriptEngine* engine); void cleanupMenuItem(const QString& menuItemString); - void printedMessage(const QString& message); - void errorMessage(const QString& message); - void warningMessage(const QString& message); - void infoMessage(const QString& message); + void printedMessage(const QString& message, const QString& scriptName); + void errorMessage(const QString& message, const QString& scriptName); + void warningMessage(const QString& message, const QString& scriptName); + void infoMessage(const QString& message, const QString& scriptName); void runningStateChanged(); void loadScript(const QString& scriptName, bool isUserLoaded); void reloadScript(const QString& scriptName, bool isUserLoaded); diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 57887d2d96..88b0e0b7b5 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -34,34 +34,24 @@ ScriptsModel& getScriptsModel() { return scriptsModel; } -void ScriptEngines::onPrintedMessage(const QString& message) { - auto scriptEngine = qobject_cast(sender()); - auto scriptName = scriptEngine ? scriptEngine->getFilename() : ""; +void ScriptEngines::onPrintedMessage(const QString& message, const QString& scriptName) { emit printedMessage(message, scriptName); } -void ScriptEngines::onErrorMessage(const QString& message) { - auto scriptEngine = qobject_cast(sender()); - auto scriptName = scriptEngine ? scriptEngine->getFilename() : ""; +void ScriptEngines::onErrorMessage(const QString& message, const QString& scriptName) { emit errorMessage(message, scriptName); } -void ScriptEngines::onWarningMessage(const QString& message) { - auto scriptEngine = qobject_cast(sender()); - auto scriptName = scriptEngine ? scriptEngine->getFilename() : ""; +void ScriptEngines::onWarningMessage(const QString& message, const QString& scriptName) { emit warningMessage(message, scriptName); } -void ScriptEngines::onInfoMessage(const QString& message) { - auto scriptEngine = qobject_cast(sender()); - auto scriptName = scriptEngine ? scriptEngine->getFilename() : ""; +void ScriptEngines::onInfoMessage(const QString& message, const QString& scriptName) { emit infoMessage(message, scriptName); } void ScriptEngines::onErrorLoadingScript(const QString& url) { - auto scriptEngine = qobject_cast(sender()); - auto scriptName = scriptEngine ? scriptEngine->getFilename() : ""; - emit errorLoadingScript(url, scriptName); + emit errorLoadingScript(url); } ScriptEngines::ScriptEngines(ScriptEngine::Context context) diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 2fadfc81f8..63b7e8f11c 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -79,13 +79,13 @@ signals: void errorMessage(const QString& message, const QString& engineName); void warningMessage(const QString& message, const QString& engineName); void infoMessage(const QString& message, const QString& engineName); - void errorLoadingScript(const QString& url, const QString& engineName); + void errorLoadingScript(const QString& url); public slots: - void onPrintedMessage(const QString& message); - void onErrorMessage(const QString& message); - void onWarningMessage(const QString& message); - void onInfoMessage(const QString& message); + void onPrintedMessage(const QString& message, const QString& scriptName); + void onErrorMessage(const QString& message, const QString& scriptName); + void onWarningMessage(const QString& message, const QString& scriptName); + void onInfoMessage(const QString& message, const QString& scriptName); void onErrorLoadingScript(const QString& url); protected slots: From 0a118bd268d0033fd35ce6c99891b7bb9092379d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 16 Mar 2017 18:41:26 -0700 Subject: [PATCH 21/23] add a guard for trading entity servers by checking node count --- .../src/scripts/EntityScriptServer.cpp | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index cea2d24534..c46d658c52 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -326,7 +326,26 @@ void EntityScriptServer::nodeActivated(SharedNodePointer activatedNode) { void EntityScriptServer::nodeKilled(SharedNodePointer killedNode) { switch (killedNode->getType()) { case NodeType::EntityServer: { - clear(); + // Before we clear, make sure this was our only entity server. + // Otherwise we're assuming that we have "trading" entity servers + // (an old one going away and a new one coming onboard) + // and that we shouldn't clear here because we're still doing work. + bool hasAnotherEntityServer = false; + auto nodeList = DependencyManager::get(); + + nodeList->eachNodeBreakable([&hasAnotherEntityServer, &killedNode](const SharedNodePointer& node){ + if (node->getType() == NodeType::EntityServer && node->getUUID() != killedNode->getUUID()) { + // we're talking to > 1 entity servers, we know we won't clear + hasAnotherEntityServer = true; + return false; + } + + return true; + }); + + if (hasAnotherEntityServer) { + clear(); + } break; } From 96cf6b8c0418ca4e8548792d921405d70c81db30 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 17 Mar 2017 13:19:59 -0700 Subject: [PATCH 22/23] fix clear check for missing other entity servers --- assignment-client/src/scripts/EntityScriptServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index c46d658c52..954c25a342 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -343,7 +343,7 @@ void EntityScriptServer::nodeKilled(SharedNodePointer killedNode) { return true; }); - if (hasAnotherEntityServer) { + if (!hasAnotherEntityServer) { clear(); } From dff67886d099d66f29cfc146651c66810466b092 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 22 Mar 2017 17:28:10 +0100 Subject: [PATCH 23/23] CR Changes - remove double constructor, use creation function instead --- unpublishedScripts/marketplace/boppo/boppoClownEntity.js | 8 ++++---- unpublishedScripts/marketplace/boppo/boppoServer.js | 8 +++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/unpublishedScripts/marketplace/boppo/boppoClownEntity.js b/unpublishedScripts/marketplace/boppo/boppoClownEntity.js index 2fa4441e52..36f2bf5ab0 100644 --- a/unpublishedScripts/marketplace/boppo/boppoClownEntity.js +++ b/unpublishedScripts/marketplace/boppo/boppoClownEntity.js @@ -8,7 +8,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals BoppoClownEntity:true LookAtTarget */ +/* globals LookAtTarget */ (function() { var SFX_PREFIX = 'https://hifi-content.s3-us-west-1.amazonaws.com/caitlyn/production/elBoppo/sfx/'; @@ -21,7 +21,7 @@ Script.include('lookAtEntity.js'); - BoppoClownEntity = function() { + var createBoppoClownEntity = function() { var _this, _entityID, _boppoUserData, @@ -38,7 +38,7 @@ return {}; }; - BoppoClownEntity = function () { + var BoppoClownEntity = function () { _this = this; PUNCH_SOUNDS.forEach(function(punch) { _punchSounds.push(SoundCache.getSound(SFX_PREFIX + punch)); @@ -76,5 +76,5 @@ return new BoppoClownEntity(); }; - return new BoppoClownEntity(); + return createBoppoClownEntity(); }); diff --git a/unpublishedScripts/marketplace/boppo/boppoServer.js b/unpublishedScripts/marketplace/boppo/boppoServer.js index 28690c0a00..f03154573c 100644 --- a/unpublishedScripts/marketplace/boppo/boppoServer.js +++ b/unpublishedScripts/marketplace/boppo/boppoServer.js @@ -8,8 +8,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals BoppoServer:true */ - (function() { var SFX_PREFIX = 'https://hifi-content.s3-us-west-1.amazonaws.com/caitlyn/production/elBoppo/sfx/'; var CLOWN_LAUGHS = [ @@ -41,7 +39,7 @@ var TICK_TOCK_FROM = 3; // seconds var COOLDOWN_TIME_MS = MILLISECONDS_PER_SECOND * 3; - BoppoServer = function() { + var createBoppoServer = function() { var _this, _isInitialized = false, _clownLaughs = [], @@ -164,7 +162,7 @@ } }; - BoppoServer = function () { + var BoppoServer = function () { _this = this; _hits = 0; _boppoClownID = null; @@ -301,5 +299,5 @@ return new BoppoServer(); }; - return new BoppoServer(); + return createBoppoServer(); });