Skip to content

Commit

Permalink
adding a music-player component
Browse files Browse the repository at this point in the history
  • Loading branch information
stemkoski committed Feb 21, 2022
1 parent 418e09e commit b0f1023
Show file tree
Hide file tree
Showing 10 changed files with 367 additions and 0 deletions.
Binary file added music/ChauSara/Mando.mp3
Binary file not shown.
Binary file added music/ChauSara/image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions music/ChauSara/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Artist: Chau Sara
Song: Mando
Music provided by LoFi Girl
Binary file added music/Khutko/Violet.mp3
Binary file not shown.
Binary file added music/Khutko/image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions music/Khutko/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Artist: Khutko
Song: Violet
Music provided by LoFi Girl
Binary file added music/Osaki/Reflections.mp3
Binary file not shown.
Binary file added music/Osaki/image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions music/Osaki/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Artist: Osaki
Song: Reflections
Music provided by LoFi Girl
358 changes: 358 additions & 0 deletions quest-music.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,358 @@
<!DOCTYPE html>
<html>

<head>
<title>A-Frame: Music Player</title>
<meta name="description" content="Creating a music player that interacts with Quest touch controllers.">
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<script src="js/aframe-environment-component.js"></script>
<script src="js/controller-listener.js"></script>
<script src="js/player-move.js"></script>
<script src="js/raycaster-graphics.js"></script>
<script src="js/raycaster-controller-grabber.js"></script>
</head>

<body>

<script>

// uses other custom components: raycaster-graphics, raycaster-controller-grabber
AFRAME.registerComponent("music-player", {
init: function ()
{
// set up the physical entity
this.base = document.createElement("a-entity");
this.base.setAttribute("geometry",
{ primitive: "box", width: 2.0, height: 1.60, depth: 0.04 } );
this.base.setAttribute("material", {color: "#CCCCCC"});
this.base.setAttribute("class", "raycaster-target grabbable" );
// add component
this.el.setAttribute("sound", {positional: false, volume: 0.50});
this.el.appendChild(this.base);

// add a box to serve as border
let baseBorder = document.createElement("a-entity");
baseBorder.setAttribute("geometry",
{ primitive: "box", width: 2.2, height: 1.8, depth: 0.04 } );
baseBorder.setAttribute("material", "color", "black");
baseBorder.setAttribute("position", "0 0 -0.01");
baseBorder.setAttribute("class", "raycaster-target" );
this.base.appendChild(baseBorder);

// add another box to frame button controls
let buttonBase = document.createElement("a-entity");
buttonBase.setAttribute("geometry",
{ primitive: "box", width: 1.999, height: 0.20, depth: 0.04 } );
buttonBase.setAttribute("material", {color: "#444444"});
buttonBase.setAttribute("class", "raycaster-target" );
buttonBase.setAttribute("position", {x: 0, y: -0.70, z: 0.01});
this.base.appendChild(buttonBase);

function initButton(materialSrc, posX, posY, posZ)
{
let button = document.createElement("a-entity");
button.setAttribute("geometry",
{ primitive: "box", width: 0.16, height: 0.16, depth: 0.04 } );
button.setAttribute("material", "color", "#EEEEEE");
button.setAttribute("material", "src", materialSrc);
button.setAttribute("position", {x: posX, y: posY, z: posZ});
button.setAttribute("class", "raycaster-target");
button.setAttribute("raycaster-hover", "");
return button;
}

this.previousButton = initButton("#iconPrevious", -0.90, 0, 0.01);
buttonBase.appendChild( this.previousButton );

this.replayButton = initButton("#iconReplay", -0.70, 0, 0.01);
buttonBase.appendChild( this.replayButton );

this.playButton = initButton("#iconPlay", -0.50, 0, 0.01);
buttonBase.appendChild( this.playButton );

this.nextButton = initButton("#iconNext", -0.30, 0, 0.01);
buttonBase.appendChild( this.nextButton );

this.volumeUpButton = initButton("#iconVolumeUp", 0.90, 0, 0.01);
buttonBase.appendChild( this.volumeUpButton );

this.volumeDownButton = initButton("#iconVolumeDown", 0.70, 0, 0.01);
buttonBase.appendChild( this.volumeDownButton );

// create text area to display music information
this.textArea = document.createElement("a-entity");
this.textArea.setAttribute("geometry",
{ primitive: "plane", width: 2, height: 0.2 } );
this.textArea.setAttribute("material",
{ color: "#000000" } );
this.textArea.setAttribute("text",
{ anchor: "center", baseline: "center", wrapCount: 40,
color: "#8888FF", value: "" } );
this.textArea.setAttribute("position", {x: 0, y: -0.50, z: 0.03});
this.base.appendChild(this.textArea);

// create area to display image art
this.imageArea = document.createElement("a-entity");
this.imageArea.setAttribute("geometry",
{ primitive: "plane", width: 2, height: 1.2 } );
// adding some emission so image can be seen more easily
this.textArea.setAttribute("material", { emission: "#222222" } );
// images should be approximately 900 x 500
this.imageArea.setAttribute("position", {x: 0, y: 0.20, z: 0.04});
this.base.appendChild(this.imageArea);

// this.imageArea.setAttribute("material", "src", "url(music/ChauSara/image.jpg)");

this.rightController = document.querySelector("#right-controller-entity");

let self = this;

this.el.addEventListener("sound-loaded", function(event)
{
// change "loading music..." to song name
self.textArea.setAttribute("text", "value",
self.musicDataList[self.musicDataIndex].songText );
self.playButton.setAttribute("material", "src", "#iconPlay");
self.buttonIcon = "play";
}
);

this.el.addEventListener("sound-ended", function(event)
{
self.playButton.setAttribute("material", "src", "#iconPlay");
self.buttonIcon = "play";
}
);

// TODO: manage this with a schema
this.musicDataList = [];
this.addMusicData("music/ChauSara/Mando.mp3",
"music/ChauSara/image.jpg",
"Artist: Chau Sara --- Song: Mondo \n (music provided by Lofi Girl)" );
this.addMusicData("music/Osaki/Reflections.mp3",
"music/Osaki/image.jpg",
"Artist: Osaki --- Song: Reflections \n (music provided by Lofi Girl)" );
this.addMusicData("music/Khutko/Violet.mp3",
"music/Khutko/image.jpg",
"Artist: Khutko --- Song: Violet \n (music provided by Lofi Girl)" );
this.musicDataIndex = 0;
this.buttonIcon = "wait";
this.loadMusic( this.musicDataIndex );
},

addMusicData: function(audioURL, imageURL, songText)
{
let musicData = {"audioURL": audioURL, "imageURL": imageURL, "songText": songText};
this.musicDataList.push( musicData );
},

loadMusic: function(index)
{
this.imageArea.setAttribute("material", "src",
"url(" + this.musicDataList[index].imageURL + ")" );

this.el.setAttribute("sound", "src",
"url(" + this.musicDataList[index].audioURL + ")" );

// while loading music:
this.textArea.setAttribute("text", "value", "music loading...");

// change play button icon to Wait
this.playButton.setAttribute("material", "src", "#iconWait");
this.buttonIcon = "wait";

// used by event listener
this.musicDataIndex = index;
},

tick: function()
{
this.rightData = this.rightController.components["controller-listener"];

if (this.rightData.trigger.pressed)
{
// determine which button was clicked (if any)
if ( this.playButton.components["raycaster-hover"].data.hasFocus )
{
if ( this.buttonIcon == "play" )
{
this.el.components["sound"].playSound();
this.playButton.setAttribute("material", "src", "#iconPause");
this.buttonIcon = "pause";
}
else if ( this.buttonIcon == "pause" )
{
this.el.components["sound"].pauseSound();
this.playButton.setAttribute("material", "src", "#iconPlay");
this.buttonIcon = "play";
}
else if ( this.buttonIcon == "wait" )
{
// just wait patiently.
}
}
else if ( this.replayButton.components["raycaster-hover"].data.hasFocus )
{
this.el.components["sound"].stopSound();
this.el.components["sound"].playSound();
this.playButton.setAttribute("material", "src", "#iconPause");
this.buttonIcon = "pause";
}
else if ( this.nextButton.components["raycaster-hover"].data.hasFocus )
{
this.el.components["sound"].stopSound();
this.musicDataIndex++;
if (this.musicDataIndex == this.musicDataList.length)
this.musicDataIndex = 0;
this.loadMusic( this.musicDataIndex );
}
else if ( this.previousButton.components["raycaster-hover"].data.hasFocus )
{
this.el.components["sound"].stopSound();
this.musicDataIndex--;
if (this.musicDataIndex == -1)
this.musicDataIndex = this.musicDataList.length - 1;
this.loadMusic( this.musicDataIndex );
}
else if ( this.volumeDownButton.components["raycaster-hover"].data.hasFocus )
{
let volume = this.el.getAttribute("sound").volume;
if (volume >= 0.10)
volume -= 0.10;
this.el.setAttribute("sound", "volume", volume);
}
else if ( this.volumeUpButton.components["raycaster-hover"].data.hasFocus )
{
let volume = this.el.getAttribute("sound").volume;
if (volume <= 0.90)
volume += 0.10;
this.el.setAttribute("sound", "volume", volume);
}
}

} // end of tick()

});


</script>

<a-scene environment="preset: default;" renderer="antialias: true;">

<a-assets>
<img id="gradient" src="images/gradient-fade.png" />
<!-- icons used by music-player component -->
<img id="iconBlank" src="images/icon-blank.jpg" />
<img id="iconWait" src="images/icon-wait.jpg" />
<img id="iconPlay" src="images/icon-play.jpg" />
<img id="iconPause" src="images/icon-pause.jpg" />
<img id="iconNext" src="images/icon-next.jpg" />
<img id="iconPrevious" src="images/icon-previous.jpg" />
<img id="iconReplay" src="images/icon-replay.jpg" />
<img id="iconVolumeUp" src="images/icon-volume-up.jpg" />
<img id="iconVolumeDown" src="images/icon-volume-down.jpg" />
</a-assets>

<a-sky
color = "#001337">
</a-sky>

<!-- player entity -->
<a-entity id="player" position="0 0 0" player-move>

<a-camera></a-camera>

<a-entity
visible="true"
id="left-controller-entity"
oculus-touch-controls="hand: left"
controller-listener="hand: left">
</a-entity>

<a-entity
visible="true"
id="right-controller-entity"
laser-controls="hand: right"
raycaster="objects: .raycaster-target, .environmentGround;"
raycaster-graphics="beamImageSrc: #gradient; beamLength: 1;"
raycaster-controller-grabber
controller-listener="hand: right">
</a-entity>

</a-entity>

<a-entity
position = "0 1 -2"
scale = "0.5 0.5 0.5"
music-player>
</a-entity>

<a-torus-knot
p="2" q="3" radius="0.5" radius-tubular="0.1"
position = "-2.5 1.5 -4"
color="#CC3333"
class="raycaster-target"
raycaster-hover>
</a-torus-knot>

<a-box
width = "2" height = "1" depth = "1"
position = "-1 0.5 -3"
rotation = "0 45 0"
color = "#FF8800"
class="raycaster-target"
raycaster-hover>
</a-box>

<a-sphere
radius = "1.25"
position = "0 1.25 -5"
color = "#DDBB00"
class="raycaster-target"
raycaster-hover>
</a-sphere>

<a-cylinder
radius = "0.5" height = "1.5"
position = " 1 0.75 -3"
color = "#008800"
class="raycaster-target"
raycaster-hover>
</a-cylinder>

<a-cone
radius-bottom = "1" radius-top = "0" height = "2"
position = "3 1 -4"
color = "#4444CC"
class="raycaster-target"
raycaster-hover>
</a-cone>

<a-torus
radius="0.5" radius-tubular="0.1"
position = "2 3 -4"
rotation = "30 -20 0"
color="#8800FF"
class="raycaster-target"
raycaster-hover>
</a-torus>

<!-- demo interaction boxes -->

<!--
<a-entity
id="textArea"
position="0 1.5 -1.9"
geometry="primitive: plane; width: 3; height: auto"
material="color: #444444; transparent: true; opacity: 0.80;"
text="anchor: center; baseline: center; wrapCount: 40;
transparent: true; opacity: 0.90; color: #8888FF;
value: \n Debug messages here. \n"
>
</a-entity>
-->

</a-scene>

</body>
</html>

0 comments on commit b0f1023

Please sign in to comment.