Code viewer for World: Use Blockade Labs API (clo...

// Cloned by Moses Crasto on 19 Nov 2023 from World "MineCraft" by Starter user 
// Please leave this clone trail here.
 

// ==== Starter World =================================================================================================
// This code is designed for use on the Ancient Brain site.
// This code may be freely copied and edited by anyone on the Ancient Brain site.
// To include a working run of this program on another site, see the "Embed code" links provided on Ancient Brain.
// ====================================================================================================================

// ===================================================================================================================
// === Start of tweaker's box ======================================================================================== 
// ===================================================================================================================

// The easiest things to modify are in this box.
// You should be able to change things in this box without being a JavaScript programmer.
// Go ahead and change some of these. What's the worst that could happen?


AB.clockTick       = 100;    

	// Speed of run: Step every n milliseconds. Default 100.
	
AB.maxSteps        = 1000000;    

	// Length of run: Maximum length of run in steps. Default 1000.

AB.screenshotStep  = 50;   
  
	// Take screenshot on this step. (All resources should have finished loading.) Default 50.

const SKYCOLOR 	= 0xffffff;				// a number, not a string 
 
const MAXPOS                = 4000 ;                                 
const startRadiusConst	 	= MAXPOS * 0.5 ;		// distance from centre to start the camera at
const maxRadiusConst 		= MAXPOS * 5 ;		// maximum distance from camera we will render things  


//--- change ABWorld defaults: -------------------------------

ABHandler.MAXCAMERAPOS = MAXPOS * 50 ;			// allow camera go far away 

ABWorld.drawCameraControls = false;

// ===================================================================================================================
// === End of tweaker's box ==========================================================================================
// ===================================================================================================================


// You will need to be some sort of JavaScript programmer to change things below the tweaker's box.


// document.write is good at the moment we include the JS, not later
 
document.write ( ` 
    <div id="them">
        
    </div>
` );
 
var splashClicked = false;

function makeSplash () // replace splash screen with this HTML
{   
    var html = "<div style='max-width:600px; text-align:left;'>" +
        `<br>
            Generate a skybox using the <a href="https://api-documentation.blockadelabs.com/api/">Skybox AI API</a>.
        <br>
        <div id="enterkey">
        Enter API key:
        <input style='width:25vw;' maxlength='2000' NAME="apikey" id="apikey" VALUE=''>
        <button onclick='setkey();' class=ab-normbutton>Set API key</button>
        </div>

        <div style="width:60vw; background-color:white; border: 1px solid black; margin:20; padding: 20px;">
        <h3>Enter a "prompt"</h3>
        <input style="width:50vw;" id="me" value="new york in the evening">
        <button onclick="sendchat();" class=ab-normbutton>Send</button>
        </div>
        
        <div>
        <h3>Select a style</h3>
        <input type="radio" id="option1" name="toggle" value="3">
        <label>Anime</label>
        <input type="radio" id="option2" name="toggle" value="43">
        <label>Art Mix</label>
        <input type="radio" id="option3" name="toggle" value="31">
        <label>Claymation</label>
        <input type="radio" id="option4" name="toggle" value="35">
        <label>Cyberpunk</label>
        <br>
        <input type="radio" id="option5" name="toggle" value="5">
        <label>Digital Painting</label>
        <input type="radio" id="option6" name="toggle" value="15">
        <label>Interiors</label>
        <input type="radio" id="option7" name="toggle" value="20">
        <label>Kids CGI Animation</label>
        <input type="radio" id="option8" name="toggle" value="24">
        <label>Pen & Ink</label>
        <br>
        <input type="radio" id="option9" name="toggle" value="48">
        <label>Psychedelic Illustration</label>
        <input type="radio" id="option10" name="toggle" value="41">
        <label>Radiant Painting</label>
        <input type="radio" id="option11" name="toggle" value="9">
        <label>Realism</label>
        <input type="radio" id="option12" name="toggle" value="16">
        <label>Sky Dome</label>
        <br>
        <input type="radio" id="option13" name="toggle" value="4">
        <label>Surreal</label>
        <input type="radio" id="option14" name="toggle" value="22">
        <label>Watercolor</label>
        </div>

        <div style="width:60vw; background-color:#ffffcc; border: 1px solid black; margin:20; padding: 20px;">
        <h3 id="status"></h3>
        </div>`
	
    return ( html + "</div>" );
}
  
AB.world.newRun = function() 
{
	AB.runReady = false;  
	
	// when this returns it makes a splash screen
	
	AB.getAllData ( process );		// process is the callback function 
	
	ABWorld.init3d ( startRadiusConst, maxRadiusConst, SKYCOLOR  ); 
};


const skyboxURL = "https://backend.blockadelabs.com/api/v1";  // Skybox API endpoint
var skyboxAPIKey = "";  // Your Skybox API key
var theprompt = "";
var pusherChannel;
var pusherEvent;
var pusher;

//Pusher parameters
const pusherAppId = "1713507";
const pusherKey = "8979e09a3dafe1a132a6";
const pusherCluster = "eu";

function setkey() {
    skyboxAPIKey = jQuery("input#apikey").val();
    skyboxAPIKey = skyboxAPIKey.trim();
    $("#enterkey").html("<b> API key has been set. </b>");
}


function sendchat() {
    theprompt = $("#me").val();
    style = $('input[name="toggle"]:checked').val();
    var thedata = {
        "prompt": theprompt,
        "skybox_style_id" : style
    };

    var thedatastring = JSON.stringify(thedata);
  
    $.ajaxSetup({
        headers:
        {
            "Content-Type":"appliaction/json",
            "x-api-key":skyboxAPIKey
        }
    });
  
    $.ajax({
        type: "POST",
        url: skyboxURL + "/skybox",
        data: thedatastring,
        dataType: "json",
        success: function (d, rc) { successfn(d, rc); },
        error: function () { errorfn(); }
    });
}

// Initializing Pusher with app credentials
function initializePusher() {
 pusher = new Pusher(pusherKey, {
    cluster: pusherCluster,
  });
}

function loadPusherLibrary() {
  const script = document.createElement('script');
  script.src = 'https://js.pusher.com/7.0/pusher.min.js';
  script.onload = initializePusher;
  document.head.appendChild(script);
}

loadPusherLibrary();

var a;
var answer;

function successfn(data, rc) {
    a = data;
    var id = a["id"];
    
    // Set up Pusher with the received channel and event
    pusherChannel = data.pusher_channel;
    pusherEvent = data.pusher_event;

    // Subscribe to the Pusher channel
    const channel = pusher.subscribe(pusherChannel);
    
    // Listen for status updates
    channel.bind(pusherEvent, function (data) {
      updateStatus(data.status);
    
      // Check if the status is "complete" or "error" to stop the recursive calls
      if (data.status === "complete" || data.status === "error") {
        return;
      }

      // Continue checking the status after a short delay
      setTimeout(() => {
        checkStatus(id);
      }, 1000);
    });
    
    // Initial check of the status
    checkStatus(id);
}

function checkStatus(id) {
  // Fetch the latest status using the Skybox API
    $.ajax({
      type: "GET",
      url: `${skyboxURL}/imagine/requests/${id}`,
      success: function (data, rc) { checkStatusSuccess(data, rc); },
      error: function () { checkStatusError(); }
    });
}

function checkStatusSuccess(data, rc) {
  // Update the status
  updateStatus(data.request.status);
  if (data.request.status === "complete") {

    // Process the result or update the UI as needed
    answer = data.request.file_url;
    $("#them").html(`
        <script>
            const scene = new THREE.Scene();
            const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            const renderer = new THREE.WebGLRenderer();
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
            
            // Create a cube with the skybox texture
            const geometry = new THREE.BoxGeometry(1000, 1000, 1000);
            const materials = [];
            const textureLoader = new THREE.TextureLoader();
                
            const x_offset = [3, 1, 2, 2, 2, 0];
            const y_offset = [1, 1, 2, 0, 1, 1];
            const t = [];
            
            for (var i = 0; i < 6; i++) {
                t[i] = textureLoader.load(answer);
                t[i].repeat.x = 1 / 4;
                t[i].offset.x = x_offset[i] / 4;
                t[i].repeat.y = 1 / 3;
                t[i].offset.y = y_offset[i] / 3;
                t[i].minFilter = THREE.NearestFilter;
                t[i].generateMipmaps = false;
            
                materials.push(new THREE.MeshBasicMaterial({ map: t[i], side: THREE.BackSide }));
            }
        
            const skybox = new THREE.Mesh(geometry, materials);
            scene.add(skybox);
                
            // Set camera position
            camera.position.z = 5;
            
            // Add animation
            const animate = function () {
                requestAnimationFrame(animate);
                
                // Rotate the skybox
                skybox.rotation.y += 0.005;
                
                renderer.render(scene, camera);
            };
            animate();
        </script>`);
        status = "Skybox will be generated in a few seconds :)"
        updateStatus(status)
        setTimeout(() => {
            AB.removeSplash();
            AB.splashClick ( removeSplash );
        }, 3000);
  } else if (data.request.status === "error") {
    // Handle the error
    console.error(data.error_message);
  } else {
    // Continue checking the status after a short delay
    setTimeout(() => {
      checkStatus(data.request.id);
    }, 1000);
  }
}

function checkStatusError() {
  // Handle the error when checking the status
  console.error("Error checking status");
}

function errorfn() {
  if (skyboxAPIKey == "") $("#them").html("<font color=red><b> Enter API key to be able to chat. </b></font>");
  else $("#them").html("<font color=red><b> Unknown error. </b></font>");
}
 
function updateStatus(status) {
  status = status.charAt(0).toUpperCase() + status.slice(1);
  $("#status").html(`Status: ${status}`);
}

function process()          
// makes a splash screen
{
	AB.newSplash();	
	
	// build splash contents 
	var html = makeSplash ();
	
	// replace splash contents 
	AB.splashHtml ( html );
}