diff --git a/applications/appreciate/README.md b/applications/appreciate/README.md index b3f9a36..b98401d 100644 --- a/applications/appreciate/README.md +++ b/applications/appreciate/README.md @@ -6,6 +6,13 @@ Show someone else that you like what they're doing. Open the app to see usage in ## Releases +### v1.6 (By Alezia Kurdis for Overte, August 12th, 2023) + +- Replace the Color Picker Component (sadly GPLv3) by a simple hue selector. +- Add a Install button +- Keep the icon active if the switch is on. +- The appreciation dodecahedron is now emissive, and glows as the intensity grows. + ### v1.5 | [48d8247](https://github.com/highfidelity/hifi-content/commit/48d8247) - Fixed an issue where Appreciate app users wearing avatars without a specific joint wouldn't hear the Appreciate sound or see the Appreciation Dodecahedron diff --git a/applications/appreciate/appreciate_app.js b/applications/appreciate/appreciate_app.js index df2cd33..4f45bf1 100644 --- a/applications/appreciate/appreciate_app.js +++ b/applications/appreciate/appreciate_app.js @@ -8,20 +8,10 @@ "Appreciate" application. Show someone else that you like what they're doing. Open the app to see usage instructions and some options! - (version 1.5.0) + (version 1.6.0) - * This program ("Appreciate" application) is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + Distributed under the Apache License, Version 2.0 + See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html */ (function () { @@ -71,30 +61,11 @@ return minOutput + (maxOutput - minOutput) * (factor - minInput) / (maxInput - minInput); } - - - // Linearly scales an RGB color between 0 and 1 based on RGB color values - // between 0 and 255. - function linearScaleColor(intensity, min, max) { - var output = { - "red": 0, - "green": 0, - "blue": 0 - }; - - output.red = linearScale(intensity, 0, 1, min.red, max.red); - output.green = linearScale(intensity, 0, 1, min.green, max.green); - output.blue = linearScale(intensity, 0, 1, min.blue, max.blue); - - return output; - } - function randomFloat(min, max) { return Math.random() * (max - min) + min; } - // Updates the Current Intensity Meter UI element. Called when intensity changes. function updateCurrentIntensityUI() { ui.sendMessage({method: "updateCurrentIntensityUI", currentIntensity: currentIntensity}); @@ -117,6 +88,7 @@ if (intensityEntity) { Entities.deleteEntity(intensityEntity); intensityEntity = false; + intensityEntityMaterial = Uuid.NULL; } } @@ -179,6 +151,7 @@ // current intensity of their appreciation. // Many of these property values are empirically determined. var intensityEntity = false; + var intensityEntityMaterial = Uuid.NULL; var INTENSITY_ENTITY_MAX_DIMENSIONS = { "x": 0.24, "y": 0.24, @@ -205,6 +178,7 @@ "blue": 5 }; var MIN_COLOR_MULTIPLIER = 0.4; + var MAX_GLOW = 3; var intensityEntityColorMax = JSON.parse(Settings.getValue("appreciate/entityColor", JSON.stringify(INTENSITY_ENTITY_COLOR_MAX_DEFAULT))); var ANGVEL_ENTITY_MULTIPLY_FACTOR = 62; @@ -225,35 +199,12 @@ }, "angularDamping": 0, "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } + "grabbable": false }, "collisionless": true, "ignoreForCollisions": true, - "queryAACube": { - "x": -0.17320507764816284, - "y": -0.17320507764816284, - "z": -0.17320507764816284, - "scale": 0.3464101552963257 - }, "damping": 0, - "color": intensityEntityColorMin, - "clientOnly": false, - "avatarEntity": true, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false + "color": intensityEntityColorMin }; var currentInitialAngularVelocity = { "x": 0, @@ -266,12 +217,22 @@ } if (currentIntensity > 0) { + var matData = { + "materialVersion": 1, + "materials": [ + { + "name": "intensity", + "albedo": [intensityEntityColorMax.red/255, intensityEntityColorMax.green/255, intensityEntityColorMax.blue/255], + "metallic": 0.001, + "roughness": 0.9, + "emissive": [(intensityEntityColorMax.red/255) * (MAX_GLOW * currentIntensity), (intensityEntityColorMax.green/255) * (MAX_GLOW * currentIntensity), (intensityEntityColorMax.blue/255) * (MAX_GLOW * currentIntensity)], + "cullFaceMode": "CULL_BACK", + "model": "hifi_pbr" + } + ] + }; + if (intensityEntity) { - intensityEntityColorMin.red = intensityEntityColorMax.red * MIN_COLOR_MULTIPLIER; - intensityEntityColorMin.green = intensityEntityColorMax.green * MIN_COLOR_MULTIPLIER; - intensityEntityColorMin.blue = intensityEntityColorMax.blue * MIN_COLOR_MULTIPLIER; - - var color = linearScaleColor(currentIntensity, intensityEntityColorMin, intensityEntityColorMax); var propsToUpdate = { position: getAppreciationPosition() @@ -290,13 +251,8 @@ lastAngularVelocity = currentAngularVelocity; } - var currentColor = color; - if (colorChangedEnough(currentColor, lastColor, COLOR_DISTANCE_THRESHOLD_PERCENT_CHANGE)) { - propsToUpdate.color = currentColor; - lastColor = currentColor; - } - Entities.editEntity(intensityEntity, propsToUpdate); + Entities.editEntity(intensityEntityMaterial, {"materialData": JSON.stringify(matData)}); } else { var props = INTENSITY_ENTITY_PROPERTIES; props.position = getAppreciationPosition(); @@ -310,11 +266,21 @@ props.angularVelocity = currentInitialAngularVelocity; intensityEntity = Entities.addEntity(props, "avatar"); + intensityEntityMaterial = Entities.addEntity({ + "type": "Material", + "name": "Intensity Entity Material", + "parentID": intensityEntity, + "materialURL": "materialData", + "materialData": JSON.stringify(matData), + "priority": 2, + "parentMaterialName": "0" + }, "avatar"); } } else { if (intensityEntity) { Entities.deleteEntity(intensityEntity); intensityEntity = false; + intensityEntityMaterial = Uuid.NULL; } maybeClearUpdateIntensityEntityInterval(); @@ -327,6 +293,13 @@ updateCurrentIntensityUI(); } + function onClosed() { + if (appreciateEnabled) { + ui.buttonActive(true); + } else { + ui.buttonActive(false); + } + } // Locally pre-caches all of the sounds in the sounds/claps and sounds/whistles // directories. @@ -1018,7 +991,11 @@ intensityEntityColorMax = message.entityColor; Settings.setValue("appreciate/entityColor", JSON.stringify(intensityEntityColorMax)); break; - + + case "uninstall": + ScriptDiscoveryService.stopScript(Script.resolvePath(''), false); + break; + case "zKeyDown": var pressEvent = { "text": "Z", @@ -1088,12 +1065,12 @@ if (intensityEntity) { Entities.deleteEntity(intensityEntity); intensityEntity = false; + intensityEntityMaterial = Uuid.NULL; } HMD.displayModeChanged.disconnect(enableOrDisableAppreciate); } - // When called, this function will stop the versions of this script that are // baked into the client installation IF there's another version of the script // running that ISN'T the baked version. @@ -1121,7 +1098,6 @@ } } - // Called when the script starts up var BUTTON_NAME = "APPRECIATE"; var APP_UI_URL = Script.resolvePath('resources/appreciate_ui.html'); @@ -1135,7 +1111,8 @@ // clap by Rena from the Noun Project graphicsDirectory: Script.resolvePath("./resources/images/icons/"), onOpened: onOpened, - onMessage: onMessage + onMessage: onMessage, + onClosed: onClosed }); cleanupOldIntensityEntities(); @@ -1146,6 +1123,12 @@ getAnimations(); HMD.displayModeChanged.connect(enableOrDisableAppreciate); maybeStopBakedScriptVersions(); + + if (appreciateEnabled) { + ui.buttonActive(true); + } else { + ui.buttonActive(false); + } } diff --git a/applications/appreciate/resources/appreciate_ui.html b/applications/appreciate/resources/appreciate_ui.html index f89504e..9034efb 100644 --- a/applications/appreciate/resources/appreciate_ui.html +++ b/applications/appreciate/resources/appreciate_ui.html @@ -8,18 +8,8 @@ UI for the "Appreciate" application. - * This program ("Appreciate" application) is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + Distributed under the Apache License, Version 2.0 + See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html --> @@ -27,8 +17,6 @@ Appreciate - - @@ -38,7 +26,7 @@
- Appreciate v1.5 + Appreciate v1.6
- +
- - +
Dodecahedron Color
+
+
-
Desktop Mode:
Tap or hold the Z key on your keyboard! @@ -89,8 +76,12 @@ VR Mode:
Raise your hands above your head and shake them!
+
+
+ +
diff --git a/applications/appreciate/resources/css/style.css b/applications/appreciate/resources/css/style.css index 8ac3f48..127deb4 100644 --- a/applications/appreciate/resources/css/style.css +++ b/applications/appreciate/resources/css/style.css @@ -26,7 +26,7 @@ body { #mainContainer { width: 100vw; - height: 100vh; + height: 96vh; } #loadingContainer { @@ -151,7 +151,7 @@ input:checked + .slider:before { #currentIntensityDisplay { width: 100%; - height: 175px; + height: 100px; margin-top: 8px; background: #FFFFFF; background-image: linear-gradient(to right, #EEE 0, #EEE 55%, #FFF 55%, #FFF 100%); @@ -180,22 +180,31 @@ input:checked + .slider:before { #optionsContainer { display: flex; flex-direction: column; - height: 150px; + height: 100px; width: calc(100vw - 24px); margin: 12px 12px 0 12px; position: absolute; } #colorPickerContainer { - margin: 8px 0 0 0; - visibility: hidden; + text-align: left; + width: 100%; } -#colorPickerContainer > input { +#colorPicker { font-family: Raleway; + color: #000000; height: 34px; - font-size: 18px; - min-width: 185px; + font-size: 24px; + width: 360px; + border: 1px solid #000000; + vertical-align: middle; + text-align: center; +} + +#hueSelector { + width: 360px; + border: 1px solid #000000; } .checkmark { @@ -277,7 +286,7 @@ input:checked + .slider:before { #instructions { position: fixed; height: 150px; - bottom: 0; + bottom: 20px; left: 0; right: 0; margin: 0 12px; @@ -287,3 +296,33 @@ input:checked + .slider:before { #instructions > div { margin-top: 16px; } + +#uninstall { + font-family: Raleway; + background-color: #222222; + font-size: 9px; + color: #cccccc; + border-radius: 3px; + border: 0px solid #000000; + transition-duration: 0.2s; + width: 140px; + padding: 3px; +} + +#uninstall:hover { + background-color: #000000; + color: #ffffff; +} + +#uninstall:focus { + outline: none; +} + +#uninstallBar { + text-align: right; + background-color: #121212; + width: 100vw; + height: 4vh; + padding-right: 8px; + padding-top: 2px; +} diff --git a/applications/appreciate/resources/images/hueBar.jpg b/applications/appreciate/resources/images/hueBar.jpg new file mode 100644 index 0000000..8215cdb Binary files /dev/null and b/applications/appreciate/resources/images/hueBar.jpg differ diff --git a/applications/appreciate/resources/js/appreciate_ui.js b/applications/appreciate/resources/js/appreciate_ui.js index 2732ce4..bafcc8d 100644 --- a/applications/appreciate/resources/js/appreciate_ui.js +++ b/applications/appreciate/resources/js/appreciate_ui.js @@ -7,18 +7,8 @@ Javascript code for the UI of the "Appreciate" application. - * This program ("Appreciate" application) is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + Distributed under the Apache License, Version 2.0 + See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html */ /* globals document EventBridge setTimeout */ @@ -67,14 +57,15 @@ function showAppreciationEntityCheckboxClicked(checkbox) { } } -// Called when the user changes the entity's color using the jscolor picker. +// Called when the user changes the entity's color using the hue selector. // Modifies the color of the Intensity Meter gradient and sends a message to the App JS. var START_COLOR_MULTIPLIER = 0.2; -function setEntityColor(jscolor) { +function setEntityColor(colorArray) { + var newEntityColor = { - "red": jscolor.rgb[0], - "green": jscolor.rgb[1], - "blue": jscolor.rgb[2] + "red": colorArray[0], + "green": colorArray[1], + "blue": colorArray[2] }; var startColor = { @@ -86,8 +77,10 @@ function setEntityColor(jscolor) { var currentIntensityDisplayWidth = document.getElementById("currentIntensityDisplay").offsetWidth; var bgString = "linear-gradient(to right, rgb(" + startColor.red + ", " + startColor.green + ", " + startColor.blue + ") 0, " + - jscolor.toHEXString() + " " + currentIntensityDisplayWidth + "px)"; + "rgb(" + newEntityColor.red + ", " + newEntityColor.green + ", " + newEntityColor.blue + ") " + + currentIntensityDisplayWidth + "px)"; document.getElementById("currentIntensity").style.backgroundImage = bgString; + document.getElementById("colorPicker").style.backgroundColor = "rgb(" + newEntityColor.red + ", " + newEntityColor.green + ", " + newEntityColor.blue + ")"; EventBridge.emitWebEvent(JSON.stringify({ app: "appreciate", @@ -96,6 +89,59 @@ function setEntityColor(jscolor) { })); } +var hueSelector = document.getElementById('hueSelector'); +hueSelector.addEventListener("click", function(event) { + var rect = hueSelector.getBoundingClientRect(); + var hue = event.clientX - rect.left; + if (hue >= 0 || hue <= 360) { + setEntityColor(hslToRgb(hue/360, 1, 0.65)); //.65 is adding just a bit of white in the saturated color (0.5) to get a brighter glow effect. + } +}); + +/* + * Converts an HSL color value to RGB. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes h, s, and l are contained in the set [0, 1] and + * returns r, g, and b in the set [0, 255]. + * + * @param {number} h The hue + * @param {number} s The saturation + * @param {number} l The lightness + * @return {Array} The RGB representation + */ +function hslToRgb(h, s, l){ + var r, g, b; + + if(s == 0){ + r = g = b = l; // achromatic + }else{ + var hue2rgb = function hue2rgb(p, q, t){ + if(t < 0) t += 1; + if(t > 1) t -= 1; + if(t < 1/6) return p + (q - p) * 6 * t; + if(t < 1/2) return q; + if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + } + + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; +} + +function uninstall() { + var message = { + "app": "appreciate", + "method": "uninstall" + }; + EventBridge.emitWebEvent(JSON.stringify(message)); +} + // Handle EventBridge messages from *_app.js. function onScriptEventReceived(message) { try { @@ -133,19 +179,8 @@ function onScriptEventReceived(message) { document.getElementById("loadingContainer").style.display = "none"; - var color = document.getElementById("colorPicker").jscolor; - color.fromRGB(message.entityColor.red, message.entityColor.green, message.entityColor.blue); - - var startColor = { - "red": Math.floor(color.rgb[0] * START_COLOR_MULTIPLIER), - "green": Math.floor(color.rgb[1] * START_COLOR_MULTIPLIER), - "blue": Math.floor(color.rgb[2] * START_COLOR_MULTIPLIER) - }; - var currentIntensityDisplayWidth = document.getElementById("currentIntensityDisplay").offsetWidth; - document.getElementById("currentIntensity").style.backgroundImage = - "linear-gradient(to right, rgb(" + startColor.red + ", " + - startColor.green + ", " + startColor.blue + ") 0, " + - color.toHEXString() + " " + currentIntensityDisplayWidth + "px)"; + setEntityColor([message.entityColor.red, message.entityColor.green, message.entityColor.blue]); + break; case "updateCurrentIntensityUI":