quackscape/assets/js/scene.js

164 lines
4.6 KiB
JavaScript
Raw Normal View History

import { getScene } from "./api";
import { loadSidebar } from "./scene/sidebar";
import { loadNavbar } from "./scene/navbar";
import { Dropdown, Collapse } from "bootstrap";
import "../scss/frontend.scss";
import "../css/scene.css";
2024-03-11 14:56:03 +00:00
require("aframe");
// Detect iOS devices
// There is probably a better way to handle issues there, but...
var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
2024-03-11 14:56:03 +00:00
// Define the <quackscape-scene> element
class QuackscapeScene extends HTMLElement {
connectedCallback() {
// When one is created, automatically load the scene
this.scene = this.getAttribute("scene");
this.embedded = this.getAttribute("embedded") != undefined;
this.x = this.getAttribute("x") | 0;
this.y = this.getAttribute("y") | 0;
this.z = this.getAttribute("z") | 0;
this.navbar = this.getAttribute("navbar") != undefined;
this.sidebar = this.getAttribute("sidebar") != undefined;
2024-03-11 14:56:03 +00:00
loadScene(this.scene, this.x, this.y, this.z, this, this.embedded);
if (this.navbar) {
loadNavbar(this.scene, this);
}
else if (this.sidebar) {
loadSidebar(this.scene, this);
}
2024-03-11 14:56:03 +00:00
}
}
document.addEventListener("contextmenu", function (event) {
2024-03-11 14:56:03 +00:00
event.preventDefault();
});
2024-03-11 14:56:03 +00:00
customElements.define("quackscape-scene", QuackscapeScene);
// Function to load a scene into a destination object
// x and y signify the initial looking direction, -1 for the scene's default
async function loadScene(
scene_id,
x = -1,
y = -1,
z = -1,
destination = null,
embedded = false
) {
2024-03-11 14:56:03 +00:00
// Get WebGL maximum texture size
var canvas = document.createElement("canvas");
var gl =
canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
if (!gl) {
alert("Unable to initialize WebGL. Your browser may not support it.");
return;
}
var maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
if (iOS) {
maxTextureSize = Math.min(8192, maxTextureSize);
}
2024-03-11 14:56:03 +00:00
// Get scene information from API
getScene(scene_id).then((response) => {
var scene = response.obj;
// Get largest image that will fit in the texture size from scene.resolutions
// First, order the resolutions by width
var resolutions = scene.base_content.resolutions.sort(
(a, b) => b.width - a.width
);
// Then, find the first resolution that is less than or equal to the max texture size
var content = resolutions.find(
(resolution) => resolution.width <= maxTextureSize
);
// Select a destination element if not specified
if (!destination) {
destination = document.getElementsByTagName("quackscape-scene")[0];
}
destination.setAttribute("id", scene_id);
// Start by removing any existing scenes
var scenes = document.getElementsByTagName("a-scene");
if (scenes.length > 0) {
scenes[0].remove();
}
// Now, build the scene element
var a_scene = document.createElement("a-scene");
a_scene.setAttribute("cursor", "rayOrigin: mouse");
if (embedded) {
a_scene.setAttribute("embedded", "embedded");
}
2024-03-11 14:56:03 +00:00
// Create a-camera element
var rig = document.createElement("a-entity");
rig.setAttribute("id", "rig");
// Rotate camera if requested
if (x != -1 && y != -1 && z != -1) {
rig.setAttribute("rotation", x + " " + y + " " + z);
2024-03-11 14:56:03 +00:00
}
var camera = document.createElement("a-camera");
camera.setAttribute("wasd-controls-enabled", "false"); // TODO: Find a more elegant way to disable z axis movement
rig.appendChild(camera);
a_scene.appendChild(rig);
// Create a-assets element
var assets = document.createElement("a-assets");
a_scene.appendChild(assets);
// Add background image as sky
var sky = document.createElement("a-sky");
sky.setAttribute("src", "#" + content.id);
a_scene.appendChild(sky);
// Add img element to assets
var background = document.createElement("img");
background.setAttribute("id", content.id);
background.setAttribute("src", content.file);
assets.appendChild(background);
// Add elements to scene
scene.elements.forEach((element) => {
var node = document.createElement(element.data.tag);
node.setAttribute("id", element.data.id);
for (const [key, value] of Object.entries(element.data.attributes)) {
node.setAttribute(key, value);
}
// Add node to scene
a_scene.appendChild(node);
});
destination.appendChild(a_scene);
// Dispatch a signal for the editor to pick up
const loaded_event = new CustomEvent("loadedQuackscapeScene");
2024-03-11 14:56:03 +00:00
document.dispatchEvent(loaded_event);
});
}
2024-03-11 14:56:03 +00:00
window.loadScene = loadScene;
export { loadScene };