589 lines
18 KiB
JavaScript
589 lines
18 KiB
JavaScript
|
const interfaceWrapper = document.getElementById("interface-wrapper");
|
||
|
const moduleWrapper = document.createElement("div");
|
||
|
moduleWrapper.setAttribute("id", "module-wrapper");
|
||
|
interfaceWrapper.appendChild(moduleWrapper);
|
||
|
|
||
|
const isMobile = new RegExp(/Android|webOS|iPhone|iPad|BlackBerry|Windows Phone|Opera Mini|IEMobile|Mobile/).test(navigator.userAgent);
|
||
|
|
||
|
const styles = ["light", "medium", "heavy"];
|
||
|
let currentStyle = styles[0];
|
||
|
if (localStorage.style) {
|
||
|
currentStyle = styles[localStorage.style];
|
||
|
} else {
|
||
|
localStorage.style = "0";
|
||
|
}
|
||
|
const modules = [];
|
||
|
|
||
|
//GENERAL FUNCTIONS
|
||
|
function loadSVG(path, callback) {
|
||
|
let xhr = new XMLHttpRequest();
|
||
|
xhr.open("GET", path, true);
|
||
|
// Following line is just to be on the safe side;
|
||
|
// not needed if your server delivers SVG with correct MIME type
|
||
|
xhr.overrideMimeType("image/svg+xml");
|
||
|
|
||
|
xhr.onreadystatechange = function () {
|
||
|
if (xhr.readyState == 4 && xhr.status === 200) {
|
||
|
// Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
|
||
|
callback(xhr.responseXML.documentElement);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
xhr.send();
|
||
|
}
|
||
|
|
||
|
function createModule(titleText) {
|
||
|
let div = document.createElement("div");
|
||
|
div.classList = ["module module-out"];
|
||
|
let title = document.createElement("h2");
|
||
|
title.innerHTML = titleText;
|
||
|
div.appendChild(title);
|
||
|
modules.push(div);
|
||
|
moduleWrapper.appendChild(div);
|
||
|
return div;
|
||
|
}
|
||
|
|
||
|
//STYLE SPECIFICS GENERATION
|
||
|
function createToggleCheckbox(scope, parent, config) {
|
||
|
|
||
|
let wrapper = document.createElement("div");
|
||
|
wrapper.classList = "module-row";
|
||
|
|
||
|
let header = document.createElement("h4");
|
||
|
header.style = "width: fit-content;position: absolute;right: 50%;";
|
||
|
header.innerHTML = config.name;
|
||
|
|
||
|
let container = document.createElement("label");
|
||
|
container.classList = "checkbox-container";
|
||
|
let checkBox = document.createElement("input");
|
||
|
if (config.default) {
|
||
|
checkBox.checked = "checked";
|
||
|
}
|
||
|
checkBox.type = "checkbox";
|
||
|
let span = document.createElement("span");
|
||
|
span.classList = "checkmark";
|
||
|
|
||
|
checkBox.addEventListener("input", function () {
|
||
|
config.callback(checkBox.checked);
|
||
|
}, false);
|
||
|
|
||
|
container.appendChild(checkBox);
|
||
|
container.appendChild(span);
|
||
|
wrapper.appendChild(header);
|
||
|
wrapper.appendChild(container);
|
||
|
parent.appendChild(wrapper);
|
||
|
}
|
||
|
|
||
|
function createToggleSwitch(scope, parent, config) {
|
||
|
|
||
|
let wrapper = document.createElement("div");
|
||
|
wrapper.classList = "module-row";
|
||
|
|
||
|
let header = document.createElement("h4");
|
||
|
header.innerHTML = config.name;
|
||
|
|
||
|
let switchContainer = document.createElement("label");
|
||
|
switchContainer.classList = "switch-container";
|
||
|
|
||
|
let checkbox = document.createElement("input");
|
||
|
checkbox.type = "checkbox";
|
||
|
checkbox.addEventListener("input", function () {
|
||
|
config.callback(checkbox.checked);
|
||
|
});
|
||
|
checkbox.checked = true //_default;
|
||
|
|
||
|
let span = document.createElement("span");
|
||
|
span.classList = "slider";
|
||
|
|
||
|
wrapper.appendChild(header);
|
||
|
switchContainer.appendChild(checkbox);
|
||
|
switchContainer.appendChild(span);
|
||
|
wrapper.appendChild(switchContainer);
|
||
|
parent.appendChild(wrapper);
|
||
|
|
||
|
}
|
||
|
|
||
|
function createToggleTabs(scope, parent, config) {
|
||
|
let wrapper = document.createElement("div");
|
||
|
wrapper.classList.add("module-row");
|
||
|
let buttonWrapper = document.createElement("div");
|
||
|
buttonWrapper.classList.add("toggle-wrapper");
|
||
|
let header = document.createElement("h4");
|
||
|
let left = document.createElement("div");
|
||
|
let pL = document.createElement("p");
|
||
|
pL.innerHTML = "An";
|
||
|
left.appendChild(pL);
|
||
|
left.classList = "toggle-left";
|
||
|
let right = document.createElement("div");
|
||
|
let pR = document.createElement("p");
|
||
|
pR.innerHTML = "Aus";
|
||
|
right.appendChild(pR);
|
||
|
left.classList = "toggle-left";
|
||
|
right.innerHMTL = "Aus";
|
||
|
right.classList = "toggle-right";
|
||
|
left.addEventListener("click", function () {
|
||
|
left.classList.add("toggle-active");
|
||
|
right.classList.remove("toggle-active");
|
||
|
config.callback(true);
|
||
|
});
|
||
|
right.addEventListener("click", function () {
|
||
|
left.classList.remove("toggle-active");
|
||
|
right.classList.add("toggle-active");
|
||
|
config.callback(false);
|
||
|
});
|
||
|
|
||
|
//SET THE DEFAULTS
|
||
|
if (config.default) {
|
||
|
left.classList.add("toggle-active");
|
||
|
} else {
|
||
|
right.classList.add("toggle-active");
|
||
|
}
|
||
|
|
||
|
header.innerHTML = name;
|
||
|
|
||
|
wrapper.appendChild(header);
|
||
|
buttonWrapper.appendChild(left);
|
||
|
buttonWrapper.appendChild(right);
|
||
|
wrapper.appendChild(buttonWrapper);
|
||
|
parent.appendChild(wrapper);
|
||
|
}
|
||
|
|
||
|
//GENERAL INTERFACE GENERATION
|
||
|
function createButton(scope, parent, config) {
|
||
|
let div = document.createElement("div");
|
||
|
let title = document.createElement("h4");
|
||
|
div.classList.add("button");
|
||
|
title.innerHTML = config.name;
|
||
|
div.appendChild(title);
|
||
|
parent.appendChild(div);
|
||
|
div.addEventListener("click", function () {
|
||
|
callback();
|
||
|
}, false);
|
||
|
};
|
||
|
|
||
|
function createSlider(scope, parent, config) {
|
||
|
|
||
|
let div = document.createElement("div");
|
||
|
div.classList.add("module-row");
|
||
|
let title = document.createElement("h4");
|
||
|
title.innerHTML = config.name + " " + config.default * 100 + " %";
|
||
|
let slider = document.createElement("input");
|
||
|
slider.value = config.default * 100;
|
||
|
slider.type = "range";
|
||
|
slider.min = config.min;
|
||
|
slider.max = config.max;
|
||
|
|
||
|
slider.addEventListener("input", function () {
|
||
|
config.callback(slider.value);
|
||
|
title.innerHTML = config.name + " " + slider.value + "%";
|
||
|
});
|
||
|
|
||
|
function handleOut() {
|
||
|
moduleWrapper.style.transition = "all 0s";
|
||
|
title.style.visibility = "visible";
|
||
|
interfaceWrapper.style.visibility = "hidden";
|
||
|
moduleWrapper.style.visibility = "hidden";
|
||
|
slider.style.visibility = "visible";
|
||
|
scope.rendering = true;
|
||
|
}
|
||
|
|
||
|
function handleIn() {
|
||
|
moduleWrapper.style.transition = "";
|
||
|
interfaceWrapper.style.visibility = "";
|
||
|
title.style.visibility = "";
|
||
|
moduleWrapper.style.visibility = "visible";
|
||
|
slider.style.visibility = "";
|
||
|
scope.rendering = false;
|
||
|
}
|
||
|
|
||
|
//HIDE THE BACKGROUND ON CHANGE
|
||
|
if (config.name === "Render Auflösung") {
|
||
|
slider.id = "render-quality-slider";
|
||
|
title.id = "render-quality-title";
|
||
|
if (isMobile) {
|
||
|
slider.addEventListener("touchstart", function () {
|
||
|
handleOut();
|
||
|
}, false);
|
||
|
slider.addEventListener("touchend", function () {
|
||
|
handleIn();
|
||
|
}, false);
|
||
|
slider.addEventListener("touchcancel", function () {
|
||
|
handleIn();
|
||
|
}, false);
|
||
|
} else {
|
||
|
slider.addEventListener("mousedown", function () {
|
||
|
handleOut();
|
||
|
}, false);
|
||
|
|
||
|
slider.addEventListener("mouseup", function () {
|
||
|
handleIn();
|
||
|
}, false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
div.appendChild(title);
|
||
|
div.appendChild(slider);
|
||
|
parent.appendChild(div);
|
||
|
|
||
|
}
|
||
|
|
||
|
function createToggle(scope, parent, config) {
|
||
|
switch (currentStyle) {
|
||
|
case "light":
|
||
|
createToggleSwitch(scope, parent, config);
|
||
|
break;
|
||
|
case "medium":
|
||
|
createToggleCheckbox(scope, parent, config);
|
||
|
break;
|
||
|
case "heavy":
|
||
|
createToggleTabs(scope, parent, config);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function createDropdown(scope, parent, config) {
|
||
|
let wrapper = document.createElement("div");
|
||
|
wrapper.classList = "module-row";
|
||
|
|
||
|
let header = document.createElement("h4");
|
||
|
header.innerHTML = name;
|
||
|
|
||
|
let selectWrapper = document.createElement("div");
|
||
|
selectWrapper.classList = "select-wrapper";
|
||
|
|
||
|
let select = document.createElement("select");
|
||
|
|
||
|
let active;
|
||
|
for (let i = 0; i < config.options.length; i++) {
|
||
|
let _option = document.createElement("option");
|
||
|
_option.innerHTML = config.options[i];
|
||
|
_option.setAttribute("value", i);
|
||
|
if (localStorage.style == styles.indexOf(config.options[i])) {
|
||
|
_option.selected = "selected";
|
||
|
active = _option;
|
||
|
}
|
||
|
select.appendChild(_option);
|
||
|
}
|
||
|
|
||
|
select.addEventListener("change", function (ev) {
|
||
|
header.innerHTML = ev.srcElement.innerHTML;
|
||
|
config.callback(this.value);
|
||
|
});
|
||
|
|
||
|
wrapper.appendChild(header);
|
||
|
selectWrapper.append(select);
|
||
|
wrapper.appendChild(selectWrapper);
|
||
|
parent.appendChild(wrapper);
|
||
|
}
|
||
|
|
||
|
//EXPORT CLASS
|
||
|
export default class UserInterface {
|
||
|
|
||
|
constructor(lights, renderer, controls) {
|
||
|
|
||
|
var scope = this;
|
||
|
|
||
|
this.rendering = true;
|
||
|
|
||
|
this.state = false;
|
||
|
|
||
|
this.fullscreenState = false;
|
||
|
|
||
|
//SET CURRENT STYLE
|
||
|
interfaceWrapper.classList = currentStyle;
|
||
|
|
||
|
this.config = [
|
||
|
|
||
|
{
|
||
|
name: "Qualität",
|
||
|
children: [{
|
||
|
type: "slider",
|
||
|
mobileOnly: false,
|
||
|
name: "Render Auflösung",
|
||
|
default: renderer.getPixelRatio(),
|
||
|
min: 20,
|
||
|
max: 200,
|
||
|
callback: function (val) {
|
||
|
renderer.setPixelRatio(val / 100);
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
type: "toggle",
|
||
|
mobileOnly: false,
|
||
|
name: "High Quality Lights",
|
||
|
default: lights.state,
|
||
|
callback: function (val) {
|
||
|
if (val) {
|
||
|
lights.enable();
|
||
|
} else {
|
||
|
lights.disable();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
name: "Steuerung",
|
||
|
children: [{
|
||
|
type: "slider",
|
||
|
mobileOnly: false,
|
||
|
name: "Geschwindigkeit",
|
||
|
default: controls.lookSpeed,
|
||
|
min: 0,
|
||
|
max: 200,
|
||
|
callback: function (val) {
|
||
|
controls.lookSpeed = val / 100;
|
||
|
localStorage.lookSpeed = controls.lookSpeed;
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
type: "toggle",
|
||
|
mobileOnly: false,
|
||
|
name: "Nachziehen",
|
||
|
default: controls.drag,
|
||
|
callback: function (val) {
|
||
|
controls.drag = val;
|
||
|
localStorage.drag = controls.drag;
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
type: "toggle",
|
||
|
mobileOnly: false,
|
||
|
name: "Automatisch drehen",
|
||
|
default: controls.autoRotate,
|
||
|
callback: function (val) {
|
||
|
controls.autoRotate = val;
|
||
|
localStorage.autoRotate = controls.autoRotate;
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
type: "toggle",
|
||
|
mobileOnly: true,
|
||
|
name: "Geräte Drehung nutzen",
|
||
|
default: controls.deviceorientation,
|
||
|
callback: function (val) {
|
||
|
controls.deviceorientation = val;
|
||
|
localStorage.deviceorientation = controls.deviceorientation;
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
type: "slider",
|
||
|
mobileOnly: true,
|
||
|
name: "Geräte Drehung Geschwindigkeit",
|
||
|
default: controls.deviceorientationSpeed * 100,
|
||
|
min: 10,
|
||
|
max: 150,
|
||
|
callback: function (val) {
|
||
|
controls.deviceorientationSpeed = val / 1000;
|
||
|
localStorage.deviceorientationSpeed = controls.deviceorientationSpeed;
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
type: "button",
|
||
|
mobileOnly: false,
|
||
|
name: "Kamera zurücksetzen",
|
||
|
callback: function () {
|
||
|
controls.reset();
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
name: "Interface",
|
||
|
children: [{
|
||
|
type: "dropdown",
|
||
|
mobileOnly: false,
|
||
|
name: "Stil",
|
||
|
options: [
|
||
|
"light",
|
||
|
"medium",
|
||
|
"heavy"
|
||
|
],
|
||
|
callback: function (val) {
|
||
|
scope.setStyle(val);
|
||
|
console.log("Setting val " + val);
|
||
|
localStorage.style = val;
|
||
|
}
|
||
|
}]
|
||
|
}
|
||
|
|
||
|
];
|
||
|
|
||
|
this.loadConfig();
|
||
|
|
||
|
}
|
||
|
|
||
|
loadConfig(callback) {
|
||
|
|
||
|
var scope = this;
|
||
|
|
||
|
//LOAD THE COGWHEEL OPTIONS
|
||
|
loadSVG("./icons/" + currentStyle + "_options.svg", (svg) => {
|
||
|
this.cogwheel = svg;
|
||
|
this.cogwheel.classList = "cogwheel";
|
||
|
this.cogwheel.addEventListener("click", () => {
|
||
|
this.toggle();
|
||
|
}, false);
|
||
|
interfaceWrapper.insertBefore(this.cogwheel, interfaceWrapper.firstChild);
|
||
|
});
|
||
|
|
||
|
//LOAD THE FULLSCREEN ICON
|
||
|
loadSVG("./icons/" + currentStyle + "_fullscreen.svg", (svg) => {
|
||
|
this.fullscreen = svg;
|
||
|
this.fullscreen.classList = "fullscreen";
|
||
|
this.fullscreen.addEventListener("click", () => {
|
||
|
this.toggleFullscreen();
|
||
|
}, false);
|
||
|
interfaceWrapper.insertBefore(this.fullscreen, interfaceWrapper.firstChild);
|
||
|
});
|
||
|
|
||
|
//CREATE ALL CHILDREN OF THE MODULE
|
||
|
for (let i = 0; i < this.config.length; i++) {
|
||
|
|
||
|
let _module = createModule(this.config[i].name);
|
||
|
|
||
|
for (let j = 0; j < this.config[i].children.length; j++) {
|
||
|
|
||
|
let obj = this.config[i].children[j];
|
||
|
|
||
|
if (isMobile === false && obj.mobileOnly === true) {
|
||
|
//DONT DO ANYTHING
|
||
|
} else {
|
||
|
|
||
|
//CREATE HAIR LINES
|
||
|
if (currentStyle !== "heavy") {
|
||
|
let hr = document.createElement("hr");
|
||
|
_module.appendChild(hr);
|
||
|
}
|
||
|
|
||
|
switch (obj.type) {
|
||
|
case "toggle":
|
||
|
createToggle(this, _module, obj);
|
||
|
break;
|
||
|
case "slider":
|
||
|
createSlider(this, _module, obj);
|
||
|
break;
|
||
|
case "button":
|
||
|
createButton(this, _module, obj);
|
||
|
break;
|
||
|
case "dropdown":
|
||
|
createDropdown(this, _module, obj);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (callback) {
|
||
|
callback();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
toggleFullscreen() {
|
||
|
if (this.fullscreenState) {
|
||
|
this.fullscreenState = false;
|
||
|
if (document.exitFullscreen) {
|
||
|
document.exitFullscreen();
|
||
|
} else if (document.mozCancelFullScreen) {
|
||
|
document.mozCancelFullScreen();
|
||
|
} else if (document.webkitExitFullscreen) {
|
||
|
document.webkitExitFullscreen();
|
||
|
}
|
||
|
} else {
|
||
|
this.fullscreenState = true;
|
||
|
if (document.documentElement.requestFullscreen) {
|
||
|
document.documentElement.requestFullscreen();
|
||
|
} else if (document.documentElement.mozRequestFullScreen) {
|
||
|
document.documentElement.mozRequestFullScreen();
|
||
|
} else if (document.documentElement.webkitRequestFullscreen) {
|
||
|
document.documentElement.webkitRequestFullscreen();
|
||
|
} else if (document.documentElement.msRequestFullscreen) {
|
||
|
document.documentElement.msRequestFullscreen();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
setStyle(style) {
|
||
|
|
||
|
var scope = this;
|
||
|
|
||
|
modules.length = 0;
|
||
|
|
||
|
currentStyle = styles[style];
|
||
|
interfaceWrapper.classList = currentStyle;
|
||
|
|
||
|
//REMOVE ALL CHILDREN
|
||
|
while (moduleWrapper.firstChild) {
|
||
|
moduleWrapper.removeChild(moduleWrapper.firstChild);
|
||
|
}
|
||
|
|
||
|
interfaceWrapper.removeChild(this.cogwheel);
|
||
|
interfaceWrapper.removeChild(this.fullscreen);
|
||
|
|
||
|
this.loadConfig(function () {
|
||
|
scope.animIn();
|
||
|
});
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
setRenderQuality(val) {
|
||
|
document.getElementById("render-quality-slider").value = Math.floor(val * 100);
|
||
|
document.getElementById("render-quality-title").innerHTML = "Render Auflösung " + Math.floor(val * 100) + "%";
|
||
|
}
|
||
|
|
||
|
animIn() {
|
||
|
this.state = true;
|
||
|
interfaceWrapper.classList.add("interface-in");
|
||
|
this.cogwheel.classList.add("cogwheel-in");
|
||
|
|
||
|
let i = modules.length - 1;
|
||
|
modules[i].classList.remove("module-out");
|
||
|
let int = window.setInterval(function () {
|
||
|
i--;
|
||
|
if (i >= 0) {
|
||
|
modules[i].classList.remove("module-out");
|
||
|
} else {
|
||
|
moduleWrapper.style.visibility = "visible";
|
||
|
clearInterval(int);
|
||
|
}
|
||
|
}, 100);
|
||
|
}
|
||
|
|
||
|
animOut() {
|
||
|
this.state = false;
|
||
|
interfaceWrapper.classList.remove("interface-in");
|
||
|
this.cogwheel.classList.remove("cogwheel-in");
|
||
|
|
||
|
let i = modules.length - 1;
|
||
|
modules[i].classList.add("module-out");
|
||
|
let int = window.setInterval(function () {
|
||
|
i--;
|
||
|
if (i >= 0) {
|
||
|
modules[i].classList.add("module-out");
|
||
|
} else {
|
||
|
moduleWrapper.style.visibility = "hidden";
|
||
|
clearInterval(int);
|
||
|
}
|
||
|
|
||
|
}, 100);
|
||
|
}
|
||
|
|
||
|
toggle() {
|
||
|
|
||
|
if (this.state) {
|
||
|
this.animOut();
|
||
|
this.rendering = true;
|
||
|
} else {
|
||
|
this.rendering = false;
|
||
|
this.animIn();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|