2024-03-15 15:41:37 +00:00
|
|
|
import { getScene, getCategory } from "./api";
|
2024-03-15 18:27:19 +00:00
|
|
|
import { Dropdown, Collapse } from "bootstrap";
|
2024-03-15 15:41:37 +00:00
|
|
|
|
|
|
|
import "../scss/frontend.scss";
|
|
|
|
import "../css/scene.css";
|
2024-03-11 14:56:03 +00:00
|
|
|
|
|
|
|
require("aframe");
|
|
|
|
|
2024-03-11 18:49:48 +00:00
|
|
|
// 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");
|
Enhance editor UI and user content management
Introduced significant updates to the user interface for editing VR
scenes, adding new CSS styles for a coherent and modern look.
Implemented data tables for robust content management in the user area,
now users can easily navigate through scenes and media with DataTables
integration. Expanded the API with category retrieval capabilities,
enabling dynamic content categorization.
The editor now seamlessly integrates into the UI with a sidebar for
properties editing, improving usability. The teleportation element
creation and modification logic has been significantly refined,
including a search-enabled dropdown for destination selection, making it
more user-friendly. Added thumbnail display for scenes and media in the
user area, enhancing content overview.
This update also introduced user area templates and routes, providing a
foundational structure for user content management functionality,
including categories and individual category views.
Refactored JavaScript imports to align with the new editor CSS and
adjusted scene loading to support embedded scenes, improving the
flexibility and usability of scene components.
2024-03-14 16:28:14 +00:00
|
|
|
this.embedded = this.getAttribute("embedded") != undefined;
|
2024-03-11 15:29:47 +00:00
|
|
|
this.x = this.getAttribute("x") | 0;
|
|
|
|
this.y = this.getAttribute("y") | 0;
|
|
|
|
this.z = this.getAttribute("z") | 0;
|
2024-03-15 18:27:19 +00:00
|
|
|
this.navbar = this.getAttribute("navbar") != undefined;
|
|
|
|
this.sidebar = this.getAttribute("sidebar") != undefined;
|
2024-03-11 14:56:03 +00:00
|
|
|
|
Enhance editor UI and user content management
Introduced significant updates to the user interface for editing VR
scenes, adding new CSS styles for a coherent and modern look.
Implemented data tables for robust content management in the user area,
now users can easily navigate through scenes and media with DataTables
integration. Expanded the API with category retrieval capabilities,
enabling dynamic content categorization.
The editor now seamlessly integrates into the UI with a sidebar for
properties editing, improving usability. The teleportation element
creation and modification logic has been significantly refined,
including a search-enabled dropdown for destination selection, making it
more user-friendly. Added thumbnail display for scenes and media in the
user area, enhancing content overview.
This update also introduced user area templates and routes, providing a
foundational structure for user content management functionality,
including categories and individual category views.
Refactored JavaScript imports to align with the new editor CSS and
adjusted scene loading to support embedded scenes, improving the
flexibility and usability of scene components.
2024-03-14 16:28:14 +00:00
|
|
|
loadScene(this.scene, this.x, this.y, this.z, this, this.embedded);
|
2024-03-15 15:41:37 +00:00
|
|
|
|
|
|
|
if (this.navbar) {
|
|
|
|
loadNavbar(this.scene, this);
|
|
|
|
}
|
2024-03-15 18:27:19 +00:00
|
|
|
|
|
|
|
if (this.sidebar) {
|
|
|
|
loadSidebar(this.scene, this);
|
|
|
|
}
|
2024-03-11 14:56:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-11 18:49:48 +00:00
|
|
|
document.addEventListener("contextmenu", function (event) {
|
2024-03-11 14:56:03 +00:00
|
|
|
event.preventDefault();
|
2024-03-11 18:49:48 +00:00
|
|
|
});
|
2024-03-11 14:56:03 +00:00
|
|
|
|
|
|
|
customElements.define("quackscape-scene", QuackscapeScene);
|
|
|
|
|
2024-03-15 18:27:19 +00:00
|
|
|
// Function to add a sidebar to the destination object
|
|
|
|
|
|
|
|
async function loadSidebar(scene_id, destination) {
|
|
|
|
getScene(scene_id).then((scene) => {
|
|
|
|
getCategory(scene.obj.category).then((category) => {
|
|
|
|
var sidebar = document.createElement("div");
|
|
|
|
sidebar.setAttribute("class", "collapse show");
|
|
|
|
sidebar.setAttribute("id", "sceneSidebar");
|
|
|
|
|
|
|
|
var p = document.createElement("div");
|
|
|
|
p.setAttribute("class", "p-4");
|
|
|
|
|
|
|
|
var h5 = document.createElement("h5");
|
|
|
|
h5.setAttribute("class", "font-weight-bold");
|
|
|
|
h5.textContent = "Scenes";
|
|
|
|
|
|
|
|
var ul = document.createElement("ul");
|
|
|
|
ul.setAttribute("class", "nav flex-column");
|
|
|
|
|
|
|
|
category.obj.scenes.forEach((scene) => {
|
|
|
|
var li = document.createElement("li");
|
|
|
|
li.setAttribute("class", "nav-item");
|
|
|
|
|
|
|
|
var a = document.createElement("a");
|
|
|
|
a.setAttribute("href", "#");
|
|
|
|
a.setAttribute("class", "nav-link");
|
|
|
|
a.textContent = scene.title;
|
|
|
|
a.addEventListener("click", function () {
|
|
|
|
loadScene(scene.id, -1, -1, -1, destination);
|
|
|
|
});
|
|
|
|
|
|
|
|
li.appendChild(a);
|
|
|
|
ul.appendChild(li);
|
|
|
|
});
|
|
|
|
|
|
|
|
p.appendChild(h5);
|
|
|
|
p.appendChild(ul);
|
|
|
|
|
|
|
|
var button = document.createElement("button");
|
|
|
|
button.setAttribute("class", "btn btn-primary");
|
|
|
|
button.setAttribute("type", "button");
|
|
|
|
button.setAttribute("data-bs-toggle", "collapse");
|
|
|
|
button.setAttribute("data-bs-target", "#sceneSidebar");
|
|
|
|
button.setAttribute("aria-expanded", false);
|
|
|
|
button.setAttribute("aria-controls", "sceneSidebar");
|
|
|
|
button.textContent = "<";
|
|
|
|
|
|
|
|
//p.appendChild(button); // TODO: Make it prettier before enabling.
|
|
|
|
|
|
|
|
sidebar.appendChild(p);
|
|
|
|
|
|
|
|
destination.prepend(sidebar);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-03-15 15:41:37 +00:00
|
|
|
// Function to add a navbar to the destination object
|
|
|
|
|
|
|
|
async function loadNavbar(scene_id, destination) {
|
|
|
|
getScene(scene_id).then((scene) => {
|
|
|
|
getCategory(scene.obj.category).then((category) => {
|
|
|
|
var nav = document.createElement("nav");
|
|
|
|
nav.setAttribute("class", "navbar navbar-expand-lg navbar-dark bg-dark");
|
|
|
|
nav.setAttribute("id", "sceneNavbar");
|
|
|
|
|
|
|
|
var container = document.createElement("div");
|
|
|
|
container.setAttribute("class", "container-fluid");
|
|
|
|
|
|
|
|
var dropdown = document.createElement("div");
|
|
|
|
dropdown.setAttribute("class", "dropdown");
|
|
|
|
|
|
|
|
var sceneSelector = document.createElement("button");
|
|
|
|
sceneSelector.setAttribute("class", "btn btn-secondary dropdown-toggle");
|
|
|
|
sceneSelector.setAttribute("type", "button");
|
|
|
|
sceneSelector.setAttribute("id", "sceneSelector");
|
|
|
|
sceneSelector.setAttribute("data-bs-toggle", "dropdown");
|
|
|
|
sceneSelector.setAttribute("aria-expanded", "true");
|
|
|
|
sceneSelector.textContent = "Select Scene";
|
|
|
|
|
|
|
|
var dropdownMenu = document.createElement("ul");
|
|
|
|
dropdownMenu.setAttribute("class", "dropdown-menu show");
|
|
|
|
dropdownMenu.setAttribute("aria-labelledby", "sceneSelector");
|
|
|
|
console.log(dropdownMenu);
|
|
|
|
|
|
|
|
category.obj.scenes.forEach((scene) => {
|
|
|
|
console.log(scene);
|
|
|
|
var sceneLink = document.createElement("a");
|
|
|
|
sceneLink.setAttribute("class", "dropdown-item");
|
|
|
|
sceneLink.setAttribute("href", "#");
|
|
|
|
sceneLink.textContent = scene.title;
|
|
|
|
sceneLink.addEventListener("click", function () {
|
|
|
|
loadScene(scene.id, -1, -1, -1, destination);
|
|
|
|
});
|
|
|
|
|
|
|
|
dropdownMenu.appendChild(sceneLink);
|
|
|
|
});
|
|
|
|
|
|
|
|
var sceneTitle = document.createElement("a");
|
|
|
|
sceneTitle.setAttribute("class", "navbar-brand");
|
|
|
|
sceneTitle.setAttribute("href", "#");
|
|
|
|
sceneTitle.setAttribute("id", "sceneTitle");
|
|
|
|
sceneTitle.textContent = scene.obj.title;
|
|
|
|
|
|
|
|
dropdown.appendChild(sceneSelector);
|
|
|
|
dropdown.appendChild(dropdownMenu);
|
|
|
|
console.log(dropdownMenu);
|
|
|
|
|
|
|
|
container.appendChild(dropdown);
|
|
|
|
container.appendChild(sceneTitle);
|
|
|
|
|
|
|
|
nav.appendChild(container);
|
|
|
|
|
|
|
|
destination.prepend(nav);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-03-11 14:56:03 +00:00
|
|
|
// Function to load a scene into a destination object
|
|
|
|
// x and y signify the initial looking direction, -1 for the scene's default
|
|
|
|
|
Enhance editor UI and user content management
Introduced significant updates to the user interface for editing VR
scenes, adding new CSS styles for a coherent and modern look.
Implemented data tables for robust content management in the user area,
now users can easily navigate through scenes and media with DataTables
integration. Expanded the API with category retrieval capabilities,
enabling dynamic content categorization.
The editor now seamlessly integrates into the UI with a sidebar for
properties editing, improving usability. The teleportation element
creation and modification logic has been significantly refined,
including a search-enabled dropdown for destination selection, making it
more user-friendly. Added thumbnail display for scenes and media in the
user area, enhancing content overview.
This update also introduced user area templates and routes, providing a
foundational structure for user content management functionality,
including categories and individual category views.
Refactored JavaScript imports to align with the new editor CSS and
adjusted scene loading to support embedded scenes, improving the
flexibility and usability of scene components.
2024-03-14 16:28:14 +00:00
|
|
|
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);
|
|
|
|
|
2024-03-11 18:49:48 +00:00
|
|
|
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");
|
|
|
|
|
Enhance editor UI and user content management
Introduced significant updates to the user interface for editing VR
scenes, adding new CSS styles for a coherent and modern look.
Implemented data tables for robust content management in the user area,
now users can easily navigate through scenes and media with DataTables
integration. Expanded the API with category retrieval capabilities,
enabling dynamic content categorization.
The editor now seamlessly integrates into the UI with a sidebar for
properties editing, improving usability. The teleportation element
creation and modification logic has been significantly refined,
including a search-enabled dropdown for destination selection, making it
more user-friendly. Added thumbnail display for scenes and media in the
user area, enhancing content overview.
This update also introduced user area templates and routes, providing a
foundational structure for user content management functionality,
including categories and individual category views.
Refactored JavaScript imports to align with the new editor CSS and
adjusted scene loading to support embedded scenes, improving the
flexibility and usability of scene components.
2024-03-14 16:28:14 +00:00
|
|
|
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
|
2024-03-11 15:29:47 +00:00
|
|
|
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
|
2024-03-11 18:49:48 +00:00
|
|
|
const loaded_event = new CustomEvent("loadedQuackscapeScene");
|
2024-03-11 14:56:03 +00:00
|
|
|
document.dispatchEvent(loaded_event);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
window.loadScene = loadScene;
|
|
|
|
|
2024-03-11 18:49:48 +00:00
|
|
|
export { loadScene };
|