From 7b88deef16e07a83f7dd2c560cb7ed95aeb2b2c5 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 13 Jan 2015 22:08:35 +0100 Subject: [PATCH 1/3] Implement UI sounds for virtualKeyboard & notifications --- examples/controllers/oculus/goTo.js | 10 +- .../virtualKeyboardTextEntityExample.js | 10 +- examples/libraries/soundArray.js | 40 ++++++ examples/notifications.js | 135 +++++++++--------- 4 files changed, 128 insertions(+), 67 deletions(-) create mode 100644 examples/libraries/soundArray.js diff --git a/examples/controllers/oculus/goTo.js b/examples/controllers/oculus/goTo.js index ba1ee1eb81..f3db99493d 100644 --- a/examples/controllers/oculus/goTo.js +++ b/examples/controllers/oculus/goTo.js @@ -18,6 +18,7 @@ Script.include("../../libraries/globals.js"); Script.include("../../libraries/virtualKeyboard.js"); +Script.include("../../libraries/soundArray.js"); var windowDimensions = Controller.getViewportDimensions(); var cursor = null; @@ -26,6 +27,12 @@ var textFontSize = 9; var text = null; var locationURL = ""; +var randomSounds = new SoundArray({}, true); +var numberOfSounds = 7; +for (var i = 1; i <= numberOfSounds; i++) { + randomSounds.addSound(HIFI_PUBLIC_BUCKET + "sounds/UI/virtualKeyboard-press" + i + ".raw"); +} + function appendChar(char) { locationURL += char; updateTextOverlay(); @@ -51,6 +58,7 @@ function updateTextOverlay() { } keyboard.onKeyPress = function(event) { + randomSounds.playRandom(); if (event.event == 'keypress') { appendChar(event.char); } @@ -66,7 +74,7 @@ keyboard.onKeyRelease = function(event) { print("going to hifi://" + locationURL); location = "hifi://" + locationURL; locationURL = ""; - keyboard.hide(); + keyboard.hide(); updateTextOverlay(); } } diff --git a/examples/controllers/oculus/virtualKeyboardTextEntityExample.js b/examples/controllers/oculus/virtualKeyboardTextEntityExample.js index 794b659bcb..3c201cb307 100644 --- a/examples/controllers/oculus/virtualKeyboardTextEntityExample.js +++ b/examples/controllers/oculus/virtualKeyboardTextEntityExample.js @@ -17,6 +17,7 @@ Script.include("../../libraries/globals.js"); Script.include("../../libraries/virtualKeyboard.js"); +Script.include("../../libraries/soundArray.js"); const SPAWN_DISTANCE = 1; const DEFAULT_TEXT_DIMENSION_Z = 0.02; @@ -34,6 +35,12 @@ var text = null; var textText = ""; var textSizeMeasureOverlay = Overlays.addOverlay("text3d", {visible: false}); +var randomSounds = new SoundArray({}, true); +var numberOfSounds = 7; +for (var i = 1; i <= numberOfSounds; i++) { + randomSounds.addSound(HIFI_PUBLIC_BUCKET + "sounds/UI/virtualKeyboard-press" + i + ".raw"); +} + function appendChar(char) { textText += char; updateTextOverlay(); @@ -58,6 +65,7 @@ function updateTextOverlay() { } keyboard.onKeyPress = function(event) { + randomSounds.playRandom(); if (event.event == 'keypress') { appendChar(event.char); } else if (event.event == 'enter') { @@ -100,7 +108,7 @@ keyboard.onKeyRelease = function(event) { backgroundColor: { red: 0, green: 0, blue: 0 }, textColor: { red: 255, green: 255, blue: 255 }, text: textText + "\n" + usernameLine, - lineHeight: 0.1 + lineHeight: 0.1 }); } textText = ""; diff --git a/examples/libraries/soundArray.js b/examples/libraries/soundArray.js new file mode 100644 index 0000000000..0da2db07d3 --- /dev/null +++ b/examples/libraries/soundArray.js @@ -0,0 +1,40 @@ +/** + * An array for sounds, allows you to randomly play a sound + * taken from the removed editVoxels.js + */ +SoundArray = function(audioOptions, autoUpdateAudioPosition) { + this.audioOptions = audioOptions !== undefined ? audioOptions : {}; + this.autoUpdateAudioPosition = autoUpdateAudioPosition !== undefined ? autoUpdateAudioPosition : false; + if (this.audioOptions.position === undefined) { + this.audioOptions.position = Vec3.sum(MyAvatar.position, { x: 0, y: 1, z: 0}), + } + if (this.audioOptions.volume === undefined) { + this.audioOptions.volume = 1.0; + } + this.sounds = new Array(); + this.addSound = function (soundURL) { + this.sounds[this.sounds.length] = SoundCache.getSound(soundURL); + }; + this.play = function (index) { + if (0 <= index && index < this.sounds.length) { + if (this.autoUpdateAudioPosition) { + this.updateAudioPosition(); + } + Audio.playSound(this.sounds[index], this.audioOptions); + } else { + print("[ERROR] libraries/soundArray.js:play() : Index " + index + " out of range."); + } + }; + this.playRandom = function () { + if (this.sounds.length > 0) { + this.play(Math.floor(Math.random() * this.sounds.length)); + } else { + print("[ERROR] libraries/soundArray.js:playRandom() : Array is empty."); + } + }; + this.updateAudioPosition = function() { + var position = MyAvatar.position; + var forwardVector = Quat.getFront(MyAvatar.orientation); + this.audioOptions.position = Vec3.sum(position, forwardVector); + }; +}; diff --git a/examples/notifications.js b/examples/notifications.js index 5527fc35fc..2449873f27 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -1,13 +1,13 @@ -// -// notifications.js -// Version 0.801 -// Created by Adrian +// +// notifications.js +// Version 0.801 +// Created by Adrian // // Adrian McCarlie 8-10-14 // This script demonstrates on-screen overlay type notifications. // Copyright 2014 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 @@ -20,29 +20,29 @@ // CTRL/m for mic mute and unmute. // System generated notifications: -// Displays users online at startup. +// Displays users online at startup. // If Screen is resized. // Triggers notification if @MyUserName is mentioned in chat. // Announces existing user logging out. // Announces new user logging in. // If mic is muted for any reason. -// +// // To add a new System notification type: // -// 1. Set the Event Connector at the bottom of the script. -// example: +// 1. Set the Event Connector at the bottom of the script. +// example: // GlobalServices.incomingMessage.connect(onIncomingMessage); // -// 2. Create a new function to produce a text string, do not include new line returns. +// 2. Create a new function to produce a text string, do not include new line returns. // example: // function onIncomingMessage(user, message) { -// //do stuff here; +// //do stuff here; // var text = "This is a notification"; // wordWrap(text); // } // // This new function must call wordWrap(text) if the length of message is longer than 42 chars or unknown. -// wordWrap() will format the text to fit the notifications overlay and send it to createNotification(text). +// wordWrap() will format the text to fit the notifications overlay and send it to createNotification(text). // If the message is 42 chars or less you should bypass wordWrap() and call createNotification() directly. @@ -53,37 +53,44 @@ // 3. Call createNotifications(text) parsing the text. // example: // if (key.text == "q") { //queries number of users online -// var numUsers = GlobalServices.onlineUsers.length; -// var welcome = "There are " + numUsers + " users online now."; -// createNotification(welcome); +// var numUsers = GlobalServices.onlineUsers.length; +// var welcome = "There are " + numUsers + " users online now."; +// createNotification(welcome); // } - +Script.include("./libraries/globals.js"); +Script.include("./libraries/soundArray.js"); var width = 340.0; //width of notification overlay var height = 40.0; // height of a single line notification overlay var windowDimensions = Controller.getViewportDimensions(); // get the size of the interface window var overlayLocationX = (windowDimensions.x - (width + 20.0));// positions window 20px from the right of the interface window -var buttonLocationX = overlayLocationX + (width - 28.0); +var buttonLocationX = overlayLocationX + (width - 28.0); var locationY = 20.0; // position down from top of interface window var topMargin = 13.0; var leftMargin = 10.0; var textColor = { red: 228, green: 228, blue: 228}; // text color -var backColor = { red: 2, green: 2, blue: 2}; // background color was 38,38,38 +var backColor = { red: 2, green: 2, blue: 2}; // background color was 38,38,38 var backgroundAlpha = 0; var fontSize = 12.0; var persistTime = 10.0; // time in seconds before notification fades var clickedText = false; var frame = 0; -var ourWidth = Window.innerWidth; -var ourHeight = Window.innerHeight; +var ourWidth = Window.innerWidth; +var ourHeight = Window.innerHeight; var text = "placeholder"; var last_users = GlobalServices.onlineUsers; var users = []; var ctrlIsPressed = false; var ready = true; - + +var randomSounds = new SoundArray({}, true); +var numberOfSounds = 2; +for (var i = 1; i <= numberOfSounds; i++) { + randomSounds.addSound(HIFI_PUBLIC_BUCKET + "sounds/UI/notification-general" + i + ".raw"); +} + // When our script shuts down, we should clean up all of our overlays -function scriptEnding() { +function scriptEnding() { for (i = 0; i < notifications.length; i++) { Overlays.deleteOverlay(notifications[i]); Overlays.deleteOverlay(buttons[i]); @@ -92,7 +99,7 @@ function scriptEnding() { Script.scriptEnding.connect(scriptEnding); var notifications = []; -var buttons = []; +var buttons = []; var times = []; var heights = []; var myAlpha = []; @@ -117,7 +124,7 @@ function createNotification(text) { height = height + extraLine; var overlayProperties = { x: overlayLocationX, - y: level, + y: level, width: width, height: height, color: textColor, @@ -126,10 +133,10 @@ function createNotification(text) { topMargin: topMargin, leftMargin: leftMargin, font: {size: fontSize}, - text: text, + text: text, }; var bLevel = level + 12.0; - var buttonProperties = { + var buttonProperties = { x: buttonLocationX, y: bLevel, width: 10.0, @@ -139,17 +146,15 @@ function createNotification(text) { color: { red: 255, green: 255, blue: 255}, visible: true, alpha: backgroundAlpha, - }; - - Notify(overlayProperties, buttonProperties, height); - + }; + Notify(overlayProperties, buttonProperties, height); } -// Pushes data to each array and sets up data for 2nd dimension array +// Pushes data to each array and sets up data for 2nd dimension array // to handle auxiliary data not carried by the overlay class -// specifically notification "heights", "times" of creation, and . -function Notify(notice, button, height){ - +// specifically notification "heights", "times" of creation, and . +function Notify(notice, button, height){ + randomSounds.playRandom(); notifications.push((Overlays.addOverlay("text", notice))); buttons.push((Overlays.addOverlay("image",button))); times.push(new Date().getTime() / 1000); @@ -162,14 +167,14 @@ function Notify(notice, button, height){ } function fadeIn(noticeIn, buttonIn) { - var myLength = arrays.length; + var myLength = arrays.length; var q = 0; var pauseTimer = null; - pauseTimer = Script.setInterval(function() { + pauseTimer = Script.setInterval(function() { q++; qFade = q / 10.0; - Overlays.editOverlay(noticeIn, {alpha: qFade}); - Overlays.editOverlay(buttonIn, {alpha: qFade}); + Overlays.editOverlay(noticeIn, {alpha: qFade}); + Overlays.editOverlay(buttonIn, {alpha: qFade}); if (q >= 9.0) { Script.clearInterval(pauseTimer); } @@ -178,11 +183,11 @@ function fadeIn(noticeIn, buttonIn) { // push data from above to the 2 dimensional array -function createArrays(notice, button, createTime, height, myAlpha) { - arrays.push([notice, button, createTime, height, myAlpha]); +function createArrays(notice, button, createTime, height, myAlpha) { + arrays.push([notice, button, createTime, height, myAlpha]); } // handles mouse clicks on buttons -function mousePressEvent(event) { +function mousePressEvent(event) { var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); //identify which overlay was clicked for (i = 0; i < buttons.length; i++) { //if user clicked a button if(clickedOverlay == buttons[i]) { @@ -192,10 +197,10 @@ function mousePressEvent(event) { buttons.splice(i, 1); times.splice(i, 1); heights.splice(i, 1); - myAlpha.splice(i, 1); + myAlpha.splice(i, 1); arrays.splice(i, 1); } - } + } } // Control key remains active only while key is held down @@ -204,19 +209,19 @@ function keyReleaseEvent(key) { ctrlIsPressed = false; } } - + // Triggers notification on specific key driven events function keyPressEvent(key) { if (key.key == 16777249) { ctrlIsPressed = true; } if (key.text == "q") { //queries number of users online - var numUsers = GlobalServices.onlineUsers.length; - var welcome = "There are " + numUsers + " users online now."; - createNotification(welcome); - } + var numUsers = GlobalServices.onlineUsers.length; + var welcome = "There are " + numUsers + " users online now."; + createNotification(welcome); + } - if (key.text == "s") { + if (key.text == "s") { if (ctrlIsPressed == true){ var noteString = "Snapshot taken."; createNotification(noteString); @@ -241,7 +246,7 @@ function stringDivider(str, slotWidth, spaceReplacer) { return left + spaceReplacer + stringDivider(right, slotWidth, spaceReplacer); } } - return str; + return str; } // This fires a notification on window resize @@ -249,7 +254,7 @@ function checkSize(){ if((Window.innerWidth != ourWidth)||(Window.innerHeight != ourHeight)) { var windowResize = "Window has been resized"; ourWidth = Window.innerWidth; - ourHeight = Window.innerHeight; + ourHeight = Window.innerHeight; windowDimensions = Controller.getViewportDimensions(); overlayLocationX = (windowDimensions.x - (width + 60.0)); buttonLocationX = overlayLocationX + (width - 35.0); @@ -261,12 +266,12 @@ function checkSize(){ function onOnlineUsersChanged(users) { for (user in users) { if (last_users.indexOf(users[user]) == -1.0) { - createNotification(users[user] + " has joined"); + createNotification(users[user] + " has joined"); } } for (user in last_users) { if (users.indexOf(last_users[user]) == -1.0) { - createNotification(last_users[user] + " has left"); + createNotification(last_users[user] + " has left"); } } last_users = users; @@ -294,7 +299,7 @@ function update(){ checkSize(); // checks for size change to trigger windowResize notification locationY = 20.0; for (var i = 0; i < arrays.length; i++) { //repositions overlays as others fade - var nextOverlay = Overlays.getOverlayAtPoint({x: overlayLocationX, y: locationY}); + var nextOverlay = Overlays.getOverlayAtPoint({x: overlayLocationX, y: locationY}); Overlays.editOverlay(notifications[i], { x:overlayLocationX, y:locationY}); Overlays.editOverlay(buttons[i], { x:buttonLocationX, y:locationY + 12.0}); locationY = locationY + arrays[i][3]; @@ -302,12 +307,12 @@ function update(){ } // This checks the age of the notification and prepares to fade it after 9.0 seconds (var persistTime - 1) - for (var i = 0; i < arrays.length; i++) { - if (ready){ - var j = arrays[i][2]; - var k = j + persistTime; + for (var i = 0; i < arrays.length; i++) { + if (ready) { + var j = arrays[i][2]; + var k = j + persistTime; if (k < (new Date().getTime() / 1000)) { - ready = false; + ready = false; noticeOut = arrays[i][0]; buttonOut = arrays[i][1]; var arraysOut = i; @@ -322,11 +327,11 @@ function fadeOut(noticeOut, buttonOut, arraysOut) { var myLength = arrays.length; var r = 9.0; var pauseTimer = null; - pauseTimer = Script.setInterval(function() { + pauseTimer = Script.setInterval(function() { r--; - rFade = r / 10.0; - Overlays.editOverlay(noticeOut, {alpha: rFade}); - Overlays.editOverlay(buttonOut, {alpha: rFade}); + rFade = r / 10.0; + Overlays.editOverlay(noticeOut, {alpha: rFade}); + Overlays.editOverlay(buttonOut, {alpha: rFade}); if (r < 0) { dismiss(noticeOut, buttonOut, arraysOut); arrays.splice(arraysOut, 1); @@ -337,8 +342,8 @@ function fadeOut(noticeOut, buttonOut, arraysOut) { } // This handles the final dismissal of a notification after fading -function dismiss(firstNoteOut, firstButOut, firstOut) { - var working = firstOut +function dismiss(firstNoteOut, firstButOut, firstOut) { + var working = firstOut; Overlays.deleteOverlay(firstNoteOut); Overlays.deleteOverlay(firstButOut); notifications.splice(firstOut, 1); From 96b3114a36a63ff99c6193bb6e41da140ddfdeb1 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 17 Feb 2015 23:37:37 +0100 Subject: [PATCH 2/3] style --- examples/notifications.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/notifications.js b/examples/notifications.js index 88198a2ea1..287bfd0b36 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -474,7 +474,6 @@ function onOnlineUsersChanged(users) { if (last_users.indexOf(users[i]) === -1.0) { createNotification(users[i] + " has joined"); } - } for (i = 0; i < last_users.length; i += 1) { From d10f37291b3703a7ece68d3d88e099ab47f4fee9 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 18 Feb 2015 18:25:16 +0100 Subject: [PATCH 3/3] check if sounds are downloaded before play thanks @Atlante45 --- examples/libraries/soundArray.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/libraries/soundArray.js b/examples/libraries/soundArray.js index 0da2db07d3..813621fb4b 100644 --- a/examples/libraries/soundArray.js +++ b/examples/libraries/soundArray.js @@ -20,7 +20,9 @@ SoundArray = function(audioOptions, autoUpdateAudioPosition) { if (this.autoUpdateAudioPosition) { this.updateAudioPosition(); } - Audio.playSound(this.sounds[index], this.audioOptions); + if (this.sounds[index].downloaded) { + Audio.playSound(this.sounds[index], this.audioOptions); + } } else { print("[ERROR] libraries/soundArray.js:play() : Index " + index + " out of range."); }