Several reworks

v1.6 (By Alezia Kurdis for Overte, August 12th, 2023)

    Replace the Color Picker Component (sadly GPLv3) by a simple hue selector.
    Add an "uninstall" button
    Keep the icon active if the switch is on.
    The appreciation dodecahedron is now emissive, and glows as the intensity grows.
This commit is contained in:
Alezia Kurdis 2023-08-12 23:12:25 -04:00 committed by GitHub
parent fbfda48090
commit 4bb43d3443
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 187 additions and 132 deletions

View file

@ -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

View file

@ -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 <https://www.gnu.org/licenses/>.
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);
}
}

View file

@ -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 <https://www.gnu.org/licenses/>.
Distributed under the Apache License, Version 2.0
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-->
<html>
@ -27,8 +17,6 @@
<title>Appreciate</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="css/style.css">
<!--I modified jscolor to prevent it from printing the color code to the value of the input onchange. -->
<script type="text/javascript" src="js/jscolor.js"></script>
</head>
<body>
@ -38,7 +26,7 @@
<div id="mainContainer">
<div id="titleBarContainer">
<div id="titleText" style="font-weight:bold;">
Appreciate v1.5
Appreciate v1.6
</div>
<label class="switch">
<input id="appreciateSwitch" type="checkbox" onclick="appreciateSwitchClicked(this)">
@ -73,14 +61,13 @@
<input id="showAppreciationEntityCheckbox" type="checkbox" onclick="showAppreciationEntityCheckboxClicked(this)">
<span class="checkmark"></span>
</label>
<br>
<div id="colorPickerContainer">
<input type="button" id="colorPicker" class="jscolor"
onchange="setEntityColor(this.jscolor)" value="Choose Dodecahedron Color">
</input>
<div id="colorPicker">Dodecahedron Color</div>
<img src="images/hueBar.jpg" id="hueSelector" draggable="false">
</div>
</div>
<div id="instructions">
<div id="desktopModeInstructions">
Desktop Mode:<br/>Tap or hold the Z key on your keyboard!
@ -89,8 +76,12 @@
VR Mode:<br/>Raise your hands above your head and shake them!
</div>
</div>
</div>
<div id ="uninstallBar">
<button id="uninstall" onClick = "uninstall();">Uninstall this application</button>
</div>
<!--Include this script here so it only executes once the DOM is ready.-->
<script type="text/javascript" src="js/appreciate_ui.js"></script>
</body>

View file

@ -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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View file

@ -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 <https://www.gnu.org/licenses/>.
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":