import AppState from "./state.js";
import { changeLightDirection, toggleAmbientOcclusion } from "./utils/environment.js";
import { resetClipping, addClippingPlane } from "./utils/clipping.js";
import { traverseOntology } from "./ontology.js";
/**
* @module UI
*/
const domParser = new DOMParser;
const contentMenuTabs = `
`;
const audioExample = `
`;
/**
*
* @param {String} triggerSelector - Usually, the close modal trigger element(s) selector
*/
export function pauseAudio(triggerSelector) {
// What if more than one audio element is playing?
const audio = document.querySelector('audio');
if (audio) {
document.querySelectorAll(triggerSelector).forEach(el => {
el.addEventListener('click', () => audio.pause());
});
document.querySelector('.modal').addEventListener('blur', () => {
audio.pause();
});
}
}
/**
* Resets the UI state (essentially hides the clipper toolbar if visible...)
* @todo Other elements to reset?? Restore inital lighting conditions and viewpoint...
*/
function reset() {
document.querySelector('#clipper-bar')?.classList.add('d-none');
document.querySelector('#clipper')?.classList.remove('border', 'border-2', 'border-white');
}
/**
* Right-side main menu panel
* @param {String} triggerId - The menu button id
* @param {String} ontologyJsonPath
*/
function toggleContentMenu(triggerId, ontologyJsonPath) {
const btn = document.querySelector(`#${triggerId}`);
btn.addEventListener('click', async () => {
ATON.UI.setSidePanelRight();
ATON.UI.showSidePanel({header: 'Menu'});
// Append tabs, then tab panes
const tabs = domParser.parseFromString(contentMenuTabs, 'text/html');
ATON.UI.elSidePanel.appendChild(tabs.querySelector('#content-tabs'));
ATON.UI.elSidePanel.appendChild(tabs.querySelector('.tab-content'));
buildLayersMenu(AppState.normalizedNodes, ATON.UI.elSidePanel.querySelector('#layer'));
buildOntologyMenu(await traverseOntology(ontologyJsonPath), ATON.UI.elSidePanel.querySelector('#content'));
});
}
/**
* @todo Don't rebuild it every time the side panel is shown...
* @param {Array} nodes The normalized scene nodes (IDs and status)
* @param {HTMLElement} sidePanel ATON's side panel element
*/
function buildLayersMenu(nodes, sidePanel) {
for(let node of nodes) {
const menuItem = document.createElement('div');
menuItem.className = `form-check form-switch ms-${node.depth} ps-${node.depth} mt-2`;
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.className = "form-check-input";
checkbox.checked = node.active;
checkbox.role = 'switch';
checkbox.title = "Mostra / nascondi layer";
menuItem.appendChild(checkbox);
const label = document.createElement('label');
label.className = "form-check-label";
label.textContent = node.id;
menuItem.appendChild(label);
sidePanel.appendChild(menuItem);
// Will this ever work??
menuItem.addEventListener('change', event => toggleNode(node.id, event.target.checked));
}
/**
* This is terrible...
* @param {String} id
* @param {Boolean} status
*/
const toggleNode = (id, status) => {
ATON.getSceneNode(id).toggle(status);
AppState.normalizedNodes.find(n => n.id === id).active = status;
}
}
/**
* @see traverseOntology
* @param {Object} ontology The traversed ontology object (temp)
* @param {HTMLElement} sidePanel ATON's side panel element
*/
function buildOntologyMenu(ontology, sidePanel) {
const list = document.createElement('ul');
list.className = 'list-group';
const mainNode = document.createElement('li');
mainNode.className = 'list-group-item';
mainNode.textContent = ontology.ontology;
const domainList = document.createElement('ul');
domainList.className = 'list-group';
for(let domain of ontology.domains) {
const domainItem = document.createElement('li');
domainItem.textContent = domain.label;
domainItem.className = 'list-group-item';
domainList.appendChild(domainItem);
}
mainNode.appendChild(domainList);
list.appendChild(mainNode);
sidePanel.appendChild(list);
}
/**
* Initialize required components for scene UI
* @param {String} ontologyJsonPath
*/
export async function initUI(ontologyJsonPath) {
toggleContentMenu('menu', ontologyJsonPath);
}