playcanvas
Version:
PlayCanvas WebGL game engine
2,032 lines (1,637 loc) • 2.16 MB
JavaScript
/**
* @license
* PlayCanvas Engine v1.41.0-dev revision bbc2326ad (PROFILER)
* Copyright 2011-2021 PlayCanvas Ltd. All rights reserved.
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.pc = {}));
}(this, (function (exports) { 'use strict';
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
value: function value(predicate) {
if (this == null) {
throw TypeError('"this" is null or not defined');
}
var o = Object(this);
var len = o.length >>> 0;
if (typeof predicate !== 'function') {
throw TypeError('predicate must be a function');
}
var thisArg = arguments[1];
var k = 0;
while (k < len) {
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
}
k++;
}
return undefined;
},
configurable: true,
writable: true
});
}
if (!Array.prototype.findIndex) {
Object.defineProperty(Array.prototype, 'findIndex', {
value: function value(predicate) {
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
var o = Object(this);
var len = o.length >>> 0;
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var thisArg = arguments[1];
var k = 0;
while (k < len) {
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return k;
}
k++;
}
return -1;
},
configurable: true,
writable: true
});
}
Math.log2 = Math.log2 || function (x) {
return Math.log(x) * Math.LOG2E;
};
if (!Math.sign) {
Math.sign = function (x) {
return (x > 0) - (x < 0) || +x;
};
}
if (Number.isFinite === undefined) Number.isFinite = function (value) {
return typeof value === 'number' && isFinite(value);
};
if (typeof Object.assign != 'function') {
Object.defineProperty(Object, "assign", {
value: function assign(target, varArgs) {
if (target == null) {
throw new TypeError('Cannot convert undefined or null to object');
}
var to = Object(target);
for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index];
if (nextSource != null) {
for (var nextKey in nextSource) {
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
},
writable: true,
configurable: true
});
}
(function () {
if (typeof navigator === 'undefined' || typeof document === 'undefined') {
return;
}
navigator.pointer = navigator.pointer || navigator.webkitPointer || navigator.mozPointer;
var pointerlockchange = function pointerlockchange() {
var e = document.createEvent('CustomEvent');
e.initCustomEvent('pointerlockchange', true, false, null);
document.dispatchEvent(e);
};
var pointerlockerror = function pointerlockerror() {
var e = document.createEvent('CustomEvent');
e.initCustomEvent('pointerlockerror', true, false, null);
document.dispatchEvent(e);
};
document.addEventListener('webkitpointerlockchange', pointerlockchange, false);
document.addEventListener('webkitpointerlocklost', pointerlockchange, false);
document.addEventListener('mozpointerlockchange', pointerlockchange, false);
document.addEventListener('mozpointerlocklost', pointerlockchange, false);
document.addEventListener('webkitpointerlockerror', pointerlockerror, false);
document.addEventListener('mozpointerlockerror', pointerlockerror, false);
if (Element.prototype.mozRequestPointerLock) {
Element.prototype.requestPointerLock = function () {
this.mozRequestPointerLock();
};
} else {
Element.prototype.requestPointerLock = Element.prototype.requestPointerLock || Element.prototype.webkitRequestPointerLock || Element.prototype.mozRequestPointerLock;
}
if (!Element.prototype.requestPointerLock && navigator.pointer) {
Element.prototype.requestPointerLock = function () {
var el = this;
document.pointerLockElement = el;
navigator.pointer.lock(el, pointerlockchange, pointerlockerror);
};
}
document.exitPointerLock = document.exitPointerLock || document.webkitExitPointerLock || document.mozExitPointerLock;
if (!document.exitPointerLock) {
document.exitPointerLock = function () {
if (navigator.pointer) {
document.pointerLockElement = null;
navigator.pointer.unlock();
}
};
}
})();
(function () {
if (typeof window === 'undefined') return;
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame) window.requestAnimationFrame = function (callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function () {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function (id) {
clearTimeout(id);
};
})();
if (!String.prototype.endsWith) {
String.prototype.endsWith = function (search, this_len) {
if (this_len === undefined || this_len > this.length) {
this_len = this.length;
}
return this.substring(this_len - search.length, this_len) === search;
};
}
if (!String.prototype.includes) {
String.prototype.includes = function (search, start) {
if (typeof start !== 'number') {
start = 0;
}
if (start + search.length > this.length) {
return false;
} else {
return this.indexOf(search, start) !== -1;
}
};
}
if (!String.prototype.startsWith) {
String.prototype.startsWith = function (search, pos) {
return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
};
}
(function () {
var glErrorShadow = {};
function error(msg) {
if (window.console && window.console.error) {
window.console.error(msg);
}
}
function log(msg) {
if (window.console && window.console.log) {
window.console.log(msg);
}
}
function synthesizeGLError(err, opt_msg) {
glErrorShadow[err] = true;
if (opt_msg !== undefined) {
error(opt_msg);
}
}
function wrapGLError(gl) {
var f = gl.getError;
gl.getError = function () {
var err;
do {
err = f.apply(gl);
if (err != gl.NO_ERROR) {
glErrorShadow[err] = true;
}
} while (err != gl.NO_ERROR);
for (var err in glErrorShadow) {
if (glErrorShadow[err]) {
delete glErrorShadow[err];
return parseInt(err);
}
}
return gl.NO_ERROR;
};
}
var WebGLVertexArrayObjectOES = function WebGLVertexArrayObjectOES(ext) {
var gl = ext.gl;
this.ext = ext;
this.isAlive = true;
this.hasBeenBound = false;
this.elementArrayBuffer = null;
this.attribs = new Array(ext.maxVertexAttribs);
for (var n = 0; n < this.attribs.length; n++) {
var attrib = new WebGLVertexArrayObjectOES.VertexAttrib(gl);
this.attribs[n] = attrib;
}
this.maxAttrib = 0;
};
WebGLVertexArrayObjectOES.VertexAttrib = function VertexAttrib(gl) {
this.enabled = false;
this.buffer = null;
this.size = 4;
this.type = gl.FLOAT;
this.normalized = false;
this.stride = 16;
this.offset = 0;
this.cached = "";
this.recache();
};
WebGLVertexArrayObjectOES.VertexAttrib.prototype.recache = function recache() {
this.cached = [this.size, this.type, this.normalized, this.stride, this.offset].join(":");
};
var OESVertexArrayObject = function OESVertexArrayObject(gl) {
var self = this;
this.gl = gl;
wrapGLError(gl);
var original = this.original = {
getParameter: gl.getParameter,
enableVertexAttribArray: gl.enableVertexAttribArray,
disableVertexAttribArray: gl.disableVertexAttribArray,
bindBuffer: gl.bindBuffer,
getVertexAttrib: gl.getVertexAttrib,
vertexAttribPointer: gl.vertexAttribPointer
};
gl.getParameter = function getParameter(pname) {
if (pname == self.VERTEX_ARRAY_BINDING_OES) {
if (self.currentVertexArrayObject == self.defaultVertexArrayObject) {
return null;
} else {
return self.currentVertexArrayObject;
}
}
return original.getParameter.apply(this, arguments);
};
gl.enableVertexAttribArray = function enableVertexAttribArray(index) {
var vao = self.currentVertexArrayObject;
vao.maxAttrib = Math.max(vao.maxAttrib, index);
var attrib = vao.attribs[index];
attrib.enabled = true;
return original.enableVertexAttribArray.apply(this, arguments);
};
gl.disableVertexAttribArray = function disableVertexAttribArray(index) {
var vao = self.currentVertexArrayObject;
vao.maxAttrib = Math.max(vao.maxAttrib, index);
var attrib = vao.attribs[index];
attrib.enabled = false;
return original.disableVertexAttribArray.apply(this, arguments);
};
gl.bindBuffer = function bindBuffer(target, buffer) {
switch (target) {
case gl.ARRAY_BUFFER:
self.currentArrayBuffer = buffer;
break;
case gl.ELEMENT_ARRAY_BUFFER:
self.currentVertexArrayObject.elementArrayBuffer = buffer;
break;
}
return original.bindBuffer.apply(this, arguments);
};
gl.getVertexAttrib = function getVertexAttrib(index, pname) {
var vao = self.currentVertexArrayObject;
var attrib = vao.attribs[index];
switch (pname) {
case gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
return attrib.buffer;
case gl.VERTEX_ATTRIB_ARRAY_ENABLED:
return attrib.enabled;
case gl.VERTEX_ATTRIB_ARRAY_SIZE:
return attrib.size;
case gl.VERTEX_ATTRIB_ARRAY_STRIDE:
return attrib.stride;
case gl.VERTEX_ATTRIB_ARRAY_TYPE:
return attrib.type;
case gl.VERTEX_ATTRIB_ARRAY_NORMALIZED:
return attrib.normalized;
default:
return original.getVertexAttrib.apply(this, arguments);
}
};
gl.vertexAttribPointer = function vertexAttribPointer(indx, size, type, normalized, stride, offset) {
var vao = self.currentVertexArrayObject;
vao.maxAttrib = Math.max(vao.maxAttrib, indx);
var attrib = vao.attribs[indx];
attrib.buffer = self.currentArrayBuffer;
attrib.size = size;
attrib.type = type;
attrib.normalized = normalized;
attrib.stride = stride;
attrib.offset = offset;
attrib.recache();
return original.vertexAttribPointer.apply(this, arguments);
};
if (gl.instrumentExtension) {
gl.instrumentExtension(this, "OES_vertex_array_object");
}
gl.canvas.addEventListener('webglcontextrestored', function () {
log("OESVertexArrayObject emulation library context restored");
self.reset_();
}, true);
this.reset_();
};
OESVertexArrayObject.prototype.VERTEX_ARRAY_BINDING_OES = 0x85B5;
OESVertexArrayObject.prototype.reset_ = function reset_() {
var contextWasLost = this.vertexArrayObjects !== undefined;
if (contextWasLost) {
for (var ii = 0; ii < this.vertexArrayObjects.length; ++ii) {
this.vertexArrayObjects.isAlive = false;
}
}
var gl = this.gl;
this.maxVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
this.defaultVertexArrayObject = new WebGLVertexArrayObjectOES(this);
this.currentVertexArrayObject = null;
this.currentArrayBuffer = null;
this.vertexArrayObjects = [this.defaultVertexArrayObject];
this.bindVertexArrayOES(null);
};
OESVertexArrayObject.prototype.createVertexArrayOES = function createVertexArrayOES() {
var arrayObject = new WebGLVertexArrayObjectOES(this);
this.vertexArrayObjects.push(arrayObject);
return arrayObject;
};
OESVertexArrayObject.prototype.deleteVertexArrayOES = function deleteVertexArrayOES(arrayObject) {
arrayObject.isAlive = false;
this.vertexArrayObjects.splice(this.vertexArrayObjects.indexOf(arrayObject), 1);
if (this.currentVertexArrayObject == arrayObject) {
this.bindVertexArrayOES(null);
}
};
OESVertexArrayObject.prototype.isVertexArrayOES = function isVertexArrayOES(arrayObject) {
if (arrayObject && arrayObject instanceof WebGLVertexArrayObjectOES) {
if (arrayObject.hasBeenBound && arrayObject.ext == this) {
return true;
}
}
return false;
};
OESVertexArrayObject.prototype.bindVertexArrayOES = function bindVertexArrayOES(arrayObject) {
var gl = this.gl;
if (arrayObject && !arrayObject.isAlive) {
synthesizeGLError(gl.INVALID_OPERATION, "bindVertexArrayOES: attempt to bind deleted arrayObject");
return;
}
var original = this.original;
var oldVAO = this.currentVertexArrayObject;
this.currentVertexArrayObject = arrayObject || this.defaultVertexArrayObject;
this.currentVertexArrayObject.hasBeenBound = true;
var newVAO = this.currentVertexArrayObject;
if (oldVAO == newVAO) {
return;
}
if (!oldVAO || newVAO.elementArrayBuffer != oldVAO.elementArrayBuffer) {
original.bindBuffer.call(gl, gl.ELEMENT_ARRAY_BUFFER, newVAO.elementArrayBuffer);
}
var currentBinding = this.currentArrayBuffer;
var maxAttrib = Math.max(oldVAO ? oldVAO.maxAttrib : 0, newVAO.maxAttrib);
for (var n = 0; n <= maxAttrib; n++) {
var attrib = newVAO.attribs[n];
var oldAttrib = oldVAO ? oldVAO.attribs[n] : null;
if (!oldVAO || attrib.enabled != oldAttrib.enabled) {
if (attrib.enabled) {
original.enableVertexAttribArray.call(gl, n);
} else {
original.disableVertexAttribArray.call(gl, n);
}
}
if (attrib.enabled) {
var bufferChanged = false;
if (!oldVAO || attrib.buffer != oldAttrib.buffer) {
if (currentBinding != attrib.buffer) {
original.bindBuffer.call(gl, gl.ARRAY_BUFFER, attrib.buffer);
currentBinding = attrib.buffer;
}
bufferChanged = true;
}
if (bufferChanged || attrib.cached != oldAttrib.cached) {
original.vertexAttribPointer.call(gl, n, attrib.size, attrib.type, attrib.normalized, attrib.stride, attrib.offset);
}
}
}
if (this.currentArrayBuffer != currentBinding) {
original.bindBuffer.call(gl, gl.ARRAY_BUFFER, this.currentArrayBuffer);
}
};
window.setupVertexArrayObject = function (gl) {
if (gl.getSupportedExtensions) {
var exts = gl.getSupportedExtensions();
if (exts.indexOf("OES_vertex_array_object") != -1) {
return;
}
} else if (gl.getExtension) {
var vao = gl.getExtension("OES_vertex_array_object");
if (vao) {
return;
}
}
if (gl.getSupportedExtensions) {
var original_getSupportedExtensions = gl.getSupportedExtensions;
gl.getSupportedExtensions = function getSupportedExtensions() {
var list = original_getSupportedExtensions.call(this) || [];
list.push("OES_vertex_array_object");
return list;
};
}
var original_getExtension = gl.getExtension;
gl.getExtension = function getExtension(name) {
if (name == "OES_vertex_array_object") {
if (!gl.__OESVertexArrayObject) {
gl.__OESVertexArrayObject = new OESVertexArrayObject(gl);
}
return gl.__OESVertexArrayObject;
}
if (original_getExtension) {
return original_getExtension.call(this, name);
} else {
return null;
}
};
};
})();
var _typeLookup = function () {
var result = {};
var names = ["Array", "Object", "Function", "Date", "RegExp", "Float32Array"];
for (var i = 0; i < names.length; i++) {
result["[object " + names[i] + "]"] = names[i].toLowerCase();
}
return result;
}();
var version = "1.41.0-dev";
var revision = "bbc2326ad";
var config = {};
var common = {};
var apps = {};
var data = {};
function type$1(obj) {
if (obj === null) {
return "null";
}
var type = typeof obj;
if (type === "undefined" || type === "number" || type === "string" || type === "boolean") {
return type;
}
return _typeLookup[Object.prototype.toString.call(obj)];
}
function extend(target, ex) {
for (var prop in ex) {
var copy = ex[prop];
if (type$1(copy) === "object") {
target[prop] = extend({}, copy);
} else if (type$1(copy) === "array") {
target[prop] = extend([], copy);
} else {
target[prop] = copy;
}
}
return target;
}
function isDefined(o) {
var a;
return o !== a;
}
var table = null;
var row = null;
var title = null;
var field = null;
function init() {
table = document.createElement('table');
row = document.createElement('tr');
title = document.createElement('td');
field = document.createElement('td');
table.style.cssText = 'position:absolute;font-family:sans-serif;font-size:12px;color:#cccccc';
table.style.top = '0px';
table.style.left = '0px';
table.style.border = 'thin solid #cccccc';
document.body.appendChild(table);
}
var debug = {
display: function display(data) {
if (!table) {
init();
}
table.innerHTML = '';
for (var key in data) {
var r = row.cloneNode();
var t = title.cloneNode();
var f = field.cloneNode();
t.textContent = key;
f.textContent = data[key];
r.appendChild(t);
r.appendChild(f);
table.appendChild(r);
}
}
};
var EventHandler = function () {
function EventHandler() {
this.initEventHandler();
}
var _proto = EventHandler.prototype;
_proto.initEventHandler = function initEventHandler() {
this._callbacks = {};
this._callbackActive = {};
};
_proto._addCallback = function _addCallback(name, callback, scope, once) {
if (once === void 0) {
once = false;
}
if (!name || typeof name !== 'string' || !callback) return;
if (!this._callbacks[name]) this._callbacks[name] = [];
if (this._callbackActive[name] && this._callbackActive[name] === this._callbacks[name]) this._callbackActive[name] = this._callbackActive[name].slice();
this._callbacks[name].push({
callback: callback,
scope: scope || this,
once: once
});
};
_proto.on = function on(name, callback, scope) {
this._addCallback(name, callback, scope, false);
return this;
};
_proto.off = function off(name, callback, scope) {
if (name) {
if (this._callbackActive[name] && this._callbackActive[name] === this._callbacks[name]) this._callbackActive[name] = this._callbackActive[name].slice();
} else {
for (var key in this._callbackActive) {
if (!this._callbacks[key]) continue;
if (this._callbacks[key] !== this._callbackActive[key]) continue;
this._callbackActive[key] = this._callbackActive[key].slice();
}
}
if (!name) {
this._callbacks = {};
} else if (!callback) {
if (this._callbacks[name]) this._callbacks[name] = [];
} else {
var events = this._callbacks[name];
if (!events) return this;
var count = events.length;
for (var i = 0; i < count; i++) {
if (events[i].callback !== callback) continue;
if (scope && events[i].scope !== scope) continue;
events[i--] = events[--count];
}
events.length = count;
}
return this;
};
_proto.fire = function fire(name, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) {
if (!name || !this._callbacks[name]) return this;
var callbacks;
if (!this._callbackActive[name]) {
this._callbackActive[name] = this._callbacks[name];
} else {
if (this._callbackActive[name] === this._callbacks[name]) this._callbackActive[name] = this._callbackActive[name].slice();
callbacks = this._callbacks[name].slice();
}
for (var i = 0; (callbacks || this._callbackActive[name]) && i < (callbacks || this._callbackActive[name]).length; i++) {
var evt = (callbacks || this._callbackActive[name])[i];
evt.callback.call(evt.scope, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
if (evt.once) {
var ind = this._callbacks[name].indexOf(evt);
if (ind !== -1) {
if (this._callbackActive[name] === this._callbacks[name]) this._callbackActive[name] = this._callbackActive[name].slice();
this._callbacks[name].splice(ind, 1);
}
}
}
if (!callbacks) this._callbackActive[name] = null;
return this;
};
_proto.once = function once(name, callback, scope) {
this._addCallback(name, callback, scope, true);
return this;
};
_proto.hasEvent = function hasEvent(name) {
return this._callbacks[name] && this._callbacks[name].length !== 0 || false;
};
return EventHandler;
}();
var events = {
attach: function attach(target) {
var ev = events;
target._addCallback = ev._addCallback;
target.on = ev.on;
target.off = ev.off;
target.fire = ev.fire;
target.once = ev.once;
target.hasEvent = ev.hasEvent;
target._callbacks = {};
target._callbackActive = {};
return target;
},
_addCallback: EventHandler.prototype._addCallback,
on: EventHandler.prototype.on,
off: EventHandler.prototype.off,
fire: EventHandler.prototype.fire,
once: EventHandler.prototype.once,
hasEvent: EventHandler.prototype.hasEvent
};
var guid = {
create: function create() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0;
var v = c === 'x' ? r : r & 0x3 | 0x8;
return v.toString(16);
});
}
};
var path = {
delimiter: "/",
join: function join() {
var num = arguments.length;
var result = arguments[0];
for (var index = 0; index < num - 1; ++index) {
var one = arguments[index];
var two = arguments[index + 1];
if (!isDefined(one) || !isDefined(two)) {
throw new Error("undefined argument to pc.path.join");
}
if (two[0] === path.delimiter) {
result = two;
continue;
}
if (one && two && one[one.length - 1] !== path.delimiter && two[0] !== path.delimiter) {
result += path.delimiter + two;
} else {
result += two;
}
}
return result;
},
normalize: function normalize(pathname) {
var lead = pathname.startsWith(path.delimiter);
var trail = pathname.endsWith(path.delimiter);
var parts = pathname.split('/');
var result = '';
var cleaned = [];
for (var i = 0; i < parts.length; i++) {
if (parts[i] === '') continue;
if (parts[i] === '.') continue;
if (parts[i] === '..' && cleaned.length > 0) {
cleaned = cleaned.slice(0, cleaned.length - 2);
continue;
}
if (i > 0) cleaned.push(path.delimiter);
cleaned.push(parts[i]);
}
result = cleaned.join('');
if (!lead && result[0] === path.delimiter) {
result = result.slice(1);
}
if (trail && result[result.length - 1] !== path.delimiter) {
result += path.delimiter;
}
return result;
},
split: function split(pathname) {
var parts = pathname.split(path.delimiter);
var tail = parts.slice(parts.length - 1)[0];
var head = parts.slice(0, parts.length - 1).join(path.delimiter);
return [head, tail];
},
getBasename: function getBasename(pathname) {
return path.split(pathname)[1];
},
getDirectory: function getDirectory(pathname) {
var parts = pathname.split(path.delimiter);
return parts.slice(0, parts.length - 1).join(path.delimiter);
},
getExtension: function getExtension(pathname) {
var ext = pathname.split('?')[0].split('.').pop();
if (ext !== pathname) {
return "." + ext;
}
return "";
},
isRelativePath: function isRelativePath(pathname) {
return pathname.charAt(0) !== "/" && pathname.match(/:\/\//) === null;
},
extractPath: function extractPath(pathname) {
var result = "";
var parts = pathname.split("/");
var i = 0;
if (parts.length > 1) {
if (path.isRelativePath(pathname)) {
if (parts[0] === ".") {
for (i = 0; i < parts.length - 1; ++i) {
result += i === 0 ? parts[i] : "/" + parts[i];
}
} else if (parts[0] === "..") {
for (i = 0; i < parts.length - 1; ++i) {
result += i === 0 ? parts[i] : "/" + parts[i];
}
} else {
result = ".";
for (i = 0; i < parts.length - 1; ++i) {
result += "/" + parts[i];
}
}
} else {
for (i = 0; i < parts.length - 1; ++i) {
result += i === 0 ? parts[i] : "/" + parts[i];
}
}
}
return result;
}
};
var desktop = false;
var mobile = false;
var windows = false;
var xbox = false;
var android = false;
var ios = false;
var touch = false;
var gamepads = false;
var workers = false;
var passiveEvents = false;
if (typeof navigator !== 'undefined') {
var ua = navigator.userAgent;
if (/(windows|mac os|linux|cros)/i.test(ua)) desktop = true;
if (/xbox/i.test(ua)) xbox = true;
if (/(windows phone|iemobile|wpdesktop)/i.test(ua)) {
desktop = false;
mobile = true;
windows = true;
} else if (/android/i.test(ua)) {
desktop = false;
mobile = true;
android = true;
} else if (/ip([ao]d|hone)/i.test(ua)) {
desktop = false;
mobile = true;
ios = true;
}
if (typeof window !== 'undefined') {
touch = 'ontouchstart' in window || 'maxTouchPoints' in navigator && navigator.maxTouchPoints > 0;
}
gamepads = 'getGamepads' in navigator;
workers = typeof Worker !== 'undefined';
try {
var opts = Object.defineProperty({}, 'passive', {
get: function get() {
passiveEvents = true;
return false;
}
});
window.addEventListener("testpassive", null, opts);
window.removeEventListener("testpassive", null, opts);
} catch (e) {}
}
var platform = {
desktop: desktop,
mobile: mobile,
ios: ios,
android: android,
windows: windows,
xbox: xbox,
gamepads: gamepads,
touch: touch,
workers: workers,
passiveEvents: passiveEvents
};
var ASCII_LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
var ASCII_UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var ASCII_LETTERS = ASCII_LOWERCASE + ASCII_UPPERCASE;
var HIGH_SURROGATE_BEGIN = 0xD800;
var HIGH_SURROGATE_END = 0xDBFF;
var LOW_SURROGATE_BEGIN = 0xDC00;
var LOW_SURROGATE_END = 0xDFFF;
var ZERO_WIDTH_JOINER = 0x200D;
var REGIONAL_INDICATOR_BEGIN = 0x1F1E6;
var REGIONAL_INDICATOR_END = 0x1F1FF;
var FITZPATRICK_MODIFIER_BEGIN = 0x1F3FB;
var FITZPATRICK_MODIFIER_END = 0x1F3FF;
var DIACRITICAL_MARKS_BEGIN = 0x20D0;
var DIACRITICAL_MARKS_END = 0x20FF;
var VARIATION_MODIFIER_BEGIN = 0xFE00;
var VARIATION_MODIFIER_END = 0xFE0F;
function getCodePointData(string, i) {
if (i === void 0) {
i = 0;
}
var size = string.length;
if (i < 0 || i >= size) {
return null;
}
var first = string.charCodeAt(i);
if (size > 1 && first >= HIGH_SURROGATE_BEGIN && first <= HIGH_SURROGATE_END) {
var second = string.charCodeAt(i + 1);
if (second >= LOW_SURROGATE_BEGIN && second <= LOW_SURROGATE_END) {
return {
code: (first - HIGH_SURROGATE_BEGIN) * 0x400 + second - LOW_SURROGATE_BEGIN + 0x10000,
long: true
};
}
}
return {
code: first,
long: false
};
}
function isCodeBetween(string, begin, end) {
if (!string) return false;
var codeData = getCodePointData(string);
if (codeData) {
var code = codeData.code;
return code >= begin && code <= end;
}
return false;
}
function numCharsToTakeForNextSymbol(string, index) {
if (index === string.length - 1) {
return 1;
}
if (isCodeBetween(string[index], HIGH_SURROGATE_BEGIN, HIGH_SURROGATE_END)) {
var first = string.substring(index, index + 2);
var second = string.substring(index + 2, index + 4);
if (isCodeBetween(second, FITZPATRICK_MODIFIER_BEGIN, FITZPATRICK_MODIFIER_END) || isCodeBetween(first, REGIONAL_INDICATOR_BEGIN, REGIONAL_INDICATOR_END) && isCodeBetween(second, REGIONAL_INDICATOR_BEGIN, REGIONAL_INDICATOR_END)) {
return 4;
}
if (isCodeBetween(second, VARIATION_MODIFIER_BEGIN, VARIATION_MODIFIER_END)) {
return 3;
}
return 2;
}
if (isCodeBetween(string[index + 1], VARIATION_MODIFIER_BEGIN, VARIATION_MODIFIER_END)) {
return 2;
}
return 1;
}
var string = {
ASCII_LOWERCASE: ASCII_LOWERCASE,
ASCII_UPPERCASE: ASCII_UPPERCASE,
ASCII_LETTERS: ASCII_LETTERS,
format: function format(s) {
for (var i = 1; i < arguments.length; i++) {
s = s.replace('{' + (i - 1) + '}', arguments[i]);
}
return s;
},
toBool: function toBool(s, strict) {
if (strict === void 0) {
strict = false;
}
if (s === 'true') {
return true;
}
if (strict) {
if (s === 'false') {
return false;
}
throw new TypeError('Not a boolean string');
}
return false;
},
getCodePoint: function getCodePoint(string, i) {
var codePointData = getCodePointData(string, i);
return codePointData && codePointData.code;
},
getCodePoints: function getCodePoints(string) {
if (typeof string !== 'string') {
throw new TypeError('Not a string');
}
var i = 0;
var arr = [];
var codePoint;
while (!!(codePoint = getCodePointData(string, i))) {
arr.push(codePoint.code);
i += codePoint.long ? 2 : 1;
}
return arr;
},
getSymbols: function getSymbols(string) {
if (typeof string !== 'string') {
throw new TypeError('Not a string');
}
var index = 0;
var length = string.length;
var output = [];
var take = 0;
var ch;
while (index < length) {
take += numCharsToTakeForNextSymbol(string, index + take);
ch = string[index + take];
if (isCodeBetween(ch, DIACRITICAL_MARKS_BEGIN, DIACRITICAL_MARKS_END)) {
ch = string[index + take++];
}
if (isCodeBetween(ch, VARIATION_MODIFIER_BEGIN, VARIATION_MODIFIER_END)) {
ch = string[index + take++];
}
if (ch && ch.charCodeAt(0) === ZERO_WIDTH_JOINER) {
ch = string[index + take++];
continue;
}
var char = string.substring(index, index + take);
output.push(char);
index += take;
take = 0;
}
return output;
},
fromCodePoint: function fromCodePoint() {
var chars = [];
var current;
var codePoint;
var units;
for (var i = 0; i < arguments.length; ++i) {
current = Number(arguments[i]);
codePoint = current - 0x10000;
units = current > 0xFFFF ? [(codePoint >> 10) + 0xD800, codePoint % 0x400 + 0xDC00] : [current];
chars.push(String.fromCharCode.apply(null, units));
}
return chars.join('');
}
};
var IndexedList = function () {
function IndexedList() {
this._list = [];
this._index = {};
}
var _proto = IndexedList.prototype;
_proto.push = function push(key, item) {
if (this._index[key]) {
throw Error("Key already in index " + key);
}
var location = this._list.push(item) - 1;
this._index[key] = location;
};
_proto.has = function has(key) {
return this._index[key] !== undefined;
};
_proto.get = function get(key) {
var location = this._index[key];
if (location !== undefined) {
return this._list[location];
}
return null;
};
_proto.remove = function remove(key) {
var location = this._index[key];
if (location !== undefined) {
this._list.splice(location, 1);
delete this._index[key];
for (key in this._index) {
var idx = this._index[key];
if (idx > location) {
this._index[key] = idx - 1;
}
}
return true;
}
return false;
};
_proto.list = function list() {
return this._list;
};
_proto.clear = function clear() {
this._list.length = 0;
for (var prop in this._index) {
delete this._index[prop];
}
};
return IndexedList;
}();
var SortedLoopArray = function () {
function SortedLoopArray(args) {
this._sortBy = args.sortBy;
this.items = [];
this.length = 0;
this.loopIndex = -1;
this._sortHandler = this._doSort.bind(this);
}
var _proto = SortedLoopArray.prototype;
_proto._binarySearch = function _binarySearch(item) {
var left = 0;
var right = this.items.length - 1;
var search = item[this._sortBy];
var middle;
var current;
while (left <= right) {
middle = Math.floor((left + right) / 2);
current = this.items[middle][this._sortBy];
if (current <= search) {
left = middle + 1;
} else if (current > search) {
right = middle - 1;
}
}
return left;
};
_proto._doSort = function _doSort(a, b) {
var sortBy = this._sortBy;
return a[sortBy] - b[sortBy];
};
_proto.insert = function insert(item) {
var index = this._binarySearch(item);
this.items.splice(index, 0, item);
this.length++;
if (this.loopIndex >= index) {
this.loopIndex++;
}
};
_proto.append = function append(item) {
this.items.push(item);
this.length++;
};
_proto.remove = function remove(item) {
var idx = this.items.indexOf(item);
if (idx < 0) return;
this.items.splice(idx, 1);
this.length--;
if (this.loopIndex >= idx) {
this.loopIndex--;
}
};
_proto.sort = function sort() {
var current = this.loopIndex >= 0 ? this.items[this.loopIndex] : null;
this.items.sort(this._sortHandler);
if (current !== null) {
this.loopIndex = this.items.indexOf(current);
}
};
return SortedLoopArray;
}();
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
_setPrototypeOf(subClass, superClass);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _createForOfIteratorHelperLoose(o, allowArrayLike) {
var it;
if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it) o = it;
var i = 0;
return function () {
if (i >= o.length) return {
done: true
};
return {
done: false,
value: o[i++]
};
};
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
it = o[Symbol.iterator]();
return it.next.bind(it);
}
var Tags = function (_EventHandler) {
_inheritsLoose(Tags, _EventHandler);
function Tags(parent) {
var _this;
_this = _EventHandler.call(this) || this;
_this._index = {};
_this._list = [];
_this._parent = parent;
return _this;
}
var _proto = Tags.prototype;
_proto.add = function add() {
var changed = false;
var tags = this._processArguments(arguments, true);
if (!tags.length) return changed;
for (var i = 0; i < tags.length; i++) {
if (this._index[tags[i]]) continue;
changed = true;
this._index[tags[i]] = true;
this._list.push(tags[i]);
this.fire('add', tags[i], this._parent);
}
if (changed) this.fire('change', this._parent);
return changed;
};
_proto.remove = function remove() {
var changed = false;
if (!this._list.length) return changed;
var tags = this._processArguments(arguments, true);
if (!tags.length) return changed;
for (var i = 0; i < tags.length; i++) {
if (!this._index[tags[i]]) continue;
changed = true;
delete this._index[tags[i]];
this._list.splice(this._list.indexOf(tags[i]), 1);
this.fire('remove', tags[i], this._parent);
}
if (changed) this.fire('change', this._parent);
return changed;
};
_proto.clear = function clear() {
if (!this._list.length) return;
var tags = this._list.slice(0);
this._list = [];
this._index = {};
for (var i = 0; i < tags.length; i++) {
this.fire('remove', tags[i], this._parent);
}
this.fire('change', this._parent);
};
_proto.has = function has() {
if (!this._list.length) return false;
return this._has(this._processArguments(arguments));
};
_proto._has = function _has(tags) {
if (!this._list.length || !tags.length) return false;
for (var i = 0; i < tags.length; i++) {
if (tags[i].length === 1) {
if (this._index[tags[i][0]]) return true;
} else {
var multiple = true;
for (var t = 0; t < tags[i].length; t++) {
if (this._index[tags[i][t]]) continue;
multiple = false;
break;
}
if (multiple) return true;
}
}
return false;
};
_proto.list = function list() {
return this._list.slice(0);
};
_proto._processArguments = function _processArguments(args, flat) {
var tags = [];
var tmp = [];
if (!args || !args.length) return tags;
for (var i = 0; i < args.length; i++) {
if (args[i] instanceof Array) {
if (!flat) tmp = [];
for (var t = 0; t < args[i].length; t++) {
if (typeof args[i][t] !== 'string') continue;
if (flat) {
tags.push(args[i][t]);
} else {
tmp.push(args[i][t]);
}
}
if (!flat && tmp.length) tags.push(tmp);
} else if (typeof args[i] === 'string') {
if (flat) {
tags.push(args[i]);
} else {
tags.push([args[i]]);
}
}
}
return tags;
};
_createClass(Tags, [{
key: "size",
get: function get() {
return this._list.length;
}
}]);
return Tags;
}(EventHandler);
var now = typeof window !== 'undefined' && window.performance && window.performance.now && window.performance.timing ? function () {
return window.performance.now();
} : Date.now;
var Timer = function () {
function Timer() {
this._isRunning = false;
this._a = 0;
this._b = 0;
}
var _proto = Timer.prototype;
_proto.start = function start() {
this._isRunning = true;
this._a = now();
};
_proto.stop = function stop() {
this._isRunning = false;
this._b = now();
};
_proto.getMilliseconds = function getMilliseconds() {
return this._b - this._a;
};
return Timer;
}();
function createURI(options) {
var s = "";
if ((options.authority || options.scheme) && (options.host || options.hostpath)) {
throw new Error("Can't have 'scheme' or 'authority' and 'host' or 'hostpath' option");
}
if (options.host && options.hostpath) {
throw new Error("Can't have 'host' and 'hostpath' option");
}
if (options.path && options.hostpath) {
throw new Error("Can't have 'path' and 'hostpath' option");
}
if (options.scheme) {
s += options.scheme + ":";
}
if (options.authority) {
s += "//" + options.authority;
}
if (options.host) {
s += options.host;
}
if (options.path) {
s += options.path;
}
if (options.hostpath) {
s += options.hostpath;
}
if (options.query) {
s += "?" + options.query;
}
if (options.fragment) {
s += "#" + options.fragment;
}
return s;
}
var re = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
var URI = function () {
function URI(uri) {
var result = uri.match(re);
this.scheme = result[2];
this.authority = result[4];
this.path = result[5];
this.query = result[7];
this.fragment = result[9];
}
var _proto = URI.prototype;
_proto.toString = function toString() {
var s = "";
if (this.scheme) {
s += this.scheme + ":";
}
if (this.authority) {
s += "//" + this.authority;
}
s += this.path;
if (this.query) {
s += "?" + this.query;
}
if (this.fragment) {
s += "#" + this.fragment;
}
return s;
};
_proto.getQuery = function getQuery() {
var result = {};
if (this.query) {
var queryParams = decodeURIComponent(this.query).split("&");
for (var _iterator = _createForOfIteratorHelperLoose(queryParams), _step; !(_step = _iterator()).done;) {
var queryParam = _step.value;
var pair = queryParam.split("=");
result[pair[0]] = pair[1];
}
}
return result;
};
_proto.setQuery = function setQuery(params) {
var q = "";
for (var key in params) {
if (params.hasOwnProperty(key)) {
if (q !== "") {
q += "&";
}
q += encodeURIComponent(key) + "=" + encodeURIComponent(params[key]);
}
}
this.query = q;
};
return URI;
}();
var math = {
DEG_TO_RAD: Math.PI / 180,
RAD_TO_DEG: 180 / Math.PI,
clamp: function clamp(value, min, max) {
if (value >= max) return max;
if (value <= min) return min;
return value;
},
intToBytes24: function intToBytes24(i) {
var r = i >> 16 & 0xff;
var g = i >> 8 & 0xff;
var b = i & 0xff;
return [r, g, b];
},
intToBytes32: function intToBytes32(i) {
var r = i >> 24 & 0xff;
var g = i >> 16 & 0xff;
var b = i >> 8 & 0xff;
var a = i & 0xff;
return [r, g, b, a];
},
bytesToInt24: function bytesToInt24(r, g, b) {
if (r.length) {
b = r[2];
g = r[1];
r = r[0];
}
return r << 16 | g << 8 | b;
},
bytesToInt32: function bytesToInt32(r, g, b, a) {
if (r.length) {
a = r[3];
b = r[2];
g = r[1];
r = r[0];
}
return (r << 24 | g << 16 | b << 8 | a) >>> 32;
},
lerp: function lerp(a, b, alpha) {
return a + (b - a) * math.clamp(alpha, 0, 1);
},
lerpAngle: function lerpAngle(a, b, alpha) {
if (b - a > 180) {
b -= 360;
}
if (b - a < -180) {
b += 360;
}
return math.lerp(a, b, math.clamp(alpha, 0, 1));
},
powerOfTwo: function powerOfTwo(x) {
return x !== 0 && !(x & x - 1);
},
nextPowerOfTwo: function nextPowerOfTwo(val) {
val--;
val |= val >> 1;
val |= val >> 2;
val |= val >> 4;
val |= val >> 8;
val |= val >> 16;
val++;
return val;
},
random: function random(min, max) {
var diff = max - min;
return Math.random() * diff + min;
},
smoothstep: function smoothstep(min, max, x) {
if (x <= min) return 0;
if (x >= max) return 1;
x = (x - min) / (max - min);
return x * x * (3 - 2 * x);
},
smootherstep: function smootherstep(min, max, x) {
if (x <= min) return 0;
if (x >= max) return 1;
x = (x - min) / (max - min);
return x * x * x * (x * (x * 6 - 15) + 10);
},
roundUp: function roundUp(numToRound, multiple) {
if (multiple === 0) return numToRound;
return Math.ceil(numToRound / multiple) * multiple;
},
float2Half: function () {
var floatView = new Float32Array(1);
var int32View = new Int32Array(floatView.buffer);
return function (val) {
floatView[0] = val;
var x = int32View[0];
var bits = x >> 16 & 0x8000;
var m = x >> 12 & 0x07ff;
var e = x >> 23 & 0xff;
if (e < 103) {
return bits;
}
if (e > 142) {
bits |= 0x7c00;
bits |= (e === 255 ? 0 : 1) && x & 0x007fffff;
return bits;
}
if (e < 113) {
m |= 0x0800;
bits |= (m >> 114 - e) + (m >> 113 - e & 1);
return bits;
}
bits |= e - 112 << 10 | m >> 1;
bits += m & 1;
return bits;
};
}(),
between: function between(num, a, b, inclusive) {
var min = Math.min(a, b);
var max = Math.max(a, b);
return inclusive ? num >= min && num <= max : num > min && num < max;
}
};
var Http = function () {
function Http() {
this.ContentType = Http.ContentType;
this.ResponseType = Http.ResponseType;
this.binaryExtensions = Http.binaryExtensions;
}
var _proto = Http.prototype;
_proto.get = function get(url, options, callback) {
if (typeof options === "function") {
callback = options;
options = {};
}
return this.request("GET", url, options, callback);
};
_proto.post = function post(url, data, options, callback) {
if (typeof options === "function") {
callback = options;
options = {};
}
options.postdata = data;
return this.request("POST", url, options, callback);
};
_proto.put = function put(url, data, options, callback) {
if (typeof options === "function") {
callback = options;
options = {};
}
options.postdata = data;
return this.request("PUT", url, options, callback);
};
_proto.del = function del(url, options, callback) {
if (typeof options === "function") {
callback = options;
options = {};
}
return this.request("DELETE", url, options, callback);
};
_proto.request = function request(method, url, options, callback) {
var uri, query, timestamp, postdata, xhr;
var errored = false;
if (typeof options === "function") {
callback = options;
options = {};
}
if (options.retry) {
options = Object.assign({
retries: 0,
maxRetries: 5
}, options);
}
options.callback = callback;
if (options.async == null) {
options.async = true;
}
if (options.headers == null) {
options.headers = {};
}
if (options.postdata != null) {
if (options.postdata instanceof Document) {
postdata = options.postdata;
} else if (options.postdata instanceof FormData) {
postdata = options.postdata;
} else if (options.postdata instanceof Object) {
var contentType = options.headers["Content-Type"];
if (contentType === undefined) {
options.headers["Content-Type"] = Http.ContentType.FORM_URLENCODED;
contentType = options.headers["Content-Type"];
}
switch (contentType) {
case Http.ContentType.FORM_URLENCODED:
postdata = "";
var bFirstItem = true;
for (var key in options.postdata) {
if (options.postdata.hasOwnProperty(key)) {
if (bFirstItem) {
bFirstItem = false;
} else {
postdata += "&";
}
postdata += escape(key) + "=" + escape(options.postdata[key]);
}
}
break;
default:
case Http.ContentType.JSON:
if (contentType == null) {
options.headers["Content-Type"] = Http.ContentType.JSON;
}
postdata = JSON.stringify(options.postdata);
break;
}
} else {
postdata = options.postdata;
}
}
if (options.cache === false) {
timestamp = now();
uri = new URI(url);
if (!uri.query) {
uri.query = "ts=" + timestamp;
} else {
uri.query = uri.query + "&ts=" + timestamp;
}
url = uri.toString();
}
if (options.query) {
uri = new URI(url);
query = extend(uri.getQuery(), options.query);
uri.setQuery(query);
url = uri.toString();
}
xhr = new XMLHttpRequest();
xhr.open(method, url, options.async);
xhr.withCredentials = options.withCredentials !== undefined ? options.withCredentials : false;
xhr.responseType = options.responseType || this._guessResponseType(url);
for (var header in options.headers) {
if (options.headers.hasOwnProperty(header)) {
xhr.setRequestHeader(header, options.headers[header]);
}
}
xhr.onreadystatechange = function () {
this._onReadyStateChange(method, url, options, xhr);
}.bind(this);
xhr.onerror = function () {
this._onError(method, url, options, xhr);
errored = true;
}.bind(this);
try {
xhr.send(postdata);
} catch (e) {
if (!errored) {
options.error(xhr.status, xhr, e);
}
}
return xhr;
};
_proto._guessResponseType = function _guessResponseType(url) {
var uri = new URI(url);
var ext = path.getExtension(uri.path);
if (Http.binaryExtensions.indexOf(ext) >= 0) {
return Http.ResponseType.ARRAY_BUFFER;
}
if (ext === ".xml") {
return Http.ResponseType.DOCUMENT;
}
return Http.ResponseType.TEXT;
};
_proto._isBinaryContentType = function _isBinaryContentType(contentType) {
var binTypes = [Http.ContentType.MP4, Http.ContentType.WAV, Http.ContentType.OGG, Http.ContentType.MP3, Http.ContentType.BIN, Http.ContentType.DDS, Http.ContentType.BASIS, Http.ContentType.GLB];
if (binTypes.indexOf(contentType) >= 0) {
return true;
}
return false;
};
_proto._onReadyStateChange = function _onReadyStateChange(method, url, options, xhr) {
if (xhr.readyState === 4) {
switch (xhr.status) {
case 0:
{
if (xhr.responseURL && xhr.responseURL.startsWith('file:///')) {
this._onSuccess(method, url, options, xhr);
} else {
this._onError(method, url, options, xhr);
}
break;
}
case 200:
case 201:
case 206:
case 304:
{
this._