content/hifi-content/rebecca/Karaoke/karaoke.js
2022-02-14 02:04:11 +01:00

256 lines
8.8 KiB
JavaScript

"use strict";
/*jslint vars:true, plusplus:true, forin:true*/
/*global Tablet, Script, */
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */
//
// HRTF.js
//
// Created by Zach Fox on 2018-03-16
// Copyright 2018 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
//
(function () { // BEGIN LOCAL_SCOPE
var SOUND_SONG = SoundCache.getSound(Script.resolvePath("song.wav"));
var soundsArray = [SOUND_SONG];
// Function Name: addOrRemoveButton()
//
// Description:
// -Used to add or remove the "HRTF" app button from the HUD/tablet. Set the "isShuttingDown" argument
// to true if you're calling this function upon script shutdown.
//
// Relevant Variables:
// -button: The tablet button.
// -buttonName: The name of the button.
var button = false;
var buttonName = "HRTF";
function addOrRemoveButton(isShuttingDown) {
if (!tablet) {
print("Warning in addOrRemoveButton(): 'tablet' undefined!");
return;
}
if (!button && !isShuttingDown) {
button = tablet.addButton({
text: buttonName,
icon: Script.resolvePath("hrtf-i.svg"),
activeIcon: Script.resolvePath("hrtf-a.svg")
});
button.clicked.connect(onTabletButtonClicked);
} else if (button) {
button.clicked.disconnect(onTabletButtonClicked);
tablet.removeButton(button);
button = false;
} else {
print("ERROR adding/removing HRTF button!");
}
}
// Function Name: startup()
//
// Description:
// -startup() will be called when the script is loaded.
//
// Relevant Variables:
// -tablet: The tablet instance to be modified.
var tablet = null;
function startup() {
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
addOrRemoveButton(false);
tablet.screenChanged.connect(onTabletScreenChanged);
}
// Function Name: wireEventBridge()
//
// Description:
// -Used to connect/disconnect the script's response to the tablet's "fromQml" signal. Set the "on" argument to enable or
// disable to event bridge.
//
// Relevant Variables:
// -hasEventBridge: true/false depending on whether we've already connected the event bridge.
var hasEventBridge = false;
function wireEventBridge(on) {
if (!tablet) {
print("Warning in wireEventBridge(): 'tablet' undefined!");
return;
}
if (on) {
if (!hasEventBridge) {
tablet.fromQml.connect(fromQml);
hasEventBridge = true;
}
} else {
if (hasEventBridge) {
tablet.fromQml.disconnect(fromQml);
hasEventBridge = false;
}
}
}
// Function Name: onTabletButtonClicked()
//
// Description:
// -Fired when the app button is pressed.
//
// Relevant Variables:
// -HRTF_QML_SOURCE: The path to the app QML
// -onHRTFScreen: true/false depending on whether we're looking at the app.
var HRTF_QML_SOURCE = Script.resolvePath("HRTF.qml");
var onHRTFScreen = false;
function onTabletButtonClicked() {
if (!tablet) {
print("Warning in onTabletButtonClicked(): 'tablet' undefined!");
return;
}
if (onHRTFScreen) {
// In Toolbar Mode, `gotoHomeScreen` will close the app window.
tablet.gotoHomeScreen();
} else {
tablet.loadQMLSource(HRTF_QML_SOURCE);
}
}
// Function Name: onTabletScreenChanged()
//
// Description:
// -Called when the TabletScriptingInterface::screenChanged() signal is emitted. The "type" argument can be either the string
// value of "Home", "Web", "Menu", "QML", or "Closed". The "url" argument is only valid for Web and QML.
function onTabletScreenChanged(type, url) {
onHRTFScreen = (type === "QML" && url === HRTF_QML_SOURCE);
wireEventBridge(onHRTFScreen);
if (onHRTFScreen && !audioSphere) {
audioSphere = Entities.addEntity({
"angularDamping": 1,
"clientOnly": true,
"collidesWith": "",
"collisionMask": 0,
"collisionless": true,
"color": {
"blue": 0,
"green": 255,
"red": 255
},
"damping": 1,
"dimensions": {
"x": 0.15,
"y": 0.15,
"z": 0.15
},
"ignoreForCollisions": true,
"type": "Sphere"
}, true);
} else if (audioSphere && !audioInjector) {
Entities.deleteEntity(audioSphere);
audioSphere = null;
}
if (onHRTFScreen) {
sendToQml({ method: 'updateState', isPlaying: !!audioInjector });
}
// Change button to active when window is first opened OR if a sound is playing, false otherwise.
if (button) {
button.editProperties({ isActive: (onHRTFScreen || !!audioInjector) });
}
}
// Function Name: sendToQml()
//
// Description:
// -Use this function to send a message to the QML (i.e. to change appearances). The "message" argument is what is sent to
// the QML in the format "{method, params}", like json-rpc. See also fromQml().
function sendToQml(message) {
tablet.sendToQml(message);
}
var audioInjector;
var audioSphere;
var currentlyPlayingSound;
var currentPosition = MyAvatar.position;
function playCurrentSound() {
if (audioInjector) {
audioInjector.stop();
}
audioInjector = Audio.playSound(currentlyPlayingSound, {
position: currentPosition,
localOnly: false,
volume: 1.0,
loop: true
});
}
// Function Name: fromQml()
//
// Description:
// -Called when a message is received from the app's QML. The "message" argument is what is sent from the QML
// in the format "{method, params}", like json-rpc. See also sendToQml().
function fromQml(message) {
switch (message.method) {
case 'stopSounds':
currentlyPlayingSound = null;
if (audioInjector) {
audioInjector.stop();
audioInjector = null;
}
break;
case 'soundSelected':
if (message.soundID <= soundsArray.length) {
currentlyPlayingSound = soundsArray[message.soundID - 1];
playCurrentSound();
} else {
console.log("soundID out of range!");
}
break;
case 'positionSelected':
currentPosition = {
x: MyAvatar.position.x + message.x,
y: MyAvatar.position.y + message.y + 0.6,
z: MyAvatar.position.z + message.z
};
if (audioInjector) {
audioInjector.setOptions({
position: currentPosition,
localOnly: false,
volume: 1.0,
loop: true
});
}
if (audioSphere) {
Entities.editEntity(audioSphere, { position: currentPosition })
}
break;
default:
print('Unrecognized message from HRTF.qml:', JSON.stringify(message));
break;
}
}
// Function Name: shutdown()
//
// Description:
// -shutdown() will be called when the script ends (i.e. is stopped).
function shutdown() {
addOrRemoveButton(true);
if (audioInjector) {
audioInjector.stop();
audioInjector = null;
}
if (audioSphere) {
Entities.deleteEntity(audioSphere);
audioSphere = null;
}
if (tablet) {
tablet.screenChanged.disconnect(onTabletScreenChanged);
if (onHRTFScreen) {
tablet.gotoHomeScreen();
}
}
}
// These functions will be called when the script is loaded.
startup();
Script.scriptEnding.connect(shutdown);
}()); // END LOCAL_SCOPE