mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
There was a "scale" property on the original 3d overlay that was used in this script or scale the dimensions. But it seems that the "scale" property was not doing anything. When I moved this script to Local Entities, I had to multiply the dimensions with their respective scale and the result was badly streched. (clearly, based on the texture deformation, it was not wished. In addition that Hifi release it as functional ignoring that the scale was doing nothing.) This fix just remove that scaling added assuming that it was working. Now it is it was before V8.
219 lines
8.7 KiB
JavaScript
219 lines
8.7 KiB
JavaScript
"use strict";
|
|
//
|
|
// bubble.js
|
|
// scripts/system/
|
|
//
|
|
// Created by Brad Hefta-Gaub on November 18th, 2016
|
|
// Copyright 2016 High Fidelity, Inc.
|
|
// Copyright 2023 Overte e.V.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
/* global Script, Users, Entities, AvatarList, Controller, Camera, getControllerWorldLocation, UserActivityLogger */
|
|
|
|
(function () { // BEGIN LOCAL_SCOPE
|
|
var button;
|
|
// Used for animating and disappearing the bubble
|
|
var bubbleOverlayTimestamp;
|
|
// Used for rate limiting the bubble sound
|
|
var lastBubbleSoundTimestamp = 0;
|
|
// Affects bubble height
|
|
var BUBBLE_HEIGHT_SCALE = 0.15;
|
|
// The bubble model itself
|
|
var bubbleOverlay = Entities.addEntity({
|
|
"type": "Model",
|
|
"modelURL": Script.resolvePath("assets/models/Bubble-v14.fbx"), // If you'd like to change the model, modify this line (and the dimensions below)
|
|
"dimensions": {
|
|
"x": MyAvatar.sensorToWorldScale,
|
|
"y": (0.75 * MyAvatar.sensorToWorldScale),
|
|
"z": MyAvatar.sensorToWorldScale
|
|
},
|
|
"position": { "x": MyAvatar.position.x, "y": -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, "z": MyAvatar.position.z },
|
|
"rotation": Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({"x": 0.0, "y": 180.0, "z": 0.0})),
|
|
"visible": false,
|
|
"ignorePickIntersection": true
|
|
}, "local");
|
|
// The bubble activation sound
|
|
var bubbleActivateSound = SoundCache.getSound(Script.resolvePath("assets/sounds/bubble.wav"));
|
|
// Is the update() function connected?
|
|
var updateConnected = false;
|
|
|
|
var BUBBLE_VISIBLE_DURATION_MS = 3000;
|
|
var BUBBLE_RAISE_ANIMATION_DURATION_MS = 750;
|
|
var BUBBLE_SOUND_RATE_LIMIT_MS = 15000;
|
|
|
|
// Hides the bubble model overlay
|
|
function hideOverlays() {
|
|
Entities.editEntity(bubbleOverlay, {
|
|
"visible": false
|
|
});
|
|
}
|
|
|
|
//create a menu item in "Setings" to toggle the bubble/shield HUD button
|
|
var menuItemName = "HUD Shield Button";
|
|
Menu.addMenuItem({
|
|
menuName: "Settings",
|
|
menuItemName: menuItemName,
|
|
isCheckable: true,
|
|
isChecked: AvatarInputs.showBubbleTools
|
|
});
|
|
Menu.menuItemEvent.connect(onToggleHudShieldButton);
|
|
AvatarInputs.showBubbleToolsChanged.connect(showBubbleToolsChanged);
|
|
|
|
function onToggleHudShieldButton(menuItem) {
|
|
if (menuItem === menuItemName) {
|
|
AvatarInputs.setShowBubbleTools(Menu.isOptionChecked(menuItem));
|
|
};
|
|
}
|
|
|
|
function showBubbleToolsChanged(show) {
|
|
Menu.setIsOptionChecked(menuItemName, show);
|
|
}
|
|
|
|
// Make the bubble overlay visible, set its position, and play the sound
|
|
function createOverlays() {
|
|
var nowTimestamp = Date.now();
|
|
if (nowTimestamp - lastBubbleSoundTimestamp >= BUBBLE_SOUND_RATE_LIMIT_MS) {
|
|
Audio.playSound(bubbleActivateSound, {
|
|
position: { x: MyAvatar.position.x, y: MyAvatar.position.y, z: MyAvatar.position.z },
|
|
localOnly: true,
|
|
volume: 0.2
|
|
});
|
|
lastBubbleSoundTimestamp = nowTimestamp;
|
|
}
|
|
hideOverlays();
|
|
if (updateConnected === true) {
|
|
updateConnected = false;
|
|
Script.update.disconnect(update);
|
|
}
|
|
|
|
Entities.editEntity(bubbleOverlay, {
|
|
"dimensions": {
|
|
"x": MyAvatar.sensorToWorldScale,
|
|
"y": 0.75 * MyAvatar.sensorToWorldScale,
|
|
"z": MyAvatar.sensorToWorldScale
|
|
},
|
|
"position": {
|
|
"x": MyAvatar.position.x,
|
|
"y": -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE,
|
|
"z": MyAvatar.position.z
|
|
},
|
|
"rotation": Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({"x": 0.0, "y": 180.0, "z": 0.0})),
|
|
"visible": true
|
|
});
|
|
bubbleOverlayTimestamp = nowTimestamp;
|
|
Script.update.connect(update);
|
|
updateConnected = true;
|
|
}
|
|
|
|
// Called from the C++ scripting interface to show the bubble overlay
|
|
function enteredIgnoreRadius() {
|
|
createOverlays();
|
|
UserActivityLogger.privacyShieldActivated();
|
|
}
|
|
|
|
// Used to set the state of the bubble HUD button
|
|
function writeButtonProperties(parameter) {
|
|
button.editProperties({isActive: parameter});
|
|
}
|
|
|
|
// The bubble script's update function
|
|
function update() {
|
|
var timestamp = Date.now();
|
|
var delay = (timestamp - bubbleOverlayTimestamp);
|
|
var overlayAlpha = 1.0 - (delay / BUBBLE_VISIBLE_DURATION_MS);
|
|
if (overlayAlpha > 0) {
|
|
if (delay < BUBBLE_RAISE_ANIMATION_DURATION_MS) {
|
|
Entities.editEntity(bubbleOverlay, {
|
|
"dimensions": {
|
|
"x": MyAvatar.sensorToWorldScale,
|
|
"y": (0.75 * MyAvatar.sensorToWorldScale) * (1 - ((BUBBLE_RAISE_ANIMATION_DURATION_MS - delay) / BUBBLE_RAISE_ANIMATION_DURATION_MS)),
|
|
"z": MyAvatar.sensorToWorldScale
|
|
},
|
|
// Quickly raise the bubble from the ground up
|
|
"position": {
|
|
"x": MyAvatar.position.x,
|
|
"y": (-((BUBBLE_RAISE_ANIMATION_DURATION_MS - delay) / BUBBLE_RAISE_ANIMATION_DURATION_MS)) * MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE,
|
|
"z": MyAvatar.position.z
|
|
},
|
|
"rotation": Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({"x": 0.0, "y": 180.0, "z": 0.0}))
|
|
});
|
|
} else {
|
|
// Keep the bubble in place for a couple seconds
|
|
Entities.editEntity(bubbleOverlay, {
|
|
"dimensions": {
|
|
"x": MyAvatar.sensorToWorldScale,
|
|
"y": 0.75 * MyAvatar.sensorToWorldScale,
|
|
"z": MyAvatar.sensorToWorldScale
|
|
},
|
|
"position": {
|
|
"x": MyAvatar.position.x,
|
|
"y": MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE,
|
|
"z": MyAvatar.position.z
|
|
},
|
|
"rotation": Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({"x": 0.0, "y": 180.0, "z": 0.0}))
|
|
});
|
|
}
|
|
} else {
|
|
hideOverlays();
|
|
if (updateConnected === true) {
|
|
Script.update.disconnect(update);
|
|
updateConnected = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// When the space bubble is toggled...
|
|
// NOTE: the c++ calls this with just the first param -- we added a second
|
|
// just for not logging the initial state of the bubble when we startup.
|
|
function onBubbleToggled(enabled, doNotLog) {
|
|
writeButtonProperties(enabled);
|
|
if (doNotLog !== true) {
|
|
UserActivityLogger.privacyShieldToggled(enabled);
|
|
}
|
|
if (enabled) {
|
|
createOverlays();
|
|
} else {
|
|
hideOverlays();
|
|
if (updateConnected === true) {
|
|
Script.update.disconnect(update);
|
|
updateConnected = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Setup the bubble button
|
|
var buttonName = "SHIELD";
|
|
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
|
button = tablet.addButton({
|
|
icon: "icons/tablet-icons/bubble-i.svg",
|
|
activeIcon: "icons/tablet-icons/bubble-a.svg",
|
|
text: buttonName,
|
|
sortOrder: 4
|
|
});
|
|
|
|
onBubbleToggled(Users.getIgnoreRadiusEnabled(), true); // pass in true so we don't log this initial one in the UserActivity table
|
|
|
|
button.clicked.connect(Users.toggleIgnoreRadius);
|
|
Users.ignoreRadiusEnabledChanged.connect(onBubbleToggled);
|
|
Users.enteredIgnoreRadius.connect(enteredIgnoreRadius);
|
|
|
|
// Cleanup the tablet button and overlays when script is stopped
|
|
Script.scriptEnding.connect(function () {
|
|
Menu.menuItemEvent.disconnect(onToggleHudShieldButton);
|
|
AvatarInputs.showBubbleToolsChanged.disconnect(showBubbleToolsChanged);
|
|
Menu.removeMenuItem("Settings", menuItemName);
|
|
button.clicked.disconnect(Users.toggleIgnoreRadius);
|
|
if (tablet) {
|
|
tablet.removeButton(button);
|
|
}
|
|
Users.ignoreRadiusEnabledChanged.disconnect(onBubbleToggled);
|
|
Users.enteredIgnoreRadius.disconnect(enteredIgnoreRadius);
|
|
Entities.deleteEntity(bubbleOverlay);
|
|
if (updateConnected === true) {
|
|
Script.update.disconnect(update);
|
|
}
|
|
});
|
|
|
|
}()); // END LOCAL_SCOPE
|