A mo-mo-mo-monster
This commit is contained in:
commit
d6e76e8cfd
56 changed files with 8523 additions and 0 deletions
173
assets/js/editor.js
Normal file
173
assets/js/editor.js
Normal file
|
@ -0,0 +1,173 @@
|
|||
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", "");
|
||||
}
|
||||
}
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue