173 lines
4.6 KiB
JavaScript
173 lines
4.6 KiB
JavaScript
import { getScene, getSceneElement } from "./api";
|
|
|
|
import { Modal } from "bootstrap";
|
|
|
|
let clickTimestamp = 0;
|
|
var editModal = null;
|
|
|
|
// Find parent quackscape-scene for ID
|
|
function findParentScene(element) {
|
|
var parent = element.parentElement;
|
|
|
|
while (parent.tagName != "QUACKSCAPE-SCENE") {
|
|
parent = parent.parentElement;
|
|
}
|
|
|
|
return parent;
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
editModal = new Modal("#editModal");
|
|
});
|
|
|
|
// Distinguishing clicks from drags based on duration.
|
|
// TODO: Find a better way to distinguish these.
|
|
function addEventListeners(element) {
|
|
element.addEventListener("mousedown", function (event) {
|
|
clickTimestamp = event.timeStamp;
|
|
});
|
|
|
|
element.addEventListener("mouseup", function (event) {
|
|
if (event.timeStamp - clickTimestamp > 200) {
|
|
// Ignoring this, we only handle regular short clicks.
|
|
// TODO: Find a way to handle drags of elements
|
|
return;
|
|
} else {
|
|
handleClick(event);
|
|
}
|
|
|
|
// Right-clicks are definitely intentional.
|
|
element.addEventListener("contextmenu", function (event) {
|
|
handleClick(event);
|
|
});
|
|
});
|
|
}
|
|
|
|
// Open a modal for creating a new Element
|
|
function startCreateModal(event) {
|
|
var modalLabel = document.getElementById("editModalLabel");
|
|
modalLabel.textContent = "Create Element";
|
|
|
|
var modalContent = document.getElementById("editModalContent");
|
|
|
|
var thetaStart = cartesianToTheta(
|
|
event.detail.intersection.point.x,
|
|
event.detail.intersection.point.z
|
|
);
|
|
|
|
modalContent.innerHTML = `<b>Creating element at:</b><br/>
|
|
X: ${event.detail.intersection.point.x}<br/>
|
|
Y: ${event.detail.intersection.point.y}<br/>
|
|
Z: ${event.detail.intersection.point.z}<br/>
|
|
Calculated Theta: ${thetaStart}<br/>
|
|
|
|
Parent Element Type: ${event.srcElement.tagName}<br/>
|
|
<hr/>
|
|
|
|
<form id="newElementForm">
|
|
<select class="form-select" aria-label="Default select example">
|
|
<option selected>Select Element Type</option>
|
|
<option value="1">Marker</option>
|
|
<option value="2">Image</option>
|
|
<option value="3">Teleport</option>
|
|
</select>
|
|
</form>
|
|
`;
|
|
|
|
editModal.show();
|
|
}
|
|
|
|
function startModifyModal(event) {
|
|
var modalLabel = document.getElementById("editModalLabel");
|
|
modalLabel.textContent = "Modify Element";
|
|
|
|
// Get element from API
|
|
var scene = findParentScene(event.target);
|
|
|
|
var element_data_request = getSceneElement(
|
|
scene.getAttribute("id"),
|
|
event.target.getAttribute("id")
|
|
);
|
|
|
|
element_data_request.then((element_data) => {
|
|
console.log(element_data);
|
|
|
|
var modalContent = document.getElementById("editModalContent");
|
|
|
|
modalContent.innerHTML = `<b>Modifying element:</b><br/>
|
|
Element Type: ${event.srcElement.tagName}<br/>
|
|
Element ID: ${event.target.getAttribute("id")}<br/>
|
|
Element data: ${JSON.stringify(element_data.obj)}<br/>
|
|
<hr/>
|
|
|
|
<form id="modifyElementForm">
|
|
</form>
|
|
`;
|
|
|
|
editModal.show();
|
|
});
|
|
}
|
|
|
|
function cartesianToTheta(x, z) {
|
|
// Calculate the angle in radians
|
|
let angleRadians = Math.atan2(z, x);
|
|
|
|
// Convert to degrees
|
|
let angleDegrees = angleRadians * (180 / Math.PI);
|
|
|
|
// A-Frame's thetaStart is measured from the positive X-axis ("right" direction)
|
|
// and goes counter-clockwise, so this should directly give us the thetaStart value.
|
|
let thetaStart = 90 - angleDegrees;
|
|
|
|
// Since atan2 returns values from -180 to 180, let's normalize this to 0 - 360
|
|
thetaStart = thetaStart < 0 ? thetaStart + 360 : thetaStart;
|
|
|
|
return thetaStart;
|
|
}
|
|
|
|
function latLonToXYZ(lat, lon, radius = 5) {
|
|
// Convert lat/lon to X/Y/Z coordinates on the sphere
|
|
const phi = (90 - lat) * (Math.PI / 180);
|
|
const theta = (lon + 180) * (Math.PI / 180);
|
|
|
|
const x = -(radius * Math.sin(phi) * Math.cos(theta));
|
|
const y = radius * Math.cos(phi);
|
|
const z = radius * Math.sin(phi) * Math.sin(theta);
|
|
|
|
return { x, y, z };
|
|
}
|
|
|
|
function handleClick(event) {
|
|
console.log(event);
|
|
|
|
if (event.target.tagName == "A-SKY") {
|
|
startCreateModal(event);
|
|
} else {
|
|
startModifyModal(event);
|
|
}
|
|
}
|
|
|
|
document.addEventListener("loadedQuackscapeScene", function (event) {
|
|
// Get the scene
|
|
var scene = document.querySelector("a-scene");
|
|
|
|
// Get all children
|
|
var children = scene.children;
|
|
|
|
for (var i = 0; i < children.length; i++) {
|
|
var child = children[i];
|
|
|
|
if (child.tagName.startsWith("A-")) {
|
|
// Remove original onclick events
|
|
if (child.hasAttribute("onclick")) {
|
|
child.removeAttribute("onclick");
|
|
}
|
|
|
|
// Add new event listeners
|
|
addEventListeners(child);
|
|
|
|
// Add click-drag component to all a-entity elements
|
|
child.setAttribute("click-drag", "");
|
|
}
|
|
}
|
|
});
|