From 2f92a4cccdfde90b9ead3c86c0c77df9e864a645 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sat, 5 Mar 2016 00:45:25 -0800 Subject: [PATCH] first cut at music player --- .../createNewMusicPlayerOnClick.js | 100 ++++++ examples/toybox/musicPlayer/defaultImage.jpg | Bin 0 -> 58245 bytes examples/toybox/musicPlayer/imageShader.fs | 44 +++ examples/toybox/musicPlayer/musicPlayer.js | 328 ++++++++++++++++++ 4 files changed, 472 insertions(+) create mode 100644 examples/toybox/musicPlayer/createNewMusicPlayerOnClick.js create mode 100644 examples/toybox/musicPlayer/defaultImage.jpg create mode 100644 examples/toybox/musicPlayer/imageShader.fs create mode 100644 examples/toybox/musicPlayer/musicPlayer.js diff --git a/examples/toybox/musicPlayer/createNewMusicPlayerOnClick.js b/examples/toybox/musicPlayer/createNewMusicPlayerOnClick.js new file mode 100644 index 0000000000..68da1d2628 --- /dev/null +++ b/examples/toybox/musicPlayer/createNewMusicPlayerOnClick.js @@ -0,0 +1,100 @@ +// +// createNewMusicPlayerOnClick.js +// +// Created by Brad Hefta-Gaub on 3/3/16. +// Copyright 2016 High Fidelity, Inc. +// +// Entity Script that you can attach to any entity to have it spawn new "music players" +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +(function(){ + + var musicPlayerScript = Script.resolvePath("./musicPlayer.js"); + var imageShader = Script.resolvePath("./imageShader.fs"); + var defaultImage = Script.resolvePath("./defaultImage.jpg"); + + function getPositionToCreateEntity() { + var distance = 0.5; + var direction = Quat.getFront(Camera.orientation); + var offset = Vec3.multiply(distance, direction); + var placementPosition = Vec3.sum(Camera.position, offset); + + var cameraPosition = Camera.position; + + var HALF_TREE_SCALE = 16384; + + var cameraOutOfBounds = Math.abs(cameraPosition.x) > HALF_TREE_SCALE || Math.abs(cameraPosition.y) > HALF_TREE_SCALE || Math.abs(cameraPosition.z) > HALF_TREE_SCALE; + var placementOutOfBounds = Math.abs(placementPosition.x) > HALF_TREE_SCALE || Math.abs(placementPosition.y) > HALF_TREE_SCALE || Math.abs(placementPosition.z) > HALF_TREE_SCALE; + + if (cameraOutOfBounds && placementOutOfBounds) { + return null; + } + + placementPosition.x = Math.min(HALF_TREE_SCALE, Math.max(-HALF_TREE_SCALE, placementPosition.x)); + placementPosition.y = Math.min(HALF_TREE_SCALE, Math.max(-HALF_TREE_SCALE, placementPosition.y)); + placementPosition.z = Math.min(HALF_TREE_SCALE, Math.max(-HALF_TREE_SCALE, placementPosition.z)); + + return placementPosition; + } + + function createNewIPOD() { + var iPodPosition = { x: 0, y: .5, z: 0}; + var iPodDimensions = { x: 0.15, y: 0.3, z: 0.03 }; + var overlayDimensions = { x: 0.13, y: 0.13, z: 0.001 }; + var boxOverlayDimensions = { x: 0.13, y: 0.13, z: 0.0001 }; + + var iPodID = Entities.addEntity({ + type: "Box", + name: "music player", + position: iPodPosition, + dimensions: iPodDimensions, + color: { red: 150, green: 150, blue: 150}, + script: musicPlayerScript, + dynamic: true + }); + print(iPodID); + + var textID = Entities.addEntity({ + type: "Text", + name: "now playing", + position: { x: 0, y: (0.5+0.07), z: 0.0222}, + dimensions: overlayDimensions, + color: { red: 150, green: 150, blue: 150}, + parentID: iPodID, + lineHeight: 0.01, + text: "Pause" + }); + + + var newAlbumArt = JSON.stringify( + { + "ProceduralEntity": { + "version":2, + "shaderUrl":imageShader, + "uniforms":{"iSpeed":0,"iShell":1}, + "channels":[defaultImage] + } + }); + + + var albumArtID = Entities.addEntity({ + type: "Box", + name: "album art", + position: { x: 0, y: (0.5-0.07), z: 0.01506}, + dimensions: boxOverlayDimensions, + color: { red: 255, green: 255, blue: 255}, + userData: newAlbumArt, + parentID: iPodID + }); + Entities.editEntity(iPodID, { position: getPositionToCreateEntity() }); + } + + + this.clickDownOnEntity = function(myID, mouseEvent) { + createNewIPOD(); + }; +}) + + diff --git a/examples/toybox/musicPlayer/defaultImage.jpg b/examples/toybox/musicPlayer/defaultImage.jpg new file mode 100644 index 0000000000000000000000000000000000000000..54de95bf42e2981ecdbdf187fbce2112d633cab2 GIT binary patch literal 58245 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 1.0) { + float offset = aspectCorrection - 1.0; + float halfOffset = offset / 2.0; + uv.y -= halfOffset; + uv.y *= aspectCorrection; + } else { + float offset = 1.0 - aspectCorrection; + float halfOffset = offset / 2.0; + uv.x -= halfOffset; + uv.x /= aspectCorrection; + } + + if (any(lessThan(uv, vec2(0.0)))) { + return vec3(0.0); + } + + if (any(greaterThan(uv, vec2(1.0)))) { + return vec3(0.0); + } + + vec4 color = texture(iChannel0, uv); + return color.rgb * max(0.5, sourceAspect) * max(0.9, fract(iWorldPosition.x)); +} + +float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) { + if (_position.z > -0.49) { + discard; + } + + specular = indexedTexture(); + return 1.0; +} \ No newline at end of file diff --git a/examples/toybox/musicPlayer/musicPlayer.js b/examples/toybox/musicPlayer/musicPlayer.js new file mode 100644 index 0000000000..674d9019d1 --- /dev/null +++ b/examples/toybox/musicPlayer/musicPlayer.js @@ -0,0 +1,328 @@ +// +// musicPlayer.js +// +// Created by Brad Hefta-Gaub on 3/3/16. +// Copyright 2016 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 + +/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */ + +(function() { + + var imageShader = Script.resolvePath("./imageShader.fs"); + var defaultImage = Script.resolvePath("./defaultImage.jpg"); + + var MAPPING_NAME = "com.highfidelity.musicPlayerEntity"; + + var SONG_VOLUME = 0.1; + var HEADPHONES_ATTACHMENT = { + modelURL: "https://s3.amazonaws.com/hifi-public/brad/musicplayer/headphones2-v2.fbx", + jointName: "Head", + translation: {"x": 0, "y": 0.19, "z": 0.06}, + rotation: {"x":0,"y":0.7071067690849304,"z":0.7071067690849304,"w":0}, + scale: 0.435, + isSoft: false + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Various helper functions... + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // Helper function for returning either a value, or the default value if the value is undefined. This is + // is handing in parsing JSON where you don't know if the values have been set or not. + function valueOrDefault(value, defaultValue) { + if (value !== undefined) { + return value; + } + return defaultValue; + } + + // return a random float between high and low + function randFloat(low, high) { + return low + Math.random() * (high - low); + } + + // wears an attachment on MyAvatar + function wearAttachment(attachment) { + MyAvatar.attach(attachment.modelURL, + attachment.jointName, + attachment.translation, + attachment.rotation, + attachment.scale, + attachment.isSoft); + } + + // un-wears an attachment from MyAvatar + function removeAttachment(attachment) { + var attachments = MyAvatar.attachmentData; + var i, l = attachments.length; + for (i = 0; i < l; i++) { + if (attachments[i].modelURL === attachment.modelURL) { + attachments.splice(i, 1); + MyAvatar.attachmentData = attachments; + break; + } + } + } + + var _this; + MusicPlayer = function() { + _this = this; + this.equipped = false; + }; + + MusicPlayer.prototype = { + preload: function(entityID) { + print("preload"); + //print("rotation:" + JSON.stringify(Quat.fromPitchYawRollDegrees(-90,180,0))); + this.entityID = entityID; + + // Get the entities userData property, to see if someone has overridden any of our default settings + var userDataText = Entities.getEntityProperties(entityID, ["userData"]).userData; + //print(userDataText); + var userData = {}; + if (userDataText !== "") { + //print("calling JSON.parse"); + userData = JSON.parse(userDataText); + //print("userData:" + JSON.stringify(userData)); + } + var musicPlayerUserData = valueOrDefault(userData.musicPlayer, {}); + this.headphonesAttachment = valueOrDefault(musicPlayerUserData.headphonesAttachment, HEADPHONES_ATTACHMENT); + + this.track = 0; // start at the first track + this.songVolume = valueOrDefault(musicPlayerUserData.songVolume, SONG_VOLUME); + this.songPlaying = false; + + this.loadPlayList(); + + // Find my screen and any controlls + var children = Entities.getChildrenIDsOfJoint(entityID, 65535); + for (var child in children) { + var childID = children[child]; + var childProperties = Entities.getEntityProperties(childID,["type", "name"]); + if (childProperties.type == "Text" && childProperties.name == "now playing") { + this.nowPlayingID = childID; + } + if (childProperties.type == "Box" && childProperties.name == "album art") { + this.albumArt = childID; + } + } + }, + + unload: function() { + print("unload"); + if (_this.songInjector !== undefined) { + _this.songInjector.stop(); + } + }, + + loadPlayList: function() { + print("loadPlayList"); + var req = new XMLHttpRequest(); + req.open("GET", "https://spreadsheets.google.com/feeds/cells/1x-ceGPGHldkHadARABFWfujLPTOWzXJPhrf2bTwg2cQ/od6/public/basic?alt=json", false); + req.send(); + + var entries = JSON.parse(req.responseText).feed.entry; + + for (entry in entries) { + var cellDetails = entries[entry]; + var cellName = cellDetails.title.$t; + var column = Number(cellName.charCodeAt(0)) - Number("A".charCodeAt(0)); + var row = Number(cellName.slice(1)) - 1; + var cellContent = cellDetails.content.$t; + //print(JSON.stringify(cellDetails)); + //print("["+column +"/"+ row +":"+cellContent+"]"); + if (_this.playList === undefined) { + _this.playList = new Array(); + } + if (_this.playList[row] === undefined) { + _this.playList[row] = { }; + } + switch (column) { + case 0: + _this.playList[row].title = cellContent; + break; + case 1: + _this.playList[row].artist = cellContent; + break; + case 2: + _this.playList[row].album = cellContent; + break; + case 3: + _this.playList[row].url = cellContent; + _this.playList[row].sound = SoundCache.getSound(cellContent); + break; + case 4: + _this.playList[row].albumArtURL = cellContent; + break; + } + } + //print(req.responseText); + print(JSON.stringify(_this.playList)); + }, + + startEquip: function(id, params) { + var whichHand = params[0]; // "left" or "right" + print("I am equipped in the " + whichHand + " hand...."); + this.equipped = true; + this.hand = whichHand; + + this.loadPlayList(); // reload the playlist in case... + + this.mapHandButtons(whichHand); + wearAttachment(HEADPHONES_ATTACHMENT); + }, + + continueEquip: function(id, params) { + if (!this.equipped) { + return; + } + }, + releaseEquip: function(id, params) { + print("I am NO LONGER equipped...."); + this.hand = null; + this.equipped = false; + Controller.disableMapping(MAPPING_NAME); + removeAttachment(HEADPHONES_ATTACHMENT); + this.pause(); + }, + + mapHandButtons: function(hand) { + var mapping = Controller.newMapping(MAPPING_NAME); + if (hand === "left") { + mapping.from(Controller.Standard.LS).peek().to(this.playOrPause); + mapping.from(Controller.Standard.LX).peek().to(this.seek); + mapping.from(Controller.Standard.LY).peek().to(this.volume); + } else { + mapping.from(Controller.Standard.RS).peek().to(this.playOrPause); + mapping.from(Controller.Standard.RX).peek().to(this.seek); + mapping.from(Controller.Standard.RY).peek().to(this.volume); + } + Controller.enableMapping(MAPPING_NAME); + }, + + playOrPause: function(value) { + print("[playOrPause: "+value+"]"); + if (value === 1) { + if (!_this.songPlaying) { + _this.play(); + } else { + _this.pause(); + } + } + }, + + play: function() { + print("play current track:" + _this.track); + if (!_this.playList[_this.track].sound.downloaded) { + print("still waiting on track to download...."); + return; // not yet ready + } + + var statusText = "Song:" + _this.playList[_this.track].title + "\n" + + "Artist:" + _this.playList[_this.track].artist + "\n" + + "Album:" + _this.playList[_this.track].album; + + Entities.editEntity(_this.nowPlayingID, { text: statusText }); + + var newAlbumArt = JSON.stringify( + { + "ProceduralEntity": { + "version":2, + "shaderUrl":imageShader, + "uniforms":{"iSpeed":0,"iShell":1}, + "channels":[_this.playList[_this.track].albumArtURL] + } + }); + + Entities.editEntity(_this.albumArt, { userData: newAlbumArt }); + + + _this.songInjector = Audio.playSound(_this.playList[_this.track].sound, { + position: MyAvatar.position, + volume: _this.songVolume, + loop: false, + localOnly: true + }); + _this.songPlaying = true; + }, + + pause: function() { + print("pause"); + Entities.editEntity(_this.nowPlayingID, { text: "Paused" }); + if (_this.songInjector !== undefined) { + _this.songInjector.stop(); + } + var newAlbumArt = JSON.stringify( + { + "ProceduralEntity": { + "version":2, + "shaderUrl":imageShader, + "uniforms":{"iSpeed":0,"iShell":1}, + "channels":[defaultImage] + } + }); + + Entities.editEntity(_this.albumArt, { userData: newAlbumArt }); + + + _this.songPlaying = false; + }, + + seek: function(value) { + print("[seek: " + value + "]"); + if (value > 0.9) { + _this.next(); + } else if (value < -0.9) { + _this.previous(); + } + }, + + volume: function(value) { + print("adjusting volume disabled because of a bug in audio injectors...."); + /* + var scaledValue = value / 20; + _this.songVolume += scaledValue; + print("[volume: " + value + "] new volume:" + _this.songVolume); + if (_this.songInjector !== undefined) { + print("[volume: attempting to set options...."); + var newOptions = { + position: MyAvatar.position, + volume: _this.songVolume, + loop: false, + localOnly: true + }; + + _this.songInjector.options = newOptions; + print("[volume: attempting to set options.... RESULT:" + JSON.stringify(_this.songInjector.options)); + } + */ + }, + + previous: function() { + print("[previous]"); + _this.pause(); + _this.track--; + if (_this.track < 0) { + _this.track = (_this.playList.length - 1); + } + _this.play(); + }, + + next: function() { + print("[next]"); + _this.pause(); + _this.track++; + if (_this.track >= _this.playList.length) { + _this.track = 0; + } + _this.play(); + }, + + }; + + // entity scripts always need to return a newly constructed object of our type + return new MusicPlayer(); +});