Code viewer for World: Sampler

// Cloned by Enhanced on 19 Jul 2018 from World "Sampler" by Mathias Bazin 
// Please leave this clone trail here.
 

AB.drawRunControls = false;


const audiofiles = [
        "/uploads/mathias/clap.wav",
        "/uploads/mathias/crash.wav",
        "/uploads/mathias/kick.wav",
        "/uploads/mathias/perc.wav",
        "/uploads/mathias/snap.wav",
        "/uploads/mathias/snare.wav",
        "/uploads/mathias/kalimba.mp3",
        "/uploads/mathias/hihat.wav"
    ];
    
let ColorEnum = Object.freeze({"red":0, "green":1, "blue":2, "yellow":3});

function World() 
{
    
    let objects = [];
    let selectedAudio = [4];
    let grid = new Array(4); //2d array 
    for(let i = 0; i<4; i++)
    {
        grid[i] = new Array(16);
        for(let j = 0; j<16; j++)
        {
            grid[i][j] = false;
        }
    }
    let play = false;
    let current = 0;
    let bpm = 90;
    let timeoutNextBeat;
    
    function playSample()
    {
        let i = this.type;
        let a = new Audio(audiofiles[i]);
        a.play();
    }
    
    function drawButton(x,y,z,width,height,color,name)
    {
        let cube = new THREE.Mesh(new THREE.BoxBufferGeometry( width, 10, height ), new THREE.MeshBasicMaterial({color:color}));
	 	cube.name = name;
	 	cube.position.set(x, y, z);
	    threeworld.scene.add(cube);
	    objects.push(cube);
    }
    
    function printGrid() //for debugging
    {
        s = "";
        
        for(let i = 0; i< 4; i++)
        {
            for(let j = 0; j< 16; j++)
            {
                if (grid[i][j]) s+="x";
                else s+="-";
            }
            s+="\n";
        }
        
        return s;
    }

    
    function switchButton(obj,color,type)
    {
        
        // console.log(ColorEnum.red, +type, "grid[ColorEnum.red][+type] : ", grid[ColorEnum.red][+type]);
        // console.log(printGrid());
        switch(color)
        {
            case "r":
                if (grid[ColorEnum.red][+type] === false)
                {
                    grid[ColorEnum.red][+type] = true;
                    obj.material.color.setHex(0x8b0000);
                }
                else
                {
                    grid[ColorEnum.red][+type] = false;
                    obj.material.color.setHex(0xD3D3D3);
                }
                break;
                
            case "g":
                if (!grid[ColorEnum.green][+type])
                {
                    grid[ColorEnum.green][+type] = true;
                    obj.material.color.setHex(0x8b0000);
                }
                else
                {
                    grid[ColorEnum.green][+type] = false;
                    obj.material.color.setHex(0xD3D3D3);
                }
                break;
                
            case "b":
                if (!grid[ColorEnum.blue][+type])
                {
                    grid[ColorEnum.blue][+type] = true;
                    obj.material.color.setHex(0x8b0000);
                }
                else
                {
                    grid[ColorEnum.blue][+type] = false;
                    obj.material.color.setHex(0xD3D3D3);
                }
                break;
                
            case "y":
                if (!grid[ColorEnum.yellow][+type])
                {
                    grid[ColorEnum.yellow][+type] = true;
                    obj.material.color.setHex(0x8b0000);
                }
                else
                {
                    grid[ColorEnum.yellow][+type] = false;
                    obj.material.color.setHex(0xD3D3D3);
                }
                break;
        }
    }
    
    function playAudio(selection)
    {
        let a = new Audio(selectedAudio[selection]);
        a.play();
    }
    
    function initDrag ( x, y )              // x,y position on screen
    {
        let obj = objectClicked( x, y );     
        
        if (obj !== null) 
        {
            
            let color = obj.name.split(".")[0];
            let type = obj.name.split(".")[1];
            
            // console.log("Clicked : ", color, type);
            
            if (type == "indicator")
            {
                switch(color)
                {
                    case "r":
                        playAudio(ColorEnum.red);
                        break;
                        
                    case "g":
                        playAudio(ColorEnum.green);
                        break;
                        
                    case "b":
                        playAudio(ColorEnum.blue);
                        break;
                        
                    case "y":
                        playAudio(ColorEnum.yellow);
                        break;
                    
                    default:
                        console.error("Error in switch of initdrag()");
                        break;
                }
            }
            else if (!isNaN(type)) //this checks if the string type contains a number
            {
                switchButton(obj,color,type);
            }
        }
    }

    
    function objectClicked(x,y)
    {
        for (let o of objects)
        {
            if (threeworld.hitsObject(x,y,o))
            {
                return o;
            }
        }
        
        // console.log("Clicked : the Void");
        return null;
    }
    
    
    function load()
    {
        for (let f of audiofiles)
        {
            let a = new Audio(f);
            audios.push(a);
        }
    }
    
    function selectRedAudio()
    {
        let selectBox = document.getElementById("rselect");
        let selectedValue = selectBox.options[selectBox.selectedIndex].value;
        selectedAudio[0] = audiofiles[selectedValue];
    }
    
    function selectGreenAudio()
    {
        let selectBox = document.getElementById("gselect");
        let selectedValue = selectBox.options[selectBox.selectedIndex].value;
        selectedAudio[1] = audiofiles[selectedValue];
    }
    
    function selectBlueAudio()
    {
        let selectBox = document.getElementById("bselect");
        let selectedValue = selectBox.options[selectBox.selectedIndex].value;
        selectedAudio[2] = audiofiles[selectedValue];
    }
    
    function selectYellowAudio()
    {
        let selectBox = document.getElementById("yselect");
        let selectedValue = selectBox.options[selectBox.selectedIndex].value;
        selectedAudio[3] = audiofiles[selectedValue];
    }
    
    function onClickPlay()
    {
        play = true;
        nextBeat();
    }
    
    function onClickPause()
    {
        play = false;
        clearTimeout(timeoutNextBeat);
    }
    
    function onClickStop()
    {
        play = false;
        let previous = current-1;
        if (previous == -1) previous = 15;
        
        o = threeworld.scene.getObjectByName( "none."+previous );
        o.material.color.setHex(0xd3d3d3);
        
        current = 0;
        clearTimeout(timeoutNextBeat);
    }
    
    function nextBeat()
    {
        if (grid[ColorEnum.red][current]) playAudio(ColorEnum.red);
        if (grid[ColorEnum.green][current]) playAudio(ColorEnum.green);
        if (grid[ColorEnum.blue][current]) playAudio(ColorEnum.blue);
        if (grid[ColorEnum.yellow][current]) playAudio(ColorEnum.yellow);
        
        let o = threeworld.scene.getObjectByName( "none."+current );
        o.material.color.set("chartreuse");
        
        let previous = current-1;
        if (previous == -1) previous = 15;
        
        o = threeworld.scene.getObjectByName( "none."+previous );
        o.material.color.setHex(0xd3d3d3);
        
        current++;
        current %= 16;
        
        if (play) timeoutNextBeat = setTimeout(nextBeat,60000/bpm);
    }

    function clearTracker()
    {
        for(let o in objects)
        {
            if (o.name.includes("none"))
            {
                o.material.color.setHex(0xd3d3d3);
            }
        }
    }
    
    function reset()
    {
        
        for (let i=0; i<4; i++)
        {
            for (let j=0; j<16; j++)
            {
                grid[i][j] = false;
            }
        }
        
        for (let o of objects)
        {
            let color = o.name.split(".")[0];
            let type = o.name.split(".")[1];
            
            
            
            if (type !== "indicator"  &&  color !== "none")
            {
                o.material.color.setHex(0xd3d3d3);   
            }
        }
    }
    
    function updateBPM()
    {
        bpm = document.getElementById("bpm").value;
        // console.log(bpm);
    }

	this.newRun = function()
	{
	    //setup selectors
	    let s1 = "<p> <font color='red'>Red</font>  : <select id='rselect' name='red audio'>";
	    
	    for (let i = 0; i<audiofiles.length; i++)
	    {
	        s1 +=  '<option value="'+i+'">' +audiofiles[i].replace("/uploads/",'').replace(".mp3",'').replace(".wav",'')+ '</option>';
	    }
	    
	    s1 += "</select>"
	
	    
	    
	    s1+= " <font color='green'>Green</font> : <select id='gselect' name='green audio'>";
	    
	    for (let i = 0; i<audiofiles.length; i++)
	    {
	        s1 +=  '<option value="'+i+'">' +audiofiles[i].replace("/uploads/",'').replace(".mp3",'').replace(".wav",'')+ '</option>';
	    }
	    
	    s1 += "</select></p>"
	
	    $("#user_span1").html(s1);
	    
	    
	    
	    let s3 = "<p> <font color='blue'>Blue</font> : <select id='bselect' name='blue audio'>";
	    
	    for (let i = 0; i<audiofiles.length; i++)
	    {
	        s3 +=  '<option value="'+i+'">' +audiofiles[i].replace("/uploads/",'').replace(".mp3",'').replace(".wav",'')+ '</option>';
	    }
	    
	    s3 += "</select>"
	

	    
	    
	    s3 += "<font color='yellow'>Yellow </font>: <select id='yselect' name='yellow audio'>";
	    
	    for (let i = 0; i<audiofiles.length; i++)
	    {
	        s3 +=  '<option value="'+i+'">' +audiofiles[i].replace("/uploads/",'').replace(".mp3",'').replace(".wav",'')+ '</option>';
	    }
	    
	    s3 += "</select></p>"
	
	    $("#user_span3").html(s3);
	    
	    
	    
	    let s5 = "<p><button id=play> Play </button>  <button id=pause> Pause </button> <button id=stop> Stop </button>  <button id=reset> Reset </button></p>";
	    $("#user_span5").html(s5);
	    
	    let s6 = "<p>BPM : <input id='bpm' type='number' value='80'></p>"
	    $("#user_span6").html(s6);
	    
	    if ( AB.runloggedin )
        {
            $("#user_span7").html ( " <button onclick='AB.saveData();' >Save your work</button> " );
                       
            // Check if any data exists, if so make restore button:
            AB.queryDataExists();           // will call World.queryDataExists when done 
        }       
        else
            $("#user_span7").html(  " <p> <b> To save your work, go to the World page and run this \"logged in\". </b> </p> " );

	    
	    
	    //default selected audio
	    selectedAudio = audiofiles.slice(0,4);
	    
	    
	    //setup camera
	    threeworld.camera = new THREE.OrthographicCamera( $(document).width() / - 2, $(document).width() / 2, $(document).height() / 2, $(document).height() / - 2, 1, 1000 );
	 	threeworld.init2d ( 50, 0, 0x000000 ); //0x93A1AC
	 	

	 	
	 	//drawing the board
	    
	    drawButton(-$(window).width()/2 + 60,0,0,50,50,"red","r.indicator");
	    
	    for (let i = 0; i< 16; i++)
	    {
	        drawButton(-$(window).width()/2 + 120 + i*30, 0, 0, 20, 40, 0xD3D3D3, "r."+i);
	    }
	    
	    
	    drawButton(-$(window).width()/2 + 60,0,70,50,50,"green","g.indicator");
	    
	    for (let i = 0; i< 16; i++)
	    {
	        drawButton(-$(window).width()/2 + 120 + i*30, 0, 70, 20, 40, 0xD3D3D3, "g."+i);
	    }
	    
	    
	    drawButton(-$(window).width()/2 + 60,0,140,50,50,"blue","b.indicator");
	    
	    for (let i = 0; i< 16; i++)
	    {
	        drawButton(-$(window).width()/2 + 120 + i*30, 0, 140, 20, 40, 0xD3D3D3, "b."+i);
	    }
	    
	    
	    drawButton(-$(window).width()/2 + 60,0,210,50,50,"yellow","y.indicator");
	    
	    for (let i = 0; i< 16; i++)
	    {
	        drawButton(-$(window).width()/2 + 120 + i*30, 0, 210, 20, 40, 0xD3D3D3, "y."+i);
	    }
	    
	    
	    for (let i = 0; i< 16; i++)
	    {
	        drawButton(-$(window).width()/2 + 120 + i*30, 0, -50, 10, 10, 0xD3D3D3, "none."+i);
	    }
	    
        // drawButton(-$(window).width()/2 + 120 + i*30, 0, -50, 10, 10, 0xD3D3D3, "none.play");	    

	 	//disabling camera controls
        threehandler.mouseZoom     = function ( delta ) {  };
        threehandler.touchDrag     = function ( x, y )  {  };
        threehandler.touchZoom     = function ( delta ) {  };
        threehandler.mouseDrag     = function ( x, y )  {  }; 
        threehandler.initTouchDrag  = initDrag;
        threehandler.initMouseDrag  = initDrag;
        
        document.getElementById("rselect").addEventListener("change", selectRedAudio);
        document.getElementById("yselect").addEventListener("change", selectYellowAudio);
        document.getElementById("bselect").addEventListener("change", selectBlueAudio);
        document.getElementById("gselect").addEventListener("change", selectGreenAudio);
        document.getElementById("play").addEventListener("click", onClickPlay);
        document.getElementById("pause").addEventListener("click", onClickPause);
        document.getElementById("stop").addEventListener("click", onClickStop);
        document.getElementById("bpm").addEventListener("change", updateBPM);
        document.getElementById("reset").addEventListener("click", reset);
        
	};

    

	this.nextStep = function()		 
	{
	   // console.log("play", play, "current", current);
		// Code for Three.js re-drawing of objects.  		
		
	
	};

    this.saveData = function()
    {
        $("#user_span8").html ( " <button onclick='AB.restoreData();' >Restore your work</button> " );
            
        return { selectedAudio: selectedAudio, grid: grid};
        
    }
    
    this.restoreData = function(a)
    {
        grid = a.grid;
        selectedAudio = a.selectedAudio;
        onClickStop();
        
        for (let o of objects)
        {
            let color = o.name.split(".")[0];
            let type = o.name.split(".")[1];
            
            
            if (!isNaN(type) && color != "none")
            {
                console.log(color,type);

                if (color == "r")
                {
                    console.log("aba")
                    if (grid[ColorEnum.red][+type]) o.material.color.setHex(0x8b0000);
                    else o.material.color.setHex(0xd3d3d3);   
                }
                else if (color == "b")
                {
                    if (grid[ColorEnum.blue][+type]) o.material.color.setHex(0x8b0000);
                    else o.material.color.setHex(0xd3d3d3);   
                }
                else if (color == "y")
                {
                    if (grid[ColorEnum.yellow][+type]) o.material.color.setHex(0x8b0000);
                    else o.material.color.setHex(0xd3d3d3);   
                }
                else if (color == "g")
                {
                    if (grid[ColorEnum.green][+type]) o.material.color.setHex(0x8b0000);
                    else o.material.color.setHex(0xd3d3d3);   
                }
                    
            }
        }
        
    }
    
    this.queryDataExists = function ( exists )
 {
        if ( exists ) 
          $("#user_span8").html ( " <button onclick='AB.restoreData();' >Restore your work</button> " );
 };

}