var CABLES;
/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	// The require scope
/******/ 	var __webpack_require__ = {};
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "default": () => (/* binding */ core)
});

// NAMESPACE OBJECT: ./src/core/utils.js
var utils_namespaceObject = {};
__webpack_require__.r(utils_namespaceObject);
__webpack_require__.d(utils_namespaceObject, {
  UTILS: () => (UTILS),
  ajax: () => (ajax),
  ajaxSync: () => (ajaxSync),
  basename: () => (basename),
  cacheBust: () => (cacheBust),
  clamp: () => (clamp),
  cleanJson: () => (cleanJson),
  copyArray: () => (copyArray),
  filename: () => (filename),
  generateUUID: () => (generateUUID),
  getShortOpName: () => (getShortOpName),
  keyCodeToName: () => (keyCodeToName),
  logErrorConsole: () => (logErrorConsole),
  logStack: () => (logStack),
  map: () => (map),
  prefixedHash: () => (prefixedHash),
  request: () => (request),
  shortId: () => (shortId),
  shuffleArray: () => (shuffleArray),
  simpleId: () => (simpleId),
  smoothStep: () => (smoothStep),
  smootherStep: () => (smootherStep),
  uuid: () => (uuid)
});

// NAMESPACE OBJECT: ./src/core/anim.js
var anim_namespaceObject = {};
__webpack_require__.r(anim_namespaceObject);
__webpack_require__.d(anim_namespaceObject, {
  ANIM: () => (ANIM),
  Anim: () => (Anim)
});

;// CONCATENATED MODULE: ./src/core/constants.js
const CONSTANTS = {
    "ANIM": {
        "EASINGS": [
            "linear",
            "absolute",
            "smoothstep",
            "smootherstep",
            "Cubic In",
            "Cubic Out",
            "Cubic In Out",
            "Expo In",
            "Expo Out",
            "Expo In Out",
            "Sin In",
            "Sin Out",
            "Sin In Out",
            "Quart In",
            "Quart Out",
            "Quart In Out",
            "Quint In",
            "Quint Out",
            "Quint In Out",
            "Back In",
            "Back Out",
            "Back In Out",
            "Elastic In",
            "Elastic Out",
            "Bounce In",
            "Bounce Out",
        ],
        "EASING_LINEAR": 0,
        "EASING_ABSOLUTE": 1,
        "EASING_SMOOTHSTEP": 2,
        "EASING_SMOOTHERSTEP": 3,
        "EASING_CUBICSPLINE": 4,

        "EASING_CUBIC_IN": 5,
        "EASING_CUBIC_OUT": 6,
        "EASING_CUBIC_INOUT": 7,

        "EASING_EXPO_IN": 8,
        "EASING_EXPO_OUT": 9,
        "EASING_EXPO_INOUT": 10,

        "EASING_SIN_IN": 11,
        "EASING_SIN_OUT": 12,
        "EASING_SIN_INOUT": 13,

        "EASING_BACK_IN": 14,
        "EASING_BACK_OUT": 15,
        "EASING_BACK_INOUT": 16,

        "EASING_ELASTIC_IN": 17,
        "EASING_ELASTIC_OUT": 18,

        "EASING_BOUNCE_IN": 19,
        "EASING_BOUNCE_OUT": 21,

        "EASING_QUART_IN": 22,
        "EASING_QUART_OUT": 23,
        "EASING_QUART_INOUT": 24,

        "EASING_QUINT_IN": 25,
        "EASING_QUINT_OUT": 26,
        "EASING_QUINT_INOUT": 27,
    },

    "OP": {
        "OP_PORT_TYPE_VALUE": 0,
        "OP_PORT_TYPE_NUMBER": 0,
        "OP_PORT_TYPE_FUNCTION": 1,
        "OP_PORT_TYPE_TRIGGER": 1,
        "OP_PORT_TYPE_OBJECT": 2,
        "OP_PORT_TYPE_TEXTURE": 2,
        "OP_PORT_TYPE_ARRAY": 3,
        "OP_PORT_TYPE_DYNAMIC": 4,
        "OP_PORT_TYPE_STRING": 5,

        "OP_VERSION_PREFIX": "_v",
    },

    "PORT": {
        "PORT_DIR_IN": 0,
        "PORT_DIR_OUT": 1,
    },

    "PACO": {
        "PACO_CLEAR": 0,
        "PACO_VALUECHANGE": 1,
        "PACO_OP_DELETE": 2,
        "PACO_UNLINK": 3,
        "PACO_LINK": 4,
        "PACO_LOAD": 5,
        "PACO_OP_CREATE": 6,
        "PACO_OP_ENABLE": 7,
        "PACO_OP_DISABLE": 8,
        "PACO_UIATTRIBS": 9,
        "PACO_VARIABLES": 10,
        "PACO_TRIGGERS": 11,
        "PACO_PORT_SETVARIABLE": 12,
        "PACO_PORT_SETANIMATED": 13,
        "PACO_PORT_ANIM_UPDATED": 14,
        "PACO_DESERIALIZE": 15,
        "PACO_OP_RELOAD": 16
    },
};

;// CONCATENATED MODULE: ./src/core/utils.js

/**
 * @namespace external:CABLES#Utils
 */



const UTILS = {};
/**
 * Merge two Float32Arrays.
 * @function float32Concat
 * @memberof Utils
 * @param {Float32Array} first Left-hand side array
 * @param {Float32Array} second Right-hand side array
 * @return {Float32Array}
 * @static
 */
UTILS.float32Concat = function (first, second)
{
    if (!(first instanceof Float32Array)) first = new Float32Array(first);
    if (!(second instanceof Float32Array)) second = new Float32Array(second);

    const result = new Float32Array(first.length + second.length);

    result.set(first);
    result.set(second, first.length);

    return result;
};

/**
 * get op shortname: only last part of fullname and without version
 * @function getShortOpName
 * @memberof CABLES
 * @param {string} fullname full op name
 * @static
 */
const getShortOpName = function (fullname)
{
    let name = fullname.split(".")[fullname.split(".").length - 1];

    if (name.contains(CONSTANTS.OP.OP_VERSION_PREFIX))
    {
        const n = name.split(CONSTANTS.OP.OP_VERSION_PREFIX)[1];
        name = name.substring(0, name.length - (CONSTANTS.OP.OP_VERSION_PREFIX + n).length);
    }
    return name;
};

/**
 * randomize order of an array
 * @function shuffleArray
 * @memberof Utils
 * @param {Array|Float32Array} array {Array} original
 * @return {Array|Float32Array} shuffled array
 * @static
 */
const shuffleArray = function (array)
{
    for (let i = array.length - 1; i > 0; i--)
    {
        const j = Math.floor(Math.seededRandom() * (i + 1));
        const temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    return array;
};


/**
 * generate a short "relativly unique" id
 * @function shortId
 * @memberof Utils
 * @return {String} generated ID
 * @static
 */

const _shortIds = {};
const _shortId = function ()
{
    let str = Math.random().toString(36).substr(2, 9);

    if (_shortIds.hasOwnProperty(str)) str = _shortId();
    _shortIds[str] = true;
    return str;
};
const shortId = _shortId;


/**
 * generate a UUID
 * @function uuid
 * @memberof Utils
 * @return {String} generated UUID
 * @static
 */
const _uuid = function ()
{
    let d = new Date().getTime();
    const uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) =>
    {
        const r = (d + Math.random() * 16) % 16 | 0;
        d = Math.floor(d / 16);
        return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
    });
    return uuid;
};
const uuid = _uuid;
const generateUUID = _uuid;



function cleanJson(obj)
{
    for (const i in obj)
    {
        if (obj[i] && typeof objValue === "object" && obj[i].constructor === Object) obj[i] = cleanJson(obj[i]);

        if (obj[i] === null || obj[i] === undefined) delete obj[i];
        else if (Array.isArray(obj[i]) && obj[i].length == 0) delete obj[i];
    }

    return obj;
}


/**
 * @see http://stackoverflow.com/q/7616461/940217
 * @memberof Utils
 * @param str
 * @param prefix
 * @return {string}
 */
const _prefixedHash = function (str, prefix = "id")
{
    let hash = 0;
    if (Array.prototype.reduce)
    {
        hash = str.split("").reduce((a, b) => { a = ((a << 5) - a) + b.charCodeAt(0); return a & a; }, 0);
    }
    else
    {
        if (str.length > 0)
        {
            for (let i = 0; i < str.length; i++)
            {
                let character = str.charCodeAt(i);
                hash = ((hash << 5) - hash) + character;
                hash &= hash; // Convert to 32bit integer
            }
        }
    }
    return prefix + "" + hash;
};
const prefixedHash = _prefixedHash;

/**
 * generate a simple ID
 * @function simpleId
 * @memberof Utils
 * @return {Number} new id
 * @static
 */
let simpleIdCounter = 0;
const simpleId = function ()
{
    simpleIdCounter++;
    return simpleIdCounter;
};

/**
 * smoothStep a value
 * @function smoothStep
 * @memberof Utils
 * @function
 * @param {Number} perc value value to be smoothed [0-1]
 * @return {Number} smoothed value
 * @static
 */
const smoothStep = function (perc)
{
    const x = Math.max(0, Math.min(1, (perc - 0) / (1 - 0)));
    perc = x * x * (3 - 2 * x); // smoothstep
    return perc;
};

/**
 * smootherstep a value
 * @function smootherStep
 * @memberof Utils
 * @param {Number} perc value to be smoothed [0-1]
 * @return {Number} smoothed value
 * @static
 */
const smootherStep = function (perc)
{
    const x = Math.max(0, Math.min(1, (perc - 0) / (1 - 0)));
    perc = x * x * x * (x * (x * 6 - 15) + 10); // smootherstep
    return perc;
};


/**
 * clamp number / make sure its between min/max
 * @function clamp
 * @memberof Utils
 * @param {Number} value value to be mapped
 * @param {Number} min minimum value
 * @param {Number} max maximum value
 * @static
 */
const clamp = function (value, min, max)
{
    return Math.min(Math.max(value, min), max);
};

/**
 * map a value in a range to a value in another range
 * @function map
 * @memberof Utils
 * @param {Number} x value to be mapped
 * @param {Number} _oldMin old range minimum value
 * @param {Number} _oldMax old range maximum value
 * @param {Number} _newMin new range minimum value
 * @param {Number} _newMax new range maximum value
 * @param {Number} _easing
 * @return {Number} mapped value
 * @static
 */
const map = function (x, _oldMin, _oldMax, _newMin, _newMax, _easing)
{
    if (x >= _oldMax) return _newMax;
    if (x <= _oldMin) return _newMin;

    let reverseInput = false;
    const oldMin = Math.min(_oldMin, _oldMax);
    const oldMax = Math.max(_oldMin, _oldMax);
    if (oldMin != _oldMin) reverseInput = true;

    let reverseOutput = false;
    const newMin = Math.min(_newMin, _newMax);
    const newMax = Math.max(_newMin, _newMax);
    if (newMin != _newMin) reverseOutput = true;

    let portion = 0;
    let r = 0;

    if (reverseInput) portion = ((oldMax - x) * (newMax - newMin)) / (oldMax - oldMin);
    else portion = ((x - oldMin) * (newMax - newMin)) / (oldMax - oldMin);

    if (reverseOutput) r = newMax - portion;
    else r = portion + newMin;

    if (!_easing) return r;
    if (_easing == 1)
    {
        // smoothstep
        x = Math.max(0, Math.min(1, (r - _newMin) / (_newMax - _newMin)));
        return _newMin + x * x * (3 - 2 * x) * (_newMax - _newMin);
    }
    if (_easing == 2)
    {
        // smootherstep
        x = Math.max(0, Math.min(1, (r - _newMin) / (_newMax - _newMin)));
        return _newMin + x * x * x * (x * (x * 6 - 15) + 10) * (_newMax - _newMin);
    }

    return r;
};

/**
 * @namespace Math
 */
/**
 * set random seed for seededRandom()
 * @memberof Math
 * @type Number
 * @static
 */
Math.randomSeed = 1;


Math.setRandomSeed = function (seed)
{
    // https://github.com/cables-gl/cables_docs/issues/622
    Math.randomSeed = seed * 50728129;
    if (seed != 0)
    {
        Math.randomSeed = Math.seededRandom() * 17624813;
        Math.randomSeed = Math.seededRandom() * 9737333;
    }
};


/**
 * generate a seeded random number
 * @function seededRandom
 * @memberof Math
 * @param {Number} max minimum possible random number
 * @param {Number} min maximum possible random number
 * @return {Number} random value
 * @static
 */
Math.seededRandom = function (max, min)
{
    if (Math.randomSeed === 0) Math.randomSeed = Math.random() * 999;
    max = max || 1;
    min = min || 0;

    Math.randomSeed = (Math.randomSeed * 9301 + 49297) % 233280;
    const rnd = Math.randomSeed / 233280.0;

    return min + rnd * (max - min);
};


// ----------------------------------------------------------------

/**
 * returns true if parameter is a number
 * @function isNumeric
 * @memberof Utils
 * @param {Any} n value The value to check.
 * @return {Boolean}
 * @static
 */
UTILS.isNumeric = function (n)
{
    return !isNaN(parseFloat(n)) && isFinite(n);
};

/**
 * returns true if parameter is array
 * @function isArray
 * @param {Any} v value Value to check
 * @memberof Utils
 * @return {Boolean}
 * @static
 */
UTILS.isArray = function (v)
{
    return Object.prototype.toString.call(v) === "[object Array]";
};

/**
 * @namespace String
 */

/**
 * append a linebreak to a string
 * @function endl
 * @memberof String
 * @return {String} string with newline break appended ('\n')
 */
String.prototype.endl = function ()
{
    return this + "\n";
};

/**
 * return true if string starts with prefix
 * @function startsWith
 * @memberof String
 * @param {String} prefix The prefix to check.
 * @return {Boolean}
 */
String.prototype.startsWith = function (prefix)
{
    if (!this || !prefix) return false;
    if (this.length >= prefix.length)
    {
        if (this.substring(0, prefix.length) == prefix) return true;
    }
    return false;
    // return this.indexOf(prefix) === 0;
};

/**
 * return true if string ends with suffix
 * @function endsWith
 * @memberof String
 * @param {String} suffix
 * @return {Boolean}
 */
String.prototype.endsWith = String.prototype.endsWith || function (suffix)
{
    return this.match(suffix + "$") == suffix;
};

/**
 * return true if string contains string
 * @function contains
 * @memberof String
 * @param {String} searchStr
 * @return {Boolean}
 */
String.prototype.contains = String.prototype.contains || function (searchStr)
{
    return this.indexOf(searchStr) > -1;
};



// ----------------------------------------------------------------

/**
 * append a unique/random parameter to a url, so the browser is forced to reload the file, even if its cached
 * @function cacheBust
 * @static
 * @memberof Utils
 * @param {String} url The url to append the cachebuster parameter to.
 * @return {String} url with cachebuster parameter
 */
const cacheBust = function (url = "")
{
    if (!url) return "";
    if (url.startsWith("data:")) return;
    if (url.contains("?")) url += "&";
    else url += "?";
    return url + "cache=" + CABLES.uuid();
};

/**
 * copy the content of an array
 * @function copyArray
 * @static
 * @memberof Utils
 * @param {Array} src sourceArray
 * @param {Array} dst optional
 * @return {Array} dst
 */
const copyArray = function (src, dst)
{
    if (!src) return null;
    dst = dst || [];
    dst.length = src.length;
    for (let i = 0; i < src.length; i++)
    {
        dst[i] = src[i];
    }

    return dst;
};


/**
 * return the filename part of a url without extension
 * @function basename
 * @static
 * @memberof Utils
 * @param {String} url
 * @return {String} just the filename
 */
const basename = function (url)
{
    let name = CABLES.filename(url);

    const parts2 = name.split(".");
    name = parts2[0];

    return name;
};

/**
 * output a stacktrace to the console
 * @function logStack
 * @static
 * @memberof Utils
 */
const logStack = function ()
{
    console.log("logstack", (new Error()).stack);
};

/**
 * return the filename part of a url
 * @function filename
 * @static
 * @memberof Utils
 * @param {String} url
 * @return {String} just the filename
 */
const filename = function (url)
{
    let name = "";
    if (!url) return "";

    if (url.startsWith("data:") && url.contains(":"))
    {
        const parts = url.split(",");
        return parts[0];
    }

    let parts = (url + "").split("/");
    if (parts.length > 0)
    {
        const str = parts[parts.length - 1];
        let parts2 = str.split("?");
        name = parts2[0];
    }

    return name || "";
};


const ajaxSync = function (url, cb, method, post, contenttype)
{
    request({
        "url": url,
        "cb": cb,
        "method": method,
        "data": post,
        "contenttype": contenttype,
        "sync": true,
    });
};

/**
 * make an ajax request
 * @static
 * @function ajax
 * @param url
 * @param cb
 * @param method
 * @param post
 * @param contenttype
 * @param jsonP
 * @param headers
 * @param options
 */
const ajax = function (url, cb, method, post, contenttype, jsonP, headers = {}, options = {})
{
    const requestOptions = {
        "url": url,
        "cb": cb,
        "method": method,
        "data": post,
        "contenttype": contenttype,
        "sync": false,
        "jsonP": jsonP,
        "headers": headers,
    };
    if (options && options.credentials) requestOptions.credentials = options.credentials;
    request(requestOptions);
};

const request = function (options)
{
    if (!options.hasOwnProperty("asynch")) options.asynch = true;

    let xhr;
    try
    {
        xhr = new XMLHttpRequest();
    }
    catch (e) {}

    xhr.onreadystatechange = function ()
    {
        if (xhr.readyState != 4) return;

        if (options.cb)
        {
            if (xhr.status == 200 || xhr.status == 0) options.cb(false, xhr.responseText, xhr);
            else options.cb(true, xhr.responseText, xhr);
        }
    };

    try
    {
        xhr.open(options.method ? options.method.toUpperCase() : "GET", options.url, !options.sync);
    }
    catch (e)
    {
        if (options.cb && e) options.cb(true, e.msg, xhr);
    }

    if (typeof options.headers === "object")
    {
        if (options.headers)
        {
            const keys = Object.keys(options.headers);
            for (let i = 0; i < keys.length; i++)
            {
                const name = keys[i];
                const value = options.headers[name];
                xhr.setRequestHeader(name, value);
            }
        }
    }

    if (options.credentials && options.credentials !== "omit")
    {
        xhr.withCredentials = true;
    }

    try
    {
        if (!options.post && !options.data)
        {
            xhr.send();
        }
        else
        {
            xhr.setRequestHeader(
                "Content-type",
                options.contenttype ? options.contenttype : "application/x-www-form-urlencoded",
            );
            xhr.send(options.data || options.post);
        }
    }
    catch (e)
    {
        if (options.cb) options.cb(true, e.msg, xhr);
    }
};


const keyCodeToName = function (keyCode)
{
    if (!keyCode && keyCode !== 0) return "Unidentified";
    const keys = {
        "8": "Backspace",
        "9": "Tab",
        "12": "Clear",
        "13": "Enter",
        "16": "Shift",
        "17": "Control",
        "18": "Alt",
        "19": "Pause",
        "20": "CapsLock",
        "27": "Escape",
        "32": "Space",
        "33": "PageUp",
        "34": "PageDown",
        "35": "End",
        "36": "Home",
        "37": "ArrowLeft",
        "38": "ArrowUp",
        "39": "ArrowRight",
        "40": "ArrowDown",
        "45": "Insert",
        "46": "Delete",
        "112": "F1",
        "113": "F2",
        "114": "F3",
        "115": "F4",
        "116": "F5",
        "117": "F6",
        "118": "F7",
        "119": "F8",
        "120": "F9",
        "121": "F10",
        "122": "F11",
        "123": "F12",
        "144": "NumLock",
        "145": "ScrollLock",
        "224": "Meta"
    };
    if (keys[keyCode])
    {
        return keys[keyCode];
    }
    else
    {
        return String.fromCharCode(keyCode);
    }
};
// ----------------------------------------------------------------

window.performance = window.performance || {
    "offset": Date.now(),
    "now": function now()
    {
        return Date.now() - this.offset;
    },
};


const logErrorConsole = function (initiator)
{
    CABLES.errorConsole = CABLES.errorConsole || { "log": [] };
    CABLES.errorConsole.log.push({ "initiator": initiator, "arguments": arguments });

    if (!CABLES.errorConsole.ele)
    {
        const ele = document.createElement("div");
        ele.id = "cablesErrorConsole";
        ele.style.width = "90%";
        ele.style.height = "300px";
        ele.style.zIndex = "9999999";
        ele.style.display = "inline-block";
        ele.style.position = "absolute";
        ele.style.padding = "10px";
        ele.style.fontFamily = "monospace";
        ele.style.color = "red";
        ele.style.backgroundColor = "#200";

        CABLES.errorConsole.ele = ele;
        document.body.appendChild(ele);
    }

    let logHtml = "ERROR<br/>for more info, open your browsers dev tools console (Ctrl+Shift+I or Command+Alt+I)<br/>";

    for (let l = 0; l < CABLES.errorConsole.log.length; l++)
    {
        logHtml += CABLES.errorConsole.log[l].initiator + " ";
        for (let i = 1; i < CABLES.errorConsole.log[l].arguments.length; i++)
        {
            if (i > 2)logHtml += ", ";
            let arg = CABLES.errorConsole.log[l].arguments[i];
            if (arg.constructor.name.indexOf("Error") > -1 || arg.constructor.name.indexOf("error") > -1)
            {
                let txt = "Uncaught ErrorEvent ";
                if (arg.message)txt += " message: " + arg.message;
                logHtml += txt;
            }
            else if (typeof arg == "string")
                logHtml += arg;
            else if (typeof arg == "number")
                logHtml += String(arg) + " ";
        }
        logHtml += "<br/>";
    }


    CABLES.errorConsole.ele.innerHTML = logHtml;
};




;// CONCATENATED MODULE: ../shared/client/src/logger.js
/* eslint-disable no-console */

class Logger
{
    constructor(initiator, options)
    {
        this.initiator = initiator;
        this._options = options;
    }

    stack(t)
    {
        console.info("[" + this.initiator + "] ", t);
        console.log((new Error()).stack);
    }

    groupCollapsed(t)
    {
        if ((CABLES.UI && CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 0 }, ...arguments)) || !CABLES.logSilent) console.log("[" + this.initiator + "]", ...arguments);

        console.groupCollapsed("[" + this.initiator + "] " + t);
    }

    table(t)
    {
        console.table(t);
    }

    groupEnd()
    {
        console.groupEnd();
    }

    error()
    {
        if ((CABLES.UI && CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 2 }, ...arguments)) || !CABLES.UI)
        {
            console.error("[" + this.initiator + "]", ...arguments);
        }

        if (this._options && this._options.onError)
        {
            this._options.onError(this.initiator, ...arguments);
            // console.log("emitevent onerror...");
            // CABLES.patch.emitEvent("onError", this.initiator, ...arguments);
            // CABLES.logErrorConsole("[" + this.initiator + "]", ...arguments);
        }
    }

    errorGui()
    {
        if (CABLES.UI) CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 2 }, ...arguments);
    }

    warn()
    {
        if ((CABLES.UI && CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 1 }, ...arguments)) || !CABLES.logSilent)
            console.warn("[" + this.initiator + "]", ...arguments);
    }

    verbose()
    {
        if ((CABLES.UI && CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 0 }, ...arguments)) || !CABLES.logSilent)
            console.log("[" + this.initiator + "]", ...arguments);
    }

    info()
    {
        if ((CABLES.UI && CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 0 }, ...arguments)) || !CABLES.logSilent)
            console.info("[" + this.initiator + "]", ...arguments);
    }

    log()
    {
        if ((CABLES.UI && CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 0 }, ...arguments)) || !CABLES.logSilent)
            console.log("[" + this.initiator + "]", ...arguments);
    }

    logGui()
    {
        if (CABLES.UI) CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 0 }, ...arguments);
    }

    userInteraction(text)
    {
        // this.log({ "initiator": "userinteraction", "text": text });
    }
}

;// CONCATENATED MODULE: ./src/core/anim_key.js


const Key = function (obj)
{
    this.time = 0.0;
    this.value = 0.0;
    // this.ui = null;
    this.onChange = null;
    this._easing = 0;
    // this.bezTangIn = 0;
    // this.bezTangOut = 0;
    // this.bezTime = 0.5;
    // this.bezValue = 0;
    // this.bezTimeIn = -0.5;
    // this.bezValueIn = 0;

    this.cb = null;
    this.cbTriggered = false;

    // const bezierAnim = null;
    // this._updateBezier = false;

    this.setEasing(CONSTANTS.ANIM.EASING_LINEAR);
    this.set(obj);
};

Key.cubicSpline = function (perc, key1, key2)
{
    let
        previousPoint = key1.value,
        previousTangent = key1.bezTangOut,
        nextPoint = key2.value,
        nextTangent = key2.bezTangIn;
    let t = perc;
    let t2 = t * t;
    let t3 = t2 * t;

    return (2 * t3 - 3 * t2 + 1) * previousPoint + (t3 - 2 * t2 + t) * previousTangent + (-2 * t3 + 3 * t2) * nextPoint + (t3 - t2) * nextTangent;
};

Key.easeCubicSpline = function (perc, key2)
{
    return Key.cubicSpline(perc, this, key2);
};


Key.linear = function (perc, key1, key2)
{
    return parseFloat(key1.value) + parseFloat(key2.value - key1.value) * perc;
};

Key.easeLinear = function (perc, key2)
{
    return Key.linear(perc, this, key2);
};

Key.easeAbsolute = function (perc, key2)
{
    return this.value;
};

const easeExpoIn = function (t)
{
    return (t = 2 ** (10 * (t - 1)));
};

Key.easeExpoIn = function (t, key2)
{
    t = easeExpoIn(t);
    return Key.linear(t, this, key2);
};

const easeExpoOut = function (t)
{
    t = -(2 ** (-10 * t)) + 1;
    return t;
};

Key.easeExpoOut = function (t, key2)
{
    t = easeExpoOut(t);
    return Key.linear(t, this, key2);
};

const easeExpoInOut = function (t)
{
    t *= 2;
    if (t < 1)
    {
        t = 0.5 * 2 ** (10 * (t - 1));
    }
    else
    {
        t--;
        t = 0.5 * (-(2 ** (-10 * t)) + 2);
    }
    return t;
};

Key.easeExpoInOut = function (t, key2)
{
    t = easeExpoInOut(t);
    return Key.linear(t, this, key2);
};

Key.easeSinIn = function (t, key2)
{
    t = -1 * Math.cos((t * Math.PI) / 2) + 1;
    return Key.linear(t, this, key2);
};

Key.easeSinOut = function (t, key2)
{
    t = Math.sin((t * Math.PI) / 2);
    return Key.linear(t, this, key2);
};

Key.easeSinInOut = function (t, key2)
{
    t = -0.5 * (Math.cos(Math.PI * t) - 1.0);
    return Key.linear(t, this, key2);
};

const easeCubicIn = function (t)
{
    t = t * t * t;
    return t;
};

Key.easeCubicIn = function (t, key2)
{
    t = easeCubicIn(t);
    return Key.linear(t, this, key2);
};


// b 0
// c 1/2 or 1
// d always 1
// easeOutCubic: function (x, t, b, c, d) {
//     return c*((t=t/d-1)*t*t + 1) + b;

Key.easeInQuint = function (t, key2)
{
    t = t * t * t * t * t;
    return Key.linear(t, this, key2);
};
Key.easeOutQuint = function (t, key2)
{
    t = (t -= 1) * t * t * t * t + 1;
    return Key.linear(t, this, key2);
};
Key.easeInOutQuint = function (t, key2)
{
    if ((t /= 0.5) < 1) t = 0.5 * t * t * t * t * t;
    else t = 0.5 * ((t -= 2) * t * t * t * t + 2);
    return Key.linear(t, this, key2);
};

Key.easeInQuart = function (t, key2)
{
    t = t * t * t * t;
    return Key.linear(t, this, key2);
};

Key.easeOutQuart = function (t, key2)
{
    // return -c * ((t=t/d-1)*t*t*t - 1) + b;
    t = -1 * ((t -= 1) * t * t * t - 1);
    return Key.linear(t, this, key2);
};

Key.easeInOutQuart = function (t, key2)
{
    if ((t /= 0.5) < 1) t = 0.5 * t * t * t * t;
    else t = -0.5 * ((t -= 2) * t * t * t - 2);
    return Key.linear(t, this, key2);
};

Key.bounce = function (t)
{
    if ((t /= 1) < 1 / 2.75) t = 7.5625 * t * t;
    else if (t < 2 / 2.75) t = 7.5625 * (t -= 1.5 / 2.75) * t + 0.75;
    else if (t < 2.5 / 2.75) t = 7.5625 * (t -= 2.25 / 2.75) * t + 0.9375;
    else t = 7.5625 * (t -= 2.625 / 2.75) * t + 0.984375;
    return t;
};

Key.easeInBounce = function (t, key2)
{
    return Key.linear(Key.bounce(t), this, key2);
    // return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d);
};

Key.easeOutBounce = function (t, key2)
{
    return Key.linear(Key.bounce(t), this, key2);
};

Key.easeInElastic = function (t, key2)
{
    let s = 1.70158;
    let p = 0;
    let a = 1;

    const b = 0;
    const d = 1;
    const c = 1;

    if (t === 0) t = b;
    else if ((t /= d) == 1) t = b + c;
    else
    {
        if (!p) p = d * 0.3;
        if (a < Math.abs(c))
        {
            a = c;
            s = p / 4;
        }
        else s = (p / (2 * Math.PI)) * Math.asin(c / a);
        t = -(a * 2 ** (10 * (t -= 1)) * Math.sin(((t * d - s) * (2 * Math.PI)) / p)) + b;
    }

    return Key.linear(t, this, key2);
};


Key.easeOutElastic = function (t, key2)
{
    let s = 1.70158;
    let p = 0;
    let a = 1;

    const b = 0;
    const d = 1;
    const c = 1;

    if (t === 0) t = b;
    else if ((t /= d) == 1) t = b + c;
    else
    {
        if (!p) p = d * 0.3;
        if (a < Math.abs(c))
        {
            a = c;
            s = p / 4;
        }
        else s = (p / (2 * Math.PI)) * Math.asin(c / a);
        t = a * 2 ** (-10 * t) * Math.sin(((t * d - s) * (2 * Math.PI)) / p) + c + b;
    }

    return Key.linear(t, this, key2);
};

Key.easeInBack = function (t, key2)
{
    const s = 1.70158;
    t = t * t * ((s + 1) * t - s);

    return Key.linear(t, this, key2);
};

Key.easeOutBack = function (t, key2)
{
    const s = 1.70158;
    t = (t = t / 1 - 1) * t * ((s + 1) * t + s) + 1;

    return Key.linear(t, this, key2);
};

Key.easeInOutBack = function (t, key2)
{
    let s = 1.70158;
    const c = 1 / 2;
    if ((t /= 1 / 2) < 1) t = c * (t * t * (((s *= 1.525) + 1) * t - s));
    else t = c * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2);

    return Key.linear(t, this, key2);
};

const easeCubicOut = function (t)
{
    t--;
    t = t * t * t + 1;
    return t;
};

Key.easeCubicOut = function (t, key2)
{
    t = easeCubicOut(t);
    return Key.linear(t, this, key2);
};

const easeCubicInOut = function (t)
{
    t *= 2;
    if (t < 1) t = 0.5 * t * t * t;
    else
    {
        t -= 2;
        t = 0.5 * (t * t * t + 2);
    }
    return t;
};

Key.easeCubicInOut = function (t, key2)
{
    t = easeCubicInOut(t);
    return Key.linear(t, this, key2);
};

Key.easeSmoothStep = function (perc, key2)
{
    // var x = Math.max(0, Math.min(1, (perc-0)/(1-0)));
    const x = Math.max(0, Math.min(1, perc));
    perc = x * x * (3 - 2 * x); // smoothstep
    return Key.linear(perc, this, key2);
};

Key.easeSmootherStep = function (perc, key2)
{
    const x = Math.max(0, Math.min(1, (perc - 0) / (1 - 0)));
    perc = x * x * x * (x * (x * 6 - 15) + 10); // smootherstep
    return Key.linear(perc, this, key2);
};

Key.prototype.setEasing = function (e)
{
    this._easing = e;

    if (this._easing == CONSTANTS.ANIM.EASING_LINEAR) this.ease = Key.easeLinear;
    else if (this._easing == CONSTANTS.ANIM.EASING_ABSOLUTE) this.ease = Key.easeAbsolute;
    else if (this._easing == CONSTANTS.ANIM.EASING_SMOOTHSTEP) this.ease = Key.easeSmoothStep;
    else if (this._easing == CONSTANTS.ANIM.EASING_SMOOTHERSTEP) this.ease = Key.easeSmootherStep;
    else if (this._easing == CONSTANTS.ANIM.EASING_CUBIC_IN) this.ease = Key.easeCubicIn;
    else if (this._easing == CONSTANTS.ANIM.EASING_CUBIC_OUT) this.ease = Key.easeCubicOut;
    else if (this._easing == CONSTANTS.ANIM.EASING_CUBIC_INOUT) this.ease = Key.easeCubicInOut;
    else if (this._easing == CONSTANTS.ANIM.EASING_EXPO_IN) this.ease = Key.easeExpoIn;
    else if (this._easing == CONSTANTS.ANIM.EASING_EXPO_OUT) this.ease = Key.easeExpoOut;
    else if (this._easing == CONSTANTS.ANIM.EASING_EXPO_INOUT) this.ease = Key.easeExpoInOut;
    else if (this._easing == CONSTANTS.ANIM.EASING_SIN_IN) this.ease = Key.easeSinIn;
    else if (this._easing == CONSTANTS.ANIM.EASING_SIN_OUT) this.ease = Key.easeSinOut;
    else if (this._easing == CONSTANTS.ANIM.EASING_SIN_INOUT) this.ease = Key.easeSinInOut;
    else if (this._easing == CONSTANTS.ANIM.EASING_BACK_OUT) this.ease = Key.easeOutBack;
    else if (this._easing == CONSTANTS.ANIM.EASING_BACK_IN) this.ease = Key.easeInBack;
    else if (this._easing == CONSTANTS.ANIM.EASING_BACK_INOUT) this.ease = Key.easeInOutBack;
    else if (this._easing == CONSTANTS.ANIM.EASING_ELASTIC_IN) this.ease = Key.easeInElastic;
    else if (this._easing == CONSTANTS.ANIM.EASING_ELASTIC_OUT) this.ease = Key.easeOutElastic;
    else if (this._easing == CONSTANTS.ANIM.EASING_ELASTIC_INOUT) this.ease = Key.easeElasticInOut;
    else if (this._easing == CONSTANTS.ANIM.EASING_BOUNCE_IN) this.ease = Key.easeInBounce;
    else if (this._easing == CONSTANTS.ANIM.EASING_BOUNCE_OUT) this.ease = Key.easeOutBounce;
    else if (this._easing == CONSTANTS.ANIM.EASING_QUART_OUT) this.ease = Key.easeOutQuart;
    else if (this._easing == CONSTANTS.ANIM.EASING_QUART_IN) this.ease = Key.easeInQuart;
    else if (this._easing == CONSTANTS.ANIM.EASING_QUART_INOUT) this.ease = Key.easeInOutQuart;
    else if (this._easing == CONSTANTS.ANIM.EASING_QUINT_OUT) this.ease = Key.easeOutQuint;
    else if (this._easing == CONSTANTS.ANIM.EASING_QUINT_IN) this.ease = Key.easeInQuint;
    else if (this._easing == CONSTANTS.ANIM.EASING_QUINT_INOUT) this.ease = Key.easeInOutQuint;
    else if (this._easing == CONSTANTS.ANIM.EASING_CUBICSPLINE)
    {
        // this._updateBezier = true;
        this.ease = Key.easeCubicSpline;
    }
    else
    {
        this._easing = CONSTANTS.ANIM.EASING_LINEAR;
        this.ease = Key.easeLinear;
    }
};

Key.prototype.trigger = function ()
{
    this.cb();
    this.cbTriggered = true;
};

Key.prototype.setValue = function (v)
{
    this.value = v;
    // this._updateBezier = true;
    if (this.onChange !== null) this.onChange();
};

Key.prototype.set = function (obj)
{
    if (obj)
    {
        if (obj.e) this.setEasing(obj.e);
        if (obj.cb)
        {
            this.cb = obj.cb;
            this.cbTriggered = false;
        }

        if (obj.b)
        {
            // this.bezTime = obj.b[0];
            // this.bezValue = obj.b[1];
            // this.bezTimeIn = obj.b[2];
            // this.bezValueIn = obj.b[3];
            // this._updateBezier = true;
        }

        if (obj.hasOwnProperty("t")) this.time = obj.t;
        if (obj.hasOwnProperty("time")) this.time = obj.time;
        if (obj.hasOwnProperty("v")) this.value = obj.v;
        else if (obj.hasOwnProperty("value")) this.value = obj.value;
    }
    if (this.onChange !== null) this.onChange();
};

Key.prototype.getSerialized = function ()
{
    const obj = {};
    obj.t = this.time;
    obj.v = this.value;
    obj.e = this._easing;
    // if (this._easing == CONSTANTS.ANIM.EASING_CUBICSPLINE) obj.b = [this.bezTime, this.bezValue, this.bezTimeIn, this.bezValueIn];

    return obj;
};

Key.prototype.getEasing = function ()
{
    return this._easing;
};



;// CONCATENATED MODULE: ./src/core/eventtarget.js


const EventTarget = function ()
{
    this._log = new Logger("eventtarget");
    this._eventCallbacks = {};
    this._logName = "";
    this._logEvents = false;
    this._listeners = {};

    this.addEventListener = this.on = function (which, cb, idPrefix)
    {
        const event =
        {
            "id": (idPrefix || "") + CABLES.simpleId(),
            "name": which,
            "cb": cb,
        };
        if (!this._eventCallbacks[which]) this._eventCallbacks[which] = [event];
        else this._eventCallbacks[which].push(event);

        this._listeners[event.id] = event;

        return event.id;
    };

    this.hasEventListener = function (which, cb)
    {
        if (which && !cb)
        {
            // check by id
            if (this._listeners[which]) return true;
            else return false;
        }
        else
        {
            this._log.warn("old eventtarget function haseventlistener!");
            if (which && cb)
            {
                if (this._eventCallbacks[which])
                {
                    const idx = this._eventCallbacks[which].indexOf(cb);
                    if (idx == -1) return false;
                    return true;
                }
            }
        }
    };

    this.hasListenerForEventName = function (eventName)
    {
        return this._eventCallbacks[eventName] && this._eventCallbacks[eventName].length > 0;
    };

    this.removeEventListener = this.off = function (which, cb)
    {
        if (which === null || which === undefined) return;

        if (!cb) // new style, remove by id, not by name/callback
        {
            const event = this._listeners[which];
            if (!event)
            {
                this._log.log("removeEvent: could not find event...", which, this);
                return;
            }

            let found = true;
            while (found)
            {
                found = false;
                let index = -1;
                for (let i = 0; i < this._eventCallbacks[event.name].length; i++)
                {
                    if (this._eventCallbacks[event.name][i].id.startsWith(which)) // this._eventCallbacks[event.name][i].id == which ||
                    {
                        found = true;
                        index = i;
                    }
                }

                if (index !== -1)
                {
                    this._eventCallbacks[event.name].splice(index, 1);
                    delete this._listeners[which];
                }
            }

            return;
        }

        this._log.info("[eventtaget] ", "old function signature: removeEventListener! use listener id");
        this._log.log((new Error()).stack);

        let index = null;
        for (let i = 0; i < this._eventCallbacks[which].length; i++)
            if (this._eventCallbacks[which][i].cb == cb)
                index = i;

        if (index !== null)
        {
            delete this._eventCallbacks[index];
        }
        else this._log.warn("removeEventListener not found " + which);
    };

    this.logEvents = function (enabled, name)
    {
        this._logEvents = enabled;
        this._logName = name;
    };

    this.emitEvent = function (which, param1, param2, param3, param4, param5, param6)
    {
        if (this._logEvents) this._log.log("[event] ", this._logName, which, this._eventCallbacks);

        if (this._eventCallbacks[which])
        {
            for (let i = 0; i < this._eventCallbacks[which].length; i++)
            {
                if (this._eventCallbacks[which][i])
                {
                    this._eventCallbacks[which][i].cb(param1, param2, param3, param4, param5, param6);
                }
            }
        }
        else
        {
            if (this._logEvents) this._log.log("[event] has no event callback", which, this._eventCallbacks);
        }
    };
};



;// CONCATENATED MODULE: ./src/core/anim.js





/**
 * Keyframed interpolated animation.
 *
 * Available Easings:
 * <code>
 * CONSTANTS.ANIM.EASING_LINEAR
 * CONSTANTS.ANIM.EASING_ABSOLUTE
 * CONSTANTS.ANIM.EASING_SMOOTHSTEP
 * CONSTANTS.ANIM.EASING_SMOOTHERSTEP
 * CONSTANTS.ANIM.EASING_CUBICSPLINE

 * CONSTANTS.ANIM.EASING_CUBIC_IN
 * CONSTANTS.ANIM.EASING_CUBIC_OUT
 * CONSTANTS.ANIM.EASING_CUBIC_INOUT

 * CONSTANTS.ANIM.EASING_EXPO_IN
 * CONSTANTS.ANIM.EASING_EXPO_OUT
 * CONSTANTS.ANIM.EASING_EXPO_INOUT

 * CONSTANTS.ANIM.EASING_SIN_IN
 * CONSTANTS.ANIM.EASING_SIN_OUT
 * CONSTANTS.ANIM.EASING_SIN_INOUT

 * CONSTANTS.ANIM.EASING_BACK_IN
 * CONSTANTS.ANIM.EASING_BACK_OUT
 * CONSTANTS.ANIM.EASING_BACK_INOUT

 * CONSTANTS.ANIM.EASING_ELASTIC_IN
 * CONSTANTS.ANIM.EASING_ELASTIC_OUT

 * CONSTANTS.ANIM.EASING_BOUNCE_IN
 * CONSTANTS.ANIM.EASING_BOUNCE_OUT

 * CONSTANTS.ANIM.EASING_QUART_IN
 * CONSTANTS.ANIM.EASING_QUART_OUT
 * CONSTANTS.ANIM.EASING_QUART_INOUT

 * CONSTANTS.ANIM.EASING_QUINT_IN
 * CONSTANTS.ANIM.EASING_QUINT_OUT
 * CONSTANTS.ANIM.EASING_QUINT_INOUT
 * </code>
 * @class
 * @param cfg
 * @example
 * var anim=new CABLES.Anim();
 * anim.setValue(0,0);  // set value 0 at 0 seconds
 * anim.setValue(10,1); // set value 1 at 10 seconds
 * anim.getValue(5);    // get value at 5 seconds - this returns 0.5
 */

const Anim = function (cfg)
{
    EventTarget.apply(this);

    cfg = cfg || {};
    this.keys = [];
    this.onChange = null;
    this.stayInTimeline = false;
    this.loop = false;
    this._log = new Logger("Anim");
    this._lastKeyIndex = 0;
    this._cachedIndex = 0;
    this.name = cfg.name || null;

    /**
     * @member defaultEasing
     * @memberof Anim
     * @instance
     * @type {Number}
     */
    this.defaultEasing = cfg.defaultEasing || CONSTANTS.ANIM.EASING_LINEAR;
    this.onLooped = null;

    this._timesLooped = 0;
    this._needsSort = false;
};

Anim.prototype.forceChangeCallback = function ()
{
    if (this.onChange !== null) this.onChange();
    this.emitEvent("onChange", this);
};

Anim.prototype.getLoop = function ()
{
    return this.loop;
};

Anim.prototype.setLoop = function (target)
{
    this.loop = target;
    this.emitEvent("onChange", this);
};

/**
 * returns true if animation has ended at @time
 * checks if last key time is < time
 * @param {Number} time
 * @returns {Boolean}
 * @memberof Anim
 * @instance
 * @function
 */
Anim.prototype.hasEnded = function (time)
{
    if (this.keys.length === 0) return true;
    if (this.keys[this._lastKeyIndex].time <= time) return true;
    return false;
};

Anim.prototype.isRising = function (time)
{
    if (this.hasEnded(time)) return false;
    const ki = this.getKeyIndex(time);
    if (this.keys[ki].value < this.keys[ki + 1].value) return true;
    return false;
};

/**
 * remove all keys from animation before time
 * @param {Number} time
 * @memberof Anim
 * @instance
 * @function
 */
Anim.prototype.clearBefore = function (time)
{
    const v = this.getValue(time);
    const ki = this.getKeyIndex(time);

    this.setValue(time, v);

    if (ki > 1) this.keys.splice(0, ki);
    this._updateLastIndex();
};
/**
 * remove all keys from animation
 * @param {Number} [time=0] set a new key at time with the old value at time
 * @memberof Anim
 * @instance
 * @function
 */
Anim.prototype.clear = function (time)
{
    let v = 0;
    if (time) v = this.getValue(time);
    this.keys.length = 0;
    this._updateLastIndex();
    if (time) this.setValue(time, v);
    if (this.onChange !== null) this.onChange();
    this.emitEvent("onChange", this);
};

Anim.prototype.sortKeys = function ()
{
    this.keys.sort((a, b) => { return parseFloat(a.time) - parseFloat(b.time); });
    this._updateLastIndex();
    this._needsSort = false;
    if (this.keys.length % 1000 == 0)console.log(this.name, this.keys.length);
};

Anim.prototype.getLength = function ()
{
    if (this.keys.length === 0) return 0;
    return this.keys[this.keys.length - 1].time;
};

Anim.prototype.getKeyIndex = function (time)
{
    let index = 0;
    let start = 0;
    if (this._cachedIndex && this.keys.length > this._cachedIndex && time >= this.keys[this._cachedIndex].time) start = this._cachedIndex;
    for (let i = start; i < this.keys.length; i++)
    {
        if (time >= this.keys[i].time) index = i;
        if (this.keys[i].time > time)
        {
            if (time != 0) this._cachedIndex = index;
            return index;
        }
    }

    return index;
};

/**
 * set value at time
 * @function setValue
 * @memberof Anim
 * @instance
 * @param {Number} time
 * @param {Number} value
 * @param {Function} cb callback
 */
Anim.prototype.setValue = function (time, value, cb)
{
    let found = null;

    if (this.keys.length == 0 || time <= this.keys[this.keys.length - 1].time)
        for (let i = 0; i < this.keys.length; i++)
            if (this.keys[i].time == time)
            {
                found = this.keys[i];
                this.keys[i].setValue(value);
                this.keys[i].cb = cb;
                break;
            }

    if (!found)
    {
        found = new Key(
            {
                "time": time,
                "value": value,
                "e": this.defaultEasing,
                "cb": cb,
            });
        this.keys.push(found);

        // if (this.keys.length % 1000 == 0)console.log(this.name, this.keys.length);
        this._updateLastIndex();
    }

    if (this.onChange) this.onChange();
    this.emitEvent("onChange", this);
    this._needsSort = true;
    return found;
};

Anim.prototype.setKeyEasing = function (index, e)
{
    if (this.keys[index])
    {
        this.keys[index].setEasing(e);
        this.emitEvent("onChange", this);
    }
};

Anim.prototype.getSerialized = function ()
{
    const obj = {};
    obj.keys = [];
    obj.loop = this.loop;

    for (let i = 0; i < this.keys.length; i++)
        obj.keys.push(this.keys[i].getSerialized());

    return obj;
};

Anim.prototype.getKey = function (time)
{
    const index = this.getKeyIndex(time);
    return this.keys[index];
};

Anim.prototype.getNextKey = function (time)
{
    let index = this.getKeyIndex(time) + 1;
    if (index >= this.keys.length) index = this.keys.length - 1;

    return this.keys[index];
};

Anim.prototype.isFinished = function (time)
{
    if (this.keys.length <= 0) return true;
    return time > this.keys[this.keys.length - 1].time;
};

Anim.prototype.isStarted = function (time)
{
    if (this.keys.length <= 0) return false;
    return time >= this.keys[0].time;
};

/**
 * get value at time
 * @function getValue
 * @memberof Anim
 * @instance
 * @param {Number} [time] time
 * @returns {Number} interpolated value at time
 */
Anim.prototype.getValue = function (time)
{
    if (this.keys.length === 0)
    {
        return 0;
    }
    if (this._needsSort) this.sortKeys();

    if (!this.loop && time > this.keys[this._lastKeyIndex].time)
    {
        if (this.keys[this._lastKeyIndex].cb && !this.keys[this._lastKeyIndex].cbTriggered) this.keys[this._lastKeyIndex].trigger();

        return this.keys[this._lastKeyIndex].value;
    }

    if (time < this.keys[0].time)
    {
        // if (this.name)console.log("A");

        return this.keys[0].value;
    }

    if (this.loop && time > this.keys[this._lastKeyIndex].time)
    {
        const currentLoop = time / this.keys[this._lastKeyIndex].time;
        if (currentLoop > this._timesLooped)
        {
            this._timesLooped++;
            if (this.onLooped) this.onLooped();
        }
        time = (time - this.keys[0].time) % (this.keys[this._lastKeyIndex].time - this.keys[0].time);
        time += this.keys[0].time;
    }

    const index = this.getKeyIndex(time);
    if (index >= this._lastKeyIndex)
    {
        if (this.keys[this._lastKeyIndex].cb && !this.keys[this._lastKeyIndex].cbTriggered) this.keys[this._lastKeyIndex].trigger();

        return this.keys[this._lastKeyIndex].value;
    }


    const index2 = index + 1;
    const key1 = this.keys[index];
    const key2 = this.keys[index2];

    if (key1.cb && !key1.cbTriggered) key1.trigger();

    if (!key2) return -1;

    const perc = (time - key1.time) / (key2.time - key1.time);

    if (!key1.ease) this.log._warn("has no ease", key1, key2);

    return key1.ease(perc, key2);
};

Anim.prototype._updateLastIndex = function ()
{
    this._lastKeyIndex = this.keys.length - 1;
};

Anim.prototype.addKey = function (k)
{
    if (k.time === undefined)
    {
        this.log.warn("key time undefined, ignoring!");
    }
    else
    {
        this.keys.push(k);
        if (this.onChange !== null) this.onChange();
        this.emitEvent("onChange", this);
    }
    this._updateLastIndex();
};

Anim.prototype.easingFromString = function (str)
{
    if (str == "linear") return CONSTANTS.ANIM.EASING_LINEAR;
    if (str == "absolute") return CONSTANTS.ANIM.EASING_ABSOLUTE;
    if (str == "smoothstep") return CONSTANTS.ANIM.EASING_SMOOTHSTEP;
    if (str == "smootherstep") return CONSTANTS.ANIM.EASING_SMOOTHERSTEP;

    if (str == "Cubic In") return CONSTANTS.ANIM.EASING_CUBIC_IN;
    if (str == "Cubic Out") return CONSTANTS.ANIM.EASING_CUBIC_OUT;
    if (str == "Cubic In Out") return CONSTANTS.ANIM.EASING_CUBIC_INOUT;

    if (str == "Expo In") return CONSTANTS.ANIM.EASING_EXPO_IN;
    if (str == "Expo Out") return CONSTANTS.ANIM.EASING_EXPO_OUT;
    if (str == "Expo In Out") return CONSTANTS.ANIM.EASING_EXPO_INOUT;

    if (str == "Sin In") return CONSTANTS.ANIM.EASING_SIN_IN;
    if (str == "Sin Out") return CONSTANTS.ANIM.EASING_SIN_OUT;
    if (str == "Sin In Out") return CONSTANTS.ANIM.EASING_SIN_INOUT;

    if (str == "Back In") return CONSTANTS.ANIM.EASING_BACK_IN;
    if (str == "Back Out") return CONSTANTS.ANIM.EASING_BACK_OUT;
    if (str == "Back In Out") return CONSTANTS.ANIM.EASING_BACK_INOUT;

    if (str == "Elastic In") return CONSTANTS.ANIM.EASING_ELASTIC_IN;
    if (str == "Elastic Out") return CONSTANTS.ANIM.EASING_ELASTIC_OUT;

    if (str == "Bounce In") return CONSTANTS.ANIM.EASING_BOUNCE_IN;
    if (str == "Bounce Out") return CONSTANTS.ANIM.EASING_BOUNCE_OUT;

    if (str == "Quart Out") return CONSTANTS.ANIM.EASING_QUART_OUT;
    if (str == "Quart In") return CONSTANTS.ANIM.EASING_QUART_IN;
    if (str == "Quart In Out") return CONSTANTS.ANIM.EASING_QUART_INOUT;

    if (str == "Quint Out") return CONSTANTS.ANIM.EASING_QUINT_OUT;
    if (str == "Quint In") return CONSTANTS.ANIM.EASING_QUINT_IN;
    if (str == "Quint In Out") return CONSTANTS.ANIM.EASING_QUINT_INOUT;
};

Anim.prototype.createPort = function (op, title, cb)
{
    const port = op.inDropDown(title, CONSTANTS.ANIM.EASINGS, "Cubic Out");

    // const port = op.addInPort(
    //     new Port(op, title, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
    //         "display": "dropdown",
    //         "values": CONSTANTS.ANIM.EASINGS,
    //     }),
    // );

    port.set("linear");
    port.defaultValue = "linear";

    port.onChange = function ()
    {
        this.defaultEasing = this.easingFromString(port.get());
        this.emitEvent("onChangeDefaultEasing", this);

        if (cb) cb();
    }.bind(this);

    return port;
};

// ------------------------------

Anim.slerpQuaternion = function (time, q, animx, animy, animz, animw)
{
    if (!Anim.slerpQuaternion.q1)
    {
        Anim.slerpQuaternion.q1 = quat.create();
        Anim.slerpQuaternion.q2 = quat.create();
    }

    const i1 = animx.getKeyIndex(time);
    let i2 = i1 + 1;
    if (i2 >= animx.keys.length) i2 = animx.keys.length - 1;

    if (i1 == i2)
    {
        quat.set(q, animx.keys[i1].value, animy.keys[i1].value, animz.keys[i1].value, animw.keys[i1].value);
    }
    else
    {
        const key1Time = animx.keys[i1].time;
        const key2Time = animx.keys[i2].time;
        const perc = (time - key1Time) / (key2Time - key1Time);

        quat.set(Anim.slerpQuaternion.q1, animx.keys[i1].value, animy.keys[i1].value, animz.keys[i1].value, animw.keys[i1].value);

        quat.set(Anim.slerpQuaternion.q2, animx.keys[i2].value, animy.keys[i2].value, animz.keys[i2].value, animw.keys[i2].value);

        quat.slerp(q, Anim.slerpQuaternion.q1, Anim.slerpQuaternion.q2, perc);
    }
    return q;
};

const ANIM = { "Key": Key };




;// CONCATENATED MODULE: ./src/core/core_link.js



/**
 * @namespace external:CABLES#Link
 * @param {Object} scene The patch object
 * @description a link is a connection between two ops/ports -> one input and one output port
 * @hideconstructor
 * @class
 */
const Link = function (scene)
{
    EventTarget.apply(this);

    this.id = CABLES.simpleId();
    this.portIn = null;
    this.portOut = null;
    this.scene = scene; // todo: make private and rename to patch
    this.activityCounter = 0;
    this.ignoreInSerialize = false;
};

Link.prototype.setValue = function (v)
{
    if (v === undefined) this._setValue();
    else this.portIn.set(v);
};

Link.prototype.activity = function ()
{
    this.activityCounter++;
    // if(Date.now()-this.lastTime>100)
    // {
    //     // this.lastTime=Date.now();
    //     // this.changesPerSecond=this.changesCounter*10;
    //     this.changesCounter=0;
    // }
};

Link.prototype._setValue = function ()
{
    if (!this.portOut)
    {
        this.remove();
        return;
    }
    const v = this.portOut.get();

    if (v == v) // NaN is the only JavaScript value that is treated as unequal to itself
    {
        if (this.portIn.type != CONSTANTS.OP.OP_PORT_TYPE_FUNCTION) this.activity();

        if (this.portIn.get() !== v)
        {
            this.portIn.set(v);
        }
        else
        {
            if (this.portIn.changeAlways) this.portIn.set(v);
            if (this.portOut.forceRefChange) this.portIn.forceChange();
        }
    }
};

/**
 * @function getOtherPort
 * @memberof Link
 * @instance
 * @param {Port} p port
 * @description returns the port of the link, which is not port
 */
Link.prototype.getOtherPort = function (p)
{
    if (p == this.portIn) return this.portOut;
    return this.portIn;
};

/**
 * @function remove
 * @memberof Link
 * @instance
 * @description unlink/remove this link from all ports
 */
Link.prototype.remove = function ()
{
    if (this.portIn) this.portIn.removeLink(this);
    if (this.portOut) this.portOut.removeLink(this);
    if (this.scene)
    {
        this.scene.emitEvent("onUnLink", this.portIn, this.portOut, this);
    }

    if (this.portIn && (this.portIn.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT || this.portIn.type == CONSTANTS.OP.OP_PORT_TYPE_ARRAY))
    {
        this.portIn.set(null);
        if (this.portIn.links.length > 0) this.portIn.set(this.portIn.links[0].getOtherPort(this.portIn).get());
    }

    if (this.portIn) this.portIn.op._checkLinksNeededToWork();
    if (this.portOut) this.portOut.op._checkLinksNeededToWork();

    this.portIn = null;
    this.portOut = null;
    this.scene = null;
};

/**
 * @function link
 * @memberof Link
 * @instance
 * @description link those two ports
 * @param {Port} p1 port1
 * @param {Port} p2 port2
 */
Link.prototype.link = function (p1, p2)
{
    if (!Link.canLink(p1, p2))
    {
        console.warn("[core_link] cannot link ports!", p1, p2);
        return false;
    }

    if (p1.direction == CONSTANTS.PORT.PORT_DIR_IN)
    {
        this.portIn = p1;
        this.portOut = p2;
    }
    else
    {
        this.portIn = p2;
        this.portOut = p1;
    }

    p1.addLink(this);
    p2.addLink(this);

    this.setValue();

    if (p1.onLink) p1.onLink(this);
    if (p2.onLink) p2.onLink(this);

    p1.op._checkLinksNeededToWork();
    p2.op._checkLinksNeededToWork();
};

Link.prototype.getSerialized = function ()
{
    const obj = {};

    obj.portIn = this.portIn.getName();
    obj.portOut = this.portOut.getName();
    obj.objIn = this.portIn.op.id;
    obj.objOut = this.portOut.op.id;

    return obj;
};

// --------------------------------------------

/**
 * @function canLinkText
 * @memberof Link
 * @instance
 * @description return a text message with human readable reason if ports can not be linked, or can be
 * @param {Port} p1 port1
 * @param {Port} p2 port2
 */
Link.canLinkText = function (p1, p2)
{
    if (p1.direction == p2.direction)
    {
        let txt = "(out)";
        if (p2.direction == CONSTANTS.PORT.PORT_DIR_IN) txt = "(in)";
        return "can not link: same direction " + txt;
    }
    if (p1.op == p2.op) return "can not link: same op";
    if (p1.type != CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC && p2.type != CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC)
    {
        if (p1.type != p2.type) return "can not link: different type";
    }

    if (CABLES.UI && p1.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT && p2.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT)
    {
        if (p1.uiAttribs.objType && p2.uiAttribs.objType)
            if (p1.uiAttribs.objType != p2.uiAttribs.objType)
                return "incompatible objects";
    }


    if (!p1) return "can not link: port 1 invalid";
    if (!p2) return "can not link: port 2 invalid";

    if (p1.direction == CONSTANTS.PORT.PORT_DIR_IN && p1.isAnimated()) return "can not link: is animated";
    if (p2.direction == CONSTANTS.PORT.PORT_DIR_IN && p2.isAnimated()) return "can not link: is animated";

    // if(p1.direction==CABLES.CONSTANTS.PORT.PORT_DIR_IN && p1.links.length>0)return 'input port already busy';
    // if(p2.direction==CABLES.CONSTANTS.PORT.PORT_DIR_IN && p2.links.length>0)return 'input port already busy';
    if (p1.isLinkedTo(p2)) return "ports already linked";

    if ((p1.canLink && !p1.canLink(p2)) || (p2.canLink && !p2.canLink(p1))) return "Incompatible";

    return "can link";
};

/**
 * @function canLink
 * @memberof Link
 * @instance
 * @description return true if ports can be linked
 * @param {Port} p1 port1
 * @param {Port} p2 port2
 * @returns {Boolean}
 */
Link.canLink = function (p1, p2)
{
    if (!p1) return false;
    if (!p2) return false;
    if (p1.direction == CONSTANTS.PORT.PORT_DIR_IN && p1.isAnimated()) return false;
    if (p2.direction == CONSTANTS.PORT.PORT_DIR_IN && p2.isAnimated()) return false;

    if (p1.isHidden() || p2.isHidden()) return false;

    if (p1.isLinkedTo(p2)) return false;

    if (p1.direction == p2.direction) return false;

    if (CABLES.UI && p1.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT && p2.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT)
    {
        if (p1.uiAttribs.objType && p2.uiAttribs.objType)
        {
            if (p1.uiAttribs.objType.indexOf("sg_") == 0 && p2.uiAttribs.objType.indexOf("sg_") == 0) return true;
            if (p1.uiAttribs.objType != p2.uiAttribs.objType)
                return false;
        }
    }

    if (p1.type != p2.type && (p1.type != CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC && p2.type != CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC)) return false;
    if (p1.type == CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC || p2.type == CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC) return true;

    if (p1.op == p2.op) return false;

    if (p1.canLink && !p1.canLink(p2)) return false;
    if (p2.canLink && !p2.canLink(p1)) return false;

    return true;
};



;// CONCATENATED MODULE: ./src/core/core_port.js







/**
 * data is coming into and out of ops through input and output ports
 * @namespace external:CABLES#Port
 * @class
 * @hideconstructor
 * @param ___op
 * @param name
 * @param type
 * @param uiAttribs
 * @example
 * const myPort=op.inString("String Port");
 */
const Port = function (___op, name, type, uiAttribs)
{
    EventTarget.apply(this);

    this.data = {}; // UNUSED, DEPRECATED, only left in for backwards compatibility with userops
    this._log = new Logger("core_port");
    /**
     * @type {Number}
     * @name direction
     * @instance
     * @memberof Port
     * @description direction of port (input(0) or output(1))
     */
    this.direction = CONSTANTS.PORT.PORT_DIR_IN;
    this.id = String(CABLES.simpleId());
    this._op = ___op;

    /**
     * @type {Array<Link>}
     * @name links
     * @instance
     * @memberof Port
     * @description links of port
     */
    this.links = [];
    this.value = 0.0;
    this.name = name;
    this.type = type || CONSTANTS.OP.OP_PORT_TYPE_VALUE;
    this.uiAttribs = uiAttribs || {};
    this.anim = null;
    this._oldAnimVal = -5711;
    this.defaultValue = null;


    this._uiActiveState = true;
    this.ignoreValueSerialize = false;
    this.onLinkChanged = null;
    this.crashed = false;

    this._valueBeforeLink = null;
    this._lastAnimFrame = -1;
    this._animated = false;

    this.onValueChanged = null;
    this.onTriggered = null;
    this.onUiActiveStateChange = null;
    this.changeAlways = false;
    this.forceRefChange = false;

    this._useVariableName = null;

    this.activityCounter = 0;
    this.apf = 0;
    this.activityCounterStartFrame = 0;

    this._tempLastUiValue = null;

    Object.defineProperty(this, "title", {
        get()
        {
            return this.uiAttribs.title || this.name;
        } });

    Object.defineProperty(this, "parent", {
        get()
        {
            this._log.stack("use port.op, not .parent");
            return this._op;
        } });

    Object.defineProperty(this, "op", {
        get()
        {
            return this._op;
        } });

    Object.defineProperty(this, "val", {
        get()
        {
            // this._log.warn("val getter deprecated!", this);
            // this._log.stack("val getter deprecated");
            return this.get();
        },
        set(v)
        {
            // this._log.warn("val setter deprecated!", this);
            // this._log.stack("val setter deprecated");
            this.setValue(v);
        }
    });
};


/**
 * copy over a uiattrib from an external connected port to another port
 * @function copyLinkedUiAttrib
 * @memberof Port
 * @param {string} which attrib name
 * @param {Port} port source port
 * @instance
 * @example

inArray.onLinkChanged=()=>
{
    if(inArray) inArray.copyLinkedUiAttrib("stride", outArray);
};

 */
Port.prototype.copyLinkedUiAttrib = function (which, port)
{
    if (!CABLES.UI) return;
    if (!this.isLinked()) return;

    const attr = {};
    attr[which] = this.links[0].getOtherPort(this).getUiAttrib(which);
    port.setUiAttribs(attr);
};


// TODO make extend class for ports, like for ops only for ui
Port.prototype.getValueForDisplay = function ()
{
    let str = this.value;

    if (typeof this.value === "string" || this.value instanceof String)
    {
        if (str.length > 1000)
        {
            str = str.substring(0, 999);
            str += "...";
        }
        if (this.uiAttribs && (this.uiAttribs.display == "boolnum"))
        {
            str += " - ";

            if (!this.value) str += "false";
            else str += "true";
        }

        str = str.replace(/[\u00A0-\u9999<>\&]/g, function (i)
        {
            return "&#" + i.charCodeAt(0) + ";";
        });


        if (str.length > 100) str = str.substring(0, 100);
    }
    else
    {
        str = this.value;
    }
    return str;
};

/**
 * change listener for input value ports, overwrite to react to changes
 * @function onChange
 * @memberof Port
 * @instance
 * @example
 * const myPort=op.inString("MyPort");
 * myPort.onChange=function()
 * {
 *   console.log("was changed to: ",myPort.get());
 * }
 *
 */
Port.prototype.onAnimToggle = function () {};
Port.prototype._onAnimToggle = function ()
{
    this.onAnimToggle();
};


/**
 * @function remove
 * @memberof Port
 * @instance
 * @description remove port
 */
Port.prototype.remove = function ()
{
    // this.setUiAttribs({ "hidePort": true });
    this.removeLinks();
    this._op.removePort(this);
};

/**
 * set ui attributes
 * @function setUiAttribs
 * @memberof Port
 * @instance
 * @param {Object} newAttribs
 * <pre>
 * title - overwrite title of port (by default this is portname)
 * greyout - port paramater will appear greyed out, can not be
 * hidePort - port will be hidden from op
 * hideParam - port params will be hidden from parameter panel
 * showIndex - only for dropdowns - show value index (e.g. `0 - normal` )
 * editorSyntax - set syntax highlighting theme for editor port
 * ignoreObjTypeErrors - do not auto check object types
 * </pre>
 * @example
 * myPort.setUiAttribs({greyout:true});
 */
Port.prototype.setUiAttribs = function (newAttribs)
{
    let changed = false;
    if (!this.uiAttribs) this.uiAttribs = {};

    for (const p in newAttribs)
    {
        if (newAttribs[p] === undefined)
        {
            // delete newAttribs[p];
            delete this.uiAttribs[p];
            continue;
        }
        if (this.uiAttribs[p] != newAttribs[p]) changed = true;
        this.uiAttribs[p] = newAttribs[p];

        if (p == "group" && this.indexPort) this.indexPort.setUiAttribs({ "group": newAttribs[p] });
    }

    if (newAttribs.hasOwnProperty("expose")) this._op.patch.emitEvent("subpatchExpose", this._op.uiAttribs.subPatch);

    if (changed) this.emitEvent("onUiAttrChange", newAttribs, this);
};

/**
 * get ui attributes
 * @function getUiAttribs
 * @memberof Port
 * @example
 * myPort.getUiAttribs();
 */
Port.prototype.getUiAttribs = function ()
{
    return this.uiAttribs;
};

/**
 * get ui attribute
 * @function getUiAttrib
 * @memberof Port
 * @instance
 * @param {String} attribName
 * <pre>
 * attribName - return value of the ui-attribute, or null on unknown attribute
 * </pre>
 * @example
 * myPort.setUiAttribs("values");
 */
Port.prototype.getUiAttrib = function (attribName)
{
    if (!this.uiAttribs || !this.uiAttribs.hasOwnProperty(attribName))
    {
        return null;
    }
    return this.uiAttribs[attribName];
};

/**
 * @function get
 * @memberof Port
 * @instance
 * @description get value of port
 */
Port.prototype.get = function ()
{
    if (this._animated && this._lastAnimFrame != this._op.patch.getFrameNum())
    {
        this._lastAnimFrame = this._op.patch.getFrameNum();

        let animval = this.anim.getValue(this._op.patch.timer.getTime());

        if (this.value != animval)
        {
            this.value = animval;
            this._oldAnimVal = this.value;
            this.forceChange();
        }
    }

    return this.value;
};

Port.prototype.setRef = function (v)
{
    this.forceRefChange = true;
    this.set(v);
};

/**
 * @function setValue
 * @memberof Port
 * @instance
 * @description set value of port / will send value to all linked ports (only for output ports)
 */
Port.prototype.set = Port.prototype.setValue = function (v)
{
    if (v === undefined) v = null;


    if (CABLES.UI && CABLES.UI.showDevInfos)
        if (this.direction == CONSTANTS.PORT.PORT_DIR_OUT && this.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT && v && !this.forceRefChange)
            this._log.warn("object port uses .set", this.name, this.op.objName);


    if (this._op.enabled && !this.crashed)
    {
        if (v !== this.value || this.changeAlways || this.type == CONSTANTS.OP.OP_PORT_TYPE_TEXTURE || this.type == CONSTANTS.OP.OP_PORT_TYPE_ARRAY)
        {
            if (this._animated)
            {
                this.anim.setValue(this._op.patch.timer.getTime(), v);
            }
            else
            {
                try
                {
                    this.value = v;
                    this.forceChange();
                }
                catch (ex)
                {
                    this.crashed = true;

                    this.setValue = function (_v) {};
                    this.onTriggered = function () {};

                    this._log.error("exception in ", this._op);
                    this._log.error(ex);

                    this._op.patch.emitEvent("exception", ex, this._op);
                }

                if (this._op && this._op.patch && this._op.patch.isEditorMode() && this.type == CONSTANTS.OP.OP_PORT_TYPE_TEXTURE) gui.texturePreview().updateTexturePort(this);
            }

            if (this.direction == CONSTANTS.PORT.PORT_DIR_OUT) for (let i = 0; i < this.links.length; ++i) this.links[i].setValue();
        }
    }
};

Port.prototype.updateAnim = function ()
{
    if (this._animated)
    {
        this.value = this.get();

        if (this._oldAnimVal != this.value || this.changeAlways)
        {
            this._oldAnimVal = this.value;
            this.forceChange();
        }
        this._oldAnimVal = this.value;
    }
};

Port.prototype.forceChange = function ()
{
    if (this.onValueChanged || this.onChange)
    {
        // very temporary: deprecated warning!!!!!!!!!
        // if(params.length>0) this._log.warn('TOM: port has onchange params!',this._op.objName,this.name);
    }
    this._activity();
    this.emitEvent("change", this.value, this);

    // try
    // {
    if (this.onChange) this.onChange(this, this.value);
    else if (this.onValueChanged) this.onValueChanged(this, this.value); // deprecated
    // }
    // catch (e)
    // {
    //     console.log(e);
    // }
};

/**
 * @function getTypeString
 * @memberof Port
 * @instance
 * @description get port type as string, e.g. "Function","Value"...
 * @return {String} type
 */
Port.prototype.getTypeString = function ()
{
    if (this.type == CONSTANTS.OP.OP_PORT_TYPE_VALUE) return "Number";
    if (this.type == CONSTANTS.OP.OP_PORT_TYPE_FUNCTION) return "Trigger";
    if (this.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT) return "Object";
    if (this.type == CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC) return "Dynamic";
    if (this.type == CONSTANTS.OP.OP_PORT_TYPE_ARRAY) return "Array";
    if (this.type == CONSTANTS.OP.OP_PORT_TYPE_STRING) return "String";
    return "Unknown";
};

Port.prototype.deSerializeSettings = function (objPort)
{
    if (!objPort) return;
    if (objPort.animated) this.setAnimated(objPort.animated);
    if (objPort.useVariable) this.setVariableName(objPort.useVariable);
    if (objPort.title) this.setUiAttribs({ "title": objPort.title });
    if (objPort.expose) this.setUiAttribs({ "expose": true });
    if (objPort.order) this.setUiAttribs({ "order": objPort.order });

    if (objPort.multiPortManual) this.setUiAttribs({ "multiPortManual": objPort.multiPortManual });
    if (objPort.multiPortNum) this.setUiAttribs({ "multiPortNum": objPort.multiPortNum });

    if (objPort.anim)
    {
        if (!this.anim) this.anim = new Anim({ "name": "port " + this.name });
        this._op._hasAnimPort = true;
        this.anim.addEventListener("onChange", () =>
        {
            this._op.patch.emitEvent("portAnimUpdated", this._op, this, this.anim);
        });
        if (objPort.anim.loop) this.anim.loop = objPort.anim.loop;
        for (const ani in objPort.anim.keys)
        {
            this.anim.keys.push(new ANIM.Key(objPort.anim.keys[ani]));
        }
        this.anim.sortKeys();
    }
};


Port.prototype.setInitialValue = function (v)
{
    if (this.op.preservedPortLinks[this.name])
    {
        for (let i = 0; i < this.op.preservedPortLinks[this.name].length; i++)
        {
            const lobj = this.op.preservedPortLinks[this.name][i];
            this.op.patch._addLink(
                lobj.objIn,
                lobj.objOut,
                lobj.portIn,
                lobj.portOut);
        }
    }


    if (this.op.preservedPortValues && this.op.preservedPortValues.hasOwnProperty(this.name) && this.op.preservedPortValues[this.name] !== undefined)
    {
        this.set(this.op.preservedPortValues[this.name]);
    }
    else
    if (v !== undefined) this.set(v);
    if (v !== undefined) this.defaultValue = v;
};




Port.prototype.getSerialized = function ()
{
    let obj = { "name": this.getName() };


    if (!this.ignoreValueSerialize && this.links.length === 0)
    {
        if (this.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT && this.value && this.value.tex) {}
        else obj.value = this.value;
    }
    if (this._useVariableName) obj.useVariable = this._useVariableName;
    if (this._animated) obj.animated = true;
    if (this.anim) obj.anim = this.anim.getSerialized();
    if (this.uiAttribs.multiPortNum) obj.multiPortNum = this.uiAttribs.multiPortNum;
    if (this.uiAttribs.multiPortManual) obj.multiPortManual = this.uiAttribs.multiPortManual;

    if (this.uiAttribs.display == "file") obj.display = this.uiAttribs.display;
    if (this.uiAttribs.expose)
    {
        obj.expose = true;
        if (this.uiAttribs.hasOwnProperty("order")) obj.order = this.uiAttribs.order;
    }
    if (this.uiAttribs.title) obj.title = this.uiAttribs.title;
    if ((this.preserveLinks || this.direction == CONSTANTS.PORT.PORT_DIR_OUT) && this.links.length > 0)
    {
        obj.links = [];
        for (const i in this.links)
        {
            if (!this.links[i].ignoreInSerialize && (this.links[i].portIn && this.links[i].portOut)) obj.links.push(this.links[i].getSerialized());
        }
    }

    if (this.direction == CONSTANTS.PORT.PORT_DIR_IN && this.links.length > 0)
    {
        for (const i in this.links)
        {
            if (!this.links[i].portIn || !this.links[i].portOut) continue;

            const otherp = this.links[i].getOtherPort(this);
            // check if functions exist, are defined in core_extend_ops code in ui
            if (otherp.op.isInBlueprint2 && this.op.isInBlueprint2)
            {
                if (otherp.op.isInBlueprint2() && !this.op.isInBlueprint2())
                {
                    obj.links = obj.links || [];
                    obj.links.push(this.links[i].getSerialized());
                }
            }
        }
    }

    if (obj.links && obj.links.length == 0) delete obj.links;
    if (this.type === CONSTANTS.OP.OP_PORT_TYPE_FUNCTION) delete obj.value;
    if (this.type === CONSTANTS.OP.OP_PORT_TYPE_FUNCTION && this.links.length == 0) obj = null;
    if (obj && Object.keys(obj).length == 1 && obj.name)obj = null; // obj is null if there is no real information other than name

    // console.log(obj);
    cleanJson(obj);

    return obj;
};

Port.prototype.shouldLink = function ()
{
    return true;
};

/**
 * @function removeLinks
 * @memberof Port
 * @instance
 * @description remove all links from port
 */
Port.prototype.removeLinks = function ()
{
    let count = 0;
    while (this.links.length > 0)
    {
        count++;
        if (count > 5000)
        {
            this._log.warn("could not delete links... / infinite loop");
            this.links.length = 0;
            break;
        }
        this.links[0].remove();
    }
};

/**
 * @function removeLink
 * @memberof Port
 * @instance
 * @description remove all link from port
 * @param {CABLES.Link} link
 */
Port.prototype.removeLink = function (link)
{
    for (const i in this.links)
        if (this.links[i] == link)
            this.links.splice(i, 1);

    if (this.direction == CONSTANTS.PORT.PORT_DIR_IN)
    {
        if (this.type == CONSTANTS.OP.OP_PORT_TYPE_VALUE) this.setValue(this._valueBeforeLink || 0);
        else this.setValue(this._valueBeforeLink || null);
    }

    if (CABLES.UI && this._op.checkLinkTimeWarnings) this._op.checkLinkTimeWarnings();

    try
    {
        if (this.onLinkChanged) this.onLinkChanged();
        this.emitEvent("onLinkChanged");
        this.emitEvent("onLinkRemoved");
        this._op.emitEvent("onLinkChanged");
    }
    catch (e)
    {
        this._log.error(e);
    }
};

/**
 * @function getName
 * @memberof Port
 * @instance
 * @description return port name
 */
Port.prototype.getName = function ()
{
    return this.name;
};

/**
 * @function getTitle
 * @memberof Port
 * @instance
 * @description return port name or title
 */
Port.prototype.getTitle = function ()
{
    if (this.uiAttribs.title) return this.uiAttribs.title;
    return this.name;
};

Port.prototype.addLink = function (l)
{
    this._valueBeforeLink = this.value;
    this.links.push(l);
    if (CABLES.UI && this._op.checkLinkTimeWarnings) this._op.checkLinkTimeWarnings();

    try
    {
        if (this.onLinkChanged) this.onLinkChanged();
        this.emitEvent("onLinkChanged");
        this._op.emitEvent("onLinkChanged");
    }
    catch (e)
    {
        this._log.error(e);
    }
};

/**
 * @function getLinkTo
 * @memberof Port
 * @instance
 * @param {Port} p2 otherPort
 * @description return link, which is linked to otherPort
 */
Port.prototype.getLinkTo = function (p2)
{
    for (const i in this.links) if (this.links[i].portIn == p2 || this.links[i].portOut == p2) return this.links[i];
};

/**
 * @function removeLinkTo
 * @memberof Port
 * @instance
 * @param {Port} p2 otherPort
 * @description removes link, which is linked to otherPort
 */
Port.prototype.removeLinkTo = function (p2)
{
    for (const i in this.links)
    {
        if (this.links[i].portIn == p2 || this.links[i].portOut == p2)
        {
            this.links[i].remove();
            if (CABLES.UI && this._op.checkLinkTimeWarnings) this._op.checkLinkTimeWarnings();

            if (this.onLinkChanged) this.onLinkChanged();
            this.emitEvent("onLinkChanged");
            this.emitEvent("onLinkRemoved");
            return;
        }
    }
};

/**
 * @function isLinkedTo
 * @memberof Port
 * @instance
 * @param {Port} p2 otherPort
 * @description returns true if port is linked to otherPort
 */
Port.prototype.isLinkedTo = function (p2)
{
    for (const i in this.links) if (this.links[i].portIn == p2 || this.links[i].portOut == p2) return true;

    return false;
};

Port.prototype._activity = function ()
{
    this.activityCounter++;
};

/**
 * @function trigger
 * @memberof Port
 * @instance
 * @description trigger the linked port (usually invoked on an output function port)
 */
Port.prototype.trigger = function ()
{
    const linksLength = this.links.length;

    this._activity();
    if (linksLength === 0) return;
    if (!this._op.enabled) return;

    let portTriggered = null;
    try
    {
        for (let i = 0; i < linksLength; ++i)
        {
            if (this.links[i].portIn)
            {
                portTriggered = this.links[i].portIn;

                portTriggered.op.patch.pushTriggerStack(portTriggered);
                portTriggered._onTriggered();

                portTriggered.op.patch.popTriggerStack();
            }
            if (this.links[i]) this.links[i].activity();
        }
    }
    catch (ex)
    {
        portTriggered.op.enabled = false;

        if (this._op.patch.isEditorMode())
        {
            // this._op.patch.emitEvent("exception", ex, portTriggered.op);
            // this._op.patch.emitEvent("opcrash", portTriggered);
            // console.log("crash", portTriggered.op.objName);

            if (portTriggered.op.onError) portTriggered.op.onError(ex);
        }
        this._log.error("exception in port: ", portTriggered.name, portTriggered.op.name, portTriggered.op);
        this._log.error(ex);
    }
};

Port.prototype.call = function ()
{
    this._log.warn("call deprecated - use trigger() ");
    this.trigger();
};

Port.prototype.execute = function ()
{
    this._log.warn("### execute port: " + this.getName(), this.goals.length);
};

Port.prototype.setVariableName = function (n)
{
    this._useVariableName = n;


    this._op.patch.on("variableRename", (oldname, newname) =>
    {
        if (oldname != this._useVariableName) return;
        this._useVariableName = newname;
    });
};

Port.prototype.getVariableName = function ()
{
    return this._useVariableName;
};

Port.prototype.setVariable = function (v)
{
    this.setAnimated(false);
    const attr = { "useVariable": false };

    if (this._variableIn && this._varChangeListenerId)
    {
        this._variableIn.off(this._varChangeListenerId);
        this._variableIn = null;
    }

    if (v)
    {
        this._variableIn = this._op.patch.getVar(v);

        if (!this._variableIn)
        {
            this._log.warn("PORT VAR NOT FOUND!!!", v);
        }
        else
        {
            if (this.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT)
            {
                this._varChangeListenerId = this._variableIn.on("change", () => { this.set(null); this.set(this._variableIn.getValue()); });
            }
            else
            {
                this._varChangeListenerId = this._variableIn.on("change", this.set.bind(this));
            }
            this.set(this._variableIn.getValue());
        }
        this._useVariableName = v;
        attr.useVariable = true;
        attr.variableName = this._useVariableName;
    }
    else
    {
        attr.variableName = this._useVariableName = null;
        attr.useVariable = false;
    }

    this.setUiAttribs(attr);
    this._op.patch.emitEvent("portSetVariable", this._op, this, v);
};

Port.prototype._handleNoTriggerOpAnimUpdates = function (a)
{
    let hasTriggerPort = false;
    for (let i = 0; i < this._op.portsIn.length; i++)
    {
        if (this._op.portsIn.type == CONSTANTS.OP.OP_PORT_TYPE_FUNCTION)
        {
            hasTriggerPort = true;
            break;
        }
    }

    if (!hasTriggerPort)
    {
        if (a) this._notriggerAnimUpdate = this._op.patch.on("onRenderFrame",
            () =>
            {
                this.updateAnim();
            });
        else this._op.patch.removeEventListener(this._notriggerAnimUpdate);
    }
};

Port.prototype.setAnimated = function (a)
{
    if (this._animated != a)
    {
        this._animated = a;
        this._op._hasAnimPort = true;

        if (this._animated && !this.anim)
        {
            this.anim = new Anim({ "name": "port " + this.name });
            this.anim.addEventListener("onChange", () =>
            {
                this._op.patch.emitEvent("portAnimUpdated", this._op, this, this.anim);
            });
        }
        this._onAnimToggle();
    }

    this._handleNoTriggerOpAnimUpdates(a);
    if (!a)
    {
        this.anim = null;
    }

    this.setUiAttribs({ "isAnimated": this._animated });
};

Port.prototype.toggleAnim = function ()
{
    this._animated = !this._animated;
    if (this._animated && !this.anim)
    {
        this.anim = new Anim({ "name": "port " + this.name });
        this.anim.addEventListener("onChange", () =>
        {
            this._op.patch.emitEvent("portAnimUpdated", this._op, this, this.anim);
        });
    }
    this.setAnimated(this._animated);
    this._onAnimToggle();
    this.setUiAttribs({ "isAnimated": this._animated });
};

/**
 * <pre>
 * CABLES.CONSTANTS.OP.OP_PORT_TYPE_VALUE = 0;
 * CABLES.CONSTANTS.OP.OP_PORT_TYPE_FUNCTION = 1;
 * CABLES.CONSTANTS.OP.OP_PORT_TYPE_OBJECT = 2;
 * CABLES.CONSTANTS.OP.OP_PORT_TYPE_TEXTURE = 2;
 * CABLES.CONSTANTS.OP.OP_PORT_TYPE_ARRAY = 3;
 * CABLES.CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC = 4;
 * CABLES.CONSTANTS.OP.OP_PORT_TYPE_STRING = 5;
 * </pre>
 * @function getType
 * @memberof Port
 * @instance
 * @return {Number} type of port
 */
Port.prototype.getType = function ()
{
    return this.type;
};

/**
 * @function isLinked
 * @memberof Port
 * @instance
 * @return {Boolean} true if port is linked
 */
Port.prototype.isLinked = function ()
{
    return this.links.length > 0 || this._animated || this._useVariableName != null;
};

Port.prototype.isBoundToVar = function ()
{
    const b = this._useVariableName != null;
    this.uiAttribs.boundToVar = b;
    return b;
};
/**
 * @function isAnimated
 * @memberof Port
 * @instance
 * @return {Boolean} true if port is animated
 */
Port.prototype.isAnimated = function ()
{
    return this._animated;
};

/**
 * @function isHidden
 * @memberof Port
 * @instance
 * @return {Boolean} true if port is hidden
 */
Port.prototype.isHidden = function ()
{
    return this.uiAttribs.hidePort;
};

/**
 * @function onTriggered
 * @memberof Port
 * @instance
 * @param {function} a onTriggeredCallback
 * @description set callback, which will be executed when port was triggered (usually output port)
 */
Port.prototype._onTriggered = function (a)
{
    this._activity();
    this._op.updateAnims();
    if (this._op.enabled && this.onTriggered) this.onTriggered(a);

    if (this._op.enabled) this.emitEvent("trigger");
};

Port.prototype._onSetProfiling = function (v)
{
    this._op.patch.profiler.add("port", this);
    this.setValue(v);
    this._op.patch.profiler.add("port", null);
};

Port.prototype._onTriggeredProfiling = function ()
{
    if (this._op.enabled && this.onTriggered)
    {
        this._op.patch.profiler.add("port", this);
        this.onTriggered();
        this._op.patch.profiler.add("port", null);
    }
};



Port.prototype.getUiActiveState = function ()
{
    return this._uiActiveState;
};

Port.prototype.setUiActiveState = function (onoff)
{
    this._uiActiveState = onoff;
    if (this.onUiActiveStateChange) this.onUiActiveStateChange();
};

/**
 * @deprecated
 * @param {function} cb
 */
Port.prototype.onValueChange = function (cb)
{
    this.onChange = cb;
};

/**
 * @deprecated
 */
Port.prototype.hidePort = function () {};


/**
 * Returns the port type string, e.g. "value" based on the port type number
 * @function portTypeNumberToString
 * @instance
 * @memberof Port
 * @param {Number} type - The port type number
 * @returns {String} - The port type as string
 */
Port.portTypeNumberToString = function (type)
{
    if (type == CONSTANTS.OP.OP_PORT_TYPE_VALUE) return "value";
    if (type == CONSTANTS.OP.OP_PORT_TYPE_FUNCTION) return "function";
    if (type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT) return "object";
    if (type == CONSTANTS.OP.OP_PORT_TYPE_ARRAY) return "array";
    if (type == CONSTANTS.OP.OP_PORT_TYPE_STRING) return "string";
    if (type == CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC) return "dynamic";
    return "unknown";
};



;// CONCATENATED MODULE: ./src/core/core_port_switch.js




class SwitchPort extends Port
{
    constructor(__parent, name, type, uiAttribs, indexPort)
    {
        super(__parent, name, type, uiAttribs);

        this.get = () =>
        {
            let s = super.get();

            if (CABLES.UI)
            {
                if (
                    s === "" ||
                    s === null ||
                    s === undefined ||
                    (uiAttribs.values && uiAttribs.values.indexOf(String(s)) === -1)
                )
                {
                    this.op.setUiError("invalidswitch", "Invalid Value [" + this.name + "]: \"" + s + "\"", 1);
                }
                else this.op.setUiError("invalidswitch", null);
            }

            if (s === null || s === undefined)s = "";

            return s;
        };

        this.indexPort = indexPort;
        this.indexPort.set = (value) =>
        {
            const values = uiAttribs.values;

            if (!values)
            {
                // console.log("switch port has no values", this);
                return;
            }

            let intValue = Math.floor(value);

            intValue = Math.min(intValue, values.length - 1);
            intValue = Math.max(intValue, 0);

            this.indexPort.setValue(intValue);
            this.set(values[intValue]);

            if (this.op.patch.isEditorMode() && performance.now() - (this.lastTime || 0) > 100 && window.gui && gui.patchView.isCurrentOp(this.op))
            {
                gui.opParams.show(this.op);
                this.lastTime = performance.now();
            }
        };
    }

    setUiAttribs(attribs)
    {
        const hidePort = attribs.hidePort;
        attribs.hidePort = true;
        super.setUiAttribs(attribs);
        if (typeof hidePort !== "undefined")
        {
            this.indexPort.setUiAttribs({ hidePort });
        }
    }
}



;// CONCATENATED MODULE: ./src/core/core_port_select.js




class ValueSelectPort extends SwitchPort
{
    setUiAttribs(newAttribs)
    {
        // never unhide valuePort when indexPort is linked
        if (this.indexPort.isLinked())
        {
            for (const p in newAttribs)
            {
                if (p == "greyout" && !newAttribs[p]) newAttribs[p] = "true";
            }
        }
        super.setUiAttribs(newAttribs);
    }
}





;// CONCATENATED MODULE: ./src/core/core_port_multi.js



const MIN_NUM_PORTS = 2;

class MultiPort extends Port
{
    constructor(__parent, name, type, dir, uiAttribs, uiAttribsPorts)
    {
        super(__parent, name, CONSTANTS.OP.OP_PORT_TYPE_ARRAY, uiAttribs);

        this.setUiAttribs({ "multiPort": true, "group": this.name, "order": -1 });
        this.ports = [];
        this.direction = dir;
        this._uiAttribsPorts = uiAttribsPorts;

        // console.log("uiattribs", uiAttribs);

        const updateArray = () =>
        {
            const arr = [];

            let ll = 1;
            if (this.uiAttribs.multiPortManual)ll = 0;

            for (let i = 0; i < this.ports.length - ll; i++)
                arr[i] = this.ports[i];

            this.setRef(arr);
        };

        const updateUi = () =>
        {
            let grey = !this.uiAttribs.multiPortManual || undefined;

            if (this.direction == CONSTANTS.PORT.PORT_DIR_OUT)grey = false;

            for (let i = 0; i < this.ports.length; i++)
            {
                let lp; // undefined to remove/not set it
                // let opacity;// undefined to remove/not set it
                // let grey;// undefined to remove/not set it
                let addPort = false;
                let title;
                let o = {};


                // console.log("this.op.preservedPortTitles", this.op.preservedPortTitles, this.op.preservedPortTitles[po.name], po.name);
                if (this.op.preservedPortTitles && this.op.preservedPortTitles[this.ports[i].name]) title = this.op.preservedPortTitles[this.ports[i].name];


                // if (!this.uiAttribs.multiPortManual)grey = true;
                if (i == 0) lp = this.ports.length;

                if (!this.uiAttribs.multiPortManual)
                    if (i == this.ports.length - 1)
                    {
                        title = "add port";
                        addPort = true;
                        grey = true;
                    }

                for (const attin in this._uiAttribsPorts)
                {
                    o[attin] = this._uiAttribsPorts[attin];
                }

                o.addPort = addPort;
                o.longPort = lp;
                o.title = title;
                o.greyout = grey;
                o.group = this.name;

                this.ports[i].setUiAttribs(o);
            }
        };

        this.removeInvalidPorts = () =>
        {
            for (let i = 0; i < this.ports.length; i++)
            {
                if (!this.ports[i]) this.ports.splice(i, 1);
            }

            if (!this.uiAttribs.multiPortManual)
            {
                if (this.ports.length > MIN_NUM_PORTS)

                    for (let i = this.ports.length - 1; i > 1; i--)
                    {
                        if (!this.ports[i].isLinked()) this.uiAttribs.multiPortNum = i;
                        else break;
                    }
            }

            updateArray();
        };

        this.countPorts = () =>
        {
            if (CABLES.UI && !gui.isRemoteClient && gui.patchView && gui.patchView.patchRenderer && gui.patchView.patchRenderer.isDraggingPort())
            {
                clearTimeout(this.retryTo);
                this.retryTo = setTimeout(this.countPorts.bind(this));
                return;
            }
            this.retryTo = null;

            let redo = false;
            this.removeListeners();
            this.removeInvalidPorts();

            for (let i = 0; i < this.ports.length; i++)
            {
                if (this.ports[i] && this.ports[i].links.length > 1)
                {
                    const po = this.ports[i + 1];
                    const otherPort = this.ports[i].links[0].getOtherPort(this.ports[i]);

                    if (!po || !otherPort)
                    {
                        this._log.warn("no port found?");
                    }
                    else
                    {
                        this.ports[i].links[0].remove();
                        this.op.patch.link(this.op, po.name, otherPort.op, otherPort.name);
                        redo = true;
                    }
                    break;
                }
            }

            if (!this.uiAttribs.multiPortManual)
            {
                let foundHole = true;
                while (foundHole)
                {
                    // console.log("search holes...");
                    foundHole = false;

                    for (let i = this.ports.length - 1; i > 1; i--)
                    {
                        if (this.ports[i] && this.ports[i].links.length > 0 && this.ports[i - 1].links.length == 0)
                        {
                            // console.log("found hole!");

                            // found hole
                            const otherPort = this.ports[i].links[0].getOtherPort(this.ports[i]);
                            this.ports[i].links[0].remove();

                            const po = this.ports[i - 1];

                            if (po && this.ports[i])
                            {
                                // console.log("move ", this.ports[i].name, "to", po.name);
                                this.op.patch.link(this.op, po.name, otherPort.op, otherPort.name);
                                foundHole = true;
                                redo = true;
                                break;
                            }
                        }
                    }


                    // this.checkNum();
                }

                // this.removeInvalidPorts();
            }


            if (!this.uiAttribs.multiPortManual) // if auto
            {
                while (this.ports.length > MIN_NUM_PORTS && !this.ports[this.ports.length - 1].isLinked() && !this.ports[this.ports.length - 2].isLinked())
                {
                    let i = this.ports.length - 1;
                    if (!this.ports[i].isLinked() && this.ports[i - 1] && !this.ports[i - 1].isLinked())
                    {
                        this.ports[i].setUiAttribs({ "removed": true });
                        this.ports[i].remove();
                        // this.ports[i] = null;
                        this.ports.splice(i, 1);
                    }
                }
            }

            this.removeInvalidPorts();

            if (!this.uiAttribs.multiPortManual && this.ports.length > 0 && this.ports[this.ports.length - 1].isLinked()) this.newPort();

            updateArray();
            updateUi();

            if (redo) this.countPorts();
            else this.addListeners();
        };

        this.removeListeners = () =>
        {
            for (let i = 0; i < this.ports.length; i++)
            {
                const po = this.ports[i];
                po.multiPortChangeListener = po.off(po.multiPortChangeListener);
                po.multiLinkChangeListener = po.off(po.multiLinkChangeListener);
            }
        };

        this.addListeners = () =>
        {
            for (let i = 0; i < this.ports.length; i++)
            {
                const po = this.ports[i];
                const idx = i;

                if (po.multiPortChangeListener)po.multiPortChangeListener = po.off(po.multiPortChangeListener);
                po.multiPortChangeListener = po.on("change", updateArray.bind(this));


                if (po.multiPortTriggerListener)po.multiPortTriggerListener = po.off(po.multiPortTriggerListener);
                po.multiPortTriggerListener = po.on("trigger", () => { this._onTriggered(idx); });


                // if (po.multiPortTriggerListener)po.multiPortTriggerListener = po.off(po.multiPortTriggerListener);
                // po.multiPortTriggerListener = po.on("trigger", this.trigger());

                if (po.multiLinkChangeListener)po.multiLinkChangeListener = po.off(po.multiLinkChangeListener);
                po.multiLinkChangeListener = po.on("onLinkChanged", () =>
                {
                    this.countPorts();
                    this.emitEvent("onLinkChanged");
                });

                if (po.multiLinkRemoveListener)po.multiLinkRemoveListener = po.off(po.multiLinkRemoveListener);
                po.multiLinkRemoveListener = po.on("onLinkRemoved", () =>
                {
                    // this.removeInvalidPorts();
                    // this.checkNum();
                    // this.countPorts();
                    updateUi();
                    this.emitEvent("onLinkChanged");
                    // this.countPorts.bind(this);
                });
            }
        };

        this.newPort = () =>
        {
            const attrs = {};
            // if (type == CABLES.OP_PORT_TYPE_STRING) attrs.type = "string";
            attrs.type = type;
            const po = new Port(this.op, name + "_" + this.ports.length, type, attrs);

            po.direction = dir;
            this.ports.push(po);
            // console.log("CONSTANTS.PORT_DIR_OUT", CONSTANTS.PORT.PORT_DIR_OUT, this.direction);
            if (this.direction == CONSTANTS.PORT.PORT_DIR_OUT) this.op.addOutPort(po);
            else this.op.addInPort(po);

            if (type == CONSTANTS.OP.OP_PORT_TYPE_NUMBER) po.setInitialValue(0);
            else if (type == CONSTANTS.OP.OP_PORT_TYPE_STRING) po.setInitialValue("");

            this.addListeners();

            updateUi();
            updateArray();
            this.emitEvent("onLinkChanged");
            // console.log("this.op.preservedPortTitles", this.op.preservedPortTitles, this.op.preservedPortTitles[po.name], po.name);
            if (this.op.preservedPortTitles && this.op.preservedPortTitles[po.name]) po.setUiAttribs({ "title": this.op.preservedPortTitles[po.name] });

            return po;
        };

        this.initPorts = () =>
        {
            for (let i = 0; i < MIN_NUM_PORTS; i++) this.newPort();
            updateArray();
            updateUi();
        };

        this.checkNum = () =>
        {
            this.uiAttribs.multiPortNum = Math.max(MIN_NUM_PORTS, this.uiAttribs.multiPortNum);

            while (this.ports.length < this.uiAttribs.multiPortNum) this.newPort();
            while (this.ports.length > this.uiAttribs.multiPortNum) if (this.ports[this.ports.length - 1]) this.ports.pop().remove();

            this.removeInvalidPorts();
        };

        this.incDec = (incDir) =>
        {
            this.uiAttribs.multiPortNum = this.uiAttribs.multiPortNum || MIN_NUM_PORTS;
            // console.log("this.uiAttribs.multiPortNum", this.uiAttribs.multiPortNum, this.uiAttribs.multiPortNum + incDir);
            this.setUiAttribs({ "multiPortNum": this.uiAttribs.multiPortNum + incDir });
            this.checkNum();

            updateUi();
        };

        this.toggleManual = () =>
        {
            this.setUiAttribs({ "multiPortManual": !this.uiAttribs.multiPortManual });
            this.op.refreshParams();
        };

        this.on("onUiAttrChange", (attribs) =>
        {
            if (attribs.hasOwnProperty("multiPortManual"))
            {
                updateUi();
                this.removeInvalidPorts();
                this.checkNum();
                this.countPorts();
                updateUi();
            }
        });


        this.on("onUiAttrChange", this.checkNum.bind(this));
        this.checkNum();
        this.countPorts();
        this.removeInvalidPorts();
        updateUi();
    }
}





;// CONCATENATED MODULE: ./src/core/core_op.js









/**
 * op the class of all operators
 * @namespace external:CABLES#Op
 * @hideconstructor
 */

/**
 * @type {Object}
 * @name attachments
 * @instance
 * @memberof Op
 * @description access file attachments as String values
 * @example
 * // set shader source to attached files (files are called shader.vert / shader.frag)
 * shader.setSource(attachments.shader_vert,attachments.shader_frag);
 */

const Ops = {};

const Op = function ()
{
    EventTarget.apply(this);

    this._log = new Logger("core_op");
    this.data = {}; // UNUSED, DEPRECATED, only left in for backwards compatibility with userops
    this.storage = {}; // op-specific data to be included in export
    this.__objName = "";
    this.portsOut = [];
    this.portsIn = [];
    this.portsInData = []; // original loaded patch data
    this.opId = ""; // unique op id
    this.uiAttribs = {};
    this.enabled = true;
    this.patch = arguments[0];
    this._name = arguments[1];
    this.preservedPortTitles = {};
    this.preservedPortValues = {};
    this.preservedPortLinks = {};

    this._linkTimeRules = {
        "needsLinkedToWork": [],
        "needsParentOp": null
    };

    this.shouldWork = {};
    this.hasUiErrors = false;
    this._uiErrors = {};
    this._hasAnimPort = false;

    if (arguments[1])
    {
        this._shortOpName = CABLES.getShortOpName(arguments[1]);
        this.getTitle();
    }

    this.id = arguments[2] || shortId(); // instance id
    this.onAddPort = null;
    this.onCreate = null;
    this.onResize = null;
    this.onLoaded = null;
    this.onDelete = null;
    this.onError = null;

    this._instances = null;

    /**
     * overwrite this to prerender shader and meshes / will be called by op `loadingStatus`
     * @function preRender
     * @memberof Op
     * @instance
     */
    this.preRender = null;

    /**
     * overwrite this to initialize your op
     * @function init
     * @memberof Op
     * @instance
     */
    this.init = null;

    Object.defineProperty(this, "name", {
        get() { return this.getTitle(); },
        set(v)
        {
            this.setTitle(v);
        }
    });

    Object.defineProperty(this, "_objName", { set(on)
    {
        this.__objName = on; this._log = new Logger("op " + on);
    } });

    Object.defineProperty(this, "objName", { get() { return this.__objName; } });
    Object.defineProperty(this, "shortName", { get() { return this._shortOpName; } });

    if (this.initUi) this.initUi();
};

{
    Op.prototype.clearUiAttrib = function (name)
    {
        const obj = {};
        // obj.name = null;
        this.uiAttrib(obj);
    };

    Op.prototype.require = function (name)
    {
        if (CABLES.platform && CABLES.StandaloneElectron && !CABLES.platform.frontendOptions.isStandalone)
            this.setUiError("notstandalone", "This op will only work in cables standalone version", 3);

        return null;
    };


    Op.prototype.checkMainloopExists = function ()
    {
        if (!CABLES.UI) return;
        if (!this.patch.tempData.mainloopOp) this.setUiError("nomainloop", "patch should have a mainloop to use this op");
        else this.setUiError("nomainloop", null);
    };

    Op.prototype.getTitle = function ()
    {
        if (!this.uiAttribs) return "nouiattribs" + this._name;

        // if ((this.uiAttribs.title === undefined || this.uiAttribs.title === "") && this.objName.indexOf("Ops.Ui.") == -1)
        //     this.uiAttribs.title = this._shortOpName;

        return this.uiAttribs.title || this._shortOpName;
    };

    Op.prototype.setTitle = function (title)
    {
        // this._log.log("settitle", title);
        // this._log.log(
        //     (new Error()).stack
        // );

        if (title != this.getTitle()) this.uiAttr({ "title": title });
    };

    Op.prototype.setStorage = function (newAttribs)
    {
        if (!newAttribs) return;
        this.storage = this.storage || {};

        let changed = false;
        for (const p in newAttribs)
        {
            if (this.storage[p] != newAttribs[p]) changed = true;
            this.storage[p] = newAttribs[p];
        }

        if (changed) this.emitEvent("onStorageChange", newAttribs);
    };

    Op.prototype.isSubPatchOp = function ()
    {
        if (this.patchId && this.storage) return (this.storage.subPatchVer || this.storage.blueprintVer || 0);
        return false;
    };

    const _setUiAttrib = function (newAttribs)
    {
        if (!newAttribs) return;

        if (newAttribs.error || newAttribs.warning || newAttribs.hint)
        {
            this._log.warn("old ui error/warning attribute in " + this._name + ", use op.setUiError !", newAttribs);
        }


        if (typeof newAttribs != "object") this._log.error("op.uiAttrib attribs are not of type object");
        if (!this.uiAttribs) this.uiAttribs = {};

        let changed = false;
        let emitMove = false;
        if (
            CABLES.UI &&
            newAttribs.hasOwnProperty("translate") &&
            (
                !this.uiAttribs.translate ||
                this.uiAttribs.translate.x != newAttribs.translate.x ||
                this.uiAttribs.translate.y != newAttribs.translate.y
            )) emitMove = true;


        if (newAttribs.hasOwnProperty("title") && newAttribs.title != this.uiAttribs.title)
        {
            // const doEmitEvent = newAttribs.title != this.getTitle();
            this.uiAttribs.title = newAttribs.title;
            // if (doEmitEvent) this.emitEvent("onTitleChange", newAttribs.title);
            changed = true;
            // this.setTitle(newAttribs.title);
        }

        if (newAttribs.hasOwnProperty("disabled")) this.setEnabled(!newAttribs.disabled);

        for (const p in newAttribs)
        {
            if (this.uiAttribs[p] != newAttribs[p]) changed = true;
            this.uiAttribs[p] = newAttribs[p];
        }


        if (this.uiAttribs.hasOwnProperty("selected") && this.uiAttribs.selected == false) delete this.uiAttribs.selected;


        if (changed)
        {
            this.emitEvent("onUiAttribsChange", newAttribs);
            this.patch.emitEvent("onUiAttribsChange", this, newAttribs);
        }


        if (emitMove) this.emitEvent("move");
    };
    /**
     * setUiAttrib
     * possible values:
     * <pre>
     * warning - warning message - showing up in op parameter panel
     * error - error message - showing up in op parameter panel
     * extendTitle - op title extension, e.g. [ + ]
     * </pre>
     * @function setUiAttrib
     * @param {Object} newAttribs, e.g. {"attrib":value}
     * @memberof Op
     * @instance
     * @example
     * op.setUiAttrib({"extendTitle":str});
     */
    Op.prototype.setUiAttribs = Op.prototype.setUiAttrib = Op.prototype.uiAttr = _setUiAttrib;

    Op.prototype.getName = function ()
    {
        if (this.uiAttribs.name) return this.uiAttribs.name;
        return this._name;
    };

    Op.prototype.addOutPort = function (p)
    {
        p.direction = CONSTANTS.PORT.PORT_DIR_OUT;
        p._op = this;
        this.portsOut.push(p);
        this.emitEvent("onPortAdd", p);
        return p;
    };

    Op.prototype.hasDynamicPort = function ()
    {
        let i = 0;
        for (i = 0; i < this.portsIn.length; i++)
        {
            if (this.portsIn[i].type == CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC) return true;
            if (this.portsIn[i].getName() == "dyn") return true;
        }
        for (i = 0; i < this.portsOut.length; i++)
        {
            if (this.portsOut[i].type == CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC) return true;
            if (this.portsOut[i].getName() == "dyn") return true;
        }

        return false;
    };

    Op.prototype.addInPort = function (p)
    {
        if (!(p instanceof Port)) throw new Error("parameter is not a port!");

        p.direction = CONSTANTS.PORT.PORT_DIR_IN;
        p._op = this;

        this.portsIn.push(p);
        this.emitEvent("onPortAdd", p);

        return p;
    };

    /**
     * create a trigger input port
     * @function inTrigger
     * @instance
     * @memberof Op
     * @param {String} name
     * @return {Port} created port
     *
     */
    Op.prototype.inFunction = Op.prototype.inTrigger = function (name, v)
    {
        const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_FUNCTION));
        if (v !== undefined) p.set(v);
        return p;
    };

    /**
     * create multiple UI trigger buttons
     * @function inTriggerButton
     * @memberof Op
     * @instance
     * @param {String} name
     * @param {Array} names
     * @return {Port} created port
     */
    Op.prototype.inFunctionButton = Op.prototype.inTriggerButton = function (name, v)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_FUNCTION, {
                "display": "button"
            })
        );
        if (v !== undefined) p.set(v);
        return p;
    };

    Op.prototype.inFunctionButton = Op.prototype.inUiTriggerButtons = function (name, v)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_FUNCTION, {
                "display": "buttons"
            })
        );
        if (v !== undefined) p.set(v);
        return p;
    };



    /**
     * create a number value input port
     * @function inFloat
     * @memberof Op
     * @instance
     * @param {String} name
     * @param {Number} value
     * @return {Port} created port
     */
    Op.prototype.inValueFloat = Op.prototype.inValue = Op.prototype.inFloat = function (name, v)
    {
        const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE));

        p.setInitialValue(v);

        return p;
    };

    /**
     * create a boolean input port, displayed as a checkbox
     * @function inBool
     * @instance
     * @memberof Op
     * @param {String} name
     * @param {Boolean} value
     * @return {Port} created port
     */
    Op.prototype.inValueBool = Op.prototype.inBool = function (name, v)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_NUMBER, {
                "display": "bool"
            })
        );

        if (v === true)v = 1;
        if (v === false)v = 0;
        p.setInitialValue(v);

        return p;
    };


    Op.prototype.inMultiPort = function (name, type)
    {
        const p = new MultiPort(
            this,
            name,
            type,
            CONSTANTS.PORT.PORT_DIR_IN,
            {
                "addPort": true,
                "hidePort": true
            }
        );
        p.ignoreValueSerialize = true;

        this.addInPort(p);
        p.initPorts();

        return p;
    };

    Op.prototype.outMultiPort = function (name, type, uiAttribsPort = {})
    {
        const p = new MultiPort(
            this,
            name,
            type,
            CONSTANTS.PORT.PORT_DIR_OUT,
            {
                "display": "multiport",
                "hidePort": true
            },
            uiAttribsPort
        );
        p.ignoreValueSerialize = true;

        this.addOutPort(p);
        p.initPorts();

        return p;
    };



    Op.prototype.inValueString = function (name, v)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
                "type": "string"
            })
        );
        p.value = "";

        p.setInitialValue(v);
        return p;
    };

    /**
     * create a String value input port
     * @function inString
     * @instance
     * @memberof Op
     * @param {String} name
     * @param {String} value default value
     * @return {Port} created port
     */
    Op.prototype.inString = function (name, v)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
                "type": "string"
            })
        );
        v = v || "";
        // p.value = v;

        p.setInitialValue(v);
        return p;
    };

    /**
     * create a String value input port displayed as TextArea
     * @function inValueText
     * @instance
     * @memberof Op
     * @param {String} name
     * @param {String} value default value
     * @return {Port} created port
     */
    Op.prototype.inValueText = function (name, v)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
                "type": "string",
                "display": "text"
            })
        );
        p.value = "";

        p.setInitialValue(v);
        // if (v !== undefined)
        // {
        //     p.set(v);
        //     p.defaultValue = v;
        // }
        return p;
    };

    Op.prototype.inTextarea = function (name, v)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
                "type": "string",
                "display": "text"
            })
        );
        p.value = "";
        if (v !== undefined)
        {
            p.set(v);
            p.defaultValue = v;
        }
        return p;
    };

    /**
     * create a String value input port displayed as editor
     * @function inStringEditor
     * @instance
     * @memberof Op
     * @param {String} name
     * @param {String} value default value
     * @return {Port} created port
     */
    // new string
    Op.prototype.inStringEditor = function (name, v, syntax, hideFormatButton = true)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
                "type": "string",
                "display": "editor",
                "editShortcut": true,
                "editorSyntax": syntax,
                "hideFormatButton": hideFormatButton
            }));

        p.value = "";
        if (v !== undefined)
        {
            p.set(v);
            p.defaultValue = v;
        }
        return p;
    };

    // old
    Op.prototype.inValueEditor = function (name, v, syntax, hideFormatButton = true)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_NUMBER, {
                "type": "string",
                "display": "editor",
                "editorSyntax": syntax,
                "hideFormatButton": hideFormatButton
            })
        );
        p.value = "";
        if (v !== undefined)
        {
            p.set(v);
            p.defaultValue = v;
        }
        return p;
    };

    /**
     * create a string select box
     * @function inDropDown
     * @instance
     * @memberof Op
     * @param {String} name
     * @param {Array} values
     * @param {String} value default value
     * @return {Port} created port
     */
    Op.prototype.inValueSelect = Op.prototype.inDropDown = function (name, values, v, noindex)
    {
        let p = null;
        if (!noindex)
        {
            const indexPort = new Port(this, name + " index", CONSTANTS.OP.OP_PORT_TYPE_NUMBER, {
                "increment": "integer",
                "hideParam": true
            });
            const n = this.addInPort(indexPort);

            if (values) for (let i = 0; i < values.length; i++) values[i] = String(values[i]);

            const valuePort = new ValueSelectPort(
                this,
                name,
                CONSTANTS.OP.OP_PORT_TYPE_NUMBER,
                {
                    "display": "dropdown",
                    "hidePort": true,
                    "type": "string",
                    "values": values
                },
                n
            );

            valuePort.indexPort = indexPort;

            valuePort.on("change", (val, thePort) =>
            {
                if (!thePort.indexPort.isLinked() && thePort.uiAttribs.values)
                {
                    const idx = thePort.uiAttribs.values.indexOf(val);
                    if (idx > -1) thePort.indexPort.set(idx);
                }
            });

            indexPort.onLinkChanged = function ()
            {
                valuePort.setUiAttribs({ "greyout": indexPort.isLinked() });
            };

            p = this.addInPort(valuePort);

            if (v !== undefined)
            {
                p.set(v);
                const index = values.findIndex((item) => { return item == v; });
                n.setValue(index);
                p.defaultValue = v;
                n.defaultValue = index;
            }
        }
        else
        {
            const valuePort = new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
                "display": "dropdown",
                "hidePort": true,
                "type": "string",
                values
            });

            p = this.addInPort(valuePort);
        }

        return p;
    };

    /**
     * create a string switch box
     * @function inSwitch
     * @instance
     * @memberof Op
     * @param {String} name
     * @param {Array} values
     * @param {String} value default value
     * @return {Port} created port
     */
    Op.prototype.inSwitch = function (name, values, v, noindex)
    {
        let p = null;
        if (!noindex)
        {
            if (!v)v = values[0];
            const indexPort = new Port(this, name + " index", CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
                "increment": "integer",
                "values": values,
                "hideParam": true
            });
            const n = this.addInPort(indexPort);

            if (values) for (let i = 0; i < values.length; i++) values[i] = String(values[i]);

            const switchPort = new SwitchPort(
                this,
                name,
                CONSTANTS.OP.OP_PORT_TYPE_STRING,
                {
                    "display": "switch",
                    "hidePort": true,
                    "type": "string",
                    "values": values
                },
                n
            );

            switchPort.indexPort = indexPort;

            switchPort.on("change", (val, thePort) =>
            {
                if (!thePort.indexPort.isLinked() && thePort.uiAttribs.values)
                {
                    const idx = thePort.uiAttribs.values.indexOf(val);
                    if (idx > -1) thePort.indexPort.set(idx);
                }
            });

            indexPort.onLinkChanged = function ()
            {
                switchPort.setUiAttribs({ "greyout": indexPort.isLinked() });
            };
            p = this.addInPort(switchPort);

            if (v !== undefined)
            {
                p.set(v);
                const index = values.findIndex((item) => { return item == v; });
                n.setValue(index);
                p.defaultValue = v;
                n.defaultValue = index;
            }
        }
        else
        {
            const switchPort = new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
                "display": "switch",
                "hidePort": true,
                "type": "string",
                "values": values
            });
            p = this.addInPort(switchPort);
        }

        return p;
    };

    /**
     * create a integer input port
     * @function inInt
     * @instance
     * @memberof Op
     * @param {String} name
     * @param {number} value default value
     * @return {Port} created port
     */
    Op.prototype.inValueInt = Op.prototype.inInt = function (name, v)
    {
        // old
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
                "increment": "integer"
            })
        );
        if (v !== undefined)
        {
            p.set(v);
            p.defaultValue = v;
        }
        return p;
    };

    /**
     * create a file/URL input port
     * @function inURL
     * @instance
     * @memberof Op
     * @param {String} name
     * @return {Port} created port
     */
    Op.prototype.inFile = function (name, filter, v)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
                "display": "file",
                "type": "string",
                "filter": filter
            })
        );
        if (v !== undefined)
        {
            p.set(v);
            p.defaultValue = v;
        }
        return p;
    };

    Op.prototype.inUrl = function (name, filter, v)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
                "display": "file",
                "type": "string",
                "filter": filter
            })
        );
        if (v !== undefined)
        {
            p.set(v);
            p.defaultValue = v;
        }
        return p;
    };

    /**
     * create a texture input port
     * @function inTexture
     * @instance
     * @memberof Op
     * @param {String} name
     * @return {Port} created port
     */
    Op.prototype.inTexture = function (name, v)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_OBJECT, {
                "display": "texture",
                "objType": "texture",
                "preview": true
            })
        );
        p.ignoreValueSerialize = true;
        if (v !== undefined) p.set(v);
        return p;
    };


    /**
     * create a object input port
     * @function inObject
     * @instance
     * @memberof Op
     * @param {String} name
     * @return {Port} created port
     */
    Op.prototype.inObject = function (name, v, objType)
    {
        const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_OBJECT, { "objType": objType }));
        p.ignoreValueSerialize = true;

        if (v !== undefined) p.set(v);
        return p;
    };

    Op.prototype.inGradient = function (name, v)
    {
        const p = this.addInPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
                "display": "gradient"
                // "hidePort": true
            })
        );
        if (v !== undefined) p.set(v);
        return p;
    };


    Op.prototype.getPortVisibleIndex = function (p)
    {
        let ports = this.portsIn;
        if (p.direction == CONSTANTS.PORT_DIR_OUT)ports = this.portsOut;

        let index = 0;
        for (let i = 0; i < ports.length; i++)
        {
            if (ports[i].uiAttribs.hidePort) continue;
            index++;
            if (ports[i] == p) return index;
        }
    };

    /**
     * create a array input port
     * @function inArray
     * @instance
     * @memberof Op
     * @param {String} name
     * @return {Port} created port
     */
    Op.prototype.inArray = function (name, v, stride)
    {
        if (!stride && CABLES.UTILS.isNumeric(v))stride = v;

        const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_ARRAY, { "stride": stride }));

        if (v !== undefined && (Array.isArray(v) || v == null)) p.set(v);

        // if (v !== undefined) p.set(v);
        return p;
    };

    /**
     * create a value slider input port
     * @function inFloatSlider
     * @instance
     * @memberof Op
     * @param {String} name
     * @param {number} defaultvalue
     * @param {number} min
     * @param {number} max
     * @return {Port} created port
     */
    Op.prototype.inValueSlider = Op.prototype.inFloatSlider = function (name, v, min, max)
    {
        const uiattribs = { "display": "range" };

        if (min != undefined && max != undefined)
        {
            uiattribs.min = min;
            uiattribs.max = max;
        }

        const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, uiattribs));
        if (v !== undefined)
        {
            p.set(v);
            p.defaultValue = v;
        }
        return p;
    };

    /**
     * create output trigger port
     * @function outTrigger
     * @instance
     * @memberof Op
     * @param {String} name
     * @return {Port} created port
     */
    Op.prototype.outFunction = Op.prototype.outTrigger = function (name, v)
    {
        // old
        const p = this.addOutPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_FUNCTION));
        if (v !== undefined) p.set(v);
        return p;
    };

    /**
     * create output value port
     * @function outNumber
     * @instance
     * @memberof Op
     * @param {String} name
     * @param {number} default value
     * @return {Port} created port
     */
    Op.prototype.outValue = Op.prototype.outNumber = function (name, v)
    {
        // old
        const p = this.addOutPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE));
        if (v !== undefined) p.set(v);
        return p;
    };

    /**
     * deprecated create output boolean port
     * @deprecated
     * @function outBool
     * @instance
     * @memberof Op
     * @param {String} name
     * @return {Port} created port
     */
    Op.prototype.outValueBool = Op.prototype.outBool = function (name, v)
    {
        // old: use outBoolNum
        const p = this.addOutPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
                "display": "bool"
            })
        );
        if (v !== undefined) p.set(v);
        else p.set(0);
        return p;
    };

    /**
     * create output boolean port,value will be converted to 0 or 1
     * @function outBoolNum
     * @instance
     * @memberof Op
     * @param {String} name
     * @return {Port} created port
     */
    Op.prototype.outBoolNum = function (name, v)
    {
        const p = this.addOutPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
                "display": "boolnum"
            })
        );

        p.set = function (b)
        {
            this.setValue(b ? 1 : 0);
            // this._log.log("bool set", b, this.get());
        }.bind(p);

        if (v !== undefined) p.set(v);
        else p.set(0);
        return p;
    };

    /**
     * create output string port
     * @function outString
     * @instance
     * @memberof Op
     * @param {String} name
     * @return {Port} created port
     */
    Op.prototype.outValueString = function (name, v)
    {
        const p = this.addOutPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
                "type": "string"
            })
        );
        if (v !== undefined) p.set(v);
        return p;
    };
    Op.prototype.outString = function (name, v)
    {
        const p = this.addOutPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
                "type": "string"
            })
        );
        if (v !== undefined) p.set(v);
        else p.set("");
        return p;
    };

    /**
     * create output object port
     * @function outObject
     * @instance
     * @memberof Op
     * @param {String} name
     * @return {Port} created port
     */
    Op.prototype.outObject = function (name, v, objType)
    {
        const p = this.addOutPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_OBJECT, { "objType": objType || null }));
        p.set(v || null);
        p.ignoreValueSerialize = true;
        return p;
    };

    /**
     * create output array port
     * @function outArray
     * @instance
     * @memberof Op
     * @param {String} name
     * @return {Port} created port
     */
    Op.prototype.outArray = function (name, v, stride)
    {
        if (!stride && CABLES.UTILS.isNumeric(v))stride = v;
        const p = this.addOutPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_ARRAY, { "stride": stride }));
        if (v !== undefined && (Array.isArray(v) || v == null)) p.set(v);

        p.ignoreValueSerialize = true;
        return p;
    };

    /**
     * create output texture port
     * @function outTexture
     * @instance
     * @memberof Op
     * @param {String} name
     * @return {Port} created port
     */
    Op.prototype.outTexture = function (name, v)
    {
        const p = this.addOutPort(
            new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_OBJECT, {
                "preview": true,
                "objType": "texture",
                "display": "texture"
            })
        );
        if (v !== undefined) p.setRef(v || CGL.Texture.getEmptyTexture(this.patch.cgl));

        p.ignoreValueSerialize = true;
        return p;
    };

    Op.prototype.inDynamic = function (name, filter, options, v)
    {
        const p = new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC, options);

        p.shouldLink = function (p1, p2)
        {
            if (filter && UTILS.isArray(filter))
            {
                for (let i = 0; i < filter.length; i++)
                {
                    if (p1 == this && p2.type === filter[i]) return true;
                    if (p2 == this && p1.type === filter[i]) return true;
                }
                return false; // types do not match
            }
            return true; // no filter set
        };

        this.addInPort(p);
        if (v !== undefined)
        {
            p.set(v);
            p.defaultValue = v;
        }
        return p;
    };

    Op.prototype.removeLinks = function ()
    {
        for (let i = 0; i < this.portsIn.length; i++) this.portsIn[i].removeLinks();
        for (let i = 0; i < this.portsOut.length; i++) this.portsOut[i].removeLinks();
    };

    Op.prototype.getSerialized = function ()
    {
        const opObj = {};

        if (this.opId) opObj.opId = this.opId;
        if (this.patch.storeObjNames) opObj.objName = this.objName;

        opObj.id = this.id;
        opObj.uiAttribs = JSON.parse(JSON.stringify(this.uiAttribs)) || {};

        if (this.storage && Object.keys(this.storage).length > 0) opObj.storage = JSON.parse(JSON.stringify(this.storage));
        if (this.uiAttribs.hasOwnProperty("working") && this.uiAttribs.working == true) delete this.uiAttribs.working;
        if (opObj.uiAttribs.hasOwnProperty("uierrors")) delete opObj.uiAttribs.uierrors;

        if (opObj.uiAttribs.title === "") delete opObj.uiAttribs.title;
        if (opObj.uiAttribs.color === null) delete opObj.uiAttribs.color;
        if (opObj.uiAttribs.comment === null) delete opObj.uiAttribs.comment;

        if (opObj.uiAttribs.title == this._shortOpName ||
            (this.uiAttribs.title || "").toLowerCase() == this._shortOpName.toLowerCase()) delete opObj.uiAttribs.title;

        opObj.portsIn = [];
        opObj.portsOut = [];

        for (let i = 0; i < this.portsIn.length; i++)
        {
            const s = this.portsIn[i].getSerialized();
            if (s) opObj.portsIn.push(s);
        }

        for (let i = 0; i < this.portsOut.length; i++)
        {
            const s = this.portsOut[i].getSerialized();
            if (s) opObj.portsOut.push(s);
        }

        if (opObj.portsIn.length == 0) delete opObj.portsIn;
        if (opObj.portsOut.length == 0) delete opObj.portsOut;
        cleanJson(opObj);

        return opObj;
    };

    Op.prototype.getFirstOutPortByType = function (type)
    {
        for (const ipo in this.portsOut) if (this.portsOut[ipo].type == type) return this.portsOut[ipo];
    };

    Op.prototype.getFirstInPortByType = function (type)
    {
        for (const ipo in this.portsIn) if (this.portsIn[ipo].type == type) return this.portsIn[ipo];
    };

    /**
     * return port by the name portName
     * @function getPort
     * @instance
     * @memberof Op
     * @param {String} portName
     * @return {Port}
     */
    Op.prototype.getPort = Op.prototype.getPortByName = function (name, lowerCase)
    {
        if (lowerCase)
        {
            for (let ipi = 0; ipi < this.portsIn.length; ipi++)
                if (this.portsIn[ipi].getName().toLowerCase() == name || this.portsIn[ipi].id.toLowerCase() == name)
                    return this.portsIn[ipi];

            for (let ipo = 0; ipo < this.portsOut.length; ipo++)
                if (this.portsOut[ipo].getName().toLowerCase() == name || this.portsOut[ipo].id.toLowerCase() == name)
                    return this.portsOut[ipo];
        }
        else
        {
            for (let ipi = 0; ipi < this.portsIn.length; ipi++)
                if (this.portsIn[ipi].getName() == name || this.portsIn[ipi].id == name)
                    return this.portsIn[ipi];

            for (let ipo = 0; ipo < this.portsOut.length; ipo++)
                if (this.portsOut[ipo].getName() == name || this.portsOut[ipo].id == name)
                    return this.portsOut[ipo];
        }
    };


    /**
     * return port by the name id
     * @function getPortById
     * @instance
     * @memberof Op
     * @param {String} id
     * @return {Port}
     */
    Op.prototype.getPortById = function (id)
    {
        for (let ipi = 0; ipi < this.portsIn.length; ipi++) if (this.portsIn[ipi].id == id) return this.portsIn[ipi];
        for (let ipo = 0; ipo < this.portsOut.length; ipo++) if (this.portsOut[ipo].id == id) return this.portsOut[ipo];
    };

    Op.prototype.updateAnims = function ()
    {
        if (this._hasAnimPort)
            for (let i = 0; i < this.portsIn.length; i++) this.portsIn[i].updateAnim();
    };

    Op.prototype.log = function ()
    {
        this._log.log(...arguments);
    };

    Op.prototype.error = Op.prototype.logError = function ()
    {
        // if (!this)
        // {
        //     this._log.error("no this...!!!");
        //     debugger;
        //     return;
        // }
        // const initiator = "op " + this.objName;
        // if (CABLES.UI && !CABLES.UI.logFilter.filterLog({ "initiator": initiator, "opInstId": this.id, "level": 2 }, ...arguments)) return;

        // // if (this.patch.silent) return;
        // const args = ["[op " + CABLES.getShortOpName(this.objName) + "]"];
        // args.push.apply(args, arguments);
        // Function.prototype.apply.apply(this._log.error, [console, args]);// eslint-disable-line
        // if (window.gui) window.gui.emitEvent("opLogEvent", this.objName, "error", arguments);
        this._log.error(...arguments);
    };

    Op.prototype.warn = Op.prototype.logWarn = function ()
    {
        this._log.warn(...arguments);

        // const initiator = "op " + this.objName;
        // if (CABLES.UI && !CABLES.UI.logFilter.filterLog({ "initiator": initiator, "opInstId": this.id, "level": 1 }, ...arguments)) return;

        // // if (this.patch.silent) return;
        // const args = ["[op " + CABLES.getShortOpName(this.objName) + "]"];
        // args.push.apply(args, arguments);
        // Function.prototype.apply.apply(this._log.warn, [console, args]);// eslint-disable-line
    };

    Op.prototype.verbose = Op.prototype.logVerbose = function ()
    {
        // const initiator = "op " + CABLES.getShortOpName(this.objName);
        // if (CABLES.UI && !CABLES.UI.logFilter.filterLog({ "initiator": initiator, "opInstId": this.id, "level": 0 }, ...arguments)) return;

        // if (!CABLES.UI && this.patch.silent) return;

        // const args = ["[" + initiator + "]"];
        // args.push.apply(args, arguments);
        // Function.prototype.apply.apply(this._log.info, [console, args]);// eslint-disable-line
        this._log.verbose(...arguments);
    };


    Op.prototype.profile = function (enable)
    {
        for (let ipi = 0; ipi < this.portsIn.length; ipi++)
        {
            this.portsIn[ipi]._onTriggered = this.portsIn[ipi]._onTriggeredProfiling;
            this.portsIn[ipi].set = this.portsIn[ipi]._onSetProfiling;
        }
    };

    Op.prototype.findParent = function (objName)
    {
        for (let ipi = 0; ipi < this.portsIn.length; ipi++)
        {
            if (this.portsIn[ipi].isLinked())
            {
                if (this.portsIn[ipi].links[0].portOut.parent.objName == objName)
                    return this.portsIn[ipi].links[0].portOut.parent;

                let found = null;
                found = this.portsIn[ipi].links[0].portOut.parent.findParent(objName);
                if (found) return found;
            }
        }
        return null;
    };


    // todo: check instancing stuff?
    Op.prototype.cleanUp = function ()
    {
        if (this._instances)
        {
            for (let i = 0; i < this._instances.length; i++)
            {
                if (this._instances[i].onDelete) this._instances[i].onDelete();
            }


            this._instances.length = 0;
        }
        for (let i = 0; i < this.portsIn.length; i++)
        {
            this.portsIn[i].setAnimated(false);
        }

        if (this.onAnimFrame) this.patch.removeOnAnimFrame(this);
    };

    // todo: check instancing stuff?
    Op.prototype.instanced = function (triggerPort)
    {
        return false;
        // this._log.log("instanced", this.patch.instancing.numCycles());
        // if (this.patch.instancing.numCycles() === 0) return false;


        // let i = 0;
        // let ipi = 0;
        // if (!this._instances || this._instances.length != this.patch.instancing.numCycles())
        // {
        //     if (!this._instances) this._instances = [];
        //     this._.log("creating instances of ", this.objName, this.patch.instancing.numCycles(), this._instances.length);
        //     this._instances.length = this.patch.instancing.numCycles();

        //     for (i = 0; i < this._instances.length; i++)
        //     {
        //         this._instances[i] = this.patch.createOp(this.objName, true);
        //         this._instances[i].instanced = function ()
        //         {
        //             return false;
        //         };
        //         this._instances[i].uiAttr(this.uiAttribs);

        //         for (let ipo = 0; ipo < this.portsOut.length; ipo++)
        //         {
        //             if (this.portsOut[ipo].type == CONSTANTS.OP.OP_PORT_TYPE_FUNCTION)
        //             {
        //                 this._instances[i].getPortByName(this.portsOut[ipo].name).trigger = this.portsOut[ipo].trigger.bind(this.portsOut[ipo]);
        //             }
        //         }
        //     }

        //     for (ipi = 0; ipi < this.portsIn.length; ipi++)
        //     {
        //         this.portsIn[ipi].onChange = null;
        //         this.portsIn[ipi].onValueChanged = null;
        //     }
        // }

        // const theTriggerPort = null;
        // for (ipi = 0; ipi < this.portsIn.length; ipi++)
        // {
        //     if (
        //         this.portsIn[ipi].type == CONSTANTS.OP.OP_PORT_TYPE_VALUE ||
        //         this.portsIn[ipi].type == CONSTANTS.OP.OP_PORT_TYPE_ARRAY
        //     )
        //     {
        //         this._instances[this.patch.instancing.index()].portsIn[ipi].set(this.portsIn[ipi].get());
        //     }
        //     if (this.portsIn[ipi].type == CONSTANTS.OP.OP_PORT_TYPE_FUNCTION)
        //     {
        //         // if(this._instances[ this.patch.instancing.index() ].portsIn[ipi].name==triggerPort.name)
        //         // theTriggerPort=this._instances[ this.patch.instancing.index() ].portsIn[ipi];
        //     }
        // }

        // if (theTriggerPort) theTriggerPort.onTriggered();

        // for (ipi = 0; ipi < this.portsOut.length; ipi++)
        // {
        //     if (this.portsOut[ipi].type == CONSTANTS.OP.OP_PORT_TYPE_VALUE)
        //     {
        //         this.portsOut[ipi].set(this._instances[this.patch.instancing.index()].portsOut[ipi].get());
        //     }
        // }

        // return true;
    };

    // todo: check instancing stuff?
    Op.prototype.initInstancable = function ()
    {
        //         if(this.isInstanced)
        //         {
        //             this._log.log('cancel instancing');
        //             return;
        //         }
        //         this._instances=[];
        //         for(var ipi=0;ipi<this.portsIn.length;ipi++)
        //         {
        //             if(this.portsIn[ipi].type==CONSTANTS.OP.OP_PORT_TYPE_VALUE)
        //             {
        //
        //             }
        //             if(this.portsIn[ipi].type==CONSTANTS.OP.OP_PORT_TYPE_FUNCTION)
        //             {
        //                 // var piIndex=ipi;
        //                 this.portsIn[ipi].onTriggered=function(piIndex)
        //                 {
        //
        //                     var i=0;
        // // this._log.log('trigger',this._instances.length);
        //
        //                 }.bind(this,ipi );
        //
        //             }
        // };
        // this._instances=null;
    };

    Op.prototype.setValues = function (obj)
    {
        for (const i in obj)
        {
            const port = this.getPortByName(i);
            if (port) port.set(obj[i]);
            else this._log.warn("op.setValues: port not found:", i);
        }
    };

    /**
     * return true if op has this error message id
     * @function hasUiError
     * @instance
     * @memberof Op
     * @param {id} error id
     * @returns {Boolean} - has id
     */
    Op.prototype.hasUiError = function (id)
    {
        return this._uiErrors.hasOwnProperty(id) && this._uiErrors[id];
    };

    /**
     * show op error message - set message to null to remove error message
     * @function setUiError
     * @instance
     * @memberof Op
     * @param {id} error id
     * @param {txt} text message
     * @param {level} level
     */
    Op.prototype.setUiError = function (id, txt, level)
    {
        // overwritten in ui: core_extend_op
    };

    // todo: remove
    Op.prototype.setError = function (id, txt)
    {
        this._log.warn("old error message op.error() - use op.setUiError()");
    };


    /**
     * enable/disable op
     * @function
     * @instance
     * @memberof Op
     * @param {boolean}
     */
    Op.prototype.setEnabled = function (b)
    {
        this.enabled = b;
        this.emitEvent("onEnabledChange", b);
    };

    /**
     * organize ports into a group
     * @function
     * @instance
     * @memberof Op
     * @param {String} name
     * @param {Array} ports
     */
    Op.prototype.setPortGroup = function (name, ports)
    {
        for (let i = 0; i < ports.length; i++)
        {
            if (ports[i])
                if (ports[i].setUiAttribs) ports[i].setUiAttribs({ "group": name });
                else
                {
                    this._log.error("setPortGroup: invalid port!");
                }
        }
    };

    /**
     * visually indicate ports that they are coordinate inputs
     * @function
     * @instance
     * @memberof Op
     * @param {Port} portX
     * @param {Port} portY
     * @param {Port} portZ
     */
    Op.prototype.setUiAxisPorts = function (px, py, pz)
    {
        if (px) px.setUiAttribs({ "axis": "X" });
        if (py) py.setUiAttribs({ "axis": "Y" });
        if (pz) pz.setUiAttribs({ "axis": "Z" });
    };

    /**
     * remove port from op
     * @function removePort
     * @instance
     * @memberof Op
     * @param {Port} port to remove
     */
    Op.prototype.removePort = function (port)
    {
        for (let ipi = 0; ipi < this.portsIn.length; ipi++)
        {
            if (this.portsIn[ipi] == port)
            {
                this.portsIn.splice(ipi, 1);
                this.emitEvent("onUiAttribsChange", {});
                this.emitEvent("onPortRemoved", {});
                return;
            }
        }
        for (let ipi = 0; ipi < this.portsOut.length; ipi++)
        {
            if (this.portsOut[ipi] == port)
            {
                this.portsOut.splice(ipi, 1);
                this.emitEvent("onUiAttribsChange", {});
                this.emitEvent("onPortRemoved", {});
                return;
            }
        }
    };

    Op.prototype._checkLinksNeededToWork = function () {};

    /**
     * show a warning of this op is not a child of parentOpName
     * @function
     * @instance
     * @memberof Op
     * @param {String} parentOpName
     */
    Op.prototype.toWorkNeedsParent = function (parentOpName)
    {
        this._linkTimeRules.needsParentOp = parentOpName;
    };

    // /**
    //  * show a warning of this op is a child of parentOpName
    //  * @function
    //  * @instance
    //  * @memberof Op
    //  * @param {String} parentOpName
    //  */
    Op.prototype.toWorkShouldNotBeChild = function (parentOpName, type)
    {
        if (!this.patch.isEditorMode()) return;
        this._linkTimeRules.forbiddenParent = parentOpName;
        if (type != undefined) this._linkTimeRules.forbiddenParentType = type;
    };


    /**
     * show a small X to indicate op is not working when given ports are not linked
     * @function
     * @instance
     * @memberof Op
     * @param {Port} port1
     * @param {Port} port2
     * @param {Port} port3
     */
    Op.prototype.toWorkPortsNeedToBeLinked = function ()
    {
        if (!this.patch.isEditorMode()) return;
        for (let i = 0; i < arguments.length; i++)
            if (this._linkTimeRules.needsLinkedToWork.indexOf(arguments[i]) == -1) this._linkTimeRules.needsLinkedToWork.push(arguments[i]);
    };
    Op.prototype.toWorkPortsNeedToBeLinkedReset = function ()
    {
        if (!this.patch.isEditorMode()) return;
        this._linkTimeRules.needsLinkedToWork.length = 0;
        if (this.checkLinkTimeWarnings) this.checkLinkTimeWarnings();
    };

    Op.prototype.initVarPorts = function ()
    {
        for (let i = 0; i < this.portsIn.length; i++)
        {
            if (this.portsIn[i].getVariableName()) this.portsIn[i].setVariable(this.portsIn[i].getVariableName());
        }
    };

    /**
     * refresh op parameters, if current op is selected
     * @function
     * @instance
     * @memberof Op
     */
    Op.prototype.refreshParams = function ()
    {
        if (this.patch && this.patch.isEditorMode() && this.isCurrentUiOp())
        {
            gui.opParams.show(this);
        }
    };

    /**
     * Returns true if op is selected and parameter are shown in the editor, can only return true if in editor/ui
     * @function isCurrentUiOp
     * @instance
     * @memberof Op
     * @returns {Boolean} - is current ui op
     */
    Op.prototype.isCurrentUiOp = function ()
    {
        if (this.patch.isEditorMode()) return gui.patchView.isCurrentOp(this);
    };

    /**
     * Implement to render 2d canvas based graphics from in an op
     * @function renderVizLayer
     * @instance
     * @memberof Op
     * @param {ctx} context of canvas 2d
     * @param {Object} layer info
     * @param {number} layer.x x position on canvas
     * @param {number} layer.y y position on canvas
     * @param {number} layer.width width of canvas
     * @param {number} layer.height height of canvas
     * @param {number} layer.scale current scaling of patchfield view
     */
    Op.prototype.renderVizLayer = null; // optionaly defined in op instance
}



;// CONCATENATED MODULE: ./src/core/loadingstatus.js




/**
 * LoadingStatus class, manages asynchronous loading jobs
 *
 * @namespace external:CABLES#LoadingStatus
 * @hideconstructor
 * @class
 * @param patch
 */
const LoadingStatus = function (patch)
{
    EventTarget.apply(this);

    this._log = new Logger("LoadingStatus");
    this._loadingAssets = {};
    this._cbFinished = [];
    this._assetTasks = [];
    this._percent = 0;
    this._count = 0;
    this._countFinished = 0;
    this._order = 0;
    this._startTime = 0;
    this._patch = patch;
    this._wasFinishedPrinted = false;
    this._loadingAssetTaskCb = false;
};

LoadingStatus.prototype.setOnFinishedLoading = function (cb)
{
    this._cbFinished.push(cb);
};

LoadingStatus.prototype.getNumAssets = function ()
{
    return this._countFinished;
};

LoadingStatus.prototype.getProgress = function ()
{
    return this._percent;
};

LoadingStatus.prototype.checkStatus = function ()
{
    this._countFinished = 0;
    this._count = 0;

    for (const i in this._loadingAssets)
    {
        this._count++;
        if (!this._loadingAssets[i].finished)
        {
            this._countFinished++;
        }
    }

    this._percent = (this._count - this._countFinished) / this._count;

    if (this._countFinished === 0)
    {
        for (let j = 0; j < this._cbFinished.length; j++)
        {
            if (this._cbFinished[j])
            {
                const cb = this._cbFinished[j];
                setTimeout(() => { cb(this._patch); this.emitEvent("finishedAll"); }, 100);
            }
        }

        if (!this._wasFinishedPrinted)
        {
            this._wasFinishedPrinted = true;
            this.print();
        }
        this.emitEvent("finishedAll");
    }
};

LoadingStatus.prototype.getList = function ()
{
    let arr = [];
    for (const i in this._loadingAssets)
    {
        arr.push(this._loadingAssets[i]);
    }

    return arr;
};


LoadingStatus.prototype.getListJobs = function ()
{
    let arr = [];
    for (const i in this._loadingAssets)
    {
        if (!this._loadingAssets[i].finished)arr.push(this._loadingAssets[i].name);
    }

    return arr;
};

LoadingStatus.prototype.print = function ()
{
    if (this._patch.config.silent) return;

    const rows = [];

    for (const i in this._loadingAssets)
    {
        rows.push([
            this._loadingAssets[i].order,
            this._loadingAssets[i].type,
            this._loadingAssets[i].name,
            (this._loadingAssets[i].timeEnd - this._loadingAssets[i].timeStart) / 1000 + "s",
        ]);
    }

    this._log.groupCollapsed("finished loading " + this._order + " assets in " + (Date.now() - this._startTime) / 1000 + "s");
    this._log.table(rows);
    this._log.groupEnd();
};

LoadingStatus.prototype.finished = function (id)
{
    const l = this._loadingAssets[id];
    if (l)
    {
        if (l.finished) this._log.warn("loading job was already finished", l);

        if (l.op) l.op.setUiAttribs({ "loading": false });
        l.finished = true;
        l.timeEnd = Date.now();
    }

    this.checkStatus();
    this.emitEvent("finishedTask");
    return null;
};

LoadingStatus.prototype._startAssetTasks = function ()
{
    for (let i = 0; i < this._assetTasks.length; i++) this._assetTasks[i]();
    this._assetTasks.length = 0;
};

/**
 * delay an asset loading task, mainly to wait for ui to be finished loading and showing, and only then start loading assets
 * @function addAssetLoadingTask
 * @instance
 * @memberof LoadingStatus
 * @param {function} cb callback
 */
LoadingStatus.prototype.addAssetLoadingTask = function (cb)
{
    if (this._patch.isEditorMode() && !CABLES.UI.loaded)
    {
        this._assetTasks.push(cb);

        if (!this._loadingAssetTaskCb)window.gui.addEventListener("uiloaded", this._startAssetTasks.bind(this));
        this._loadingAssetTaskCb = true;
    }
    else
    {
        cb();
    }
    this.emitEvent("addAssetTask");
};

LoadingStatus.prototype.existByName = function (name)
{
    for (let i in this._loadingAssets)
    {
        if (this._loadingAssets[i].name == name && !this._loadingAssets[i].finished)
            return true;
    }
};

LoadingStatus.prototype.start = function (type, name, op)
{
    if (this._startTime == 0) this._startTime = Date.now();
    const id = generateUUID();

    name = name || "unknown";
    if (name.length > 100)name = name.substring(0, 100);


    if (op)op.setUiAttribs({ "loading": true });

    this._loadingAssets[id] = {
        "id": id,
        "op": op,
        "type": type,
        "name": name,
        "finished": false,
        "timeStart": Date.now(),
        "order": this._order,
    };
    this._order++;

    this.emitEvent("startTask");

    return id;
};



;// CONCATENATED MODULE: ./src/core/timer.js


/** @namespace CABLES */

const internalNow = function ()
{
    return window.performance.now();
};



/**
 * current time in milliseconds
 * @memberof CABLES
 * @function now
 * @static
 */
const now = function ()
{
    return internalNow();
};

// ----------------------------

/**
 * Measuring time
 * @namespace external:CABLES#Timer
 * @hideconstructor
 * @class
 */
const Timer = function ()
{
    EventTarget.apply(this);

    this._timeStart = internalNow();
    this._timeOffset = 0;

    this._currentTime = 0;
    this._lastTime = 0;
    this._paused = true;
    this._delay = 0;
    this.overwriteTime = -1;
};


Timer.prototype._internalNow = function ()
{
    if (this._ts) return this._ts;
    return internalNow();
};

Timer.prototype._getTime = function ()
{
    this._lastTime = (this._internalNow() - this._timeStart) / 1000;
    return this._lastTime + this._timeOffset;
};

Timer.prototype.setDelay = function (d)
{
    this._delay = d;
    this.emitEvent("timeChange");
};

/**
 * @function
 * @memberof Timer
 * @instance
 * @description returns true if timer is playing
 * @return {Boolean} value
 */
Timer.prototype.isPlaying = function ()
{
    return !this._paused;
};

/**
 * @function
 * @memberof Timer
 * @instance
 * @param ts
 * @description update timer
 * @return {Number} time
 */
Timer.prototype.update = function (ts)
{
    if (ts) this._ts = ts;
    if (this._paused) return;
    this._currentTime = this._getTime();

    return this._currentTime;
};

/**
 * @function
 * @memberof Timer
 * @instance
 * @return {Number} time in milliseconds
 */
Timer.prototype.getMillis = function ()
{
    return this.get() * 1000;
};

/**
 * @function
 * @memberof Timer
 * @instance
 * @return {Number} value time in seconds
 */
Timer.prototype.get = Timer.prototype.getTime = function ()
{
    if (this.overwriteTime >= 0) return this.overwriteTime - this._delay;
    return this._currentTime - this._delay;
};

/**
 * toggle between play/pause state
 * @function
 * @memberof Timer
 * @instance
 */
Timer.prototype.togglePlay = function ()
{
    if (this._paused) this.play();
    else this.pause();
};

/**
 * set current time
 * @function
 * @memberof Timer
 * @instance
 * @param {Number} t
 */
Timer.prototype.setTime = function (t)
{
    if (isNaN(t) || t < 0) t = 0;
    this._timeStart = this._internalNow();
    this._timeOffset = t;
    this._currentTime = t;
    this.emitEvent("timeChange");
};

Timer.prototype.setOffset = function (val)
{
    if (this._currentTime + val < 0)
    {
        this._timeStart = this._internalNow();
        this._timeOffset = 0;
        this._currentTime = 0;
    }
    else
    {
        this._timeOffset += val;
        this._currentTime = this._lastTime + this._timeOffset;
    }
    this.emitEvent("timeChange");
};

/**
 * (re)starts the timer
 * @function
 * @memberof Timer
 * @instance
 */
Timer.prototype.play = function ()
{
    this._timeStart = this._internalNow();
    this._paused = false;
    this.emitEvent("playPause");
};

/**
 * pauses the timer
 * @function
 * @memberof Timer
 * @instance
 */
Timer.prototype.pause = function ()
{
    this._timeOffset = this._currentTime;
    this._paused = true;
    this.emitEvent("playPause");
};



;// CONCATENATED MODULE: ./src/core/core_profiler.js


class Profiler
{
    constructor(patch)
    {
        this.startFrame = patch.getFrameNum();
        this.items = {};
        this.currentId = null;
        this.currentStart = 0;
        this._patch = patch;
    }

    getItems()
    {
        return this.items;
    }

    clear()
    {
        if (this.paused) return;
        this.items = {};
    }

    togglePause()
    {
        this.paused = !this.paused;
        if (!this.paused)
        {
            this.items = {};
            this.currentStart = performance.now();
        }
    }

    add(type, object)
    {
        if (this.paused) return;

        if (this.currentId !== null)
        {
            if (!object || object.id != this.currentId)
            {
                if (this.items[this.currentId])
                {
                    this.items[this.currentId].timeUsed += performance.now() - this.currentStart;

                    if (!this.items[this.currentId].peakTime || now() - this.items[this.currentId].peakTime > 5000)
                    {
                        this.items[this.currentId].peak = 0;
                        this.items[this.currentId].peakTime = now();
                    }
                    this.items[this.currentId].peak = Math.max(this.items[this.currentId].peak, performance.now() - this.currentStart);
                }
            }
        }

        if (object !== null)
        {
            if (!this.items[object.id])
            {
                this.items[object.id] = {
                    "numTriggers": 0,
                    "timeUsed": 0,
                };
            }

            if (this.items[object.id].lastFrame != this._patch.getFrameNum()) this.items[object.id].numTriggers = 0;

            this.items[object.id].lastFrame = this._patch.getFrameNum();
            this.items[object.id].numTriggers++;
            this.items[object.id].opid = object.op.id;
            this.items[object.id].title = object.op.name + "." + object.name;
            this.items[object.id].subPatch = object.op.uiAttribs.subPatch;

            this.currentId = object.id;
            this.currentStart = performance.now();
        }
        else
        {
            this.currentId = null;
        }
    }

    print()
    {
        console.log("--------");
        for (const i in this.items)
        {
            console.log(this.items[i].title + ": " + this.items[i].numTriggers + " / " + this.items[i].timeUsed);
        }
    }
}



;// CONCATENATED MODULE: ./src/core/cgl/constants.js
const SHADER = {
    // default attributes
    "SHADERVAR_VERTEX_POSITION": "vPosition",
    "SHADERVAR_VERTEX_NUMBER": "attrVertIndex",
    "SHADERVAR_VERTEX_NORMAL": "attrVertNormal",
    "SHADERVAR_VERTEX_TEXCOORD": "attrTexCoord",
    "SHADERVAR_INSTANCE_MMATRIX": "instMat",
    "SHADERVAR_VERTEX_COLOR": "attrVertColor",

    "SHADERVAR_INSTANCE_INDEX": "instanceIndex",

    // default uniforms
    "SHADERVAR_UNI_PROJMAT": "projMatrix",
    "SHADERVAR_UNI_VIEWMAT": "viewMatrix",
    "SHADERVAR_UNI_MODELMAT": "modelMatrix",
    "SHADERVAR_UNI_NORMALMAT": "normalMatrix",
    "SHADERVAR_UNI_INVVIEWMAT": "inverseViewMatrix",
    "SHADERVAR_UNI_INVPROJMAT": "invProjMatrix",
    "SHADERVAR_UNI_MATERIALID": "materialId",
    "SHADERVAR_UNI_OBJECTID": "objectId",

    "SHADERVAR_UNI_VIEWPOS": "camPos",
};


const BLEND_MODES = {
    "BLEND_NONE": 0,
    "BLEND_NORMAL": 1,
    "BLEND_ADD": 2,
    "BLEND_SUB": 3,
    "BLEND_MUL": 4,
};





const RAD2DEG = 180.0 / Math.PI;
const DEG2RAD = Math.PI / 180.0;

const constants_CONSTANTS = {
    "MATH": {
        "DEG2RAD": DEG2RAD,
        "RAD2DEG": RAD2DEG,
    },
    "SHADER": SHADER,
    "BLEND_MODES": BLEND_MODES,
};




;// CONCATENATED MODULE: ./src/core/cg/cg_uniform.js



class CgUniform
{
    constructor(__shader, __type, __name, _value, _port2, _port3, _port4, _structUniformName, _structName, _propertyName)
    {
        this._log = new Logger("cg_uniform");
        this._type = __type;
        this._name = __name;
        this._shader = __shader;
        this._value = 0.00001;
        this._oldValue = null;
        this._port = null;
        this._structName = _structName;
        this._structUniformName = _structUniformName;
        this._propertyName = _propertyName;

        this._shader._addUniform(this);
        this.needsUpdate = true;
        this.shaderType = null;
        this.comment = null;

        if (__type == "f")
        {
            this.set = this.setValue = this.setValueF.bind(this);
            this.updateValue = this.updateValueF.bind(this);
        }
        else if (__type == "f[]")
        {
            this.set = this.setValue = this.setValueArrayF.bind(this);
            this.updateValue = this.updateValueArrayF.bind(this);
        }
        else if (__type == "2f[]")
        {
            this.set = this.setValue = this.setValueArray2F.bind(this);
            this.updateValue = this.updateValueArray2F.bind(this);
        }
        else if (__type == "3f[]")
        {
            this.set = this.setValue = this.setValueArray3F.bind(this);
            this.updateValue = this.updateValueArray3F.bind(this);
        }
        else if (__type == "4f[]")
        {
            this.set = this.setValue = this.setValueArray4F.bind(this);
            this.updateValue = this.updateValueArray4F.bind(this);
        }
        else if (__type == "i")
        {
            this.set = this.setValue = this.setValueI.bind(this);
            this.updateValue = this.updateValueI.bind(this);
        }
        else if (__type == "2i")
        {
            this.set = this.setValue = this.setValue2I.bind(this);
            this.updateValue = this.updateValue2I.bind(this);
        }
        else if (__type == "3i")
        {
            this.set = this.setValue = this.setValue3I.bind(this);
            this.updateValue = this.updateValue3I.bind(this);
        }
        else if (__type == "4i")
        {
            this.set = this.setValue = this.setValue4I.bind(this);
            this.updateValue = this.updateValue4I.bind(this);
        }
        else if (__type == "b")
        {
            this.set = this.setValue = this.setValueBool.bind(this);
            this.updateValue = this.updateValueBool.bind(this);
        }
        else if (__type == "4f")
        {
            this.set = this.setValue = this.setValue4F.bind(this);
            this.updateValue = this.updateValue4F.bind(this);
        }
        else if (__type == "3f")
        {
            this.set = this.setValue = this.setValue3F.bind(this);
            this.updateValue = this.updateValue3F.bind(this);
        }
        else if (__type == "2f")
        {
            this.set = this.setValue = this.setValue2F.bind(this);
            this.updateValue = this.updateValue2F.bind(this);
        }
        else if (__type == "t")
        {
            this.set = this.setValue = this.setValueT.bind(this);
            this.updateValue = this.updateValueT.bind(this);
        }
        else if (__type == "sampler")
        {
            if (this.setValueAny)
            {
                this.set = this.setValue = this.setValueAny.bind(this);
                this.updateValue = this.updateValueAny.bind(this);
            }
        }
        else if (__type == "tc")
        {
            this.set = this.setValue = this.setValueT.bind(this);
            this.updateValue = this.updateValueT.bind(this);
        }
        else if (__type == "t[]")
        {
            this.set = this.setValue = this.setValueArrayT.bind(this);
            this.updateValue = this.updateValueArrayT.bind(this);
        }
        else if (__type == "m4" || __type == "m4[]")
        {
            this.set = this.setValue = this.setValueM4.bind(this);
            this.updateValue = this.updateValueM4.bind(this);
        }
        else
        {
            // console.error("unknown");
            this._log.error("Unknown uniform type " + __type);
        }

        if (typeof _value == "object" && _value instanceof Port)
        {
            this._port = _value;
            this._value = this._port.get();


            if (_port2 && _port3 && _port4)
            {
                if (!(_port2 instanceof Port) || !(_port3 instanceof Port) || !(_port4 instanceof Port))
                {
                    this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ", this._name);
                }

                this._value = [0, 0, 0, 0];
                this._port2 = _port2;
                this._port3 = _port3;
                this._port4 = _port4;

                this._port.on("change", this.updateFromPort4f.bind(this));
                this._port2.on("change", this.updateFromPort4f.bind(this));
                this._port3.on("change", this.updateFromPort4f.bind(this));
                this._port4.on("change", this.updateFromPort4f.bind(this));

                // this._port.onChange = this._port2.onChange = this._port3.onChange = this._port4.onChange = this.updateFromPort4f.bind(this);
                this.updateFromPort4f();
            }
            else if (_port2 && _port3)
            {
                if (!(_port2 instanceof Port) || !(_port3 instanceof Port))
                {
                    this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ", this._name);
                }

                this._value = [0, 0, 0];
                this._port2 = _port2;
                this._port3 = _port3;
                // this._port.onChange = this._port2.onChange = this._port3.onChange = this.updateFromPort3f.bind(this);
                this._port.on("change", this.updateFromPort3f.bind(this));
                this._port2.on("change", this.updateFromPort3f.bind(this));
                this._port3.on("change", this.updateFromPort3f.bind(this));

                this.updateFromPort3f();
            }
            else if (_port2)
            {
                if (!(_port2 instanceof Port))
                {
                    this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ", this._name);
                }

                this._value = [0, 0];
                this._port2 = _port2;
                // this._port.onChange = this._port2.onChange = this.updateFromPort2f.bind(this);
                this._port.on("change", this.updateFromPort2f.bind(this));
                this._port2.on("change", this.updateFromPort2f.bind(this));

                this.updateFromPort2f();
            }
            else
            {
                // this._port.on = this.updateFromPort.bind(this);
                this._port.on("change", this.updateFromPort.bind(this));
            }
        }
        else this._value = _value;


        if (this._value == undefined)
        {
            console.log("value undefined", this);
            this._value = 0;
        }

        this.setValue(this._value);

        this.needsUpdate = true;
    }

    getType()
    {
        return this._type;
    }

    get type()
    {
        return this._type;
    }

    get name()
    {
        return this._name;
    }

    getName()
    {
        return this._name;
    }

    getValue()
    {
        return this._value;
    }

    getShaderType()
    {
        return this.shaderType;
    }

    isStructMember()
    {
        return !!this._structName;
    }


    updateFromPort4f()
    {
        this._value[0] = this._port.get();
        this._value[1] = this._port2.get();
        this._value[2] = this._port3.get();
        this._value[3] = this._port4.get();
        this.setValue(this._value);
    }

    updateFromPort3f()
    {
        this._value[0] = this._port.get();
        this._value[1] = this._port2.get();
        this._value[2] = this._port3.get();
        this.setValue(this._value);
    }

    updateFromPort2f()
    {
        this._value[0] = this._port.get();
        this._value[1] = this._port2.get();
        this.setValue(this._value);
    }

    updateFromPort()
    {
        this.setValue(this._port.get());
    }
}

/* harmony default export */ const cg_uniform = (CgUniform);

;// CONCATENATED MODULE: ./src/core/cgl/cgl_shader_uniform.js




/**
 * Shader uniforms
 *
 * types:
 * <pre>
 * f    - float
 * 2f   - vec2
 * 3f   - vec3
 * 4f   - vec4
 * i    - integer
 * t    - texture
 * m4   - mat4, 4x4 float matrix
 * f[]  - array of floats
 * 2f[] - array of float vec2
 * 3f[] - array of float vec3
 * 4f[] - array of float vec4
 * </pre>
 *
 * @namespace external:CGL
 * @class
 * @param {Shader} shader
 * @param {String} [type=f]
 * @param {String} name
 * @param {Number|Port} value  can be a Number,Matrix or Port
 * @example
 * // bind float uniform called myfloat and initialize with value 1.0
 * const unir=new CGL.Uniform(shader,'f','myfloat',1.0);
 * unir.setValue(1.0);
 *
 * // bind float uniform called myfloat and automatically set it to input port value
 * const myPort=op.inFloat("input");
 * const pv=new CGL.Uniform(shader,'f','myfloat',myPort);
 *
 */


// export const Uniform(__shader, __type, __name, _value, _port2, _port3, _port4, _structUniformName, _structName, _propertyName)

class Uniform extends cg_uniform
{
    constructor(__shader, __type, __name, _value, _port2, _port3, _port4, _structUniformName, _structName, _propertyName)
    {
        super(__shader, __type, __name, _value, _port2, _port3, _port4, _structUniformName, _structName, _propertyName);
        this._loc = -1;
        this._cgl = __shader._cgl;
    }

    get name()
    {
        return this._name;
    }

    copy(newShader)
    {
        const uni = new Uniform(newShader, this._type, this._name, this._value, this._port2, this._port3, this._port4, this._structUniformName, this._structName, this._propertyName);
        uni.shaderType = this.shaderType;
        return uni;
    }

    /**
     * returns type as glsl type string. e.g. 'f' returns 'float'
     * @function getGlslTypeString
     * @memberof Uniform
     * @instance
     * @return {string} type as string
     */
    getGlslTypeString()
    {
        return Uniform.glslTypeString(this._type);
    }

    _isValidLoc()
    {
        return this._loc != -1;// && this._loc != null;
    }

    resetLoc()
    {
        this._loc = -1;
        this.needsUpdate = true;
    }

    bindTextures() {}

    getLoc()
    {
        return this._loc;
    }

    updateFromPort4f()
    {
        this._value[0] = this._port.get();
        this._value[1] = this._port2.get();
        this._value[2] = this._port3.get();
        this._value[3] = this._port4.get();
        this.setValue(this._value);
    }

    updateFromPort3f()
    {
        this._value[0] = this._port.get();
        this._value[1] = this._port2.get();
        this._value[2] = this._port3.get();
        this.setValue(this._value);
    }

    updateFromPort2f()
    {
        this._value[0] = this._port.get();
        this._value[1] = this._port2.get();
        this.setValue(this._value);
    }

    updateFromPort()
    {
        this.setValue(this._port.get());
    }

    updateValueF()
    {
        if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
        else this.needsUpdate = false;

        this._shader.getCgl().gl.uniform1f(this._loc, this._value);
        this._cgl.profileData.profileUniformCount++;
    }

    setValueF(v)
    {
        if (v != this._value)
        {
            this.needsUpdate = true;
            this._value = v;
        }
    }

    updateValueI()
    {
        if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
        else this.needsUpdate = false;

        this._shader.getCgl().gl.uniform1i(this._loc, this._value);
        this._cgl.profileData.profileUniformCount++;
    }

    updateValue2I()
    {
        if (!this._value) return;

        if (!this._isValidLoc())
        {
            this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
            this._cgl.profileData.profileShaderGetUniform++;
            this._cgl.profileData.profileShaderGetUniformName = this._name;
        }

        this._shader.getCgl().gl.uniform2i(this._loc, this._value[0], this._value[1]);

        this.needsUpdate = false;
        this._cgl.profileData.profileUniformCount++;
    }

    updateValue3I()
    {
        if (!this._value) return;
        if (!this._isValidLoc())
        {
            this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
            this._cgl.profileData.profileShaderGetUniform++;
            this._cgl.profileData.profileShaderGetUniformName = this._name;
        }

        this._shader.getCgl().gl.uniform3i(this._loc, this._value[0], this._value[1], this._value[2]);
        this.needsUpdate = false;
        this._cgl.profileData.profileUniformCount++;
    }

    updateValue4I()
    {
        if (!this._isValidLoc())
        {
            this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
            this._cgl.profileData.profileShaderGetUniform++;
            this._cgl.profileData.profileShaderGetUniformName = this._name;
        }
        this._shader.getCgl().gl.uniform4i(this._loc, this._value[0], this._value[1], this._value[2], this._value[3]);
        this._cgl.profileData.profileUniformCount++;
    }

    setValueI(v)
    {
        if (v != this._value)
        {
            this.needsUpdate = true;
            this._value = v;
        }
    }

    setValue2I(v)
    {
        if (!v) return;
        if (!this._oldValue)
        {
            this._oldValue = [v[0] - 1, 1];
            this.needsUpdate = true;
        }
        else if (v[0] != this._oldValue[0] || v[1] != this._oldValue[1])
        {
            this._oldValue[0] = v[0];
            this._oldValue[1] = v[1];
            this.needsUpdate = true;
        }

        this._value = v;
    }

    setValue3I(v)
    {
        if (!v) return;
        if (!this._oldValue)
        {
            this._oldValue = [v[0] - 1, 1, 2];
            this.needsUpdate = true;
        }
        else if (v[0] != this._oldValue[0] || v[1] != this._oldValue[1] || v[2] != this._oldValue[2])
        {
            this._oldValue[0] = v[0];
            this._oldValue[1] = v[1];
            this._oldValue[2] = v[2];
            this.needsUpdate = true;
        }

        this._value = v;
    }

    setValue4I(v)
    {
        this.needsUpdate = true;
        this._value = v || vec4.create();
    }

    updateValueBool()
    {
        if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
        else this.needsUpdate = false;
        this._shader.getCgl().gl.uniform1i(this._loc, this._value ? 1 : 0);

        this._cgl.profileData.profileUniformCount++;
    }

    setValueBool(v)
    {
        if (v != this._value)
        {
            this.needsUpdate = true;
            this._value = v;
        }
    }

    setValueArray4F(v)
    {
        this.needsUpdate = true;
        this._value = v;
    }

    updateValueArray4F()
    {
        if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
        else this.needsUpdate = false;

        if (!this._value) return;
        this._shader.getCgl().gl.uniform4fv(this._loc, this._value);
        this._cgl.profileData.profileUniformCount++;
    }

    setValueArray3F(v)
    {
        this.needsUpdate = true;
        this._value = v;
    }

    updateValueArray3F()
    {
        if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
        else this.needsUpdate = false;

        if (!this._value) return;
        this._shader.getCgl().gl.uniform3fv(this._loc, this._value);
        this._cgl.profileData.profileUniformCount++;
    }

    setValueArray2F(v)
    {
        this.needsUpdate = true;
        this._value = v;
    }

    updateValueArray2F()
    {
        if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
        else this.needsUpdate = false;

        if (!this._value) return;
        this._shader.getCgl().gl.uniform2fv(this._loc, this._value);
        this._cgl.profileData.profileUniformCount++;
    }

    setValueArrayF(v)
    {
        this.needsUpdate = true;
        this._value = v;
    }

    updateValueArrayF()
    {
        if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
        else this.needsUpdate = false;

        if (!this._value) return;
        this._shader.getCgl().gl.uniform1fv(this._loc, this._value);
        this._cgl.profileData.profileUniformCount++;
    }

    setValueArrayT(v)
    {
        this.needsUpdate = true;
        this._value = v;
    }


    updateValue3F()
    {
        if (!this._value) return;
        if (!this._isValidLoc())
        {
            this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
            this._cgl.profileData.profileShaderGetUniform++;
            this._cgl.profileData.profileShaderGetUniformName = this._name;
        }

        this._shader.getCgl().gl.uniform3f(this._loc, this._value[0], this._value[1], this._value[2]);
        this.needsUpdate = false;
        this._cgl.profileData.profileUniformCount++;
    }

    setValue3F(v)
    {
        if (!v) return;
        if (!this._oldValue)
        {
            this._oldValue = [v[0] - 1, 1, 2];
            this.needsUpdate = true;
        }
        else if (v[0] != this._oldValue[0] || v[1] != this._oldValue[1] || v[2] != this._oldValue[2])
        {
            this._oldValue[0] = v[0];
            this._oldValue[1] = v[1];
            this._oldValue[2] = v[2];
            this.needsUpdate = true;
        }

        this._value = v;
    }

    updateValue2F()
    {
        if (!this._value) return;

        if (!this._isValidLoc())
        {
            this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
            this._cgl.profileData.profileShaderGetUniform++;
            this._cgl.profileData.profileShaderGetUniformName = this._name;
        }

        this._shader.getCgl().gl.uniform2f(this._loc, this._value[0], this._value[1]);
        this.needsUpdate = false;
        this._cgl.profileData.profileUniformCount++;
    }

    setValue2F(v)
    {
        if (!v) return;
        if (!this._oldValue)
        {
            this._oldValue = [v[0] - 1, 1];
            this.needsUpdate = true;
        }
        else if (v[0] != this._oldValue[0] || v[1] != this._oldValue[1])
        {
            this._oldValue[0] = v[0];
            this._oldValue[1] = v[1];
            this.needsUpdate = true;
        }
        this._value = v;
    }

    updateValue4F()
    {
        if (!this._isValidLoc())
        {
            this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
            this._cgl.profileData.profileShaderGetUniform++;
            this._cgl.profileData.profileShaderGetUniformName = this._name;
        }

        if (!this._value)
        {
            this._log.warn("no value for uniform", this._name, this);
            this._value = [0, 0, 0, 0];
        }

        this.needsUpdate = false;
        this._shader.getCgl().gl.uniform4f(this._loc, this._value[0], this._value[1], this._value[2], this._value[3]);
        this._cgl.profileData.profileUniformCount++;
    }

    setValue4F(v)
    {
        if (typeof this.value == "number") this.value = vec4.create(); // this should not be needed, but somehow it crashes with some shadermods

        if (!v) return;
        if (!this._oldValue)
        {
            this._oldValue = [v[0] - 1, 1, 2, 3];
            this.needsUpdate = true;
        }
        else if (v[0] != this._oldValue[0] || v[1] != this._oldValue[1] || v[2] != this._oldValue[2] || v[3] != this._oldValue[3])
        {
            this._oldValue[0] = v[0];
            this._oldValue[1] = v[1];
            this._oldValue[2] = v[2];
            this.needsUpdate = true;
        }

        this._value = v;
    }

    updateValueM4()
    {
        if (!this._isValidLoc())
        {
            this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
            this._cgl.profileData.profileShaderGetUniform++;
            this._cgl.profileData.profileShaderGetUniformName = this._name;
        }
        if (!this._value || this._value.length % 16 != 0) return console.log("this.name", this._name, this._value);

        this._shader.getCgl().gl.uniformMatrix4fv(this._loc, false, this._value);
        this._cgl.profileData.profileUniformCount++;
    }

    setValueM4(v)
    {
        this.needsUpdate = true;
        this._value = v || mat4.create();
    }

    updateValueArrayT()
    {
        if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
        else this.needsUpdate = false;

        if (!this._value) return;
        this._shader.getCgl().gl.uniform1iv(this._loc, this._value);
        this._cgl.profileData.profileUniformCount++;
    }

    updateValueT()
    {
        if (!this._isValidLoc())
        {
            this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
            this._cgl.profileData.profileShaderGetUniform++;
            this._cgl.profileData.profileShaderGetUniformName = this._name;
        }

        this._cgl.profileData.profileUniformCount++;
        this._shader.getCgl().gl.uniform1i(this._loc, this._value);
        this.needsUpdate = false;
    }

    setValueT(v)
    {
        this.needsUpdate = true;
        this._value = v;
    }
}


Uniform.glslTypeString = (t) =>
{
    if (t == "f") return "float";
    if (t == "b") return "bool";
    if (t == "i") return "int";
    if (t == "2i") return "ivec2";
    if (t == "2f") return "vec2";
    if (t == "3f") return "vec3";
    if (t == "4f") return "vec4";
    if (t == "m4") return "mat4";

    if (t == "t") return "sampler2D";
    if (t == "tc") return "samplerCube";

    if (t == "3f[]") return null; // ignore this for now...
    if (t == "m4[]") return null; // ignore this for now...
    if (t == "f[]") return null; // ignore this for now...

    console.warn("[CGL UNIFORM] unknown glsl type string ", t);
};


/**
 * @function setValue
 * @memberof Uniform
 * @instance
 * @param {Number|Array|Matrix|Texture} value
 */



;// CONCATENATED MODULE: ./src/core/cg/cg_texture.js
const DEFAULT_TEXTURE_SIZE = 8;

class CgTexture
{
    constructor(options = {})
    {
        this.id = CABLES.uuid();
        this.width = 0;
        this.height = 0;
        this.name = "unknown";

        options = options || {};
        this.pixelFormat = options.pixelFormat || CgTexture.PFORMATSTR_RGBA8UB;

        this.name = options.name || "unknown";

        if (!options.width) options.width = DEFAULT_TEXTURE_SIZE;
        if (!options.height) options.height = DEFAULT_TEXTURE_SIZE;
    }
}


CgTexture.getDefaultTextureData = (name, size, options = {}) =>
{
    if (name == "empty")
    {
        return new Uint8Array(size * size * 4).fill(0);
    }
    else
    if (name == "color")
    {
        const data = new Uint8Array(size * size * 4);
        let r = options.r || 1;
        let g = options.g || 1;
        let b = options.b || 1;

        for (let x = 0; x < size * size; x++)
        {
            data[x * 4 + 0] = r;
            data[x * 4 + 1] = g;
            data[x * 4 + 2] = b;
            data[x * 4 + 3] = 255;
        }
        return data;
    }
    else
    if (name == "randomUInt")
    {
        const data = new Uint8Array(size * size * 4);

        for (let x = 0; x < size * size; x++)
        {
            data[x * 4 + 0] = Math.random() * 255;
            data[x * 4 + 1] = Math.random() * 255;
            data[x * 4 + 2] = Math.random() * 255;
            data[x * 4 + 3] = 255;
        }
        return data;
    }
    else
    if (name == "random" || name == "randomFloat")
    {
        const data = new Float32Array(size * size * 4);

        for (let x = 0; x < size * size; x++)
        {
            data[x * 4 + 0] = (Math.random() - 0.5) * 2.0;
            data[x * 4 + 1] = (Math.random() - 0.5) * 2.0;
            data[x * 4 + 2] = (Math.random() - 0.5) * 2.0;
            data[x * 4 + 3] = 1;
        }
        return data;
    }
    else
    if (name == "stripes")
    {
        const arr = [];

        let r = options.r;
        let g = options.g;
        let b = options.b;

        if (r === undefined)r = 1;
        if (g === undefined)g = 1;
        if (b === undefined)b = 1;

        for (let y = 0; y < size; y++)
        {
            for (let x = 0; x < size; x++)
            {
                if ((x + y) % 64 < 32)
                {
                    arr.push((200 + (y / size) * 25 + (x / size) * 25) * r);
                    arr.push((200 + (y / size) * 25 + (x / size) * 25) * g);
                    arr.push((200 + (y / size) * 25 + (x / size) * 25) * b);
                }
                else
                {
                    arr.push((40 + (y / size) * 25 + (x / size) * 25) * r);
                    arr.push((40 + (y / size) * 25 + (x / size) * 25) * g);
                    arr.push((40 + (y / size) * 25 + (x / size) * 25) * b);
                }
                arr.push(255);
            }
        }

        return new Uint8Array(arr);
    }
    else
    {
        console.warn("unknown default texture", name);
        return CgTexture.getDefaultTextureData("stripes", size, { "r": 1, "g": 0, "b": 0 });
    }
};



CgTexture.FILTER_NEAREST = 0;
CgTexture.FILTER_LINEAR = 1;
CgTexture.FILTER_MIPMAP = 2;

CgTexture.WRAP_REPEAT = 0;
CgTexture.WRAP_MIRRORED_REPEAT = 1;
CgTexture.WRAP_CLAMP_TO_EDGE = 2;

CgTexture.TYPE_DEFAULT = 0;
CgTexture.TYPE_DEPTH = 1;
CgTexture.TYPE_FLOAT = 2;


CgTexture.PFORMATSTR_RGB565 = "RGB 5/6/5bit ubyte";

CgTexture.PFORMATSTR_R8UB = "R 8bit ubyte";
CgTexture.PFORMATSTR_RG8UB = "RG 8bit ubyte";
CgTexture.PFORMATSTR_RGB8UB = "RGB 8bit ubyte";
CgTexture.PFORMATSTR_RGBA8UB = "RGBA 8bit ubyte";

CgTexture.PFORMATSTR_SRGBA8 = "SRGBA 8bit ubyte";

CgTexture.PFORMATSTR_R11FG11FB10F = "RGB 11/11/10bit float";

CgTexture.PFORMATSTR_R16F = "R 16bit float";
CgTexture.PFORMATSTR_RG16F = "RG 16bit float";
CgTexture.PFORMATSTR_RGB16F = "RGB 16bit float";
CgTexture.PFORMATSTR_RGBA16F = "RGBA 16bit float";


CgTexture.PFORMATSTR_R32F = "R 32bit float";
CgTexture.PFORMATSTR_RG32F = "RG 32bit float";
CgTexture.PFORMATSTR_RGB32F = "RGB 32bit float";
CgTexture.PFORMATSTR_RGBA32F = "RGBA 32bit float";

CgTexture.PFORMATSTR_DEPTH = "DEPTH";


CgTexture.PIXELFORMATS = [

    CgTexture.PFORMATSTR_RGB565,

    CgTexture.PFORMATSTR_R8UB,
    CgTexture.PFORMATSTR_RG8UB,
    CgTexture.PFORMATSTR_RGB8UB,
    CgTexture.PFORMATSTR_RGBA8UB,

    CgTexture.PFORMATSTR_SRGBA8,

    CgTexture.PFORMATSTR_R11FG11FB10F,
    CgTexture.PFORMATSTR_R16F,
    CgTexture.PFORMATSTR_RG16F,
    CgTexture.PFORMATSTR_RGBA16F,

    CgTexture.PFORMATSTR_R32F,
    CgTexture.PFORMATSTR_RGBA32F

];

;// CONCATENATED MODULE: ./src/core/cgl/cgl_texture.js




const cgl_texture_DEFAULT_TEXTURE_SIZE = 8;

/**
 * A Texture
 * @namespace external:CGL
 * @class
 * @param {Context} __cgl cgl
 * @param {Object} options
 * @hideconstructor
 * @example
 * // generate a 256x256 pixel texture of random colors
 * const size=256;
 * const data = new Uint8Array(size*size*4);
 *
 * for(var x=0;x<size*size*4;x++) data[ x*4+3]=255;
 *
 * const tex=new CGL.Texture(cgl);
 * tex.initFromData(data,size,size,CGL.Texture.FILTER_NEAREST,CGL.Texture.WRAP_REPEAT);
 */
class Texture extends CgTexture
{
    constructor(__cgl, options = {})
    {
        super(options);
        if (!__cgl) throw new Error("no cgl");
        this._log = new Logger("cgl_texture");
        this._cgl = __cgl;
        this.tex = this._cgl.gl.createTexture();
        this.loading = false;
        this.flip = true;
        this.flipped = false;
        this.shadowMap = false;
        this.deleted = false;
        this.image = null;
        this.anisotropic = 0;
        this.filter = Texture.FILTER_NEAREST;
        this.wrap = Texture.WRAP_CLAMP_TO_EDGE;
        this.texTarget = this._cgl.gl.TEXTURE_2D;
        if (options && options.type) this.texTarget = options.type;
        this.textureType = Texture.TYPE_DEFAULT;
        this.unpackAlpha = true;
        this._fromData = true;

        this._glDataType = -1;
        this._glInternalFormat = -1;
        this._glDataFormat = -1;


        if (options)
        {
            if (options.isDepthTexture) this.textureType = Texture.TYPE_DEPTH;
            if (options.isFloatingPointTexture === true) this.textureType = Texture.TYPE_FLOAT;

            if ("textureType" in options) this.textureType = options.textureType;
            if ("filter" in options) this.filter = options.filter;
            if ("wrap" in options) this.wrap = options.wrap;
            if ("unpackAlpha" in options) this.unpackAlpha = options.unpackAlpha;
            if ("flip" in options) this.flip = options.flip;
            if ("shadowMap" in options) this.shadowMap = options.shadowMap;
            if ("anisotropic" in options) this.anisotropic = options.anisotropic;
        }
        else
        {
            options = {};
        }

        if (!options.pixelFormat && options.isFloatingPointTexture) this.pixelFormat = Texture.PFORMATSTR_RGBA32F;

        if (this.textureType == Texture.TYPE_DEPTH) this.pixelFormat = Texture.PFORMATSTR_DEPTH;

        this._cgl.profileData.profileTextureNew++;


        this.setFormat(Texture.setUpGlPixelFormat(this._cgl, this.pixelFormat));
        this._cgl.profileData.addHeavyEvent("texture created", this.name, options.width + "x" + options.height);

        this.setSize(options.width, options.height);
        this.getInfoOneLine();
    }



    isFloatingPoint()
    {
        return Texture.isPixelFormatFloat(this.pixelFormat);
    }

    /**
     * returns true if otherTexture has same options (width/height/filter/wrap etc)
     * @function compareSettings
     * @memberof Texture
     * @instance
     * @param {Texture} tex otherTexture
     * @returns {Boolean}
     */
    compareSettings(tex)
    {
    // if (!tex) { this._log.warn("compare: no tex"); return false; }
    // if (tex.width != this.width) this._log.warn("tex.width not equal", tex.width, this.width);
    // if (tex.height != this.height) this._log.warn("tex.height not equal", tex.height, this.height);
    // if (tex.filter != this.filter) this._log.warn("tex.filter not equal");
    // if (tex.wrap != this.wrap) this._log.warn("tex.wrap not equal");
    // if (tex.textureType != this.textureType) this._log.warn("tex.textureType not equal");
    // if (tex.unpackAlpha != this.unpackAlpha) this._log.warn("tex.unpackAlpha not equal");
    // if (tex.anisotropic != this.anisotropic) this._log.warn("tex.anisotropic not equal");
    // if (tex.shadowMap != this.shadowMap) this._log.warn("tex.shadowMap not equal");
    // if (tex.texTarget != this.texTarget) this._log.warn("tex.texTarget not equal");
    // if (tex.flip != this.flip) this._log.warn("tex.flip not equal");

        if (!tex) return false;
        return (
            tex.width == this.width &&
            tex.height == this.height &&
            tex.filter == this.filter &&
            tex.wrap == this.wrap &&
            tex.textureType == this.textureType &&
            tex.unpackAlpha == this.unpackAlpha &&
            tex.anisotropic == this.anisotropic &&
            tex.shadowMap == this.shadowMap &&
            tex.texTarget == this.texTarget &&
            tex.flip == this.flip
        );
    }

    /**
     * returns a new texture with the same settings (does not copy texture itself)
     * @function clone
     * @memberof Texture
     * @instance
     * @returns {Texture}
     */
    clone()
    {
        const newTex = new Texture(this._cgl, {
            "name": this.name,
            "filter": this.filter,
            "anisotropic": this.anisotropic,
            "wrap": this.wrap,
            "textureType": this.textureType,
            "pixelFormat": this.pixelFormat,
            "unpackAlpha": this.unpackAlpha,
            "flip": this.flip,
            "width": this.width,
            "height": this.height,
        });

        this._cgl.profileData.addHeavyEvent("texture created", this.name, this.width + "x" + this.height);

        if (!this.compareSettings(newTex))
        {
            this._log.error("Cloned texture settings do not compare!");
            this._log.error(this);
            this._log.error(newTex);
        }

        return newTex;
    }


    setFormat(o)
    {
        this.pixelFormat = o.pixelFormat;
        this._glDataFormat = o.glDataFormat;
        this._glInternalFormat = o.glInternalFormat;
        this._glDataType = o.glDataType;
    }



    /**
     * set pixel size of texture
     * @function setSize
     * @memberof Texture
     * @instance
     * @param {Number} w width
     * @param {Number} h height
     */
    setSize(w, h)
    {
        if (this._cgl.aborted) return;
        if (w != w || w <= 0 || !w) w = cgl_texture_DEFAULT_TEXTURE_SIZE;
        if (h != h || h <= 0 || !h) h = cgl_texture_DEFAULT_TEXTURE_SIZE;

        if (w > this._cgl.maxTexSize || h > this._cgl.maxTexSize) this._log.error("texture size too big! " + w + "x" + h + " / max: " + this._cgl.maxTexSize);

        w = Math.min(w, this._cgl.maxTexSize);
        h = Math.min(h, this._cgl.maxTexSize);

        w = Math.floor(w);
        h = Math.floor(h);
        if (this.width == w && this.height == h) return;

        w = this._cgl.checkTextureSize(w);
        h = this._cgl.checkTextureSize(h);

        this.width = w;
        this.height = h;
        this.deleted = false;

        this.setFormat(Texture.setUpGlPixelFormat(this._cgl, this.pixelFormat));

        this.shortInfoString = this.getInfoOneLine();// w + "x" + h + "";

        this._cgl.gl.bindTexture(this.texTarget, this.tex);
        this._cgl.profileData.profileTextureResize++;

        const uarr = null;

        this._cgl.gl.texImage2D(this.texTarget, 0, this._glInternalFormat, w, h, 0, this._glDataFormat, this._glDataType, uarr);

        this._setFilter();

        this.updateMipMap();

        this._cgl.gl.bindTexture(this.texTarget, null);
    }


    /**
     * @function initFromData
     * @memberof Texture
     * @instance
     * @description create texturem from rgb data
     * @param {Array<Number>} data rgb color array [r,g,b,a,r,g,b,a,...]
     * @param {Number} w width
     * @param {Number} h height
     * @param {Number} filter
     * @param {Number} wrap
     */
    initFromData(data, w, h, filter, wrap)
    {
        this.filter = filter;
        this.wrap = wrap;
        if (filter == undefined) this.filter = Texture.FILTER_LINEAR;
        if (wrap == undefined) this.wrap = Texture.WRAP_CLAMP_TO_EDGE;
        this.width = w;
        this.height = h;
        this._fromData = true;
        this.deleted = false;

        if (this.height > this._cgl.maxTexSize || this.width > this._cgl.maxTexSize)
        {
            const t = CGL.Texture.getTempTexture(this._cgl);
            this.width = t.width;
            this.height = t.height;
            this.tex = t.tex;
            this._log.warn("[cgl_texture] texture size too big!", this.width, this.height, this._cgl.maxTexSize);
            return;
        }

        if (this.flip) this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_FLIP_Y_WEBGL, this.flip);

        this._cgl.gl.bindTexture(this.texTarget, this.tex);

        this.setFormat(Texture.setUpGlPixelFormat(this._cgl, this.pixelFormat));

        this._cgl.gl.texImage2D(this.texTarget, 0, this._glInternalFormat, w, h, 0, this._glDataFormat, this._glDataType, data);

        this._setFilter();
        this.updateMipMap();

        if (this.flip) this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_FLIP_Y_WEBGL, false);
        this._cgl.gl.bindTexture(this.texTarget, null);
    }

    updateMipMap()
    {
        if ((this._cgl.glVersion == 2 || this.isPowerOfTwo()) && this.filter == Texture.FILTER_MIPMAP)
        {
            this._cgl.gl.generateMipmap(this.texTarget);
            this._cgl.profileData.profileGenMipMap++;
        }
    }

    /**
     * set texture data from an image/canvas object
     * @function initTexture
     * @memberof Texture
     * @instance
     * @param {Object} img image
     * @param {Number} filter
     */
    initTexture(img, filter)
    {
        this._cgl.printError("before initTexture");
        this._cgl.checkFrameStarted("texture inittexture");
        this._fromData = false;

        this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.unpackAlpha);
        if (img.width || img.videoWidth) this.width = img.videoWidth || img.width;
        if (img.height || img.videoHeight) this.height = img.videoHeight || img.height;

        if (filter !== undefined) this.filter = filter; // todo: can we remove this filter param?

        if (img.height > this._cgl.maxTexSize || img.width > this._cgl.maxTexSize)
        {
            const t = CGL.Texture.getTempTexture(this._cgl);
            this.width = t.width;
            this.height = t.height;
            this.tex = t.tex;
            this._log.warn("[cgl_texture] texture size too big!", img.width, img.height, this._cgl.maxTexSize);
            return;
        }

        this._cgl.gl.bindTexture(this.texTarget, this.tex);

        this.deleted = false;
        this.flipped = !this.flip;
        if (this.flipped) this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_FLIP_Y_WEBGL, this.flipped);


        this.setFormat(Texture.setUpGlPixelFormat(this._cgl, this.pixelFormat));

        this._cgl.gl.texImage2D(this.texTarget, 0, this._glInternalFormat, this._glDataFormat, this._glDataType, img);

        this._setFilter();
        this.updateMipMap();

        this._cgl.gl.bindTexture(this.texTarget, null);
        this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
        if (this.flipped) this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_FLIP_Y_WEBGL, false);

        this.getInfoOneLine();
        this._cgl.printError("initTexture");
    }

    /**
     * delete texture. use this when texture is no longer needed
     * @function delete
     * @memberof Texture
     * @instance
     */
    dispose()
    {
        this.delete();
    }

    delete()
    {
        if (this.loading)
        {
        // cant delete texture when still loading
        // setTimeout(this.delete.bind(this), 50);
            return;
        }

        this.deleted = true;
        this.width = 0;
        this.height = 0;
        this._cgl.profileData.profileTextureDelete++;
        this._cgl.gl.deleteTexture(this.tex);
        this.image = null;

        this.tex = null;
    }

    /**
     * @function isPowerOfTwo
     * @memberof Texture
     * @instance
     * @description return true if texture width and height are both power of two
     * @return {Boolean}
     */
    isPowerOfTwo()
    {
        return Texture.isPowerOfTwo(this.width) && Texture.isPowerOfTwo(this.height);
    }

    printInfo()
    {
        console.log(this.getInfo());
    }

    getInfoReadable()
    {
        const info = this.getInfo();
        let html = "";

        info.name = info.name.substr(0, info.name.indexOf("?rnd="));

        for (const i in info)
        {
            html += "* " + i + ":  **" + info[i] + "**\n";
        }

        return html;
    }

    getInfoOneLine()
    {
        let txt = "" + this.width + "x" + this.height;
        txt += " ";
        // if (this.textureType === CGL.Texture.TYPE_FLOAT) txt += " 32bit"; else txt += " 8bit";
        // if (this.textureType === CGL.Texture.TYPE_FLOAT) txt += " 32bit"; else txt += " 8bit";
        txt += this.pixelFormat;

        if (this.filter === CGL.Texture.FILTER_NEAREST) txt += " nearest";
        if (this.filter === CGL.Texture.FILTER_LINEAR) txt += " linear";
        if (this.filter === CGL.Texture.FILTER_MIPMAP) txt += " mipmap";

        if (this.wrap === CGL.Texture.WRAP_CLAMP_TO_EDGE) txt += " clamp";
        if (this.wrap === CGL.Texture.WRAP_REPEAT) txt += " repeat";
        if (this.wrap === CGL.Texture.WRAP_MIRRORED_REPEAT) txt += " repeatmir";

        this.shortInfoString = txt;

        return txt;
    }

    getInfoOneLineShort()
    {
        let txt = "" + this.width + "x" + this.height;
        // if (this.textureType === CGL.Texture.TYPE_FLOAT) txt += " 32bit"; else txt += " 8bit";
        txt += " ";
        txt += this.pixelFormat;

        this.shortInfoString = txt;

        return txt;
    }


    getInfo()
    {
        return Texture.getTexInfo(this);
    }


    _setFilter()
    {
        this._cgl.printError("before _setFilter");

        if (!this._fromData)
        {
            this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.unpackAlpha);
        }

        if (this.shadowMap)
        {
            this._cgl.gl.texParameteri(this._cgl.gl.TEXTURE_2D, this._cgl.gl.TEXTURE_COMPARE_MODE, this._cgl.gl.COMPARE_REF_TO_TEXTURE);
            this._cgl.gl.texParameteri(this._cgl.gl.TEXTURE_2D, this._cgl.gl.TEXTURE_COMPARE_FUNC, this._cgl.gl.LEQUAL);
        }

        if (this.textureType == Texture.TYPE_FLOAT && this.filter == Texture.FILTER_MIPMAP)
        {
            this.filter = Texture.FILTER_LINEAR;
            this._log.stack("texture: HDR and mipmap filtering at the same time is not possible");
        }

        if (this._cgl.glVersion == 1 && !this.isPowerOfTwo())
        {
            this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_MAG_FILTER, this._cgl.gl.NEAREST);
            this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_MIN_FILTER, this._cgl.gl.NEAREST);

            this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_WRAP_S, this._cgl.gl.CLAMP_TO_EDGE);
            this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_WRAP_T, this._cgl.gl.CLAMP_TO_EDGE);

            this.filter = Texture.FILTER_NEAREST;
            this.wrap = Texture.WRAP_CLAMP_TO_EDGE;
        }
        else
        {
            if (this.wrap == Texture.WRAP_CLAMP_TO_EDGE)
            {
                this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_WRAP_S, this._cgl.gl.CLAMP_TO_EDGE);
                this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_WRAP_T, this._cgl.gl.CLAMP_TO_EDGE);
            }
            else if (this.wrap == Texture.WRAP_REPEAT)
            {
                this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_WRAP_S, this._cgl.gl.REPEAT);
                this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_WRAP_T, this._cgl.gl.REPEAT);
            }
            else if (this.wrap == Texture.WRAP_MIRRORED_REPEAT)
            {
                this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_WRAP_S, this._cgl.gl.MIRRORED_REPEAT);
                this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_WRAP_T, this._cgl.gl.MIRRORED_REPEAT);
            }

            if (this.filter == Texture.FILTER_NEAREST)
            {
                this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_MAG_FILTER, this._cgl.gl.NEAREST);
                this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_MIN_FILTER, this._cgl.gl.NEAREST);
            }
            else if (this.filter == Texture.FILTER_LINEAR)
            {
                this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_MIN_FILTER, this._cgl.gl.LINEAR);
                this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_MAG_FILTER, this._cgl.gl.LINEAR);
            }
            else if (this.filter == Texture.FILTER_MIPMAP)
            {
                this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_MAG_FILTER, this._cgl.gl.LINEAR);
                this._cgl.gl.texParameteri(this.texTarget, this._cgl.gl.TEXTURE_MIN_FILTER, this._cgl.gl.LINEAR_MIPMAP_LINEAR);
            }
            else
            {
                this._log.log("unknown texture filter!", this.filter);
                throw new Error("unknown texture filter!" + this.filter);
            }

            if (this.anisotropic)
            {
                const ext = this._cgl.enableExtension("EXT_texture_filter_anisotropic");



                if (this._cgl.maxAnisotropic)
                {
                    const aniso = Math.min(this._cgl.maxAnisotropic, this.anisotropic);
                    this._cgl.gl.texParameterf(this._cgl.gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, aniso);
                }
            }
        }
        this.getInfoOneLine();
        this._cgl.printError("_setFilter");
    }
}


























/**
 * @function load
 * @static
 * @memberof Texture
 * @description load an image from an url
 * @param {Context} cgl
 * @param {String} url
 * @param {Function} finishedCallback
 * @param {Object} settings
 * @return {Texture}
 */
Texture.load = function (cgl, url, finishedCallback, settings)
{
    if (!url) return finishedCallback({ "error": true });
    let loadingId = null;
    if (!cgl.patch.loading.existByName(url)) loadingId = cgl.patch.loading.start("cgl.texture", url);

    const texture = new Texture(cgl);
    texture.name = url;

    texture.image = new Image();
    texture.image.crossOrigin = "anonymous";
    texture.loading = true;

    if (settings && settings.hasOwnProperty("filter")) texture.filter = settings.filter;
    if (settings && settings.hasOwnProperty("flip")) texture.flip = settings.flip;
    if (settings && settings.hasOwnProperty("wrap")) texture.wrap = settings.wrap;
    if (settings && settings.hasOwnProperty("anisotropic")) texture.anisotropic = settings.anisotropic;
    if (settings && settings.hasOwnProperty("unpackAlpha")) texture.unpackAlpha = settings.unpackAlpha;
    if (settings && settings.hasOwnProperty("pixelFormat")) texture.pixelFormat = settings.pixelFormat;

    texture.image.onabort = texture.image.onerror = (e) =>
    {
        console.warn("[cgl.texture.load] error loading texture", url, e);
        texture.loading = false;
        if (loadingId) cgl.patch.loading.finished(loadingId);
        const error = { "error": true };
        if (finishedCallback) finishedCallback(error, texture);
    };

    texture.image.onload = function (e)
    {
        cgl.addNextFrameOnceCallback(() =>
        {
            texture.initTexture(texture.image);
            if (loadingId) cgl.patch.loading.finished(loadingId);
            texture.loading = false;

            if (finishedCallback) finishedCallback(null, texture);
        });
    };
    texture.image.src = url;

    return texture;
};






/**
 * @static
 * @function getTempTexture
 * @memberof Texture
 * @description returns the default temporary texture (grey diagonal stipes)
 * @param {Context} cgl
 * @return {Texture}
 */
Texture.getTempTexture = function (cgl)
{
    if (!cgl) console.error("[getTempTexture] no cgl!");
    if (!cgl.tempTexture) cgl.tempTexture = Texture.getTemporaryTexture(cgl, 256, Texture.FILTER_LINEAR, Texture.REPEAT);
    return cgl.tempTexture;
};

/**
 * @static
 * @function getErrorTexture
 * @memberof Texture
 * @description returns the default temporary texture (grey diagonal stipes)
 * @param {Context} cgl
 * @return {Texture}
 */
Texture.getErrorTexture = function (cgl)
{
    if (!cgl) console.error("[getTempTexture] no cgl!");
    if (!cgl.errorTexture) cgl.errorTexture = Texture.getTemporaryTexture(cgl, 256, Texture.FILTER_LINEAR, Texture.REPEAT, 1, 0.2, 0.2);
    return cgl.errorTexture;
};


/**
 * @function getEmptyTexture
 * @memberof Texture
 * @instance
 * @param cgl
 * @param fp
 * @description returns a reference to a small empty (transparent) texture
 * @return {Texture}
 */
Texture.getEmptyTexture = function (cgl, fp)
{
    if (fp) return Texture.getEmptyTextureFloat(cgl);
    if (!cgl) console.error("[getEmptyTexture] no cgl!");
    if (cgl.tempTextureEmpty) return cgl.tempTextureEmpty;

    let size = 8;

    cgl.tempTextureEmpty = new Texture(cgl, { "name": "emptyTexture" });
    const data = Texture.getDefaultTextureData("empty", size);

    cgl.tempTextureEmpty.initFromData(data, size, size, Texture.FILTER_NEAREST, Texture.WRAP_REPEAT);

    return cgl.tempTextureEmpty;
};

/**
 * @function getEmptyTextureFloat
 * @memberof Texture
 * @instance
 * @param cgl
 * @description returns a reference to a small empty (transparent) 32bit texture
 * @return {Texture}
 */
Texture.getEmptyTextureFloat = function (cgl)
{
    if (!cgl) console.error("[getEmptyTextureFloat] no cgl!");
    if (cgl.tempTextureEmptyFloat) return cgl.tempTextureEmptyFloat;

    cgl.tempTextureEmptyFloat = new Texture(cgl, { "name": "emptyTexture", "isFloatingPointTexture": true });
    const data = new Float32Array(8 * 8 * 4).fill(1);
    for (let i = 0; i < 8 * 8 * 4; i += 4) data[i + 3] = 0;

    cgl.tempTextureEmptyFloat.initFromData(data, 8, 8, Texture.FILTER_NEAREST, Texture.WRAP_REPEAT);

    return cgl.tempTextureEmptyFloat;
};


/**
 * @function getRandomTexture
 * @memberof Texture
 * @static
 * @param cgl
 * @description returns a reference to a random texture
 * @return {Texture}
 */
Texture.getRandomTexture = function (cgl)
{
    if (!cgl) console.error("[getRandomTexture] no cgl!");
    if (cgl.randomTexture) return cgl.randomTexture;

    const size = 256;
    const data = Texture.getDefaultTextureData("randomUInt", size);

    cgl.randomTexture = new Texture(cgl);
    cgl.randomTexture.initFromData(data, size, size, Texture.FILTER_NEAREST, Texture.WRAP_REPEAT);

    return cgl.randomTexture;
};

/**
 * @function getRandomFloatTexture
 * @memberof Texture
 * @static
 * @param cgl
 * @description returns a reference to a texture containing random numbers between -1 and 1
 * @return {Texture}
 */
Texture.getRandomFloatTexture = function (cgl)
{
    if (!cgl) console.error("[getRandomTexture] no cgl!");
    if (cgl.getRandomFloatTexture) return cgl.getRandomFloatTexture;

    const size = 256;
    const data = Texture.getDefaultTextureData("randomFloat", size);

    cgl.getRandomFloatTexture = new Texture(cgl, { "isFloatingPointTexture": true });
    cgl.getRandomFloatTexture.initFromData(data, size, size, Texture.FILTER_NEAREST, Texture.WRAP_REPEAT);

    return cgl.getRandomFloatTexture;
};

/**
 * @function getBlackTexture
 * @memberof Texture
 * @static
 * @param cgl
 * @description returns a reference to a black texture
 * @return {Texture}
 */
Texture.getBlackTexture = function (cgl)
{
    if (!cgl) this._log.error("[getBlackTexture] no cgl!");
    if (cgl.blackTexture) return cgl.blackTexture;

    const size = 8;
    const data = Texture.getDefaultTextureData("color", size, { "r": 0, "g": 0, "b": 0 });

    cgl.blackTexture = new Texture(cgl);
    cgl.blackTexture.initFromData(data, size, size, Texture.FILTER_NEAREST, Texture.WRAP_REPEAT);

    return cgl.blackTexture;
};


/**
 * @function getEmptyCubemapTexture
 * @memberof Texture
 * @static
 * @param cgl
 * @description returns an empty cubemap texture with rgba = [0, 0, 0, 0]
 * @return {Texture}
 */
Texture.getEmptyCubemapTexture = function (cgl)
{
    const faces = [
        cgl.gl.TEXTURE_CUBE_MAP_POSITIVE_X,
        cgl.gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
        cgl.gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
        cgl.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
        cgl.gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
        cgl.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z
    ];

    const tex = cgl.gl.createTexture();
    const target = cgl.gl.TEXTURE_CUBE_MAP;
    const filter = Texture.FILTER_NEAREST;
    const wrap = Texture.WRAP_CLAMP_TO_EDGE;
    const width = 8;
    const height = 8;

    cgl.profileData.profileTextureNew++;


    cgl.gl.bindTexture(target, tex);
    cgl.profileData.profileTextureResize++;

    for (let i = 0; i < 6; i += 1)
    {
        const data = new Uint8Array(8 * 8 * 4);

        cgl.gl.texImage2D(faces[i], 0, cgl.gl.RGBA, 8, 8, 0, cgl.gl.RGBA, cgl.gl.UNSIGNED_BYTE, data);
        cgl.gl.texParameteri(target, cgl.gl.TEXTURE_MAG_FILTER, cgl.gl.NEAREST);
        cgl.gl.texParameteri(target, cgl.gl.TEXTURE_MIN_FILTER, cgl.gl.NEAREST);

        cgl.gl.texParameteri(target, cgl.gl.TEXTURE_WRAP_S, cgl.gl.CLAMP_TO_EDGE);
        cgl.gl.texParameteri(target, cgl.gl.TEXTURE_WRAP_T, cgl.gl.CLAMP_TO_EDGE);
    }


    cgl.gl.bindTexture(target, null);

    return {
        "id": CABLES.uuid(),
        "tex": tex,
        "cubemap": tex,
        "width": width,
        "height": height,
        "filter": filter,
        "wrap": wrap,
        "unpackAlpha": true,
        "flip": true,
        "_fromData": true,
        "name": "emptyCubemapTexture",
        "anisotropic": 0,
    };
};


Texture.getTempGradientTexture = function (cgl) // deprecated...
{
    if (!cgl) console.error("[getTempGradientTexture] no cgl!");
    return Texture.getTempTexture(cgl);
};

Texture.getTemporaryTexture = function (cgl, size, filter, wrap, r, g, b)
{
    const data = Texture.getDefaultTextureData("stripes", 256, { "r": r, "g": g, "b": b });
    const temptex = new Texture(cgl);
    temptex.initFromData(data, size, size, filter, wrap);
    return temptex;
};

/**
 * @static
 * @function createFromImage
 * @memberof Texture
 * @description create texturem from image data (e.g. image or canvas)
 * @param {Context} cgl
 * @param {Object} img image
 * @param {Object} options
 */
Texture.createFromImage = function (cgl, img, options)
{
    options = options || {};
    const texture = new Texture(cgl, options);
    texture.flip = false;
    texture.image = img;
    texture.width = img.videoWidth || img.width || 8;
    texture.height = img.videoHeight || img.height || 8;
    if (options.hasOwnProperty("wrap"))texture.wrap = options.wrap;

    texture.initTexture(img, options.filter);

    return texture;
};

// deprecated!
Texture.fromImage = function (cgl, img, filter, wrap)
{
    console.error("deprecated texture from image...");

    const texture = new Texture(cgl);
    texture.flip = false;
    if (filter) texture.filter = filter;
    if (wrap) texture.wrap = wrap;
    texture.image = img;
    texture.initTexture(img);
    return texture;
};

/**
 * @static
 * @function isPowerOfTwo
 * @memberof Texture
 * @description returns true if x is power of two
 * @param {Number} x
 * @return {Boolean}
 */
Texture.isPowerOfTwo = function (x)
{
    return x == 1 || x == 2 || x == 4 || x == 8 || x == 16 || x == 32 || x == 64 || x == 128 || x == 256 || x == 512 || x == 1024 || x == 2048 || x == 4096 || x == 8192 || x == 16384;
};

Texture.getTexInfo = function (tex)
{
    const obj = {};

    obj.name = tex.name;
    obj["power of two"] = tex.isPowerOfTwo();
    obj.size = tex.width + " x " + tex.height;

    let targetString = tex.texTarget;
    if (tex.texTarget == tex._cgl.gl.TEXTURE_2D) targetString = "TEXTURE_2D";
    obj.target = targetString;

    obj.unpackAlpha = tex.unpackAlpha;

    if (tex.cubemap)obj.cubemap = true;

    if (tex.textureType == Texture.TYPE_FLOAT) obj.textureType = "TYPE_FLOAT";
    if (tex.textureType == Texture.TYPE_HALF_FLOAT) obj.textureType = "TYPE_HALF_FLOAT";
    else if (tex.textureType == Texture.TYPE_DEPTH) obj.textureType = "TYPE_DEPTH";
    else if (tex.textureType == Texture.TYPE_DEFAULT) obj.textureType = "TYPE_DEFAULT";
    else obj.textureType = "UNKNOWN " + this.textureType;

    if (tex.wrap == Texture.WRAP_CLAMP_TO_EDGE) obj.wrap = "CLAMP_TO_EDGE";
    else if (tex.wrap == Texture.WRAP_REPEAT) obj.wrap = "WRAP_REPEAT";
    else if (tex.wrap == Texture.WRAP_MIRRORED_REPEAT) obj.wrap = "WRAP_MIRRORED_REPEAT";
    else obj.wrap = "UNKNOWN";

    if (tex.filter == Texture.FILTER_NEAREST) obj.filter = "FILTER_NEAREST";
    else if (tex.filter == Texture.FILTER_LINEAR) obj.filter = "FILTER_LINEAR";
    else if (tex.filter == Texture.FILTER_MIPMAP) obj.filter = "FILTER_MIPMAP";
    else obj.filter = "UNKNOWN";

    obj.pixelFormat = tex.pixelFormat || "unknown";

    return obj;
};

Texture.setUpGlPixelFormat = function (cgl, pixelFormatStr)
{
    const o = {};

    if (!pixelFormatStr)
    {
        cgl._log.error("no pixelformatstr!");
        cgl._log.log(new Error());
        pixelFormatStr = Texture.PFORMATSTR_RGBA8UB;
    }

    o.pixelFormatBase = pixelFormatStr;
    o.pixelFormat = pixelFormatStr;
    o.glDataType = cgl.gl.UNSIGNED_BYTE;
    o.glInternalFormat = cgl.gl.RGBA8;
    o.glDataFormat = cgl.gl.RGBA;

    let floatDatatype = cgl.gl.FLOAT;

    if (cgl.glUseHalfFloatTex)
    {
        if (pixelFormatStr == Texture.PFORMATSTR_RGBA32F) pixelFormatStr = Texture.PFORMATSTR_RGBA16F;
        if (pixelFormatStr == Texture.PFORMATSTR_RG32F) pixelFormatStr = Texture.PFORMATSTR_RG16F;
        if (pixelFormatStr == Texture.PFORMATSTR_R32F) pixelFormatStr = Texture.PFORMATSTR_R16F;
    }

    if (pixelFormatStr.contains("16bit"))
    {
        if (cgl.glVersion == 2)
        {
            // cgl.enableExtension("OES_texture_half_float");
            const hasExt = cgl.enableExtension("EXT_color_buffer_half_float");

            if (!hasExt)
            {
                console.warn("no 16bit extension, fallback to 32bit", pixelFormatStr);
                // fallback to 32 bit?
                if (pixelFormatStr == Texture.PFORMATSTR_RGBA16F) pixelFormatStr = Texture.PFORMATSTR_RGBA32F;
                if (pixelFormatStr == Texture.PFORMATSTR_RGB16F) pixelFormatStr = Texture.PFORMATSTR_RGB32F;
                if (pixelFormatStr == Texture.PFORMATSTR_RG16F) pixelFormatStr = Texture.PFORMATSTR_RG32F;
                if (pixelFormatStr == Texture.PFORMATSTR_R16F) pixelFormatStr = Texture.PFORMATSTR_R32F;
            }
            else
            {
                floatDatatype = cgl.gl.HALF_FLOAT;
            }
        }
    }

    if (cgl.glVersion == 1)
    {
        o.glInternalFormat = cgl.gl.RGBA;

        if (pixelFormatStr == Texture.PFORMATSTR_RGBA16F || pixelFormatStr == Texture.PFORMATSTR_RG16F || pixelFormatStr == Texture.PFORMATSTR_R16F)
        {
            const ext = cgl.enableExtension("OES_texture_half_float");
            if (!ext) throw new Error("no half float texture extension");

            floatDatatype = ext.HALF_FLOAT_OES;
        }
    }


    if (pixelFormatStr == Texture.PFORMATSTR_RGBA8UB)
    {
    }
    else if (pixelFormatStr == Texture.PFORMATSTR_RGB565)
    {
        o.glInternalFormat = cgl.gl.RGB565;
        o.glDataFormat = cgl.gl.RGB;
    }
    else if (pixelFormatStr == Texture.PFORMATSTR_R8UB)
    {
        o.glInternalFormat = cgl.gl.R8;
        o.glDataFormat = cgl.gl.RED;
    }
    else if (pixelFormatStr == Texture.PFORMATSTR_RG8UB)
    {
        o.glInternalFormat = cgl.gl.RG8;
        o.glDataFormat = cgl.gl.RG;
    }
    else if (pixelFormatStr == Texture.PFORMATSTR_RGB8UB)
    {
        o.glInternalFormat = cgl.gl.RGB8;
        o.glDataFormat = cgl.gl.RGB;
    }
    else if (pixelFormatStr == Texture.PFORMATSTR_SRGBA8)
    {
        o.glInternalFormat = cgl.gl.SRGB8_ALPHA8;
    }

    else if (pixelFormatStr == Texture.PFORMATSTR_R32F)
    {
        o.glInternalFormat = cgl.gl.R32F;
        o.glDataFormat = cgl.gl.RED;
        o.glDataType = floatDatatype;
    }
    else if (pixelFormatStr == Texture.PFORMATSTR_R16F)
    {
        o.glInternalFormat = cgl.gl.R16F;
        o.glDataType = floatDatatype;
        o.glDataFormat = cgl.gl.RED;
    }
    else if (pixelFormatStr == Texture.PFORMATSTR_RG16F)
    {
        o.glInternalFormat = cgl.gl.RG16F;
        o.glDataType = floatDatatype;
        o.glDataFormat = cgl.gl.RG;
    }
    else if (pixelFormatStr == Texture.PFORMATSTR_RGBA16F)
    {
        if (cgl.glVersion == 1) o.glInternalFormat = cgl.gl.RGBA;
        else o.glInternalFormat = cgl.gl.RGBA16F;
        o.glDataType = floatDatatype;
    }
    else if (pixelFormatStr == Texture.PFORMATSTR_R11FG11FB10F)
    {
        o.glInternalFormat = cgl.gl.R11F_G11F_B10F;
        o.glDataType = floatDatatype;
        o.glDataFormat = cgl.gl.RGB;
    }
    else if (pixelFormatStr == Texture.PFORMATSTR_RGBA32F)
    {
        if (cgl.glVersion == 1) o.glInternalFormat = cgl.gl.RGBA;
        else o.glInternalFormat = cgl.gl.RGBA32F;
        o.glDataType = floatDatatype;
    }
    else if (pixelFormatStr == Texture.PFORMATSTR_DEPTH)
    {
        if (cgl.glVersion == 1)
        {
            o.glInternalFormat = cgl.gl.DEPTH_COMPONENT;
            o.glDataType = cgl.gl.UNSIGNED_SHORT;
            o.glDataFormat = cgl.gl.DEPTH_COMPONENT;
        }
        else
        {
            o.glInternalFormat = cgl.gl.DEPTH_COMPONENT32F;
            o.glDataType = cgl.gl.FLOAT;
            o.glDataFormat = cgl.gl.DEPTH_COMPONENT;
        }
    }
    else
    {
        console.log("unknown pixelformat ", pixelFormatStr);
    }

    /// //////

    if (pixelFormatStr.contains("32bit") || pixelFormatStr == Texture.PFORMATSTR_R11FG11FB10F)
    {
        if (cgl.glVersion == 2) cgl.enableExtension("EXT_color_buffer_float");
        if (cgl.glVersion == 2) cgl.enableExtension("EXT_float_blend");

        cgl.enableExtension("OES_texture_float_linear"); // yes, i am sure, this is a webgl 1 and 2 ext
    }


    o.numColorChannels = Texture.getPixelFormatNumChannels(pixelFormatStr);


    if (!o.glDataType || !o.glInternalFormat || !o.glDataFormat) console.log("pixelformat wrong ?!", pixelFormatStr, o.glDataType, o.glInternalFormat, o.glDataFormat, this);

    return o;
};



Texture.getPixelFormatNumChannels =
    (pxlFrmtStr) =>
    {
        if (pxlFrmtStr.startsWith("RGBA")) return 4;
        if (pxlFrmtStr.startsWith("RGB")) return 3;
        if (pxlFrmtStr.startsWith("RG")) return 2;
        return 1;
    };

Texture.isPixelFormatFloat =
    (pxlFrmtStr) =>
    {
        return (pxlFrmtStr || "").contains("float");
    };

Texture.isPixelFormatHalfFloat =
    (pxlFrmtStr) =>
    {
        return (pxlFrmtStr || "").contains("float") && (pxlFrmtStr || "").contains("16bit");
    };






;// CONCATENATED MODULE: ./src/core/cg/cg_boundingbox.js


/**
 * bounding box
 *
 * @namespace external:CGL
 * @param {Geometry} geometry or bounding box
 */
class BoundingBox
{
    constructor(geom)
    {
        this._init();
        this._first = true;
        this._wireMesh = null;

        if (geom) this.apply(geom);
    }

    _init()
    {
        this._max = [-0, -0, -0];
        this._min = [0, 0, 0];
        this._center = [0, 0, 0];
        this._size = [0, 0, 0];
        this._maxAxis = 0.0;
        this._first = true;
    }

    /**
     * get biggest number of maxX,maxY,maxZ
     * @type {Number}
     */
    get maxAxis() { return this._maxAxis || 1; }

    /**
     * size of bounding box
     * @type {vec3}
     */
    get size() { return this._size; }

    /**
     * center of bounding box
     * @type {vec3}
     */
    get center() { return this._center; }

    /**
     * center x
     * @type {Number}
     */
    get x() { return this._center[0]; }

    /**
     * center y
     * @type {Number}
     */
    get y() { return this._center[1]; }

    /**
     * center z
     * @type {Number}
     */
    get z() { return this._center[2]; }


    /**
     * minimum x
     * @type {Number}
     */
    get minX() { return this._min[0]; }

    /**
     * minimum y
     * @type {Number}
     */
    get minY() { return this._min[1]; }

    /**
     * minimum z
     * @type {Number}
     */
    get minZ() { return this._min[2]; }

    /**
     * maximum x
     * @type {Number}
     */
    get maxX() { return this._max[0]; }

    /**
     * maximum y
     * @type {Number}
     */
    get maxY() { return this._max[1]; }

    /**
     * maximum z
     * @type {Number}
     */
    get maxZ() { return this._max[2]; }


    apply(geom, mat)
    {
        if (!geom)
        {
            // console.warn("[boundingbox] no geom/vertices", geom);
            return;
        }

        if (geom instanceof BoundingBox)
        {
            const bb = geom;

            this.applyPos(bb.maxX, bb.maxY, bb.maxZ);
            this.applyPos(bb.minX, bb.minY, bb.minZ);
        }
        else
        {
            for (let i = 0; i < geom.vertices.length; i += 3)
                this.applyPos(geom.vertices[i], geom.vertices[i + 1], geom.vertices[i + 2]);
        }
        this.calcCenterSize();
    }

    /**
     * returns a copy of the bounding box
     * @function copy
     * @memberof BoundingBox
     * @instance
     */
    copy()
    {
        return new BoundingBox(this);
    }

    get changed()
    {
        return !(this._max[0] == -Number.MAX_VALUE && this._max[1] == -Number.MAX_VALUE && this._max[2] == -Number.MAX_VALUE);
    }

    applyPos(x, y, z)
    {
        if (x == Number.MAX_VALUE || x == -Number.MAX_VALUE ||
            y == Number.MAX_VALUE || y == -Number.MAX_VALUE ||
            z == Number.MAX_VALUE || z == -Number.MAX_VALUE) return;

        if (!CABLES.UTILS.isNumeric(x) || !CABLES.UTILS.isNumeric(y) || !CABLES.UTILS.isNumeric(z)) return;

        if (this._first)
        {
            this._max[0] = x;
            this._max[1] = y;
            this._max[2] = z;

            this._min[0] = x;
            this._min[1] = y;
            this._min[2] = z;
            this._first = false;
            return;
        }

        this._max[0] = Math.max(this._max[0], x);
        this._max[1] = Math.max(this._max[1], y);
        this._max[2] = Math.max(this._max[2], z);

        this._min[0] = Math.min(this._min[0], x);
        this._min[1] = Math.min(this._min[1], y);
        this._min[2] = Math.min(this._min[2], z);
    }

    calcCenterSize()
    {
        if (this._first) return;


        this._size[0] = this._max[0] - this._min[0];
        this._size[1] = this._max[1] - this._min[1];
        this._size[2] = this._max[2] - this._min[2];

        this._center[0] = (this._min[0] + this._max[0]) / 2;
        this._center[1] = (this._min[1] + this._max[1]) / 2;
        this._center[2] = (this._min[2] + this._max[2]) / 2;

        this._maxAxis = Math.max(this._size[2], Math.max(this._size[0], this._size[1]));
    }

    mulMat4(m)
    {
        if (this._first)
        {
            this._max[0] = 0;
            this._max[1] = 0;
            this._max[2] = 0;

            this._min[0] = 0;
            this._min[1] = 0;
            this._min[2] = 0;
            this._first = false;
        }
        vec3.transformMat4(this._max, this._max, m);
        vec3.transformMat4(this._min, this._min, m);
        this.calcCenterSize();
    }

    render(cgl, shader, op)
    {
        if (!this._wireMesh) this._wireMesh = new CGL.WireCube(cgl);

        cgl.pushModelMatrix();
        mat4.translate(cgl.mMatrix, cgl.mMatrix, this._center);

        if (CABLES.UI && op)
        {
            CABLES.UI.OverlayMeshes.drawCube(op, this._size[0] / 2, this._size[1] / 2, this._size[2] / 2);
        }

        cgl.popModelMatrix();
    }
}

;// CONCATENATED MODULE: ./src/core/cg/cg_geom.js
// import { vec2, vec3 } from "gl-matrix";




/**
 * a geometry contains all information about a mesh, vertices, texturecoordinates etc. etc.
 * @namespace external:CGL#Geometry
 * @param {String} name
 * @class
 * @example
 * // create a triangle with all attributes
 * const geom=new Geometry("triangle"),
 *
 * geom.vertices = [
 *      0.0,           sizeH.get(),  0.0,
 *     -sizeW.get(),  -sizeH.get(),  0.0,
 *      sizeW.get(),  -sizeH.get(),  0.0 ];
 *
 * geom.vertexNormals = [
 *      0.0,  0.0,  1.0,
 *      0.0,  0.0,  1.0,
 *      0.0,  0.0,  1.0 ];
 *
 * geom.tangents = [
 *     1,0,0,
 *     1,0,0,
 *     1,0,0 ];
 *
 * geom.biTangents = [
 *     0,1,0,
 *     0,1,0,
 *     0,1,0 ];
 *
 * geom.texCoords = [
 *      0.5,  0.0,
 *      1.0,  1.0,
 *      0.0,  1.0, ];
 *
 * geom.verticesIndices = [
 *     0, 1, 2 ];
 *
 */
const Geometry = function (name)
{
    this.name = name || "unknown";
    this._log = new Logger("cgl_geometry");

    this.faceVertCount = 3;
    this.glPrimitive = null;
    this._attributes = {};

    this._vertices = [];
    this.verticesIndices = [];

    this.isGeometry = true;

    this.morphTargets = [];

    Object.defineProperty(this, "vertices", {
        get()
        {
            return this._vertices;
        },
        set(v)
        {
            this.setVertices(v);
        },
    });

    Object.defineProperty(this, "texCoords", {
        get()
        {
            const att = this.getAttribute("texCoords");
            if (!att) return [];
            return att.data;
        },
        set(v)
        {
            this.setAttribute("texCoords", v, 2);
        },
    });

    Object.defineProperty(this, "vertexNormals", {
        get()
        {
            const att = this.getAttribute("vertexNormals");
            if (!att) return [];
            return att.data;
        },
        set(v)
        {
            this.setAttribute("vertexNormals", v, 3);
        },
    });

    Object.defineProperty(this, "tangents", {
        get()
        {
            const att = this.getAttribute("tangents");
            if (!att) return [];
            return att.data;
        },
        set(v)
        {
            this.setAttribute("tangents", v, 3);
        },
    });

    Object.defineProperty(this, "biTangents", {
        get()
        {
            const att = this.getAttribute("biTangents");
            if (!att) return [];
            return att.data;
        },
        set(v)
        {
            this.setAttribute("biTangents", v, 3);
        },
    });

    Object.defineProperty(this, "vertexColors", {
        get()
        {
            const att = this.getAttribute("vertexColors");
            if (!att) return [];
            return att.data;
        },
        set(v)
        {
            this.setAttribute("vertexColors", v, 4);
        },
    });
};

/**
 * @function clear
 * @memberof Geometry
 * @instance
 * @description clear all buffers/set them to length 0
 */
Geometry.prototype.clear = function ()
{
    this._vertices = new Float32Array([]);
    this.verticesIndices = [];
    this.texCoords = new Float32Array([]);
    this.vertexNormals = new Float32Array([]);
    this.tangents = [];
    this.biTangents = [];
    this._attributes = {};
};



/**
 * @function getAttributes
   @memberof Geometry
 * @instance
 * @return {Array<Object>} returns array of attribute objects
 */
Geometry.prototype.getAttributes = function ()
{
    return this._attributes;
};

/**
 * @function getAttribute
 * @memberof Geometry
 * @instance
 * @param {String} name
 * @return {Object}
 */
Geometry.prototype.getAttribute = function (name)
{
    for (const i in this._attributes)
    {
        if (this._attributes[i].name == name) return this._attributes[i];
    }
    return null;
};

/**
 * @function setAttribute
 * @description create an attribute
 * @memberof Geometry
 * @instance
 * @param {String} name
 * @param {Array} arr
 * @param {Number} itemSize
 */
Geometry.prototype.setAttribute = function (name, arr, itemSize)
{
    let attrType = "";
    if (!itemSize || itemSize > 4)
    {
        console.log("itemsize wrong?", itemSize, name);
        this._log.stack("itemsize");

        itemSize = 3;
    }

    if (itemSize == 1) attrType = "float";
    else if (itemSize == 2) attrType = "vec2";
    else if (itemSize == 3) attrType = "vec3";
    else if (itemSize == 4) attrType = "vec4";


    const attr = {
        "name": name,
        "data": arr,
        "itemSize": itemSize,
        "type": attrType,
    };

    this._attributes[name] = attr;
};

Geometry.prototype.copyAttribute = function (name, newgeom)
{
    const attr = this.getAttribute(name);
    newgeom.setAttribute(name, new Float32Array(attr.data), attr.itemSize);
};


/**
 * @function setVertices
 * @memberof Geometry
 * @instance
 * @description set vertices
 * @param {Array|Float32Array} arr [x,y,z,x,y,z,...]
 */
Geometry.prototype.setVertices = function (arr)
{
    if (arr instanceof Float32Array) this._vertices = arr;
    else this._vertices = new Float32Array(arr);
};

/**
 * @function setTexCoords
 * @memberof Geometry
 * @instance
 * @description set texcoords
 * @param {Array|Float32Array} arr [u,v,u,v,...]
 */
Geometry.prototype.setTexCoords = function (arr)
{
    if (arr instanceof Float32Array) this.texCoords = arr;
    else this.texCoords = new Float32Array(arr);
};

// Geometry.prototype.testIndices = function ()
// {
//     var foundError = false;
//     for (var i = 0; i < this.verticesIndices.length; i++)
//     {
//         if (this.verticesIndices[i * 3 + 0] >= this._vertices.length / 3 || this.verticesIndices[i * 3 + 1] >= this._vertices.length / 3 || this.verticesIndices[i * 3 + 2] >= this._vertices.length / 3)
//         {
//             foundError = true;
//             console.log("index error!");
//         }
//     }
// };

// deprecated
Geometry.prototype.calcNormals = function (smooth)
{
    const options = { "smooth": smooth };
    this.calculateNormals(options);
};

/**
 * @function flipNormals
 * @memberof Geometry
 * @param x
 * @param y
 * @param z
 * @description flip normals
 */
Geometry.prototype.flipNormals = function (x, y, z)
{
    let vec = vec3.create();

    if (x == undefined)x = 1;
    if (y == undefined)y = 1;
    if (z == undefined)z = 1;


    for (let i = 0; i < this.vertexNormals.length; i += 3)
    {
        vec3.set(vec,
            this.vertexNormals[i + 0],
            this.vertexNormals[i + 1],
            this.vertexNormals[i + 2]);

        vec[0] *= -x;
        vec[1] *= -y;
        vec[2] *= -z;

        vec3.normalize(vec, vec);

        this.vertexNormals[i + 0] = vec[0];
        this.vertexNormals[i + 1] = vec[1];
        this.vertexNormals[i + 2] = vec[2];
    }
};

Geometry.prototype.getNumTriangles = function ()
{
    if (this.verticesIndices && this.verticesIndices.length) return this.verticesIndices.length / 3;
    return this.vertices.length / 3;
};


/**
 * @function flipVertDir
 * @memberof Geometry
 * @description flip order of vertices in geom faces
 */
Geometry.prototype.flipVertDir = function ()
{
    const newInd = [];
    newInd.length = this.verticesIndices.length;
    for (let i = 0; i < this.verticesIndices.length; i += 3)
    {
        newInd[i] = this.verticesIndices[i + 2];
        newInd[i + 1] = this.verticesIndices[i + 1];
        newInd[i + 2] = this.verticesIndices[i];
    }
    this.verticesIndices = newInd;
};


Geometry.prototype.setPointVertices = function (verts)
{
    if (verts.length % 3 !== 0)
    {
        this._log.error("SetPointVertices: Array must be multiple of three.");
        return;
    }

    if (!(verts instanceof Float32Array)) this.vertices = new Float32Array(verts);
    else this.vertices = verts;

    if (!(this.texCoords instanceof Float32Array)) this.texCoords = new Float32Array((verts.length / 3) * 2);

    // this.texCoords.length=verts.length/3*2;
    this.verticesIndices.length = verts.length / 3;
    // this.verticesIndices=[];

    for (let i = 0; i < verts.length / 3; i++)
    {
        this.verticesIndices[i] = i;
        this.texCoords[i * 2] = 0;
        this.texCoords[i * 2 + 1] = 0;
    }
};

/**
 * merge a different geometry into the this geometry
 * @function merge
 * @param {Geometry} geom
 * @memberof Geometry
 * @instance
 */
Geometry.prototype.merge = function (geom)
{
    if (!geom) return;

    if (this.isIndexed() != geom.isIndexed())
    {
        if (this.isIndexed())
        {
            this.unIndex(false, true);
        }
        if (geom.isIndexed())
        {
            const g = geom.copy();
            g.unIndex(false, true);
            geom = g;
        }
    }

    const oldIndizesLength = this.verticesIndices.length;
    const vertLength = this._vertices.length / 3;

    this.verticesIndices.length += geom.verticesIndices.length;
    for (let i = 0; i < geom.verticesIndices.length; i++)
        this.verticesIndices[oldIndizesLength + i] = geom.verticesIndices[i] + vertLength;

    this.vertices = UTILS.float32Concat(this._vertices, geom.vertices);
    this.texCoords = UTILS.float32Concat(this.texCoords, geom.texCoords);
    this.vertexNormals = UTILS.float32Concat(this.vertexNormals, geom.vertexNormals);
    this.tangents = UTILS.float32Concat(this.tangents, geom.tangents);
    this.biTangents = UTILS.float32Concat(this.biTangents, geom.biTangents);
};

/**
 *   a copy of the geometry
 * @function copy
 * @memberof Geometry
 * @instance
 */
Geometry.prototype.copy = function ()
{
    const geom = new Geometry(this.name + " copy");
    geom.faceVertCount = this.faceVertCount;
    geom.glPrimitive = this.glPrimitive;

    geom.setVertices(this._vertices.slice(0));

    if (this.verticesIndices)
    {
        geom.verticesIndices.length = this.verticesIndices.length;
        for (let i = 0; i < this.verticesIndices.length; i++) geom.verticesIndices[i] = this.verticesIndices[i];
    }

    for (let i in this._attributes) this.copyAttribute(i, geom);

    geom.morphTargets.length = this.morphTargets.length;
    for (let i = 0; i < this.morphTargets.length; i++) geom.morphTargets[i] = this.morphTargets[i];

    return geom;
};

/**
 * Calculaten normals
 * @function calculateNormals
 * @memberof Geometry
 * @param options
 * @instance
 */
Geometry.prototype.calculateNormals = function (options)
{
    // todo: should check angle of normals to get edges    https://community.khronos.org/t/calculating-accurate-vertex-normals/28152
    options = options || {};
    if (options.smooth === false) this.unIndex();

    const u = vec3.create();
    const v = vec3.create();
    const n = vec3.create();

    function calcNormal(triangle)
    {
        vec3.subtract(u, triangle[0], triangle[1]);
        vec3.subtract(v, triangle[0], triangle[2]);
        vec3.cross(n, u, v);
        vec3.normalize(n, n);

        if (options && options.forceZUp)
        {
            if (n[2] < 0)
            {
                n[0] *= -1;
                n[1] *= -1;
                n[2] *= -1;
            }
        }
        return n;
    }

    this.getVertexVec = function (which)
    {
        const vec = [0, 0, 0];
        vec[0] = this.vertices[which * 3 + 0];
        vec[1] = this.vertices[which * 3 + 1];
        vec[2] = this.vertices[which * 3 + 2];
        return vec;
    };

    if (!(this.vertexNormals instanceof Float32Array) || this.vertexNormals.length != this.vertices.length) this.vertexNormals = new Float32Array(this.vertices.length);

    for (let i = 0; i < this.vertices.length; i++)
    {
        this.vertexNormals[i] = 0;
    }

    if (!this.isIndexed())
    {
        const norms = [];
        for (let i = 0; i < this.vertices.length; i += 9)
        {
            const triangle = [[this.vertices[i + 0], this.vertices[i + 1], this.vertices[i + 2]], [this.vertices[i + 3], this.vertices[i + 4], this.vertices[i + 5]], [this.vertices[i + 6], this.vertices[i + 7], this.vertices[i + 8]]];
            const nn = calcNormal(triangle);
            norms.push(nn[0], nn[1], nn[2], nn[0], nn[1], nn[2], nn[0], nn[1], nn[2]);
        }
        this.vertexNormals = norms;
    }
    else
    {
        const faceNormals = [];

        faceNormals.length = Math.floor(this.verticesIndices.length / 3);

        for (let i = 0; i < this.verticesIndices.length; i += 3)
        {
            const triangle = [this.getVertexVec(this.verticesIndices[i + 0]), this.getVertexVec(this.verticesIndices[i + 1]), this.getVertexVec(this.verticesIndices[i + 2])];

            faceNormals[i / 3] = calcNormal(triangle);

            this.vertexNormals[this.verticesIndices[i + 0] * 3 + 0] += faceNormals[i / 3][0];
            this.vertexNormals[this.verticesIndices[i + 0] * 3 + 1] += faceNormals[i / 3][1];
            this.vertexNormals[this.verticesIndices[i + 0] * 3 + 2] += faceNormals[i / 3][2];

            this.vertexNormals[this.verticesIndices[i + 1] * 3 + 0] += faceNormals[i / 3][0];
            this.vertexNormals[this.verticesIndices[i + 1] * 3 + 1] += faceNormals[i / 3][1];
            this.vertexNormals[this.verticesIndices[i + 1] * 3 + 2] += faceNormals[i / 3][2];

            this.vertexNormals[this.verticesIndices[i + 2] * 3 + 0] += faceNormals[i / 3][0];
            this.vertexNormals[this.verticesIndices[i + 2] * 3 + 1] += faceNormals[i / 3][1];
            this.vertexNormals[this.verticesIndices[i + 2] * 3 + 2] += faceNormals[i / 3][2];
        }


        for (let i = 0; i < this.verticesIndices.length; i += 3) // faces
        {
            for (let k = 0; k < 3; k++) // triangles
            {
                const vv = [this.vertexNormals[this.verticesIndices[i + k] * 3 + 0], this.vertexNormals[this.verticesIndices[i + k] * 3 + 1], this.vertexNormals[this.verticesIndices[i + k] * 3 + 2]];
                vec3.normalize(vv, vv);
                this.vertexNormals[this.verticesIndices[i + k] * 3 + 0] = vv[0];
                this.vertexNormals[this.verticesIndices[i + k] * 3 + 1] = vv[1];
                this.vertexNormals[this.verticesIndices[i + k] * 3 + 2] = vv[2];
            }
        }
    }
};

/**
 * Calculates tangents & bitangents with the help of uv-coordinates. Adapted from
 * Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”.
 * Terathon Software 3D Graphics Library.
 * https://fenix.tecnico.ulisboa.pt/downloadFile/845043405449073/Tangent%20Space%20Calculation.pdf
 *
 * @function calcTangentsBitangents
 * @memberof Geometry
 * @instance
 */
Geometry.prototype.calcTangentsBitangents = function ()
{
    if (!this.vertices.length)
    {
        // this._log.error("Cannot calculate tangents/bitangents without vertices.");
        return;
    }
    if (!this.vertexNormals.length)
    {
        // this._log.error("Cannot calculate tangents/bitangents without normals.");
        return;
    }
    if (!this.texCoords.length)
    {
        // console.warn("No texcoords. Replacing with default values [0, 0].");
        const texCoordLength = (this.vertices.length / 3) * 2;
        this.texCoords = new Float32Array(texCoordLength);
        for (let i = 0; i < texCoordLength; i += 1) this.texCoords[i] = 0;
    }
    if (!this.verticesIndices || !this.verticesIndices.length)
    {
        // this._log.error("Cannot calculate tangents/bitangents without vertex indices.");
        return;
    }
    // this code assumes that we have three indices per triangle
    if (this.verticesIndices.length % 3 !== 0)
    {
        this._log.error("Vertex indices mismatch!");
        return;
    }

    const triangleCount = this.verticesIndices.length / 3;
    const vertexCount = this.vertices.length / 3;

    this.tangents = new Float32Array(this.vertexNormals.length);
    this.biTangents = new Float32Array(this.vertexNormals.length);

    // temporary buffers
    const tempVertices = [];
    tempVertices.length = vertexCount * 2;
    const v1 = vec3.create();
    const v2 = vec3.create();
    const v3 = vec3.create();

    const w1 = vec2.create();
    const w2 = vec2.create();
    const w3 = vec2.create();

    const sdir = vec3.create();
    const tdir = vec3.create();

    // for details on calculation, see article referenced above
    for (let tri = 0; tri < triangleCount; tri += 1)
    {
        // indices of the three vertices for a triangle
        const i1 = this.verticesIndices[tri * 3];
        const i2 = this.verticesIndices[tri * 3 + 1];
        const i3 = this.verticesIndices[tri * 3 + 2];

        // vertex position as vec3
        vec3.set(v1, this.vertices[i1 * 3], this.vertices[i1 * 3 + 1], this.vertices[i1 * 3 + 2]);
        vec3.set(v2, this.vertices[i2 * 3], this.vertices[i2 * 3 + 1], this.vertices[i2 * 3 + 2]);
        vec3.set(v3, this.vertices[i3 * 3], this.vertices[i3 * 3 + 1], this.vertices[i3 * 3 + 2]);

        // texture coordinate as vec2
        vec2.set(w1, this.texCoords[i1 * 2], this.texCoords[i1 * 2 + 1]);
        vec2.set(w2, this.texCoords[i2 * 2], this.texCoords[i2 * 2 + 1]);
        vec2.set(w3, this.texCoords[i3 * 2], this.texCoords[i3 * 2 + 1]);

        const x1 = v2[0] - v1[0];
        const x2 = v3[0] - v1[0];
        const y1 = v2[1] - v1[1];
        const y2 = v3[1] - v1[1];
        const z1 = v2[2] - v1[2];
        const z2 = v3[2] - v1[2];

        const s1 = w2[0] - w1[0];
        const s2 = w3[0] - w1[0];
        const t1 = w2[1] - w1[1];
        const t2 = w3[1] - w1[1];

        const r = 1.0 / (s1 * t2 - s2 * t1);

        vec3.set(sdir, (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
        vec3.set(tdir, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);

        tempVertices[i1] = sdir;
        tempVertices[i2] = sdir;
        tempVertices[i3] = sdir;

        tempVertices[i1 + vertexCount] = tdir;
        tempVertices[i2 + vertexCount] = tdir;
        tempVertices[i3 + vertexCount] = tdir;
    }

    const normal = vec3.create();
    const tempVert = vec3.create();
    const tan = vec3.create();
    const bitan = vec3.create();
    const temp1 = vec3.create();
    const temp2 = vec3.create();
    const crossPd = vec3.create();
    const normalized = vec3.create();

    for (let vert = 0; vert < vertexCount; vert += 1)
    {
        // NOTE: some meshes don't have index 0 - n in their indexbuffer, if this is the case, skip calculation of this vertex
        if (!tempVertices[vert]) continue;

        vec3.set(normal, this.vertexNormals[vert * 3], this.vertexNormals[vert * 3 + 1], this.vertexNormals[vert * 3 + 2]);
        vec3.set(tempVert, tempVertices[vert][0], tempVertices[vert][1], tempVertices[vert][2]);

        // Gram-Schmidt orthagonalize
        const _dp = vec3.dot(normal, tempVert);
        vec3.scale(temp1, normal, _dp);
        vec3.subtract(temp2, tempVert, temp1);

        vec3.normalize(normalized, temp2);
        vec3.cross(crossPd, normal, tempVert);

        // const intermDot = vec3.dot(crossPd, tempVertices[vert + vertexCount]);
        const w = 1.0;// intermDot < 0.0 ? -1.0 : 1.0;

        vec3.scale(tan, normalized, 1 / w);
        vec3.cross(bitan, normal, tan);

        this.tangents[vert * 3 + 0] = tan[0];
        this.tangents[vert * 3 + 1] = tan[1];
        this.tangents[vert * 3 + 2] = tan[2];
        this.biTangents[vert * 3 + 0] = bitan[0];
        this.biTangents[vert * 3 + 1] = bitan[1];
        this.biTangents[vert * 3 + 2] = bitan[2];
    }
};

Geometry.prototype.isIndexed = function ()
{
    if (this._vertices.length == 0) return true;
    return this.verticesIndices.length != 0;
};

/**
 * @function unIndex
 * @memberof Geometry
 * @instance
 * @description remove all vertex indizes, vertices array will contain 3*XYZ for every triangle
 * @param {boolean} reIndex
 * @param {boolean} dontCalcNormals
 */
Geometry.prototype.unIndex = function (reIndex, dontCalcNormals)
{
    const newVerts = [];
    const newIndizes = [];
    let count = 0;

    for (let j in this._attributes)
    {
        const attr = this._attributes[j];
        let na = [];

        for (let i = 0; i < this.verticesIndices.length; i += 3)
        {
            for (let s = 0; s < 3; s++)
            {
                if (attr.itemSize == 3)
                    na.push(
                        attr.data[this.verticesIndices[i + s] * 3 + 0],
                        attr.data[this.verticesIndices[i + s] * 3 + 1],
                        attr.data[this.verticesIndices[i + s] * 3 + 2]);
                else if (attr.itemSize == 4)
                    na.push(
                        attr.data[this.verticesIndices[i + s] * 4 + 0],
                        attr.data[this.verticesIndices[i + s] * 4 + 1],
                        attr.data[this.verticesIndices[i + s] * 4 + 2],
                        attr.data[this.verticesIndices[i + s] * 4 + 3]);
                else if (attr.itemSize == 2)
                    na.push(
                        attr.data[this.verticesIndices[i + s] * 2 + 0],
                        attr.data[this.verticesIndices[i + s] * 2 + 1]);
                else if (attr.itemSize == 1)
                    na.push(
                        attr.data[this.verticesIndices[i + s]]);
                else console.log("unknown attr", attr);
            }
        }
        this.setAttribute(attr.name, na, attr.itemSize);
    }

    for (let i = 0; i < this.verticesIndices.length; i += 3)
    {
        newVerts.push(
            this.vertices[this.verticesIndices[i + 0] * 3 + 0],
            this.vertices[this.verticesIndices[i + 0] * 3 + 1],
            this.vertices[this.verticesIndices[i + 0] * 3 + 2]);

        newIndizes.push(count);
        count++;

        newVerts.push(
            this.vertices[this.verticesIndices[i + 1] * 3 + 0],
            this.vertices[this.verticesIndices[i + 1] * 3 + 1],
            this.vertices[this.verticesIndices[i + 1] * 3 + 2]);

        newIndizes.push(count);
        count++;

        newVerts.push(
            this.vertices[this.verticesIndices[i + 2] * 3 + 0],
            this.vertices[this.verticesIndices[i + 2] * 3 + 1],
            this.vertices[this.verticesIndices[i + 2] * 3 + 2]);

        newIndizes.push(count);
        count++;
    }

    this.vertices = newVerts;

    this.verticesIndices = [];
    if (reIndex) this.verticesIndices = newIndizes;

    if (!dontCalcNormals) this.calculateNormals();
};

Geometry.prototype.calcBarycentric = function ()
{
    let barycentrics = [];
    barycentrics.length = this.vertices.length;
    for (let i = 0; i < this.vertices.length; i++) barycentrics[i] = 0;

    let count = 0;
    for (let i = 0; i < this.vertices.length; i += 3)
    {
        barycentrics[i + count] = 1;
        count++;
        if (count == 3) count = 0;
    }

    this.setAttribute("attrBarycentric", barycentrics, 3);
};

Geometry.prototype.getBounds = function ()
{
    return new BoundingBox(this);
};

Geometry.prototype.center = function (x, y, z)
{
    if (x === undefined)
    {
        x = true;
        y = true;
        z = true;
    }

    let i = 0;
    const bounds = this.getBounds();
    const offset = [bounds.minX + (bounds.maxX - bounds.minX) / 2, bounds.minY + (bounds.maxY - bounds.minY) / 2, bounds.minZ + (bounds.maxZ - bounds.minZ) / 2];

    for (i = 0; i < this.vertices.length; i += 3)
    {
        if (this.vertices[i + 0] == this.vertices[i + 0])
        {
            if (x) this.vertices[i + 0] -= offset[0];
            if (y) this.vertices[i + 1] -= offset[1];
            if (z) this.vertices[i + 2] -= offset[2];
        }
    }

    return offset;
};

Geometry.prototype.mapTexCoords2d = function ()
{
    const bounds = this.getBounds();
    const num = this.vertices.length / 3;

    this.texCoords = new Float32Array(num * 2);

    for (let i = 0; i < num; i++)
    {
        const vertX = this.vertices[i * 3 + 0];
        const vertY = this.vertices[i * 3 + 1];
        this.texCoords[i * 2 + 0] = vertX / (bounds.maxX - bounds.minX) + 0.5;
        this.texCoords[i * 2 + 1] = 1.0 - vertY / (bounds.maxY - bounds.minY) + 0.5;
    }
};


Geometry.prototype.getInfoOneLine = function ()
{
    let txt = "";
    if (this.faceVertCount == 3 && this.verticesIndices)txt += this.verticesIndices.length / 3;
    else txt += 0;

    txt += " tris ";

    if (this.vertices)txt += this.vertices.length / 3;
    else txt += 0;

    txt += " verts";

    return txt;
};

Geometry.prototype.getInfo = function ()
{
    const info = {};

    if (this.faceVertCount == 3 && this.verticesIndices)info.numFaces = this.verticesIndices.length / 3;
    else info.numFaces = 0;

    if (this.verticesIndices && this.verticesIndices.length)info.indices = this.verticesIndices.length;

    if (this.vertices)info.numVerts = this.vertices.length / 3;
    else info.numVerts = 0;

    if (this.vertexNormals) info.numNormals = this.vertexNormals.length / 3;
    else info.numNormals = 0;

    if (this.texCoords) info.numTexCoords = this.texCoords.length / 2;
    else info.numTexCoords = 0;

    if (this.tangents) info.numTangents = this.tangents.length / 3;
    else info.numTangents = 0;

    if (this.biTangents) info.numBiTangents = this.biTangents.length / 3;
    else info.numBiTangents = 0;

    if (this.biTangents) info.numBiTangents = this.biTangents.length / 3;
    else info.numBiTangents = 0;

    if (this.vertexColors) info.numVertexColors = this.vertexColors.length / 4;
    else info.numVertexColors = 0;

    if (this.getAttributes()) info.numAttribs = Object.keys(this.getAttributes()).length;
    else info.numAttribs = 0;

    info.isIndexed = this.isIndexed();

    return info;
};

// -----------------

// TODO : rewritwe circle op
Geometry.buildFromFaces = function (arr, name, optimize)
{
    const vertices = [];
    const verticesIndices = [];

    for (let i = 0; i < arr.length; i += 3)
    {
        const a = arr[i + 0];
        const b = arr[i + 1];
        const c = arr[i + 2];
        const face = [-1, -1, -1];

        if (optimize)
            for (let iv = 0; iv < vertices.length; iv += 3)
            {
                if (vertices[iv + 0] == a[0] && vertices[iv + 1] == a[1] && vertices[iv + 2] == a[2]) face[0] = iv / 3;
                if (vertices[iv + 0] == b[0] && vertices[iv + 1] == b[1] && vertices[iv + 2] == b[2]) face[1] = iv / 3;
                if (vertices[iv + 0] == c[0] && vertices[iv + 1] == c[1] && vertices[iv + 2] == c[2]) face[2] = iv / 3;
            }

        if (face[0] == -1)
        {
            vertices.push(a[0], a[1], a[2]);
            face[0] = (vertices.length - 1) / 3;
        }

        if (face[1] == -1)
        {
            vertices.push(b[0], b[1], b[2]);
            face[1] = (vertices.length - 1) / 3;
        }

        if (face[2] == -1)
        {
            vertices.push(c[0], c[1], c[2]);
            face[2] = (vertices.length - 1) / 3;
        }

        verticesIndices.push(parseInt(face[0], 10));
        verticesIndices.push(parseInt(face[1], 10));
        verticesIndices.push(parseInt(face[2], 10));
    }

    const geom = new Geometry(name);
    geom.name = name;
    geom.vertices = vertices;
    geom.verticesIndices = verticesIndices;

    return geom;
};




;// CONCATENATED MODULE: ./src/core/cgl/cgl_mesh.js




const MESH = {};
MESH.lastMesh = null;

/**
 * webgl renderable 3d object
 * @class
 * @namespace external:CGL
 * @hideconstructor
 * @param {Context} _cgl cgl
 * @param {Geometry} __geom geometry
 * @param {Number} _options glPrimitive
 * @example
 * const cgl=this._cgl
 * const mesh=new CGL.Mesh(cgl, geometry);
 *
 * function render()
 * {
 *   mesh.render(cgl.getShader());
 * }
 */
const Mesh = function (_cgl, __geom, _options)
{
    this._cgl = _cgl;

    let options = _options || {};
    if (CABLES.UTILS.isNumeric(options))options = { "glPrimitive": _options }; // old constructor fallback...
    this._log = new Logger("cgl_mesh");
    this._bufVertexAttrib = null;
    this._bufVerticesIndizes = this._cgl.gl.createBuffer();
    this._indexType = this._cgl.gl.UNSIGNED_SHORT;
    this._attributes = [];
    this._attribLocs = {};
    this._geom = null;
    this._lastShader = null;
    this._numInstances = 0;
    this._glPrimitive = options.glPrimitive;

    this.opId = options.opId || "";
    this._preWireframeGeom = null;
    this.addVertexNumbers = false;
    this._name = "unknown";

    this.feedBackAttributes = [];
    this.setGeom(__geom);

    this._feedBacks = [];
    this._feedBacksChanged = false;
    this._transformFeedBackLoc = -1;
    this._lastAttrUpdate = 0;

    this.memFreed = false;

    this._cgl.profileData.addHeavyEvent("mesh constructed", this._name);

    this._queryExt = null;

    Object.defineProperty(this, "numInstances", {
        get()
        {
            return this._numInstances;
        },
        set(v)
        {
            this.setNumInstances(v);
        },
    });
};

Mesh.prototype.freeMem = function ()
{
    this.memFreed = true;

    for (let i = 0; i < this._attributes.length; i++)
    {
        this._attributes[i].floatArray = null;
    }
};

/**
 * @function updateVertices
 * @memberof Mesh
 * @instance
 * @description update vertices only from a geometry
 * @param {Geometry} geom
 */
Mesh.prototype.updateVertices = function (geom)
{
    this.setAttribute(constants_CONSTANTS.SHADER.SHADERVAR_VERTEX_POSITION, geom.vertices, 3);
    this._numVerts = geom.vertices.length / 3;
};

Mesh.prototype.setAttributePointer = function (attrName, name, stride, offset)
{
    for (let i = 0; i < this._attributes.length; i++)
    {
        if (this._attributes[i].name == attrName)
        {
            if (!this._attributes[i].pointer) this._attributes[i].pointer = [];

            this._attributes[i].pointer.push(
                {
                    "loc": -1,
                    "name": name,
                    "stride": stride,
                    "offset": offset,
                    "instanced": attrName == constants_CONSTANTS.SHADER.SHADERVAR_INSTANCE_MMATRIX,
                }
            );
        }
    }
};

Mesh.prototype.getAttribute = function (name)
{
    for (let i = 0; i < this._attributes.length; i++) if (this._attributes[i].name == name) return this._attributes[i];
};

Mesh.prototype.setAttributeRange = function (attr, array, start, end)
{
    if (!attr) return;
    if (!start && !end) return;

    if (!attr.name)
    {
        this._log.stack("no attrname?!");
    }

    this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER, attr.buffer);
    this._cgl.profileData.profileMeshAttributes += (end - start) || 0;

    this._cgl.profileData.profileSingleMeshAttribute[this._name] = this._cgl.profileData.profileSingleMeshAttribute[this._name] || 0;
    this._cgl.profileData.profileSingleMeshAttribute[this._name] += (end - start) || 0;

    if (attr.numItems < array.length / attr.itemSize)
    {
        this._resizeAttr(array, attr);
    }

    if (end > array.length)
    {
        if (CABLES.platform.isDevEnv())
            this._log.log(this._cgl.canvas.id + " " + attr.name + " buffersubdata out of bounds ?", array.length, end, start, attr);
        // end = array.length - 1;
        return;
    }

    if (this._cgl.glVersion == 1) this._cgl.gl.bufferSubData(this._cgl.gl.ARRAY_BUFFER, 0, array); // probably slow/ maybe create and array with only changed size ??
    else this._cgl.gl.bufferSubData(this._cgl.gl.ARRAY_BUFFER, start * 4, array, start, (end - start));
};

Mesh.prototype._resizeAttr = function (array, attr)
{
    if (attr.buffer)
        this._cgl.gl.deleteBuffer(attr.buffer);

    attr.buffer = this._cgl.gl.createBuffer();
    this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER, attr.buffer);
    this._bufferArray(array, attr);
    attr.numItems = array.length / attr.itemSize;// numItems;
};


Mesh.prototype._bufferArray = function (array, attr)
{
    let floatArray = attr.floatArray || null;
    if (!array) return;


    if (this._cgl.debugOneFrame)
    {
        console.log("_bufferArray", array.length, attr.name); // eslint-disable-line
    }

    if (!(array instanceof Float32Array))
    {
        if (attr && floatArray && floatArray.length == array.length)
        {
            floatArray.set(array);
            // floatArray = floatArray;
        }
        else
        {
            floatArray = new Float32Array(array);

            if (this._cgl.debugOneFrame)
            {
                console.log("_bufferArray create new float32array", array.length, attr.name); // eslint-disable-line
            }

            if (array.length > 10000)
            {
                this._cgl.profileData.profileNonTypedAttrib++;
                this._cgl.profileData.profileNonTypedAttribNames = "(" + this._name + ":" + attr.name + ")";
            }
        }
    }
    else floatArray = array;

    attr.arrayLength = floatArray.length;
    attr.floatArray = null;// floatArray;

    this._cgl.gl.bufferData(this._cgl.gl.ARRAY_BUFFER, floatArray, this._cgl.gl.DYNAMIC_DRAW);
};

/**
 * @function setAttribute
 * @description update attribute
 * @memberof Mesh
 * @instance
 * @param {String} attribute name
 * @param {Array} data
 * @param {Number} itemSize
 * @param {Object} options
 */
Mesh.prototype.addAttribute = Mesh.prototype.updateAttribute = Mesh.prototype.setAttribute = function (name, array, itemSize, options)
{
    if (!array)
    {
        this._log.error("mesh addAttribute - no array given! " + name);
        throw new Error();
    }
    let cb = null;
    let instanced = false;
    let i = 0;
    const numItems = array.length / itemSize;

    this._cgl.profileData.profileMeshAttributes += numItems || 0;

    if (typeof options == "function")
    {
        cb = options;
    }

    if (typeof options == "object")
    {
        if (options.cb) cb = options.cb;
        if (options.instanced) instanced = options.instanced;
    }

    if (name == constants_CONSTANTS.SHADER.SHADERVAR_INSTANCE_MMATRIX) instanced = true;


    for (i = 0; i < this._attributes.length; i++)
    {
        const attr = this._attributes[i];
        if (attr.name == name)
        {
            if (attr.numItems === numItems)
            {
            }
            else
            {
                // this._log.log("wrong buffer size", this._geom.name, attr.name, attr.numItems, numItems);
                this._resizeAttr(array, attr);
            }

            this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER, attr.buffer);
            this._bufferArray(array, attr);

            return attr;
        }
    }

    // create new buffer...

    const buffer = this._cgl.gl.createBuffer();

    this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER, buffer);
    // this._cgl.gl.bufferData(this._cgl.gl.ARRAY_BUFFER, floatArray, this._cgl.gl.DYNAMIC_DRAW);

    let type = this._cgl.gl.FLOAT;
    if (options && options.type) type = options.type;
    const attr = {
        "buffer": buffer,
        "name": name,
        "cb": cb,
        "itemSize": itemSize,
        "numItems": numItems,
        "startItem": 0,
        "instanced": instanced,
        "type": type
    };

    this._bufferArray(array, attr);

    if (name == constants_CONSTANTS.SHADER.SHADERVAR_VERTEX_POSITION) this._bufVertexAttrib = attr;
    this._attributes.push(attr);
    this._attribLocs = {};

    return attr;
};

Mesh.prototype.getAttributes = function ()
{
    return this._attributes;
};

/**
 * @function updateTexCoords
 * @description update texture coordinates only from a geometry
 * @memberof Mesh
 * @instance
 * @param {Geometry} geom
 */
Mesh.prototype.updateTexCoords = function (geom)
{
    if (geom.texCoords && geom.texCoords.length > 0)
    {
        this.setAttribute(constants_CONSTANTS.SHADER.SHADERVAR_VERTEX_TEXCOORD, geom.texCoords, 2);
    }
    else
    {
        const tcBuff = new Float32Array(Math.round((geom.vertices.length / 3) * 2));
        this.setAttribute(constants_CONSTANTS.SHADER.SHADERVAR_VERTEX_TEXCOORD, tcBuff, 2);
    }
};


/**
 * @function updateNormals
 * @description update normals only from a geometry
 * @memberof Mesh
 * @instance
 * @param {Geometry} geom
 */
Mesh.prototype.updateNormals = function (geom)
{
    if (geom.vertexNormals && geom.vertexNormals.length > 0)
    {
        this.setAttribute(constants_CONSTANTS.SHADER.SHADERVAR_VERTEX_NORMAL, geom.vertexNormals, 3);
    }
    else
    {
        const tcBuff = new Float32Array(Math.round((geom.vertices.length)));
        this.setAttribute(constants_CONSTANTS.SHADER.SHADERVAR_VERTEX_NORMAL, tcBuff, 3);
    }
};


Mesh.prototype._setVertexNumbers = function (arr)
{
    if (!this._verticesNumbers || this._verticesNumbers.length != this._numVerts || arr)
    {
        if (arr) this._verticesNumbers = arr;
        else
        {
            this._verticesNumbers = new Float32Array(this._numVerts);
            for (let i = 0; i < this._numVerts; i++) this._verticesNumbers[i] = i;
        }

        this.setAttribute(constants_CONSTANTS.SHADER.SHADERVAR_VERTEX_NUMBER, this._verticesNumbers, 1, (attr, geom, shader) =>
        {
            if (!shader.uniformNumVertices) shader.uniformNumVertices = new Uniform(shader, "f", "numVertices", this._numVerts);
            shader.uniformNumVertices.setValue(this._numVerts);

            // console.log("this._numVerts", this._numVerts, attr, shader.uniformNumVertices);
        });
    }
};

/**
 * @function setVertexIndices
 * @description update vertex indices / faces
 * @memberof Mesh
 * @instance
 * @param {array} vertIndices
 */
Mesh.prototype.setVertexIndices = function (vertIndices)
{
    if (!this._bufVerticesIndizes)
    {
        this._log.warn("no bufVerticesIndizes: " + this._name);
        return;
    }
    if (vertIndices.length > 0)
    {
        if (vertIndices instanceof Float32Array) this._log.warn("vertIndices float32Array: " + this._name);

        for (let i = 0; i < vertIndices.length; i++)
        {
            if (vertIndices[i] >= this._numVerts)
            {
                this._log.warn("invalid index in " + this._name, i, vertIndices[i]);
                return;
            }
        }

        this._cgl.gl.bindBuffer(this._cgl.gl.ELEMENT_ARRAY_BUFFER, this._bufVerticesIndizes);

        // todo cache this ?
        // if(!this.vertIndicesTyped || this.vertIndicesTyped.length!=this._geom.verticesIndices.length)

        if (vertIndices.length > 65535)
        {
            this.vertIndicesTyped = new Uint32Array(vertIndices);
            this._indexType = this._cgl.gl.UNSIGNED_INT;
        }
        else
        if (vertIndices instanceof Uint32Array)
        {
            this.vertIndicesTyped = vertIndices;
            this._indexType = this._cgl.gl.UNSIGNED_INT;
        }
        else
        if (!(vertIndices instanceof Uint16Array))
        {
            this.vertIndicesTyped = new Uint16Array(vertIndices);
            this._indexType = this._cgl.gl.UNSIGNED_SHORT;
        }
        else this.vertIndicesTyped = vertIndices;

        this._cgl.gl.bufferData(this._cgl.gl.ELEMENT_ARRAY_BUFFER, this.vertIndicesTyped, this._cgl.gl.DYNAMIC_DRAW);
        this._bufVerticesIndizes.itemSize = 1;
        this._bufVerticesIndizes.numItems = vertIndices.length;
    }
    else this._bufVerticesIndizes.numItems = 0;
};

/**
 * @function setGeom
 * @memberof Mesh
 * @instance
 * @description set geometry for mesh
 * @param {Geometry} geom
 * @param {boolean} removeRef
 */
Mesh.prototype.setGeom = function (geom, removeRef)
{
    this._geom = geom;
    if (geom.glPrimitive != null) this._glPrimitive = geom.glPrimitive;
    if (this._geom && this._geom.name) this._name = "mesh " + this._geom.name;

    MESH.lastMesh = null;
    this._cgl.profileData.profileMeshSetGeom++;

    this._disposeAttributes();

    this.updateVertices(this._geom);
    this.setVertexIndices(this._geom.verticesIndices);

    if (this.addVertexNumbers) this._setVertexNumbers();

    const geomAttribs = this._geom.getAttributes();

    const attribAssoc = {
        "texCoords": constants_CONSTANTS.SHADER.SHADERVAR_VERTEX_TEXCOORD,
        "vertexNormals": constants_CONSTANTS.SHADER.SHADERVAR_VERTEX_NORMAL,
        "vertexColors": constants_CONSTANTS.SHADER.SHADERVAR_VERTEX_COLOR,
        "tangents": "attrTangent",
        "biTangents": "attrBiTangent",
    };

    for (const index in geomAttribs)
        if (geomAttribs[index].data && geomAttribs[index].data.length)
            this.setAttribute(attribAssoc[index] || index, geomAttribs[index].data, geomAttribs[index].itemSize);


    if (removeRef)
    {
        this._geom = null;
    }
};

Mesh.prototype._preBind = function (shader)
{
    for (let i = 0; i < this._attributes.length; i++)
        if (this._attributes[i].cb)
            this._attributes[i].cb(this._attributes[i], this._geom, shader);
};

Mesh.prototype._checkAttrLengths = function ()
{
    if (this.memFreed) return;
    // check length
    for (let i = 0; i < this._attributes.length; i++)
    {
        if (this._attributes[i].arrayLength / this._attributes[i].itemSize < this._attributes[0].arrayLength / this._attributes[0].itemSize)
        {
            let name = "unknown";
            if (this._geom)name = this._geom.name;
            // this._log.warn(
            //     name + ": " + this._attributes[i].name +
            //     " wrong attr length. is:", this._attributes[i].arrayLength / this._attributes[i].itemSize,
            //     " should be:", this._attributes[0].arrayLength / this._attributes[0].itemSize,
            // );
        }
    }
};

Mesh.prototype._bind = function (shader)
{
    if (!shader.isValid()) return;

    let attrLocs = [];
    if (this._attribLocs[shader.id]) attrLocs = this._attribLocs[shader.id];
    else this._attribLocs[shader.id] = attrLocs;

    this._lastShader = shader;
    if (shader.lastCompile > this._lastAttrUpdate || attrLocs.length != this._attributes.length)
    {
        this._lastAttrUpdate = shader.lastCompile;
        for (let i = 0; i < this._attributes.length; i++) attrLocs[i] = -1;
    }

    for (let i = 0; i < this._attributes.length; i++)
    {
        const attribute = this._attributes[i];
        if (attrLocs[i] == -1)
        {
            if (attribute._attrLocationLastShaderTime != shader.lastCompile)
            {
                attribute._attrLocationLastShaderTime = shader.lastCompile;
                attrLocs[i] = this._cgl.glGetAttribLocation(shader.getProgram(), attribute.name);
                // this._log.log('attribloc',attribute.name,attrLocs[i]);
                this._cgl.profileData.profileAttrLoc++;
            }
        }

        if (attrLocs[i] != -1)
        {
            this._cgl.gl.enableVertexAttribArray(attrLocs[i]);
            this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER, attribute.buffer);

            if (attribute.instanced)
            {
                // todo: easier way to fill mat4 attribs...
                if (attribute.itemSize <= 4)
                {
                    if (!attribute.itemSize || attribute.itemSize == 0) this._log.warn("instanced attrib itemsize error", this._geom.name, attribute);

                    this._cgl.gl.vertexAttribPointer(attrLocs[i], attribute.itemSize, attribute.type, false, attribute.itemSize * 4, 0);
                    this._cgl.gl.vertexAttribDivisor(attrLocs[i], 1);
                }
                else if (attribute.itemSize == 16)
                {
                    const stride = 16 * 4;

                    this._cgl.gl.vertexAttribPointer(attrLocs[i], 4, attribute.type, false, stride, 0);
                    this._cgl.gl.enableVertexAttribArray(attrLocs[i] + 1);
                    this._cgl.gl.vertexAttribPointer(attrLocs[i] + 1, 4, attribute.type, false, stride, 4 * 4 * 1);
                    this._cgl.gl.enableVertexAttribArray(attrLocs[i] + 2);
                    this._cgl.gl.vertexAttribPointer(attrLocs[i] + 2, 4, attribute.type, false, stride, 4 * 4 * 2);
                    this._cgl.gl.enableVertexAttribArray(attrLocs[i] + 3);
                    this._cgl.gl.vertexAttribPointer(attrLocs[i] + 3, 4, attribute.type, false, stride, 4 * 4 * 3);

                    this._cgl.gl.vertexAttribDivisor(attrLocs[i], 1);
                    this._cgl.gl.vertexAttribDivisor(attrLocs[i] + 1, 1);
                    this._cgl.gl.vertexAttribDivisor(attrLocs[i] + 2, 1);
                    this._cgl.gl.vertexAttribDivisor(attrLocs[i] + 3, 1);
                }
                else
                {
                    this._log.warn("unknown instance attrib size", attribute.name);
                }
            }
            else
            {
                if (!attribute.itemSize || attribute.itemSize == 0) this._log.warn("attrib itemsize error", this._name, attribute);
                this._cgl.gl.vertexAttribPointer(attrLocs[i], attribute.itemSize, attribute.type, false, attribute.itemSize * 4, 0);

                if (attribute.pointer)
                {
                    for (let ip = 0; ip < attribute.pointer.length; ip++)
                    {
                        const pointer = attribute.pointer[ip];

                        if (pointer.loc == -1)
                            pointer.loc = this._cgl.glGetAttribLocation(shader.getProgram(), pointer.name);

                        this._cgl.profileData.profileAttrLoc++;

                        this._cgl.gl.enableVertexAttribArray(pointer.loc);
                        this._cgl.gl.vertexAttribPointer(pointer.loc, attribute.itemSize, attribute.type, false, pointer.stride, pointer.offset);
                    }
                }
                if (this.bindFeedback) this.bindFeedback(attribute);
            }
        }
    }

    if (this._bufVerticesIndizes && this._bufVerticesIndizes.numItems !== 0) this._cgl.gl.bindBuffer(this._cgl.gl.ELEMENT_ARRAY_BUFFER, this._bufVerticesIndizes);
};

Mesh.prototype.unBind = function ()
{
    const shader = this._lastShader;
    this._lastShader = null;
    if (!shader) return;

    let attrLocs = [];
    if (this._attribLocs[shader.id]) attrLocs = this._attribLocs[shader.id];
    else this._attribLocs[shader.id] = attrLocs;

    MESH.lastMesh = null;

    for (let i = 0; i < this._attributes.length; i++)
    {
        if (this._attributes[i].instanced)
        {
            // todo: easier way to fill mat4 attribs...
            if (this._attributes[i].itemSize <= 4)
            {
                if (attrLocs[i] != -1) this._cgl.gl.vertexAttribDivisor(attrLocs[i], 0);
                if (attrLocs[i] >= 0) this._cgl.gl.disableVertexAttribArray(attrLocs[i]);
            }
            else
            {
                this._cgl.gl.vertexAttribDivisor(attrLocs[i], 0);
                this._cgl.gl.vertexAttribDivisor(attrLocs[i] + 1, 0);
                this._cgl.gl.vertexAttribDivisor(attrLocs[i] + 2, 0);
                this._cgl.gl.vertexAttribDivisor(attrLocs[i] + 3, 0);
                this._cgl.gl.disableVertexAttribArray(attrLocs[i] + 1);
                this._cgl.gl.disableVertexAttribArray(attrLocs[i] + 2);
                this._cgl.gl.disableVertexAttribArray(attrLocs[i] + 3);
            }
        }

        if (attrLocs[i] != -1) this._cgl.gl.disableVertexAttribArray(attrLocs[i]);
    }
};

Mesh.prototype.meshChanged = function ()
{
    return this._cgl.lastMesh && this._cgl.lastMesh != this;
};

Mesh.prototype.printDebug = function (shader)
{
    console.log("--attributes");
    for (let i = 0; i < this._attributes.length; i++)
    {
        console.log("attribute " + i + " " + this._attributes[i].name);
    }
};

Mesh.prototype.setNumVertices = function (num)
{
    this._bufVertexAttrib.numItems = num;
};

Mesh.prototype.getNumVertices = function ()
{
    return this._bufVertexAttrib.numItems;
};


/**
 * @function render
 * @memberof Mesh
 * @instance
 * @description draw mesh to screen
 * @param {Shader} shader
 */
Mesh.prototype.render = function (shader)
{
    // TODO: enable/disablevertex only if the mesh has changed... think drawing 10000x the same mesh

    if (!shader || !shader.isValid() || this._cgl.aborted) return;

    this._checkAttrLengths();

    if (this._geom)
    {
        if (this._preWireframeGeom && !shader.wireframe && !this._geom.isIndexed())
        {
            this.setGeom(this._preWireframeGeom);
            this._preWireframeGeom = null;
            // console.log("remove prewireframe geom");
        }

        if (shader.wireframe)
        {
            let changed = false;

            if (this._geom.isIndexed())
            {
                if (!this._preWireframeGeom)
                {
                    this._preWireframeGeom = this._geom;
                    this._geom = this._geom.copy();
                }

                this._geom.unIndex();
                changed = true;
            }

            if (!this._geom.getAttribute("attrBarycentric"))
            {
                if (!this._preWireframeGeom)
                {
                    this._preWireframeGeom = this._geom;
                    this._geom = this._geom.copy();
                }
                changed = true;

                this._geom.calcBarycentric();
            }
            if (changed) this.setGeom(this._geom);
        }
        // if (shader.wireframe)
        // console.log(shader.wireframe, this._geom.isIndexed());
    }

    let needsBind = false;
    if (MESH.lastMesh != this)
    {
        if (MESH.lastMesh) MESH.lastMesh.unBind();
        needsBind = true;
    }


    // var needsBind=false;
    // {
    //     needsBind=true;
    // }
    if (needsBind) this._preBind(shader);

    if (!shader.bind()) return;

    // if(needsBind)
    this._bind(shader);
    if (this.addVertexNumbers) this._setVertexNumbers();

    MESH.lastMesh = this;

    let prim = this._cgl.gl.TRIANGLES;
    if (this._glPrimitive !== undefined) prim = this._glPrimitive;
    if (shader.glPrimitive !== null) prim = shader.glPrimitive;

    let elementDiv = 1;
    let doQuery = this._cgl.profileData.doProfileGlQuery;
    let queryStarted = false;
    if (doQuery)
    {
        let id = this._name + " - " + shader.getName() + " #" + shader.id;
        if (this._numInstances) id += " instanced " + this._numInstances + "x";

        let queryProfilerData = this._cgl.profileData.glQueryData[id];

        if (!queryProfilerData) queryProfilerData = { "id": id, "num": 0 };

        if (shader.opId)queryProfilerData.shaderOp = shader.opId;
        if (this.opId)queryProfilerData.meshOp = this.opId;

        this._cgl.profileData.glQueryData[id] = queryProfilerData;

        if (!this._queryExt && this._queryExt !== false) this._queryExt = this._cgl.enableExtension("EXT_disjoint_timer_query_webgl2") || false;
        if (this._queryExt)
        {
            if (queryProfilerData._drawQuery)
            {
                const available = this._cgl.gl.getQueryParameter(queryProfilerData._drawQuery, this._cgl.gl.QUERY_RESULT_AVAILABLE);
                if (available)
                {
                    const elapsedNanos = this._cgl.gl.getQueryParameter(queryProfilerData._drawQuery, this._cgl.gl.QUERY_RESULT);
                    const currentTimeGPU = elapsedNanos / 1000000;

                    queryProfilerData._times = queryProfilerData._times || 0;
                    queryProfilerData._times += currentTimeGPU;
                    queryProfilerData._numcount++;
                    queryProfilerData.when = performance.now();
                    queryProfilerData._drawQuery = null;
                    queryProfilerData.queryStarted = false;
                }
            }

            if (!queryProfilerData.queryStarted)
            {
                queryProfilerData._drawQuery = this._cgl.gl.createQuery();
                this._cgl.gl.beginQuery(this._queryExt.TIME_ELAPSED_EXT, queryProfilerData._drawQuery);
                queryStarted = queryProfilerData.queryStarted = true;
            }
        }
    }


    if (this.hasFeedbacks && this.hasFeedbacks()) this.drawFeedbacks(shader, prim);
    else if (!this._bufVerticesIndizes || this._bufVerticesIndizes.numItems === 0)
    {
        // for (let i = 0; i < this._attributes.length; i++)
        // {
        //     if (this._attributes[i].arrayLength / this._attributes[i].itemSize != this._bufVertexAttrib.floatArray.length / 3)
        //     {
        //         this._log.warn("attrib buffer length wrong! ", this._attributes[i].name, this._attributes[i].arrayLength / this._attributes[i].itemSize, this._bufVertexAttrib.floatArray.length / 3, this._attributes[i].itemSize);
        //         // this._log.log(this);
        //         // debugger;
        //         return;
        //     }
        // }


        if (prim == this._cgl.gl.TRIANGLES)elementDiv = 3;
        if (this._numInstances === 0) this._cgl.gl.drawArrays(prim, this._bufVertexAttrib.startItem, this._bufVertexAttrib.numItems - this._bufVertexAttrib.startItem);
        else this._cgl.gl.drawArraysInstanced(prim, this._bufVertexAttrib.startItem, this._bufVertexAttrib.numItems, this._numInstances);
    }
    else
    {
        if (prim == this._cgl.gl.TRIANGLES)elementDiv = 3;
        if (this._numInstances === 0)
        {
            // console.log("la", this._bufVerticesIndizes.numItems);

            this._cgl.gl.drawElements(prim, this._bufVerticesIndizes.numItems, this._indexType, 0);
        }
        else
        {
            this._cgl.gl.drawElementsInstanced(prim, this._bufVerticesIndizes.numItems, this._indexType, 0, this._numInstances);
        }
    }

    if (this._cgl.debugOneFrame && this._cgl.gl.getError() != this._cgl.gl.NO_ERROR)
    {
        this._log.error("mesh draw gl error");
        this._log.error("mesh", this);
        this._log.error("shader", shader);

        const attribNames = [];
        for (let i = 0; i < this._cgl.gl.getProgramParameter(shader.getProgram(), this._cgl.gl.ACTIVE_ATTRIBUTES); i++)
        {
            const name = this._cgl.gl.getActiveAttrib(shader.getProgram(), i).name;
            this._log.error("attrib ", name);
        }
    }

    this._cgl.profileData.profileMeshNumElements += (this._bufVertexAttrib.numItems / elementDiv) * (this._numInstances || 1);
    this._cgl.profileData.profileMeshDraw++;

    if (doQuery && queryStarted)
    {
        this._cgl.gl.endQuery(this._queryExt.TIME_ELAPSED_EXT);
    }

    this._cgl.printError("mesh render " + this._name);

    this.unBind();
};

Mesh.prototype.setNumInstances = function (n)
{
    n = Math.max(0, n);
    if (this._numInstances != n)
    {
        this._numInstances = n;
        const indexArr = new Float32Array(n);
        for (let i = 0; i < n; i++) indexArr[i] = i;
        this.setAttribute(constants_CONSTANTS.SHADER.SHADERVAR_INSTANCE_INDEX, indexArr, 1, { "instanced": true });
    }
};

Mesh.prototype._disposeAttributes = function ()
{
    if (!this._attributes) return;

    for (let i = 0; i < this._attributes.length; i++)
    {
        if (this._attributes[i].buffer)
        {
            this._cgl.gl.deleteBuffer(this._attributes[i].buffer);
            this._attributes[i].buffer = null;
        }
    }
    this._attributes.length = 0;
};

Mesh.prototype.dispose = function ()
{
    if (this._bufVertexAttrib && this._bufVertexAttrib.buffer) this._cgl.gl.deleteBuffer(this._bufVertexAttrib.buffer);
    if (this._bufVerticesIndizes) this._cgl.gl.deleteBuffer(this._bufVerticesIndizes);
    this._bufVerticesIndizes = null;

    this._disposeAttributes();
};





;// CONCATENATED MODULE: ./src/core/cgl/cgl_simplerect.js




const MESHES = {};

MESHES.getSimpleRect = function (cgl, name, size = 1.0)
{
    const geom = new Geometry(name);



    geom.vertices = [1.0 * size, 1.0 * size, 0.0, -1.0 * size, 1.0 * size, 0.0, 1.0 * size, -1.0 * size, 0.0, -1.0 * size, -1.0 * size, 0.0];
    geom.texCoords = [1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0];
    geom.verticesIndices = [0, 1, 2, 2, 1, 3];
    geom.vertexNormals = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0];

    return cgl.createMesh(geom);
    // return new Mesh(cgl, geom);
};


MESHES.getSimpleCube = function (cgl, name)
{
    const geom = new Geometry(name);
    geom.vertices = [-1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1];
    geom.setTexCoords([0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0,]);
    geom.verticesIndices = [0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23];
    geom.vertexNormals = new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0]);
    geom.tangents = new Float32Array([0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]);
    geom.biTangents = new Float32Array([-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1]);

    return new Mesh(cgl, geom);
};




;// CONCATENATED MODULE: ./src/core/cgl/cgl_textureeffect.js




const TextureEffect = function (cgl, options)
{
    this._cgl = cgl;
    this._log = new Logger("cgl_TextureEffect");

    if (!cgl.TextureEffectMesh) this.createMesh();

    this._textureSource = null;
    this._options = options;
    this.name = options.name || "unknown";

    // TODO: do we still need the options ?
    // var opts=options ||
    //     {
    //         isFloatingPointTexture:false,
    //         filter:CGL.Texture.FILTER_LINEAR
    //     };
    // if(options && options.fp)opts.isFloatingPointTexture=true;

    this.imgCompVer = 0;
    this.aspectRatio = 1;
    this._textureTarget = null; // new CGL.Texture(this._cgl,opts);
    this._frameBuf = this._cgl.gl.createFramebuffer();
    this._frameBuf2 = this._cgl.gl.createFramebuffer();
    this._renderbuffer = this._cgl.gl.createRenderbuffer();
    this._renderbuffer2 = this._cgl.gl.createRenderbuffer();
    this.switched = false;
    this.depth = false;
};

TextureEffect.prototype.dispose = function ()
{
    if (this._renderbuffer) this._cgl.gl.deleteRenderbuffer(this._renderbuffer);
    if (this._frameBuf) this._cgl.gl.deleteFramebuffer(this._frameBuf);
    if (this._renderbuffer2) this._cgl.gl.deleteRenderbuffer(this._renderbuffer2);
    if (this._frameBuf2) this._cgl.gl.deleteFramebuffer(this._frameBuf2);
};

TextureEffect.prototype.getWidth = function ()
{
    return this._textureSource.width;
};

TextureEffect.prototype.getHeight = function ()
{
    return this._textureSource.height;
};

TextureEffect.prototype.setSourceTexture = function (tex)
{
    if (tex === null)
    {
        this._textureSource = new Texture(this._cgl);
        this._textureSource.setSize(16, 16);
    }
    else
    {
        this._textureSource = tex;
    }

    if (!this._textureSource.compareSettings(this._textureTarget))
    {
        if (this._textureTarget) this._textureTarget.delete();

        this._textureTarget = this._textureSource.clone();

        this._cgl.profileData.profileEffectBuffercreate++;

        this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuf);

        this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, this._renderbuffer);

        // if(tex.textureType==CGL.Texture.TYPE_FLOAT) this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,this._cgl.gl.RGBA32F, this._textureSource.width,this._textureSource.height);
        // else this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,this._cgl.gl.RGBA8, this._textureSource.width,this._textureSource.height);

        if (this.depth) this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, this._cgl.gl.DEPTH_COMPONENT16, this._textureSource.width, this._textureSource.height);
        this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.TEXTURE_2D, this._textureTarget.tex, 0);
        if (this.depth) this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.RENDERBUFFER, this._renderbuffer);

        // this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.TEXTURE_2D, this._textureTarget.tex, 0);

        this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, null);
        this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, null);
        this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);

        this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuf2);

        this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, this._renderbuffer2);

        // if(tex.textureType==CGL.Texture.TYPE_FLOAT) this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,this._cgl.gl.RGBA32F, this._textureSource.width,this._textureSource.height);
        // else this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,this._cgl.gl.RGBA8, this._textureSource.width,this._textureSource.height);

        if (this.depth) this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, this._cgl.gl.DEPTH_COMPONENT16, this._textureSource.width, this._textureSource.height);
        this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.TEXTURE_2D, this._textureSource.tex, 0);

        if (this.depth) this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.RENDERBUFFER, this._renderbuffer2);

        // this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.TEXTURE_2D, this._textureSource.tex, 0);

        this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, null);
        this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, null);
        this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
    }

    this.aspectRatio = this._textureSource.width / this._textureSource.height;
};
TextureEffect.prototype.continueEffect = function ()
{
    this._cgl.pushDepthTest(false);
    this._cgl.pushModelMatrix();
    this._cgl.pushPMatrix();
    // todo why two pushs?



    this._cgl.pushViewPort(0, 0, this.getCurrentTargetTexture().width, this.getCurrentTargetTexture().height);



    mat4.perspective(this._cgl.pMatrix, 45, this.getCurrentTargetTexture().width / this.getCurrentTargetTexture().height, 0.1, 1100.0); // todo: why?

    this._cgl.pushPMatrix();
    mat4.identity(this._cgl.pMatrix);

    this._cgl.pushViewMatrix();
    mat4.identity(this._cgl.vMatrix);

    this._cgl.pushModelMatrix();
    mat4.identity(this._cgl.mMatrix);
};


TextureEffect.prototype.startEffect = function (bgTex)
{
    if (!this._textureTarget)
    {
        this._log.warn("effect has no target");
        return;
    }

    this.switched = false;

    this.continueEffect();

    if (bgTex)
    {
        this._bgTex = bgTex;
    }
    this._countEffects = 0;
};

TextureEffect.prototype.endEffect = function ()
{
    this._cgl.popDepthTest();
    this._cgl.popModelMatrix();

    this._cgl.popPMatrix();
    this._cgl.popModelMatrix();
    this._cgl.popViewMatrix();

    this._cgl.popPMatrix();
    this._cgl.popViewPort();
};

TextureEffect.prototype.bind = function ()
{
    if (this._textureSource === null)
    {
        this._log.warn("no base texture set!");
        return;
    }

    if (!this.switched)
    {
        this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuf);
        this._cgl.pushGlFrameBuffer(this._frameBuf);
    }
    else
    {
        this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuf2);
        this._cgl.pushGlFrameBuffer(this._frameBuf2);
    }
};

TextureEffect.prototype.finish = function ()
{
    if (this._textureSource === null)
    {
        this._log.warn("no base texture set!");
        return;
    }

    this._cgl.TextureEffectMesh.render(this._cgl.getShader());

    this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.popGlFrameBuffer());

    this._cgl.profileData.profileTextureEffect++;

    if (this._textureTarget.filter == Texture.FILTER_MIPMAP)
    {
        if (!this.switched)
        {
            this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, this._textureTarget.tex);
            this._textureTarget.updateMipMap();
        }
        else
        {
            this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, this._textureSource.tex);
            this._textureSource.updateMipMap();
        }

        this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, null);
    }

    this.switched = !this.switched;
    this._countEffects++;
};

TextureEffect.prototype.getCurrentTargetTexture = function ()
{
    if (this.switched) return this._textureSource;
    return this._textureTarget;
};

TextureEffect.prototype.getCurrentSourceTexture = function ()
{
    if (this._countEffects == 0 && this._bgTex) return this._bgTex;

    if (this.switched) return this._textureTarget;
    return this._textureSource;
};

TextureEffect.prototype.delete = function ()
{
    if (this._textureTarget) this._textureTarget.delete();
    if (this._textureSource) this._textureSource.delete();
    this._cgl.gl.deleteRenderbuffer(this._renderbuffer);
    this._cgl.gl.deleteFramebuffer(this._frameBuf);
};

TextureEffect.prototype.createMesh = function ()
{
    this._cgl.TextureEffectMesh = MESHES.getSimpleRect(this._cgl, "texEffectRect");
};

// ---------------------------------------------------------------------------------

TextureEffect.checkOpNotInTextureEffect = function (op)
{
    if (!op.patch.cgl) return true;
    if (op.uiAttribs.error && !op.patch.cgl.currentTextureEffect)
    {
        op.setUiError("textureeffect", null);
        return true;
    }
    if (!op.patch.cgl.currentTextureEffect) return true;

    if (op.patch.cgl.currentTextureEffect && !op.uiAttribs.error)
    {
        op.setUiError("textureeffect", "This op can not be a child of a ImageCompose/texture effect! imagecompose should only have textureeffect childs.", 0);
        return false;
    }

    if (op.patch.cgl.currentTextureEffect) return false;
    return true;
};

TextureEffect.checkOpInEffect = function (op, minver)
{
    minver = minver || 0;

    if (op.patch.cgl.currentTextureEffect)
    {
        if (op.uiAttribs.uierrors && op.patch.cgl.currentTextureEffect.imgCompVer >= minver)
        {
            op.setUiError("texeffect", null);
            return true;
        }

        if (minver && op.patch.cgl.currentTextureEffect.imgCompVer < minver)
        {
            op.setUiError("texeffect", "This op must be a child of an ImageCompose op with version >=" + minver + " <span class=\"button-small\" onclick=\"gui.patchView.downGradeOp('" + op.id + "','" + op.name + "')\">Downgrade</span> to previous version", 1);
        }
    }

    if (op.patch.cgl.currentTextureEffect) return true;

    if (!op.patch.cgl.currentTextureEffect && (!op.uiAttribs.uierrors || op.uiAttribs.uierrors.length == 0))
    {
        op.setUiError("texeffect", "This op must be a child of an ImageCompose op! More infos <a href=\"https://cables.gl/docs/image_composition/image_composition.html\" target=\"_blank\">here</a>. ", 1);
        return false;
    }

    if (!op.patch.cgl.currentTextureEffect) return false;
    return true;
};

TextureEffect.getBlendCode = function (ver)
{
    let src = "".endl()
        + "vec3 _blend(vec3 base,vec3 blend)".endl()
        + "{".endl()
        + "   vec3 colNew=blend;".endl()
        + "   #ifdef BM_MULTIPLY".endl()
        + "       colNew=base*blend;".endl()
        + "   #endif".endl()
        + "   #ifdef BM_MULTIPLY_INV".endl()
        + "       colNew=base* vec3(1.0)-blend;".endl()
        + "   #endif".endl()
        + "   #ifdef BM_AVERAGE".endl()
        + "       colNew=((base + blend) / 2.0);".endl()
        + "   #endif".endl()
        + "   #ifdef BM_ADD".endl()
        + "       colNew=min(base + blend, vec3(1.0));".endl()
        + "   #endif".endl()
        + "   #ifdef BM_SUBTRACT_ONE".endl()
        + "       colNew=max(base + blend - vec3(1.0), vec3(0.0));".endl()
        + "   #endif".endl()

        + "   #ifdef BM_SUBTRACT".endl()
        + "       colNew=base - blend;".endl()
        + "   #endif".endl()

        + "   #ifdef BM_DIFFERENCE".endl()
        + "       colNew=abs(base - blend);".endl()
        + "   #endif".endl()
        + "   #ifdef BM_NEGATION".endl()
        + "       colNew=(vec3(1.0) - abs(vec3(1.0) - base - blend));".endl()
        + "   #endif".endl()
        + "   #ifdef BM_EXCLUSION".endl()
        + "       colNew=(base + blend - 2.0 * base * blend);".endl()
        + "   #endif".endl()
        + "   #ifdef BM_LIGHTEN".endl()
        + "       colNew=max(blend, base);".endl()
        + "   #endif".endl()
        + "   #ifdef BM_DARKEN".endl()
        + "       colNew=min(blend, base);".endl()
        + "   #endif".endl()
        + "   #ifdef BM_OVERLAY".endl()
        + "      #define BlendOverlayf(base, blend)  (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))"
            // .endl()+'       #define BlendOverlay(base, blend)       Blend(base, blend, BlendOverlayf)'
            //    .endl()+'      colNew=Blend(base, blend, BlendOverlayf);'
            .endl()
        + "      colNew=vec3(BlendOverlayf(base.r, blend.r),BlendOverlayf(base.g, blend.g),BlendOverlayf(base.b, blend.b));".endl()
        + "   #endif".endl()
        + "   #ifdef BM_SCREEN".endl()
        + "      #define BlendScreenf(base, blend)       (1.0 - ((1.0 - base) * (1.0 - blend)))"
            // .endl()+'       #define BlendScreen(base, blend)        Blend(base, blend, BlendScreenf)'
            // .endl()+'      colNew=Blend(base, blend, BlendScreenf);'
            .endl()
        + "      colNew=vec3(BlendScreenf(base.r, blend.r),BlendScreenf(base.g, blend.g),BlendScreenf(base.b, blend.b));".endl()
        + "   #endif".endl()
        + "   #ifdef BM_SOFTLIGHT".endl()
        + "      #define BlendSoftLightf(base, blend)    ((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend)))"
            // .endl()+'       #define BlendSoftLight(base, blend)     Blend(base, blend, BlendSoftLightf)'
            //    .endl()+'      colNew=Blend(base, blend, BlendSoftLightf);'
            .endl()
        + "      colNew=vec3(BlendSoftLightf(base.r, blend.r),BlendSoftLightf(base.g, blend.g),BlendSoftLightf(base.b, blend.b));".endl()
        + "   #endif".endl()
        + "   #ifdef BM_HARDLIGHT".endl()
        + "      #define BlendOverlayf(base, blend)  (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))"
            // .endl()+'       #define BlendOverlay(base, blend)       Blend(base, blend, BlendOverlayf)'
            // .endl()+'      colNew=Blend(blend, base, BlendOverlayf);'
            .endl()
        + "      colNew=vec3(BlendOverlayf(base.r, blend.r),BlendOverlayf(base.g, blend.g),BlendOverlayf(base.b, blend.b));".endl()
        + "   #endif".endl()
        + "   #ifdef BM_COLORDODGE".endl()
        + "      #define BlendColorDodgef(base, blend)   ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0))"
            // .endl()+'      colNew=Blend(base, blend, BlendColorDodgef);'
            .endl()
        + "      colNew=vec3(BlendColorDodgef(base.r, blend.r),BlendColorDodgef(base.g, blend.g),BlendColorDodgef(base.b, blend.b));".endl()
        + "   #endif".endl()
        + "   #ifdef BM_COLORBURN".endl()
        + "      #define BlendColorBurnf(base, blend)    ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0))"
            // .endl()+'      colNew=Blend(base, blend, BlendColorBurnf);'
            .endl()
        + "      colNew=vec3(BlendColorBurnf(base.r, blend.r),BlendColorBurnf(base.g, blend.g),BlendColorBurnf(base.b, blend.b));".endl()
        + "   #endif".endl()










        + "   return colNew;".endl()
        + "}".endl();

    if (!ver)
        src += "vec4 cgl_blend(vec4 oldColor,vec4 newColor,float amount)".endl()
                + "{".endl()
                    + "vec4 col=vec4( _blend(oldColor.rgb,newColor.rgb) ,1.0);".endl()
                    + "col=vec4( mix( col.rgb, oldColor.rgb ,1.0-oldColor.a*amount),1.0);".endl()
                    + "return col;".endl()
                + "}".endl();

    if (ver >= 3)
        src += "vec4 cgl_blendPixel(vec4 base,vec4 col,float amount)".endl() +
                "{".endl() +

                "#ifdef BM_MATH_ADD".endl() +
                "   return vec4(base.rgb+col.rgb*amount,1.0);".endl() +
                "#endif".endl() +

                "#ifdef BM_MATH_SUB".endl() +
                "   return vec4(base.rgb-col.rgb*amount,1.0);".endl() +
                "#endif".endl() +

                "#ifdef BM_MATH_MUL".endl() +
                "   return vec4(base.rgb*col.rgb*amount,1.0);".endl() +
                "#endif".endl() +

                "#ifdef BM_MATH_DIV".endl() +
                "   return vec4(base.rgb/col.rgb*amount,1.0);".endl() +
                "#endif".endl() +


                    "#ifndef BM_MATH".endl() +
                        "vec3 colNew=_blend(base.rgb,col.rgb);".endl() +

                        "float newA=clamp(base.a+(col.a*amount),0.,1.);".endl() +

                        "#ifdef BM_ALPHAMASKED".endl() +
                            "newA=base.a;".endl() +
                        "#endif".endl() +

                        "return vec4(".endl() +
                            "mix(colNew,base.rgb,1.0-(amount*col.a)),".endl() +
                            "newA);".endl() +

                    "#endif".endl() +
    "}".endl();

    return src;
};

TextureEffect.onChangeBlendSelect = function (shader, blendName, maskAlpha = false)
{
    blendName = String(blendName);
    shader.toggleDefine("BM_NORMAL", blendName == "normal");
    shader.toggleDefine("BM_MULTIPLY", blendName == "multiply");
    shader.toggleDefine("BM_MULTIPLY_INV", blendName == "multiply invert");
    shader.toggleDefine("BM_AVERAGE", blendName == "average");
    shader.toggleDefine("BM_ADD", blendName == "add");
    shader.toggleDefine("BM_SUBTRACT_ONE", blendName == "subtract one");
    shader.toggleDefine("BM_SUBTRACT", blendName == "subtract");
    shader.toggleDefine("BM_DIFFERENCE", blendName == "difference");
    shader.toggleDefine("BM_NEGATION", blendName == "negation");
    shader.toggleDefine("BM_EXCLUSION", blendName == "exclusion");
    shader.toggleDefine("BM_LIGHTEN", blendName == "lighten");
    shader.toggleDefine("BM_DARKEN", blendName == "darken");
    shader.toggleDefine("BM_OVERLAY", blendName == "overlay");
    shader.toggleDefine("BM_SCREEN", blendName == "screen");
    shader.toggleDefine("BM_SOFTLIGHT", blendName == "softlight");
    shader.toggleDefine("BM_HARDLIGHT", blendName == "hardlight");
    shader.toggleDefine("BM_COLORDODGE", blendName == "color dodge");
    shader.toggleDefine("BM_COLORBURN", blendName == "color burn");

    shader.toggleDefine("BM_MATH_ADD", blendName == "Math Add");
    shader.toggleDefine("BM_MATH_SUB", blendName == "Math Subtract");
    shader.toggleDefine("BM_MATH_MUL", blendName == "Math Multiply");
    shader.toggleDefine("BM_MATH_DIV", blendName == "Math Divide");

    shader.toggleDefine("BM_MATH", blendName.indexOf("Math ") == 0);


    shader.toggleDefine("BM_ALPHAMASKED", maskAlpha);
};

TextureEffect.AddBlendSelect = function (op, name, defaultMode)
{
    const p = op.inValueSelect(name || "Blend Mode", [
        "normal", "lighten", "darken", "multiply", "multiply invert", "average", "add", "subtract", "difference", "negation", "exclusion", "overlay", "screen", "color dodge", "color burn", "softlight", "hardlight", "subtract one",
        "Math Add",
        "Math Subtract",
        "Math Multiply",
        "Math Divide",

    ], defaultMode || "normal");
    return p;
};

TextureEffect.AddBlendAlphaMask = function (op, name, defaultMode)
{
    const p = op.inSwitch(name || "Alpha Mask", ["Off", "On"], defaultMode || "Off");
    return p;
};

TextureEffect.setupBlending = function (op, shader, blendPort, amountPort, alphaMaskPort)
{
    const onChange = () =>
    {
        let maskAlpha = false;
        if (alphaMaskPort) maskAlpha = alphaMaskPort.get() == "On";
        TextureEffect.onChangeBlendSelect(shader, blendPort.get(), maskAlpha);

        let str = blendPort.get();
        if (str == "normal") str = null;
        else if (str == "multiply") str = "mul";
        else if (str == "multiply invert") str = "mulinv";
        else if (str == "lighten") str = "light";
        else if (str == "darken") str = "darken";
        else if (str == "average") str = "avg";
        else if (str == "subtract one") str = "sub one";
        else if (str == "subtract") str = "sub";
        else if (str == "difference") str = "diff";
        else if (str == "negation") str = "neg";
        else if (str == "exclusion") str = "exc";
        else if (str == "overlay") str = "ovl";
        else if (str == "color dodge") str = "dodge";
        else if (str == "color burn") str = "burn";
        else if (str == "softlight") str = "soft";
        else if (str == "hardlight") str = "hard";
        else if (str == "Math Add") str = "+";
        else if (str == "Math Subtract") str = "-";
        else if (str == "Math Multiply") str = "*";
        else if (str == "Math Divide") str = "/";

        op.setUiAttrib({ "extendTitle": str });
    };
    op.setPortGroup("Blending", [blendPort, amountPort, alphaMaskPort]);

    let maskAlpha = false;

    blendPort.onChange = onChange;
    if (alphaMaskPort)
    {
        alphaMaskPort.onChange = onChange;
        maskAlpha = alphaMaskPort.get() == "On";
    }

    TextureEffect.onChangeBlendSelect(shader, blendPort.get(), maskAlpha);
};



;// CONCATENATED MODULE: ./src/core/cgl/cgl_shader_lib.js




const ShaderLibMods = {
    "CGL.BLENDMODES": function ()
    {
        this.name = "blendmodes";
        this.srcHeadFrag = TextureEffect.getBlendCode();
    },
    "CGL.BLENDMODES3": function ()
    {
        this.name = "blendmodes3";
        this.srcHeadFrag = TextureEffect.getBlendCode(3);
    },

    "CGL.LUMINANCE": function ()
    {
        this.name = "luminance";
        this.srcHeadFrag = "".endl()
            + "float cgl_luminance(vec3 c)".endl()
            + "{".endl()
            + "    return dot(vec3(0.2126,0.7152,0.0722),c);".endl()
            + "}".endl();
    },


    // quite good random numbers, but somehow don't work in ANGLE
    "CGL.RANDOM_OLD": function ()
    {
        this.name = "randomNumber";
        this.srcHeadFrag = "".endl()
            + "float cgl_random(vec2 co)".endl()
            + "{".endl()
            + "    return fract(sin(dot(co.xy ,vec2(12.9898,4.1414))) * 432758.5453);".endl()
            + "}".endl()
            + "vec3 cgl_random3(vec2 co)".endl()
            + "{".endl()
            + "    return vec3( cgl_random(co),cgl_random(co+0.5711),cgl_random(co+1.5711));".endl()
            + "}";
    },


    // low quality generative ranodm numbers
    "CGL.RANDOM_LOW": function ()
    {
        this.name = "randomNumber";
        this.srcHeadFrag = "".endl()
            + "float cgl_random(vec2 co)".endl()
            + "{".endl()
            + "    return fract(sin(dot(co.xy ,vec2(12.9898,4.1414))) * 358.5453);".endl()
            + "}".endl()
            + "vec3 cgl_random3(vec2 co)".endl()
            + "{".endl()
            + "    return vec3( cgl_random(co),cgl_random(co+0.5711),cgl_random(co+1.5711));".endl()
            + "}";
    },

    // texture based random numbers
    "CGL.RANDOM_TEX": function ()
    {
        this.name = "randomNumbertex";
        this.srcHeadFrag = "".endl()
            + "UNI sampler2D CGLRNDTEX;".endl()
            + "float cgl_random(vec2 co)".endl()
            + "{".endl()
            + "    return texture(CGLRNDTEX,co*5711.0).r;".endl()
            + "}".endl()
            + "vec3 cgl_random3(vec2 co)".endl()
            + "{".endl()
            + "    return texture(CGLRNDTEX,co*5711.0).rgb;".endl()
            + "}";

        this.initUniforms = function (shader)
        {
            return [new Uniform(shader, "t", "CGLRNDTEX", 7)];
        };

        this.onBind = function (cgl, shader)
        {
            Texture.getRandomTexture(cgl);
            cgl.setTexture(7, Texture.getRandomTexture(cgl).tex);
        };
    },
};



;// CONCATENATED MODULE: ./src/core/cgl/cgl_utils.js
/** @namespace CGL */

/**
 * multiply to get radians from degree, e.g. `360 * CGL.DEG2RAD`
 * @const {Number}
 * @memberof CGL
 * @static
 */
const cgl_utils_DEG2RAD = Math.PI / 180.0;

/**
 * to get degrees from radians, e.g. `3.14 * CGL.RAD2DEG`
 * @const {number}
 * @memberof CGL
 */
const cgl_utils_RAD2DEG = 180.0 / Math.PI;

const onLoadingAssetsFinished = null; // deprecated / remove later

/**
 * get normalized mouse wheel delta (including browser specific adjustment)
 * @function getWheelDelta
 * @static
 * @memberof CGL
 * @param {MouseEvent} event
 * @return {Number} normalized delta
 */
const isWindows = window.navigator.userAgent.contains("Windows");
const getWheelDelta_ = function (event)
{
    let normalized;
    if (event.wheelDelta)
    {
        // chrome
        normalized = (event.wheelDelta % 120) - 0 == -0 ? event.wheelDelta / 120 : event.wheelDelta / 30;
        normalized *= -1.5;
        if (isWindows) normalized *= 2;
    }
    else
    {
        // firefox
        let d = event.deltaY;
        if (event.shiftKey) d = event.deltaX;
        const rawAmmount = d || event.detail;
        normalized = -(rawAmmount % 3 ? rawAmmount * 10 : rawAmmount / 3);
        normalized *= -3;
    }

    if (normalized > 20) normalized = 20;
    if (normalized < -20) normalized = -20;

    return normalized;
};

const getWheelSpeed = getWheelDelta_;
const getWheelDelta = getWheelDelta_;

// from https://github.com/lodash/lodash/blob/master/escape.js

const htmlEscapes = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    "\"": "&quot;",
    "'": "&#39;",
};

/** Used to match HTML entities and HTML characters. */
const reUnescapedHtml = /[&<>"']/g;
const reHasUnescapedHtml = RegExp(reUnescapedHtml.source);

/*  eslint-disable */
const escapeHTML = function(string)
{
    return string && reHasUnescapedHtml.test(string) ?
        string.replace(reUnescapedHtml, function(chr) { return htmlEscapes[chr]; })
        : string || "";
}
/* eslint-enable */

;// CONCATENATED MODULE: ./src/core/cg/cg_shader.js



class CgShader extends EventTarget
{
    constructor()
    {
        super();
        this.id = simpleId();
        this._isValid = true;
        this._defines = [];

        this._moduleNames = [];
        this._modules = [];
        this._moduleNumId = 0;
    }

    /**
     * easily enable/disable a define without a value
     * @function toggleDefine
     * @memberof Shader
     * @instance
     * @param {name} name
     * @param {any} enabled value or port
     */
    toggleDefine(name, enabled)
    {
        if (enabled && typeof (enabled) == "object" && enabled.addEventListener) // port
        {
            if (enabled.changeListener)enabled.removeEventListener(enabled.changeListener);

            enabled.onToggleDefine = (v) =>
            {
                this.toggleDefine(name, v);
            };

            enabled.changeListener = enabled.on("change", enabled.onToggleDefine);
            enabled = enabled.get();
        }

        if (enabled) this.define(name);
        else this.removeDefine(name);
    }

    /**
     * add a define to a shader, e.g.  #define DO_THIS_THAT 1
     * @function define
     * @memberof Shader
     * @instance
     * @param {String} name
     * @param {Any} value (can be empty)
     */
    define(name, value)
    {
        if (value === null || value === undefined) value = "";

        if (typeof (value) == "object") // port
        {
            value.removeEventListener("change", value.onDefineChange);
            value.onDefineChange = (v) =>
            {
                this.define(name, v);
            };
            value.on("change", value.onDefineChange);

            value = value.get();
        }


        for (let i = 0; i < this._defines.length; i++)
        {
            if (this._defines[i][0] == name && this._defines[i][1] == value) return;
            if (this._defines[i][0] == name)
            {
                this._defines[i][1] = value;
                this.setWhyCompile("define " + name + " " + value);

                this._needsRecompile = true;
                return;
            }
        }
        this.setWhyCompile("define " + name + " " + value);
        this._needsRecompile = true;
        this._defines.push([name, value]);
    }

    getDefines()
    {
        return this._defines;
    }

    getDefine(name)
    {
        for (let i = 0; i < this._defines.length; i++)
            if (this._defines[i][0] == name) return this._defines[i][1];
        return null;
    }

    /**
     * return true if shader has define
     * @function hasDefine
     * @memberof Shader
     * @instance
     * @param {String} name
     * @return {Boolean}
     */
    hasDefine(name)
    {
        for (let i = 0; i < this._defines.length; i++)
            if (this._defines[i][0] == name) return true;
    }

    /**
     * remove a define from a shader
     * @param {name} name
     * @function removeDefine
     * @memberof Shader
     * @instance
     */
    removeDefine(name)
    {
        for (let i = 0; i < this._defines.length; i++)
        {
            if (this._defines[i][0] == name)
            {
                this._defines.splice(i, 1);
                this._needsRecompile = true;

                this.setWhyCompile("define removed:" + name);

                return;
            }
        }
    }


    hasModule(modId)
    {
        for (let i = 0; i < this._modules.length; i++)
        {
            if (this._modules[i].id == modId) return true;
        }
        return false;
    }

    setModules(names)
    {
        this._moduleNames = names;
    }


    /**
     * remove a module from shader
     * @function removeModule
     * @memberof Shader
     * @instance
     * @param {shaderModule} mod the module to be removed
     */
    removeModule(mod)
    {
        for (let i = 0; i < this._modules.length; i++)
        {
            if (mod && mod.id)
            {
                if (this._modules[i].id == mod.id || !this._modules[i])
                {
                    let found = true;
                    while (found)
                    {
                        found = false;
                        for (let j = 0; j < this._uniforms.length; j++)
                        {
                            if (this._uniforms[j].getName().startsWith(mod.prefix))
                            {
                                this._uniforms.splice(j, 1);
                                found = true;
                                continue;
                            }
                        }
                    }

                    this._needsRecompile = true;
                    this.setWhyCompile("remove module " + mod.title);
                    this._modules.splice(i, 1);
                    break;
                }
            }
        }
    }


    getNumModules()
    {
        return this._modules.length;
    }


    getCurrentModules() { return this._modules; }


    /**
     * add a module
     * @function addModule
     * @memberof Shader
     * @instance
     * @param {shaderModule} mod the module to be added
     * @param {shaderModule} [sibling] sibling module, new module will share the same group
     */
    addModule(mod, sibling)
    {
        if (this.hasModule(mod.id)) return;
        if (!mod.id) mod.id = CABLES.simpleId();
        if (!mod.numId) mod.numId = this._moduleNumId;
        if (!mod.num)mod.num = this._modules.length;
        if (sibling && !sibling.group) sibling.group = simpleId();

        if (!mod.group)
            if (sibling) mod.group = sibling.group;
            else mod.group = simpleId();

        mod.prefix = "mod" + mod.group + "_";
        this._modules.push(mod);

        this._needsRecompile = true;
        this.setWhyCompile("add module " + mod.title);
        this._moduleNumId++;

        return mod;
    }

    getAttributeSrc(mod, srcHeadVert, srcVert)
    {
        if (mod.attributes)
            for (let k = 0; k < mod.attributes.length; k++)
            {
                const r = this._getAttrSrc(mod.attributes[k], false);
                if (r.srcHeadVert)srcHeadVert += r.srcHeadVert;
                if (r.srcVert)srcVert += r.srcVert;
            }

        return { "srcHeadVert": srcHeadVert, "srcVert": srcVert };
    }

    replaceModuleSrc()
    {
        let srcHeadVert = "";

        for (let j = 0; j < this._modules.length; j++)
        {
            const mod = this._modules[j];
            if (mod.name == this._moduleNames[i])
            {
                srcHeadVert += "\n//---- MOD: group:" + mod.group + ": idx:" + j + " - prfx:" + mod.prefix + " - " + mod.title + " ------\n";

                srcVert += "\n\n//---- MOD: " + mod.title + " / " + mod.priority + " ------\n";


                if (mod.getAttributeSrc)
                {
                    const r = getAttributeSrc(mod, srcHeadVert, srcVert);
                    if (r.srcHeadVert)srcHeadVert += r.srcHeadVert;
                    if (r.srcVert)srcVert += r.srcVert;
                }


                srcHeadVert += mod.srcHeadVert || "";
                srcVert += mod.srcBodyVert || "";

                srcHeadVert += "\n//---- end mod ------\n";

                srcVert += "\n//---- end mod ------\n";

                srcVert = srcVert.replace(/{{mod}}/g, mod.prefix);
                srcHeadVert = srcHeadVert.replace(/{{mod}}/g, mod.prefix);

                srcVert = srcVert.replace(/MOD_/g, mod.prefix);
                srcHeadVert = srcHeadVert.replace(/MOD_/g, mod.prefix);
            }
        }


        vs = vs.replace("{{" + this._moduleNames[i] + "}}", srcVert);
    }
}



;// CONCATENATED MODULE: ./src/core/cgl/cgl_shader_default_glsl.vert
/* harmony default export */ const cgl_shader_default_glsl = ("{{MODULES_HEAD}}\nIN vec3 vPosition; //!@\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\nIN vec3 attrTangent,attrBiTangent;\n\nIN float attrVertIndex;\n\nOUT vec2 texCoord;\nOUT vec3 norm;\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\nvoid main()\n{\n    texCoord=attrTexCoord;\n    norm=attrVertNormal;\n    vec4 pos=vec4(vPosition,  1.0);\n    vec3 tangent=attrTangent;\n    vec3 bitangent=attrBiTangent;\n    mat4 mMatrix=modelMatrix;\n    gl_PointSize=10.0;\n\n    {{MODULE_VERTEX_POSITION}}\n\n    mat4 modelViewMatrix=viewMatrix*mMatrix;\n    {{MODULE_VERTEX_MODELVIEW}}\n\n    gl_Position = projMatrix * modelViewMatrix * pos;\n}\n");
;// CONCATENATED MODULE: ./src/core/cgl/cgl_shader.js









// ---------------------------------------------------------------------------


/*

proposal default shader variable names:

attrVertex - currently: vPosition
attrVertexIndex - currently: attrVertIndex
attrTexCoord
attrInstMat - currently: instMat
attrVertColor
attrTangent
attrBiTangent

uProjMatrix - currently: projMatrix
uModelMatrix - currently: modelMatrix
uNormalMatrix - currently: normalMatrix
uCamPosition - currently: camPos

*/


// ---------------------------------------------------------------------------

let materialIdCounter = 0;




function getDefaultVertexShader()
{
    return cgl_shader_default_glsl;
}


function getDefaultFragmentShader(r, g, b)
{
    if (r == undefined)
    {
        r = 0.5;
        g = 0.5;
        b = 0.5;
    }
    return ""
        .endl() + "IN vec2 texCoord;"
        .endl() + "{{MODULES_HEAD}}"
        .endl() + "void main()"
        .endl() + "{"
        .endl() + "    vec4 col=vec4(" + r + "," + g + "," + b + ",1.0);"
        .endl() + "    {{MODULE_COLOR}}"
        .endl() + "    outColor = col;"
        .endl() + "}";
};


/**
 * @class
 * @namespace external:CGL
 * @hideconstructor
 * @param _cgl
 * @param _name
 * @param _op
 * @example
 * var shader=new CGL.Shader(cgl,'MinimalMaterial');
 * shader.setSource(attachments.shader_vert,attachments.shader_frag);
 */
class Shader extends CgShader
{
    constructor (_cgl, _name, _op)
    {
        super();
        if (!_cgl) throw new Error("shader constructed without cgl " + _name);

        this._log = new Logger("cgl_shader");
        this._cgl = _cgl;

        if (!_name) this._log.stack("no shader name given");
        this._name = _name || "unknown";

        if (_op) this.opId = _op.id;
        this.glslVersion = 0;
        if (_cgl.glVersion > 1) this.glslVersion = 300;

        this._materialId = ++materialIdCounter;

        this._program = null;
        this._uniforms = [];
        this._drawBuffers = [true];

        this._needsRecompile = true;
        this._compileReason = "initial";

        this.ignoreMissingUniforms = false;
        this._projMatrixUniform = null;
        this._mvMatrixUniform = null;
        this._mMatrixUniform = null;
        this._vMatrixUniform = null;
        this._camPosUniform = null;
        this._normalMatrixUniform = null;
        this._inverseViewMatrixUniform = null;
        this._fromUserInteraction = false;

        this._attrVertexPos = -1;
        this.precision = _cgl.patch.config.glslPrecision || "highp";

        this._pMatrixState = -1;
        this._vMatrixState = -1;

        this._countMissingUniforms = 0;
        this._modGroupCount = 0; // not needed anymore...
        this._feedBackNames = [];
        this._attributes = [];

        this.glPrimitive = null;
        this.offScreenPass = false;
        this._extensions = [];
        this.srcVert = getDefaultVertexShader();
        this.srcFrag = getDefaultFragmentShader();
        this.lastCompile = 0;


        this._libs = [];
        this._structNames = [];
        this._structUniformNames = [];
        this._textureStackUni = [];
        this._textureStackTex = [];
        this._textureStackType = [];
        this._textureStackTexCgl = [];

        this._tempNormalMatrix = mat4.create();
        this._tempCamPosMatrix = mat4.create();
        this._tempInverseViewMatrix = mat4.create();
        this._tempInverseProjMatrix = mat4.create();

        this.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG", "MODULE_VERTEX_MODELVIEW"]);
    };







    isValid()
    {
        return this._isValid;
    };

    getCgl()
    {
        return this._cgl;
    };

    getName()
    {
        return this._name;
    };

    /**
     * enable an extension for the shader
     * @function enableExtension
     * @memberof Shader
     * @instance
     * @param name extension name
     */
    enableExtension(name)
    {
        this.setWhyCompile("enable extension " + name);
        this._needsRecompile = true;
        this._extensions.push(name);
    };

    getAttrVertexPos()
    {
        return this._attrVertexPos;
    };

    hasTextureUniforms()
    {
        for (let i = 0; i < this._uniforms.length; i++)
            if (this._uniforms[i].getType() == "t") return true;
        return false;
    };

    setWhyCompile(why)
    {
        this._compileReason = why;
    };

    /**
     * copy all uniform values from another shader
     * @function copyUniforms
     * @memberof Shader
     * @instance
     * @param origShader uniform values will be copied from this shader
     */
    copyUniformValues(origShader)
    {
        // console.log(origShader._uniforms);
        for (let i = 0; i < origShader._uniforms.length; i++)
        {
            if (!this._uniforms[i])
            {
                this._log.log("unknown uniform?!");
                continue;
            }

            // this._log.log(origShader._uniforms[i].getName());
            // this.getUniform(origShader._uniforms[i].)
            // this._uniforms[i].set(origShader._uniforms[i].getValue());


            // if (origShader._uniforms[i].getName().contains("pathPoints"))
            //     console.log("copyUniformValues", origShader._uniforms[i].getName(), origShader._uniforms[i].getValue());

            this.getUniform(origShader._uniforms[i].getName()).set(origShader._uniforms[i].getValue());
        }

        this.popTextures();
        for (let i = 0; i < origShader._textureStackUni.length; i++)
        {
            this._textureStackUni[i] = origShader._textureStackUni[i];
            this._textureStackTex[i] = origShader._textureStackTex[i];
            this._textureStackType[i] = origShader._textureStackType[i];
            this._textureStackTexCgl[i] = origShader._textureStackTexCgl[i];
        }

        // this._textureStackUni = [];
        // this._textureStackTex = [];
        // this._textureStackType = [];
        // this._textureStackTexCgl = [];
    };

    /**
     * copy current shader
     * @function copy
     * @memberof Shader
     * @instance
     * @returns newShader
     */
    copy()
    {
        const shader = new Shader(this._cgl, this._name + " copy");
        shader.setSource(this.srcVert, this.srcFrag);

        shader._modules = JSON.parse(JSON.stringify(this._modules));
        shader._defines = JSON.parse(JSON.stringify(this._defines));

        shader._modGroupCount = this._modGroupCount;
        shader._moduleNames = this._moduleNames;
        shader.glPrimitive = this.glPrimitive;
        shader.offScreenPass = this.offScreenPass;
        shader._extensions = this._extensions;
        shader.wireframe = this.wireframe;
        shader._attributes = this._attributes;

        for (let i = 0; i < this._uniforms.length; i++)
        {
            const u = this._uniforms[i].copy(shader);
            u.resetLoc();
        }

        this.setWhyCompile("copy");
        shader._needsRecompile = true;
        return shader;
    };


    /**
     * set shader source code
     * @function setSource
     * @memberof Shader
     * @instance
     * @param {String} srcVert
     * @param {String} srcFrag
     * @param {Bool} fromUserInteraction
     */
    setSource(srcVert, srcFrag, fromUserInteraction)
    {
        this._fromUserInteraction = fromUserInteraction;
        this.srcVert = srcVert;
        this.srcFrag = srcFrag;
        this.setWhyCompile("Source changed");
        this._needsRecompile = true;
        this._isValid = true;
    };

    _addLibs(src)
    {
        for (const id in ShaderLibMods)
        {
            if (src.contains(id))
            {
                const lib = new ShaderLibMods[id]();
                src = src.replace("{{" + id + "}}", lib.srcHeadFrag);
                this._libs.push(lib);
                if (lib.initUniforms)lib.initUniforms(this);
            }
        }

        return src;
    };

    createStructUniforms()
    {
        // * create structs
        let structStrFrag = "";
        let structStrVert = ""; // TODO: not used yet

        this._structNames = [];
        // * reset the arrays holding the value each recompile so we don't skip structs
        // * key value mapping so the same struct can be added twice (two times the same modifier)
        this._injectedStringsFrag = {};
        this._injectedStringsVert = {};

        this._structUniformNamesIndicesFrag = [];
        this._structUniformNamesIndicesVert = [];

        for (let i = 0; i < this._uniforms.length; i++)
        {
            // * only add uniforms to struct that are a member of a struct
            if (this._uniforms[i].isStructMember())
            {
                const injectionString = "{{INJECTION_POINT_STRUCT_" + this._uniforms[i]._structName + "}}";

                // * check if struct is not already part of shader
                if (!this._structNames.includes(this._uniforms[i]._structName))
                {
                    // * create struct definition with placeholder string to inject
                    const structDefinition = "struct "
                        + this._uniforms[i]._structName + " {".endl()
                        + injectionString
                        + "};".endl().endl();

                    if (this._uniforms[i].getShaderType() === "both" || this._uniforms[i].getShaderType() === "frag")
                        structStrFrag = structStrFrag.concat(structDefinition);

                    if (this._uniforms[i].getShaderType() === "both" || this._uniforms[i].getShaderType() === "vert")
                        structStrVert = structStrVert.concat(structDefinition);

                    this._structNames.push(this._uniforms[i]._structName);
                    this._injectedStringsFrag[this._uniforms[i]._structName] = [];
                    this._injectedStringsVert[this._uniforms[i]._structName] = [];
                }

                // * create member & comment
                let comment = "";
                if (this._uniforms[i].comment) comment = " // " + this._uniforms[i].comment;

                let stringToInsert = "";
                if (this._uniforms[i].getGlslTypeString() == undefined)stringToInsert += "//";
                stringToInsert += "  " + this._uniforms[i].getGlslTypeString()
                        + " " + this._uniforms[i]._propertyName + ";"
                        + comment;

                if (this._uniforms[i].getShaderType() === "both")
                {
                    // * inject member before {injectionString}
                    if (
                        !this._injectedStringsFrag[this._uniforms[i]._structName].contains(stringToInsert)
                    && !this._injectedStringsVert[this._uniforms[i]._structName].contains(stringToInsert))
                    {
                        const insertionIndexFrag = structStrFrag.lastIndexOf(injectionString);
                        const insertionIndexVert = structStrVert.lastIndexOf(injectionString);

                        structStrFrag =
                            structStrFrag.slice(0, insertionIndexFrag)
                            + stringToInsert + structStrFrag.slice(insertionIndexFrag - 1);

                        structStrVert =
                            structStrVert.slice(0, insertionIndexVert)
                            + stringToInsert + structStrVert.slice(insertionIndexVert - 1);

                        this._injectedStringsFrag[this._uniforms[i]._structName].push(stringToInsert);
                        this._injectedStringsVert[this._uniforms[i]._structName].push(stringToInsert);
                    }

                    if (!this._structUniformNamesIndicesFrag.includes(i)) this._structUniformNamesIndicesFrag.push(i);
                    if (!this._structUniformNamesIndicesVert.includes(i)) this._structUniformNamesIndicesVert.push(i);
                }
                else if (this._uniforms[i].getShaderType() === "frag")
                {
                    // * inject member before {injectionString}
                    if (!this._injectedStringsFrag[this._uniforms[i]._structName].includes(stringToInsert)) //
                    {
                        const insertionIndexFrag = structStrFrag.lastIndexOf(injectionString);

                        structStrFrag =
                            structStrFrag.slice(0, insertionIndexFrag)
                            + stringToInsert + structStrFrag.slice(insertionIndexFrag - 1);

                        this._injectedStringsFrag[this._uniforms[i]._structName].push(stringToInsert);
                    }

                    if (!this._structUniformNamesIndicesFrag.includes(i)) this._structUniformNamesIndicesFrag.push(i);
                }
                else if (this._uniforms[i].getShaderType() === "vert")
                {
                    // * inject member before {injectionString}
                    if (!this._injectedStringsVert[this._uniforms[i]._structName].includes(stringToInsert))
                    {
                        const insertionIndexVert = structStrVert.lastIndexOf(injectionString);

                        structStrVert =
                            structStrVert.slice(0, insertionIndexVert)
                            + stringToInsert + structStrVert.slice(insertionIndexVert - 1);

                        this._injectedStringsVert[this._uniforms[i]._structName].push(stringToInsert);
                    }

                    if (!this._structUniformNamesIndicesVert.includes(i)) this._structUniformNamesIndicesVert.push(i);
                }
            }
        }

        // * dedupe injected uni declarations
        this._uniDeclarationsFrag = [];
        this._uniDeclarationsVert = [];

        // * remove struct injection points and add uniform in fragment
        for (let i = 0; i < this._structUniformNamesIndicesFrag.length; i += 1)
        {
            const index = this._structUniformNamesIndicesFrag[i];
            const uniDeclarationString = "UNI " + this._uniforms[index]._structName + " " + this._uniforms[index]._structUniformName + ";".endl();

            if (!this._uniDeclarationsFrag.includes(uniDeclarationString))
            {
                const injectionString = "{{INJECTION_POINT_STRUCT_" + this._uniforms[index]._structName + "}}";

                structStrFrag = structStrFrag.replace(injectionString, "");
                structStrFrag += uniDeclarationString;

                this._uniDeclarationsFrag.push(uniDeclarationString);
            }
        }

        // * remove struct injection points and add uniform in vertex
        for (let i = 0; i < this._structUniformNamesIndicesVert.length; i += 1)
        {
            const index = this._structUniformNamesIndicesVert[i];
            const uniDeclarationString = "UNI " + this._uniforms[index]._structName + " " + this._uniforms[index]._structUniformName + ";".endl();

            if (!this._uniDeclarationsVert.includes(uniDeclarationString))
            {
                const injectionString = "{{INJECTION_POINT_STRUCT_" + this._uniforms[index]._structName + "}}";

                structStrVert = structStrVert.replace(injectionString, "");
                structStrVert += uniDeclarationString;
                this._uniDeclarationsVert.push(uniDeclarationString);
            }
        }

        return [structStrVert, structStrFrag];
    };

    _getAttrSrc(attr, firstLevel)
    {
        const r = {};
        if (attr.name && attr.type)
        {
            r.srcHeadVert = "";
            if (!firstLevel) r.srcHeadVert += "#ifndef ATTRIB_" + attr.name.endl();
            r.srcHeadVert += "#define ATTRIB_" + attr.name.endl();
            r.srcHeadVert += "IN " + attr.type + " " + attr.name + ";".endl();
            if (!firstLevel) r.srcHeadVert += "#endif".endl();

            if (attr.nameFrag)
            {
                r.srcHeadVert += "";
                if (!firstLevel) r.srcHeadVert += "#ifndef ATTRIB_" + attr.nameFrag.endl();
                r.srcHeadVert += "#define ATTRIB_" + attr.nameFrag.endl();
                r.srcHeadVert += "OUT " + attr.type + " " + attr.nameFrag + ";".endl();
                if (!firstLevel) r.srcHeadVert += "#endif".endl();

                r.srcVert = "".endl() + attr.nameFrag + "=" + attr.name + ";";

                r.srcHeadFrag = "";
                if (!firstLevel) r.srcHeadFrag += "#ifndef ATTRIB_" + attr.nameFrag.endl();
                r.srcHeadFrag += "#define ATTRIB_" + attr.nameFrag.endl();
                r.srcHeadFrag += "IN " + attr.type + " " + attr.nameFrag + ";".endl();
                if (!firstLevel) r.srcHeadFrag += "#endif".endl();
            }
        }
        return r;
    };

    compile()
    {
        if (this._cgl.aborted) return;
        const startTime = performance.now();



        this._cgl.profileData.profileShaderCompiles++;
        this._cgl.profileData.profileShaderCompileName = this._name + " [" + this._compileReason + "]";

        let extensionString = "";
        if (this._extensions)
            for (let i = 0; i < this._extensions.length; i++)
                extensionString += "#extension " + this._extensions[i] + " : enable".endl();

        let definesStr = "";
        if (this._defines.length) definesStr = "\n// cgl generated".endl();
        for (let i = 0; i < this._defines.length; i++)
            definesStr += "#define " + this._defines[i][0] + " " + this._defines[i][1] + "".endl();

        const structStrings = this.createStructUniforms();
        this._cgl.profileData.addHeavyEvent("shader compile", this._name + " [" + this._compileReason + "]");
        this._compileReason = "";



        if (this._uniforms)
        {
            // * we create an array of the uniform names to check our indices & an array to save them
            const uniNames = this._uniforms.map((uni) => { return uni._name; });
            const indicesToRemove = [];

            // * we go through our uniforms and check if the same name is contained somewhere further in the array
            // * if so, we add the current index to be removed later
            for (let i = 0; i < this._uniforms.length; i++)
            {
                const uni = this._uniforms[i];
                const nextIndex = uniNames.indexOf(uni._name, i + 1);
                if (nextIndex > -1) indicesToRemove.push(i);
            }

            // * after that, we go through the uniforms backwards (so we keep the order) and remove the indices
            // * also, we reset the locations of all the other valid uniforms
            for (let j = this._uniforms.length - 1; j >= 0; j -= 1)
            {
                if (indicesToRemove.includes(j)) this._uniforms.splice(j, 1);
                else this._uniforms[j].resetLoc();
            }
        }

        this._cgl.printError("uniform resets");

        if (this.hasTextureUniforms()) definesStr += "#define HAS_TEXTURES".endl();

        let vs = "";
        let fs = "";

        if (!this.srcFrag)
        {
            this._log.warn("[cgl shader] has no fragment source!", this._name, this);
            this.srcVert = getDefaultVertexShader();
            this.srcFrag = getDefaultFragmentShader();
            // return;
        }

        if (this.glslVersion == 300)
        {
            vs = "#version 300 es"
                .endl() + "// "
                .endl() + "// vertex shader " + this._name
                .endl() + "// "
                .endl() + "precision " + this.precision + " float;"
                .endl() + "precision " + this.precision + " sampler2D;"
                .endl() + ""
                .endl() + "#define WEBGL2"
                .endl() + "#define texture2D texture"
                .endl() + "#define UNI uniform"
                .endl() + "#define IN in"
                .endl() + "#define OUT out"
                .endl();

            fs = "#version 300 es"
                .endl() + "// "
                .endl() + "// fragment shader " + this._name
                .endl() + "// "
                .endl() + "precision " + this.precision + " float;"
                .endl() + "precision " + this.precision + " sampler2D;"
                .endl() + ""
                .endl() + "#define WEBGL2"
                .endl() + "#define texture2D texture"
                .endl() + "#define IN in"
                .endl() + "#define OUT out"
                .endl() + "#define UNI uniform"
                .endl() + "{{DRAWBUFFER}}"

                .endl();
        }
        else
        {
            fs = ""
                .endl() + "// "
                .endl() + "// fragment shader " + this._name
                .endl() + "// "
                .endl() + "#define WEBGL1"
                .endl() + "#define texture texture2D"
                .endl() + "#define outColor gl_FragColor"
                .endl() + "#define IN varying"
                .endl() + "#define UNI uniform"
                .endl();

            vs = ""
                .endl() + "// "
                .endl() + "// vertex shader " + this._name
                .endl() + "// "
                .endl() + "#define WEBGL1"
                .endl() + "#define texture texture2D"
                .endl() + "#define OUT varying"
                .endl() + "#define IN attribute"
                .endl() + "#define UNI uniform"
                .endl();
        }

        let uniformsStrVert = "\n// cgl generated".endl();
        let uniformsStrFrag = "\n// cgl generated".endl();


        fs += "\n// active mods: --------------- ";
        vs += "\n// active mods: --------------- ";

        let foundModsFrag = false;
        let foundModsVert = false;
        for (let i = 0; i < this._moduleNames.length; i++)
        {
            for (let j = 0; j < this._modules.length; j++)
            {
                if (this._modules[j].name == this._moduleNames[i])
                {
                    if (this._modules[j].srcBodyFrag || this._modules[j].srcHeadFrag)
                    {
                        foundModsFrag = true;
                        fs += "\n// " + i + "." + j + ". " + this._modules[j].title + " (" + this._modules[j].name + ")";
                    }
                    if (this._modules[j].srcBodyVert || this._modules[j].srcHeadVert)
                    {
                        vs += "\n// " + i + "." + j + ". " + this._modules[j].title + " (" + this._modules[j].name + ")";
                        foundModsVert = true;
                    }
                }
            }
        }
        if (!foundModsVert)fs += "\n// no mods used...";
        if (!foundModsFrag)fs += "\n// no mods used...";
        fs += "\n";
        vs += "\n";

        for (let i = 0; i < this._uniforms.length; i++)
        {
            if (this._uniforms[i].shaderType && !this._uniforms[i].isStructMember())
            {
                let uniStr = "";
                if (!this._uniforms[i].getGlslTypeString())uniStr += "// ";
                uniStr += "UNI " + this._uniforms[i].getGlslTypeString() + " " + this._uniforms[i].getName();
                let comment = "";
                if (this._uniforms[i].comment) comment = " // " + this._uniforms[i].comment;

                if (this._uniforms[i].shaderType == "vert" || this._uniforms[i].shaderType == "both")
                    if (!this.srcVert.contains(uniStr) && !this.srcVert.contains("uniform " + this._uniforms[i].getGlslTypeString() + " " + this._uniforms[i].getName()))
                        uniformsStrVert += uniStr + ";" + comment.endl();

                if (this._uniforms[i].shaderType == "frag" || this._uniforms[i].shaderType == "both")
                    if (!this.srcFrag.contains(uniStr) && !this.srcFrag.contains("uniform " + this._uniforms[i].getGlslTypeString() + " " + this._uniforms[i].getName()))
                        uniformsStrFrag += uniStr + ";" + comment.endl();
            }
        }


        let countUniFrag = 0;
        let countUniVert = 0;
        for (let i = 0; i < this._uniforms.length; i++)
        {
            if (this._uniforms[i].shaderType && !this._uniforms[i].isStructMember())
            {
                if (this._uniforms[i].shaderType == "vert" || this._uniforms[i].shaderType == "both") countUniVert++;
                if (this._uniforms[i].shaderType == "frag" || this._uniforms[i].shaderType == "both") countUniFrag++;
            }
        }
        if (countUniFrag >= this._cgl.maxUniformsFrag) this._log.warn("[cgl_shader] num uniforms frag: " + countUniFrag + " / " + this._cgl.maxUniformsFrag);
        if (countUniVert >= this._cgl.maxUniformsVert) this._log.warn("[cgl_shader] num uniforms vert: " + countUniVert + " / " + this._cgl.maxUniformsVert);


        if (!fs.contains("precision")) fs = "precision " + this.precision + " float;".endl() + fs;
        if (!vs.contains("precision")) vs = "precision " + this.precision + " float;".endl() + vs;
        if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))
        {
            fs += "#define MOBILE".endl();
            vs += "#define MOBILE".endl();
        }
        vs = extensionString + vs + definesStr + structStrings[0] + uniformsStrVert + "\n// -- \n" + this.srcVert;
        fs = extensionString + fs + definesStr + structStrings[1] + uniformsStrFrag + "\n// -- \n" + this.srcFrag;


        let srcHeadVert = "";
        let srcHeadFrag = "";

        // testing if this breaks things...
        // this._modules.sort(function (a, b)
        // {
        //     return a.group - b.group;
        // });

        this._modules.sort(function (a, b)
        {
            return a.priority || 0 - b.priority || 0;
        });


        let addedAttribs = false;

        for (let i = 0; i < this._moduleNames.length; i++)
        {
            let srcVert = "";
            let srcFrag = "";

            if (!addedAttribs)
            {
                addedAttribs = true;

                for (let k = 0; k < this._attributes.length; k++)
                {
                    const r = this._getAttrSrc(this._attributes[k], true);
                    if (r.srcHeadVert)srcHeadVert += r.srcHeadVert;
                    if (r.srcVert)srcVert += r.srcVert;
                    if (r.srcHeadFrag)srcHeadFrag += r.srcHeadFrag;
                }
            }

            for (let j = 0; j < this._modules.length; j++)
            {
                const mod = this._modules[j];
                if (mod.name == this._moduleNames[i])
                {
                    srcHeadVert += "\n//---- MOD: group:" + mod.group + ": idx:" + j + " - prfx:" + mod.prefix + " - " + mod.title + " ------\n";
                    srcHeadFrag += "\n//---- MOD: group:" + mod.group + ": idx:" + j + " - prfx:" + mod.prefix + " - " + mod.title + " ------\n";

                    srcVert += "\n\n//---- MOD: " + mod.title + " / " + mod.priority + " ------\n";
                    srcFrag += "\n\n//---- MOD: " + mod.title + " / " + mod.priority + " ------\n";

                    if (mod.attributes)
                        for (let k = 0; k < mod.attributes.length; k++)
                        {
                            const r = this._getAttrSrc(mod.attributes[k], false);
                            if (r.srcHeadVert)srcHeadVert += r.srcHeadVert;
                            if (r.srcVert)srcVert += r.srcVert;
                            if (r.srcHeadFrag)srcHeadFrag += r.srcHeadFrag;
                        }

                    srcHeadVert += mod.srcHeadVert || "";
                    srcHeadFrag += mod.srcHeadFrag || "";
                    srcVert += mod.srcBodyVert || "";
                    srcFrag += mod.srcBodyFrag || "";

                    srcHeadVert += "\n//---- end mod ------\n";
                    srcHeadFrag += "\n//---- end mod ------\n";

                    srcVert += "\n//---- end mod ------\n";
                    srcFrag += "\n//---- end mod ------\n";

                    srcVert = srcVert.replace(/{{mod}}/g, mod.prefix);
                    srcFrag = srcFrag.replace(/{{mod}}/g, mod.prefix);
                    srcHeadVert = srcHeadVert.replace(/{{mod}}/g, mod.prefix);
                    srcHeadFrag = srcHeadFrag.replace(/{{mod}}/g, mod.prefix);

                    srcVert = srcVert.replace(/MOD_/g, mod.prefix);
                    srcFrag = srcFrag.replace(/MOD_/g, mod.prefix);
                    srcHeadVert = srcHeadVert.replace(/MOD_/g, mod.prefix);
                    srcHeadFrag = srcHeadFrag.replace(/MOD_/g, mod.prefix);
                }
            }


            vs = vs.replace("{{" + this._moduleNames[i] + "}}", srcVert);
            fs = fs.replace("{{" + this._moduleNames[i] + "}}", srcFrag);
        }


        vs = vs.replace("{{MODULES_HEAD}}", srcHeadVert);
        fs = fs.replace("{{MODULES_HEAD}}", srcHeadFrag);


        vs = this._addLibs(vs);
        fs = this._addLibs(fs);


        // SETUP draw buffers / multi texture render targets

        let drawBufferStr = "";
        for (let i = 0; i < 16; i++)
            if (fs.contains("outColor" + i)) this._drawBuffers[i] = true;

        if (this._drawBuffers.length == 1)
        {
            drawBufferStr = "out vec4 outColor;".endl();
            drawBufferStr += "#define gl_FragColor outColor".endl();
        }
        else
        {
            drawBufferStr += "#define MULTI_COLORTARGETS".endl();
            drawBufferStr += "vec4 outColor;".endl();

            let count = 0;
            for (let i = 0; i < this._drawBuffers.length; i++)
            {
                if (count == 0) drawBufferStr += "#define gl_FragColor outColor" + i + "".endl();
                drawBufferStr += "layout(location = " + i + ") out vec4 outColor" + i + ";".endl();
                count++;
            }
        }

        fs = fs.replace("{{DRAWBUFFER}}", drawBufferStr);
        // //////


        if (!this._program)
        {
            this._program = this._createProgram(vs, fs);
        }
        else
        {
            // this.vshader=createShader(vs, gl.VERTEX_SHADER, this.vshader );
            // this.fshader=createShader(fs, gl.FRAGMENT_SHADER, this.fshader );
            // linkProgram(program);
            this._program = this._createProgram(vs, fs);

            this._projMatrixUniform = null;

            for (let i = 0; i < this._uniforms.length; i++) this._uniforms[i].resetLoc();
        }

        this.finalShaderFrag = fs;
        this.finalShaderVert = vs;


        MESH.lastMesh = null;
        MESH.lastShader = null;

        this._countMissingUniforms = 0;
        this._needsRecompile = false;
        this.lastCompile = now();

        // this._cgl.printError("shader compile");

        this._cgl.profileData.shaderCompileTime += performance.now() - startTime;
    };

    hasChanged()
    {
        return this._needsRecompile;
    }


    bind()
    {
        if (!this._isValid || this._cgl.aborted) return;

        MESH.lastShader = this;

        if (!this._program || this._needsRecompile) this.compile();
        if (!this._isValid) return;

        if (!this._projMatrixUniform && !this.ignoreMissingUniforms)
        {
            this._countMissingUniforms++;
            // if (this._countMissingUniforms == 10)console.log("stopping getlocation of missing uniforms...", this._name);
            if (this._countMissingUniforms < 10)
            {
                this._projMatrixUniform = this._cgl.gl.getUniformLocation(this._program, constants_CONSTANTS.SHADER.SHADERVAR_UNI_PROJMAT);
                this._attrVertexPos = this._cgl.glGetAttribLocation(this._program, constants_CONSTANTS.SHADER.SHADERVAR_VERTEX_POSITION);
                this._mvMatrixUniform = this._cgl.gl.getUniformLocation(this._program, "mvMatrix");
                this._vMatrixUniform = this._cgl.gl.getUniformLocation(this._program, constants_CONSTANTS.SHADER.SHADERVAR_UNI_VIEWMAT);
                this._mMatrixUniform = this._cgl.gl.getUniformLocation(this._program, constants_CONSTANTS.SHADER.SHADERVAR_UNI_MODELMAT);
                this._camPosUniform = this._cgl.gl.getUniformLocation(this._program, constants_CONSTANTS.SHADER.SHADERVAR_UNI_VIEWPOS);
                this._normalMatrixUniform = this._cgl.gl.getUniformLocation(this._program, constants_CONSTANTS.SHADER.SHADERVAR_UNI_NORMALMAT);
                this._inverseViewMatrixUniform = this._cgl.gl.getUniformLocation(this._program, constants_CONSTANTS.SHADER.SHADERVAR_UNI_INVVIEWMAT);
                this._inverseProjMatrixUniform = this._cgl.gl.getUniformLocation(this._program, constants_CONSTANTS.SHADER.SHADERVAR_UNI_INVPROJMAT);
                this._materialIdUniform = this._cgl.gl.getUniformLocation(this._program, constants_CONSTANTS.SHADER.SHADERVAR_UNI_MATERIALID);
                this._objectIdUniform = this._cgl.gl.getUniformLocation(this._program, constants_CONSTANTS.SHADER.SHADERVAR_UNI_OBJECTID);

                for (let i = 0; i < this._uniforms.length; i++) this._uniforms[i].needsUpdate = true;
            }
        }


        if (this._cgl.currentProgram != this._program)
        {
            this._cgl.profileData.profileShaderBinds++;
            this._cgl.gl.useProgram(this._program);
            this._cgl.currentProgram = this._program;
        }

        for (let i = 0; i < this._uniforms.length; i++)
            if (this._uniforms[i].needsUpdate) this._uniforms[i].updateValue();

        if (this._pMatrixState != this._cgl.getProjectionMatrixStateCount())
        {
            this._pMatrixState = this._cgl.getProjectionMatrixStateCount();
            this._cgl.gl.uniformMatrix4fv(this._projMatrixUniform, false, this._cgl.pMatrix);
            this._cgl.profileData.profileMVPMatrixCount++;
        }

        if (this._objectIdUniform)
            this._cgl.gl.uniform1f(this._objectIdUniform, ++this._cgl.tempData.objectIdCounter);

        if (this._materialIdUniform)
            this._cgl.gl.uniform1f(this._materialIdUniform, this._materialId);

        if (this._vMatrixUniform)
        {
            if (this._vMatrixState != this._cgl.getViewMatrixStateCount())
            {
                this._cgl.gl.uniformMatrix4fv(this._vMatrixUniform, false, this._cgl.vMatrix);
                this._cgl.profileData.profileMVPMatrixCount++;
                this._vMatrixState = this._cgl.getViewMatrixStateCount();

                if (this._inverseViewMatrixUniform)
                {
                    mat4.invert(this._tempInverseViewMatrix, this._cgl.vMatrix);
                    this._cgl.gl.uniformMatrix4fv(this._inverseViewMatrixUniform, false, this._tempInverseViewMatrix);
                    this._cgl.profileData.profileMVPMatrixCount++;
                }
                if (this._inverseProjMatrixUniform)
                {
                    mat4.invert(this._tempInverseProjMatrix, this._cgl.pMatrix);
                    this._cgl.gl.uniformMatrix4fv(this._inverseProjMatrixUniform, false, this._tempInverseProjMatrix);
                    this._cgl.profileData.profileMVPMatrixCount++;
                }
            }
            this._cgl.gl.uniformMatrix4fv(this._mMatrixUniform, false, this._cgl.mMatrix);
            this._cgl.profileData.profileMVPMatrixCount++;

            if (this._camPosUniform)
            {
                mat4.invert(this._tempCamPosMatrix, this._cgl.vMatrix);
                this._cgl.gl.uniform3f(this._camPosUniform, this._tempCamPosMatrix[12], this._tempCamPosMatrix[13], this._tempCamPosMatrix[14]);
                this._cgl.profileData.profileMVPMatrixCount++;
            }
        }
        else
        {
            // mvmatrix deprecated....
            const tempmv = mat4.create();

            mat4.mul(tempmv, this._cgl.vMatrix, this._cgl.mMatrix);
            this._cgl.gl.uniformMatrix4fv(this._mvMatrixUniform, false, tempmv);
            this._cgl.profileData.profileMVPMatrixCount++;
        }

        if (this._normalMatrixUniform)
        {
            // mat4.mul(this._tempNormalMatrix, this._cgl.vMatrix, this._cgl.mMatrix);
            mat4.invert(this._tempNormalMatrix, this._cgl.mMatrix);
            mat4.transpose(this._tempNormalMatrix, this._tempNormalMatrix);

            this._cgl.gl.uniformMatrix4fv(this._normalMatrixUniform, false, this._tempNormalMatrix);
            this._cgl.profileData.profileMVPMatrixCount++;
        }

        for (let i = 0; i < this._libs.length; i++)
        {
            if (this._libs[i].onBind) this._libs[i].onBind.bind(this._libs[i])(this._cgl, this);
        }

        this._bindTextures();

        return this._isValid;
    };

    unBind()
    {
    };


    dispose()
    {
        this._cgl.gl.deleteProgram(this._program);
    };

    needsRecompile()
    {
        return this._needsRecompile;
    };

    setDrawBuffers(arr)
    {
        console.log("useless drawbuffers...?!");
        // if (this._drawBuffers.length !== arr.length)
        // {
        //     this._drawBuffers = arr;
        //     this._needsRecompile = true;
        //     this.setWhyCompile("setDrawBuffers");
        //     return;
        // }
        // for (let i = 0; i < arr.length; i++)
        // {
        //     if (arr[i] !== this._drawBuffers[i])
        //     {
        //         this._drawBuffers = arr;
        //         this._needsRecompile = true;
        //         this.setWhyCompile("setDrawBuffers");
        //         return;
        //     }
        // }
    };

    getUniforms()
    {
        return this._uniforms;
    };

    getUniform(name)
    {
        for (let i = 0; i < this._uniforms.length; i++)
            if (this._uniforms[i].getName() == name)
                return this._uniforms[i];
        return null;
    };

    removeAllUniforms()
    {
        this._uniforms = [];
        // for (let i = 0; i < this._uniforms.length; i++)
        //     this.removeUniform(this._uniforms[i].name);
    };

    removeUniform(name)
    {
        for (let i = 0; i < this._uniforms.length; i++)
        {
            if (this._uniforms[i].getName() == name)
            {
                this._uniforms.splice(i, 1);
            }
        }
        this._needsRecompile = true;
        this.setWhyCompile("remove uniform " + name);
    };


    _addUniform(uni)
    {
        this._uniforms.push(uni);
        this.setWhyCompile("add uniform " + name);
        this._needsRecompile = true;
    };

    /**
     * add a uniform to the fragment shader
     * @param {String} type ['f','t', etc]
     * @param {String} name
     * @param {any} valueOrPort value or port
     * @param p2
     * @param p3
     * @param p4
     * @memberof Shader
     * @instance
     * @function addUniformFrag
     * @returns {CGL.Uniform}
     */
    addUniformFrag(type, name, valueOrPort, p2, p3, p4)
    {
        const uni = new CGL.Uniform(this, type, name, valueOrPort, p2, p3, p4);
        uni.shaderType = "frag";
        return uni;
    };

    /**
     * add a uniform to the vertex shader
     * @param {String} type ['f','t', etc]
     * @param {String} name
     * @param {any} valueOrPort value or port
     * @param p2
     * @param p3
     * @param p4
     * @memberof Shader
     * @instance
     * @function addUniformVert
     * @returns {CGL.Uniform}
     */
    addUniformVert(type, name, valueOrPort, p2, p3, p4)
    {
        const uni = new CGL.Uniform(this, type, name, valueOrPort, p2, p3, p4);
        uni.shaderType = "vert";
        return uni;
    };
    /**
     * add a uniform to both shaders
     * @param {String} type ['f','t', etc]
     * @param {String} name
     * @param {any} valueOrPort value or port
     * @param p2
     * @param p3
     * @param p4
     * @memberof Shader
     * @instance
     * @function addUniformBoth
     * @returns {CGL.Uniform}
     */
    addUniformBoth(type, name, valueOrPort, p2, p3, p4)
    {
        const uni = new CGL.Uniform(this, type, name, valueOrPort, p2, p3, p4);
        uni.shaderType = "both";
        return uni;
    };

    /**
     * add a struct & its uniforms to the fragment shader
     * @param {String} structName name of the struct, i.e.: LightStruct
     * @param {String} uniformName name of the struct uniform in the shader, i.e.: lightUni
     * @param {Array} members array of objects containing the struct members. see example for structure

     * @memberof Shader
     * @instance
     * @function addUniformStructFrag
     * @returns {Object}
     * @example
     * const shader = new CGL.Shader(cgl, 'MinimalMaterial');
     * shader.setSource(attachments.shader_vert, attachments.shader_frag);
     * shader.addUniformStructFrag("Light", "uniformLight", [
     * { "type": "3f", "name": "position", "v1": null },
     * { "type": "4f", "name": "color", "v1": inR, v2: inG, v3: inB, v4: inAlpha }
     * ]);
     */
    addUniformStructFrag(structName, uniformName, members)
    {
        const uniforms = {};

        if (!members) return uniforms;

        for (let i = 0; i < members.length; i += 1)
        {
            const member = members[i];
            if (!this.hasUniform(uniformName + "." + member.name))
            {
                const uni = new CGL.Uniform(this, member.type, uniformName + "." + member.name, member.v1, member.v2, member.v3, member.v4, uniformName, structName, member.name);
                uni.shaderType = "frag";
                uniforms[uniformName + "." + member.name] = uni;
            }
        }

        return uniforms;
    };

    /**
     * add a struct & its uniforms to the vertex shader
     * @param {String} structName name of the struct, i.e.: LightStruct
     * @param {String} uniformName name of the struct uniform in the shader, i.e.: lightUni
     * @param {Array} members array of objects containing the struct members. see example for structure

     * @memberof Shader
     * @instance
     * @function addUniformStructVert
     * @returns {CGL.Uniform}
     * @example
     * const shader = new CGL.Shader(cgl, 'MinimalMaterial');
     * shader.setSource(attachments.shader_vert, attachments.shader_frag);
     * shader.addUniformStructVert("Light", "uniformLight", [
     * { "type": "3f", "name": "position", "v1": null },
     * { "type": "4f", "name": "color", "v1": inR, v2: inG, v3: inB, v4: inAlpha }
     * ]);
     */
    addUniformStructVert(structName, uniformName, members)
    {
        const uniforms = {};

        if (!members) return uniforms;

        for (let i = 0; i < members.length; i += 1)
        {
            const member = members[i];
            if (!this.hasUniform(uniformName + "." + member.name))
            {
                const uni = new CGL.Uniform(this, member.type, uniformName + "." + member.name, member.v1, member.v2, member.v3, member.v4, uniformName, structName, member.name);
                uni.shaderType = "vert";
                uniforms[uniformName + "." + member.name] = uni;
            }
        }

        return uniforms;
    };

    /**
     * add a struct & its uniforms to the both shaders. PLEASE NOTE: it is not possible to add the same struct to both shaders when it contains ANY integer members.
     * @param {String} structName name of the struct, i.e.: LightStruct
     * @param {String} uniformName name of the struct uniform in the shader, i.e.: lightUni
     * @param {Array} members array of objects containing the struct members. see example for structure

     * @memberof Shader
     * @instance
     * @function addUniformStructBoth
     * @returns {Object}
     * @example
     * const shader = new CGL.Shader(cgl, 'MinimalMaterial');
     * shader.setSource(attachments.shader_vert, attachments.shader_frag);
     * shader.addUniformStructBoth("Light", "uniformLight", [
     * { "type": "3f", "name": "position", "v1": null },
     * { "type": "4f", "name": "color", "v1": inR, v2: inG, v3: inB, v4: inAlpha }
     * ]);
     */
    addUniformStructBoth(structName, uniformName, members)
    {
        const uniforms = {};

        if (!members) return uniforms;

        for (let i = 0; i < members.length; i += 1)
        {
            const member = members[i];
            if ((member.type === "2i" || member.type === "i" || member.type === "3i"))
                this._log.error("Adding an integer struct member to both shaders can potentially error. Please use different structs for each shader. Error occured in struct:", structName, " with member:", member.name, " of type:", member.type, ".");
            if (!this.hasUniform(uniformName + "." + member.name))
            {
                const uni = new CGL.Uniform(this, member.type, uniformName + "." + member.name, member.v1, member.v2, member.v3, member.v4, uniformName, structName, member.name);
                uni.shaderType = "both";
                uniforms[uniformName + "." + member.name] = uni;
            }
        }

        return uniforms;
    };

    hasUniform(name)
    {
        for (let i = 0; i < this._uniforms.length; i++)
        {
            if (this._uniforms[i].getName() == name) return true;
        }
        return false;
    };

    _createProgram(vstr, fstr)
    {
        this._cgl.printError("before _createprogram");

        const program = this._cgl.gl.createProgram();

        this.vshader = Shader.createShader(this._cgl, vstr, this._cgl.gl.VERTEX_SHADER, this);
        this.fshader = Shader.createShader(this._cgl, fstr, this._cgl.gl.FRAGMENT_SHADER, this);


        if (this.vshader && this.fshader)
        {
            this._cgl.gl.attachShader(program, this.vshader);
            this._cgl.gl.attachShader(program, this.fshader);

            this._linkProgram(program, vstr, fstr);
        }
        else
        {
            this._isValid = false;
            this._cgl.printError("shader _createProgram");
            this._log.error("could not link shaderprogram");
            return null;
        }

        this._cgl.printError("shader _createProgram");
        return program;
    };

    hasErrors()
    {
        return this._hasErrors;
    };

    _linkProgram(program, vstr, fstr)
    {
        this._cgl.printError("before _linkprogram");

        if (this._feedBackNames.length > 0)
        {
            this._cgl.gl.transformFeedbackVaryings(program, this._feedBackNames, this._cgl.gl.SEPARATE_ATTRIBS);
            // INTERLEAVED_ATTRIBS
            // SEPARATE_ATTRIBS
        }

        this._cgl.gl.linkProgram(program);
        this._cgl.printError("gl.linkprogram");
        this._isValid = true;

        this._hasErrors = false;

        if (this._cgl.patch.config.glValidateShader !== false)
        {
            this._cgl.gl.validateProgram(program);

            if (!this._cgl.gl.getProgramParameter(program, this._cgl.gl.VALIDATE_STATUS))
            {
                // validation failed
                console.log("shaderprogram validation failed...");
                console.log(this._name + " programinfo: ", this._cgl.gl.getProgramInfoLog(program));
            }

            if (!this._cgl.gl.getProgramParameter(program, this._cgl.gl.LINK_STATUS))
            {
                this._hasErrors = true;

                const infoLogFrag = this._cgl.gl.getShaderInfoLog(this.fshader);
                const infoLogVert = this._cgl.gl.getShaderInfoLog(this.vshader);

                if (infoLogFrag) this._log.warn(this._cgl.gl.getShaderInfoLog(this.fshader));
                if (infoLogVert) this._log.warn(this._cgl.gl.getShaderInfoLog(this.vshader));

                this._log.error(this._name + " shader linking fail...");

                console.log(this._name + " programinfo: ", this._cgl.gl.getProgramInfoLog(program));
                console.log(this);
                this._isValid = false;

                this._name = "errorshader";
                this.setSource(Shader.getDefaultVertexShader(), Shader.getErrorFragmentShader());
                this._cgl.printError("shader link err");
            }
        }
    };

    getProgram()
    {
        return this._program;
    };

    setFeedbackNames(names)
    {
        this.setWhyCompile("setFeedbackNames");
        this._needsRecompile = true;
        this._feedBackNames = names;
    };

    // getDefaultVertexShader()
    // {
    //     return defaultShaderSrcVert;
    // }

    // getDefaultFragmentShader()
    // {
    //     return this.getDefaultFragmentShader()
    // }


    /**
      * adds attribute definition to shader header without colliding with other shader modules...
     * when attrFrag is defined, vertex shader will output this attribute to the fragment shader
     * @function
     * @memberof Shader
     * @instance
     * @param {Object} attr {type:x,name:x,[nameFrag:x]}
     * @return {Object}
     */
    addAttribute = function (attr)
    {
        for (let i = 0; i < this._attributes.length; i++)
        {
            if (this._attributes[i].name == attr.name && this._attributes[i].nameFrag == attr.nameFrag) return;
        }
        this._attributes.push(attr);
        this._needsRecompile = true;
        this.setWhyCompile("addAttribute");
    };

    bindTextures()
    {
        this._bindTextures();
    }
    _bindTextures()
    {
        if (this._textureStackTex.length > this._cgl.maxTextureUnits)
        {
            this._log.warn("[shader._bindTextures] too many textures bound", this._textureStackTex.length + "/" + this._cgl.maxTextureUnits);
        }

        // for (let i = this._textureStackTex.length + 1; i < this._cgl.maxTextureUnits; i++) this._cgl.setTexture(i, null);

        for (let i = 0; i < this._textureStackTex.length; i++)
        {
            // console.log(this._textureStackTex.length, i);
            if (!this._textureStackTex[i] && !this._textureStackTexCgl[i])
            {
                this._log.warn("no texture for pushtexture", this._name);
            }
            else
            {
                let t = this._textureStackTex[i];
                if (this._textureStackTexCgl[i])
                {
                    t = this._textureStackTexCgl[i].tex || CGL.Texture.getEmptyTexture(this._cgl).tex;
                }

                let bindOk = true;

                if (!this._textureStackUni[i])
                {
                    // throw(new Error('no uniform given to texturestack'));
                    this._log.warn("no uniform for pushtexture", this._name);
                    bindOk = this._cgl.setTexture(i, t, this._textureStackType[i]);
                }
                else
                {
                    this._textureStackUni[i].setValue(i);
                    bindOk = this._cgl.setTexture(i, t, this._textureStackType[i]);

                    // console.log(bindOk, i, t, this._textureStackType[i]);
                }
                if (!bindOk) console.warn("tex bind failed", this.getName(), this._textureStackUni[i]);
            }
        }
    };

    setUniformTexture = function (uni, tex)
    {
        tex = tex || CGL.Texture.getTempTexture(this._cgl);
        for (let i = 0; i < this._textureStackUni.length; i++)
            if (this._textureStackUni[i] == uni)
            {
                const old = this._textureStackTex[i] || this._textureStackTexCgl[i];
                if (tex.hasOwnProperty("tex"))
                {
                    this._textureStackTexCgl[i] = tex;
                    this._textureStackTex[i] = null;
                }
                else
                {
                    this._textureStackTexCgl[i] = null;
                    this._textureStackTex[i] = tex;
                }

                // this._textureStackTex[i] = tex;
                // this._cgl.setTexture(i, tex, this._textureStackType[i]);
                return old;
            }
        return null;
    };

    /**
     * push a texture on the stack. those textures will be bound when binding the shader. texture slots are automatically set
     * @param {uniform} uniform texture uniform
     * @param {texture} t texture
     * @param {type} type texture type, can be ignored when TEXTURE_2D
     * @function pushTexture
     * @memberof Shader
     * @instance
     */
    pushTexture = function (uniform, t, type)
    {
        if (!uniform)
        {
            // console.log("pushtexture: no uniform given to texturestack", "shader:"+this._name,uniform,t,type);
            return;
        }
        if (!t)
        {
            // if(uniform)this._log.warn("pushtexture: no tex","shader:"+this._name," uniform:"+uniform.name);
            return;
        }
        if (!t.hasOwnProperty("tex") && !(t instanceof WebGLTexture))
        {
            this._log.warn(new Error("invalid texture").stack);

            this._log.warn("[cgl_shader] invalid texture...", t);
            return;
        }

        this._textureStackUni.push(uniform);

        if (t.hasOwnProperty("tex"))
        {
            this._textureStackTexCgl.push(t);
            this._textureStackTex.push(null);
        }
        else
        {
            this._textureStackTexCgl.push(null);
            this._textureStackTex.push(t);
        }

        this._textureStackType.push(type);
    };

    /**
     * pop last texture
     * @function popTexture
     * @memberof Shader
     * @instance
     */
    popTexture = function ()
    {
        this._textureStackUni.pop();
        this._textureStackTex.pop();
        this._textureStackTexCgl.pop();
        this._textureStackType.pop();
    };

    /**
     * pop all textures
     * @function popTextures
     * @memberof Shader
     * @instance
     */
    popTextures = function ()
    {
        this._textureStackTex.length =
        this._textureStackTexCgl.length =
        this._textureStackType.length =
        this._textureStackUni.length = 0;
    };

    getMaterialId()
    {
        return this._materialId;
    };

    getInfo()
    {
        const info = {};
        info.name = this._name;
        // info.modules = JSON.parse(JSON.stringify(this._modules));
        // info.defines = JSON.parse(JSON.stringify(this._defines));
        info.defines = this.getDefines();
        info.hasErrors = this.hasErrors();

        return info;
    };


    getDefaultFragmentShader=function(r,g,b,a)
    {
        return getDefaultFragmentShader(r,g,b,a);
    }

    getDefaultVertexShader=function()
    {
        return getDefaultVertexShader();
    }


}

























// --------------------------

Shader.getDefaultVertexShader=getDefaultVertexShader;
Shader.getDefaultFragmentShader=getDefaultFragmentShader;


Shader.getErrorFragmentShader = function ()
{
    return ""
        .endl() + "void main()"
        .endl() + "{"
        .endl() + "   float g=mod((gl_FragCoord.y+gl_FragCoord.x),50.0)/50.0;"
        .endl() + "   g= step(0.1,g);"
        .endl() + "   outColor = vec4( g+0.5, 0.0, 0.0, 1.0);"
        .endl() + "}";
};

Shader.createShader = function (cgl, str, type, cglShader)
{
    if (cgl.aborted) return;

    // cgl.printError("[Shader.createShader] ", cglShader._name);

    function getBadLines(infoLog)
    {
        const basLines = [];
        const lines = infoLog.split("\n");
        for (const i in lines)
        {
            const divide = lines[i].split(":");
            if (parseInt(divide[2], 10)) basLines.push(parseInt(divide[2], 10));
        }
        return basLines;
    }


    const shader = cgl.gl.createShader(type);
    cgl.gl.shaderSource(shader, str);
    cgl.gl.compileShader(shader);

    if (!cgl.gl.getShaderParameter(shader, cgl.gl.COMPILE_STATUS))
    {
        let infoLog = cgl.gl.getShaderInfoLog(shader);
        if (!infoLog)
        {
            console.warn("empty shader info log", this._name);
            return;
        }


        const badLines = getBadLines(infoLog);
        let htmlWarning = "<pre style=\"margin-bottom:0px;\"><code class=\"shaderErrorCode language-glsl\" style=\"padding-bottom:0px;max-height: initial;max-width: initial;\">";
        const lines = str.match(/^.*((\r\n|\n|\r)|$)/gm);

        if (!cgl.aborted && infoLog)
        {
            if (type == cgl.gl.VERTEX_SHADER) console.log("VERTEX_SHADER");
            if (type == cgl.gl.FRAGMENT_SHADER) console.log("FRAGMENT_SHADER");

            for (const i in lines)
            {
                const j = parseInt(i, 10) + 1;
                const line = j + ": " + lines[i];

                let isBadLine = false;
                for (const bj in badLines)
                    if (badLines[bj] == j) isBadLine = true;

                if (isBadLine)
                {
                    htmlWarning += "</code></pre>";
                    htmlWarning += "<pre style=\"margin:0\"><code class=\"language-glsl\" style=\"background-color:#660000;padding-top:0px;padding-bottom:0px\">";

                    cglShader._log.log("bad line: `" + line + "`");
                }
                htmlWarning += escapeHTML(line);

                if (isBadLine)
                {
                    htmlWarning += "</code></pre>";
                    htmlWarning += "<pre style=\"margin:0\"><code class=\"language-glsl\" style=\";padding-top:0px;padding-bottom:0px\">";
                }
            }
        }

        infoLog = infoLog.replace(/\n/g, "<br/>");
        if (cgl.patch.isEditorMode())console.log("Shader error ", cglShader._name, infoLog, this);

        htmlWarning = infoLog + "<br/>" + htmlWarning + "<br/><br/>";
        htmlWarning += "</code></pre>";

        if (this._fromUserInteraction)
        {
            // console.log("todo show modal?");
            // cgl.patch.emitEvent("criticalError", { "title": "Shader error " + cglShader._name, "text": htmlWarning, "exception": { "message": infoLog } });
        }

        cglShader.setSource(Shader.getDefaultVertexShader(), Shader.getErrorFragmentShader());
    }
    else
    {
        // console.log(name+' shader compiled...');
    }
    // cgl.printError("shader create2");
    return shader;
};













;// CONCATENATED MODULE: ./src/core/cgl/cgl_profiledata.js
class ProfileData
{
    constructor(cgl)
    {
        this._cgl = cgl;
        this._lastTime = 0;
        this.pause = false;
        this.profileUniformCount = 0;
        this.profileShaderBinds = 0;
        this.profileUniformCount = 0;
        this.profileShaderCompiles = 0;
        this.profileVideosPlaying = 0;
        this.profileMVPMatrixCount = 0;
        this.profileEffectBuffercreate = 0;
        this.profileShaderGetUniform = 0;
        this.profileFrameBuffercreate = 0;
        this.profileMeshSetGeom = 0;
        this.profileTextureNew = 0;
        this.profileGenMipMap = 0;
        this.profileOnAnimFrameOps = 0;

        this.profileFencedPixelRead = 0;
        this.profileMainloopMs = 0;
        this.profileMeshDraw = 0;
        this.profileTextureEffect = 0;
        this.profileTexPreviews = 0;
        this.shaderCompileTime = 0;
        this.profileMeshNumElements = 0;
        this.profileMeshAttributes = 0;
        this.profileSingleMeshAttribute = [];
        this.heavyEvents = [];

        this.doProfileGlQuery = false;
        this.glQueryData = {};
    }

    clear()
    {
        this.profileSingleMeshAttribute = {};
        this.profileMeshAttributes = 0;
        this.profileUniformCount = 0;
        this.profileShaderGetUniform = 0;
        this.profileShaderCompiles = 0;
        this.profileShaderBinds = 0;
        this.profileTextureResize = 0;
        this.profileFrameBuffercreate = 0;
        this.profileEffectBuffercreate = 0;
        this.profileTextureDelete = 0;
        this.profileMeshSetGeom = 0;
        this.profileVideosPlaying = 0;
        this.profileMVPMatrixCount = 0;
        this.profileNonTypedAttrib = 0;
        this.profileNonTypedAttribNames = "";
        this.profileTextureNew = 0;
        this.profileGenMipMap = 0;
        this.profileFramebuffer = 0;
        this.profileMeshDraw = 0;
        this.profileTextureEffect = 0;
        this.profileTexPreviews = 0;
        this.profileMeshNumElements = 0;
        this.profileFencedPixelRead = 0;
    }

    clearGlQuery()
    {
        for (let i in this.glQueryData)
        {
            if (!this.glQueryData[i].lastClear || performance.now() - this.glQueryData[i].lastClear > 1000)
            {
                this.glQueryData[i].time = this.glQueryData[i]._times / this.glQueryData[i]._numcount;
                this.glQueryData[i].num = this.glQueryData[i]._numcount;

                this.glQueryData[i]._times = 0;
                this.glQueryData[i]._numcount = 0;
                this.glQueryData[i].lastClear = performance.now();
            }
        }
    }

    addHeavyEvent(event, name, info)
    {
        const e = { "event": event, "name": name, "info": info, "date": performance.now() };
        this.heavyEvents.push(e);
        this._cgl.emitEvent("heavyEvent", e);
    }
}




;// CONCATENATED MODULE: ../shared/client/src/helper.js
/**
 * Shared helper methods for cables uis
 */
class Helper
{
    constructor()
    {
        this._simpleIdCounter = 0;
    }


    /**
     * generate a random v4 uuid
     *
     * @return {string}
     */
    uuid()
    {
        let d = new Date().getTime();
        return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) =>
        {
            const r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d / 16);
            return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
        });
    }

    /**
     * checks value for !isNan and isFinite
     *
     * @param n
     * @return {boolean}
     */
    isNumeric(n)
    {
        return !isNaN(parseFloat(n)) && isFinite(n);
    }

    /**
     * generate a simple ID using an internal counter
     *
     * @return {Number} new id
     * @static
     */
    simpleId()
    {
        this._simpleIdCounter++;
        return this._simpleIdCounter;
    }

    deletePropertyByPath(obj, path)
    {
        if (!obj || !path)
        {
            return;
        }

        if (typeof path === "string")
        {
            path = path.split(".");
        }

        for (let i = 0; i < path.length - 1; i++)
        {
            obj = obj[path[i]];

            if (typeof obj === "undefined")
            {
                return;
            }
        }

        delete obj[path.pop()];
    }
}
/* harmony default export */ const helper = (new Helper());

;// CONCATENATED MODULE: ../shared/client/src/eventtarget.js



/**
 * add eventlistener functionality to classes
 */
class Events
{
    constructor()
    {
        this._log = new Logger("eventtarget");
        this._eventCallbacks = {};
        this._logName = "";
        this._logEvents = false;
        this._listeners = {};

        this.on = this.addEventListener;
        this.off = this.removeEventListener;
    }

    /**
     * add event listener
     * @param which event name
     * @param cb callback
     * @param {string} idPrefix prefix for id, default empty
     * @return {string} event id
     */
    addEventListener(which, cb, idPrefix = "")
    {
        const event =
            {
                "id": (idPrefix || "") + helper.simpleId(),
                "name": which,
                "cb": cb,
            };
        if (!this._eventCallbacks[which]) this._eventCallbacks[which] = [event];
        else this._eventCallbacks[which].push(event);

        this._listeners[event.id] = event;

        return event.id;
    }

    /**
     * check event listener registration
     * @param id event id
     * @param cb callback - deprecated
     * @return {boolean}
     */
    hasEventListener(id, cb = null)
    {
        if (id && !cb)
        {
            // check by id
            return !!this._listeners[id];
        }
        else
        {
            this._log.warn("old eventtarget function haseventlistener!");
            if (id && cb)
            {
                if (this._eventCallbacks[id])
                {
                    const idx = this._eventCallbacks[id].indexOf(cb);
                    return idx !== -1;
                }
            }
        }
    }

    /**
     * check event listener by name
     * @param eventName event name
     * @return {boolean}
     */
    hasListenerForEventName(eventName)
    {
        return this._eventCallbacks[eventName] && this._eventCallbacks[eventName].length > 0;
    }

    /**
     * rempve event listener registration
     * @param id event id
     * @param cb callback - deprecated
     * @return
     */
    removeEventListener(id, cb = null)
    {
        if (id === null || id === undefined) return;

        if (!cb) // new style, remove by id, not by name/callback
        {
            const event = this._listeners[id];
            if (!event)
            {
                this._log.log("could not find event...", id, this);
                return;
            }

            let found = true;
            while (found)
            {
                found = false;
                let index = -1;
                for (let i = 0; i < this._eventCallbacks[event.name].length; i++)
                {
                    if (this._eventCallbacks[event.name][i].id.indexOf(id) === 0) // this._eventCallbacks[event.name][i].id == which ||
                    {
                        found = true;
                        index = i;
                    }
                }

                if (index !== -1)
                {
                    this._eventCallbacks[event.name].splice(index, 1);
                    delete this._listeners[id];
                }
            }

            return;
        }

        this._log.info("[eventtaget] ", "old function signature: removeEventListener! use listener id");
        this._log.log((new Error()).stack);

        let index = null;
        for (let i = 0; i < this._eventCallbacks[id].length; i++)
            if (this._eventCallbacks[id][i].cb === cb)
                index = i;

        if (index !== null)
        {
            delete this._eventCallbacks[index];
        }
        else this._log.warn("removeEventListener not found " + id);
    }

    /**
     * enable/disable logging of events for the class
     *
     * @param {boolean} enabled
     * @param {string} logName
     */
    logEvents(enabled, logName)
    {
        this._logEvents = enabled;
        this._logName = logName;
    }

    /**
     * emit event
     *
     * @param {string} which event name
     * @param {*} param1
     * @param {*} param2
     * @param {*} param3
     * @param {*} param4
     * @param {*} param5
     * @param {*} param6
     */
    emitEvent(which, param1 = null, param2 = null, param3 = null, param4 = null, param5 = null, param6 = null)
    {
        if (this._logEvents) this._log.log("[event] ", this._logName, which, this._eventCallbacks);

        if (this._eventCallbacks[which])
        {
            for (let i = 0; i < this._eventCallbacks[which].length; i++)
            {
                if (this._eventCallbacks[which][i])
                {
                    this._eventCallbacks[which][i].cb(param1, param2, param3, param4, param5, param6);
                }
            }
        }
        else
        {
            if (this._logEvents) this._log.log("[event] has no event callback", which, this._eventCallbacks);
        }
    }
}


;// CONCATENATED MODULE: ./src/core/cg/cg_canvas.js
class CgCanvas
{
    constructor(options)
    {
        if (!options)
        {
            console.error("CgCanvas no options");
        }
        else
        {
            this._canvasEle = options.canvasEle;
        }

        if (!options.cg)console.error("CgCanvas options has no cg");
        if (!options.canvasEle)console.error("CgCanvas options has no canvasEle");

        this._cg = options.cg;
        this.pixelDensity = 1;
        this.canvasWidth = this.canvasEle.clientWidth;
        this.canvasHeight = this.canvasEle.clientHeight;

        this._oldWidthRp = -1;
        this._oldHeightRp = -1;

        this.setSize(this.canvasWidth, this.canvasHeight);
    }

    get canvasEle() { return this._canvasEle; }


    setSize(w, h, ignorestyle)
    {
        if (this._oldWidthRp != w * this.pixelDensity || this._oldHeightRp != h * this.pixelDensity)
        {
            this._oldWidthRp = this.canvasEle.width = w * this.pixelDensity;
            this._oldHeightRp = this.canvasEle.height = h * this.pixelDensity;

            if (!ignorestyle)
            {
                this.canvasEle.style.width = w + "px";
                this.canvasEle.style.height = h + "px";
            }

            this.updateSize();

            this._cg.emitEvent("resize");
        }
    }

    updateSize()
    {
        this.canvasEle.width = this.canvasWidth = this.canvasEle.clientWidth * this.pixelDensity;
        this.canvasEle.height = this.canvasHeight = this.canvasEle.clientHeight * this.pixelDensity;
    }

    dispose()
    {
        this._canvasEle.remove();
        this._canvasEle = null;
    }
}



;// CONCATENATED MODULE: ./src/core/cg/cg_matrixstack.js

const MatrixStack = function ()
{
    this._arr = [mat4.create()];
    this._index = 0;
    this.stateCounter = 0;
};

MatrixStack.prototype.push = function (m)
{
    this._index++;
    this.stateCounter++;

    if (this._index == this._arr.length)
    {
        const copy = mat4.create();
        this._arr.push(copy);
    }

    mat4.copy(this._arr[this._index], m || this._arr[this._index - 1]);

    return this._arr[this._index];
};

MatrixStack.prototype.pop = function ()
{
    this.stateCounter++;

    this._index--;
    if (this._index < 0) this._index = 0;

    return this._arr[this._index];
};

MatrixStack.prototype.length = function ()
{
    return this._index;
};



;// CONCATENATED MODULE: ./src/core/cg/cg_state.js




class CGState extends Events
{
    constructor(_patch)
    {
        super();
        this.tempData = this.frameStore = this.frameStore || {};
        // this.canvas = null;

        this.fpsCounter = new CABLES.CG.FpsCounter();
        this._identView = vec3.create();
        this._ident = vec3.create();
        vec3.set(this._identView, 0, 0, -2);
        vec3.set(this._ident, 0, 0, 0);

        this.patch = _patch;
        this.autoReSize = true;

        this.DEPTH_COMPARE_FUNC_NEVER = 0;
        this.DEPTH_COMPARE_FUNC_LESS = 1;
        this.DEPTH_COMPARE_FUNC_EQUAL = 2;
        this.DEPTH_COMPARE_FUNC_LESSEQUAL = 3;
        this.DEPTH_COMPARE_FUNC_GREATER = 4;
        this.DEPTH_COMPARE_FUNC_NOTEQUAL = 5;
        this.DEPTH_COMPARE_FUNC_GREATEREQUAL = 6;
        this.DEPTH_COMPARE_FUNC_ALWAYS = 7;


        /**
         * Current projection matrix
         * @memberof Context
         * @instance
         * @type {mat4}
         */
        this.pMatrix = mat4.create();

        /**
         * Current model matrix
         * @memberof Context
         * @instance
         * @type {mat4}
         */
        this.mMatrix = mat4.create();

        /**
         * Current view matrix
         * @memberof Context
         * @instance
         * @type {mat4}
         */
        this.vMatrix = mat4.create();
        this._textureslots = [];

        this._pMatrixStack = new MatrixStack();
        this._mMatrixStack = new MatrixStack();
        this._vMatrixStack = new MatrixStack();

        this.canvasScale = 1;

        mat4.identity(this.mMatrix);
        mat4.identity(this.vMatrix);


        window.matchMedia("screen and (min-resolution: 2dppx)")
            .addEventListener("change", (e) =>
            {
                this.emitEvent("resize");
            });
    }

    get canvasWidth()
    {
        return this.cgCanvas.canvasWidth;
    }

    get canvasHeight()
    {
        return this.cgCanvas.canvasHeight;
    }

    set pixelDensity(p)
    {
        if (this.cgCanvas.pixelDensity != p)
        {
            this.cgCanvas.pixelDensity = p;
            this.cgCanvas.updateSize();
            this.emitEvent("resize");
        }
    }

    get pixelDensity()
    {
        return this.cgCanvas.pixelDensity;
    }


    getGApiName()
    {
        return ["WebGL", "WebGPU"][this.gApi];
    }

    get canvas()
    {
        return this.cgCanvas.canvasEle;
    }



    setCanvas(canvEle)
    {
        if (this.cgCanvas && canvEle == this.cgCanvas.canvasEle) return;
        if (typeof canvEle === "string") canvEle = document.getElementById(canvEle);

        this.cgCanvas = new CgCanvas({ "canvasEle": canvEle, "cg": this });

        canvEle.parentElement.classList.add("cablesContainer");
        if (this._setCanvas) this._setCanvas(canvEle);

        this.updateSize();
    }

    updateSize()
    {
        this.cgCanvas.updateSize();
    }

    setSize(w, h, ignorestyle)
    {
        this.cgCanvas.setSize(w, h, ignorestyle);
    }

    _resizeToWindowSize()
    {
        if (this.autoReSize)
        {
            this.setSize(window.innerWidth, window.innerHeight);
            this.updateSize();
        }
    }

    _resizeToParentSize()
    {
        if (this.autoReSize)
        {
            const p = this.canvas.parentElement;
            if (!p)
            {
                this._log.error("cables: can not resize to container element");
                return;
            }

            this.setSize(p.clientWidth, p.clientHeight);
            this.updateSize();
        }
    }

    setAutoResize(parent)
    {
        window.removeEventListener("resize", this._resizeToWindowSize.bind(this));
        window.removeEventListener("resize", this._resizeToParentSize.bind(this));

        if (parent == "window")
        {
            window.addEventListener("resize", this._resizeToWindowSize.bind(this));
            window.addEventListener("orientationchange", this._resizeToWindowSize.bind(this));
            this._resizeToWindowSize();
        }
        if (parent == "parent")
        {
            window.addEventListener("resize", this._resizeToParentSize.bind(this));
            this._resizeToParentSize();
        }
    }

    /**
     * push a matrix to the projection matrix stack
     * @function pushPMatrix
     * @memberof Context
     * @instance
     */
    pushPMatrix()
    {
        this.pMatrix = this._pMatrixStack.push(this.pMatrix);
    }

    /**
      * pop projection matrix stack
      * @function popPMatrix
      * @memberof Context
      * @instance
      * @returns {mat4} current projectionmatrix
      */
    popPMatrix()
    {
        this.pMatrix = this._pMatrixStack.pop();
        return this.pMatrix;
    }

    getProjectionMatrixStateCount()
    {
        return this._pMatrixStack.stateCounter;
    }

    /**
      * push a matrix to the model matrix stack
      * @function pushModelMatrix
      * @memberof Context
      * @instance
      * @example
      * // see source code of translate op:
      * cgl.pushModelMatrix();
      * mat4.translate(cgl.mMatrix,cgl.mMatrix, vec);
      * trigger.trigger();
      * cgl.popModelMatrix();
      */
    pushModelMatrix()
    {
        this.mMatrix = this._mMatrixStack.push(this.mMatrix);
    }

    /**
      * pop model matrix stack
      * @function popModelMatrix
      * @memberof Context
      * @instance
      * @returns {mat4} current modelmatrix
      */
    popModelMatrix()
    {
        // todo: DEPRECATE
        // if (this._mMatrixStack.length === 0) throw "Invalid modelview popMatrix!";
        this.mMatrix = this._mMatrixStack.pop();
        return this.mMatrix;
    }

    /**
      * get model matrix
      * @function modelMatrix
      * @memberof Context
      * @instance
      * @returns {mat4} current modelmatrix
      */
    modelMatrix()
    {
        return this.mMatrix;
    }


    /**
     * push a matrix to the view matrix stack
     * @function pushviewMatrix
     * @memberof Context
     * @instance
     */
    pushViewMatrix()
    {
        this.vMatrix = this._vMatrixStack.push(this.vMatrix);
    }

    /**
      * pop view matrix stack
      * @function popViewMatrix
      * @memberof Context
      * @instance
      * @returns {mat4} current viewmatrix
      * @function
      */
    popViewMatrix()
    {
        this.vMatrix = this._vMatrixStack.pop();
    }

    getViewMatrixStateCount()
    {
        return this._vMatrixStack.stateCounter;
    }

    _startMatrixStacks(identTranslate, identTranslateView)
    {
        identTranslate = identTranslate || this._ident;
        identTranslateView = identTranslateView || this._identView;

        mat4.perspective(this.pMatrix, 45, this.canvasWidth / this.canvasHeight, 0.1, 1000.0);

        mat4.identity(this.mMatrix);
        mat4.identity(this.vMatrix);
        mat4.translate(this.mMatrix, this.mMatrix, identTranslate);
        mat4.translate(this.vMatrix, this.vMatrix, identTranslateView);

        this.pushPMatrix();
        this.pushModelMatrix();
        this.pushViewMatrix();
    }

    _endMatrixStacks()
    {
        this.popViewMatrix();
        this.popModelMatrix();
        this.popPMatrix();
    }

    dispose()
    {
        this.aborted = true;
        if (this.cgCanvas) this.cgCanvas.dispose();
        if (this._dispose) this._dispose();
    }

    shouldDrawHelpers()
    {
        return false;
    }
}





;// CONCATENATED MODULE: ./src/core/cg/sg_fpscounter.js


class FpsCounter extends Events
{
    constructor()
    {
        super();
        this._timeStartFrame = 0;
        this._timeStartSecond = 0;
        this._fpsCounter = 0;
        this._msCounter = 0;
        this._frameCount = 0;

        this.stats = { "ms": 0, "fps": 0 };
    }

    get frameCount()
    {
        return this._frameCount;
    }

    startFrame()
    {
        this._timeStartFrame = CABLES.now();
    }

    endFrame()
    {
        this._frameCount++;
        this._fpsCounter++;

        const timeFrame = CABLES.now() - this._timeStartFrame;
        this._msCounter += timeFrame;

        if (CABLES.now() - this._timeStartSecond > 1000)
        {
            this.endSecond();
        }
    }

    endSecond()
    {
        this.stats.fps = this._fpsCounter;
        this.stats.ms = Math.round(this._msCounter / this._fpsCounter * 100) / 100;

        this.emitEvent("performance", this.stats);

        // reset
        this._fpsCounter = 0;
        this._msCounter = 0;
        this._timeStartSecond = CABLES.now();
    }
}

;// CONCATENATED MODULE: ./src/core/cg/cg_constants.js





const CG = {

    "GAPI_WEBGL": 0,
    "GAPI_WEBGPU": 1,

    "DEPTH_COMPARE_NEVER": 0,
    "DEPTH_COMPARE_LESS": 1,
    "DEPTH_COMPARE_EQUAL": 2,
    "DEPTH_COMPARE_LESSEQUAL": 3,
    "DEPTH_COMPARE_GREATER": 4,
    "DEPTH_COMPARE_NOTEQUAL": 5,
    "DEPTH_COMPARE_GREATEREQUAL": 6,
    "DEPTH_COMPARE_ALWAYS": 7,

    "CULL_NONE": 0,
    "CULL_BACK": 1,
    "CULL_FRONT": 2,
    "CULL_BOTH": 3,


    "Geometry": Geometry,
    "BoundingBox": BoundingBox,
    "FpsCounter": FpsCounter,

    "CgCanvas": CgCanvas
};




;// CONCATENATED MODULE: ./src/core/cgl/cgl_state.js








/**
 * cables gl context/state manager
 * @class
 * @namespace external:CGL
 * @hideconstructor
 */
// const Context(_patch)
class Context extends CGState
{
    constructor(_patch)
    {
        super(_patch);

        this.gApi = CG.GAPI_WEBGL;
        this.aborted = false;

        this.pushMvMatrix = this.pushModelMatrix; // deprecated and wrong... still used??
        this.popMvMatrix = this.popmMatrix = this.popModelMatrix;// deprecated and wrong... still used??

        this.profileData = new ProfileData(this);
        this._log = new Logger("cgl_context", { "onError": _patch.config.onError });
        this._viewPort = [0, 0, 0, 0];
        this.glVersion = 0;
        this.glUseHalfFloatTex = false;
        this.clearCanvasTransparent = true;
        this.clearCanvasDepth = true;
        this.debugOneFrame = false;
        this.checkGlErrors = false; // true is slow // false should be default...
        this.maxTextureUnits = 0;
        this.maxVaryingVectors = 0;
        this.currentProgram = null;
        this._hadStackError = false;
        this.glSlowRenderer = false;
        this._isSafariCrap = false;

        this.temporaryTexture = null;
        this._onetimeCallbacks = [];
        this.gl = null;

        this._cursor = "auto";
        this._currentCursor = "";

        this._viewPortStack = [];
        this._glFrameBufferStack = [];
        this._frameBufferStack = [];
        this._shaderStack = [];
        this._stackDepthTest = [];
        this.mainloopOp = null;

        this._simpleShader = new Shader(this, "simpleshader");
        this._simpleShader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG", "MODULE_VERTEX_MODELVIEW"]);
        this._simpleShader.setSource(Shader.getDefaultVertexShader(), Shader.getDefaultFragmentShader());

        this._currentShader = this._simpleShader;


        this._oldCanvasWidth = -1;
        this._oldCanvasHeight = -1;
        this._enabledExtensions = {};
    }

    // set pixelDensity(p)
    // {
    //     this._pixelDensity = p;
    // }

    // get pixelDensity()
    // {
    //     return this._pixelDensity;
    // }



    get viewPort()
    {
        if (this._viewPortStack.length > 3)
        {
            const l = this._viewPortStack.length;

            return [
                this._viewPortStack[l - 4],
                this._viewPortStack[l - 3],
                this._viewPortStack[l - 2],
                this._viewPortStack[l - 1]
            ];
        }
        else
        {
            // workaround pre viewport stack times / or+and initial value...

            return this._viewPort;
        }
    }



    get mvMatrix() // deprecate
    {
        return this.mMatrix;
    }

    set mvMatrix(m) // deprecate
    {
        this.mMatrix = m;
    }

    _setCanvas(canv)
    {
        if (!canv) this._log.stack("_setCanvas undef");

        if (!this.patch.config.canvas) this.patch.config.canvas = {};
        if (!this.patch.config.canvas.hasOwnProperty("preserveDrawingBuffer")) this.patch.config.canvas.preserveDrawingBuffer = false;
        if (!this.patch.config.canvas.hasOwnProperty("premultipliedAlpha")) this.patch.config.canvas.premultipliedAlpha = false;
        if (!this.patch.config.canvas.hasOwnProperty("alpha")) this.patch.config.canvas.alpha = false;

        this.patch.config.canvas.stencil = true;

        if (this.patch.config.hasOwnProperty("clearCanvasColor")) this.clearCanvasTransparent = this.patch.config.clearCanvasColor;
        if (this.patch.config.hasOwnProperty("clearCanvasDepth")) this.clearCanvasDepth = this.patch.config.clearCanvasDepth;

        // safari stuff..........
        if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent) && (navigator.userAgent.match(/iPhone/i)))
        {
            this._isSafariCrap = true;
            this.glUseHalfFloatTex = true;
        }

        if (!this.patch.config.canvas.forceWebGl1) this.gl = canv.getContext("webgl2", this.patch.config.canvas);


        if (!this.gl || this.gl.isContextLost())
        {
            this.aborted = true;
            this._log.error("NO_WEBGL", "sorry, could not initialize WebGL. Please check if your Browser supports WebGL or try to restart your browser.");
            return;
        }

        if (this.gl.getParameter(this.gl.VERSION) != "WebGL 1.0")
        {
            this.glVersion = 2;
        }
        else
        {
            this.gl = canv.getContext("webgl", this.patch.config.canvas) || canv.getContext("experimental-webgl", this.patch.config.canvas);
            this.glVersion = 1;

            // safari
            // if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent) && (navigator.userAgent.match(/iPhone/i)))
            // {
            //     this.glUseHalfFloatTex = true;
            // }

            // ios
            if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream)
            {
                if (!this.patch.config.canvas.hasOwnProperty("powerPreference")) this.patch.config.canvas.powerPreference = "high-performance";
            }

            this.enableExtension("OES_standard_derivatives");
            // this.enableExtension("GL_OES_standard_derivatives");
            const instancingExt = this.enableExtension("ANGLE_instanced_arrays") || this.gl;
            if (instancingExt.vertexAttribDivisorANGLE)
            {
                this.gl.vertexAttribDivisor = instancingExt.vertexAttribDivisorANGLE.bind(instancingExt);
                this.gl.drawElementsInstanced = instancingExt.drawElementsInstancedANGLE.bind(instancingExt);
            }
        }

        const dbgRenderInfo = this.enableExtension("WEBGL_debug_renderer_info");
        if (dbgRenderInfo)
        {
            this.glRenderer = this.gl.getParameter(dbgRenderInfo.UNMASKED_RENDERER_WEBGL);
            if (this.glRenderer === "Google SwiftShader") this.glSlowRenderer = true;
        }

        this.canvas.addEventListener("webglcontextlost", (event) =>
        {
            if (this.aborted) return this._log.warn("[cgl_state] aborted context lost... can be ignored...");
            this._log.error("canvas lost...", event);
            this.emitEvent("webglcontextlost");
            this.aborted = true;
        });


        this.maxAnisotropic = 0;
        if (this.enableExtension("EXT_texture_filter_anisotropic"))
            this.maxAnisotropic = this.gl.getParameter(this.enableExtension("EXT_texture_filter_anisotropic").MAX_TEXTURE_MAX_ANISOTROPY_EXT);


        this.maxVaryingVectors = this.gl.getParameter(this.gl.MAX_VARYING_VECTORS);
        this.maxTextureUnits = this.gl.getParameter(this.gl.MAX_TEXTURE_IMAGE_UNITS);
        this.maxTexSize = this.gl.getParameter(this.gl.MAX_TEXTURE_SIZE);
        this.maxUniformsFrag = this.gl.getParameter(this.gl.MAX_FRAGMENT_UNIFORM_VECTORS);
        this.maxUniformsVert = this.gl.getParameter(this.gl.MAX_VERTEX_UNIFORM_VECTORS);
        this.maxSamples = 0;
        if (this.gl.MAX_SAMPLES) this.maxSamples = this.gl.getParameter(this.gl.MAX_SAMPLES);

        if (this.glVersion == 1)
        {
            this.enableExtension("OES_standard_derivatives");
            const instancingExt = this.enableExtension("ANGLE_instanced_arrays") || this.gl;

            if (instancingExt.vertexAttribDivisorANGLE)
            {
                this.gl.vertexAttribDivisor = instancingExt.vertexAttribDivisorANGLE.bind(instancingExt);
                this.gl.drawElementsInstanced = instancingExt.drawElementsInstancedANGLE.bind(instancingExt);
            }
        }

        this.DEPTH_FUNCS = [
            this.gl.NEVER,
            this.gl.ALWAYS,
            this.gl.LESS,
            this.gl.LEQUAL,
            this.gl.GREATER,
            this.gl.GEQUAL,
            this.gl.EQUAL,
            this.gl.NOTEQUAL
        ];
        this.CULL_MODES = [
            null,
            this.gl.BACK,
            this.gl.FRONT,
            this.gl.FRONT_AND_BACK
        ];
    }

    getInfo()
    {
        return {
            "glVersion": this.glVersion,
            "glRenderer": this.glRenderer,
            "glUseHalfFloatTex": this.glUseHalfFloatTex,
            "maxVaryingVectors": this.maxVaryingVectors,
            "maxTextureUnits": this.maxTextureUnits,
            "maxTexSize": this.maxTexSize,
            "maxUniformsFrag": this.maxUniformsFrag,
            "maxUniformsVert": this.maxUniformsVert,
            "maxSamples": this.maxSamples
        };
    }





    /**
     * @function popViewPort
     * @memberof Context
     * @instance
     * @description pop viewPort stack
     */


    popViewPort()
    {
        this._viewPortStack.pop();
        this._viewPortStack.pop();
        this._viewPortStack.pop();
        this._viewPortStack.pop();

        if (this._viewPortStack.length == 0)
        {
            this.setViewPort(0, 0, this.canvasWidth, this.canvasHeight);
            // this.gl.viewport(this._viewPort[0], this._viewPort[1], this._viewPort[2], this._viewPort[3]);
            // this.setViewPort(this._viewPort[0], this._viewPort[1], this._viewPort[2], this._viewPort[3]);
        }
        else
        {
            // this.viewPort = [this._viewPortStack[this._viewPort.length - 4], this._viewPortStack[this._viewPort.length - 3], this._viewPortStack[this._viewPort.length - 2], this._viewPortStack[this._viewPort.length - 1]];
            // this.gl.viewport(this._viewPortStack[this._viewPort.length - 4], this._viewPortStack[this._viewPort.length - 3], this._viewPortStack[this._viewPort.length - 2], this._viewPortStack[this._viewPort.length - 1]);
            this.setViewPort(this._viewPortStack[this._viewPort.length - 4], this._viewPortStack[this._viewPort.length - 3], this._viewPortStack[this._viewPort.length - 2], this._viewPortStack[this._viewPort.length - 1]);
        }
    }

    /**
     * @function pushViewPort
     * @memberof Context
     * @instance
     * @description push a new viewport onto stack
     * @param {Number} x
     * @param {Number} y
     * @param {Number} w
     * @param {Number} h
     */

    pushViewPort(x, y, w, h)
    {
        this._viewPortStack.push(x, y, w, h);
        this.setViewPort(x, y, w, h);
    }


    // old
    getViewPort()
    {
        return this._viewPort;
    }

    // old
    resetViewPort()
    {
        this.gl.viewport(this._viewPort[0], this._viewPort[1], this._viewPort[2], this._viewPort[3]);
    }

    // old
    setViewPort(x, y, w, h)
    {
        this._viewPort[0] = Math.round(x);
        this._viewPort[1] = Math.round(y);
        this._viewPort[2] = Math.round(w);
        this._viewPort[3] = Math.round(h);
        this.gl.viewport(this._viewPort[0], this._viewPort[1], this._viewPort[2], this._viewPort[3]);
    }


    screenShot(cb, doScreenshotClearAlpha, mimeType, quality)
    {
        if (doScreenshotClearAlpha)
        {
            this.gl.clearColor(1, 1, 1, 1);
            this.gl.colorMask(false, false, false, true);
            this.gl.clear(this.gl.COLOR_BUFFER_BIT);
            this.gl.colorMask(true, true, true, true);
        }

        if (this.canvas && this.canvas.toBlob)
        {
            this.canvas.toBlob((blob) =>
            {
                if (cb) cb(blob);
                else this._log.log("no screenshot callback...");
            }, mimeType, quality);
        }
    }

    endFrame()
    {
        if (this.patch.isEditorMode()) CABLES.GL_MARKER.drawMarkerLayer(this);

        this.setPreviousShader();

        if (this._vMatrixStack.length() > 0) this.logStackError("view matrix stack length !=0 at end of rendering...");
        if (this._mMatrixStack.length() > 0) this.logStackError("mvmatrix stack length !=0 at end of rendering...");
        if (this._pMatrixStack.length() > 0) this.logStackError("pmatrix stack length !=0 at end of rendering...");
        if (this._glFrameBufferStack.length > 0) this.logStackError("glFrameBuffer stack length !=0 at end of rendering...");
        if (this._stackDepthTest.length > 0) this.logStackError("depthtest stack length !=0 at end of rendering...");
        if (this._stackDepthWrite.length > 0) this.logStackError("depthwrite stack length !=0 at end of rendering...");
        if (this._stackDepthFunc.length > 0) this.logStackError("depthfunc stack length !=0 at end of rendering...");
        if (this._stackBlend.length > 0) this.logStackError("blend stack length !=0 at end of rendering...");
        if (this._stackBlendMode.length > 0) this.logStackError("blendMode stack length !=0 at end of rendering...");
        if (this._shaderStack.length > 0) this.logStackError("this._shaderStack length !=0 at end of rendering...");
        if (this._stackCullFace.length > 0) this.logStackError("this._stackCullFace length !=0 at end of rendering...");
        if (this._stackCullFaceFacing.length > 0) this.logStackError("this._stackCullFaceFacing length !=0 at end of rendering...");
        if (this._viewPortStack.length > 0) this.logStackError("viewport stack length !=0 at end of rendering...");

        this._frameStarted = false;

        if (this._oldCanvasWidth != this.canvasWidth || this._oldCanvasHeight != this.canvasHeight)
        {
            this._oldCanvasWidth = this.canvasWidth;
            this._oldCanvasHeight = this.canvasHeight;
            this.emitEvent("resize");
        }

        if (this._cursor != this._currentCursor)
        {
            this._currentCursor = this.canvas.style.cursor = this._cursor;
        }

        this.emitEvent("endframe");

        this.fpsCounter.endFrame();
    }

    logStackError(str)
    {
        if (!this._hadStackError)
        {
            this._hadStackError = true;
            this._log.warn("[" + this.canvas.id + "]: ", str);
        }
    }

    // shader stack
    getShader()
    {
        if (this._currentShader) if (!this.tempData || ((this.tempData.renderOffscreen === true) == this._currentShader.offScreenPass) === true) return this._currentShader;

        for (let i = this._shaderStack.length - 1; i >= 0; i--) if (this._shaderStack[i]) if (this.tempData.renderOffscreen == this._shaderStack[i].offScreenPass) return this._shaderStack[i];
    }

    getDefaultShader()
    {
        return this._simpleShader;
    }

    /**
     * push a shader to the shader stack
     * @function pushShader
     * @memberof Context
     * @instance
     * @param {Object} shader
     * @function
     */

    pushShader(shader)
    {
        if (this.tempData.forceShaderMods)
        {
            for (let i = 0; i < this.tempData.forceShaderMods.length; i++)
            {
                // if (!currentShader.forcedMod && currentShader != this.tempData.forceShaderMods[i])
                // {
                //     currentShader.forcedMod = this.tempData.forceShaderMods[i];
                shader = this.tempData.forceShaderMods[i].bind(shader, false);
                // }
                // return currentShader;
                // if (this.tempData.forceShaderMods[i].currentShader() && shader != this.tempData.forceShaderMods[i].currentShader().shader)
            }
        }

        this._shaderStack.push(shader);
        this._currentShader = shader;
    }


    /**
     * pop current used shader from shader stack
     * @function popShader
     * @memberof Context
     * @instance
     * @function
     */
    setPreviousShader()
    {
        if (this.tempData.forceShaderMods)
        {
            for (let i = 0; i < this.tempData.forceShaderMods.length; i++)
            {
                // const a =
                this.tempData.forceShaderMods[i].unbind(false);
                // if (a) return;
                // this.popShader();
            }
        }

        if (this._shaderStack.length === 0) throw new Error("Invalid shader stack pop!");
        this._shaderStack.pop();
        this._currentShader = this._shaderStack[this._shaderStack.length - 1];
    }

    /**
     * push a framebuffer to the framebuffer stack
     * @function pushGlFrameBuffer
     * @memberof Context
     * @instance
     * @param {Object} fb framebuffer
     * @function
     */
    pushGlFrameBuffer(fb)
    {
        this._glFrameBufferStack.push(fb);
    }

    /**
     * pop framebuffer stack
     * @function popGlFrameBuffer
     * @memberof Context
     * @instance
     * @returns {Object} current framebuffer or null
     */
    popGlFrameBuffer()
    {
        if (this._glFrameBufferStack.length == 0) return null;
        this._glFrameBufferStack.pop();
        return this._glFrameBufferStack[this._glFrameBufferStack.length - 1];
    }

    /**
     * get current framebuffer
     * @function getCurrentFrameBuffer
     * @memberof Context
     * @instance
     * @returns {Object} current framebuffer or null
     */
    getCurrentGlFrameBuffer()
    {
        if (this._glFrameBufferStack.length === 0) return null;
        return this._glFrameBufferStack[this._glFrameBufferStack.length - 1];
    }

    /**
     * push a framebuffer to the framebuffer stack
     * @function pushGlFrameBuffer
     * @memberof Context
     * @instance
     * @param {Framebuffer} fb framebuffer
     */
    pushFrameBuffer(fb)
    {
        this._frameBufferStack.push(fb);
    }

    /**
     * pop framebuffer stack
     * @function popFrameBuffer
     * @memberof Context
     * @instance
     * @returns {Framebuffer} current framebuffer or null
     */
    popFrameBuffer()
    {
        if (this._frameBufferStack.length == 0) return null;
        this._frameBufferStack.pop();
        return this._frameBufferStack[this._frameBufferStack.length - 1];
    }

    /**
     * get current framebuffer
     * @function getCurrentFrameBuffer
     * @memberof Context
     * @instance
     * @returns {Framebuffer} current framebuffer or null
     */
    getCurrentFrameBuffer()
    {
        if (this._frameBufferStack.length === 0) return null;
        return this._frameBufferStack[this._frameBufferStack.length - 1];
    }


    renderStart(cgl, identTranslate, identTranslateView)
    {
        this.fpsCounter.startFrame();
        this.pushDepthTest(true);
        this.pushDepthWrite(true);
        this.pushDepthFunc(cgl.gl.LEQUAL);
        this.pushCullFaceFacing(cgl.gl.BACK);
        this.pushCullFace(false);

        // if (this.clearCanvasTransparent)
        // {
        //     cgl.gl.clearColor(0, 0, 0, 0);
        //     cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT);
        // }
        // if (this.clearCanvasDepth) cgl.gl.clear(cgl.gl.DEPTH_BUFFER_BIT);

        cgl.setViewPort(0, 0, cgl.canvasWidth, cgl.canvasHeight);

        this._startMatrixStacks(identTranslate, identTranslateView);

        cgl.pushBlendMode(constants_CONSTANTS.BLEND_MODES.BLEND_NORMAL, false);

        for (let i = 0; i < this._textureslots.length; i++) this._textureslots[i] = null;

        this.pushShader(this._simpleShader);

        this._frameStarted = true;

        if (this._onetimeCallbacks.length > 0)
        {
            for (let i = 0; i < this._onetimeCallbacks.length; i++) this._onetimeCallbacks[i]();
            this._onetimeCallbacks.length = 0;
        }

        for (let i = 0; i < this._textureslots.length; i++)
        {
            this.gl.activeTexture(this.gl.TEXTURE0 + i);
            this.gl.bindTexture(this.gl.TEXTURE_2D, null);
            this._textureslots[i] = null;
        }

        this.emitEvent("beginFrame");
    }

    renderEnd(cgl)
    {
        this._endMatrixStacks();

        this.popDepthTest();
        this.popDepthWrite();
        this.popDepthFunc();
        this.popCullFaceFacing();
        this.popCullFace();
        this.popBlend();
        this.popBlendMode();

        cgl.endFrame();

        this.emitEvent("endFrame");
    }

    getTexture(slot)
    {
        return this._textureslots[slot];
    }

    hasFrameStarted()
    {
        return this._frameStarted;
    }

    /**
     * log warning to console if the rendering of one frame has not been started / handy to check for async problems
     * @function checkFrameStarted
     * @memberof Context
     * @param string
     * @instance
     */
    checkFrameStarted(string)
    {
        if (!this._frameStarted)
        {
            this._log.warn("frame not started " + string);
            this.patch.printTriggerStack();
        }
    }


    setTexture(slot, t, type)
    {
        this.checkFrameStarted("cgl setTexture");

        if (t === null) t = CGL.Texture.getEmptyTexture(this).tex;

        if (this._textureslots[slot] != t)
        {
            this.gl.activeTexture(this.gl.TEXTURE0 + slot);
            this.gl.bindTexture(type || this.gl.TEXTURE_2D, t);
            this._textureslots[slot] = t;
        }


        return true;
    }

    fullScreen()
    {
        if (this.canvas.requestFullscreen) this.canvas.requestFullscreen();
        else if (this.canvas.mozRequestFullScreen) this.canvas.mozRequestFullScreen();
        else if (this.canvas.webkitRequestFullscreen) this.canvas.webkitRequestFullscreen();
        else if (this.canvas.msRequestFullscreen) this.canvas.msRequestFullscreen();
    }


    printError(str)
    {
        if (!this.checkGlErrors) return;
        let found = false;
        let error = this.gl.getError();

        if (error != this.gl.NO_ERROR)
        {
            let errStr = "";
            if (error == this.gl.OUT_OF_MEMORY) errStr = "OUT_OF_MEMORY";
            if (error == this.gl.INVALID_ENUM) errStr = "INVALID_ENUM";
            if (error == this.gl.INVALID_OPERATION) errStr = "INVALID_OPERATION";
            if (error == this.gl.INVALID_FRAMEBUFFER_OPERATION) errStr = "INVALID_FRAMEBUFFER_OPERATION";
            if (error == this.gl.INVALID_VALUE) errStr = "INVALID_VALUE";
            if (error == this.gl.CONTEXT_LOST_WEBGL)
            {
                this.aborted = true;
                errStr = "CONTEXT_LOST_WEBGL";
            }
            if (error == this.gl.NO_ERROR) errStr = "NO_ERROR";

            found = true;


            this._log.warn("gl error [" + this.canvas.id + "]: ", str, error, errStr);

            if (this.canvas.id.contains("glGuiCanvas"))
                if (!this._loggedGlError)
                {
                    this.patch.printTriggerStack();
                    this._log.stack("glerror");
                    this._loggedGlError = true;
                }
        }
        error = this.gl.getError();

        return found;
    }

    saveScreenshot(filename, cb, pw, ph, noclearalpha)
    {
        this.patch.renderOneFrame();

        let w = this.canvas.clientWidth * this.pixelDensity;
        let h = this.canvas.clientHeight * this.pixelDensity;

        if (pw)
        {
            this.canvas.width = pw;
            w = pw;
        }
        if (ph)
        {
            this.canvas.height = ph;
            h = ph;
        }

        function padLeft(nr, n, str)
        {
            return Array(n - String(nr).length + 1).join(str || "0") + nr;
        }

        const d = new Date();

        const dateStr = "".concat(String(d.getFullYear()) + String(d.getMonth() + 1) + String(d.getDate()), "_").concat(padLeft(d.getHours(), 2)).concat(padLeft(d.getMinutes(), 2)).concat(padLeft(d.getSeconds(), 2));

        if (!filename) filename = "cables_" + dateStr + ".png";
        else filename += ".png";

        this.patch.cgl.screenShot(function (blob)
        {
            this.canvas.width = w;
            this.canvas.height = h;

            if (blob)
            {
                const anchor = document.createElement("a");

                anchor.download = filename;
                anchor.href = URL.createObjectURL(blob);

                setTimeout(function ()
                {
                    anchor.click();
                    if (cb) cb(blob);
                }, 100);
            }
            else
            {
                this._log.log("screenshot: no blob");
            }
        }.bind(this), noclearalpha);
    }

    _dispose()
    {
        this._simpleShader.dispose();
        this.gl = null;
    }
}


Context.prototype.popShader = Context.prototype.setPreviousShader;
Context.prototype.setShader = Context.prototype.pushShader;

/**
 * execute the callback next frame, once
 * @function addNextFrameOnceCallback
 * @memberof Context
 * @instance
 * @param {function} cb
 */
Context.prototype.addNextFrameOnceCallback = function (cb)
{
    if (cb && this._onetimeCallbacks.indexOf(cb) == -1) this._onetimeCallbacks.push(cb);
};

// state depthtest

/**
 * push depth testing enabled state
 * @function pushDepthTest
 * @param {Boolean} enabled
 * @memberof Context
 * @instance
 */
Context.prototype._stackDepthTest = [];
Context.prototype.pushDepthTest = function (b)
{
    this._stackDepthTest.push(b);
    if (!b) this.gl.disable(this.gl.DEPTH_TEST);
    else this.gl.enable(this.gl.DEPTH_TEST);
};
/**
 * current state of depth testing
 * @function stateCullFace
 * @returns {Boolean} enabled
 * @memberof Context
 * @instance
 */
Context.prototype.stateDepthTest = function ()
{
    return this._stackDepthTest[this._stackDepthTest.length - 1];
};

/**
 * pop depth testing state
 * @function popCullFace
 * @memberof Context
 * @instance
 */
Context.prototype.popDepthTest = function ()
{
    this._stackDepthTest.pop();

    if (!this._stackDepthTest[this._stackDepthTest.length - 1]) this.gl.disable(this.gl.DEPTH_TEST);
    else this.gl.enable(this.gl.DEPTH_TEST);
};

// --------------------------------------
// state depthwrite

/**
 * push depth write enabled state
 * @function pushDepthTest
 * @param {Boolean} enabled
 * @memberof Context
 * @instance
 */
Context.prototype._stackDepthWrite = [];
Context.prototype.pushDepthWrite = function (b)
{
    b = b || false;
    this._stackDepthWrite.push(b);
    this.gl.depthMask(b);
};

/**
 * current state of depth writing
 * @function stateDepthWrite
 * @returns {Boolean} enabled
 * @memberof Context
 * @instance
 */
Context.prototype.stateDepthWrite = function ()
{
    return this._stackDepthWrite[this._stackDepthWrite.length - 1];
};

/**
 * pop depth writing state
 * @function popDepthWrite
 * @memberof Context
 * @instance
 */
Context.prototype.popDepthWrite = function ()
{
    this._stackDepthWrite.pop();
    this.gl.depthMask(this._stackDepthWrite[this._stackDepthWrite.length - 1] || false);
};


// --------------------------------------
// state CullFace

Context.prototype._stackCullFace = [];

/**
 * push face culling face enabled state
 * @function pushCullFace
 * @param {Boolean} b enabled
 * @memberof Context
 * @instance
 */
Context.prototype.pushCullFace = function (b)
{
    this._stackCullFace.push(b);

    if (b) this.gl.enable(this.gl.CULL_FACE);
    else this.gl.disable(this.gl.CULL_FACE);
};

/**
 * current state of face culling
 * @function stateCullFace
 * @returns {Boolean} enabled
 * @memberof Context
 * @instance
 */
Context.prototype.stateCullFace = function ()
{
    return this._stackCullFace[this._stackCullFace.length - 1];
};

/**
 * pop face culling enabled state
 * @function popCullFace
 * @memberof Context
 * @instance
 */
Context.prototype.popCullFace = function ()
{
    this._stackCullFace.pop();

    if (this._stackCullFace[this._stackCullFace.length - 1]) this.gl.enable(this.gl.CULL_FACE);
    else this.gl.disable(this.gl.CULL_FACE);
};


// --------------------------------------
// state CullFace Facing


/**
 * push face culling face side
 * @function pushCullFaceFacing
 * @param {Number} cgl.gl.FRONT_AND_BACK, cgl.gl.BACK or cgl.gl.FRONT
 * @memberof Context
 * @instance
 */
Context.prototype._stackCullFaceFacing = [];
Context.prototype.pushCullFaceFacing = function (b)
{
    this._stackCullFaceFacing.push(b);
    this.gl.cullFace(this._stackCullFaceFacing[this._stackCullFaceFacing.length - 1]);
};

/**
 * current state of face culling side
 * @function stateCullFaceFacing
 * @returns {Boolean} enabled
 * @memberof Context
 * @instance
 */
Context.prototype.stateCullFaceFacing = function ()
{
    return this._stackCullFaceFacing[this._stackCullFaceFacing.length - 1];
};

/**
 * pop face culling face side
 * @function popCullFaceFacing
 * @memberof Context
 * @instance
 */
Context.prototype.popCullFaceFacing = function ()
{
    this._stackCullFaceFacing.pop();
    if (this._stackCullFaceFacing.length > 0) this.gl.cullFace(this._stackCullFaceFacing[this._stackCullFaceFacing.length - 1]);
};


// --------------------------------------
// state depthfunc

Context.prototype._stackDepthFunc = [];

/**
 * enable / disable depth testing
 * like `gl.depthFunc(boolean);`
 * @function pushDepthFunc
 * @memberof Context
 * @instance
 * @param {Boolean} f depthtesting
 */
Context.prototype.pushDepthFunc = function (f)
{
    this._stackDepthFunc.push(f);
    this.gl.depthFunc(f);
};

/**
 * current state of blend
 * @function stateDepthFunc
 * @memberof Context
 * @instance
 * @returns {Boolean} depth testing enabled/disabled
 */
Context.prototype.stateDepthFunc = function ()
{
    if (this._stackDepthFunc.length > 0) return this._stackDepthFunc[this._stackDepthFunc.length - 1];
    return false;
};

/**
 * pop depth testing and set the previous state
 * @function popDepthFunc
 * @memberof Context
 * @instance
 */
Context.prototype.popDepthFunc = function ()
{
    this._stackDepthFunc.pop();
    if (this._stackDepthFunc.length > 0) this.gl.depthFunc(this._stackDepthFunc[this._stackDepthFunc.length - 1]);
};

// --------------------------------------
// state blending

Context.prototype._stackBlend = [];

/**
 * enable / disable blend
 * like gl.enable(gl.BLEND); / gl.disable(gl.BLEND);
 * @function pushBlend
 * @memberof Context
 * @instance
 * @param {boolean} b blending
 */
Context.prototype.pushBlend = function (b)
{
    this._stackBlend.push(b);
    if (!b) this.gl.disable(this.gl.BLEND);
    else this.gl.enable(this.gl.BLEND);
};

/**
 * pop blend state and set the previous state
 * @function popBlend
 * @memberof Context
 * @instance
 */
Context.prototype.popBlend = function ()
{
    this._stackBlend.pop();

    if (!this._stackBlend[this._stackBlend.length - 1]) this.gl.disable(this.gl.BLEND);
    else this.gl.enable(this.gl.BLEND);
};

/**
 * current state of blend
 * @function stateBlend
 * @returns {boolean} blending enabled/disabled
 * @memberof Context
 * @instance
 */
Context.prototype.stateBlend = function ()
{
    return this._stackBlend[this._stackBlend.length - 1];
};

const BLENDS = {
    "BLEND_NONE": 0,
    "BLEND_NORMAL": 1,
    "BLEND_ADD": 2,
    "BLEND_SUB": 3,
    "BLEND_MUL": 4,
};

Context.prototype._stackBlendMode = [];
Context.prototype._stackBlendModePremul = [];

/**
 * push and switch to predefined blendmode (CONSTANTS.BLEND_MODES.BLEND_NONE,CONSTANTS.BLEND_MODES.BLEND_NORMAL,CONSTANTS.BLEND_MODES.BLEND_ADD,CONSTANTS.BLEND_MODES.BLEND_SUB,CONSTANTS.BLEND_MODES.BLEND_MUL)
 * @function pushBlendMode
 * @memberof Context
 * @instance
 * @param {Number} blendMode
 * @param {Boolean} premul premultiplied mode
 */
Context.prototype.pushBlendMode = function (blendMode, premul)
{
    this._stackBlendMode.push(blendMode);
    this._stackBlendModePremul.push(premul);

    const n = this._stackBlendMode.length - 1;

    this.pushBlend(this._stackBlendMode[n] !== constants_CONSTANTS.BLEND_MODES.BLEND_NONE);
    this._setBlendMode(this._stackBlendMode[n], this._stackBlendModePremul[n]);
};

/**
 * pop predefined blendmode / switch back to previous blendmode
 * @function popBlendMode
 * @memberof Context
 * @instance
 */
Context.prototype.popBlendMode = function ()
{
    this._stackBlendMode.pop();
    this._stackBlendModePremul.pop();

    const n = this._stackBlendMode.length - 1;

    this.popBlend(this._stackBlendMode[n] !== constants_CONSTANTS.BLEND_MODES.BLEND_NONE);

    if (n >= 0) this._setBlendMode(this._stackBlendMode[n], this._stackBlendModePremul[n]);
};


// --------------------------------------
// state stencil

Context.prototype._stackStencil = [];

/**
 * enable / disable stencil testing

* @function pushStencil
 * @memberof Context
 * @instance
 * @param {Boolean} b enable
 */
Context.prototype.pushStencil = function (b)
{
    this._stackStencil.push(b);
    if (!b) this.gl.disable(this.gl.STENCIL_TEST);
    else this.gl.enable(this.gl.STENCIL_TEST);
};

/**
 * pop stencil test state and set the previous state
 * @function popStencil
 * @memberof Context
 * @instance
 */
Context.prototype.popStencil = function ()
{
    this._stackStencil.pop();

    if (!this._stackStencil[this._stackStencil.length - 1]) this.gl.disable(this.gl.STENCIL_TEST);
    else this.gl.enable(this.gl.STENCIL_TEST);
};

// --------------------------------------


Context.prototype.glGetAttribLocation = function (prog, name)
{
    const l = this.gl.getAttribLocation(prog, name);
    // if (l == -1)
    // {
    //     this._log.warn("get attr loc -1 ", name);
    // }
    return l;
};


/**
 * should an op now draw helpermeshes
 * @function shouldDrawHelpers
 * @memberof Context
 * @param op
 * @instance
 */
Context.prototype.shouldDrawHelpers = function (op)
{
    if (this.tempData.shadowPass) return false;
    if (!op.patch.isEditorMode()) return false;

    // const fb = this.getCurrentFrameBuffer();
    // if (fb && fb.getWidth)
    // {
    //     const fbshould = this.canvasWidth / this.canvasHeight == fb.getWidth() / fb.getHeight();
    //     if (!fbshould) return false;
    // }

    return gui.shouldDrawOverlay;// || (CABLES.UI.renderHelperCurrent && op.isCurrentUiOp());
};

Context.prototype._setBlendMode = function (blendMode, premul)
{
    const gl = this.gl;

    if (blendMode == constants_CONSTANTS.BLEND_MODES.BLEND_NONE)
    {
        // this.gl.disable(this.gl.BLEND);
    }
    else if (blendMode == constants_CONSTANTS.BLEND_MODES.BLEND_ADD)
    {
        if (premul)
        {
            gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
            gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE);
        }
        else
        {
            gl.blendEquation(gl.FUNC_ADD);
            gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
        }
    }
    else if (blendMode == constants_CONSTANTS.BLEND_MODES.BLEND_SUB)
    {
        if (premul)
        {
            gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
            gl.blendFuncSeparate(gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA);
        }
        else
        {
            gl.blendEquation(gl.FUNC_ADD);
            gl.blendFunc(gl.ZERO, gl.ONE_MINUS_SRC_COLOR);
        }
    }
    else if (blendMode == constants_CONSTANTS.BLEND_MODES.BLEND_MUL)
    {
        if (premul)
        {
            gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
            gl.blendFuncSeparate(gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA);
        }
        else
        {
            gl.blendEquation(gl.FUNC_ADD);
            gl.blendFunc(gl.ZERO, gl.SRC_COLOR);
        }
    }
    else if (blendMode == constants_CONSTANTS.BLEND_MODES.BLEND_NORMAL)
    {
        if (premul)
        {
            gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
            gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
        }
        else
        {
            gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
            gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
        }
    }
    else
    {
        this._log.log("setblendmode: unknown blendmode");
    }
};

Context.prototype.createMesh = function (geom, options)
{
    if (CABLES.UTILS.isNumeric(options))options = { "glPrimitive": options }; // old constructor fallback...
    return new CGL.Mesh(this, geom, options);
};


/**
 * set cursor
 * @function setCursor
 * @memberof Context
 * @instance
 * @param {String} str css cursor string
 */
Context.prototype.setCursor = function (str)
{
    this._cursor = str;
};

/**
 * enable a webgl extension
 * @function enableExtension
 * @memberof Context
 * @instance
 * @param {String} name extension name
 * @returns {Object} extension object or null
 */
Context.prototype.enableExtension = function (name)
{
    if (!this.gl) return null;

    if (this._enabledExtensions.hasOwnProperty(name))
        return this._enabledExtensions[name];

    const o = this.gl.getExtension(name);
    this._enabledExtensions[name] = o;

    if (!o)
        this._log.warn("[cgl_state] extension not available " + name);
    // else
        // this._log.log("enabled extension", name);

    return o;
};

Context.prototype.checkTextureSize = function (x)
{
    x = x || 1;
    x = Math.floor(x);
    x = Math.min(x, this.maxTexSize);
    x = Math.max(x, 1);
    return x;
};





;// CONCATENATED MODULE: ./src/core/core_variable.js


/**
 * @type {Object}
 * @name PatchVariable
 * @param {String} name
 * @param {String|Number} value
 * @memberof Patch
 * @constructor
 */
class PatchVariable extends Events
{
    constructor(name, val, type)
    {
        super();
        this._name = name;
        this.type = type;
        this.setValue(val);
    }

    /**
     * keeping this for backwards compatibility in older
     * exports before using eventtarget
     *
     * @param cb
     */
    addListener(cb)
    {
        this.on("change", cb, "var");
    }

    /**
     * @function Variable.getValue
     * @memberof PatchVariable
     * @returns {String|Number|Boolean}
     */
    getValue()
    {
        return this._v;
    }

    /**
     * @function getName
     * @memberof PatchVariable
     * @instance
     * @returns {String|Number|Boolean}
     * @function
     */
    getName()
    {
        return this._name;
    }

    /**
     * @function setValue
     * @memberof PatchVariable
     * @instance
     * @param v
     * @returns {String|Number|Boolean}
     * @function
     */
    setValue(v)
    {
        this._v = v;
        this.emitEvent("change", v, this);
    }
}

/* harmony default export */ const core_variable = (PatchVariable);

;// CONCATENATED MODULE: ./src/core/core_patch.js












/**
 * Patch class, contains all operators,values,links etc. manages loading and running of the whole patch
 *
 * see {@link PatchConfig}
 *
 * @namespace external:CABLES#Patch
 * @hideconstructor
 * @param {PatchConfig} cfg The configuration object.
 * @class
 * @example
 * CABLES.patch=new CABLES.Patch(
 * {
 *     patch:pStr,
 *     glCanvasId:'glcanvas',
 *     glCanvasResizeToWindow:true,
 *     canvas:{powerPreference:"high-performance"},
 *     prefixAssetPath:'/assets/',
 *     prefixJsPath:'/js/',
 *     onError:function(e){console.log(e);}
 *     glslPrecision:'highp'
 * });
 */

class Patch extends EventTarget
{
// const Patch(cfg)
    constructor(cfg)
    {
        super();
        // EventTarget.apply(this);

        this._log = new Logger("core_patch", { "onError": cfg.onError });
        this.ops = [];
        this.settings = {};
        this.config = cfg ||
        {
            "glCanvasResizeToWindow": false,
            "prefixAssetPath": "",
            "prefixJsPath": "",
            "silent": true,
            "onError": null,
            "onFinishedLoading": null,
            "onFirstFrameRendered": null,
            "onPatchLoaded": null,
            "fpsLimit": 0
        };
        this.timer = new Timer();
        this.freeTimer = new Timer();
        this.animFrameOps = [];
        this.animFrameCallbacks = [];
        this.gui = false;
        CABLES.logSilent = this.silent = true;
        this.profiler = null;
        this.aborted = false;
        this._crashedOps = [];
        this._renderOneFrame = false;
        this._animReq = null;
        this._opIdCache = {};
        this._triggerStack = [];
        this.storeObjNames = false; // remove after may release

        this.loading = new LoadingStatus(this);

        this._volumeListeners = [];
        this._paused = false;
        this._frameNum = 0;
        this.onOneFrameRendered = null;
        this.namedTriggers = {};

        this._origData = null;
        this._frameNext = 0;
        this._frameInterval = 0;
        this._lastFrameTime = 0;
        this._frameWasdelayed = true;
        this.tempData = this.frameStore = {};
        this.deSerialized = false;
        this.reqAnimTimeStamp = 0;

        this.cgCanvas = null;

        if (!(function () { return !this; }())) console.log("not in strict mode: core patch");

        this._isLocal = document.location.href.indexOf("file:") === 0;

        if (this.config.hasOwnProperty("silent")) this.silent = CABLES.logSilent = this.config.silent;
        if (!this.config.hasOwnProperty("doRequestAnimation")) this.config.doRequestAnimation = true;

        if (!this.config.prefixAssetPath) this.config.prefixAssetPath = "";
        if (!this.config.prefixJsPath) this.config.prefixJsPath = "";
        if (!this.config.masterVolume) this.config.masterVolume = 1.0;

        this._variables = {};
        this._variableListeners = [];
        this.vars = {};
        if (cfg && cfg.vars) this.vars = cfg.vars; // vars is old!

        this.cgl = new Context(this);
        this.cgp = null;

        this._subpatchOpCache = {};

        this.cgl.setCanvas(this.config.glCanvasId || this.config.glCanvas || "glcanvas");
        if (this.config.glCanvasResizeToWindow === true) this.cgl.setAutoResize("window");
        if (this.config.glCanvasResizeToParent === true) this.cgl.setAutoResize("parent");
        this.loading.setOnFinishedLoading(this.config.onFinishedLoading);

        if (this.cgl.aborted) this.aborted = true;
        if (this.cgl.silent) this.silent = true;

        this.freeTimer.play();
        this.exec();

        if (!this.aborted)
        {
            if (this.config.patch)
            {
                this.deSerialize(this.config.patch);
            }
            else if (this.config.patchFile)
            {
                ajax(
                    this.config.patchFile,
                    (err, _data) =>
                    {
                        try
                        {
                            const data = JSON.parse(_data);
                            if (err)
                            {
                                const txt = "";
                                this._log.error("err", err);
                                this._log.error("data", data);
                                this._log.error("data", data.msg);
                                return;
                            }
                            this.deSerialize(data);
                        }
                        catch (e)
                        {
                            this._log.error("could not load/parse patch ", e);
                        }
                    }
                );
            }
            this.timer.play();
        }

    console.log("made with https://cables.gl"); // eslint-disable-line
    }

    isPlaying()
    {
        return !this._paused;
    }

    isRenderingOneFrame()
    {
        return this._renderOneFrame;
    }


    renderOneFrame()
    {
        this._paused = true;
        this._renderOneFrame = true;
        this.exec();
        this._renderOneFrame = false;
    }

    /**
 * current number of frames per second
 * @function getFPS
 * @memberof Patch
 * @instance
 * @return {Number} fps
 */
    getFPS()
    {
        this._log.error("deprecated getfps");
        return 0;
    }

    /**
 * returns true if patch is opened in editor/gui mode
 * @function isEditorMode
 * @memberof Patch
 * @instance
 * @return {Boolean} editor mode
 */
    isEditorMode()
    {
        return this.config.editorMode === true;
    }

    /**
 * pauses patch execution
 * @function pause
 * @memberof Patch
 * @instance
 */
    pause()
    {
        cancelAnimationFrame(this._animReq);
        this.emitEvent("pause");
        this._animReq = null;
        this._paused = true;
        this.freeTimer.pause();
    }

    /**
 * resumes patch execution
 * @function resume
 * @memberof Patch
 * @instance
 */
    resume()
    {
        if (this._paused)
        {
            cancelAnimationFrame(this._animReq);
            this._paused = false;
            this.freeTimer.play();
            this.emitEvent("resume");
            this.exec();
        }
    }

    /**
 * set volume [0-1]
 * @function setVolume
 * @param {Number} v volume
 * @memberof Patch
 * @instance
 */
    setVolume(v)
    {
        this.config.masterVolume = v;
        for (let i = 0; i < this._volumeListeners.length; i++) this._volumeListeners[i].onMasterVolumeChanged(v);
    }


    /**
 * get asset path
 * @function getAssetPath
 * @memberof Patch
 * @param patchId
 * @instance
 */
    getAssetPath(patchId = null)
    {
        if (this.config.hasOwnProperty("assetPath"))
        {
            return this.config.assetPath;
        }
        else if (this.isEditorMode())
        {
            let id = patchId || gui.project()._id;
            return "/assets/" + id + "/";
        }
        else if (document.location.href.indexOf("cables.gl") > 0 || document.location.href.indexOf("cables.local") > 0)
        {
            const parts = document.location.pathname.split("/");
            let id = patchId || parts[parts.length - 1];
            return "/assets/" + id + "/";
        }
        else
        {
            return "assets/";
        }
    }

    /**
 * get js path
 * @function getJsPath
 * @memberof Patch
 * @instance
 */
    getJsPath()
    {
        if (this.config.hasOwnProperty("jsPath"))
        {
            return this.config.jsPath;
        }
        else
        {
            return "js/";
        }
    }

    /**
 * get url/filepath for a filename
 * this uses prefixAssetpath in exported patches
 * @function getFilePath
 * @memberof Patch
 * @instance
 * @param {String} filename
 * @return {String} url
 */
    getFilePath(filename)
    {
        if (!filename) return filename;
        filename = String(filename);
        if (filename.indexOf("https:") === 0 || filename.indexOf("http:") === 0) return filename;
        if (filename.indexOf("data:") === 0) return filename;
        if (filename.indexOf("file:") === 0) return filename;
        filename = filename.replace("//", "/");
        if (filename.startsWith(this.config.prefixAssetPath)) filename = filename.replace(this.config.prefixAssetPath, "");
        return this.config.prefixAssetPath + filename + (this.config.suffixAssetPath || "");
    }

    clear()
    {
        this.emitEvent("patchClearStart");
        this.cgl.TextureEffectMesh = null;
        this.animFrameOps.length = 0;
        this.timer = new Timer();
        while (this.ops.length > 0) this.deleteOp(this.ops[0].id);

        this._opIdCache = {};
        this.emitEvent("patchClearEnd");
    }




    createOp(identifier, id, opName = null)
    {
        let op = null;
        let objName = "";

        try
        {
            if (!identifier)
            {
                console.error("createop identifier false", identifier);
                console.log((new Error()).stack);
                return;
            }
            if (identifier.indexOf("Ops.") === -1)
            {
                // this should be a uuid, not a namespace
                // creating ops by id should be the default way from now on!
                const opId = identifier;



                if (CABLES.OPS[opId])
                {
                    objName = CABLES.OPS[opId].objName;
                    op = new CABLES.OPS[opId].f(this, objName, id, opId);
                    op.opId = opId;
                }
                else
                {
                    if (opName)
                    {
                        identifier = opName;
                        this._log.warn("could not find op by id: " + opId);
                    }
                    else
                    {
                        throw new Error("could not find op by id: " + opId, { "cause": "opId:" + opId });
                    }
                }
            }

            if (!op)
            {
                // fallback: create by objname!
                objName = identifier;
                const parts = identifier.split(".");
                const opObj = Patch.getOpClass(objName);

                if (!opObj)
                {
                    this.emitEvent("criticalError", { "title": "unknown op" + objName, "text": "unknown op: " + objName });

                    this._log.error("unknown op: " + objName);
                    throw new Error("unknown op: " + objName);
                }
                else
                {
                    if (parts.length == 2) op = new window[parts[0]][parts[1]](this, objName, id);
                    else if (parts.length == 3) op = new window[parts[0]][parts[1]][parts[2]](this, objName, id);
                    else if (parts.length == 4) op = new window[parts[0]][parts[1]][parts[2]][parts[3]](this, objName, id);
                    else if (parts.length == 5) op = new window[parts[0]][parts[1]][parts[2]][parts[3]][parts[4]](this, objName, id);
                    else if (parts.length == 6) op = new window[parts[0]][parts[1]][parts[2]][parts[3]][parts[4]][parts[5]](this, objName, id);
                    else if (parts.length == 7) op = new window[parts[0]][parts[1]][parts[2]][parts[3]][parts[4]][parts[5]][parts[6]](this, objName, id);
                    else if (parts.length == 8) op = new window[parts[0]][parts[1]][parts[2]][parts[3]][parts[4]][parts[5]][parts[6]][parts[7]](this, objName, id);
                    else if (parts.length == 9) op = new window[parts[0]][parts[1]][parts[2]][parts[3]][parts[4]][parts[5]][parts[6]][parts[7]][parts[8]](this, objName, id);
                    else if (parts.length == 10) op = new window[parts[0]][parts[1]][parts[2]][parts[3]][parts[4]][parts[5]][parts[6]][parts[7]][parts[8]][parts[9]](this, objName, id);
                    else console.log("parts.length", parts.length);
                }

                if (op)
                {
                    op.opId = null;
                    for (const i in CABLES.OPS)
                    {
                        if (CABLES.OPS[i].objName == objName) op.opId = i;
                    }
                }
            }
        }
        catch (e)
        {
            this._crashedOps.push(objName);

            this._log.error("[instancing error] " + objName, e);

            if (!this.isEditorMode())
            {
                this._log.error("INSTANCE_ERR", "Instancing Error: " + objName, e);
                // throw new Error("instancing error 1" + objName);
            }
        }

        if (op)
        {
            op._objName = objName;
            op.patch = this;
        }
        else
        {
            this._log.log("no op was created!?", identifier, id);
        }
        return op;
    }

    /**
     * create a new op in patch
     * @function addOp
     * @memberof Patch
     * @instance
     * @param {string} opIdentifier uuid or name, e.g. Ops.Math.Sum
     * @param {Object} uiAttribs Attributes
     * @param {string} id
     * @param {boolean} fromDeserialize
     * @param {string} opName e.g. Ops.Math.Sum
     * @example
     * // add invisible op
     * patch.addOp('Ops.Math.Sum', { showUiAttribs: false });
     */
    addOp(opIdentifier, uiAttribs, id, fromDeserialize, opName)
    {
        const op = this.createOp(opIdentifier, id, opName);

        if (op)
        {
            uiAttribs = uiAttribs || {};
            if (uiAttribs.hasOwnProperty("errors")) delete uiAttribs.errors;
            if (uiAttribs.hasOwnProperty("error")) delete uiAttribs.error;
            uiAttribs.subPatch = uiAttribs.subPatch || 0;

            op.setUiAttribs(uiAttribs);
            if (op.onCreate) op.onCreate();

            if (op.hasOwnProperty("onAnimFrame")) this.addOnAnimFrame(op);
            if (op.hasOwnProperty("onMasterVolumeChanged")) this._volumeListeners.push(op);

            if (this._opIdCache[op.id])
            {
                this._log.warn("opid with id " + op.id + " already exists in patch!");
                this.deleteOp(op.id); // strange with subpatch ops: why is this needed, somehow ops get added twice ???.....
                // return;
            }

            this.ops.push(op);
            this._opIdCache[op.id] = op;

            if (this._subPatchCacheAdd) this._subPatchCacheAdd(uiAttribs.subPatch, op);
            this.emitEvent("onOpAdd", op, fromDeserialize);

            if (op.init) op.init();

            op.emitEvent("init", fromDeserialize);
        }
        else
        {
            this._log.error("addop: op could not be created: ", opIdentifier);
        }

        return op;
    }

    addOnAnimFrame(op)
    {
        for (let i = 0; i < this.animFrameOps.length; i++) if (this.animFrameOps[i] == op) { return; }

        this.animFrameOps.push(op);
    }

    removeOnAnimFrame(op)
    {
        for (let i = 0; i < this.animFrameOps.length; i++)
        {
            if (this.animFrameOps[i] == op)
            {
                this.animFrameOps.splice(i, 1);
                return;
            }
        }
    }

    addOnAnimFrameCallback(cb)
    {
        this.animFrameCallbacks.push(cb);
    }

    removeOnAnimCallback(cb)
    {
        for (let i = 0; i < this.animFrameCallbacks.length; i++)
        {
            if (this.animFrameCallbacks[i] == cb)
            {
                this.animFrameCallbacks.splice(i, 1);
                return;
            }
        }
    }

    deleteOp(opid, tryRelink, reloadingOp)
    {
        let found = false;
        for (const i in this.ops)
        {
            if (this.ops[i].id == opid)
            {
                const op = this.ops[i];
                let reLinkP1 = null;
                let reLinkP2 = null;

                if (op)
                {
                    found = true;
                    if (tryRelink)
                    {
                        if (op.portsIn.length > 0 && op.portsIn[0].isLinked() && (op.portsOut.length > 0 && op.portsOut[0].isLinked()))
                        {
                            if (op.portsIn[0].getType() == op.portsOut[0].getType() && op.portsIn[0].links[0])
                            {
                                reLinkP1 = op.portsIn[0].links[0].getOtherPort(op.portsIn[0]);
                                reLinkP2 = op.portsOut[0].links[0].getOtherPort(op.portsOut[0]);
                            }
                        }
                    }

                    const opToDelete = this.ops[i];
                    opToDelete.removeLinks();

                    if (this.onDelete)
                    {
                        // todo: remove
                        this._log.warn("deprecated this.onDelete", this.onDelete);
                        this.onDelete(opToDelete);
                    }

                    this.ops.splice(i, 1);
                    opToDelete.emitEvent("delete", opToDelete);
                    this.emitEvent("onOpDelete", opToDelete, reloadingOp);

                    if (this.clearSubPatchCache) this.clearSubPatchCache(opToDelete.uiAttribs.subPatch);

                    if (opToDelete.onDelete) opToDelete.onDelete(reloadingOp);
                    opToDelete.cleanUp();

                    if (reLinkP1 !== null && reLinkP2 !== null)
                    {
                        this.link(reLinkP1.op, reLinkP1.getName(), reLinkP2.op, reLinkP2.getName());
                    }

                    delete this._opIdCache[opid];
                    break;
                }
            }
        }

        if (!found) this._log.warn("core patch deleteop: not found...", opid);
    }

    getFrameNum()
    {
        return this._frameNum;
    }

    emitOnAnimFrameEvent(time, delta)
    {
        time = time || this.timer.getTime();

        for (let i = 0; i < this.animFrameCallbacks.length; ++i)
            if (this.animFrameCallbacks[i])
                this.animFrameCallbacks[i](time, this._frameNum, delta);

        for (let i = 0; i < this.animFrameOps.length; ++i)
            if (this.animFrameOps[i].onAnimFrame)
                this.animFrameOps[i].onAnimFrame(time, this._frameNum, delta);
    }

    renderFrame(timestamp)
    {
        this.timer.update(this.reqAnimTimeStamp);
        this.freeTimer.update(this.reqAnimTimeStamp);
        const time = this.timer.getTime();
        const startTime = performance.now();
        this.cgl.frameStartTime = this.timer.getTime();

        const delta = timestamp - this.reqAnimTimeStamp || timestamp;

        this.emitOnAnimFrameEvent(null, delta);

        this.cgl.profileData.profileFrameDelta = delta;
        this.reqAnimTimeStamp = timestamp;
        this.cgl.profileData.profileOnAnimFrameOps = performance.now() - startTime;

        this.emitEvent("onRenderFrame", time);

        this._frameNum++;
        if (this._frameNum == 1)
        {
            if (this.config.onFirstFrameRendered) this.config.onFirstFrameRendered();
        }
    }

    exec(timestamp)
    {
        if (!this._renderOneFrame && (this._paused || this.aborted)) return;
        this.emitEvent("reqAnimFrame");
        cancelAnimationFrame(this._animReq);

        this.config.fpsLimit = this.config.fpsLimit || 0;
        if (this.config.fpsLimit)
        {
            this._frameInterval = 1000 / this.config.fpsLimit;
        }

        const now = CABLES.now();
        const frameDelta = now - this._frameNext;

        if (this.isEditorMode())
        {
            if (!this._renderOneFrame)
            {
                if (now - this._lastFrameTime >= 500 && this._lastFrameTime !== 0 && !this._frameWasdelayed)
                {
                    this._lastFrameTime = 0;
                    setTimeout(this.exec.bind(this), 500);
                    this.emitEvent("renderDelayStart");
                    this._frameWasdelayed = true;
                    return;
                }
            }
        }

        if (this._renderOneFrame || this.config.fpsLimit === 0 || frameDelta > this._frameInterval || this._frameWasdelayed)
        {
            this.renderFrame(timestamp);

            if (this._frameInterval) this._frameNext = now - (frameDelta % this._frameInterval);
        }

        if (this._frameWasdelayed)
        {
            this.emitEvent("renderDelayEnd");
            this._frameWasdelayed = false;
        }

        if (this._renderOneFrame)
        {
            if (this.onOneFrameRendered) this.onOneFrameRendered(); // todo remove everywhere and use propper event...
            this.emitEvent("renderedOneFrame");
            this._renderOneFrame = false;
        }


        if (this.config.doRequestAnimation) this._animReq = this.cgl.canvas.ownerDocument.defaultView.requestAnimationFrame(this.exec.bind(this));
    }

    /**
     * link two ops/ports
     * @function link
     * @memberof Patch
     * @instance
     * @param {Op} op1
     * @param {String} port1Name
     * @param {Op} op2
     * @param {String} port2Name
     * @param {boolean} lowerCase
     * @param {boolean} fromDeserialize
     */
    link(op1, port1Name, op2, port2Name, lowerCase, fromDeserialize)
    {
        if (!op1) return this._log.warn("link: op1 is null ");
        if (!op2) return this._log.warn("link: op2 is null");

        const port1 = op1.getPort(port1Name, lowerCase);
        const port2 = op2.getPort(port2Name, lowerCase);

        if (!port1) return op1._log.warn("port1 not found! " + port1Name + " (" + op1.objName + ")");
        if (!port2) return op1._log.warn("port2 not found! " + port2Name + " of " + op2.name + "(" + op2.objName + ")", op2);

        if (!port1.shouldLink(port1, port2) || !port2.shouldLink(port1, port2)) return false;

        if (Link.canLink(port1, port2))
        {
            const link = new Link(this);
            link.link(port1, port2);

            this.emitEvent("onLink", port1, port2, link, fromDeserialize);
            return link;
        }
    }

    serialize(options)
    {
        const obj = {};

        options = options || {};
        obj.ops = [];
        obj.settings = this.settings;
        for (const i in this.ops)
        {
            const op = this.ops[i];
            if (op && op.getSerialized)obj.ops.push(op.getSerialized());
        }

        cleanJson(obj);

        if (options.asObject) return obj;
        return JSON.stringify(obj);
    }

    getOpsByRefId(refId)
    {
        const perf = CABLES.UI.uiProfiler.start("[corepatchetend] getOpsByRefId");
        const refOps = [];
        const ops = gui.corePatch().ops;
        for (let i = 0; i < ops.length; i++)
            if (ops[i].storage && ops[i].storage.ref == refId) refOps.push(ops[i]);
        perf.finish();
        return refOps;
    }

    getOpById(opid)
    {
        return this._opIdCache[opid];
    }

    getOpsByName(name)
    {
        // TODO: is this still needed ? unclear behaviour....
        const arr = [];
        for (const i in this.ops)
            if (this.ops[i].name == name) arr.push(this.ops[i]);
        return arr;
    }

    getOpsByObjName(name)
    {
        const arr = [];
        for (const i in this.ops)
            if (this.ops[i].objName == name) arr.push(this.ops[i]);
        return arr;
    }

    getOpsByOpId(opid)
    {
        const arr = [];
        for (const i in this.ops)
            if (this.ops[i].opId == opid) arr.push(this.ops[i]);
        return arr;
    }

    loadLib(which)
    {
        ajaxSync(
            "/ui/libs/" + which + ".js",
            (err, res) =>
            {
                const se = document.createElement("script");
                se.type = "text/javascript";
                se.text = res;
                document.getElementsByTagName("head")[0].appendChild(se);
            },
            "GET",
        );
    }

    getSubPatchOpsByName(patchId, objName)
    {
        const arr = [];
        for (const i in this.ops)
            if (this.ops[i].uiAttribs && this.ops[i].uiAttribs.subPatch == patchId && this.ops[i].objName == objName)
                arr.push(this.ops[i]);

        return arr;
    }

    getSubPatchOp(patchId, objName)
    {
        return this.getFirstSubPatchOpByName(patchId, objName);
    }

    getFirstSubPatchOpByName(patchId, objName)
    {
        for (const i in this.ops)
            if (this.ops[i].uiAttribs && this.ops[i].uiAttribs.subPatch == patchId && this.ops[i].objName == objName)
                return this.ops[i];

        return false;
    }

    _addLink(opinid, opoutid, inName, outName)
    {
        return this.link(this.getOpById(opinid), inName, this.getOpById(opoutid), outName, false, true);
    }

    deSerialize(obj, options)
    {
        options = options || { "genIds": false, "createRef": false };
        if (this.aborted) return;
        const newOps = [];
        const loadingId = this.loading.start("core", "deserialize");

        this.namespace = obj.namespace || "";
        this.name = obj.name || "";

        if (typeof obj === "string") obj = JSON.parse(obj);

        this.settings = obj.settings;

        this.emitEvent("patchLoadStart");

        obj.ops = obj.ops || [];

        if (window.logStartup)logStartup("add " + obj.ops.length + " ops... ");

        const addedOps = [];

        // add ops...
        for (let iop = 0; iop < obj.ops.length; iop++)
        {
            const start = CABLES.now();
            const opData = obj.ops[iop];
            let op = null;

            try
            {
                if (opData.opId) op = this.addOp(opData.opId, opData.uiAttribs, opData.id, true, opData.objName);
                else op = this.addOp(opData.objName, opData.uiAttribs, opData.id, true);
            }
            catch (e)
            {
                this._log.error("[instancing error] op data:", opData, e);
                // throw new Error("could not create op by id: <b>" + (opData.objName || opData.opId) + "</b> (" + opData.id + ")");
            }

            if (op)
            {
                addedOps.push(op);
                if (options.genIds) op.id = shortId();
                op.portsInData = opData.portsIn;
                op._origData = JSON.parse(JSON.stringify(opData));
                op.storage = opData.storage;
                // if (opData.hasOwnProperty("disabled"))op.setEnabled(!opData.disabled);

                for (const ipi in opData.portsIn)
                {
                    const objPort = opData.portsIn[ipi];
                    if (objPort && objPort.hasOwnProperty("name"))
                    {
                        const port = op.getPort(objPort.name);

                        if (port && (port.uiAttribs.display == "bool" || port.uiAttribs.type == "bool") && !isNaN(objPort.value)) objPort.value = objPort.value == true ? 1 : 0;
                        if (port && objPort.value !== undefined && port.type != CONSTANTS.OP.OP_PORT_TYPE_TEXTURE) port.set(objPort.value);

                        if (port)
                        {
                            port.deSerializeSettings(objPort);
                        }
                        else
                        {
                            // if (port.uiAttribs.hasOwnProperty("title"))
                            // {
                            //     op.preservedPortTitles = op.preservedPortTitles || {};
                            //     op.preservedPortTitles[port.name] = port.uiAttribs.title;
                            // }
                            op.preservedPortValues = op.preservedPortValues || {};
                            op.preservedPortValues[objPort.name] = objPort.value;
                        }
                    }
                }

                for (const ipo in opData.portsOut)
                {
                    const objPort = opData.portsOut[ipo];
                    if (objPort && objPort.hasOwnProperty("name"))
                    {
                        const port2 = op.getPort(objPort.name);

                        if (port2)
                        {
                            port2.deSerializeSettings(objPort);

                            if (port2.uiAttribs.hasOwnProperty("title"))
                            {
                                op.preservedPortTitles = op.preservedPortTitles || {};
                                op.preservedPortTitles[port2.name] = port2.uiAttribs.title;
                            }


                            if (port2.type != CONSTANTS.OP.OP_PORT_TYPE_TEXTURE && objPort.hasOwnProperty("value"))
                                port2.set(obj.ops[iop].portsOut[ipo].value);

                            if (objPort.expose) port2.setUiAttribs({ "expose": true });
                        }
                    }
                }
                newOps.push(op);
            }

            const timeused = Math.round(100 * (CABLES.now() - start)) / 100;
            if (!this.silent && timeused > 5) console.log("long op init ", obj.ops[iop].objName, timeused);
        }
        if (window.logStartup)logStartup("add ops done");

        for (const i in this.ops)
        {
            if (this.ops[i].onLoadedValueSet)
            {
                this.ops[i].onLoadedValueSet(this.ops[i]._origData);
                this.ops[i].onLoadedValueSet = null;
                this.ops[i]._origData = null;
            }
            this.ops[i].emitEvent("loadedValueSet");
        }

        if (window.logStartup)logStartup("creating links");

        if (options.opsCreated)options.opsCreated(addedOps);
        // create links...
        if (obj.ops)
        {
            for (let iop = 0; iop < obj.ops.length; iop++)
            {
                if (obj.ops[iop].portsIn)
                {
                    for (let ipi2 = 0; ipi2 < obj.ops[iop].portsIn.length; ipi2++)
                    {
                        if (obj.ops[iop].portsIn[ipi2] && obj.ops[iop].portsIn[ipi2].links)
                        {
                            for (let ili = 0; ili < obj.ops[iop].portsIn[ipi2].links.length; ili++)
                            {
                                const l = this._addLink(
                                    obj.ops[iop].portsIn[ipi2].links[ili].objIn,
                                    obj.ops[iop].portsIn[ipi2].links[ili].objOut,
                                    obj.ops[iop].portsIn[ipi2].links[ili].portIn,
                                    obj.ops[iop].portsIn[ipi2].links[ili].portOut);

                                // const took = performance.now - startTime;
                                // if (took > 100)console.log(obj().ops[iop].portsIn[ipi2].links[ili].objIn, obj.ops[iop].portsIn[ipi2].links[ili].objOut, took);
                            }
                        }
                    }
                }
                if (obj.ops[iop].portsOut)
                    for (let ipi2 = 0; ipi2 < obj.ops[iop].portsOut.length; ipi2++)
                        if (obj.ops[iop].portsOut[ipi2] && obj.ops[iop].portsOut[ipi2].links)
                        {
                            for (let ili = 0; ili < obj.ops[iop].portsOut[ipi2].links.length; ili++)
                            {
                                if (obj.ops[iop].portsOut[ipi2].links[ili])
                                {
                                    if (obj.ops[iop].portsOut[ipi2].links[ili].subOpRef)
                                    {
                                        // lost link
                                        const outOp = this.getOpById(obj.ops[iop].portsOut[ipi2].links[ili].objOut);
                                        let dstOp = null;
                                        let theSubPatch = 0;

                                        for (let i = 0; i < this.ops.length; i++)
                                        {
                                            if (
                                                this.ops[i].storage &&
                                                this.ops[i].storage.ref == obj.ops[iop].portsOut[ipi2].links[ili].subOpRef &&
                                                outOp.uiAttribs.subPatch == this.ops[i].uiAttribs.subPatch
                                            )
                                            {
                                                theSubPatch = this.ops[i].patchId.get();
                                                break;
                                            }
                                        }

                                        for (let i = 0; i < this.ops.length; i++)
                                        {
                                            if (
                                                this.ops[i].storage &&
                                                this.ops[i].storage.ref == obj.ops[iop].portsOut[ipi2].links[ili].refOp &&
                                                this.ops[i].uiAttribs.subPatch == theSubPatch)
                                            {
                                                dstOp = this.ops[i];
                                                break;
                                            }
                                        }

                                        if (!dstOp) this._log.warn("could not find op for lost link");
                                        else
                                        {
                                            const l = this._addLink(
                                                dstOp.id,
                                                obj.ops[iop].portsOut[ipi2].links[ili].objOut,

                                                obj.ops[iop].portsOut[ipi2].links[ili].portIn,
                                                obj.ops[iop].portsOut[ipi2].links[ili].portOut);
                                        }
                                    }
                                    else
                                    {
                                        const l = this._addLink(obj.ops[iop].portsOut[ipi2].links[ili].objIn, obj.ops[iop].portsOut[ipi2].links[ili].objOut, obj.ops[iop].portsOut[ipi2].links[ili].portIn, obj.ops[iop].portsOut[ipi2].links[ili].portOut);

                                        if (!l)
                                        {
                                            const op1 = this.getOpById(obj.ops[iop].portsOut[ipi2].links[ili].objIn);
                                            const op2 = this.getOpById(obj.ops[iop].portsOut[ipi2].links[ili].objOut);

                                            if (!op1)console.log("could not find link op1");
                                            if (!op2)console.log("could not find link op2");

                                            const p1Name = obj.ops[iop].portsOut[ipi2].links[ili].portIn;

                                            if (op1 && !op1.getPort(p1Name))
                                            {
                                                // console.log("PRESERVE port 1 not found", p1Name);

                                                op1.preservedPortLinks[p1Name] = op1.preservedPortLinks[p1Name] || [];
                                                op1.preservedPortLinks[p1Name].push(obj.ops[iop].portsOut[ipi2].links[ili]);
                                            }

                                            const p2Name = obj.ops[iop].portsOut[ipi2].links[ili].portOut;
                                            if (op2 && !op2.getPort(p2Name))
                                            {
                                                // console.log("PRESERVE port 2 not found", obj.ops[iop].portsOut[ipi2].links[ili].portOut);
                                                op2.preservedPortLinks[p1Name] = op2.preservedPortLinks[p1Name] || [];
                                                op2.preservedPortLinks[p1Name].push(obj.ops[iop].portsOut[ipi2].links[ili]);
                                            }
                                        }
                                    }
                                }
                            }
                        }
            }
        }

        if (window.logStartup)logStartup("calling ops onloaded");

        for (const i in this.ops)
        {
            if (this.ops[i].onLoaded)
            {
                // TODO: deprecate!!!
                this.ops[i].onLoaded();
                this.ops[i].onLoaded = null;
            }
        }

        if (window.logStartup)logStartup("initializing ops...");
        for (const i in this.ops)
        {
            if (this.ops[i].init)
            {
                try
                {
                    this.ops[i].init();
                    this.ops[i].init = null;
                }
                catch (e)
                {
                    console.error("op.init crash", e);
                }
            }
        }

        if (window.logStartup)logStartup("initializing vars...");

        if (this.config.variables)
            for (const varName in this.config.variables)
                this.setVarValue(varName, this.config.variables[varName]);

        if (window.logStartup)logStartup("initializing var ports");

        for (const i in this.ops)
        {
            this.ops[i].initVarPorts();
            delete this.ops[i].uiAttribs.pasted;
        }

        setTimeout(() => { this.loading.finished(loadingId); }, 100);

        if (this.config.onPatchLoaded) this.config.onPatchLoaded(this);

        this.deSerialized = true;
        this.emitEvent("patchLoadEnd", newOps, obj, options.genIds);
    }

    profile(enable)
    {
        this.profiler = new Profiler(this);
        for (const i in this.ops)
        {
            this.ops[i].profile(enable);
        }
    }

    // ----------------------

    /**
     * set variable value
     * @function setVariable
     * @memberof Patch
     * @instance
     * @param {String} name of variable
     * @param {Number|String|Boolean} val value
     */
    setVariable(name, val)
    {
        // if (this._variables.hasOwnProperty(name))
        if (this._variables[name] !== undefined)
        {
            this._variables[name].setValue(val);
        }
        else
        {
            this._log.warn("variable " + name + " not found!");
        }
    }

    _sortVars()
    {
        if (!this.isEditorMode()) return;
        const ordered = {};
        Object.keys(this._variables).sort(
            (a, b) =>
            { return a.localeCompare(b, "en", { "sensitivity": "base" }); }
        ).forEach((key) =>
        {
            ordered[key] = this._variables[key];
        });
        this._variables = ordered;
    }

    /**
     * has variable
     * @function hasVariable
     * @memberof Patch
     * @instance
     * @param {String} name of variable
     */
    hasVar(name)
    {
        return this._variables[name] !== undefined;

        // return this._variables.hasOwnProperty(name);
    }

    // used internally
    setVarValue(name, val, type)
    {
        if (this.hasVar(name))
        {
            this._variables[name].setValue(val);
        }
        else
        {
            this._variables[name] = new core_variable(name, val, type);
            this._sortVars();
            this.emitEvent("variablesChanged");
        }
        return this._variables[name];
    }

    // old?
    getVarValue(name, val)
    {
        if (this._variables.hasOwnProperty(name)) return this._variables[name].getValue();
    }

    /**
     * @function getVar
     * @memberof Patch
     * @instance
     * @param {String} name
     * @return {Variable} variable
     */
    getVar(name)
    {
        if (this._variables.hasOwnProperty(name)) return this._variables[name];
    }


    deleteVar(name)
    {
        for (let i = 0; i < this.ops.length; i++)
            for (let j = 0; j < this.ops[i].portsIn.length; j++)
                if (this.ops[i].portsIn[j].getVariableName() == name)
                    this.ops[i].portsIn[j].setVariable(null);

        delete this._variables[name];
        this.emitEvent("variableDeleted", name);
        this.emitEvent("variablesChanged");
    }

    /**
     * @function getVars
     * @memberof Patch
     * @instance
     * @param t
     * @return {Array<Variable>} variables
     * @function
     */
    getVars(t)
    {
        if (t === undefined) return this._variables;

        const vars = [];
        if (t == CABLES.OP_PORT_TYPE_STRING) t = "string";
        if (t == CABLES.OP_PORT_TYPE_VALUE) t = "number";
        if (t == CABLES.OP_PORT_TYPE_ARRAY) t = "array";
        if (t == CABLES.OP_PORT_TYPE_OBJECT) t = "object";

        for (const i in this._variables)
        {
            if (!this._variables[i].type || this._variables[i].type == t) vars.push(this._variables[i]);
        }
        return vars;
    }


    /**
     * @function preRenderOps
     * @memberof Patch
     * @instance
     * @description invoke pre rendering of ops
     * @function
     */
    preRenderOps()
    {
        this._log.log("prerendering...");

        for (let i = 0; i < this.ops.length; i++)
        {
            if (this.ops[i].preRender)
            {
                this.ops[i].preRender();
                this._log.log("prerender " + this.ops[i].objName);
            }
        }
    }

    /**
     * @function dispose
     * @memberof Patch
     * @instance
     * @description stop, dispose and cleanup patch
     */
    dispose()
    {
        this.pause();
        this.clear();
        this.cgl.dispose();
    }

    pushTriggerStack(p)
    {
        this._triggerStack.push(p);
    }

    popTriggerStack()
    {
        this._triggerStack.pop();
    }

    printTriggerStack()
    {
        if (this._triggerStack.length == 0)
        {
            // console.log("stack length", this._triggerStack.length); // eslint-disable-line
            return;
        }
        console.groupCollapsed( // eslint-disable-line
            "trigger port stack " + this._triggerStack[this._triggerStack.length - 1].op.objName + "." + this._triggerStack[this._triggerStack.length - 1].name,
        );

        const rows = [];
        for (let i = 0; i < this._triggerStack.length; i++)
        {
            rows.push(i + ". " + this._triggerStack[i].op.objName + " " + this._triggerStack[i].name);
        }

        console.table(rows); // eslint-disable-line
        console.groupEnd(); // eslint-disable-line
    }

    /**
     * returns document object of the patch could be != global document object when opening canvas ina popout window
     * @function getDocument
     * @memberof Patch
     * @instance
     * @return {Object} document
     */
    getDocument()
    {
        return this.cgl.canvas.ownerDocument;
    }
}

Patch.getOpClass = function (objName)
{
    const parts = objName.split(".");
    let opObj = null;

    try
    {
        if (parts.length == 2) opObj = window[parts[0]][parts[1]];
        else if (parts.length == 3) opObj = window[parts[0]][parts[1]][parts[2]];
        else if (parts.length == 4) opObj = window[parts[0]][parts[1]][parts[2]][parts[3]];
        else if (parts.length == 5) opObj = window[parts[0]][parts[1]][parts[2]][parts[3]][parts[4]];
        else if (parts.length == 6) opObj = window[parts[0]][parts[1]][parts[2]][parts[3]][parts[4]][parts[5]];
        else if (parts.length == 7) opObj = window[parts[0]][parts[1]][parts[2]][parts[3]][parts[4]][parts[5]][parts[6]];
        else if (parts.length == 8) opObj = window[parts[0]][parts[1]][parts[2]][parts[3]][parts[4]][parts[5]][parts[6]][parts[7]];
        else if (parts.length == 9) opObj = window[parts[0]][parts[1]][parts[2]][parts[3]][parts[4]][parts[5]][parts[6]][parts[7]][parts[8]];
        else if (parts.length == 10) opObj = window[parts[0]][parts[1]][parts[2]][parts[3]][parts[4]][parts[5]][parts[6]][parts[7]][parts[8]][parts[9]];
        return opObj;
    }
    catch (e)
    {
        return null;
    }
};



Patch.replaceOpIds = function (json, options)
{
    const opids = {};
    for (const i in json.ops)
    {
        opids[json.ops[i].id] = json.ops[i];
    }

    for (const j in json.ops)
    {
        for (const k in json.ops[j].portsOut)
        {
            const links = json.ops[j].portsOut[k].links;
            if (links)
            {
                let l = links.length;

                while (l--)
                {
                    if (links[l] && (!opids[links[l].objIn] || !opids[links[l].objOut]))
                    {
                        if (!options.doNotUnlinkLostLinks)
                        {
                            links.splice(l, 1);
                        }
                        else
                        {
                            if (options.fixLostLinks)
                            {
                                // console.log("lost link...?", links[l]);
                                const op = gui.corePatch().getOpById(links[l].objIn);
                                if (!op) console.log("op not found!");
                                else
                                {
                                    const outerOp = gui.patchView.getSubPatchOuterOp(op.uiAttribs.subPatch);
                                    if (outerOp)
                                    {
                                        op.storage = op.storage || {};
                                        op.storage.ref = op.storage.ref || CABLES.shortId();
                                        links[l].refOp = op.storage.ref;
                                        links[l].subOpRef = outerOp.storage.ref;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }



    for (const i in json.ops)
    {
        const op = json.ops[i];
        const oldId = op.id;
        let newId = CABLES.shortId();

        if (options.prefixHash) newId = prefixedHash(options.prefixHash + oldId);

        else if (options.prefixId) newId = options.prefixId + oldId;
        else if (options.refAsId) // when saving json
        {
            if (op.storage && op.storage.ref)
            {
                newId = op.storage.ref;
                delete op.storage.ref;
            }
            else
            {
                op.storage = op.storage || {};
                op.storage.ref = newId = CABLES.shortId();
            }
        }

        const newID = op.id = newId;

        if (options.oldIdAsRef) // when loading json
        {
            op.storage = op.storage || {};
            op.storage.ref = oldId;
        }

        for (const j in json.ops)
        {
            if (json.ops[j].portsIn)
                for (const k in json.ops[j].portsIn)
                {
                    if (json.ops[j].portsIn[k].links)
                    {
                        let l = json.ops[j].portsIn[k].links.length;

                        while (l--) if (json.ops[j].portsIn[k].links[l] === null) json.ops[j].portsIn[k].links.splice(l, 1);

                        for (l in json.ops[j].portsIn[k].links)
                        {
                            if (json.ops[j].portsIn[k].links[l].objIn === oldId) json.ops[j].portsIn[k].links[l].objIn = newID;
                            if (json.ops[j].portsIn[k].links[l].objOut === oldId) json.ops[j].portsIn[k].links[l].objOut = newID;
                        }
                    }
                }

            if (json.ops[j].portsOut)
                for (const k in json.ops[j].portsOut)
                {
                    if (json.ops[j].portsOut[k].links)
                    {
                        let l = json.ops[j].portsOut[k].links.length;

                        while (l--) if (json.ops[j].portsOut[k].links[l] === null) json.ops[j].portsOut[k].links.splice(l, 1);

                        for (l in json.ops[j].portsOut[k].links)
                        {
                            if (json.ops[j].portsOut[k].links[l].objIn === oldId) json.ops[j].portsOut[k].links[l].objIn = newID;
                            if (json.ops[j].portsOut[k].links[l].objOut === oldId) json.ops[j].portsOut[k].links[l].objOut = newID;
                        }
                    }
                }
        }
    }

    // set correct subpatch
    const subpatchIds = [];
    const fixedSubPatches = [];

    for (let i = 0; i < json.ops.length; i++)
    {
        // if (CABLES.Op.isSubPatchOpName(json.ops[i].objName))
        if (json.ops[i].storage && json.ops[i].storage.subPatchVer)
        {
            for (const k in json.ops[i].portsIn)
            {
                if (json.ops[i].portsIn[k].name === "patchId")
                {
                    let newId = shortId();

                    if (options.prefixHash) newId = prefixedHash(options.prefixHash + json.ops[i].portsIn[k].value);

                    const oldSubPatchId = json.ops[i].portsIn[k].value;
                    const newSubPatchId = json.ops[i].portsIn[k].value = newId;

                    subpatchIds.push(newSubPatchId);

                    for (let j = 0; j < json.ops.length; j++)
                    {
                        // op has no uiAttribs in export, we don't care about subpatches in export though
                        if (json.ops[j].uiAttribs)
                        {
                            if (json.ops[j].uiAttribs.subPatch === oldSubPatchId)
                            {
                                json.ops[j].uiAttribs.subPatch = newSubPatchId;
                                fixedSubPatches.push(json.ops[j].id);
                            }
                        }
                    }
                }
            }
        }
    }

    for (const kk in json.ops)
    {
        let found = false;
        for (let j = 0; j < fixedSubPatches.length; j++)
        {
            if (json.ops[kk].id === fixedSubPatches[j])
            {
                found = true;
                break;
            }
        }
        // op has no uiAttribs in export, we don't care about subpatches in export though
        if (!found && json.ops[kk].uiAttribs && options.parentSubPatchId != null)
            json.ops[kk].uiAttribs.subPatch = options.parentSubPatchId;
    }

    return json;
};
/**
 * remove an eventlistener
 * @instance
 * @function addEventListener
 * @param {String} name of event
 * @param {function} callback
 */

/**
 * remove an eventlistener
 * @instance
 * @function removeEventListener
 * @param {String} name of event
 * @param {function} callback
 */

/**
 * op added to patch event
 * @event onOpAdd
 *
 * @memberof Patch
 * @type {Object}
 * @property {Op} op new op
 */

/**
 * op deleted from patch
 * @event onOpDelete
 * @memberof Patch
 * @type {Object}
 * @property {Op} op that will be deleted
 */

/**
 * link event - two ports will be linked
 * @event onLink
 * @memberof Patch
 * @type {Object}
 * @property {Port} port1
 * @property {Port} port2
 */

/**
 * unlink event - a link was deleted
 * @event onUnLink
 * @memberof Patch
 * @type {Object}
 */

/**
 * variables has been changed / a variable has been added to the patch
 * @event variablesChanged
 * @memberof Patch
 * @type {Object}
 * @property {Port} port1
 * @property {Port} port2
 */

/**
 * configuration object for loading a patch
 * @typedef {Object} PatchConfig
 * @hideconstructor
 * @property {String} [prefixAssetPath=''] prefix for path to assets
 * @property {String} [assetPath=''] path to assets
 * @property {String} [jsPath=''] path to javascript files
 * @property {String} [glCanvasId='glcanvas'] dom element id of canvas element
 * @property {Function} [onError=null] called when an error occurs
 * @property {Function} [onFinishedLoading=null] called when patch finished loading all assets
 * @property {Function} [onFirstFrameRendered=null] called when patch rendered it's first frame
 * @property {Boolean} [glCanvasResizeToWindow=false] resize canvas automatically to window size
 * @property {Boolean} [doRequestAnimation=true] do requestAnimationFrame set to false if you want to trigger exec() from outside (only do if you know what you are doing)
 * @property {Boolean} [clearCanvasColor=true] clear canvas in transparent color every frame
 * @property {Boolean} [clearCanvasDepth=true] clear depth every frame
 * @property {Boolean} [glValidateShader=true] enable/disable validation of shaders *
 * @property {Boolean} [silent=false]
 * @property {Number} [fpsLimit=0] 0 for maximum possible frames per second
 * @property {String} [glslPrecision='mediump'] default precision for glsl shader
 *
 */

/* harmony default export */ const core_patch = (Patch);

;// CONCATENATED MODULE: ./src/core/embedding.js



const EMBED = {};

/**
 * add patch into html element (will create canvas and set size to fill containerElement)
 * @name CABLES.EMBED#addPatch
 * @param {object|string} _element containerElement dom element or id of element
 * @param {object} options patch options
 * @function
 */
EMBED.addPatch = function (_element, options)
{
    let el = _element;
    let id = generateUUID();
    if (typeof _element == "string")
    {
        id = _element;
        el = document.getElementById(id);

        if (!el)
        {
            console.error(id + " Polyshape Container Element not found!");
            return;
        }
    }

    const canvEl = document.createElement("canvas");
    canvEl.id = "glcanvas_" + id;
    canvEl.width = el.clientWidth;
    canvEl.height = el.clientHeight;

    window.addEventListener(
        "resize",
        function ()
        {
            this.setAttribute("width", el.clientWidth);
            this.height = el.clientHeight;
        }.bind(canvEl),
    );

    el.appendChild(canvEl);

    options = options || {};
    options.glCanvasId = canvEl.id;

    if (!options.onError)
    {
        options.onError = function (err)
        {
            console.error(err);
        };
    }

    CABLES.patch = new core_patch(options);
    return canvEl;
};



;// CONCATENATED MODULE: ./src/core/webaudio.js
/** @namespace WEBAUDIO */



const WEBAUDIO = {};

WEBAUDIO.toneJsInitialized = false;

/*
 * External JSDoc definitions
 */

/**
 * Part of the Web Audio API, the AudioBuffer interface represents a short audio asset residing in memory.
 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer}
 */

/**
 * Part of the Web Audio API, the AudioNode interface is a generic interface for representing an audio processing module.
 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/AudioNode}
 */

/**
 * The AudioContext interface represents an audio-processing graph built from audio modules linked together
 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/AudioContext}
 */

/**
 * Checks if a global audio context has been created and creates
 * it if necessary. This audio context can be used for native Web Audio as well as Tone.js ops.
 * Associates the audio context with Tone.js if it is being used
 * @param {CABLES.Op} op - The operator which needs the Audio Context
 */
WEBAUDIO.createAudioContext = function (op)
{
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    if (window.AudioContext)
    {
        if (!window.audioContext)
        {
            window.audioContext = new AudioContext();
        }
        // check if tone.js lib is being used
        if (window.Tone && !WEBAUDIO.toneJsInitialized)
        {
            // set current audio context in tone.js
            Tone.setContext(window.audioContext);
            WEBAUDIO.toneJsInitialized = true;
        }
    }
    else
    {
        if (op.patch.config.onError)op.logError("NO_WEBAUDIO", "Web Audio is not supported in this browser.");
        return;
    }
    return window.audioContext;
};

/**
 * Returns the audio context.
 * Before `createAudioContext` must have been called at least once.
 * It most cases you should use `createAudioContext`, which just returns the audio context
 * when it has been created already.
 */
WEBAUDIO.getAudioContext = function ()
{
    return window.audioContext;
};

/**
 * Creates an audio in port for the op with name `portName`
 * When disconnected it will disconnect the previous connected audio node
 * from the op's audio node.
 * @param {CABLES.Op} op - The operator to create the audio port in
 * @param {string} portName - The name of the port
 * @param {AudioNode} audioNode - The audionode incoming connections should connect to
 * @param {number} [inputChannelIndex=0] - If the audio node has multiple inputs, this is the index of the input channel to connect to
 * @returns {CABLES.Port|undefined} - The newly created audio in port or `undefined` if there was an error
 */
WEBAUDIO.createAudioInPort = function (op, portName, audioNode, inputChannelIndex)
{
    if (!op || !portName || !audioNode)
    {
        const msg = "ERROR: createAudioInPort needs three parameters, op, portName and audioNode";
        op.log(msg);
        throw new Error(msg);
        // return;
    }
    if (!inputChannelIndex)
    {
        inputChannelIndex = 0;
    }
    op.webAudio = op.webAudio || {};
    op.webAudio.audioInPorts = op.webAudio.audioInPorts || [];
    const port = op.inObject(portName);
    port.webAudio = {};
    port.webAudio.previousAudioInNode = null;
    port.webAudio.audioNode = audioNode;

    op.webAudio.audioInPorts[portName] = port;

    port.onChange = function ()
    {
        const audioInNode = port.get();
        // when port disconnected, disconnect audio nodes
        if (!audioInNode)
        {
            if (port.webAudio.previousAudioInNode)
            {
                try
                {
                    if (port.webAudio.previousAudioInNode.disconnect) port.webAudio.previousAudioInNode.disconnect(port.webAudio.audioNode, 0, inputChannelIndex);
                    op.setUiError("audioCtx", null);
                }
                catch (e)
                {
                    try
                    {
                        port.webAudio.previousAudioInNode.disconnect(port.webAudio.audioNode);
                    }
                    catch (er)
                    {
                        op.log(
                            "Disconnecting audio node with in/out port index, as well as without in/out-port-index did not work ",
                            e,
                        );
                        if (e.printStackTrace)
                        {
                            e.printStackTrace();
                        }
                        throw e;
                    }
                }
            }
        }
        else
        {
            try
            {
                if (audioInNode.connect)
                {
                    audioInNode.connect(port.webAudio.audioNode, 0, inputChannelIndex);
                    op.setUiError("audioCtx", null);
                }
                else op.setUiError("audioCtx", "The passed input is not an audio context. Please make sure you connect an audio context to the input.", 2);
            }
            catch (e)
            {
                op.log("Error: Failed to connect web audio node!", e);
                op.log("port.webAudio.audioNode", port.webAudio.audioNode);
                op.log("audioInNode: ", audioInNode);
                op.log("inputChannelIndex:", inputChannelIndex);
                op.log("audioInNode.connect: ", audioInNode.connect);
                throw e;
            }
        }
        port.webAudio.previousAudioInNode = audioInNode;
    };
    // TODO: Maybe add subtype to audio-node-object?
    return port;
};

/**
 * Sometimes it is necessary to replace a node of a port, if so all
 * connections to this node must be disconnected and connections to the new
 * node must be made.
 * Can be used for both Audio ports as well as AudioParam ports
 * if used with an AudioParam pass e.g. `synth.frequency` as newNode
 * @param {CABLES.Port} port - The port where the audio node needs to be replaced
 * @param oldNode
 * @param newNode
 */
WEBAUDIO.replaceNodeInPort = function (port, oldNode, newNode)
{
    const connectedNode = port.webAudio.previousAudioInNode;
    // check if connected
    if (connectedNode && connectedNode.disconnect)
    {
        try
        {
            connectedNode.disconnect(oldNode);
        }
        catch (e)
        {
            if (e.printStackTrace)
            {
                e.printStackTrace();
            }
            throw new Error("replaceNodeInPort: Could not disconnect old audio node. " + e.name + " " + e.message);
        }
        port.webAudio.audioNode = newNode;
        try
        {
            connectedNode.connect(newNode);
        }
        catch (e)
        {
            if (e.printStackTrace)
            {
                e.printStackTrace();
            }
            throw new Error("replaceNodeInPort: Could not connect to new node. " + e.name + " " + e.message);
        }
    }
};

/**
 * Creates an audio out port which takes care of (dis-)connecting on it’s own
 * @param {CABLES.op} op - The op to create an audio out port for
 * @param {string} portName - The name of the port to be created
 * @param {AudioNode} audioNode - The audio node to link to the port
 * @returns {(CABLES.Port|undefined)} - The newly created audio out port or `undefined` if there was an error
 */
WEBAUDIO.createAudioOutPort = function (op, portName, audioNode)
{
    if (!op || !portName || !audioNode)
    {
        const msg = "ERROR: createAudioOutPort needs three parameters, op, portName and audioNode";
        op.log(msg);
        throw new Error(msg);
    }

    const port = op.outObject(portName);
    // TODO: Maybe add subtype to audio-node-object?
    port.set(audioNode);
    return port;
};

/**
 * Creates an audio param in port for the op with name portName.
 * The port accepts other audio nodes as signals as well as values (numbers)
 * When the port is disconnected it will disconnect the previous connected audio node
 * from the op's audio node and restore the number value set before.
 * @param {CABLES.Op} op - The operator to create an audio param input port for
 * @param {string} portName - The name of the port to create
 * @param audioNode
 * @param options
 * @param defaultValue
 * @returns {(CABLES.Port|undefined)} - The newly created port, which takes care of (dis-)connecting on its own, or `undefined` if there was an error
 */
WEBAUDIO.createAudioParamInPort = function (op, portName, audioNode, options, defaultValue)
{
    if (!op || !portName || !audioNode)
    {
        op.log("ERROR: createAudioParamInPort needs three parameters, op, portName and audioNode");
        if (op && op.name) op.log("opname: ", op.name);
        op.log("portName", portName);
        op.log("audioNode: ", audioNode);
        return;
    }
    op.webAudio = op.webAudio || {};
    op.webAudio.audioInPorts = op.webAudio.audioInPorts || [];
    // var port = op.inObject(portName);
    const port = op.inDynamic(
        portName,
        [CONSTANTS.OP.OP_PORT_TYPE_VALUE, CONSTANTS.OP.OP_PORT_TYPE_OBJECT],
        options,
        defaultValue,
    );
    port.webAudio = {};
    port.webAudio.previousAudioInNode = null;
    port.webAudio.audioNode = audioNode;

    op.webAudio.audioInPorts[portName] = port;

    // port.onLinkChanged = function() {
    //   op.log("onLinkChanged");
    //   if(port.isLinked()) {
    //
    //       if(port.links[0].portOut.type === CABLES.CONSTANTS.OP.OP_PORT_TYPE_) { // value
    //
    //       } else if(port.links[0].portOut.type === CABLES.CONSTANTS.OP.OP_PORT_TYPE_OBJECT) { // object
    //
    //       }
    //   } else { // unlinked
    //
    //   }
    // };

    port.onChange = function ()
    {
        const audioInNode = port.get();
        const node = port.webAudio.audioNode;
        const audioCtx = WEBAUDIO.getAudioContext();

        if (audioInNode != undefined)
        {
            if (typeof audioInNode === "object" && audioInNode.connect)
            {
                try
                {
                    audioInNode.connect(node);
                }
                catch (e)
                {
                    op.log("Could not connect audio node: ", e);
                    if (e.printStackTrace)
                    {
                        e.printStackTrace();
                    }
                    throw e;
                }
                port.webAudio.previousAudioInNode = audioInNode;
            }
            else
            {
                // tone.js audio param
                if (node._param && node._param.minValue && node._param.maxValue)
                {
                    if (audioInNode >= node._param.minValue && audioInNode <= node._param.maxValue)
                    {
                        try
                        {
                            if (node.setValueAtTime)
                            {
                                node.setValueAtTime(audioInNode, audioCtx.currentTime);
                            }
                            else
                            {
                                node.value = audioInNode;
                            }
                        }
                        catch (e)
                        {
                            op.log("Possible AudioParam problem with tone.js op: ", e);
                            if (e.printStackTrace)
                            {
                                e.printStackTrace();
                            }
                            throw e;
                        }
                    }
                    else
                    {
                        op.log("Warning: The value for an audio parameter is out of range!");
                    }
                } // native Web Audio param
                else if (node.minValue && node.maxValue)
                {
                    if (audioInNode >= node.minValue && audioInNode <= node.maxValue)
                    {
                        try
                        {
                            if (node.setValueAtTime)
                            {
                                node.setValueAtTime(audioInNode, audioCtx.currentTime);
                            }
                            else
                            {
                                node.value = audioInNode;
                            }
                        }
                        catch (e)
                        {
                            op.log(
                                "AudioParam has minValue / maxValue defined, and value is in range, but setting the value failed! ",
                                e,
                            );
                            if (e.printStackTrace)
                            {
                                e.printStackTrace();
                            }
                            throw e;
                        }
                    }
                    else
                    {
                        op.log("Warning: The value for an audio parameter is out of range!");
                    }
                } // no min-max values, try anyway
                else
                {
                    try
                    {
                        if (node.setValueAtTime)
                        {
                            node.setValueAtTime(audioInNode, audioCtx.currentTime);
                        }
                        else
                        {
                            node.value = audioInNode;
                        }
                    }
                    catch (e)
                    {
                        op.log("Possible AudioParam problem (without minValue / maxValue): ", e);
                        if (e.printStackTrace)
                        {
                            e.printStackTrace();
                        }
                        throw e;
                    }
                }

                if (port.webAudio.previousAudioInNode && port.webAudio.previousAudioInNode.disconnect)
                {
                    try
                    {
                        port.webAudio.previousAudioInNode.disconnect(node);
                    }
                    catch (e)
                    {
                        op.log("Could not disconnect previous audio node: ", e);
                        throw e;
                    }
                    port.webAudio.previousAudioInNode = undefined;
                }
            }
        }
        else
        {
            // disconnected
            if (port.webAudio.previousAudioInNode)
            {
            }
        }
    };
    return port;
};


/**
 * Loads an audio file and updates the loading indicators when cables is run in the editor.
 * @param {CABLES.Patch} patch - The cables patch, when called from inside an op this is `op.patch`
 * @param {string} url - The url of the audio file to load
 * @param {function} onFinished - The callback to be called when the loading is finished, passes the AudioBuffer
 * @param {function} onError - The callback when there was an error loading the file, the rror message is passed
 * @param loadingTask
 * @see {@link https://developer.mozilla.org/de/docs/Web/API/AudioContext/decodeAudioData}
 */
WEBAUDIO.loadAudioFile = function (patch, url, onFinished, onError, loadingTask)
{
    const audioContext = WEBAUDIO.createAudioContext();

    if (!audioContext) onError(new Error("No Audiocontext"));

    let loadingId = null;
    if (loadingTask || loadingTask === undefined)
    {
        loadingId = patch.loading.start("audio", url);
        if (patch.isEditorMode()) gui.jobs().start({ "id": "loadaudio" + loadingId, "title": " loading audio (" + url + ")" });
    }
    const request = new XMLHttpRequest();

    if (!url) return;

    request.open("GET", url, true);
    request.responseType = "arraybuffer";

    request.onload = function ()
    {
        patch.loading.finished(loadingId);
        if (patch.isEditorMode()) gui.jobs().finish("loadaudio" + loadingId);

        audioContext.decodeAudioData(request.response, onFinished, onError).catch((e) =>
        {
            onError(e);
        });
    };
    request.send();
};

/**
 * Checks if the passed time is a valid time to be used in any of the Tone.js ops.
 * @param {(string|number)} t - The time to check
 * @returns {boolean} - True if time is valid, false if not
 */
WEBAUDIO.isValidToneTime = function (t)
{
    try
    {
        const time = new Tone.Time(t);
    }
    catch (e)
    {
        return false;
    }
    return true;
};

/**
 * Checks if the passed note is a valid note to be used with Tone.js
 * @param {string} note - The note to be checked, e.g. `"C4"`
 * @returns {boolean} - True if the note is a valid note, false otherwise
 */
WEBAUDIO.isValidToneNote = function (note)
{
    try
    {
        Tone.Frequency(note);
    }
    catch (e)
    {
        return false;
    }
    return true;
};



;// CONCATENATED MODULE: ./src/core/sessionvar.js
// todo: old... remove this from ops...

/**
 * todo: old... remove this from ops...
 *
 * @class
 */
const Variable = function ()
{
    let value = null;
    const changedCallbacks = [];

    this.onChanged = function (f)
    {
        changedCallbacks.push(f);
    };

    this.getValue = function ()
    {
        return value;
    };

    this.setValue = function (v)
    {
        value = v;
        this.emitChanged();
    };

    this.emitChanged = function ()
    {
        for (let i = 0; i < changedCallbacks.length; i++)
        {
            changedCallbacks[i]();
        }
    };
};



;// CONCATENATED MODULE: ./src/core/cgp/cgp_uniform.js



class cgp_uniform_Uniform extends cg_uniform
{
    constructor(__shader, __type, __name, _value, _port2, _port3, _port4, _structUniformName, _structName, _propertyName)
    {
        super(__shader, __type, __name, _value, _port2, _port3, _port4, _structUniformName, _structName, _propertyName);
        this._cgp = __shader._cgp;

        if (!_value)
        {
            // if (this.getType() == "m4") this._value = mat4.create();
            if (this.getType() == "t") this._value = this._cgp.getEmptyTexture();
            // else if (this.getType() == "2f") this._value = [0, 0];
            // else if (this.getType() == "4f") this._value = [0, 1, 0, 1];
            // else if (this.getType() == "3f") this._value = [0, 1, 0];
        }

        this.gpuBuffer = null;
    }


    updateValueF() { }

    updateValueArrayF() {}

    setValueArrayF(v)
    {
        this.needsUpdate = true;
        this._value = v;
    }

    setValueF(v)
    {
        this.needsUpdate = true;
        this._value = v;
    }

    updateValue2F() { }

    setValue2F(v)
    {
        this.needsUpdate = true;
        this._value = v;
    }

    updateValue3F() { }

    setValue3F(v)
    {
        this.needsUpdate = true;
        this._value = v;
    }

    updateValue4F() { }

    setValue4F(v)
    {
        if (v[0] == undefined)
        {
            this._log.stack("uniform value undefined");
            console.error("uniform value undefined");
        }
        this.needsUpdate = true;
        this._value = v;
    }

    setValueT(v)
    {
        if (this._value != v)
            this._shader.needsPipelineUpdate = "texture changed"; // todo really needed ? change binding instead?

        this.needsUpdate = true;
        this._value = v;
    }

    updateValueM4(v) {}

    setValueM4(v)
    {
        this.needsUpdate = true;
        this._value = v;
    }

    setValueAny(v)
    {
        this.needsUpdate = true;
        this._value = v;
    }

    updateValueAny() {}

    updateValueT() {}


    setGpuBuffer(b)
    {
        this.gpuBuffer = b;
    }

    copyToBuffer(buff, pos = 0)
    {
        if (this._type == "f")
        {
            buff[pos] = this._value;
        }
        else if (this._type == "t")
        {
        }
        else if (this._type == "4f")
        {
            buff[pos] = this._value[0];
            buff[pos + 1] = this._value[1];
            buff[pos + 2] = this._value[2];
            buff[pos + 3] = this._value[3];
        }
        else if (this._type == "f[]")
        {
            for (let i = 0; i < this._value.length; i++)
                buff[pos + i] = this._value[i];
        }
        else if (this._type == "m4")
        {
            for (let i = 0; i < 16; i++)
                buff[pos + i] = this._value[i];
        }
        else
        {
            this._log.warn("uniform copy to buffer unknown", this._type);
        }
    }

    getWgslTypeStr()
    {
        if (this._type == "m4") return "mat4x4f";
        if (this._type == "4f") return "vec4f";
        if (this._type == "3f") return "vec3f";
        if (this._type == "2f") return "vec2f";
        if (this._type == "f") return "float";
        if (this._type == "f[]") return "array<vec4f>";
        if (this._type == "i") return "int";
        if (this._type == "sampler") return "sampler";
        if (this._type == "t") return "texture_2d<f32>";
        this._log.warn("unknown type getWgslTypeStr", this._type);
        return "???";
    }

    getSizeBytes()
    {
        const bytesPerFloat = 4;
        const bytesPerInt = 4;
        if (this._type == "t") return 4;
        if (this._type == "sampler") return 4;
        if (this._type == "f") return 1 * bytesPerFloat;
        if (this._type == "2f") return 2 * bytesPerFloat;
        if (this._type == "3f") return 3 * bytesPerFloat;
        if (this._type == "4f") return 4 * bytesPerFloat;
        if (this._type == "f[]") return this._value.length * bytesPerFloat;

        if (this._type == "m4") return 4 * 4 * bytesPerFloat;

        if (this._type == "i") return 1 * bytesPerInt;
        if (this._type == "2i") return 2 * bytesPerInt;

        this._log.warn("unknown type getSizeBytes", this._type);
        return 4;
    }

    copy(newShader)
    {
        const uni = new cgp_uniform_Uniform(newShader, this._type, this._name, this._value, this._port2, this._port3, this._port4, this._structUniformName, this._structName, this._propertyName);
        uni.shaderType = this.shaderType;

        console.log(this._name, this._value, uni._value);


        return uni;
    }
}

;// CONCATENATED MODULE: ./src/core/cg/preproc.js
function preproc(str, vars)
{
    const lines = str.split("\n");
    const outLines = [];
    let stack = [];

    for (let i = 0; i < lines.length; i++)
    {
        let line = lines[i].trim();
        let parts = line.split(" ");

        if (line.startsWith("#ifdef "))
        {
            const s = vars[parts[1]];
            stack.push({ "state": s });
            continue;
        }
        if (line.startsWith("#ifndef "))
        {
            const s = vars[parts[1]];
            stack.push({ "state": !s });
            continue;
        }
        if (line.startsWith("#endif"))
        {
            stack.pop();
            continue;
        }
        const state = stack[stack.length - 1];

        if (line.startsWith("#else"))
        {
            state.state = !state.state;
            continue;
        }

        if (!state || state.state)
        {
            outLines.push(lines[i]);
        }
    }

    return outLines.join("\n");
}

;// CONCATENATED MODULE: ./src/core/cgp/cgp_gpubuffer.js


class GPUBuffer extends EventTarget
{
    constructor(cgp, name, data = null, options = {})
    {
        super();

        this.id = CABLES.shortId();

        this._name = name;
        this.floatArr = null;
        this._gpuBuffer = null;

        this.setData([0, 0, 0, 0]);
        this.needsUpdate = true;
        this._length = 0;

        if (options.buffCfg)
        {
            this._buffCfg = options.buffCfg;
        }

        if (data)
            this.setData(data);

        if (options.length) this.setLength(options.length);

        this.updateGpuBuffer(cgp);
    }

    setData(d)
    {
        // console.log((new Error()).stack);

        this.floatArr = new Float32Array(d);
        this.setLength(this.floatArr.length);

        // console.log(this.name, this.floatArr);
        this.needsUpdate = true;
    }

    setLength(s)
    {
        this._length = s;
        if (!this.floatArr || s != this.floatArr.length)
        {
            this.floatArr = new Float32Array(this._length);
            this.needsUpdate = true;
        }
    }

    updateGpuBuffer(cgp)
    {
        if (cgp) this._cgp = cgp;
        if (!this._cgp || !this._cgp.device)
        {
            console.log("no cgp...", this._name, this._cgp);
            return;
        }

        this._cgp.pushErrorScope("updateGpuBuffer");
        if (!this._gpuBuffer)
        {
            this._buffCfg = this._buffCfg || {};
            this._buffCfg.label = "gpuBuffer-" + this._name;
            if (!this._buffCfg.hasOwnProperty("size") && this.floatArr) this._buffCfg.size = this.floatArr.length * 4;
            this._buffCfg.usage = this._buffCfg.usage || (GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC);

            this._gpuBuffer = this._cgp.device.createBuffer(this._buffCfg);
        }

        // if (!isNaN(this.floatArr[0]))console.log("shit", this._name);

        if (this.floatArr)
            this._cgp.device.queue.writeBuffer(
                this._gpuBuffer,
                0,
                this.floatArr.buffer,
                this.floatArr.byteOffset,
                this.floatArr.byteLength
            );

        // this._gpuBuffer.unmap();

        this._cgp.popErrorScope();

        this.needsUpdate = false;
    }

    get name()
    {
        return this._name;
    }

    get gpuBuffer()
    {
        if (!this._gpuBuffer || this.needsUpdate) this.updateGpuBuffer();

        return this._gpuBuffer;
    }

    get length()
    {
        return this._length;
    }

    getSizeBytes()
    {
        return this.floatArr.length * 4;
    }

    dispose()
    {
        // setTimeout(() =>
        // {
        //     if (this._gpuBuffer) this._gpuBuffer.destroy();
        // }, 100);
    }
}

;// CONCATENATED MODULE: ./src/core/cgp/cgp_binding.js



class Binding
{
    /**
     * Description
     * @param {any} cgp
     * @param {any} idx
     * @param {string} name
     * @param {any} options={}
     */
    constructor(cgp, name, options = {})
    {
        if (typeof options != "object") this._log.error("binding options is not an object");
        this._index = -1;

        this._name = name;
        this._cgp = cgp;
        this._log = new Logger("cgp_binding");
        this.uniforms = [];
        this.cGpuBuffers = [];
        this._options = options;
        this.shader = null;
        this.bindingInstances = [];
        this.stageStr = options.stage;
        this.bindingType = options.bindingType || "uniform"; // "uniform", "storage", "read-only-storage",

        if (this.stageStr == "frag") this.stage = GPUShaderStage.FRAGMENT;
        else this.stage = GPUShaderStage.VERTEX;
        if (options.hasOwnProperty("index")) this._index = options.index;

        if (options.shader) this.shader = options.shader;

        this._buffer = null;
        this.isValid = true;
        this.changed = 0;

        if (this.shader)
        {
            if (this.stageStr == "frag") this.shader.bindingsFrag.push(this);
            if (this.stageStr == "vert") this.shader.bindingsVert.push(this);
            if (this._index == -1) this._index = this.shader.getNewBindingIndex();
        }

        if (this._index == -1) this._log.warn("binding could not get an index", this._name);

        this._cgp.on("deviceChange", () =>
        {
            // this.reInit();
        });
    }

    isStruct()
    {
        if (this.uniforms.length == 0) return false;

        if (this.uniforms.length == 1)
        {
            if (this.uniforms[0].type == "t" || this.uniforms[0].type == "sampler") return false;
            if (this.bindingType != "uniform") return false;
        }

        return true;
    }

    copy(newShader)
    {
        console.log("copy binding...");
        const options = {};

        for (const i in this._options)
            options[i] = this._options[i];

        options.shader = newShader;

        let binding = new Binding(this._cgp, this._name, options);

        for (let i = 0; i < this.uniforms.length; i++)
        {
            binding.addUniform(newShader.getUniform(this.uniforms[i].name)); // .copy(newShader)
        }




        return binding;
    }

    addUniform(uni)
    {
        this.uniforms.push(uni);
    }

    getSizeBytes()
    {
        let size = 0;
        for (let i = 0; i < this.uniforms.length; i++)
        {
            // console.log("UNIFORM!!!", i, this.uniforms[i], this.uniforms[i].getSizeBytes());
            // console.log("getSizeBytes", this.uniforms[i], this.uniforms[i].getSizeBytes);
            size += this.uniforms[i].getSizeBytes();
        }
        // if (this.uniforms.length == 0)console.log("NO UNIFORMS!!!");
        return size;
    }

    getShaderHeaderCode()
    {
        let str = "";

        let typeStr = "strct_" + this._name;
        let name = this._name;

        if (this.uniforms.length === 0) return "// no uniforms in bindinggroup...?\n";


        str += "// " + this.uniforms.length + " uniforms\n";

        if (this.isStruct())
        {
            str += "struct " + typeStr + "\n";
            str += "{\n";
            for (let i = 0; i < this.uniforms.length; i++)
            {
                str += "    " + this.uniforms[i].name + ": " + this.uniforms[i].getWgslTypeStr();
                if (i != this.uniforms.length - 1)str += ",";
                str += "\n";
            }
            str += "};\n";
        }
        else
        {
            typeStr = this.uniforms[0].getWgslTypeStr();
            name = this.uniforms[0].name;
        }

        str += "@group(0) ";
        str += "@binding(" + this._index + ") ";

        if (this.isStruct())
        {
            str += "var<" + this.bindingType + "> ";
        }
        else if (this.bindingType == "read-only-storage")str += "var<storage,read> ";
        else str += "var ";

        str += name + ": " + typeStr + ";\n";

        return str;
    }


    getBindingGroupLayoutEntry()
    {
        let label = "layout " + this._name + " [";
        for (let i = 0; i < this.uniforms.length; i++) label += this.uniforms[i].getName() + ",";
        label += "]";

        const o = {
            "label": label,
            "binding": this._index,
            "visibility": this.stage,
            "size": this.getSizeBytes()
        };

        if (this.uniforms.length == 1 && this.uniforms[0].getType() == "t")
        {
            o.texture = {};
        }
        else if (this.uniforms.length == 1 && this.uniforms[0].getType() == "sampler")
        {
            o.sampler = {};
        }
        else
        {
            o.buffer = {};
            o.buffer.type = this.bindingType;
        }

        return o;
    }

    getBindingGroupEntry(gpuDevice, inst)
    {
        this.isValid = false;

        const o = {
            "label": this._name + " binding",
            "binding": this._index,
            "size": this.getSizeBytes(),
            "visibility": this.stage,
        };

        if (this.uniforms.length == 0)
        {
            console.log("binding uniforms length 0");
            return;
        }

        if (this.uniforms.length == 1 && this.uniforms[0].getType() == "t")
        {
            if (this.uniforms[0].getValue() && this.uniforms[0].getValue().gpuTexture) o.resource = this.uniforms[0].getValue().gpuTexture.createView();
            else o.resource = this._cgp.getEmptyTexture().createView();// CABLES.emptyCglTexture.createView();
        }
        else if (this.uniforms.length == 1 && this.uniforms[0].getType() == "sampler")
        {
            let smplDesc = {
                "addressModeU": "mirror-repeat",
                "addressModeV": "mirror-repeat",
                "magFilter": "linear",
                "minFilter": "linear",
                "mipmapFilter": "linear",
            };

            if (this.uniforms[0].getValue()) smplDesc = this.uniforms[0].getValue().getSampler();

            const sampler = this.uniforms[0]._cgp.device.createSampler(smplDesc);
            o.resource = sampler;
        }
        else
        {
            this._createCgpuBuffer(inst);

            o.resource = {
                "buffer": this.cGpuBuffers[inst].gpuBuffer,
                "minBindingSize": this.getSizeBytes(),
                "hasDynamicOffset": 0
            };
        }

        this.isValid = true;
        this.bindingInstances[inst] = o;

        return o;
    }

    _createCgpuBuffer(inst)
    {
        let buffCfg = {
            "label": this._name,
            "size": this.getSizeBytes(),
            "usage": GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM,
        };

        if (this.bindingType == "read-only-storage" || this.bindingType == "storage") buffCfg.usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;

        if (this.cGpuBuffers[inst]) this.cGpuBuffers[inst].dispose();
        this.cGpuBuffers[inst] = new GPUBuffer(this._cgp, this._name + " buff", null, { "buffCfg": buffCfg });

        if (this.uniforms.length > 0 && this.uniforms[0].gpuBuffer) this.cGpuBuffers[inst] = this.uniforms[0].gpuBuffer;
    }



    update(cgp, inst)
    {
        let b = this.bindingInstances[inst];
        if (!b) b = this.getBindingGroupEntry(cgp.device, inst);

        if (this.uniforms.length == 1 && this.uniforms[0].gpuBuffer)
        {
            if (this.uniforms[0].gpuBuffer != this.cGpuBuffers[inst])
            {
                console.log("changed?!");
                this.shader._needsRecompile = true; // TODO this should actually just rebuild the bindinggroup i guess ?
            }

            if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.push("extern uni bind", [this.uniforms[0].getName(), this.cGpuBuffers[inst].floatArr]);
            if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.pop();
        }
        else
        if (this.uniforms.length == 1 && this.uniforms[0].getType() == "t")
        {
            if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.push("uni texture");
            if (this.uniforms[0].getValue())
                if (this.uniforms[0].getValue().gpuTexture)
                {
                    this.bindingInstances[inst] = this.getBindingGroupEntry(this.uniforms[0]._cgp.device, inst);
                }
                else
                {
                    console.log("uni t has no gputexture");
                    b.resource = this._cgp.getErrorTexture().createView();
                }

            if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.pop();
        }
        else if (this.uniforms.length == 1 && this.uniforms[0].getType() == "sampler")
        {
            if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.push("uni sampler");
            b.resource = this.uniforms[0].getValue();
            if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.pop();
        }
        else
        {
            let info = ["stage " + this.stageStr + " / inst " + inst];

            // console.log("B",this.);
            // update uniform values to buffer
            const s = this.getSizeBytes() / 4;

            // if (!this.cGpuBuffers[inst])
            // this._createCgpuBuffer(inst);
            // this.cGpuBuffers[inst] = new GPUBuffer(this._cgp, "buff", null, { "buffCfg": buffCfg });

            this.cGpuBuffers[inst].setLength(s);

            let off = 0;
            for (let i = 0; i < this.uniforms.length; i++)
            {
                info.push(this.uniforms[i].getName() + " " + this.uniforms[i].getValue());
                this.uniforms[i].copyToBuffer(this.cGpuBuffers[inst].floatArr, off); // todo: check if uniform changed?

                // if (isNaN(this.cGpuBuffers[inst].floatArr[0]))
                // {
                // console.log("shitttttttt", this.cGpuBuffers[inst].floatArr[0], this.uniforms[i].getName(), this.cGpuBuffers[inst].name, this.uniforms[i]);
                // }

                off += this.uniforms[i].getSizeBytes() / 4;
            }
            if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.push("uni buff", info);

            // console.log("upodate", inst);

            this.cGpuBuffers[inst].updateGpuBuffer();
            // todo: only if changed...
            // cgp.device.queue.writeBuffer(
            //     b.resource.buffer,
            //     0,
            //     this._buffer.buffer,
            //     this._buffer.byteOffset,
            //     this._buffer.byteLength
            // );

            if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.pop();
        }
    }
}

;// CONCATENATED MODULE: ./src/core/cgp/cgp_shader.js






class cgp_shader_Shader extends CgShader
{
    constructor(_cgp, _name, options = {})
    {
        super();
        if (!_cgp) throw new Error("shader constructed without cgp " + _name);
        this._log = new Logger("cgp_shader");
        this._cgp = _cgp;
        this._name = _name;
        this._uniforms = [];
        this.compute = options.compute || false;

        if (!_name) this._log.stack("no shader name given");
        this._name = _name || "unknown";
        this._compileReason = "";
        this.gpuShaderModule = null;
        this._needsRecompile = true;
        this.bindingCounter = 0;
        this.bindCountlastFrame = -1;
        this._bindingIndexCount = 0;

        this.defaultBindingVert = new Binding(_cgp, "vsUniforms", { "stage": "vert", "bindingType": "uniform", "index": this._bindingIndexCount++ });
        this.defaultBindingFrag = new Binding(_cgp, "fsUniforms", { "stage": "frag", "bindingType": "uniform", "index": this._bindingIndexCount++ });
        this.defaultBindingComp = new Binding(_cgp, "computeUniforms", { "bindingType": "uniform", "index": this._bindingIndexCount++ });
        this.bindingsFrag = [this.defaultBindingFrag];
        this.bindingsVert = [this.defaultBindingVert];
        this.bindingsComp = [this.defaultBindingComp];

        if (!this.compute)
        {
            this.uniModelMatrix = this.addUniformVert("m4", "modelMatrix");
            this.uniViewMatrix = this.addUniformVert("m4", "viewMatrix");
            this.uniProjMatrix = this.addUniformVert("m4", "projMatrix");
            this.uniNormalMatrix = this.addUniformVert("m4", "normalMatrix");
            this.uniModelViewMatrix = this.addUniformVert("m4", "modelViewMatrix");
            this._tempNormalMatrix = mat4.create();
            this._tempModelViewMatrix = mat4.create();
        }


        this._src = "";

        this._cgp.on("deviceChange", () =>
        {
            this.gpuShaderModule = null;
            this._needsRecompile = "device changed";
        });
    }

    incBindingCounter()
    {
        if (this.bindCountlastFrame != this._cgp.frame) this.bindingCounter = 0;
        else this.bindingCounter++;
        this.bindCountlastFrame = this._cgp.frame;
    }

    reInit()
    {

    }

    get isValid()
    {
        return this._isValid;
    }

    get uniforms()
    {
        return this._uniforms;
    }

    getName()
    {
        return this._name;
    }

    setWhyCompile(why)
    {
        this._compileReason = why;
    }

    getNewBindingIndex()
    {
        return ++this._bindingIndexCount;
    }


    setSource(src)
    {
        this._src = src;
        this.setWhyCompile("Source changed");
        this._needsRecompile = true;
    }

    _replaceMods(vs)
    {
        let srcHeadVert = "";
        for (let i = 0; i < this._moduleNames.length; i++)
        {
            let srcVert = "";

            for (let j = 0; j < this._modules.length; j++)
            {
                const mod = this._modules[j];
                if (mod.name == this._moduleNames[i])
                {
                    srcHeadVert += "\n//---- MOD: group:" + mod.group + ": idx:" + j + " - prfx:" + mod.prefix + " - " + mod.title + " ------\n";

                    srcVert += "\n\n//---- MOD: " + mod.title + " / " + mod.priority + " ------\n";

                    if (mod.attributes)
                        for (let k = 0; k < mod.attributes.length; k++)
                        {
                            const r = this._getAttrSrc(mod.attributes[k], false);
                            if (r.srcHeadVert)srcHeadVert += r.srcHeadVert;
                            if (r.srcVert)srcVert += r.srcVert;
                        }

                    srcHeadVert += mod.srcHead || "";
                    srcVert += mod.srcBody || "";

                    srcHeadVert += "\n//---- end mod ------\n";

                    srcVert += "\n//---- end mod ------\n";

                    srcVert = srcVert.replace(/{{mod}}/g, mod.prefix);
                    srcHeadVert = srcHeadVert.replace(/{{mod}}/g, mod.prefix);

                    srcVert = srcVert.replace(/MOD_/g, mod.prefix);
                    srcHeadVert = srcHeadVert.replace(/MOD_/g, mod.prefix);
                }
            }

            vs = vs.replace("{{" + this._moduleNames[i] + "}}", srcVert);
        }

        vs = vs.replace("{{MODULES_HEAD}}", srcHeadVert);
        return vs;
    }

    getProcessedSource()
    {
        const defs = {};
        for (let i = 0; i < this._defines.length; i++)
            defs[this._defines[i][0]] = this._defines[i][1] || true;


        let src = preproc(this._src, defs);

        let bindingsHeadVert = "";
        for (let i = 0; i < this.bindingsFrag.length; i++)
            bindingsHeadVert += this.bindingsFrag[i].getShaderHeaderCode();

        let bindingsHeadFrag = "";
        for (let i = 0; i < this.bindingsVert.length; i++)
            bindingsHeadFrag += this.bindingsVert[i].getShaderHeaderCode();



        src = bindingsHeadFrag + "\n\n////////////////\n\n" + bindingsHeadVert + "\n\n////////////////\n\n" + src;
        src = this._replaceMods(src);

        return src;
        // console.log("----------------\n", src, "\n----------------------------");
    }

    compile()
    {
        console.log("compile", this._compileReason);
        this._isValid = true;
        this._cgp.pushErrorScope("cgp_shader " + this._name);
        // console.log(this.getProcessedSource());
        this.gpuShaderModule = this._cgp.device.createShaderModule({ "code": this.getProcessedSource(), "label": this._name });
        this._cgp.popErrorScope(this.error.bind(this));
        this._needsRecompile = false;

        this.emitEvent("compiled");
    }

    error(e)
    {
        this._isValid = false;
    }

    bind()
    {
        if (!this.compute)
        {
            this.uniModelMatrix.setValue(this._cgp.mMatrix);
            this.uniViewMatrix.setValue(this._cgp.vMatrix);
            this.uniProjMatrix.setValue(this._cgp.pMatrix);

            // mat4.invert(this._tempNormalMatrix, this._cgp.mMatrix);
            // mat4.transpose(this._tempNormalMatrix, this._tempNormalMatrix);
            mat4.mul(this._tempModelViewMatrix, this._cgp.vMatrix, this._cgp.mMatrix);



            // mat4.set(this._tempNormalMatrix, this._tempModelViewMatrix);
            mat4.invert(this._tempNormalMatrix, this._tempModelViewMatrix);
            mat4.transpose(this._tempNormalMatrix, this._tempNormalMatrix);


            // cpu billboarding?
            // this._tempModelViewMatrix[0 * 4 + 0] = 1.0;
            // this._tempModelViewMatrix[0 * 4 + 1] = 0.0;
            // this._tempModelViewMatrix[0 * 4 + 2] = 0.0;

            // // #ifndef BILLBOARDING_CYLINDRIC
            // this._tempModelViewMatrix[1 * 4 + 0] = 0.0;
            // this._tempModelViewMatrix[1 * 4 + 1] = 1.0;
            // this._tempModelViewMatrix[1 * 4 + 2] = 0.0;
            // // #endif

            // this._tempModelViewMatrix[2 * 4 + 0] = 0.0;
            // this._tempModelViewMatrix[2 * 4 + 1] = 0.0;
            // this._tempModelViewMatrix[2 * 4 + 2] = 1.0;

            this.uniModelViewMatrix.setValue(this._tempModelViewMatrix);
            this.uniNormalMatrix.setValue(this._tempNormalMatrix);
        }

        if (this._needsRecompile) this.compile();
    }

    /**
     * add a uniform to the fragment shader
     * @param {String} type ['f','t', etc]
     * @param {String} name
     * @param {any} valueOrPort value or port
     * @param p2
     * @param p3
     * @param p4
     * @memberof Shader
     * @instance
     * @function addUniformFrag
     * @returns {Uniform}
     */
    addUniformFrag(type, name, valueOrPort, p2, p3, p4)
    {
        const uni = new cgp_uniform_Uniform(this, type, name, valueOrPort, p2, p3, p4);
        uni.shaderType = "frag";

        this.defaultBindingFrag.addUniform(uni);
        this.needsPipelineUpdate = "add frag uniform";

        return uni;
    }

    /**
     * add a uniform to the vertex shader
     * @param {String} type ['f','t', etc]
     * @param {String} name
     * @param {any} valueOrPort value or port
     * @param p2
     * @param p3
     * @param p4
     * @memberof Shader
     * @instance
     * @function addUniformVert
     * @returns {Uniform}
     */
    addUniformVert(type, name, valueOrPort, p2, p3, p4)
    {
        const uni = new cgp_uniform_Uniform(this, type, name, valueOrPort, p2, p3, p4);
        uni.shaderType = "vert";

        this.defaultBindingVert.addUniform(uni);
        this.needsPipelineUpdate = "add ver uniform";

        return uni;
    }

    /**
     * add a uniform to all shader programs
     * @param {String} type ['f','t', etc]
     * @param {String} name
     * @param {any} valueOrPort value or port
     * @param p2
     * @param p3
     * @param p4
     * @memberof Shader
     * @instance
     * @function addUniform
     * @returns {Uniform}
     */
    addUniform(type, name, valueOrPort, p2, p3, p4)
    {
        const uni = new cgp_uniform_Uniform(this, type, name, valueOrPort, p2, p3, p4);
        uni.shaderType = "both";
        return uni;
    }

    _addUniform(uni)
    {
        this._uniforms.push(uni);
        this.setWhyCompile("add uniform " + name);
        this._needsRecompile = true;
    }

    getUniform(name)
    {
        for (let i = 0; i < this._uniforms.length; i++)
        {
            if (this._uniforms[i].getName() == name) return this._uniforms[i];
        }
    }

    /**
     * copy current shader
     * @function copy
     * @memberof Shader
     * @instance
     * @returns newShader
     */
    copy()
    {
        const shader = new cgp_shader_Shader(this._cgp, this._name + " copy");
        shader.setSource(this._src);

        shader._modules = JSON.parse(JSON.stringify(this._modules));
        shader._defines = JSON.parse(JSON.stringify(this._defines));

        shader._modGroupCount = this._modGroupCount;
        shader._moduleNames = this._moduleNames;

        // shader.glPrimitive = this.glPrimitive;
        // shader.offScreenPass = this.offScreenPass;
        // shader._extensions = this._extensions;
        // shader.wireframe = this.wireframe;
        // shader._attributes = this._attributes;

        for (let i = 0; i < this._uniforms.length; i++) this._uniforms[i].copy(shader);

        shader.bindingsFrag = [];
        for (let i = 0; i < this.bindingsFrag.length; i++) this.bindingsFrag[i].copy(shader);
        shader.defaultBindingFrag = this.bindingsFrag[0];

        shader.bindingsVert = [];
        for (let i = 0; i < this.bindingsVert.length; i++) this.bindingsVert[i].copy(shader);
        shader.defaultBindingVert = this.bindingsVert[0];

        shader.bindingsComp = [];
        for (let i = 0; i < this.bindingsComp.length; i++) this.bindingsComp[i].copy(shader);
        shader.defaultBindingComp = this.bindingsComp[0];

        console.log("copyyyyyyyyyy", shader.bindingsVert, this.bindingsVert);

        this.setWhyCompile("copy");
        shader._needsRecompile = true;
        return shader;
    }


    /**
     * copy all uniform values from another shader
     * @function copyUniforms
     * @memberof Shader
     * @instance
     * @param origShader uniform values will be copied from this shader
     */
    copyUniformValues(origShader)
    {
        for (let i = 0; i < origShader._uniforms.length; i++)
        {
            if (!this._uniforms[i])
            {
                this._log.log("unknown uniform?!");
                continue;
            }
            this.getUniform(origShader._uniforms[i].getName()).set(origShader._uniforms[i].getValue());
        }

        // this.popTextures();
        // for (let i = 0; i < origShader._textureStackUni.length; i++)
        // {
        //     this._textureStackUni[i] = origShader._textureStackUni[i];
        //     this._textureStackTex[i] = origShader._textureStackTex[i];
        //     this._textureStackType[i] = origShader._textureStackType[i];
        //     this._textureStackTexCgl[i] = origShader._textureStackTexCgl[i];
        // }
    }
}

;// CONCATENATED MODULE: ./src/core/cgp/cgl_shader_default.wgsl
/* harmony default export */ const cgl_shader_default = ("\nstruct MyVSInput\n{\n    @location(0) position: vec3<f32>,\n    @location(1) normal: vec3<f32>,\n    @location(2) texcoord: vec2<f32>,\n};\n\nstruct MyVSOutput\n{\n    @builtin(position) position: vec4<f32>,\n    @location(0) normal: vec3<f32>,\n    @location(1) texcoord: vec2<f32>,\n};\n\n@vertex\nfn myVSMain(v: MyVSInput) -> MyVSOutput\n{\n    var vsOut: MyVSOutput;\n    var pos =vec4<f32>(v.position, 1.0);\n\n    var mvMatrix=vsUniforms.viewMatrix * vsUniforms.modelMatrix;\n    vsOut.position = vsUniforms.projMatrix * mvMatrix * pos;\n\n    vsOut.normal = v.normal;\n    vsOut.texcoord = v.texcoord;\n    return vsOut;\n}\n\n@fragment\nfn myFSMain(v: MyVSOutput) -> @location(0) vec4<f32>\n{\n    return fsUniforms.color+vec4<f32>(.5,.5,.5,1.0);\n}\n\n");
;// CONCATENATED MODULE: ./src/core/cgp/cgp_texture.js



class cgp_texture_Texture extends CgTexture
{
    constructor(_cgp, options = {})
    {
        super(options);
        if (!_cgp) throw new Error("no cgp");
        this._log = new Logger("cgp_texture");
        this._cgp = _cgp;
        // this.id = CABLES.uuid();
        this.gpuTexture = null;
        this.gpuTextureDescriptor = null;

        options = options || {};

        this.name = options.name || "unknown";

        this.samplerDesc = {
            "addressModeU": options.wrap || options.addressModeU || "clamp-to-edge",
            "addressModeV": options.wrap || options.addressModeV || "clamp-to-edge",
            "magFilter": options.magFilter || options.filter || "linear",
            "minFilter": options.minFilter || options.filter || "linear",
        };


        this._cgp.on("deviceChange", () =>
        {
            // this.reInit();
        });
    }

    /**
     * set texture data from an image/canvas object
     * @function initTexture
     * @memberof Texture
     * @instance
     * @param {Object} img image
     * @param {Number} filter
     */
    initTexture(img, filter)
    {
        this.width = img.width;
        this.height = img.height;

        const textureType = "rgba8unorm";

        this._cgp.pushErrorScope("inittexture", { "logger": this._log });

        this.gpuTextureDescriptor = {

            "size": { "width": img.width, "height": img.height },
            "format": textureType,
            "usage": GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT
        };

        this.gpuTexture = this._cgp.device.createTexture(this.gpuTextureDescriptor);
        this._cgp.device.queue.copyExternalImageToTexture({ "source": img }, { "texture": this.gpuTexture }, this.gpuTextureDescriptor.size);

        this._cgp.popErrorScope();

        return this.gpuTexture;
    }

    dispose()
    {
        console.log("todo dispose");
    }

    getInfo()
    {
        const tex = this;
        const obj = {};

        obj.name = tex.name;
        obj.size = tex.width + " x " + tex.height;

        obj.textureType = tex.textureType;

        return obj;
    }

    createView()
    {
        if (!this.gpuTexture)
        {
            console.log("no gputexture...");
            return null;
        }
        return this.gpuTexture.createView();
    }

    getSampler()
    {
        // "clamp-to-edge"
        // "repeat"
        // "mirror-repeat"

        return this.samplerDesc;
    }

    /**
     * @function initFromData
     * @memberof Texture
     * @instance
     * @description create texturem from rgb data
     * @param {Array<Number>} data rgb color array [r,g,b,a,r,g,b,a,...]
     * @param {Number} w width
     * @param {Number} h height
     * @param {Number} filter
     * @param {Number} wrap
     */
    initFromData(data, w, h, filter, wrap)
    {
        if (!w || !h) this._log.error("texture size is 0");
        this.width = w;
        this.height = h;
        this.gpuTexture = this._cgp.device.createTexture(
            {
                "size": [w, h],
                "format": "rgba8unorm",
                "usage": GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
            });

        this._cgp.device.queue.writeTexture(
            { "texture": this.gpuTexture },
            data,
            { "bytesPerRow": w * 4 },
            { "width": w, "height": h });
    }


    setWrap(v)
    {
        this.samplerDesc.addressModeU = this.samplerDesc.addressModeV = v;
    }

    setFilter(v)
    {
        this.samplerDesc.minFilter = this.samplerDesc.magFilter = v;
    }
}


/**
 * @function load
 * @static
 * @memberof Texture
 * @description load an image from an url
 * @param {Context} cgp
 * @param {String} url
 * @param {Function} onFinished
 * @param {Object} settings
 * @return {Texture}
 */
cgp_texture_Texture.load = function (cgp, url, onFinished, settings)
{
    fetch(url).then((response) =>
    {
        const texture = new cgp_texture_Texture(cgp, { "name": url });

        response.blob().then((blob) =>
        {
            createImageBitmap(blob).then((imgBitmap) =>
            {
                texture.initTexture(imgBitmap);
                if (onFinished)onFinished(texture);
                else console.log("Texture.load no onFinished callback");
            }).catch((err) =>
            {
                if (onFinished)onFinished(cgp.getErrorTexture());
            });
        });
    });
};

;// CONCATENATED MODULE: ./src/core/cgp/cgp_state.js








// https://github.com/greggman/webgpu-utils
// https://developer.chrome.com/blog/from-webgl-to-webgpu/
// https://gpuweb.github.io/gpuweb/explainer/


/**
 * cables webgpu context/state manager
 * @class
 * @namespace external:CGP
 * @hideconstructor
 */
// const Context = function (_patch)
class WebGpuContext extends CGState
{
    constructor(_patch)
    {
        super();

        this.patch = _patch;

        this.lastErrorMsg = "";

        this._log = new Logger("WebGpuContext");
        this.gApi = CG.GAPI_WEBGPU;
        this._viewport = [0, 0, 256, 256];
        this._shaderStack = [];
        this._simpleShader = null;
        this.frame = 0;
        this.catchErrors = false;

        this._stackCullFaceFacing = [];
        this._stackDepthTest = [];
        this._stackCullFace = [];
        this._stackDepthFunc = [];
        this._stackDepthWrite = [];
        this._stackErrorScope = [];
        this._stackBlend = [];
        this._stackErrorScopeLogs = [];

        this._defaultBlend = {
            "color": {
                "operation": "add",
                "srcFactor": "one",
                "dstFactor": "zero",
            },
            "alpha": {
                "operation": "add",
                "srcFactor": "one",
                "dstFactor": "zero",
            },
        };

        this.DEPTH_FUNCS = [
            "never",
            "always",
            "less",
            "less-equal",
            "greater",
            "greater-equal",
            "equal",
            "not-equal"
        ];

        this.CULL_MODES = [
            "none",
            "back",
            "front",
            "none" // both does not exist in webgpu
        ];
    }


    /// ////////////////////

    // getViewPort()
    // {
    //     return [0, 0, this.canvasWidth, this.canvasHeight];
    // }

    renderStart(cgp, identTranslate, identTranslateView)
    {
        this.frame++;
        this.pushErrorScope("cgpstate internal", "internal");
        this.pushErrorScope("cgpstate out-of-memory", "out-of-memory");

        if (!this._simpleShader)
        {
            this._simpleShader = new cgp_shader_Shader(this, "simple default shader");
            this._simpleShader.setSource(cgl_shader_default);
            this._simpleShader.addUniformFrag("4f", "color", [1, 1, 0, 1]);
        }

        this.fpsCounter.startFrame();

        this._startMatrixStacks(identTranslate, identTranslateView);
        this.setViewPort(0, 0, this.canvasWidth, this.canvasHeight);

        this.pushShader(this._simpleShader);
        this.pushDepthTest(true);
        this.pushDepthWrite(true);
        this.pushDepthFunc("less-equal");


        this.pushBlend(this._defaultBlend);

        this.emitEvent("beginFrame");
    }

    renderEnd()
    {
        this._endMatrixStacks();

        this.popShader();
        this.popDepthFunc();
        this.popDepthWrite();
        this.popDepthTest();

        this.popErrorScope();
        this.popErrorScope();

        if (this._stackErrorScope.length > 0)console.log("scope stack length invalid...");

        this.emitEvent("endFrame");
        this.fpsCounter.endFrame();
    }


    setViewPort(x, y, w, h)
    {
        this._viewport = [x, y, w, h];
    }

    /**
     * @function getViewPort
     * @memberof Context
     * @instance
     * @description get current gl viewport
     * @returns {Array} array [x,y,w,h]
     */
    getViewPort()
    {
        return this._viewPort;
    }

    createMesh(geom, glPrimitive)
    {
        return new CGP.Mesh(this, geom, glPrimitive);
    }

    /**
     * push a shader to the shader stack
     * @function pushShader
     * @memberof Context
     * @instance
     * @param {Object} shader
     * @function
    */
    pushShader(shader)
    {
        this._shaderStack.push(shader);
        // currentShader = shader;
    }

    /**
     * pop current used shader from shader stack
     * @function popShader
     * @memberof Context
     * @instance
     * @function
     */
    popShader()
    {
        if (this._shaderStack.length === 0) throw new Error("Invalid shader stack pop!");
        this._shaderStack.pop();
        // currentShader = this._shaderStack[this._shaderStack.length - 1];
    }

    getShader()
    {
        return this._shaderStack[this._shaderStack.length - 1];
        // if (currentShader) if (!this.frameStore || ((this.frameStore.renderOffscreen === true) == currentShader.offScreenPass) === true) return currentShader;
        // for (let i = this._shaderStack.length - 1; i >= 0; i--) if (this._shaderStack[i]) if (this.frameStore.renderOffscreen == this._shaderStack[i].offScreenPass) return this._shaderStack[i];
    }

    setDevice(device)
    {
        this.device = device;


        if (this._emptyTexture) this._emptyTexture = this._emptyTexture.dispose();
        if (this._defaultTexture) this._defaultTexture = this._defaultTexture.dispose();
        if (this._errorTexture) this._errorTexture = this._errorTexture.dispose();

        this.emitEvent("deviceChange");
    }

    pushErrorScope(name, options = {})
    {
        if (this.catchErrors)
        {
            this._stackErrorScope.push(name);
            this._stackErrorScopeLogs.push(options.logger || null);
            this.device.pushErrorScope(options.scope || "validation");
        }
    }

    popErrorScope(cb)
    {
        if (this.catchErrors)
        {
            const name = this._stackErrorScope.pop();
            const logger = this._stackErrorScopeLogs.pop();
            this.device.popErrorScope().then((error) =>
            {
                if (error)
                {
                    if (this.lastErrorMsg == error.message)
                    {
                        // this._log.warn("last error once more...");
                    }
                    else
                    {
                        (logger || this._log).error(error.constructor.name, "in", name);
                        (logger || this._log).error(error.message);
                    }
                    this.lastErrorMsg = error.message;

                    if (cb)cb(error);
                }
            });
        }
    }

    /**
     * push depth testing enabled state
     * @function pushDepthTest
     * @param {Boolean} b enabled
     * @memberof Context
     * @instance
     */
    pushDepthTest(b)
    {
        this._stackDepthTest.push(b);
    }

    /**
     * current state of depth testing
     * @function stateDepthTest
     * @returns {Boolean} enabled
     * @memberof Context
     * @instance
     */
    stateDepthTest()
    {
        return this._stackDepthTest[this._stackDepthTest.length - 1];
    }

    /**
     * pop depth testing state
     * @function popDepthTest
     * @memberof Context
     * @instance
     */
    popDepthTest()
    {
        this._stackDepthTest.pop();
    }

    // --------------------------------------
    // state depthwrite

    /**
     * push depth write enabled state
     * @function pushDepthWrite
     * @param {Boolean} b enabled
     * @memberof Context
     * @instance
     */
    pushDepthWrite(b)
    {
        b = b || false;
        this._stackDepthWrite.push(b);
    }

    /**
     * current state of depth writing
     * @function stateCullFace
     * @returns {Boolean} enabled
     * @memberof Context
     * @instance
     */
    stateDepthWrite()
    {
        return this._stackDepthWrite[this._stackDepthWrite.length - 1];
    }

    /**
     * pop depth writing state
     * @function popCullFace
     * @memberof Context
     * @instance
     */
    popDepthWrite()
    {
        this._stackDepthWrite.pop();
    }

    // --------------------------------------
    // state depthfunc

    /**
     * @function pushDepthFunc
     * @memberof Context
     * @instance
     * @param {string} f depth compare func
     */
    pushDepthFunc(f)
    {
        this._stackDepthFunc.push(f);
    }

    /**
     * @function stateDepthFunc
     * @memberof Context
     * @instance
     * @returns {string}
     */
    stateDepthFunc()
    {
        if (this._stackDepthFunc.length > 0) return this._stackDepthFunc[this._stackDepthFunc.length - 1];
        return false;
    }

    /**
     * pop depth compare func
     * @function popDepthFunc
     * @memberof Context
     * @instance
     */
    popDepthFunc()
    {
        this._stackDepthFunc.pop();
    }

    // --------------------------------------
    // state CullFace

    /**
     * push face culling face enabled state
     * @function pushCullFace
     * @param {Boolean} b enabled
     * @memberof Context
     * @instance
     */
    pushCullFace(b)
    {
        this._stackCullFace.push(b);
    }

    /**
     * current state of face culling
     * @function stateCullFace
     * @returns {Boolean} enabled
     * @memberof Context
     * @instance
     */
    stateCullFace()
    {
        return this._stackCullFace[this._stackCullFace.length - 1];
    }

    /**
     * pop face culling enabled state
     * @function popCullFace
     * @memberof Context
     * @instance
     */
    popCullFace()
    {
        this._stackCullFace.pop();
    }

    // --------------------------------------
    // state CullFace Facing

    /**
     * push face culling face side
     * @function pushCullFaceFacing
     * @memberof Context
     * @param b
     * @instance
     */
    pushCullFaceFacing(b)
    {
        this._stackCullFaceFacing.push(b);
    }

    /**
     * current state of face culling side
     * @function stateCullFaceFacing
     * @returns {Boolean} enabled
     * @memberof Context
     * @instance
     */
    stateCullFaceFacing()
    {
        return this._stackCullFaceFacing[this._stackCullFaceFacing.length - 1];
    }

    /**
     * pop face culling face side
     * @function popCullFaceFacing
     * @memberof Context
     * @instance
     */
    popCullFaceFacing()
    {
        this._stackCullFaceFacing.pop();
    }

    pushBlend(b)
    {
        this._stackBlend.push(b);
    }

    popBlend()
    {
        this._stackBlend.pop();
    }

    stateBlend()
    {
        return this._stackBlend[this._stackBlend.length - 1];
    }

    getEmptyTexture()
    {
        if (this._emptyTexture) return this._emptyTexture;
        const size = 8;
        this._emptyTexture = new cgp_texture_Texture(this, {});
        this._emptyTexture.initFromData(CgTexture.getDefaultTextureData("empty", size), size, size);
        return this._emptyTexture;
    }

    getErrorTexture()
    {
        // if (this._errorTexture) return this._errorTexture;
        const size = 256;
        this._errorTexture = new cgp_texture_Texture(this, {});
        this._errorTexture.initFromData(CgTexture.getDefaultTextureData("stripes", size, { "r": 1, "g": 0, "b": 0 }), size, size);
        return this._errorTexture;
    }

    getDefaultTexture()
    {
        if (this._defaultTexture) return this._defaultTexture;
        const size = 256;
        this._defaultTexture = new cgp_texture_Texture(this, {});
        this._defaultTexture.initFromData(CgTexture.getDefaultTextureData("stripes", size), size, size);
        return this._defaultTexture;
    }
}


;// CONCATENATED MODULE: ./src/core/cgp/cgp_pipeline.js



class Pipeline
{
    constructor(_cgp, name)
    {
        if (!_cgp) throw new Error("Pipeline constructed without cgp " + name);
        this._name = name;
        this._cgp = _cgp;
        this._isValid = true;
        this._log = new Logger("pipeline");

        this._pipeCfg = null;
        this._renderPipeline = null;

        this._bindGroups = [];

        this._shaderListeners = [];
        this.shaderNeedsPipelineUpdate = false;

        this._old = {};

        this.DEPTH_COMPARE_FUNCS_STRINGS = ["never", "less", "equal", "lessequal", "greater", "notequal", "greaterequal", "always"];

        this._cgp.on("deviceChange", () =>
        {
            this._renderPipeline = null;
        });
    }

    get isValid() { return this._isValid; }

    setName(name)
    {
        this._name = name;
    }

    setShaderListener(oldShader, newShader)
    {
        for (let i = 0; i < this._shaderListeners.length; i++) oldShader.off(this._shaderListeners[i]);

        this._shaderListeners.push(
            newShader.on("compiled", () =>
            {
                // console.log("pipe update shader compileeeeeee");
                // this.needsRebuildReason = "shader changed";
                this.shaderNeedsPipelineUpdate = "shader compiled";
            }));
    }


    getInfo()
    {
        // console.log(this.bindingGroupLayoutEntries);

        const arr = [
            "name: " + this._name,
            "bindgroups: " + this._bindGroups.length

        ];

        if (this.bindingGroupLayoutEntries)arr.push("layouts: " + this.bindingGroupLayoutEntries.length);

        // if (this.bindingGroupLayoutEntries)
        //     for (let i = 0; i < this.bindingGroupLayoutEntries.length; i++)
        //     {
        //         // const lines = JSON.stringify(this.bindingGroupLayoutEntries, 4, true).split(",");
        //         arr.push(...lines);
        //     }

        return arr;
    }

    setPipeline(shader, mesh)
    {
        if (!mesh || !shader)
        {
            console.log("pipeline unknown shader/mesh");
            return;
        }

        if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.push("setPipeline", this.getInfo());

        let needsRebuildReason = "";
        if (!this._renderPipeline) needsRebuildReason = "no renderpipeline";
        if (!this._pipeCfg)needsRebuildReason = "no pipecfg";
        if (this._old.mesh != mesh)needsRebuildReason = "no mesh";
        if (this._old.shader != shader)
        {
            this.setShaderListener(this._old.shader, shader);
            needsRebuildReason = "shader changed";
        }

        if (shader.needsPipelineUpdate)
        {
            needsRebuildReason = "mesh needs update: " + shader.needsPipelineUpdate;
            shader.needsPipelineUpdate = false;
        }
        if (mesh.needsPipelineUpdate)needsRebuildReason = "mesh needs update";
        if (this.shaderNeedsPipelineUpdate)needsRebuildReason = "shader was recompiled: " + this.shaderNeedsPipelineUpdate;

        if (this._pipeCfg)
        {
            if (this._pipeCfg.depthStencil.depthWriteEnabled != this._cgp.stateDepthWrite())
            {
                needsRebuildReason = "depth changed";
                this._pipeCfg.depthStencil.depthWriteEnabled = this._cgp.stateDepthWrite();
            }

            if (this._pipeCfg.fragment.targets[0].blend != this._cgp.stateBlend())
            {
                needsRebuildReason = "blend changed";
                this._pipeCfg.fragment.targets[0].blend = this._cgp.stateBlend();
            }

            // "fragment": {
            //     "module": shader.gpuShaderModule,
            //     "entryPoint": "myFSMain",
            //     "targets": [
            //         {
            //             "format": this._cgp.presentationFormat,
            //             "blend":
            //         },


            if (this._cgp.stateDepthTest() === false)
            {
                if (this._pipeCfg.depthStencil.depthCompare != "never")
                {
                    this._pipeCfg.depthStencil.depthCompare = "never";
                    needsRebuildReason = "depth compare changed";
                }
            }
            else
            if (this._pipeCfg.depthStencil.depthCompare != this._cgp.stateDepthFunc())
            {
                needsRebuildReason = "depth state ";
                this._pipeCfg.depthStencil.depthCompare = this._cgp.stateDepththis._cgp.stateDepthFunc();
            }

            // console.log(this._pipeCfg.primitive.cullMode, this._cgp.stateCullFaceFacing());
            if (this._pipeCfg.primitive.cullMode != this._cgp.stateCullFaceFacing())
            {
                needsRebuildReason = "cullmode change";
                this._pipeCfg.primitive.cullMode = this._cgp.stateCullFaceFacing();
            }
        }

        this._cgp.currentPipeDebug =
        {
            "cfg": this._pipeCfg,
            "bindingGroupEntries": this.bindingGroupEntries,
            "bindingGroupLayoutEntries": this.bindingGroupLayoutEntries
        };


        if (needsRebuildReason != "")
        {
            console.log("rebuild pipe", needsRebuildReason);
            this._cgp.pushErrorScope("createPipeline", { "logger": this._log });

            this._bindGroups = [];

            this._pipeCfg = this.getPipelineObject(shader, mesh);
            this._old.device = this._cgp.device;
            this._old.shader = shader;
            this._old.mesh = mesh;
            this._renderPipeline = this._cgp.device.createRenderPipeline(this._pipeCfg);

            this._cgp.popErrorScope();
        }


        if (this._renderPipeline && this._isValid)
        {
            this._cgp.pushErrorScope("setpipeline", { "logger": this._log });


            this._cgp.passEncoder.setPipeline(this._renderPipeline);

            if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.push("updateUniforms");

            shader.incBindingCounter();

            if (!this._bindGroups[shader.bindingCounter])
            {
                const bindingGroupEntries = [];

                for (let i = 0; i < shader.bindingsVert.length; i++)
                {
                    if (shader.bindingsVert[i].getSizeBytes() > 0)
                    {
                        bindingGroupEntries.push(shader.bindingsVert[i].getBindingGroupEntry(this._cgp.device, shader.bindingCounter));
                    }
                    else console.log("shader defaultBindingVert size 0");
                }
                for (let i = 0; i < shader.bindingsFrag.length; i++)
                {
                    if (shader.bindingsFrag[i].getSizeBytes() > 0)
                    {
                        bindingGroupEntries.push(shader.bindingsFrag[i].getBindingGroupEntry(this._cgp.device, shader.bindingCounter));
                    }
                    else console.log("shader defaultBindingFrag size 0");
                }

                const bg = {
                    "label": "label2",
                    "layout": this.bindGroupLayout,
                    "entries": bindingGroupEntries
                };

                this._bindGroups[shader.bindingCounter] = this._cgp.device.createBindGroup(bg);
            }

            this._bindUniforms(shader, shader.bindingCounter);

            if (this._bindGroups[shader.bindingCounter]) this._cgp.passEncoder.setBindGroup(0, this._bindGroups[shader.bindingCounter]);


            // shader.bindingCounter++;

            if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.pop();

            this._cgp.popErrorScope();
        }
        if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.pop();


        this.shaderNeedsPipelineUpdate = false;
    }

    getPipelineObject(shader, mesh)
    {
        this.bindingGroupLayoutEntries = [];

        for (let i = 0; i < shader.bindingsVert.length; i++)
        {
            if (shader.bindingsVert[i].getSizeBytes() > 0)
            {
                this.bindingGroupLayoutEntries.push(shader.bindingsVert[i].getBindingGroupLayoutEntry());
            }
            else console.log("shader defaultBindingVert size 0");
        }

        for (let i = 0; i < shader.bindingsFrag.length; i++)
        {
            if (shader.bindingsFrag[i].getSizeBytes() > 0)
            {
                this.bindingGroupLayoutEntries.push(shader.bindingsFrag[i].getBindingGroupLayoutEntry());
            }
            else console.log("shader defaultBindingFrag size 0");
        }
        // //////////

        this.bindGroupLayout = this._cgp.device.createBindGroupLayout(
            {
                "label": "bg layout " + this._name,
                "entries": this.bindingGroupLayoutEntries,
            });

        const pipelineLayout = this._cgp.device.createPipelineLayout({
            "label": "pipe layout " + this._name,
            "bindGroupLayouts": [this.bindGroupLayout]
        });


        let buffers = [
            // position
            {
                "arrayStride": 3 * 4, // 3 floats, 4 bytes each
                "attributes": [
                    { "shaderLocation": 0, "offset": 0, "format": "float32x3" },
                ],
            },
            // texcoords
            {
                "arrayStride": 2 * 4, // 2 floats, 4 bytes each
                "attributes": [
                    { "shaderLocation": 2, "offset": 0, "format": "float32x2", },
                ],
            },
            // normals
            {
                "arrayStride": 3 * 4, // 3 floats, 4 bytes each
                "attributes": [
                    { "shaderLocation": 1, "offset": 0, "format": "float32x3" },
                ],
            }];



        const pipeCfg = {
            // "layout": "auto",
            "label": this._name,
            "layout": pipelineLayout,
            "vertex": {
                "module": shader.gpuShaderModule,
                "entryPoint": "myVSMain",
                "buffers": buffers

            },
            "fragment": {
                "module": shader.gpuShaderModule,
                "entryPoint": "myFSMain",
                "targets": [
                    {
                        "format": this._cgp.presentationFormat,
                        "blend": this._cgp.stateBlend()
                    },
                ],
            },
            "primitive": {
                "topology": "triangle-list",
                "cullMode": this._cgp.stateCullFaceFacing(), // back/none/front

                // "point-list",
                // "line-list",
                // "line-strip",
                // "triangle-list",
                // "triangle-strip"
            },
            "depthStencil": {
                "depthWriteEnabled": this._cgp.stateDepthTest(),
                "depthCompare": this._cgp.stateDepthFunc(),
                "format": "depth24plus",
            },

        };

        return pipeCfg;
    }


    _bindUniforms(shader, inst)
    {
        // this._cgp.pushErrorScope("pipeline bind uniforms", { "logger": this._log });

        shader.bind();

        if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.push("bind uniforms vert", ["num:" + shader.bindingsVert.length]);
        for (let i = 0; i < shader.bindingsVert.length; i++) shader.bindingsVert[i].update(this._cgp, inst);
        if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.pop();

        if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.push("bind uniforms frag", ["num:" + shader.bindingsFrag.length]);
        for (let i = 0; i < shader.bindingsFrag.length; i++) shader.bindingsFrag[i].update(this._cgp, inst);
        if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.pop();



        // shader.defaultBindingVert.update(this._cgp);

        // this._cgp.popErrorScope((e) =>
        // {
        //     this._isValid = false;
        // });
    }
}

;// CONCATENATED MODULE: ./src/core/cgp/cgp_mesh.js



class cgp_mesh_Mesh
{
    constructor(_cgp, __geom)
    {
        this._log = new Logger("cgl_mesh");
        this._cgp = _cgp;
        this._geom = null;
        this.numIndex = 0;
        this.instances = 1;

        this._pipe = new Pipeline(this._cgp, "new mesh");
        this._numNonIndexed = 0;
        this._positionBuffer = null;
        this._bufVerticesIndizes = null;
        this._attributes = [];
        this._needsPipelineUpdate = false;

        if (__geom) this.setGeom(__geom);
    }

    _createBuffer(device, data, usage)
    {
        let bo = {
            "size": data.byteLength,
            "usage": usage,
            "mappedAtCreation": true,
        };
        // ifbo.stepMode = "instance";
        const buffer = device.createBuffer(bo);
        const dst = new data.constructor(buffer.getMappedRange());
        dst.set(data);
        buffer.unmap();
        return buffer;
    }

    /**
     * @function setGeom
     * @memberof Mesh
     * @instance
     * @description set geometry for mesh
     * @param {Geometry} geom geometry
     * @param {boolean} removeRef
     */
    setGeom(geom, removeRef)
    {
        this._needsPipelineUpdate = true;
        this._geom = geom;
        this._disposeAttributes();

        this._positionBuffer = this._createBuffer(this._cgp.device, new Float32Array(geom.vertices), GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST);

        let vi = geom.verticesIndices;
        if (!geom.isIndexed()) vi = Array.from(Array(geom.vertices.length / 3).keys());
        this._numIndices = vi.length;
        this._indicesBuffer = this._createBuffer(this._cgp.device, new Uint32Array(vi), GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST);

        if (geom.texCoords && geom.texCoords.length) this.setAttribute("texCoords", geom.texCoords, 2);
        if (geom.vertexNormals && geom.vertexNormals.length) this.setAttribute("normals", geom.vertexNormals, 3);

        this.setAttribute("normals", geom.vertexNormals, 3);
    }


    _disposeAttributes()
    {
        this._needsPipelineUpdate = true;
        for (let i = 0; i < this._attributes.length; i++)
        {
            this._attributes[i].buffer.destroy();
        }
        this._attributes.length = 0;
    }

    dispose()
    {
        this._disposeAttributes();
    }

    /**
     * @function setAttribute
     * @description update attribute
     * @memberof Mesh
     * @instance
     * @param {String} name attribute name
     * @param {Array} array data
     * @param {Number} itemSize
     * @param {Object} options
     */
    setAttribute(name, array, itemSize, options = {})
    {
        if (!array)
        {
            this._log.error("mesh addAttribute - no array given! " + name);
            throw new Error();
        }

        let instanced = false;
        if (options.instanced) instanced = options.instanced;

        const buffer = this._createBuffer(this._cgp.device, new Float32Array(array), GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST);

        const attr = {
            "buffer": buffer,
            "name": name,
            "instanced": instanced,
        };
        this._attributes.push(attr);

        return attr;
    }


    render()
    {
        if (!this._positionBuffer) return;
        if (this.instances <= 0) return;

        const shader = this._cgp.getShader();
        if (shader)shader.bind();

        if (!this._cgp.getShader() || !this._cgp.getShader().isValid)
        {
            // this.status = "shader invalid";
            return;
        }

        if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.push("mesh", ["geom " + this._geom.name, "shader " + this._cgp.getShader().getName()]);

        this._pipe.setName("mesh " + this._geom.name + " " + this._cgp.getShader().getName());
        this._pipe.setPipeline(this._cgp.getShader(), this);


        if (this._pipe.isValid)
        {
            this._cgp.passEncoder.setVertexBuffer(0, this._positionBuffer);
            for (let i = 0; i < this._attributes.length; i++)
            {
                this._cgp.passEncoder.setVertexBuffer(i + 1, this._attributes[i].buffer);
            }

            this._cgp.passEncoder.setIndexBuffer(this._indicesBuffer, "uint32");

            if (this._numNonIndexed)
                this._cgp.passEncoder.draw(this._numIndices, this.instances);
            else
                this._cgp.passEncoder.drawIndexed(this._numIndices, this.instances);
        }

        if (this._cgp.frameStore.branchProfiler) this._cgp.frameStore.branchStack.pop();

        // if (shader)shader.unbind();
    }
}

;// CONCATENATED MODULE: ./src/core/cgp/index.js










const cgp_CGP = {
    "Context": WebGpuContext,
    "Shader": cgp_shader_Shader,
    "Mesh": cgp_mesh_Mesh,
    "Pipeline": Pipeline,
    "Texture": cgp_texture_Texture,
    "Binding": Binding,
    "Uniform": cgp_uniform_Uniform,
    "MESHES": MESHES,
    "GPUBuffer": GPUBuffer
};

window.CABLES = window.CABLES || {};
window.CABLES.CGP = cgp_CGP;
window.CGP = cgp_CGP;




;// CONCATENATED MODULE: ./src/core/cgl/cgl_framebuffer.js



// todo: convert to prototyped...

/**
 * a framebuffer
 * @constructor
 * @class
 * @constructs Framebuffer
 * @param {Context} _cgl cgl
 * @param {Number} _w width
 * @param {Number} _h height
 * @param {Object} options
 */
const Framebuffer = function (_cgl, _w, _h, options)
{
    const cgl = _cgl;
    this._log = new Logger("Framebuffer");
    this.valid = true;

    let depthTextureExt = cgl.gl.DEPTH_TEXTURE;
    if (!depthTextureExt) depthTextureExt = cgl.enableExtension("WEBGL_depth_texture");
    if (!depthTextureExt) depthTextureExt = cgl.enableExtension("WEBKIT_WEBGL_depth_texture");
    if (!depthTextureExt) depthTextureExt = cgl.enableExtension("MOZ_WEBGL_depth_texture");

    if (!depthTextureExt)
    {
        this._log.error("NO_DEPTH_TEXTURE", "no depth texture support");
        return;
    }

    let width = _w || 512;
    let height = _h || 512;

    options = options || {
        "isFloatingPointTexture": false,
    };

    if (!options.hasOwnProperty("clear")) options.clear = true;
    if (!options.hasOwnProperty("filter")) options.filter = Texture.FILTER_LINEAR;

    const texture = new Texture(cgl, {
        "isFloatingPointTexture": options.isFloatingPointTexture,
        "filter": options.filter,
        "wrap": options.wrap || Texture.CLAMP_TO_EDGE
    });

    let textureDepth = null;
    if (depthTextureExt)
    {
        textureDepth = new Texture(cgl, {
            "isDepthTexture": true,
        });
    }
    this._options = options;

    const frameBuf = cgl.gl.createFramebuffer();
    const depthBuffer = cgl.gl.createRenderbuffer();

    this.getWidth = function ()
    {
        return width;
    };
    this.getHeight = function ()
    {
        return height;
    };

    /**
     * get native gl framebuffer
     * @function getGlFrameBuffer
     * @memberof Framebuffer
     * @returns {Object} framebuffer
     */
    this.getGlFrameBuffer = function ()
    {
        return frameBuf;
    };

    /**
     * get depth renderbuffer
     * @function getDepthRenderBuffer
     * @memberof Framebuffer
     * @returns {Object} renderbuffer
     */
    this.getDepthRenderBuffer = function ()
    {
        return depthBuffer;
    };

    /**
     * get color texture
     * @function getTextureColor
     * @memberof Framebuffer
     * @returns {Texture} rgba texture
     */
    this.getTextureColor = function ()
    {
        return texture;
    };

    /**
     * get depth texture
     * @function getTextureDepth
     * @memberof Framebuffer
     * @returns {Texture} depth texture
     */
    this.getTextureDepth = function ()
    {
        return textureDepth;
    };

    this.setFilter = function (f)
    {
        texture.filter = f;
        texture.setSize(width, height);
    };

    this.setSize = function (w, h)
    {
        if (w < 2) w = 2;
        if (h < 2) h = 2;

        width = Math.ceil(w);
        height = Math.ceil(h);

        cgl.profileData.profileFrameBuffercreate++;

        cgl.gl.bindFramebuffer(cgl.gl.FRAMEBUFFER, frameBuf);
        cgl.gl.bindRenderbuffer(cgl.gl.RENDERBUFFER, depthBuffer);

        texture.setSize(width, height);
        if (textureDepth) textureDepth.setSize(width, height);

        // if(depthTextureExt) cgl.gl.renderbufferStorage(cgl.gl.RENDERBUFFER, cgl.gl.DEPTH_COMPONENT16, width,height);
        if (depthTextureExt) cgl.gl.renderbufferStorage(cgl.gl.RENDERBUFFER, cgl.gl.DEPTH_COMPONENT16, width, height);

        cgl.gl.framebufferTexture2D(cgl.gl.FRAMEBUFFER, cgl.gl.COLOR_ATTACHMENT0, cgl.gl.TEXTURE_2D, texture.tex, 0);

        if (depthTextureExt)
        {
            cgl.gl.framebufferRenderbuffer(cgl.gl.FRAMEBUFFER, cgl.gl.DEPTH_ATTACHMENT, cgl.gl.RENDERBUFFER, depthBuffer);
            cgl.gl.framebufferTexture2D(
                cgl.gl.FRAMEBUFFER,
                cgl.gl.DEPTH_ATTACHMENT, // safari needs DEPTH_ATTACHMENT NOT DEPTH_ATTACHMENT16
                // cgl.gl.DEPTH_COMPONENT16,
                cgl.gl.TEXTURE_2D,
                textureDepth.tex,
                0,
            );
        }

        if (!cgl.gl.isFramebuffer(frameBuf)) throw new Error("Invalid framebuffer");
        const status = cgl.gl.checkFramebufferStatus(cgl.gl.FRAMEBUFFER);

        switch (status)
        {
        case cgl.gl.FRAMEBUFFER_COMPLETE:
            break;
        case cgl.gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
            this._log.warn("FRAMEBUFFER_INCOMPLETE_ATTACHMENT...", width, height, texture.tex, depthBuffer);
            this.valid = false;
            throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
        case cgl.gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
            this._log.warn("FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
            this.valid = false;
            throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
        case cgl.gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
            this._log.warn("FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
            this.valid = false;
            throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
        case cgl.gl.FRAMEBUFFER_UNSUPPORTED:
            this._log.warn("FRAMEBUFFER_UNSUPPORTED");
            this.valid = false;
            this._log.warn(width, height, options);

            throw new Error("Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED");
        case 0x8CDB:
            this._log.warn("Incomplete: FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER from ext. Or Safari/iOS undefined behaviour.");
            this.valid = false;
            break;
        default:
            this._log.warn("incomplete framebuffer", status);
            this.valid = false;
            throw new Error("Incomplete framebuffer: " + status);
        }

        cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, null);
        cgl.gl.bindRenderbuffer(cgl.gl.RENDERBUFFER, null);
        cgl.gl.bindFramebuffer(cgl.gl.FRAMEBUFFER, null);
    };

    this.renderStart = function ()
    {
        cgl.pushModelMatrix();
        cgl.gl.bindFramebuffer(cgl.gl.FRAMEBUFFER, frameBuf);
        cgl.pushGlFrameBuffer(frameBuf);
        cgl.pushFrameBuffer(this);

        cgl.pushPMatrix();
        cgl.gl.viewport(0, 0, width, height);

        if (this._options.clear)
        {
            cgl.gl.clearColor(0, 0, 0, 0);
            cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT);
        }
    };

    this.renderEnd = function ()
    {
        cgl.popPMatrix();
        cgl.gl.bindFramebuffer(cgl.gl.FRAMEBUFFER, cgl.popGlFrameBuffer());
        cgl.popFrameBuffer();

        cgl.popModelMatrix();
        cgl.resetViewPort();
    };


    this.delete = function ()
    {
        texture.delete();
        this.valid = false;
        if (textureDepth) textureDepth.delete();
        cgl.gl.deleteRenderbuffer(depthBuffer);
        cgl.gl.deleteFramebuffer(frameBuf);
    };

    this.dispose = this.delete;

    this.setSize(width, height);
};



;// CONCATENATED MODULE: ./src/core/cgl/cgl_framebuffer2.js
// * see framebuffer1






const Framebuffer2 = function (cgl, w, h, options)
{
    this._log = new Logger("cgl_framebuffer2");
    if (cgl.glVersion == 1) return this._log.error("framebuffer2 used on webgl1");
    this.Framebuffer2DrawTargetsDefault = null;
    this.Framebuffer2BlittingFramebuffer = null;
    this.Framebuffer2FinalFramebuffer = null;
    this._cgl = cgl;

    this._cgl.printError("before framebuffer2 constructor");

    this._width = 0;
    this._height = 0;
    this.valid = true;

    this._depthRenderbuffer = null;
    this._frameBuffer = null;
    this._textureFrameBuffer = null;
    this._colorRenderbuffers = [];
    this._drawTargetArray = [];
    this._disposed = false;

    if (!this.Framebuffer2BlittingFramebuffer) this.Framebuffer2BlittingFramebuffer = cgl.gl.createFramebuffer();
    if (!this.Framebuffer2FinalFramebuffer) this.Framebuffer2FinalFramebuffer = cgl.gl.createFramebuffer();

    if (!this.Framebuffer2DrawTargetsDefault) this.Framebuffer2DrawTargetsDefault = [cgl.gl.COLOR_ATTACHMENT0];

    this._options = options || {
        "isFloatingPointTexture": false,
    };

    // this._cgl.printError("fb2 before");

    this.name = this._options.name || "unknown";

    this._cgl.profileData.addHeavyEvent("framebuffer create", this.name);

    if (!this._options.hasOwnProperty("numRenderBuffers")) this._options.numRenderBuffers = 1;
    if (!this._options.hasOwnProperty("depth")) this._options.depth = true;
    if (!this._options.hasOwnProperty("clear")) this._options.clear = true;
    if (!this._options.hasOwnProperty("multisampling"))
    {
        this._options.multisampling = false;
        this._options.multisamplingSamples = 0;
    }

    if (this._options.multisamplingSamples)
    {
        if (this._cgl.glSlowRenderer) this._options.multisamplingSamples = 0;
        if (!this._cgl.gl.MAX_SAMPLES) this._options.multisamplingSamples = 0;
        else this._options.multisamplingSamples = Math.min(this._cgl.maxSamples, this._options.multisamplingSamples);
    }

    if (!this._options.hasOwnProperty("filter")) this._options.filter = Texture.FILTER_LINEAR;
    if (!this._options.hasOwnProperty("wrap")) this._options.wrap = Texture.WRAP_REPEAT;

    this._numRenderBuffers = this._options.numRenderBuffers;
    this._colorTextures = [];

    this.clearColors = [];
    for (let i = 0; i < this._numRenderBuffers; i++) this.clearColors.push([0, 0, 0, 1]);


    if (!options.pixelFormat)
    {
        if (options.isFloatingPointTexture) this._options.pixelFormat = Texture.PFORMATSTR_RGBA32F;
        else this._options.pixelFormat = Texture.PFORMATSTR_RGBA8UB;
    }

    for (let i = 0; i < this._numRenderBuffers; i++)
    {
        this._colorTextures[i] = new Texture(cgl, {
            "name": "fb2 " + this.name + " " + i,
            "isFloatingPointTexture": this._options.isFloatingPointTexture,
            "anisotropic": this._options.anisotropic || 0,
            "pixelFormat": this._options.pixelFormat,
            "filter": this._options.filter,
            "wrap": this._options.wrap,
        });
    }



    let fil = Texture.FILTER_NEAREST;
    if (this._options.shadowMap) fil = Texture.FILTER_LINEAR;

    const defaultTexSize = 512;

    if (this._options.depth)
    {
        this._textureDepth = new Texture(cgl,
            {
                "name": "fb2 depth " + this.name,
                "isDepthTexture": true,
                "filter": fil,
                "shadowMap": this._options.shadowMap || false,
                "width": w || defaultTexSize,
                "height": h || defaultTexSize,
            });
    }

    if (cgl.aborted) return;

    this.setSize(w || defaultTexSize, h || defaultTexSize);

    this._cgl.printError("framebuffer2 constructor");
};

Framebuffer2.prototype.getWidth = function ()
{
    return this._width;
};
Framebuffer2.prototype.getHeight = function ()
{
    return this._height;
};

Framebuffer2.prototype.getGlFrameBuffer = function ()
{
    return this._frameBuffer;
};

Framebuffer2.prototype.getDepthRenderBuffer = function ()
{
    return this._depthRenderbuffer;
};

Framebuffer2.prototype.getTextureColor = function ()
{
    return this._colorTextures[0];
};

Framebuffer2.prototype.getTextureColorNum = function (i)
{
    return this._colorTextures[i];
};

Framebuffer2.prototype.getTextureDepth = function ()
{
    return this._textureDepth;
};

Framebuffer2.prototype.setFilter = function (f)
{
    for (let i = 0; i < this._numRenderBuffers; i++)
    {
        this._colorTextures[i].filter = f;
        this._colorTextures[i].setSize(this._width, this._height);
    }
};

Framebuffer2.prototype.delete = Framebuffer2.prototype.dispose = function ()
{
    this._disposed = true;
    let i = 0;
    for (i = 0; i < this._numRenderBuffers; i++) this._colorTextures[i].delete();
    // this._texture.delete();
    if (this._textureDepth) this._textureDepth.delete();
    for (i = 0; i < this._numRenderBuffers; i++) this._cgl.gl.deleteRenderbuffer(this._colorRenderbuffers[i]);
    this._cgl.gl.deleteRenderbuffer(this._depthRenderbuffer);
    this._cgl.gl.deleteFramebuffer(this._frameBuffer);
    this._cgl.gl.deleteFramebuffer(this._textureFrameBuffer);
};

Framebuffer2.prototype.setSize = function (w, h)
{
    if (this._disposed) return this._log.warn("disposed framebuffer setsize...");
    this._cgl.profileData.addHeavyEvent("framebuffer resize", this.name);

    let i = 0;

    this._width = this._cgl.checkTextureSize(w);
    this._height = this._cgl.checkTextureSize(h);

    this._cgl.profileData.profileFrameBuffercreate++;

    if (this._frameBuffer)
    {
        for (i = 0; i < this._numRenderBuffers; i++) this._cgl.gl.deleteRenderbuffer(this._colorRenderbuffers[i]);
        // this._cgl.gl.deleteRenderbuffer(this._colorRenderbuffer);
        this._cgl.gl.deleteRenderbuffer(this._depthRenderbuffer);
        this._cgl.gl.deleteFramebuffer(this._frameBuffer);
        this._cgl.gl.deleteFramebuffer(this._textureFrameBuffer);
    }

    this._frameBuffer = this._cgl.gl.createFramebuffer();
    this._textureFrameBuffer = this._cgl.gl.createFramebuffer();

    const depth = this._options.depth;

    for (i = 0; i < this._numRenderBuffers; i++)
    {
        this._colorTextures[i].setSize(this._width, this._height);
    }

    for (i = 0; i < this._numRenderBuffers; i++)
    {
        const renderBuffer = this._cgl.gl.createRenderbuffer();

        // color renderbuffer

        this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuffer);
        this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, renderBuffer);

        const info = Texture.setUpGlPixelFormat(this._cgl, this._options.pixelFormat);
        let internFormat = info.glInternalFormat;

        // if (this._options.isFloatingPointTexture)
        // {
        if (CGL.Texture.isPixelFormatHalfFloat(info.pixelFormat))
        {
            if (!this._cgl.enableExtension("OES_texture_float_linear"))
            {
                this._options.filter = Texture.FILTER_NEAREST;
                this.setFilter(this._options.filter);
            }
        }
        else if (CGL.Texture.isPixelFormatFloat(info.pixelFormat))
        {
            if (!this._cgl.enableExtension("OES_texture_float_linear"))
            {
                this._log.warn("no linear pixelformat,using nearest");
                this._options.filter = Texture.FILTER_NEAREST;
                this.setFilter(this._options.filter);
            }
        }
        // else if (info.pixelFormat == Texture.PFORMATSTR_RGBA32F || info.pixelFormat == Texture.PFORMATSTR_R11FG11FB10F
        // else if (info.pixelFormat == Texture.PFORMATSTR_RGBA32F || info.pixelFormat == Texture.PFORMATSTR_R11FG11FB10F
        // else if (info.pixelFormat == Texture.PFORMATSTR_RG16F)
        // {
        //     const extcb = this._cgl.enableExtension("EXT_color_buffer_float");

        //     if (!this._cgl.enableExtension("OES_texture_float_linear"))
        //     {
        //         console.log("no linear pixelformat,switching to nearest");
        //         this._options.filter = Texture.FILTER_NEAREST;
        //         this.setFilter(this._options.filter);
        //     }
        // }
        // }

        if (this._options.multisampling && this._options.multisamplingSamples)
        {
            this._cgl.gl.renderbufferStorageMultisample(this._cgl.gl.RENDERBUFFER, this._options.multisamplingSamples, internFormat, this._width, this._height);
        }
        else
        {
            this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, internFormat, this._width, this._height);
        }



        this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0 + i, this._cgl.gl.RENDERBUFFER, renderBuffer);
        this._colorRenderbuffers[i] = renderBuffer;
    }

    // this._cgl.gl.bindFramebuffer(this._cgl.gl.DRAW_FRAMEBUFFER, this._textureFrameBuffer);
    this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._textureFrameBuffer);

    for (i = 0; i < this._numRenderBuffers; i++)
    {
        this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0 + i, this._cgl.gl.TEXTURE_2D, this._colorTextures[i].tex, 0);
    }

    if (this._options.depth)
    {
        this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.TEXTURE_2D, this._textureDepth.tex, 0);
    }

    // depth renderbuffer

    this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuffer);


    let depthType = this._cgl.gl.DEPTH_COMPONENT32F;

    if (this._cgl.glSlowRenderer) depthType = this._cgl.gl.DEPTH_COMPONENT16;
    if (depth)
    {
        this._textureDepth.setSize(this._width, this._height);
        this._depthRenderbuffer = this._cgl.gl.createRenderbuffer();

        this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, this._depthRenderbuffer);
        if (this._options.isFloatingPointTexture)
        {
            if (this._options.multisampling) this._cgl.gl.renderbufferStorageMultisample(this._cgl.gl.RENDERBUFFER, this._options.multisamplingSamples, depthType, this._width, this._height);
            else this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, depthType, this._width, this._height);
        }
        else if (this._options.multisampling)
        {
            this._cgl.gl.renderbufferStorageMultisample(this._cgl.gl.RENDERBUFFER, this._options.multisamplingSamples, depthType, this._width, this._height);
            // this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,depthType, this._width, this._height);
        }
        else
        {
            this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, depthType, this._width, this._height);
        }

        this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.RENDERBUFFER, this._depthRenderbuffer);
    }

    // this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
    // this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._textureFrameBuffer);

    this._drawTargetArray.length = 0;
    for (i = 0; i < this._numRenderBuffers; i++) this._drawTargetArray.push(this._cgl.gl.COLOR_ATTACHMENT0 + i);

    // this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);


    if (!this._cgl.gl.isFramebuffer(this._textureFrameBuffer)) this._log.warn("invalid framebuffer");// throw new Error("Invalid framebuffer");
    const status = this._cgl.gl.checkFramebufferStatus(this._cgl.gl.FRAMEBUFFER);

    if (status != this._cgl.gl.FRAMEBUFFER_COMPLETE)
    {
        this._log.error("framebuffer incomplete: " + this.name, this);
        this._log.log("options", this._options);
        this._log.log("options pixelformat", this._options.pixelFormat);

        switch (status)
        {
        case this._cgl.gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
            this._log.warn("FRAMEBUFFER_INCOMPLETE_ATTACHMENT...", this);
            throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
        case this._cgl.gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
            this._log.warn("FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
            throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
        case this._cgl.gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
            this._log.warn("FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
            throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
        case this._cgl.gl.FRAMEBUFFER_UNSUPPORTED:
            this._log.warn("FRAMEBUFFER_UNSUPPORTED");
            throw new Error("Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED");
        default:
            this.valid = false;
            this._log.error("incomplete framebuffer", status, this._frameBuffer);
            this._cgl.printError();

            this._frameBuffer = null;
            // debugger;
            throw new Error("Incomplete framebuffer: " + status);

        // throw("Incomplete framebuffer: " + status);
        }
    }

    this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
    this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, null);

    // this._cgl.printError("fb setsize");
};

Framebuffer2.prototype.renderStart = function ()
{
    if (this._disposed) return this._log.warn("disposed framebuffer renderStart...");
    this._cgl.checkFrameStarted("fb2 renderstart");
    this._cgl.pushModelMatrix(); // needed ??

    this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuffer);
    this._cgl.pushGlFrameBuffer(this._frameBuffer);
    this._cgl.pushFrameBuffer(this);

    this._cgl.pushPMatrix();
    this._cgl.pushViewPort(0, 0, this._width, this._height);

    this._cgl.gl.drawBuffers(this._drawTargetArray);

    if (this._options.clear)
    {
        this._cgl.gl.clearColor(0, 0, 0, 0);
        this._cgl.gl.clear(this._cgl.gl.COLOR_BUFFER_BIT | this._cgl.gl.DEPTH_BUFFER_BIT);
    }
};

Framebuffer2.prototype.clear = function ()
{
    if (this._numRenderBuffers <= 1)
    {
        this._cgl.gl.bindFramebuffer(this._cgl.gl.READ_FRAMEBUFFER, this._frameBuffer);
        this._cgl.gl.bindFramebuffer(this._cgl.gl.DRAW_FRAMEBUFFER, this._textureFrameBuffer);
    }
    else this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuffer);

    this._cgl.gl.drawBuffers(this._drawTargetArray);

    for (let i = 0; i < this._numRenderBuffers; i++)
    {
        this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0 + i, this._cgl.gl.TEXTURE_2D, this._colorTextures[i].tex, 0);
        this._cgl.gl.clearBufferfv(this._cgl.gl.COLOR, i, this.clearColors[i]);
    }
    this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
};

Framebuffer2.prototype.renderEnd = function ()
{
    if (this._disposed) return this._log.warn("disposed framebuffer renderEnd...");
    this._cgl.popPMatrix();

    this._cgl.profileData.profileFramebuffer++;


    if (this._numRenderBuffers <= 1)
    {
        this._cgl.gl.bindFramebuffer(this._cgl.gl.READ_FRAMEBUFFER, this._frameBuffer);
        this._cgl.gl.bindFramebuffer(this._cgl.gl.DRAW_FRAMEBUFFER, this._textureFrameBuffer);

        this._cgl.gl.clearBufferfv(this._cgl.gl.COLOR, 0, [0.0, 0.0, 0.0, 1.0]);
        this._cgl.gl.blitFramebuffer(0, 0, this._width, this._height, 0, 0, this._width, this._height, this._cgl.gl.COLOR_BUFFER_BIT | this._cgl.gl.DEPTH_BUFFER_BIT, this._cgl.gl.NEAREST);
    }
    else
    {
        this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this.Framebuffer2BlittingFramebuffer);
        this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.RENDERBUFFER, this._depthRenderbuffer);

        this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this.Framebuffer2FinalFramebuffer);
        this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.TEXTURE_2D, this._textureDepth.tex, 0);

        for (let i = 0; i < this._numRenderBuffers; i++)
        {
            this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this.Framebuffer2BlittingFramebuffer);
            this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.RENDERBUFFER, this._colorRenderbuffers[i]);


            this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this.Framebuffer2FinalFramebuffer);
            this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.TEXTURE_2D, this._colorTextures[i].tex, 0);

            this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);

            this._cgl.gl.bindFramebuffer(this._cgl.gl.READ_FRAMEBUFFER, this.Framebuffer2BlittingFramebuffer);
            this._cgl.gl.bindFramebuffer(this._cgl.gl.DRAW_FRAMEBUFFER, this.Framebuffer2FinalFramebuffer);

            // this._cgl.gl.clearBufferfv(this._cgl.gl.COLOR, i, [0.0, 0.0, 0.0, 1.0]);



            let flags = this._cgl.gl.COLOR_BUFFER_BIT;
            if (i == 0) flags |= this._cgl.gl.DEPTH_BUFFER_BIT;

            this._cgl.gl.blitFramebuffer(0, 0, this._width, this._height, 0, 0, this._width, this._height, flags, this._cgl.gl.NEAREST);
        }
    }

    this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.popGlFrameBuffer());
    this._cgl.popFrameBuffer();

    this._cgl.popModelMatrix();
    // this._cgl.resetViewPort();
    this._cgl.popViewPort();


    if (this._colorTextures[0].filter == Texture.FILTER_MIPMAP)
    {
        for (let i = 0; i < this._numRenderBuffers; i++)
        {
            this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, this._colorTextures[i].tex);
            this._colorTextures[i].updateMipMap();
            this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, null);
        }
    }
};



/// ///////

;// CONCATENATED MODULE: ./src/core/cgl/cgl_marker.js
const Marker = function (_cgl) // deprecated...
{
    this.draw = function (cgl, _size, depthTest) {};
};

const WirePoint = function (cgl) // deprecated...
{
    this.render = function (_cgl, _size) {};
};

const WireCube = function (cgl) // deprecated...
{
    this.render = function (_cgl, sizeX, sizeY, sizeZ) {};
};

;// CONCATENATED MODULE: ./src/core/cgl/cgl_unicolorshader.js


class UniColorShader
{
    constructor(_cgl)
    {
        this.shader = new CGL.Shader(_cgl, "markermaterial");

        const frag = ""
            .endl() + "void main()"
            .endl() + "{"
            .endl() + "    outColor = vec4(color.rgb,1.0);"
            .endl() + "}";


        const vert = ""
            .endl() + "IN vec3 vPosition;"
            .endl() + "UNI mat4 projMatrix;"
            .endl() + "UNI mat4 mvMatrix;"

            .endl() + "void main()"
            .endl() + "{"
            .endl() + "   gl_Position = projMatrix * mvMatrix * vec4(vPosition,1.0);"
            .endl() + "}";

        this.shader.setSource(vert, frag);
        this.coloruni = this.shader.addUniformFrag("4f", "color", [1, 0.777, 1, 1]);
    }

    setColor(r, g, b, a)
    {
        this.coloruni.set(r, g, b, a);
    }
}

;// CONCATENATED MODULE: ./src/core/cgl/index.js






















const cgl_CGL = {
    "Framebuffer": Framebuffer,
    "Framebuffer2": Framebuffer2,
    "Geometry": Geometry,
    "BoundingBox": BoundingBox,
    "Marker": Marker,
    "WirePoint": WirePoint,
    "WireCube": WireCube,
    "MatrixStack": MatrixStack,
    "Mesh": Mesh,
    "MESH": MESH,
    "ShaderLibMods": ShaderLibMods,
    "Shader": Shader,
    "Uniform": Uniform,
    "MESHES": MESHES,
    "Context": Context,
    "Texture": Texture,
    "TextureEffect": TextureEffect,
    "isWindows": isWindows,
    "getWheelSpeed": getWheelSpeed,
    "getWheelDelta": getWheelDelta,
    "onLoadingAssetsFinished": onLoadingAssetsFinished,
    "ProfileData": ProfileData,
    "UniColorShader": UniColorShader,
    ...constants_CONSTANTS.BLEND_MODES,
    ...constants_CONSTANTS.SHADER,
    ...constants_CONSTANTS.MATH,
    ...constants_CONSTANTS.BLEND_MODES,
};

window.CGL = cgl_CGL;





;// CONCATENATED MODULE: ./src/core/index.js

















window.CABLES = window.CABLES || {};

CABLES.CGL = cgl_CGL;
CABLES.CG = CG;
CABLES.CGP = cgp_CGP;
CABLES.EMBED = EMBED;
CABLES.Link = Link;
CABLES.Port = Port;
CABLES.Op = Op;
CABLES.Profiler = Profiler;
CABLES.Patch = core_patch;
CABLES.Timer = Timer;
CABLES.WEBAUDIO = WEBAUDIO;
CABLES.Variable = Variable;
CABLES.LoadingStatus = LoadingStatus;
CABLES.now = now;
CABLES.internalNow = internalNow;



CABLES = Object.assign(CABLES,
    utils_namespaceObject,
    anim_namespaceObject,
    CONSTANTS.PORT,
    CONSTANTS.PACO,
    CONSTANTS.ANIM,
    CONSTANTS.OP
);

/* harmony default export */ const core = (CABLES);

if (!(function () { return !this; }())) console.warn("not in strict mode: index core"); // eslint-disable-line

CABLES = __webpack_exports__["default"];
/******/ })()
;


var CABLES = CABLES || {}; CABLES.build = {"timestamp":1736760273867,"created":"2025-01-13T09:24:33.867Z","git":{"branch":"master","commit":"0e07848fd62e35a0a77f09c4c90a3fcbd6cb9f8f","date":"1736756567","message":"canvasinfo"}};
(()=>{"use strict";var t={d:(n,a)=>{for(var r in a)t.o(a,r)&&!t.o(n,r)&&Object.defineProperty(n,r,{enumerable:!0,get:a[r]})},o:(t,n)=>Object.prototype.hasOwnProperty.call(t,n),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},n={};t.r(n),t.d(n,{ARRAY_TYPE:()=>f,EPSILON:()=>M,RANDOM:()=>l,equals:()=>d,setMatrixArrayType:()=>v,toRadian:()=>m});var a={};t.r(a),t.d(a,{LDU:()=>j,add:()=>z,adjoint:()=>S,clone:()=>y,copy:()=>p,create:()=>x,determinant:()=>R,equals:()=>Y,exactEquals:()=>Q,frob:()=>V,fromRotation:()=>D,fromScaling:()=>F,fromValues:()=>w,identity:()=>q,invert:()=>P,mul:()=>_,multiply:()=>T,multiplyScalar:()=>X,multiplyScalarAndAdd:()=>Z,rotate:()=>I,scale:()=>E,set:()=>g,str:()=>L,sub:()=>B,subtract:()=>O,transpose:()=>A});var r={};t.r(r),t.d(r,{add:()=>it,clone:()=>k,copy:()=>U,create:()=>N,determinant:()=>J,equals:()=>ft,exactEquals:()=>Mt,frob:()=>ot,fromRotation:()=>at,fromScaling:()=>rt,fromTranslation:()=>ut,fromValues:()=>C,identity:()=>W,invert:()=>H,mul:()=>lt,multiply:()=>K,multiplyScalar:()=>ct,multiplyScalarAndAdd:()=>st,rotate:()=>$,scale:()=>tt,set:()=>G,str:()=>et,sub:()=>vt,subtract:()=>ht,translate:()=>nt});var u={};t.r(u),t.d(u,{add:()=>Yt,adjoint:()=>At,clone:()=>dt,copy:()=>xt,create:()=>bt,determinant:()=>Pt,equals:()=>Nt,exactEquals:()=>Bt,frob:()=>Qt,fromMat2d:()=>Lt,fromMat4:()=>mt,fromQuat:()=>Vt,fromRotation:()=>Dt,fromScaling:()=>Ft,fromTranslation:()=>Et,fromValues:()=>yt,identity:()=>qt,invert:()=>gt,mul:()=>kt,multiply:()=>St,multiplyScalar:()=>Zt,multiplyScalarAndAdd:()=>_t,normalFromMat4:()=>jt,projection:()=>zt,rotate:()=>Tt,scale:()=>It,set:()=>pt,str:()=>Ot,sub:()=>Ut,subtract:()=>Xt,translate:()=>Rt,transpose:()=>wt});var e={};t.r(e),t.d(e,{add:()=>Ln,adjoint:()=>nn,clone:()=>Ct,copy:()=>Gt,create:()=>Wt,determinant:()=>an,equals:()=>Qn,exactEquals:()=>On,frob:()=>Fn,fromQuat:()=>An,fromQuat2:()=>xn,fromRotation:()=>ln,fromRotationTranslation:()=>dn,fromRotationTranslationScale:()=>wn,fromRotationTranslationScaleOrigin:()=>gn,fromScaling:()=>fn,fromTranslation:()=>Mn,fromValues:()=>Ht,fromXRotation:()=>vn,fromYRotation:()=>bn,fromZRotation:()=>mn,frustum:()=>Pn,getRotation:()=>qn,getScaling:()=>pn,getTranslation:()=>yn,identity:()=>Kt,invert:()=>tn,lookAt:()=>In,mul:()=>Yn,multiply:()=>rn,multiplyScalar:()=>jn,multiplyScalarAndAdd:()=>zn,ortho:()=>Tn,perspective:()=>Sn,perspectiveFromFieldOfView:()=>Rn,rotate:()=>on,rotateX:()=>hn,rotateY:()=>cn,rotateZ:()=>sn,scale:()=>en,set:()=>Jt,str:()=>Dn,sub:()=>Xn,subtract:()=>Vn,targetTo:()=>En,translate:()=>un,transpose:()=>$t});var o={};t.r(o),t.d(o,{add:()=>Wn,angle:()=>wa,bezier:()=>va,ceil:()=>Jn,clone:()=>_n,copy:()=>kn,create:()=>Zn,cross:()=>Ma,dist:()=>Da,distance:()=>ua,div:()=>Ea,divide:()=>Hn,dot:()=>sa,equals:()=>Sa,exactEquals:()=>Pa,floor:()=>Kn,forEach:()=>ja,fromValues:()=>Nn,hermite:()=>la,inverse:()=>ha,len:()=>La,length:()=>Bn,lerp:()=>fa,max:()=>ta,min:()=>$n,mul:()=>Ia,multiply:()=>Gn,negate:()=>ia,normalize:()=>ca,random:()=>ba,rotateX:()=>ya,rotateY:()=>pa,rotateZ:()=>qa,round:()=>na,scale:()=>aa,scaleAndAdd:()=>ra,set:()=>Un,sqrDist:()=>Fa,sqrLen:()=>Va,squaredDistance:()=>ea,squaredLength:()=>oa,str:()=>Aa,sub:()=>Ta,subtract:()=>Cn,transformMat3:()=>da,transformMat4:()=>ma,transformQuat:()=>xa,zero:()=>ga});var i={};t.r(i),t.d(i,{add:()=>Za,ceil:()=>ka,clone:()=>Oa,copy:()=>Ya,create:()=>za,cross:()=>or,dist:()=>xr,distance:()=>Ka,div:()=>dr,divide:()=>Na,dot:()=>er,equals:()=>vr,exactEquals:()=>lr,floor:()=>Ua,forEach:()=>wr,fromValues:()=>Qa,inverse:()=>rr,len:()=>pr,length:()=>tr,lerp:()=>ir,max:()=>Ca,min:()=>Wa,mul:()=>mr,multiply:()=>Ba,negate:()=>ar,normalize:()=>ur,random:()=>hr,round:()=>Ga,scale:()=>Ha,scaleAndAdd:()=>Ja,set:()=>Xa,sqrDist:()=>yr,sqrLen:()=>qr,squaredDistance:()=>$a,squaredLength:()=>nr,str:()=>fr,sub:()=>br,subtract:()=>_a,transformMat4:()=>cr,transformQuat:()=>sr,zero:()=>Mr});var h={};t.r(h),t.d(h,{add:()=>$r,calculateW:()=>Fr,clone:()=>Gr,conjugate:()=>Yr,copy:()=>Jr,create:()=>gr,dot:()=>au,equals:()=>su,exactEquals:()=>cu,exp:()=>Lr,fromEuler:()=>Zr,fromMat3:()=>Xr,fromValues:()=>Hr,getAngle:()=>Rr,getAxisAngle:()=>Sr,identity:()=>Ar,invert:()=>Qr,len:()=>eu,length:()=>uu,lerp:()=>ru,ln:()=>Vr,mul:()=>tu,multiply:()=>Tr,normalize:()=>hu,pow:()=>jr,random:()=>Or,rotateX:()=>Ir,rotateY:()=>Er,rotateZ:()=>Dr,rotationTo:()=>Mu,scale:()=>nu,set:()=>Kr,setAxes:()=>lu,setAxisAngle:()=>Pr,slerp:()=>zr,sqlerp:()=>fu,sqrLen:()=>iu,squaredLength:()=>ou,str:()=>_r});var c={};t.r(c),t.d(c,{add:()=>Ou,clone:()=>bu,conjugate:()=>Nu,copy:()=>wu,create:()=>vu,dot:()=>Zu,equals:()=>Ku,exactEquals:()=>Ju,fromMat4:()=>qu,fromRotation:()=>pu,fromRotationTranslation:()=>xu,fromRotationTranslationValues:()=>du,fromTranslation:()=>yu,fromValues:()=>mu,getDual:()=>Su,getReal:()=>Pu,getTranslation:()=>Iu,identity:()=>gu,invert:()=>Bu,len:()=>Uu,length:()=>ku,lerp:()=>_u,mul:()=>Yu,multiply:()=>Qu,normalize:()=>Gu,rotateAroundAxis:()=>zu,rotateByQuatAppend:()=>Vu,rotateByQuatPrepend:()=>ju,rotateX:()=>Du,rotateY:()=>Fu,rotateZ:()=>Lu,scale:()=>Xu,set:()=>Au,setDual:()=>Tu,setReal:()=>Ru,sqrLen:()=>Cu,squaredLength:()=>Wu,str:()=>Hu,translate:()=>Eu});var s={};t.r(s),t.d(s,{add:()=>ue,angle:()=>De,ceil:()=>he,clone:()=>te,copy:()=>ae,create:()=>$u,cross:()=>ge,dist:()=>Xe,distance:()=>be,div:()=>Ye,divide:()=>ie,dot:()=>we,equals:()=>je,exactEquals:()=>Ve,floor:()=>ce,forEach:()=>Be,fromValues:()=>ne,inverse:()=>pe,len:()=>ze,length:()=>de,lerp:()=>Ae,max:()=>Me,min:()=>se,mul:()=>Qe,multiply:()=>oe,negate:()=>ye,normalize:()=>qe,random:()=>Pe,rotate:()=>Ee,round:()=>fe,scale:()=>le,scaleAndAdd:()=>ve,set:()=>re,sqrDist:()=>Ze,sqrLen:()=>_e,squaredDistance:()=>me,squaredLength:()=>xe,str:()=>Le,sub:()=>Oe,subtract:()=>ee,transformMat2:()=>Se,transformMat2d:()=>Re,transformMat3:()=>Te,transformMat4:()=>Ie,zero:()=>Fe});var M=1e-6,f="undefined"!=typeof Float32Array?Float32Array:Array,l=Math.random;function v(t){f=t}var b=Math.PI/180;function m(t){return t*b}function d(t,n){return Math.abs(t-n)<=M*Math.max(1,Math.abs(t),Math.abs(n))}function x(){var t=new f(4);return f!=Float32Array&&(t[1]=0,t[2]=0),t[0]=1,t[3]=1,t}function y(t){var n=new f(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n}function p(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t}function q(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t}function w(t,n,a,r){var u=new f(4);return u[0]=t,u[1]=n,u[2]=a,u[3]=r,u}function g(t,n,a,r,u){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t}function A(t,n){if(t===n){var a=n[1];t[1]=n[2],t[2]=a}else t[0]=n[0],t[1]=n[2],t[2]=n[1],t[3]=n[3];return t}function P(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*e-u*r;return o?(o=1/o,t[0]=e*o,t[1]=-r*o,t[2]=-u*o,t[3]=a*o,t):null}function S(t,n){var a=n[0];return t[0]=n[3],t[1]=-n[1],t[2]=-n[2],t[3]=a,t}function R(t){return t[0]*t[3]-t[2]*t[1]}function T(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],h=a[1],c=a[2],s=a[3];return t[0]=r*i+e*h,t[1]=u*i+o*h,t[2]=r*c+e*s,t[3]=u*c+o*s,t}function I(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),h=Math.cos(a);return t[0]=r*h+e*i,t[1]=u*h+o*i,t[2]=r*-i+e*h,t[3]=u*-i+o*h,t}function E(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],h=a[1];return t[0]=r*i,t[1]=u*i,t[2]=e*h,t[3]=o*h,t}function D(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=-a,t[3]=r,t}function F(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t}function L(t){return"mat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"}function V(t){return Math.hypot(t[0],t[1],t[2],t[3])}function j(t,n,a,r){return t[2]=r[2]/r[0],a[0]=r[0],a[1]=r[1],a[3]=r[3]-t[2]*a[1],[t,n,a]}function z(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t}function O(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t}function Q(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]}function Y(t,n){var a=t[0],r=t[1],u=t[2],e=t[3],o=n[0],i=n[1],h=n[2],c=n[3];return Math.abs(a-o)<=M*Math.max(1,Math.abs(a),Math.abs(o))&&Math.abs(r-i)<=M*Math.max(1,Math.abs(r),Math.abs(i))&&Math.abs(u-h)<=M*Math.max(1,Math.abs(u),Math.abs(h))&&Math.abs(e-c)<=M*Math.max(1,Math.abs(e),Math.abs(c))}function X(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t}function Z(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t}Math.hypot||(Math.hypot=function(){for(var t=0,n=arguments.length;n--;)t+=arguments[n]*arguments[n];return Math.sqrt(t)});var _=T,B=O;function N(){var t=new f(6);return f!=Float32Array&&(t[1]=0,t[2]=0,t[4]=0,t[5]=0),t[0]=1,t[3]=1,t}function k(t){var n=new f(6);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n}function U(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t}function W(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t}function C(t,n,a,r,u,e){var o=new f(6);return o[0]=t,o[1]=n,o[2]=a,o[3]=r,o[4]=u,o[5]=e,o}function G(t,n,a,r,u,e,o){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t}function H(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=a*e-r*u;return h?(h=1/h,t[0]=e*h,t[1]=-r*h,t[2]=-u*h,t[3]=a*h,t[4]=(u*i-e*o)*h,t[5]=(r*o-a*i)*h,t):null}function J(t){return t[0]*t[3]-t[1]*t[2]}function K(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=a[0],s=a[1],M=a[2],f=a[3],l=a[4],v=a[5];return t[0]=r*c+e*s,t[1]=u*c+o*s,t[2]=r*M+e*f,t[3]=u*M+o*f,t[4]=r*l+e*v+i,t[5]=u*l+o*v+h,t}function $(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=Math.sin(a),s=Math.cos(a);return t[0]=r*s+e*c,t[1]=u*s+o*c,t[2]=r*-c+e*s,t[3]=u*-c+o*s,t[4]=i,t[5]=h,t}function tt(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=a[0],s=a[1];return t[0]=r*c,t[1]=u*c,t[2]=e*s,t[3]=o*s,t[4]=i,t[5]=h,t}function nt(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=a[0],s=a[1];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=r*c+e*s+i,t[5]=u*c+o*s+h,t}function at(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=-a,t[3]=r,t[4]=0,t[5]=0,t}function rt(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t[4]=0,t[5]=0,t}function ut(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=n[0],t[5]=n[1],t}function et(t){return"mat2d("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+")"}function ot(t){return Math.hypot(t[0],t[1],t[2],t[3],t[4],t[5],1)}function it(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t}function ht(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t}function ct(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t}function st(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t}function Mt(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]}function ft(t,n){var a=t[0],r=t[1],u=t[2],e=t[3],o=t[4],i=t[5],h=n[0],c=n[1],s=n[2],f=n[3],l=n[4],v=n[5];return Math.abs(a-h)<=M*Math.max(1,Math.abs(a),Math.abs(h))&&Math.abs(r-c)<=M*Math.max(1,Math.abs(r),Math.abs(c))&&Math.abs(u-s)<=M*Math.max(1,Math.abs(u),Math.abs(s))&&Math.abs(e-f)<=M*Math.max(1,Math.abs(e),Math.abs(f))&&Math.abs(o-l)<=M*Math.max(1,Math.abs(o),Math.abs(l))&&Math.abs(i-v)<=M*Math.max(1,Math.abs(i),Math.abs(v))}var lt=K,vt=ht;function bt(){var t=new f(9);return f!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[5]=0,t[6]=0,t[7]=0),t[0]=1,t[4]=1,t[8]=1,t}function mt(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[4],t[4]=n[5],t[5]=n[6],t[6]=n[8],t[7]=n[9],t[8]=n[10],t}function dt(t){var n=new f(9);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n}function xt(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t}function yt(t,n,a,r,u,e,o,i,h){var c=new f(9);return c[0]=t,c[1]=n,c[2]=a,c[3]=r,c[4]=u,c[5]=e,c[6]=o,c[7]=i,c[8]=h,c}function pt(t,n,a,r,u,e,o,i,h,c){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=h,t[8]=c,t}function qt(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function wt(t,n){if(t===n){var a=n[1],r=n[2],u=n[5];t[1]=n[3],t[2]=n[6],t[3]=a,t[5]=n[7],t[6]=r,t[7]=u}else t[0]=n[0],t[1]=n[3],t[2]=n[6],t[3]=n[1],t[4]=n[4],t[5]=n[7],t[6]=n[2],t[7]=n[5],t[8]=n[8];return t}function gt(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8],M=s*o-i*c,f=-s*e+i*h,l=c*e-o*h,v=a*M+r*f+u*l;return v?(v=1/v,t[0]=M*v,t[1]=(-s*r+u*c)*v,t[2]=(i*r-u*o)*v,t[3]=f*v,t[4]=(s*a-u*h)*v,t[5]=(-i*a+u*e)*v,t[6]=l*v,t[7]=(-c*a+r*h)*v,t[8]=(o*a-r*e)*v,t):null}function At(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8];return t[0]=o*s-i*c,t[1]=u*c-r*s,t[2]=r*i-u*o,t[3]=i*h-e*s,t[4]=a*s-u*h,t[5]=u*e-a*i,t[6]=e*c-o*h,t[7]=r*h-a*c,t[8]=a*o-r*e,t}function Pt(t){var n=t[0],a=t[1],r=t[2],u=t[3],e=t[4],o=t[5],i=t[6],h=t[7],c=t[8];return n*(c*e-o*h)+a*(-c*u+o*i)+r*(h*u-e*i)}function St(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=a[0],l=a[1],v=a[2],b=a[3],m=a[4],d=a[5],x=a[6],y=a[7],p=a[8];return t[0]=f*r+l*o+v*c,t[1]=f*u+l*i+v*s,t[2]=f*e+l*h+v*M,t[3]=b*r+m*o+d*c,t[4]=b*u+m*i+d*s,t[5]=b*e+m*h+d*M,t[6]=x*r+y*o+p*c,t[7]=x*u+y*i+p*s,t[8]=x*e+y*h+p*M,t}function Rt(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=a[0],l=a[1];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=i,t[5]=h,t[6]=f*r+l*o+c,t[7]=f*u+l*i+s,t[8]=f*e+l*h+M,t}function Tt(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=Math.sin(a),l=Math.cos(a);return t[0]=l*r+f*o,t[1]=l*u+f*i,t[2]=l*e+f*h,t[3]=l*o-f*r,t[4]=l*i-f*u,t[5]=l*h-f*e,t[6]=c,t[7]=s,t[8]=M,t}function It(t,n,a){var r=a[0],u=a[1];return t[0]=r*n[0],t[1]=r*n[1],t[2]=r*n[2],t[3]=u*n[3],t[4]=u*n[4],t[5]=u*n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t}function Et(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=n[0],t[7]=n[1],t[8]=1,t}function Dt(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=0,t[3]=-a,t[4]=r,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function Ft(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=n[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function Lt(t,n){return t[0]=n[0],t[1]=n[1],t[2]=0,t[3]=n[2],t[4]=n[3],t[5]=0,t[6]=n[4],t[7]=n[5],t[8]=1,t}function Vt(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a+a,i=r+r,h=u+u,c=a*o,s=r*o,M=r*i,f=u*o,l=u*i,v=u*h,b=e*o,m=e*i,d=e*h;return t[0]=1-M-v,t[3]=s-d,t[6]=f+m,t[1]=s+d,t[4]=1-c-v,t[7]=l-b,t[2]=f-m,t[5]=l+b,t[8]=1-c-M,t}function jt(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15],x=a*i-r*o,y=a*h-u*o,p=a*c-e*o,q=r*h-u*i,w=r*c-e*i,g=u*c-e*h,A=s*b-M*v,P=s*m-f*v,S=s*d-l*v,R=M*m-f*b,T=M*d-l*b,I=f*d-l*m,E=x*I-y*T+p*R+q*S-w*P+g*A;return E?(E=1/E,t[0]=(i*I-h*T+c*R)*E,t[1]=(h*S-o*I-c*P)*E,t[2]=(o*T-i*S+c*A)*E,t[3]=(u*T-r*I-e*R)*E,t[4]=(a*I-u*S+e*P)*E,t[5]=(r*S-a*T-e*A)*E,t[6]=(b*g-m*w+d*q)*E,t[7]=(m*p-v*g-d*y)*E,t[8]=(v*w-b*p+d*x)*E,t):null}function zt(t,n,a){return t[0]=2/n,t[1]=0,t[2]=0,t[3]=0,t[4]=-2/a,t[5]=0,t[6]=-1,t[7]=1,t[8]=1,t}function Ot(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"}function Qt(t){return Math.hypot(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8])}function Yt(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t[6]=n[6]+a[6],t[7]=n[7]+a[7],t[8]=n[8]+a[8],t}function Xt(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t[6]=n[6]-a[6],t[7]=n[7]-a[7],t[8]=n[8]-a[8],t}function Zt(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t[6]=n[6]*a,t[7]=n[7]*a,t[8]=n[8]*a,t}function _t(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t[6]=n[6]+a[6]*r,t[7]=n[7]+a[7]*r,t[8]=n[8]+a[8]*r,t}function Bt(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]}function Nt(t,n){var a=t[0],r=t[1],u=t[2],e=t[3],o=t[4],i=t[5],h=t[6],c=t[7],s=t[8],f=n[0],l=n[1],v=n[2],b=n[3],m=n[4],d=n[5],x=n[6],y=n[7],p=n[8];return Math.abs(a-f)<=M*Math.max(1,Math.abs(a),Math.abs(f))&&Math.abs(r-l)<=M*Math.max(1,Math.abs(r),Math.abs(l))&&Math.abs(u-v)<=M*Math.max(1,Math.abs(u),Math.abs(v))&&Math.abs(e-b)<=M*Math.max(1,Math.abs(e),Math.abs(b))&&Math.abs(o-m)<=M*Math.max(1,Math.abs(o),Math.abs(m))&&Math.abs(i-d)<=M*Math.max(1,Math.abs(i),Math.abs(d))&&Math.abs(h-x)<=M*Math.max(1,Math.abs(h),Math.abs(x))&&Math.abs(c-y)<=M*Math.max(1,Math.abs(c),Math.abs(y))&&Math.abs(s-p)<=M*Math.max(1,Math.abs(s),Math.abs(p))}var kt=St,Ut=Xt;function Wt(){var t=new f(16);return f!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0),t[0]=1,t[5]=1,t[10]=1,t[15]=1,t}function Ct(t){var n=new f(16);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n[9]=t[9],n[10]=t[10],n[11]=t[11],n[12]=t[12],n[13]=t[13],n[14]=t[14],n[15]=t[15],n}function Gt(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t}function Ht(t,n,a,r,u,e,o,i,h,c,s,M,l,v,b,m){var d=new f(16);return d[0]=t,d[1]=n,d[2]=a,d[3]=r,d[4]=u,d[5]=e,d[6]=o,d[7]=i,d[8]=h,d[9]=c,d[10]=s,d[11]=M,d[12]=l,d[13]=v,d[14]=b,d[15]=m,d}function Jt(t,n,a,r,u,e,o,i,h,c,s,M,f,l,v,b,m){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=h,t[8]=c,t[9]=s,t[10]=M,t[11]=f,t[12]=l,t[13]=v,t[14]=b,t[15]=m,t}function Kt(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function $t(t,n){if(t===n){var a=n[1],r=n[2],u=n[3],e=n[6],o=n[7],i=n[11];t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=a,t[6]=n[9],t[7]=n[13],t[8]=r,t[9]=e,t[11]=n[14],t[12]=u,t[13]=o,t[14]=i}else t[0]=n[0],t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=n[1],t[5]=n[5],t[6]=n[9],t[7]=n[13],t[8]=n[2],t[9]=n[6],t[10]=n[10],t[11]=n[14],t[12]=n[3],t[13]=n[7],t[14]=n[11],t[15]=n[15];return t}function tn(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15],x=a*i-r*o,y=a*h-u*o,p=a*c-e*o,q=r*h-u*i,w=r*c-e*i,g=u*c-e*h,A=s*b-M*v,P=s*m-f*v,S=s*d-l*v,R=M*m-f*b,T=M*d-l*b,I=f*d-l*m,E=x*I-y*T+p*R+q*S-w*P+g*A;return E?(E=1/E,t[0]=(i*I-h*T+c*R)*E,t[1]=(u*T-r*I-e*R)*E,t[2]=(b*g-m*w+d*q)*E,t[3]=(f*w-M*g-l*q)*E,t[4]=(h*S-o*I-c*P)*E,t[5]=(a*I-u*S+e*P)*E,t[6]=(m*p-v*g-d*y)*E,t[7]=(s*g-f*p+l*y)*E,t[8]=(o*T-i*S+c*A)*E,t[9]=(r*S-a*T-e*A)*E,t[10]=(v*w-b*p+d*x)*E,t[11]=(M*p-s*w-l*x)*E,t[12]=(i*P-o*R-h*A)*E,t[13]=(a*R-r*P+u*A)*E,t[14]=(b*y-v*q-m*x)*E,t[15]=(s*q-M*y+f*x)*E,t):null}function nn(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15];return t[0]=i*(f*d-l*m)-M*(h*d-c*m)+b*(h*l-c*f),t[1]=-(r*(f*d-l*m)-M*(u*d-e*m)+b*(u*l-e*f)),t[2]=r*(h*d-c*m)-i*(u*d-e*m)+b*(u*c-e*h),t[3]=-(r*(h*l-c*f)-i*(u*l-e*f)+M*(u*c-e*h)),t[4]=-(o*(f*d-l*m)-s*(h*d-c*m)+v*(h*l-c*f)),t[5]=a*(f*d-l*m)-s*(u*d-e*m)+v*(u*l-e*f),t[6]=-(a*(h*d-c*m)-o*(u*d-e*m)+v*(u*c-e*h)),t[7]=a*(h*l-c*f)-o*(u*l-e*f)+s*(u*c-e*h),t[8]=o*(M*d-l*b)-s*(i*d-c*b)+v*(i*l-c*M),t[9]=-(a*(M*d-l*b)-s*(r*d-e*b)+v*(r*l-e*M)),t[10]=a*(i*d-c*b)-o*(r*d-e*b)+v*(r*c-e*i),t[11]=-(a*(i*l-c*M)-o*(r*l-e*M)+s*(r*c-e*i)),t[12]=-(o*(M*m-f*b)-s*(i*m-h*b)+v*(i*f-h*M)),t[13]=a*(M*m-f*b)-s*(r*m-u*b)+v*(r*f-u*M),t[14]=-(a*(i*m-h*b)-o*(r*m-u*b)+v*(r*h-u*i)),t[15]=a*(i*f-h*M)-o*(r*f-u*M)+s*(r*h-u*i),t}function an(t){var n=t[0],a=t[1],r=t[2],u=t[3],e=t[4],o=t[5],i=t[6],h=t[7],c=t[8],s=t[9],M=t[10],f=t[11],l=t[12],v=t[13],b=t[14],m=t[15];return(n*o-a*e)*(M*m-f*b)-(n*i-r*e)*(s*m-f*v)+(n*h-u*e)*(s*b-M*v)+(a*i-r*o)*(c*m-f*l)-(a*h-u*o)*(c*b-M*l)+(r*h-u*i)*(c*v-s*l)}function rn(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=n[9],l=n[10],v=n[11],b=n[12],m=n[13],d=n[14],x=n[15],y=a[0],p=a[1],q=a[2],w=a[3];return t[0]=y*r+p*i+q*M+w*b,t[1]=y*u+p*h+q*f+w*m,t[2]=y*e+p*c+q*l+w*d,t[3]=y*o+p*s+q*v+w*x,y=a[4],p=a[5],q=a[6],w=a[7],t[4]=y*r+p*i+q*M+w*b,t[5]=y*u+p*h+q*f+w*m,t[6]=y*e+p*c+q*l+w*d,t[7]=y*o+p*s+q*v+w*x,y=a[8],p=a[9],q=a[10],w=a[11],t[8]=y*r+p*i+q*M+w*b,t[9]=y*u+p*h+q*f+w*m,t[10]=y*e+p*c+q*l+w*d,t[11]=y*o+p*s+q*v+w*x,y=a[12],p=a[13],q=a[14],w=a[15],t[12]=y*r+p*i+q*M+w*b,t[13]=y*u+p*h+q*f+w*m,t[14]=y*e+p*c+q*l+w*d,t[15]=y*o+p*s+q*v+w*x,t}function un(t,n,a){var r,u,e,o,i,h,c,s,M,f,l,v,b=a[0],m=a[1],d=a[2];return n===t?(t[12]=n[0]*b+n[4]*m+n[8]*d+n[12],t[13]=n[1]*b+n[5]*m+n[9]*d+n[13],t[14]=n[2]*b+n[6]*m+n[10]*d+n[14],t[15]=n[3]*b+n[7]*m+n[11]*d+n[15]):(r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=n[9],l=n[10],v=n[11],t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=i,t[5]=h,t[6]=c,t[7]=s,t[8]=M,t[9]=f,t[10]=l,t[11]=v,t[12]=r*b+i*m+M*d+n[12],t[13]=u*b+h*m+f*d+n[13],t[14]=e*b+c*m+l*d+n[14],t[15]=o*b+s*m+v*d+n[15]),t}function en(t,n,a){var r=a[0],u=a[1],e=a[2];return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t[4]=n[4]*u,t[5]=n[5]*u,t[6]=n[6]*u,t[7]=n[7]*u,t[8]=n[8]*e,t[9]=n[9]*e,t[10]=n[10]*e,t[11]=n[11]*e,t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t}function on(t,n,a,r){var u,e,o,i,h,c,s,f,l,v,b,m,d,x,y,p,q,w,g,A,P,S,R,T,I=r[0],E=r[1],D=r[2],F=Math.hypot(I,E,D);return F<M?null:(I*=F=1/F,E*=F,D*=F,u=Math.sin(a),o=1-(e=Math.cos(a)),i=n[0],h=n[1],c=n[2],s=n[3],f=n[4],l=n[5],v=n[6],b=n[7],m=n[8],d=n[9],x=n[10],y=n[11],p=I*I*o+e,q=E*I*o+D*u,w=D*I*o-E*u,g=I*E*o-D*u,A=E*E*o+e,P=D*E*o+I*u,S=I*D*o+E*u,R=E*D*o-I*u,T=D*D*o+e,t[0]=i*p+f*q+m*w,t[1]=h*p+l*q+d*w,t[2]=c*p+v*q+x*w,t[3]=s*p+b*q+y*w,t[4]=i*g+f*A+m*P,t[5]=h*g+l*A+d*P,t[6]=c*g+v*A+x*P,t[7]=s*g+b*A+y*P,t[8]=i*S+f*R+m*T,t[9]=h*S+l*R+d*T,t[10]=c*S+v*R+x*T,t[11]=s*S+b*R+y*T,n!==t&&(t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15]),t)}function hn(t,n,a){var r=Math.sin(a),u=Math.cos(a),e=n[4],o=n[5],i=n[6],h=n[7],c=n[8],s=n[9],M=n[10],f=n[11];return n!==t&&(t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15]),t[4]=e*u+c*r,t[5]=o*u+s*r,t[6]=i*u+M*r,t[7]=h*u+f*r,t[8]=c*u-e*r,t[9]=s*u-o*r,t[10]=M*u-i*r,t[11]=f*u-h*r,t}function cn(t,n,a){var r=Math.sin(a),u=Math.cos(a),e=n[0],o=n[1],i=n[2],h=n[3],c=n[8],s=n[9],M=n[10],f=n[11];return n!==t&&(t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15]),t[0]=e*u-c*r,t[1]=o*u-s*r,t[2]=i*u-M*r,t[3]=h*u-f*r,t[8]=e*r+c*u,t[9]=o*r+s*u,t[10]=i*r+M*u,t[11]=h*r+f*u,t}function sn(t,n,a){var r=Math.sin(a),u=Math.cos(a),e=n[0],o=n[1],i=n[2],h=n[3],c=n[4],s=n[5],M=n[6],f=n[7];return n!==t&&(t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15]),t[0]=e*u+c*r,t[1]=o*u+s*r,t[2]=i*u+M*r,t[3]=h*u+f*r,t[4]=c*u-e*r,t[5]=s*u-o*r,t[6]=M*u-i*r,t[7]=f*u-h*r,t}function Mn(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=n[0],t[13]=n[1],t[14]=n[2],t[15]=1,t}function fn(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=n[1],t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=n[2],t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function ln(t,n,a){var r,u,e,o=a[0],i=a[1],h=a[2],c=Math.hypot(o,i,h);return c<M?null:(o*=c=1/c,i*=c,h*=c,r=Math.sin(n),e=1-(u=Math.cos(n)),t[0]=o*o*e+u,t[1]=i*o*e+h*r,t[2]=h*o*e-i*r,t[3]=0,t[4]=o*i*e-h*r,t[5]=i*i*e+u,t[6]=h*i*e+o*r,t[7]=0,t[8]=o*h*e+i*r,t[9]=i*h*e-o*r,t[10]=h*h*e+u,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t)}function vn(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=r,t[6]=a,t[7]=0,t[8]=0,t[9]=-a,t[10]=r,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function bn(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=0,t[2]=-a,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=a,t[9]=0,t[10]=r,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function mn(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=0,t[3]=0,t[4]=-a,t[5]=r,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function dn(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=r+r,h=u+u,c=e+e,s=r*i,M=r*h,f=r*c,l=u*h,v=u*c,b=e*c,m=o*i,d=o*h,x=o*c;return t[0]=1-(l+b),t[1]=M+x,t[2]=f-d,t[3]=0,t[4]=M-x,t[5]=1-(s+b),t[6]=v+m,t[7]=0,t[8]=f+d,t[9]=v-m,t[10]=1-(s+l),t[11]=0,t[12]=a[0],t[13]=a[1],t[14]=a[2],t[15]=1,t}function xn(t,n){var a=new f(3),r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=r*r+u*u+e*e+o*o;return M>0?(a[0]=2*(i*o+s*r+h*e-c*u)/M,a[1]=2*(h*o+s*u+c*r-i*e)/M,a[2]=2*(c*o+s*e+i*u-h*r)/M):(a[0]=2*(i*o+s*r+h*e-c*u),a[1]=2*(h*o+s*u+c*r-i*e),a[2]=2*(c*o+s*e+i*u-h*r)),dn(t,n,a),t}function yn(t,n){return t[0]=n[12],t[1]=n[13],t[2]=n[14],t}function pn(t,n){var a=n[0],r=n[1],u=n[2],e=n[4],o=n[5],i=n[6],h=n[8],c=n[9],s=n[10];return t[0]=Math.hypot(a,r,u),t[1]=Math.hypot(e,o,i),t[2]=Math.hypot(h,c,s),t}function qn(t,n){var a=new f(3);pn(a,n);var r=1/a[0],u=1/a[1],e=1/a[2],o=n[0]*r,i=n[1]*u,h=n[2]*e,c=n[4]*r,s=n[5]*u,M=n[6]*e,l=n[8]*r,v=n[9]*u,b=n[10]*e,m=o+s+b,d=0;return m>0?(d=2*Math.sqrt(m+1),t[3]=.25*d,t[0]=(M-v)/d,t[1]=(l-h)/d,t[2]=(i-c)/d):o>s&&o>b?(d=2*Math.sqrt(1+o-s-b),t[3]=(M-v)/d,t[0]=.25*d,t[1]=(i+c)/d,t[2]=(l+h)/d):s>b?(d=2*Math.sqrt(1+s-o-b),t[3]=(l-h)/d,t[0]=(i+c)/d,t[1]=.25*d,t[2]=(M+v)/d):(d=2*Math.sqrt(1+b-o-s),t[3]=(i-c)/d,t[0]=(l+h)/d,t[1]=(M+v)/d,t[2]=.25*d),t}function wn(t,n,a,r){var u=n[0],e=n[1],o=n[2],i=n[3],h=u+u,c=e+e,s=o+o,M=u*h,f=u*c,l=u*s,v=e*c,b=e*s,m=o*s,d=i*h,x=i*c,y=i*s,p=r[0],q=r[1],w=r[2];return t[0]=(1-(v+m))*p,t[1]=(f+y)*p,t[2]=(l-x)*p,t[3]=0,t[4]=(f-y)*q,t[5]=(1-(M+m))*q,t[6]=(b+d)*q,t[7]=0,t[8]=(l+x)*w,t[9]=(b-d)*w,t[10]=(1-(M+v))*w,t[11]=0,t[12]=a[0],t[13]=a[1],t[14]=a[2],t[15]=1,t}function gn(t,n,a,r,u){var e=n[0],o=n[1],i=n[2],h=n[3],c=e+e,s=o+o,M=i+i,f=e*c,l=e*s,v=e*M,b=o*s,m=o*M,d=i*M,x=h*c,y=h*s,p=h*M,q=r[0],w=r[1],g=r[2],A=u[0],P=u[1],S=u[2],R=(1-(b+d))*q,T=(l+p)*q,I=(v-y)*q,E=(l-p)*w,D=(1-(f+d))*w,F=(m+x)*w,L=(v+y)*g,V=(m-x)*g,j=(1-(f+b))*g;return t[0]=R,t[1]=T,t[2]=I,t[3]=0,t[4]=E,t[5]=D,t[6]=F,t[7]=0,t[8]=L,t[9]=V,t[10]=j,t[11]=0,t[12]=a[0]+A-(R*A+E*P+L*S),t[13]=a[1]+P-(T*A+D*P+V*S),t[14]=a[2]+S-(I*A+F*P+j*S),t[15]=1,t}function An(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a+a,i=r+r,h=u+u,c=a*o,s=r*o,M=r*i,f=u*o,l=u*i,v=u*h,b=e*o,m=e*i,d=e*h;return t[0]=1-M-v,t[1]=s+d,t[2]=f-m,t[3]=0,t[4]=s-d,t[5]=1-c-v,t[6]=l+b,t[7]=0,t[8]=f+m,t[9]=l-b,t[10]=1-c-M,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function Pn(t,n,a,r,u,e,o){var i=1/(a-n),h=1/(u-r),c=1/(e-o);return t[0]=2*e*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*e*h,t[6]=0,t[7]=0,t[8]=(a+n)*i,t[9]=(u+r)*h,t[10]=(o+e)*c,t[11]=-1,t[12]=0,t[13]=0,t[14]=o*e*2*c,t[15]=0,t}function Sn(t,n,a,r,u){var e,o=1/Math.tan(n/2);return t[0]=o/a,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=o,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=-1,t[12]=0,t[13]=0,t[15]=0,null!=u&&u!==1/0?(e=1/(r-u),t[10]=(u+r)*e,t[14]=2*u*r*e):(t[10]=-1,t[14]=-2*r),t}function Rn(t,n,a,r){var u=Math.tan(n.upDegrees*Math.PI/180),e=Math.tan(n.downDegrees*Math.PI/180),o=Math.tan(n.leftDegrees*Math.PI/180),i=Math.tan(n.rightDegrees*Math.PI/180),h=2/(o+i),c=2/(u+e);return t[0]=h,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=c,t[6]=0,t[7]=0,t[8]=-(o-i)*h*.5,t[9]=(u-e)*c*.5,t[10]=r/(a-r),t[11]=-1,t[12]=0,t[13]=0,t[14]=r*a/(a-r),t[15]=0,t}function Tn(t,n,a,r,u,e,o){var i=1/(n-a),h=1/(r-u),c=1/(e-o);return t[0]=-2*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*h,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*c,t[11]=0,t[12]=(n+a)*i,t[13]=(u+r)*h,t[14]=(o+e)*c,t[15]=1,t}function In(t,n,a,r){var u,e,o,i,h,c,s,f,l,v,b=n[0],m=n[1],d=n[2],x=r[0],y=r[1],p=r[2],q=a[0],w=a[1],g=a[2];return Math.abs(b-q)<M&&Math.abs(m-w)<M&&Math.abs(d-g)<M?Kt(t):(s=b-q,f=m-w,l=d-g,u=y*(l*=v=1/Math.hypot(s,f,l))-p*(f*=v),e=p*(s*=v)-x*l,o=x*f-y*s,(v=Math.hypot(u,e,o))?(u*=v=1/v,e*=v,o*=v):(u=0,e=0,o=0),i=f*o-l*e,h=l*u-s*o,c=s*e-f*u,(v=Math.hypot(i,h,c))?(i*=v=1/v,h*=v,c*=v):(i=0,h=0,c=0),t[0]=u,t[1]=i,t[2]=s,t[3]=0,t[4]=e,t[5]=h,t[6]=f,t[7]=0,t[8]=o,t[9]=c,t[10]=l,t[11]=0,t[12]=-(u*b+e*m+o*d),t[13]=-(i*b+h*m+c*d),t[14]=-(s*b+f*m+l*d),t[15]=1,t)}function En(t,n,a,r){var u=n[0],e=n[1],o=n[2],i=r[0],h=r[1],c=r[2],s=u-a[0],M=e-a[1],f=o-a[2],l=s*s+M*M+f*f;l>0&&(s*=l=1/Math.sqrt(l),M*=l,f*=l);var v=h*f-c*M,b=c*s-i*f,m=i*M-h*s;return(l=v*v+b*b+m*m)>0&&(v*=l=1/Math.sqrt(l),b*=l,m*=l),t[0]=v,t[1]=b,t[2]=m,t[3]=0,t[4]=M*m-f*b,t[5]=f*v-s*m,t[6]=s*b-M*v,t[7]=0,t[8]=s,t[9]=M,t[10]=f,t[11]=0,t[12]=u,t[13]=e,t[14]=o,t[15]=1,t}function Dn(t){return"mat4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+", "+t[9]+", "+t[10]+", "+t[11]+", "+t[12]+", "+t[13]+", "+t[14]+", "+t[15]+")"}function Fn(t){return Math.hypot(t[0],t[1],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])}function Ln(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t[6]=n[6]+a[6],t[7]=n[7]+a[7],t[8]=n[8]+a[8],t[9]=n[9]+a[9],t[10]=n[10]+a[10],t[11]=n[11]+a[11],t[12]=n[12]+a[12],t[13]=n[13]+a[13],t[14]=n[14]+a[14],t[15]=n[15]+a[15],t}function Vn(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t[6]=n[6]-a[6],t[7]=n[7]-a[7],t[8]=n[8]-a[8],t[9]=n[9]-a[9],t[10]=n[10]-a[10],t[11]=n[11]-a[11],t[12]=n[12]-a[12],t[13]=n[13]-a[13],t[14]=n[14]-a[14],t[15]=n[15]-a[15],t}function jn(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t[6]=n[6]*a,t[7]=n[7]*a,t[8]=n[8]*a,t[9]=n[9]*a,t[10]=n[10]*a,t[11]=n[11]*a,t[12]=n[12]*a,t[13]=n[13]*a,t[14]=n[14]*a,t[15]=n[15]*a,t}function zn(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t[6]=n[6]+a[6]*r,t[7]=n[7]+a[7]*r,t[8]=n[8]+a[8]*r,t[9]=n[9]+a[9]*r,t[10]=n[10]+a[10]*r,t[11]=n[11]+a[11]*r,t[12]=n[12]+a[12]*r,t[13]=n[13]+a[13]*r,t[14]=n[14]+a[14]*r,t[15]=n[15]+a[15]*r,t}function On(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]&&t[9]===n[9]&&t[10]===n[10]&&t[11]===n[11]&&t[12]===n[12]&&t[13]===n[13]&&t[14]===n[14]&&t[15]===n[15]}function Qn(t,n){var a=t[0],r=t[1],u=t[2],e=t[3],o=t[4],i=t[5],h=t[6],c=t[7],s=t[8],f=t[9],l=t[10],v=t[11],b=t[12],m=t[13],d=t[14],x=t[15],y=n[0],p=n[1],q=n[2],w=n[3],g=n[4],A=n[5],P=n[6],S=n[7],R=n[8],T=n[9],I=n[10],E=n[11],D=n[12],F=n[13],L=n[14],V=n[15];return Math.abs(a-y)<=M*Math.max(1,Math.abs(a),Math.abs(y))&&Math.abs(r-p)<=M*Math.max(1,Math.abs(r),Math.abs(p))&&Math.abs(u-q)<=M*Math.max(1,Math.abs(u),Math.abs(q))&&Math.abs(e-w)<=M*Math.max(1,Math.abs(e),Math.abs(w))&&Math.abs(o-g)<=M*Math.max(1,Math.abs(o),Math.abs(g))&&Math.abs(i-A)<=M*Math.max(1,Math.abs(i),Math.abs(A))&&Math.abs(h-P)<=M*Math.max(1,Math.abs(h),Math.abs(P))&&Math.abs(c-S)<=M*Math.max(1,Math.abs(c),Math.abs(S))&&Math.abs(s-R)<=M*Math.max(1,Math.abs(s),Math.abs(R))&&Math.abs(f-T)<=M*Math.max(1,Math.abs(f),Math.abs(T))&&Math.abs(l-I)<=M*Math.max(1,Math.abs(l),Math.abs(I))&&Math.abs(v-E)<=M*Math.max(1,Math.abs(v),Math.abs(E))&&Math.abs(b-D)<=M*Math.max(1,Math.abs(b),Math.abs(D))&&Math.abs(m-F)<=M*Math.max(1,Math.abs(m),Math.abs(F))&&Math.abs(d-L)<=M*Math.max(1,Math.abs(d),Math.abs(L))&&Math.abs(x-V)<=M*Math.max(1,Math.abs(x),Math.abs(V))}var Yn=rn,Xn=Vn;function Zn(){var t=new f(3);return f!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t}function _n(t){var n=new f(3);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n}function Bn(t){var n=t[0],a=t[1],r=t[2];return Math.hypot(n,a,r)}function Nn(t,n,a){var r=new f(3);return r[0]=t,r[1]=n,r[2]=a,r}function kn(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t}function Un(t,n,a,r){return t[0]=n,t[1]=a,t[2]=r,t}function Wn(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t}function Cn(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t}function Gn(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t[2]=n[2]*a[2],t}function Hn(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t[2]=n[2]/a[2],t}function Jn(t,n){return t[0]=Math.ceil(n[0]),t[1]=Math.ceil(n[1]),t[2]=Math.ceil(n[2]),t}function Kn(t,n){return t[0]=Math.floor(n[0]),t[1]=Math.floor(n[1]),t[2]=Math.floor(n[2]),t}function $n(t,n,a){return t[0]=Math.min(n[0],a[0]),t[1]=Math.min(n[1],a[1]),t[2]=Math.min(n[2],a[2]),t}function ta(t,n,a){return t[0]=Math.max(n[0],a[0]),t[1]=Math.max(n[1],a[1]),t[2]=Math.max(n[2],a[2]),t}function na(t,n){return t[0]=Math.round(n[0]),t[1]=Math.round(n[1]),t[2]=Math.round(n[2]),t}function aa(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t}function ra(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t}function ua(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2];return Math.hypot(a,r,u)}function ea(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2];return a*a+r*r+u*u}function oa(t){var n=t[0],a=t[1],r=t[2];return n*n+a*a+r*r}function ia(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t}function ha(t,n){return t[0]=1/n[0],t[1]=1/n[1],t[2]=1/n[2],t}function ca(t,n){var a=n[0],r=n[1],u=n[2],e=a*a+r*r+u*u;return e>0&&(e=1/Math.sqrt(e)),t[0]=n[0]*e,t[1]=n[1]*e,t[2]=n[2]*e,t}function sa(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function Ma(t,n,a){var r=n[0],u=n[1],e=n[2],o=a[0],i=a[1],h=a[2];return t[0]=u*h-e*i,t[1]=e*o-r*h,t[2]=r*i-u*o,t}function fa(t,n,a,r){var u=n[0],e=n[1],o=n[2];return t[0]=u+r*(a[0]-u),t[1]=e+r*(a[1]-e),t[2]=o+r*(a[2]-o),t}function la(t,n,a,r,u,e){var o=e*e,i=o*(2*e-3)+1,h=o*(e-2)+e,c=o*(e-1),s=o*(3-2*e);return t[0]=n[0]*i+a[0]*h+r[0]*c+u[0]*s,t[1]=n[1]*i+a[1]*h+r[1]*c+u[1]*s,t[2]=n[2]*i+a[2]*h+r[2]*c+u[2]*s,t}function va(t,n,a,r,u,e){var o=1-e,i=o*o,h=e*e,c=i*o,s=3*e*i,M=3*h*o,f=h*e;return t[0]=n[0]*c+a[0]*s+r[0]*M+u[0]*f,t[1]=n[1]*c+a[1]*s+r[1]*M+u[1]*f,t[2]=n[2]*c+a[2]*s+r[2]*M+u[2]*f,t}function ba(t,n){n=n||1;var a=2*l()*Math.PI,r=2*l()-1,u=Math.sqrt(1-r*r)*n;return t[0]=Math.cos(a)*u,t[1]=Math.sin(a)*u,t[2]=r*n,t}function ma(t,n,a){var r=n[0],u=n[1],e=n[2],o=a[3]*r+a[7]*u+a[11]*e+a[15];return o=o||1,t[0]=(a[0]*r+a[4]*u+a[8]*e+a[12])/o,t[1]=(a[1]*r+a[5]*u+a[9]*e+a[13])/o,t[2]=(a[2]*r+a[6]*u+a[10]*e+a[14])/o,t}function da(t,n,a){var r=n[0],u=n[1],e=n[2];return t[0]=r*a[0]+u*a[3]+e*a[6],t[1]=r*a[1]+u*a[4]+e*a[7],t[2]=r*a[2]+u*a[5]+e*a[8],t}function xa(t,n,a){var r=a[0],u=a[1],e=a[2],o=a[3],i=n[0],h=n[1],c=n[2],s=u*c-e*h,M=e*i-r*c,f=r*h-u*i,l=u*f-e*M,v=e*s-r*f,b=r*M-u*s,m=2*o;return s*=m,M*=m,f*=m,l*=2,v*=2,b*=2,t[0]=i+s+l,t[1]=h+M+v,t[2]=c+f+b,t}function ya(t,n,a,r){var u=[],e=[];return u[0]=n[0]-a[0],u[1]=n[1]-a[1],u[2]=n[2]-a[2],e[0]=u[0],e[1]=u[1]*Math.cos(r)-u[2]*Math.sin(r),e[2]=u[1]*Math.sin(r)+u[2]*Math.cos(r),t[0]=e[0]+a[0],t[1]=e[1]+a[1],t[2]=e[2]+a[2],t}function pa(t,n,a,r){var u=[],e=[];return u[0]=n[0]-a[0],u[1]=n[1]-a[1],u[2]=n[2]-a[2],e[0]=u[2]*Math.sin(r)+u[0]*Math.cos(r),e[1]=u[1],e[2]=u[2]*Math.cos(r)-u[0]*Math.sin(r),t[0]=e[0]+a[0],t[1]=e[1]+a[1],t[2]=e[2]+a[2],t}function qa(t,n,a,r){var u=[],e=[];return u[0]=n[0]-a[0],u[1]=n[1]-a[1],u[2]=n[2]-a[2],e[0]=u[0]*Math.cos(r)-u[1]*Math.sin(r),e[1]=u[0]*Math.sin(r)+u[1]*Math.cos(r),e[2]=u[2],t[0]=e[0]+a[0],t[1]=e[1]+a[1],t[2]=e[2]+a[2],t}function wa(t,n){var a=Nn(t[0],t[1],t[2]),r=Nn(n[0],n[1],n[2]);ca(a,a),ca(r,r);var u=sa(a,r);return u>1?0:u<-1?Math.PI:Math.acos(u)}function ga(t){return t[0]=0,t[1]=0,t[2]=0,t}function Aa(t){return"vec3("+t[0]+", "+t[1]+", "+t[2]+")"}function Pa(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]}function Sa(t,n){var a=t[0],r=t[1],u=t[2],e=n[0],o=n[1],i=n[2];return Math.abs(a-e)<=M*Math.max(1,Math.abs(a),Math.abs(e))&&Math.abs(r-o)<=M*Math.max(1,Math.abs(r),Math.abs(o))&&Math.abs(u-i)<=M*Math.max(1,Math.abs(u),Math.abs(i))}var Ra,Ta=Cn,Ia=Gn,Ea=Hn,Da=ua,Fa=ea,La=Bn,Va=oa,ja=(Ra=Zn(),function(t,n,a,r,u,e){var o,i;for(n||(n=3),a||(a=0),i=r?Math.min(r*n+a,t.length):t.length,o=a;o<i;o+=n)Ra[0]=t[o],Ra[1]=t[o+1],Ra[2]=t[o+2],u(Ra,Ra,e),t[o]=Ra[0],t[o+1]=Ra[1],t[o+2]=Ra[2];return t});function za(){var t=new f(4);return f!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0,t[3]=0),t}function Oa(t){var n=new f(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n}function Qa(t,n,a,r){var u=new f(4);return u[0]=t,u[1]=n,u[2]=a,u[3]=r,u}function Ya(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t}function Xa(t,n,a,r,u){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t}function Za(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t}function _a(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t}function Ba(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t[2]=n[2]*a[2],t[3]=n[3]*a[3],t}function Na(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t[2]=n[2]/a[2],t[3]=n[3]/a[3],t}function ka(t,n){return t[0]=Math.ceil(n[0]),t[1]=Math.ceil(n[1]),t[2]=Math.ceil(n[2]),t[3]=Math.ceil(n[3]),t}function Ua(t,n){return t[0]=Math.floor(n[0]),t[1]=Math.floor(n[1]),t[2]=Math.floor(n[2]),t[3]=Math.floor(n[3]),t}function Wa(t,n,a){return t[0]=Math.min(n[0],a[0]),t[1]=Math.min(n[1],a[1]),t[2]=Math.min(n[2],a[2]),t[3]=Math.min(n[3],a[3]),t}function Ca(t,n,a){return t[0]=Math.max(n[0],a[0]),t[1]=Math.max(n[1],a[1]),t[2]=Math.max(n[2],a[2]),t[3]=Math.max(n[3],a[3]),t}function Ga(t,n){return t[0]=Math.round(n[0]),t[1]=Math.round(n[1]),t[2]=Math.round(n[2]),t[3]=Math.round(n[3]),t}function Ha(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t}function Ja(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t}function Ka(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2],e=n[3]-t[3];return Math.hypot(a,r,u,e)}function $a(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2],e=n[3]-t[3];return a*a+r*r+u*u+e*e}function tr(t){var n=t[0],a=t[1],r=t[2],u=t[3];return Math.hypot(n,a,r,u)}function nr(t){var n=t[0],a=t[1],r=t[2],u=t[3];return n*n+a*a+r*r+u*u}function ar(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=-n[3],t}function rr(t,n){return t[0]=1/n[0],t[1]=1/n[1],t[2]=1/n[2],t[3]=1/n[3],t}function ur(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*a+r*r+u*u+e*e;return o>0&&(o=1/Math.sqrt(o)),t[0]=a*o,t[1]=r*o,t[2]=u*o,t[3]=e*o,t}function er(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]}function or(t,n,a,r){var u=a[0]*r[1]-a[1]*r[0],e=a[0]*r[2]-a[2]*r[0],o=a[0]*r[3]-a[3]*r[0],i=a[1]*r[2]-a[2]*r[1],h=a[1]*r[3]-a[3]*r[1],c=a[2]*r[3]-a[3]*r[2],s=n[0],M=n[1],f=n[2],l=n[3];return t[0]=M*c-f*h+l*i,t[1]=-s*c+f*o-l*e,t[2]=s*h-M*o+l*u,t[3]=-s*i+M*e-f*u,t}function ir(t,n,a,r){var u=n[0],e=n[1],o=n[2],i=n[3];return t[0]=u+r*(a[0]-u),t[1]=e+r*(a[1]-e),t[2]=o+r*(a[2]-o),t[3]=i+r*(a[3]-i),t}function hr(t,n){var a,r,u,e,o,i;n=n||1;do{o=(a=2*l()-1)*a+(r=2*l()-1)*r}while(o>=1);do{i=(u=2*l()-1)*u+(e=2*l()-1)*e}while(i>=1);var h=Math.sqrt((1-o)/i);return t[0]=n*a,t[1]=n*r,t[2]=n*u*h,t[3]=n*e*h,t}function cr(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3];return t[0]=a[0]*r+a[4]*u+a[8]*e+a[12]*o,t[1]=a[1]*r+a[5]*u+a[9]*e+a[13]*o,t[2]=a[2]*r+a[6]*u+a[10]*e+a[14]*o,t[3]=a[3]*r+a[7]*u+a[11]*e+a[15]*o,t}function sr(t,n,a){var r=n[0],u=n[1],e=n[2],o=a[0],i=a[1],h=a[2],c=a[3],s=c*r+i*e-h*u,M=c*u+h*r-o*e,f=c*e+o*u-i*r,l=-o*r-i*u-h*e;return t[0]=s*c+l*-o+M*-h-f*-i,t[1]=M*c+l*-i+f*-o-s*-h,t[2]=f*c+l*-h+s*-i-M*-o,t[3]=n[3],t}function Mr(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=0,t}function fr(t){return"vec4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"}function lr(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]}function vr(t,n){var a=t[0],r=t[1],u=t[2],e=t[3],o=n[0],i=n[1],h=n[2],c=n[3];return Math.abs(a-o)<=M*Math.max(1,Math.abs(a),Math.abs(o))&&Math.abs(r-i)<=M*Math.max(1,Math.abs(r),Math.abs(i))&&Math.abs(u-h)<=M*Math.max(1,Math.abs(u),Math.abs(h))&&Math.abs(e-c)<=M*Math.max(1,Math.abs(e),Math.abs(c))}var br=_a,mr=Ba,dr=Na,xr=Ka,yr=$a,pr=tr,qr=nr,wr=function(){var t=za();return function(n,a,r,u,e,o){var i,h;for(a||(a=4),r||(r=0),h=u?Math.min(u*a+r,n.length):n.length,i=r;i<h;i+=a)t[0]=n[i],t[1]=n[i+1],t[2]=n[i+2],t[3]=n[i+3],e(t,t,o),n[i]=t[0],n[i+1]=t[1],n[i+2]=t[2],n[i+3]=t[3];return n}}();function gr(){var t=new f(4);return f!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t[3]=1,t}function Ar(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t}function Pr(t,n,a){a*=.5;var r=Math.sin(a);return t[0]=r*n[0],t[1]=r*n[1],t[2]=r*n[2],t[3]=Math.cos(a),t}function Sr(t,n){var a=2*Math.acos(n[3]),r=Math.sin(a/2);return r>M?(t[0]=n[0]/r,t[1]=n[1]/r,t[2]=n[2]/r):(t[0]=1,t[1]=0,t[2]=0),a}function Rr(t,n){var a=au(t,n);return Math.acos(2*a*a-1)}function Tr(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],h=a[1],c=a[2],s=a[3];return t[0]=r*s+o*i+u*c-e*h,t[1]=u*s+o*h+e*i-r*c,t[2]=e*s+o*c+r*h-u*i,t[3]=o*s-r*i-u*h-e*c,t}function Ir(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),h=Math.cos(a);return t[0]=r*h+o*i,t[1]=u*h+e*i,t[2]=e*h-u*i,t[3]=o*h-r*i,t}function Er(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),h=Math.cos(a);return t[0]=r*h-e*i,t[1]=u*h+o*i,t[2]=e*h+r*i,t[3]=o*h-u*i,t}function Dr(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),h=Math.cos(a);return t[0]=r*h+u*i,t[1]=u*h-r*i,t[2]=e*h+o*i,t[3]=o*h-e*i,t}function Fr(t,n){var a=n[0],r=n[1],u=n[2];return t[0]=a,t[1]=r,t[2]=u,t[3]=Math.sqrt(Math.abs(1-a*a-r*r-u*u)),t}function Lr(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=Math.sqrt(a*a+r*r+u*u),i=Math.exp(e),h=o>0?i*Math.sin(o)/o:0;return t[0]=a*h,t[1]=r*h,t[2]=u*h,t[3]=i*Math.cos(o),t}function Vr(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=Math.sqrt(a*a+r*r+u*u),i=o>0?Math.atan2(o,e)/o:0;return t[0]=a*i,t[1]=r*i,t[2]=u*i,t[3]=.5*Math.log(a*a+r*r+u*u+e*e),t}function jr(t,n,a){return Vr(t,n),nu(t,t,a),Lr(t,t),t}function zr(t,n,a,r){var u,e,o,i,h,c=n[0],s=n[1],f=n[2],l=n[3],v=a[0],b=a[1],m=a[2],d=a[3];return(e=c*v+s*b+f*m+l*d)<0&&(e=-e,v=-v,b=-b,m=-m,d=-d),1-e>M?(u=Math.acos(e),o=Math.sin(u),i=Math.sin((1-r)*u)/o,h=Math.sin(r*u)/o):(i=1-r,h=r),t[0]=i*c+h*v,t[1]=i*s+h*b,t[2]=i*f+h*m,t[3]=i*l+h*d,t}function Or(t){var n=l(),a=l(),r=l(),u=Math.sqrt(1-n),e=Math.sqrt(n);return t[0]=u*Math.sin(2*Math.PI*a),t[1]=u*Math.cos(2*Math.PI*a),t[2]=e*Math.sin(2*Math.PI*r),t[3]=e*Math.cos(2*Math.PI*r),t}function Qr(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*a+r*r+u*u+e*e,i=o?1/o:0;return t[0]=-a*i,t[1]=-r*i,t[2]=-u*i,t[3]=e*i,t}function Yr(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=n[3],t}function Xr(t,n){var a,r=n[0]+n[4]+n[8];if(r>0)a=Math.sqrt(r+1),t[3]=.5*a,a=.5/a,t[0]=(n[5]-n[7])*a,t[1]=(n[6]-n[2])*a,t[2]=(n[1]-n[3])*a;else{var u=0;n[4]>n[0]&&(u=1),n[8]>n[3*u+u]&&(u=2);var e=(u+1)%3,o=(u+2)%3;a=Math.sqrt(n[3*u+u]-n[3*e+e]-n[3*o+o]+1),t[u]=.5*a,a=.5/a,t[3]=(n[3*e+o]-n[3*o+e])*a,t[e]=(n[3*e+u]+n[3*u+e])*a,t[o]=(n[3*o+u]+n[3*u+o])*a}return t}function Zr(t,n,a,r){var u=.5*Math.PI/180;n*=u,a*=u,r*=u;var e=Math.sin(n),o=Math.cos(n),i=Math.sin(a),h=Math.cos(a),c=Math.sin(r),s=Math.cos(r);return t[0]=e*h*s-o*i*c,t[1]=o*i*s+e*h*c,t[2]=o*h*c-e*i*s,t[3]=o*h*s+e*i*c,t}function _r(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"}var Br,Nr,kr,Ur,Wr,Cr,Gr=Oa,Hr=Qa,Jr=Ya,Kr=Xa,$r=Za,tu=Tr,nu=Ha,au=er,ru=ir,uu=tr,eu=uu,ou=nr,iu=ou,hu=ur,cu=lr,su=vr,Mu=(Br=Zn(),Nr=Nn(1,0,0),kr=Nn(0,1,0),function(t,n,a){var r=sa(n,a);return r<-.999999?(Ma(Br,Nr,n),La(Br)<1e-6&&Ma(Br,kr,n),ca(Br,Br),Pr(t,Br,Math.PI),t):r>.999999?(t[0]=0,t[1]=0,t[2]=0,t[3]=1,t):(Ma(Br,n,a),t[0]=Br[0],t[1]=Br[1],t[2]=Br[2],t[3]=1+r,hu(t,t))}),fu=(Ur=gr(),Wr=gr(),function(t,n,a,r,u,e){return zr(Ur,n,u,e),zr(Wr,a,r,e),zr(t,Ur,Wr,2*e*(1-e)),t}),lu=(Cr=bt(),function(t,n,a,r){return Cr[0]=a[0],Cr[3]=a[1],Cr[6]=a[2],Cr[1]=r[0],Cr[4]=r[1],Cr[7]=r[2],Cr[2]=-n[0],Cr[5]=-n[1],Cr[8]=-n[2],hu(t,Xr(t,Cr))});function vu(){var t=new f(8);return f!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0,t[4]=0,t[5]=0,t[6]=0,t[7]=0),t[3]=1,t}function bu(t){var n=new f(8);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n}function mu(t,n,a,r,u,e,o,i){var h=new f(8);return h[0]=t,h[1]=n,h[2]=a,h[3]=r,h[4]=u,h[5]=e,h[6]=o,h[7]=i,h}function du(t,n,a,r,u,e,o){var i=new f(8);i[0]=t,i[1]=n,i[2]=a,i[3]=r;var h=.5*u,c=.5*e,s=.5*o;return i[4]=h*r+c*a-s*n,i[5]=c*r+s*t-h*a,i[6]=s*r+h*n-c*t,i[7]=-h*t-c*n-s*a,i}function xu(t,n,a){var r=.5*a[0],u=.5*a[1],e=.5*a[2],o=n[0],i=n[1],h=n[2],c=n[3];return t[0]=o,t[1]=i,t[2]=h,t[3]=c,t[4]=r*c+u*h-e*i,t[5]=u*c+e*o-r*h,t[6]=e*c+r*i-u*o,t[7]=-r*o-u*i-e*h,t}function yu(t,n){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t[4]=.5*n[0],t[5]=.5*n[1],t[6]=.5*n[2],t[7]=0,t}function pu(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=0,t[5]=0,t[6]=0,t[7]=0,t}function qu(t,n){var a=gr();qn(a,n);var r=new f(3);return yn(r,n),xu(t,a,r),t}function wu(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t}function gu(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t[6]=0,t[7]=0,t}function Au(t,n,a,r,u,e,o,i,h){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=h,t}var Pu=Jr;function Su(t,n){return t[0]=n[4],t[1]=n[5],t[2]=n[6],t[3]=n[7],t}var Ru=Jr;function Tu(t,n){return t[4]=n[0],t[5]=n[1],t[6]=n[2],t[7]=n[3],t}function Iu(t,n){var a=n[4],r=n[5],u=n[6],e=n[7],o=-n[0],i=-n[1],h=-n[2],c=n[3];return t[0]=2*(a*c+e*o+r*h-u*i),t[1]=2*(r*c+e*i+u*o-a*h),t[2]=2*(u*c+e*h+a*i-r*o),t}function Eu(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=.5*a[0],h=.5*a[1],c=.5*a[2],s=n[4],M=n[5],f=n[6],l=n[7];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=o*i+u*c-e*h+s,t[5]=o*h+e*i-r*c+M,t[6]=o*c+r*h-u*i+f,t[7]=-r*i-u*h-e*c+l,t}function Du(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=i*o+s*r+h*e-c*u,f=h*o+s*u+c*r-i*e,l=c*o+s*e+i*u-h*r,v=s*o-i*r-h*u-c*e;return Ir(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t}function Fu(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=i*o+s*r+h*e-c*u,f=h*o+s*u+c*r-i*e,l=c*o+s*e+i*u-h*r,v=s*o-i*r-h*u-c*e;return Er(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t}function Lu(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=i*o+s*r+h*e-c*u,f=h*o+s*u+c*r-i*e,l=c*o+s*e+i*u-h*r,v=s*o-i*r-h*u-c*e;return Dr(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t}function Vu(t,n,a){var r=a[0],u=a[1],e=a[2],o=a[3],i=n[0],h=n[1],c=n[2],s=n[3];return t[0]=i*o+s*r+h*e-c*u,t[1]=h*o+s*u+c*r-i*e,t[2]=c*o+s*e+i*u-h*r,t[3]=s*o-i*r-h*u-c*e,i=n[4],h=n[5],c=n[6],s=n[7],t[4]=i*o+s*r+h*e-c*u,t[5]=h*o+s*u+c*r-i*e,t[6]=c*o+s*e+i*u-h*r,t[7]=s*o-i*r-h*u-c*e,t}function ju(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],h=a[1],c=a[2],s=a[3];return t[0]=r*s+o*i+u*c-e*h,t[1]=u*s+o*h+e*i-r*c,t[2]=e*s+o*c+r*h-u*i,t[3]=o*s-r*i-u*h-e*c,i=a[4],h=a[5],c=a[6],s=a[7],t[4]=r*s+o*i+u*c-e*h,t[5]=u*s+o*h+e*i-r*c,t[6]=e*s+o*c+r*h-u*i,t[7]=o*s-r*i-u*h-e*c,t}function zu(t,n,a,r){if(Math.abs(r)<M)return wu(t,n);var u=Math.hypot(a[0],a[1],a[2]);r*=.5;var e=Math.sin(r),o=e*a[0]/u,i=e*a[1]/u,h=e*a[2]/u,c=Math.cos(r),s=n[0],f=n[1],l=n[2],v=n[3];t[0]=s*c+v*o+f*h-l*i,t[1]=f*c+v*i+l*o-s*h,t[2]=l*c+v*h+s*i-f*o,t[3]=v*c-s*o-f*i-l*h;var b=n[4],m=n[5],d=n[6],x=n[7];return t[4]=b*c+x*o+m*h-d*i,t[5]=m*c+x*i+d*o-b*h,t[6]=d*c+x*h+b*i-m*o,t[7]=x*c-b*o-m*i-d*h,t}function Ou(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t[6]=n[6]+a[6],t[7]=n[7]+a[7],t}function Qu(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[4],h=a[5],c=a[6],s=a[7],M=n[4],f=n[5],l=n[6],v=n[7],b=a[0],m=a[1],d=a[2],x=a[3];return t[0]=r*x+o*b+u*d-e*m,t[1]=u*x+o*m+e*b-r*d,t[2]=e*x+o*d+r*m-u*b,t[3]=o*x-r*b-u*m-e*d,t[4]=r*s+o*i+u*c-e*h+M*x+v*b+f*d-l*m,t[5]=u*s+o*h+e*i-r*c+f*x+v*m+l*b-M*d,t[6]=e*s+o*c+r*h-u*i+l*x+v*d+M*m-f*b,t[7]=o*s-r*i-u*h-e*c+v*x-M*b-f*m-l*d,t}var Yu=Qu;function Xu(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t[6]=n[6]*a,t[7]=n[7]*a,t}var Zu=au;function _u(t,n,a,r){var u=1-r;return Zu(n,a)<0&&(r=-r),t[0]=n[0]*u+a[0]*r,t[1]=n[1]*u+a[1]*r,t[2]=n[2]*u+a[2]*r,t[3]=n[3]*u+a[3]*r,t[4]=n[4]*u+a[4]*r,t[5]=n[5]*u+a[5]*r,t[6]=n[6]*u+a[6]*r,t[7]=n[7]*u+a[7]*r,t}function Bu(t,n){var a=Wu(n);return t[0]=-n[0]/a,t[1]=-n[1]/a,t[2]=-n[2]/a,t[3]=n[3]/a,t[4]=-n[4]/a,t[5]=-n[5]/a,t[6]=-n[6]/a,t[7]=n[7]/a,t}function Nu(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=n[3],t[4]=-n[4],t[5]=-n[5],t[6]=-n[6],t[7]=n[7],t}var ku=uu,Uu=ku,Wu=ou,Cu=Wu;function Gu(t,n){var a=Wu(n);if(a>0){a=Math.sqrt(a);var r=n[0]/a,u=n[1]/a,e=n[2]/a,o=n[3]/a,i=n[4],h=n[5],c=n[6],s=n[7],M=r*i+u*h+e*c+o*s;t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=(i-r*M)/a,t[5]=(h-u*M)/a,t[6]=(c-e*M)/a,t[7]=(s-o*M)/a}return t}function Hu(t){return"quat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+")"}function Ju(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]}function Ku(t,n){var a=t[0],r=t[1],u=t[2],e=t[3],o=t[4],i=t[5],h=t[6],c=t[7],s=n[0],f=n[1],l=n[2],v=n[3],b=n[4],m=n[5],d=n[6],x=n[7];return Math.abs(a-s)<=M*Math.max(1,Math.abs(a),Math.abs(s))&&Math.abs(r-f)<=M*Math.max(1,Math.abs(r),Math.abs(f))&&Math.abs(u-l)<=M*Math.max(1,Math.abs(u),Math.abs(l))&&Math.abs(e-v)<=M*Math.max(1,Math.abs(e),Math.abs(v))&&Math.abs(o-b)<=M*Math.max(1,Math.abs(o),Math.abs(b))&&Math.abs(i-m)<=M*Math.max(1,Math.abs(i),Math.abs(m))&&Math.abs(h-d)<=M*Math.max(1,Math.abs(h),Math.abs(d))&&Math.abs(c-x)<=M*Math.max(1,Math.abs(c),Math.abs(x))}function $u(){var t=new f(2);return f!=Float32Array&&(t[0]=0,t[1]=0),t}function te(t){var n=new f(2);return n[0]=t[0],n[1]=t[1],n}function ne(t,n){var a=new f(2);return a[0]=t,a[1]=n,a}function ae(t,n){return t[0]=n[0],t[1]=n[1],t}function re(t,n,a){return t[0]=n,t[1]=a,t}function ue(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t}function ee(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t}function oe(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t}function ie(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t}function he(t,n){return t[0]=Math.ceil(n[0]),t[1]=Math.ceil(n[1]),t}function ce(t,n){return t[0]=Math.floor(n[0]),t[1]=Math.floor(n[1]),t}function se(t,n,a){return t[0]=Math.min(n[0],a[0]),t[1]=Math.min(n[1],a[1]),t}function Me(t,n,a){return t[0]=Math.max(n[0],a[0]),t[1]=Math.max(n[1],a[1]),t}function fe(t,n){return t[0]=Math.round(n[0]),t[1]=Math.round(n[1]),t}function le(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t}function ve(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t}function be(t,n){var a=n[0]-t[0],r=n[1]-t[1];return Math.hypot(a,r)}function me(t,n){var a=n[0]-t[0],r=n[1]-t[1];return a*a+r*r}function de(t){var n=t[0],a=t[1];return Math.hypot(n,a)}function xe(t){var n=t[0],a=t[1];return n*n+a*a}function ye(t,n){return t[0]=-n[0],t[1]=-n[1],t}function pe(t,n){return t[0]=1/n[0],t[1]=1/n[1],t}function qe(t,n){var a=n[0],r=n[1],u=a*a+r*r;return u>0&&(u=1/Math.sqrt(u)),t[0]=n[0]*u,t[1]=n[1]*u,t}function we(t,n){return t[0]*n[0]+t[1]*n[1]}function ge(t,n,a){var r=n[0]*a[1]-n[1]*a[0];return t[0]=t[1]=0,t[2]=r,t}function Ae(t,n,a,r){var u=n[0],e=n[1];return t[0]=u+r*(a[0]-u),t[1]=e+r*(a[1]-e),t}function Pe(t,n){n=n||1;var a=2*l()*Math.PI;return t[0]=Math.cos(a)*n,t[1]=Math.sin(a)*n,t}function Se(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[2]*u,t[1]=a[1]*r+a[3]*u,t}function Re(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[2]*u+a[4],t[1]=a[1]*r+a[3]*u+a[5],t}function Te(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[3]*u+a[6],t[1]=a[1]*r+a[4]*u+a[7],t}function Ie(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[4]*u+a[12],t[1]=a[1]*r+a[5]*u+a[13],t}function Ee(t,n,a,r){var u=n[0]-a[0],e=n[1]-a[1],o=Math.sin(r),i=Math.cos(r);return t[0]=u*i-e*o+a[0],t[1]=u*o+e*i+a[1],t}function De(t,n){var a=t[0],r=t[1],u=n[0],e=n[1],o=a*a+r*r;o>0&&(o=1/Math.sqrt(o));var i=u*u+e*e;i>0&&(i=1/Math.sqrt(i));var h=(a*u+r*e)*o*i;return h>1?0:h<-1?Math.PI:Math.acos(h)}function Fe(t){return t[0]=0,t[1]=0,t}function Le(t){return"vec2("+t[0]+", "+t[1]+")"}function Ve(t,n){return t[0]===n[0]&&t[1]===n[1]}function je(t,n){var a=t[0],r=t[1],u=n[0],e=n[1];return Math.abs(a-u)<=M*Math.max(1,Math.abs(a),Math.abs(u))&&Math.abs(r-e)<=M*Math.max(1,Math.abs(r),Math.abs(e))}var ze=de,Oe=ee,Qe=oe,Ye=ie,Xe=be,Ze=me,_e=xe,Be=function(){var t=$u();return function(n,a,r,u,e,o){var i,h;for(a||(a=2),r||(r=0),h=u?Math.min(u*a+r,n.length):n.length,i=r;i<h;i+=a)t[0]=n[i],t[1]=n[i+1],e(t,t,o),n[i]=t[0],n[i+1]=t[1];return n}}();window.glMatrix=n,window.mat2=a,window.mat2d=r,window.mat3=u,window.mat4=e,window.quat=h,window.quat2=c,window.vec2=s,window.vec3=o,window.vec4=i})();
//# sourceMappingURL=libs.core.js.map
if(!CABLES.exportedPatches)CABLES.exportedPatches={};CABLES.exportedPatches["AKyCLI"]={_id:"6802e6ad1eabef6cd41fff48",ops:[{id:"y13dqo17l",uiAttribs:{},portsIn:[{name:"Max Pixel Density (DPR)",value:2},{name:"FPS Limit",value:0},{name:"Reduce FPS unfocussed",value:0},{name:"Transparent",value:0},{name:"Active",value:1}],portsOut:[{name:"trigger",links:[{portIn:"exe",portOut:"trigger",objIn:"terdkh1mt",objOut:"y13dqo17l"}]},{name:"width",links:[{portIn:"Value",portOut:"width",objIn:"d0c7hcbyb",objOut:"y13dqo17l"}]},{name:"height",links:[{portIn:"Value",portOut:"height",objIn:"e55t1cvbf",objOut:"y13dqo17l"}]},{name:"Pixel Density",value:1.25}],objName:"Ops.Gl.MainLoop_v2"},{id:"terdkh1mt",uiAttribs:{},portsIn:[{name:"Visible",value:1},{name:"Measure GPU",value:1},{name:"Position index",value:0},{name:"Position",value:"top"},{name:"Open",value:0},{name:"Smooth Graph",value:1},{name:"Scale",value:3},{name:"Size",value:128}],portsOut:[{name:"childs",links:[{portIn:"Trigger",portOut:"childs",objIn:"l614wixal",objOut:"terdkh1mt"}]},{name:"FPS",value:60}],objName:"Ops.Gl.Performance"},{id:"d0c7hcbyb",uiAttribs:{},portsIn:[{name:"Variable",value:"width"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"e55t1cvbf",uiAttribs:{},portsIn:[{name:"Variable",value:"height"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"y5ue21jre",uiAttribs:{},portsIn:[{name:"Variable",value:"performance"}],portsOut:[{name:"Value",links:[{portIn:"Active",portOut:"Value",objIn:"terdkh1mt",objOut:"y5ue21jre"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"o5x18bylp",uiAttribs:{},portsIn:[{name:"Value",value:0},{name:"Variable",value:"performance"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"j0wipshr8",uiAttribs:{},portsIn:[{name:"Play Timeline",value:1}],portsOut:[{name:"Next",links:[{portIn:"Execute",portOut:"Next",objIn:"rcwwlhfky",objOut:"j0wipshr8"},{portIn:"Trigger",portOut:"Next",objIn:"uz88jsinn",objOut:"j0wipshr8"}]},{name:"Finished Initial Loading",value:1},{name:"Loading",links:[{portIn:"Pass Through",portOut:"Loading",objIn:"rcwwlhfky",objOut:"j0wipshr8"}]},{name:"Progress",links:[{portIn:"percent",portOut:"Progress",objIn:"jwpb9kyyo",objOut:"j0wipshr8"}]},{name:"Trigger Loading Finished ",links:[{portIn:"Pause",portOut:"Trigger Loading Finished ",objIn:"dsovwvrsf",objOut:"j0wipshr8"}]}],objName:"Ops.Cables.LoadingStatus_v2"},{id:"uz88jsinn",uiAttribs:{},portsIn:[{name:"Only if Audio Suspended",value:0},{name:"Style Outer",value:"width:100px;\r\nheight:100px;\r\nleft:50%;\r\ntop:50%;\r\nborder-radius:100%;\r\nposition:absolute;\r\ncursor:pointer;\r\nopacity:0.7;\r\ntransform:translate(-50%,-50%);\r\nz-index:999999;\r\nbackground-color:#333;\r\nborder:5px solid #333;"},{name:"Style Inner",value:"\r\nborder-style:solid;\r\nborder-color:transparent transparent transparent #ccc;\r\nbox-sizing:border-box;\r\nwidth:50px;\r\nheight:50px;\r\nmargin-top:25px;\r\nmargin-left:36px;\r\nborder-width:25px 0px 25px 40px;\r\npointer-events:none;\r\n"},{name:"Active",value:1}],portsOut:[{name:"Next",links:[{portIn:"exe",portOut:"Next",objIn:"4qbyc8zkv",objOut:"uz88jsinn"}]},{name:"Audiocontext State",value:"running"},{name:"Clicked",value:0},{name:"Clicked Trigger",links:[{portIn:"Update",portOut:"Clicked Trigger",objIn:"867t2upoz",objOut:"uz88jsinn"}]}],objName:"Ops.Html.Utils.PlayButton"},{id:"rcwwlhfky",uiAttribs:{},portsOut:[{name:"Trigger out",links:[{portIn:"render",portOut:"Trigger out",objIn:"8eo3g6an1",objOut:"rcwwlhfky"}]}],objName:"Ops.Trigger.GateTrigger"},{id:"8eo3g6an1",uiAttribs:{},portsIn:[{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1},{name:"colorizeTexture",value:0},{name:"Vertex Colors",value:0},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Opacity TexCoords Transform",value:0},{name:"Discard Transparent Pixels",value:0},{name:"diffuseRepeatX",value:1},{name:"diffuseRepeatY",value:1},{name:"Tex Offset X",value:0},{name:"Tex Offset Y",value:0},{name:"Crop TexCoords",value:0},{name:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"iafyd0fim",objOut:"8eo3g6an1"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"iafyd0fim",uiAttribs:{},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:0},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"jwpb9kyyo",objOut:"iafyd0fim"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"jwpb9kyyo",uiAttribs:{},portsIn:[{name:"radius",value:.5},{name:"innerRadius",value:0},{name:"segments",value:40},{name:"steps",value:0},{name:"invertSteps",value:0},{name:"mapping index",value:0},{name:"mapping",value:"flat"},{name:"Spline",value:0},{name:"Draw",value:1,title:"Render mesh"}],objName:"Ops.Gl.Meshes.Circle_v3"},{id:"dsovwvrsf",uiAttribs:{},portsIn:[{name:"Set current time",value:0}],portsOut:[{name:"is Playing",value:false},{name:"set time (seconds)",value:0},{name:"current time",value:0},{name:"current frame",value:0}],objName:"Ops.TimeLine.TimeLinePlayer"},{id:"4qbyc8zkv",uiAttribs:{},portsOut:[{name:"trigger 0",links:[{portIn:"Execute",portOut:"trigger 0",objIn:"gq2g2jahg",objOut:"4qbyc8zkv"}]},{name:"trigger 1",links:[{portIn:"exe",portOut:"trigger 1",objIn:"x8pefb8mg",objOut:"4qbyc8zkv"}]}],objName:"Ops.Trigger.Sequence"},{id:"iqfle5lam",uiAttribs:{},portsIn:[{name:"Title",value:"Loader"}],objName:"Ops.Ui.Area"},{id:"1ygpbxrjj",uiAttribs:{},portsIn:[{name:"Title",value:"Init"}],objName:"Ops.Ui.Area"},{id:"2edlzc043",uiAttribs:{},portsIn:[{name:"URL",value:"assets/KineKu_003_120bpm.mp3",display:"file"},{name:"Create Loading Task",value:1}],portsOut:[{name:"Audio Buffer",links:[{portIn:"Audio Buffer",portOut:"Audio Buffer",objIn:"z27imhm6v",objOut:"2edlzc043"}]},{name:"Finished Loading",value:1},{name:"Sample Rate",value:44100},{name:"Length",value:3707136},{name:"Duration",links:[{portIn:"Value",portOut:"Duration",objIn:"zv0yiarl9",objOut:"2edlzc043"}]},{name:"Number of Channels",value:2},{name:"isLoading",value:false}],objName:"Ops.WebAudio.AudioBuffer_v2"},{id:"zv0yiarl9",uiAttribs:{},portsIn:[{name:"Variable",value:"duration"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"z27imhm6v",uiAttribs:{},portsIn:[{name:"Loop",value:0},{name:"Playback Rate",value:1},{name:"Detune",value:0}],portsOut:[{name:"Audio Out",links:[{portIn:"Audio In",portOut:"Audio Out",objIn:"jmxl1tith",objOut:"z27imhm6v"},{portIn:"Audio In",portOut:"Audio Out",objIn:"xvf1yivbj",objOut:"z27imhm6v"}]},{name:"Is Playing",links:[{portIn:"Pass Through",portOut:"Is Playing",objIn:"gq2g2jahg",objOut:"z27imhm6v"}]},{name:"Loading",value:false}],objName:"Ops.WebAudio.AudioBufferPlayer_v2"},{id:"z7x5r48gc",uiAttribs:{},portsOut:[{name:"Play/Stop",links:[{portIn:"Start / Stop",portOut:"Play/Stop",objIn:"z27imhm6v",objOut:"z7x5r48gc"}]},{name:"time",links:[{portIn:"Offset",portOut:"time",objIn:"z27imhm6v",objOut:"z7x5r48gc"}]}],objName:"Ops.TimeLine.TimeLineControls"},{id:"jmxl1tith",uiAttribs:{},portsIn:[{name:"Volume",value:1},{name:"Mute",value:0},{name:"Show Audio Suspended Button",value:1}],portsOut:[{name:"Current Volume",value:1},{name:"Context State",value:"running"}],objName:"Ops.WebAudio.Output_v2"},{id:"xvf1yivbj",uiAttribs:{},portsIn:[{name:"FFT size index",value:3},{name:"FFT size",value:256},{name:"Smoothing",value:.3},{name:"Min",value:-90},{name:"Max",value:0}],portsOut:[{name:"Trigger Out",links:[{portIn:"Update",portOut:"Trigger Out",objIn:"amopgxgo5",objOut:"xvf1yivbj"}]},{name:"FFT Array",links:[{portIn:"Value",portOut:"FFT Array",objIn:"f6817rkge",objOut:"xvf1yivbj"}]},{name:"Array Length",value:128},{name:"Average Volume",links:[{portIn:"Value",portOut:"Average Volume",objIn:"amopgxgo5",objOut:"xvf1yivbj"}]},{name:"Average Volume Time-Domain",value:.5},{name:"RMS Volume",value:.5}],objName:"Ops.WebAudio.AudioAnalyzer_v2"},{id:"gq2g2jahg",uiAttribs:{},portsOut:[{name:"Trigger out",links:[{portIn:"Trigger In",portOut:"Trigger out",objIn:"xvf1yivbj",objOut:"gq2g2jahg"}]}],objName:"Ops.Trigger.GateTrigger"},{id:"f6817rkge",uiAttribs:{},portsIn:[{name:"Variable",value:"fft"}],objName:"Ops.Vars.VarSetArray_v2"},{id:"wjdcf66sx",uiAttribs:{},portsIn:[{name:"Title",value:"Audio"}],objName:"Ops.Ui.Area"},{id:"l614wixal",uiAttribs:{},portsIn:[{name:"Active",value:1},{name:"Force index",value:1},{name:"Force",value:"Aspect Ratio"},{name:"Center In Parent",value:1},{name:"Scale to fit Parent",value:0},{name:"Set Width",value:300},{name:"Set Height",value:200},{name:"Aspect Ratio index",value:3},{name:"Aspect Ratio",value:"16:9"},{name:"Ratio",value:1.7777777777777777},{name:"Fill Parent index",value:0},{name:"Fill Parent",value:"Auto"}],portsOut:[{name:"Next",links:[{portIn:"exe",portOut:"Next",objIn:"j0wipshr8",objOut:"l614wixal"}]},{name:"Width",value:688},{name:"Height",value:387},{name:"Margin Left",value:53.5},{name:"Margin Top",value:0}],objName:"Ops.Gl.ForceCanvasSize"},{id:"5qq4g2l5g",uiAttribs:{},portsIn:[{name:"Clamp",value:0},{name:"Show Time",value:1},{name:"Show Skip Buttons",value:0}],portsOut:[{name:"Play clicked",links:[{portIn:"Update",portOut:"Play clicked",objIn:"ucs02pk5f",objOut:"5qq4g2l5g"}]},{name:"Pause clicked",links:[{portIn:"Pause",portOut:"Pause clicked",objIn:"vgv57hgla",objOut:"5qq4g2l5g"}]},{name:"Rewind clicked",links:[{portIn:"Update",portOut:"Rewind clicked",objIn:"wndy50rz7",objOut:"5qq4g2l5g"}]},{name:"Dragged",links:[{portIn:"Update",portOut:"Dragged",objIn:"09ugeea98",objOut:"5qq4g2l5g"}]},{name:"Current Value",links:[{portIn:"Time",portOut:"Current Value",objIn:"ucs02pk5f",objOut:"5qq4g2l5g"},{portIn:"Time",portOut:"Current Value",objIn:"09ugeea98",objOut:"5qq4g2l5g"}]},{name:"Dragging",value:0}],objName:"Ops.Html.Utils.PlayerControlPanel_v2"},{id:"tzpr4u1ge",uiAttribs:{},portsIn:[{name:"Variable",value:"duration"}],portsOut:[{name:"Value",links:[{portIn:"Length",portOut:"Value",objIn:"5qq4g2l5g",objOut:"tzpr4u1ge"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"ryzle22ea",uiAttribs:{},portsOut:[{name:"time",links:[{portIn:"Current",portOut:"time",objIn:"5qq4g2l5g",objOut:"ryzle22ea"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"b1hmhszrd",uiAttribs:{},portsOut:[{name:"Play/Stop",links:[{portIn:"Is Playing",portOut:"Play/Stop",objIn:"5qq4g2l5g",objOut:"b1hmhszrd"}]},{name:"time",value:0}],objName:"Ops.TimeLine.TimeLineControls"},{id:"6g5gvera0",uiAttribs:{},portsIn:[{name:"Variable",value:"debug"}],portsOut:[{name:"Value",links:[{portIn:"Visible",portOut:"Value",objIn:"5qq4g2l5g",objOut:"6g5gvera0"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"6cu3k2gz2",uiAttribs:{},portsIn:[{name:"Value",value:0},{name:"Variable",value:"debug"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"d4pm1rad8",uiAttribs:{},portsOut:[{name:"UI",value:1},{name:"Overlay Mode",value:0},{name:"Remote Viewer",value:0},{name:"Is Standalone",value:1},{name:"Canvas Mode",value:0},{name:"Patch Field Visible",value:0}],objName:"Ops.Cables.UIMode"},{id:"ucs02pk5f",uiAttribs:{},portsOut:[{name:"Next",links:[{portIn:"Play",portOut:"Next",objIn:"vgv57hgla",objOut:"ucs02pk5f"}]}],objName:"Ops.TimeLine.TimeLineSetTime"},{id:"vgv57hgla",uiAttribs:{},objName:"Ops.TimeLine.TimeLinePlay"},{id:"09ugeea98",uiAttribs:{},objName:"Ops.TimeLine.TimeLineSetTime"},{id:"wndy50rz7",uiAttribs:{},portsIn:[{name:"Time",value:0}],objName:"Ops.TimeLine.TimeLineSetTime"},{id:"ti1o9mh1w",uiAttribs:{},portsIn:[{name:"Title",value:"Timeline"}],objName:"Ops.Ui.Area"},{id:"x8pefb8mg",uiAttribs:{},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"yv6xpip18",objOut:"x8pefb8mg"}]},{name:"trigger 13",links:[{portIn:"Render",portOut:"trigger 13",objIn:"i7wogdhb1",objOut:"x8pefb8mg"}]},{name:"trigger 14",links:[{portIn:"Render",portOut:"trigger 14",objIn:"oqprag0fd",objOut:"x8pefb8mg"}]},{name:"trigger 15",links:[{portIn:"render",portOut:"trigger 15",objIn:"bxc1rxcn1",objOut:"x8pefb8mg"}]}],objName:"Ops.Trigger.Sequence"},{id:"yv6xpip18",uiAttribs:{},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Canvas"},{name:"texture width",value:860},{name:"texture height",value:483},{name:"Auto Aspect",value:1},{name:"filter index",value:1},{name:"filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"Repeat"},{name:"MSAA index",value:3},{name:"MSAA",value:"8x"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{name:"Depth",value:1},{name:"Clear",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"xfjcsn9yc",objOut:"yv6xpip18"}]},{name:"texture",links:[{portIn:"Image",portOut:"texture",objIn:"we3uacszb",objOut:"yv6xpip18"},{portIn:"Image",portOut:"texture",objIn:"hiop0qwrc",objOut:"yv6xpip18"}]}],objName:"Ops.Gl.RenderToTexture_v3"},{id:"6hvep72pc",uiAttribs:{},portsOut:[{name:"trigger 0",links:[{portIn:"Execute",portOut:"trigger 0",objIn:"j7msg2abj",objOut:"6hvep72pc"}]},{name:"trigger 1",links:[{portIn:"Execute",portOut:"trigger 1",objIn:"hlpc7t9yb",objOut:"6hvep72pc"}]},{name:"trigger 2",links:[{portIn:"Execute",portOut:"trigger 2",objIn:"w7hozstk3",objOut:"6hvep72pc"}]},{name:"trigger 3",links:[{portIn:"Execute",portOut:"trigger 3",objIn:"v03dcp9mp",objOut:"6hvep72pc"}]},{name:"trigger 4",links:[{portIn:"Execute",portOut:"trigger 4",objIn:"bx2brxqxb",objOut:"6hvep72pc"}]},{name:"trigger 12",links:[{portIn:"exe 5",portOut:"trigger 12",objIn:"7a34hjy3d",objOut:"6hvep72pc"}]}],objName:"Ops.Trigger.Sequence"},{id:"hiop0qwrc",uiAttribs:{},portsIn:[{name:"blendMode index",value:0},{name:"blendMode",value:"normal"},{name:"amount",value:1},{name:"Premultiplied",value:0},{name:"Alpha Mask",value:0},{name:"removeAlphaSrc",value:1},{name:"Mask Src index",value:1},{name:"Mask Src",value:"luminance"},{name:"Invert alpha channel",value:0},{name:"Aspect Ratio",value:0},{name:"Stretch Axis index",value:0},{name:"Stretch Axis",value:"X"},{name:"Position",value:0},{name:"Crop",value:0},{name:"flip x",value:0},{name:"flip y",value:0},{name:"Transform",value:0},{name:"Scale X",value:1},{name:"Scale Y",value:1},{name:"Position X",value:0},{name:"Position Y",value:0},{name:"Rotation",value:0},{name:"Clip Repeat",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"k5cafaqyf",objOut:"hiop0qwrc"},{portIn:"exe",portOut:"trigger",objIn:"r8exldps0",objOut:"hiop0qwrc"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"bxc1rxcn1",uiAttribs:{},portsIn:[{name:"Scale index",value:1},{name:"Scale",value:"Fit"},{name:"Flip Y",value:0},{name:"Flip X",value:0}],objName:"Ops.Gl.Meshes.FullscreenRectangle_v2"},{id:"oqprag0fd",uiAttribs:{},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Auto"},{name:"Width",value:640},{name:"Height",value:480},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:0},{name:"Wrap",value:"clamp to edge"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{name:"Clear",value:1},{name:"R",value:0},{name:"G",value:0},{name:"B",value:0},{name:"A",value:0}],portsOut:[{name:"Next",links:[{portIn:"render",portOut:"Next",objIn:"we3uacszb",objOut:"oqprag0fd"}]},{name:"texture_out",links:[{portIn:"Texture",portOut:"texture_out",objIn:"bxc1rxcn1",objOut:"oqprag0fd"}]},{name:"Aspect Ratio",value:1.7805383022774328},{name:"Texture Width",value:860},{name:"Texture Height",value:483}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"i7wogdhb1",uiAttribs:{},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Auto"},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:0},{name:"Wrap",value:"clamp to edge"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{name:"Clear",value:1},{name:"R",value:0},{name:"G",value:0},{name:"B",value:0},{name:"A",value:0}],portsOut:[{name:"Next",links:[{portIn:"render",portOut:"Next",objIn:"hiop0qwrc",objOut:"i7wogdhb1"}]},{name:"texture_out",links:[{portIn:"Image",portOut:"texture_out",objIn:"oevpn5kat",objOut:"i7wogdhb1"}]},{name:"Aspect Ratio",value:1.7805383022774328},{name:"Texture Width",value:860},{name:"Texture Height",value:483}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"we3uacszb",uiAttribs:{},portsIn:[{name:"blendMode index",value:0},{name:"blendMode",value:"normal"},{name:"amount",value:1},{name:"Premultiplied",value:0},{name:"Alpha Mask",value:0},{name:"removeAlphaSrc",value:0},{name:"Mask Src index",value:1},{name:"Mask Src",value:"luminance"},{name:"Invert alpha channel",value:0},{name:"Aspect Ratio",value:0},{name:"Stretch Axis index",value:0},{name:"Stretch Axis",value:"X"},{name:"Position",value:0},{name:"Crop",value:0},{name:"flip x",value:0},{name:"flip y",value:0},{name:"Transform",value:0},{name:"Scale X",value:1},{name:"Scale Y",value:1},{name:"Position X",value:0},{name:"Position Y",value:0},{name:"Rotation",value:0},{name:"Clip Repeat",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"oevpn5kat",objOut:"we3uacszb"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"oevpn5kat",uiAttribs:{},portsIn:[{name:"blendMode index",value:12},{name:"blendMode",value:"screen"},{name:"amount",value:1},{name:"Premultiplied",value:0},{name:"Alpha Mask",value:0},{name:"removeAlphaSrc",value:1},{name:"Mask Src index",value:1},{name:"Mask Src",value:"luminance"},{name:"Invert alpha channel",value:0},{name:"Aspect Ratio",value:0},{name:"Stretch Axis index",value:0},{name:"Stretch Axis",value:"X"},{name:"Position",value:0},{name:"Crop",value:0},{name:"flip x",value:0},{name:"flip y",value:0},{name:"Transform",value:0},{name:"Scale X",value:1},{name:"Scale Y",value:1},{name:"Position X",value:0},{name:"Position Y",value:0},{name:"Rotation",value:0},{name:"Clip Repeat",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"vxbul25b4",objOut:"oevpn5kat"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"4odo0b2i6",uiAttribs:{},portsIn:[{name:"Variable",value:"width"}],portsOut:[{name:"Value",links:[{portIn:"number1",portOut:"Value",objIn:"1c18x1rto",objOut:"4odo0b2i6"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"1c18x1rto",uiAttribs:{},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"Width",portOut:"result",objIn:"i7wogdhb1",objOut:"1c18x1rto"}]}],objName:"Ops.Math.Divide"},{id:"d646j8ttd",uiAttribs:{},portsIn:[{name:"Variable",value:"height"}],portsOut:[{name:"Value",links:[{portIn:"number1",portOut:"Value",objIn:"tziij7vuz",objOut:"d646j8ttd"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"tziij7vuz",uiAttribs:{},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"Height",portOut:"result",objIn:"i7wogdhb1",objOut:"tziij7vuz"}]}],objName:"Ops.Math.Divide"},{id:"0ee6y5amn",uiAttribs:{},portsIn:[{name:"span index",value:6},{name:"span",value:"64"},{name:"reduceMin",value:128},{name:"reduceMul",value:8},{name:"use viewport size",value:1},{name:"width",value:0},{name:"height",value:0}],objName:"Ops.Gl.ImageCompose.FXAA"},{id:"0qdcwu2hf",uiAttribs:{},portsIn:[{name:"Title",value:"Post Processing"}],objName:"Ops.Ui.Area"},{id:"e9ipwj8zz",uiAttribs:{},portsIn:[{name:"amount",value:.1},{name:"direction index",value:0},{name:"direction",value:"both"},{name:"Fast",value:1}],objName:"Ops.Gl.ImageCompose.Blur"},{id:"uoy6ojcg5",uiAttribs:{},portsIn:[{name:"posX",value:-1,animated:true,anim:{keys:[{t:-1734723475976807e-30,v:-1,e:1},{t:21.566666666666666,v:1,e:1},{t:57.63333333333335,v:-1,e:0}],loop:false}},{name:"posY",value:3,animated:true,anim:{keys:[{t:0,v:3,e:1},{t:4.966666666666667,v:3.0015190502760163,e:18},{t:6.2333333333333325,v:-1,e:1},{t:21.566666666666666,v:-.45,e:1},{t:42.43333333333333,v:-.94,e:1},{t:57.63333333333335,v:-.43,e:0}],loop:false}},{name:"posZ",value:.3},{name:"scale",value:1,animated:true,anim:{keys:[{t:0,v:1,e:0},{t:5,v:2.48,e:1},{t:21.566666666666666,v:1.12,e:1},{t:42.43333333333333,v:2.3,e:1},{t:57.63333333333335,v:1,e:0}],loop:false}},{name:"rotY",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"yjqwvno7i",objOut:"uoy6ojcg5"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"yjqwvno7i",uiAttribs:{},portsIn:[{name:"r",value:.8500917353590328},{name:"g",value:.8542708333333333},{name:"b",value:.11132008234659829},{name:"a",value:1},{name:"colorizeTexture",value:0},{name:"Vertex Colors",value:0},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Opacity TexCoords Transform",value:0},{name:"Discard Transparent Pixels",value:1},{name:"diffuseRepeatX",value:1},{name:"diffuseRepeatY",value:1},{name:"Tex Offset X",value:0},{name:"Tex Offset Y",value:0},{name:"Crop TexCoords",value:0},{name:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"dgt3587wc",objOut:"yjqwvno7i"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"dgt3587wc",uiAttribs:{},portsIn:[{name:"render",title:"Trigger"},{name:"Render Mesh",value:1,title:"Render"},{name:"width",value:1},{name:"height",value:1},{name:"pivot x index",value:1},{name:"pivot x",value:"center"},{name:"pivot y index",value:1},{name:"pivot y",value:"center"},{name:"axis index",value:0},{name:"axis",value:"xy"},{name:"Flip TexCoord X",value:0,animated:true,anim:{keys:[{t:0,v:0,e:1},{t:21.566666666666666,v:1,e:1},{t:57.63333333333335,v:0,e:0}],loop:false}},{name:"Flip TexCoord Y",value:1},{name:"num columns",value:1},{name:"num rows",value:1}],objName:"Ops.Gl.Meshes.Rectangle_v4"},{id:"3nlqb4j6y",uiAttribs:{},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"Sine"},{name:"phase",value:0},{name:"frequency",value:4},{name:"amplitude",value:10}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"eye84kfsw",objOut:"3nlqb4j6y"},{portIn:"rotZ",portOut:"result",objIn:"uoy6ojcg5",objOut:"3nlqb4j6y"}]}],objName:"Ops.Anim.SineAnim"},{id:"7galv36af",uiAttribs:{},portsIn:[{name:"File",value:"assets/kine-ku.png",display:"file"},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"Wrap index",value:2},{name:"Wrap",value:"clamp to edge"},{name:"Anisotropic index",value:5},{name:"Anisotropic",value:"16"},{name:"Data Format index",value:3},{name:"Data Format",value:"RGBA"},{name:"Flip",value:0},{name:"Pre Multiplied Alpha",value:0},{name:"Active",value:1},{name:"Save Memory",value:1},{name:"Add Cachebuster",value:0}],portsOut:[{name:"Texture",links:[{portIn:"texture",portOut:"Texture",objIn:"yjqwvno7i",objOut:"7galv36af"}]},{name:"Width",value:864},{name:"Height",value:1025},{name:"Aspect Ratio",value:.8429268292682927},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"xfjcsn9yc",uiAttribs:{},portsIn:[{name:"r",value:.0009375000000000355,animated:true,anim:{keys:[{t:0,v:.0009375000000000355,e:11},{t:5.833333333333333,v:.7334248478938035,e:0},{t:75,v:.7411764705882353,e:0},{t:79.73333333333335,v:.08843994140625,e:1},{t:80.5333333333333,v:.0009361839294433948,e:1}],loop:false}},{name:"g",value:.0009375000000000355,animated:true,anim:{keys:[{t:0,v:.0009375000000000355,e:11},{t:5.833333333333333,v:.27940601942949256,e:0},{t:75,v:.2823529411764706,e:0},{t:79.73333333333335,v:1,e:1},{t:80.5333333333333,v:.0009375000000000355,e:1}],loop:false}},{name:"b",value:.0009375000000000355,animated:true,anim:{keys:[{t:0,v:.0009375000000000355,e:11},{t:5.833333333333333,v:.27940601942949256,e:0},{t:75,v:.2823529411764706,e:0},{t:79.73333333333335,v:.20295467376708975,e:1},{t:80.5333333333333,v:.000936348438262975,e:1}],loop:false}},{name:"a",value:1}],portsOut:[{name:"trigger",links:[{portIn:"exe",portOut:"trigger",objIn:"6hvep72pc",objOut:"xfjcsn9yc"}]}],objName:"Ops.Gl.ClearColor"},{id:"e6woygf5t",uiAttribs:{},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Sides",value:6.41},{name:"Angle",value:.218},{name:"Slide X",value:.481},{name:"Slide Y",value:.54},{name:"Center X",value:.405},{name:"Center Y",value:.146},{name:"Aspect Ratio",value:1}],objName:"Ops.Gl.ImageCompose.Kaleidoscope_v2"},{id:"e3wdso25m",uiAttribs:{},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Strength",value:1},{name:"Radius",value:.3},{name:"Sharp",value:.25},{name:"Aspect",value:1},{name:"r",value:.5083515624999999},{name:"g",value:.8266666666666667},{name:"b",value:.4287727864583334},{name:"Alpha",value:0}],portsOut:[{name:"Trigger",links:[{portIn:"render",portOut:"Trigger",objIn:"0ee6y5amn",objOut:"e3wdso25m"}]}],objName:"Ops.Gl.ImageCompose.Vignette_v3"},{id:"vxbul25b4",uiAttribs:{},portsIn:[{name:"Blend Mode index",value:12},{name:"Blend Mode",value:"screen"},{name:"Alpha Mask index",value:1},{name:"Alpha Mask",value:"On"},{name:"Offset X",value:0},{name:"Zoom",value:5},{name:"Iterations",value:50},{name:"Seed",value:1},{name:"Spot edge",value:.5},{name:"Gamma",value:.75}],portsOut:[{name:"trigger",links:[{portIn:"exe",portOut:"trigger",objIn:"jw3dcua13",objOut:"vxbul25b4"},{portIn:"Render",portOut:"trigger",objIn:"bfqskmu5w",objOut:"vxbul25b4"}]}],objName:"Ops.Gl.ImageCompose.LensDirt_v2"},{id:"g6422z26v",uiAttribs:{},portsIn:[{name:"Strength",value:.15},{name:"Center X",value:.2,animated:true,anim:{keys:[{t:.033333333333335304,v:.2,e:1},{t:21.566666666666666,v:.8,e:1},{t:57.63333333333335,v:.2,e:1}],loop:false}},{name:"Center Y",value:.24}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"e3wdso25m",objOut:"g6422z26v"}]}],objName:"Ops.Gl.ImageCompose.BulgePinch"},{id:"jw3dcua13",uiAttribs:{},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"Sine"},{name:"phase",value:0},{name:"frequency",value:1},{name:"amplitude",value:1}],portsOut:[{name:"Trigger out",links:[{portIn:"exe",portOut:"Trigger out",objIn:"v5gboqb07",objOut:"jw3dcua13"}]},{name:"result",value:-.7999703811767767}],objName:"Ops.Anim.SineAnim"},{id:"v5gboqb07",uiAttribs:{},portsIn:[{name:"min",value:.2},{name:"max",value:.5},{name:"duration",value:.5},{name:"pause between",value:0},{name:"easing index",value:25},{name:"easing",value:"Bounce Out"}],portsOut:[{name:"result",value:.24003025313357854}],objName:"Ops.Anim.RandomAnim_v2"},{id:"x6u2o7hdt",uiAttribs:{},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"qctr68hay",objOut:"x6u2o7hdt"}]}],objName:"Ops.Trigger.Sequence"},{id:"lpfokwv4s",uiAttribs:{},portsIn:[{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:.5676041666666667},{name:"colorizeTexture",value:0},{name:"Vertex Colors",value:0},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Opacity TexCoords Transform",value:0},{name:"Discard Transparent Pixels",value:0},{name:"diffuseRepeatX",value:1},{name:"diffuseRepeatY",value:1},{name:"Tex Offset X",value:0},{name:"Tex Offset Y",value:0},{name:"Crop TexCoords",value:0},{name:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"b0on0de2f",objOut:"lpfokwv4s"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"3qwh9x3q4",uiAttribs:{},portsIn:[{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1},{name:"colorizeTexture",value:0},{name:"Vertex Colors",value:0},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Opacity TexCoords Transform",value:0},{name:"Discard Transparent Pixels",value:0},{name:"diffuseRepeatX",value:1},{name:"diffuseRepeatY",value:1},{name:"Tex Offset X",value:0},{name:"Tex Offset Y",value:0},{name:"Crop TexCoords",value:0},{name:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"l69iv7mnh",objOut:"3qwh9x3q4"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"qctr68hay",uiAttribs:{},portsIn:[{name:"posZ",value:0},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotY",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"lpfokwv4s",objOut:"qctr68hay"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"l69iv7mnh",uiAttribs:{},portsIn:[{name:"posX",value:0},{name:"posY",value:.1},{name:"posZ",value:0},{name:"scale",value:.65},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"1jznh14a7",objOut:"l69iv7mnh"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"1jznh14a7",uiAttribs:{},portsIn:[{name:"render",title:"Trigger"},{name:"Render Mesh",value:1,title:"Render"},{name:"width",value:1},{name:"height",value:1},{name:"pivot x index",value:1},{name:"pivot x",value:"center"},{name:"pivot y index",value:1},{name:"pivot y",value:"center"},{name:"axis index",value:0},{name:"axis",value:"xy"},{name:"Flip TexCoord X",value:0},{name:"Flip TexCoord Y",value:1},{name:"num columns",value:1},{name:"num rows",value:1}],objName:"Ops.Gl.Meshes.Rectangle_v4"},{id:"b0on0de2f",uiAttribs:{},portsIn:[{name:"render",title:"Trigger"},{name:"Render Mesh",value:1,title:"Render"},{name:"width",value:10},{name:"height",value:.8},{name:"pivot x index",value:1},{name:"pivot x",value:"center"},{name:"pivot y index",value:1},{name:"pivot y",value:"center"},{name:"axis index",value:0},{name:"axis",value:"xy"},{name:"Flip TexCoord X",value:0},{name:"Flip TexCoord Y",value:1},{name:"num columns",value:1},{name:"num rows",value:1}],portsOut:[{name:"trigger",title:"Next",links:[{portIn:"render",portOut:"trigger",objIn:"gqk8blh2x",objOut:"b0on0de2f"}]}],objName:"Ops.Gl.Meshes.Rectangle_v4"},{id:"jflq6xcar",uiAttribs:{},portsIn:[{name:"Draw Mesh",value:1},{name:"Scale Mesh",value:.42},{name:"Size index",value:0},{name:"Size",value:"Auto"},{name:"Width",value:512},{name:"Height",value:512},{name:"Auto Height",value:1},{name:"Auto Line Breaks",value:1},{name:"font",value:"Impact"},{name:"weight",value:"normal"},{name:"fontSize",value:300},{name:"align index",value:0},{name:"align",value:"left"},{name:"Vertical align index",value:0},{name:"Vertical align",value:"Top"},{name:"Letter Spacing",value:0},{name:"Line Height Add",value:0},{name:"Padding Y Top",value:3},{name:"Padding Y Bottom",value:3},{name:"Padding X",value:0},{name:"filter index",value:1},{name:"filter",value:"linear"},{name:"Wrap index",value:2},{name:"Wrap",value:"clamp to edge"},{name:"Anisotropic index",value:5},{name:"Anisotropic",value:"16"},{name:"Reuse Texture",value:1},{name:"Show Debug",value:0},{name:"Redraw On Font Load",value:1},{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"Opacity",value:1},{name:"background R",value:0},{name:"background G",value:0},{name:"background B",value:0},{name:"background A",value:0}],portsOut:[{name:"Ratio",value:.40324324324324323},{name:"texture",links:[{portIn:"texture",portOut:"texture",objIn:"3qwh9x3q4",objOut:"jflq6xcar"}]},{name:"Aspect",value:2.479892761394102},{name:"Num Lines",value:1}],objName:"Ops.Gl.Textures.TextTexture_v6"},{id:"gqk8blh2x",uiAttribs:{},portsIn:[{name:"posX",value:0},{name:"posY",value:-.08},{name:"posZ",value:0},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"jflq6xcar",objOut:"gqk8blh2x"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"gxkxqw0a2",uiAttribs:{},portsIn:[{name:"Strings",multiPortNum:41,multiPortManual:true},{name:"Strings_0",value:"Kine"},{name:"Strings_1",value:"Ku"},{name:"Strings_2",value:""},{name:"Strings_3",value:"Kine"},{name:"Strings_4",value:"Ku"},{name:"Strings_5",value:""},{name:"Strings_6",value:"Ingen er så"},{name:"Strings_7",value:"tjukk og god"},{name:"Strings_8",value:"som hu"},{name:"Strings_9",value:""},{name:"Strings_10",value:"Kine"},{name:"Strings_11",value:"Ku"},{name:"Strings_12",value:""},{name:"Strings_13",value:"Kine"},{name:"Strings_14",value:"Ku"},{name:"Strings_15",value:""},{name:"Strings_16",value:"Ingen sier"},{name:"Strings_17",value:"mø"},{name:"Strings_18",value:"som"},{name:"Strings_19",value:"Kine Ku"},{name:"Strings_20",value:"---"},{name:"Strings_21",value:"Kine"},{name:"Strings_22",value:"Ku"},{name:"Strings_23",value:""},{name:"Strings_24",value:"Kine"},{name:"Strings_25",value:"Ku"},{name:"Strings_26",value:""},{name:"Strings_27",value:"Ingen liker"},{name:"Strings_28",value:"blomster"},{name:"Strings_29",value:"mer en du"},{name:"Strings_30",value:" "},{name:"Strings_31",value:"Kine"},{name:"Strings_32",value:"Ku"},{name:"Strings_33",value:" "},{name:"Strings_34",value:"Kine"},{name:"Strings_35",value:"Muu"},{name:"Strings_36",value:" "},{name:"Strings_37",value:"Danser"},{name:"Strings_38",value:"som en ekte"},{name:"Strings_39",value:"bjelle"},{name:"Strings_40",value:"Ku"}],portsOut:[{name:"String",links:[{portIn:"String",portOut:"String",objIn:"hi0uevetn",objOut:"gxkxqw0a2"},{portIn:"text",portOut:"String",objIn:"jflq6xcar",objOut:"gxkxqw0a2"}]},{name:"Num Values",links:[{portIn:"Length",portOut:"Num Values",objIn:"gpbz9w9o3",objOut:"gxkxqw0a2"}]}],objName:"Ops.String.SwitchStringMultiPort"},{id:"hi0uevetn",uiAttribs:{},portsIn:[{name:"ZoomText",value:0},{name:"Line Numbers",value:1},{name:"Whitespace",value:0},{name:"Wrap lines",value:0},{name:"Syntax index",value:0},{name:"Syntax",value:"text"},{name:"Font Size",value:10},{name:"Scroll",value:0}],objName:"Ops.Ui.VizString"},{id:"gpbz9w9o3",uiAttribs:{},portsIn:[{name:"Limit",value:1},{name:"Mode index",value:0},{name:"Mode",value:"Rewind"},{name:"Default",value:0}],portsOut:[{name:"Value",links:[{portIn:"Number",portOut:"Value",objIn:"xz7qlr4p2",objOut:"gpbz9w9o3"}]}],objName:"Ops.Math.Incrementor"},{id:"xz7qlr4p2",uiAttribs:{},portsOut:[{name:"Result",links:[{portIn:"Index",portOut:"Result",objIn:"gxkxqw0a2",objOut:"xz7qlr4p2"}]}],objName:"Ops.Ui.VizNumber"},{id:"1sezva0sf",uiAttribs:{},portsOut:[{name:"time",links:[{portIn:"number1",portOut:"time",objIn:"yrcdqdplz",objOut:"1sezva0sf"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"yrcdqdplz",uiAttribs:{},portsIn:[{name:"number2",value:.5}],portsOut:[{name:"result",links:[{portIn:"Offset Y",portOut:"result",objIn:"vxbul25b4",objOut:"yrcdqdplz"}]}],objName:"Ops.Math.Multiply"},{id:"ldbzfushr",uiAttribs:{},portsIn:[{name:"Value",value:0,animated:true,anim:{keys:[{t:0,v:0,e:5},{t:79.8,v:1,e:5},{t:80.4666666666668,v:0,e:1}],loop:false}},{name:"Variable",value:"metan"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"a969nw68t",uiAttribs:{},portsIn:[{name:"Variable",value:"metan"}],portsOut:[{name:"Value",links:[{portIn:"Amount",portOut:"Value",objIn:"e3wdso25m",objOut:"a969nw68t"},{portIn:"Amount",portOut:"Value",objIn:"vxbul25b4",objOut:"a969nw68t"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"0kux275h3",uiAttribs:{},portsIn:[{name:"Variable",value:"sing_index"}],portsOut:[{name:"Value",links:[{portIn:"Value",portOut:"Value",objIn:"uxnob00p2",objOut:"0kux275h3"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"w7hozstk3",uiAttribs:{},portsOut:[{name:"Trigger out",links:[{portIn:"exe",portOut:"Trigger out",objIn:"x6u2o7hdt",objOut:"w7hozstk3"}]}],objName:"Ops.Trigger.GateTrigger"},{id:"rr7z0ogqx",uiAttribs:{},portsIn:[{name:"Variable",value:"overlay"}],portsOut:[{name:"Value",links:[{portIn:"Pass Through",portOut:"Value",objIn:"w7hozstk3",objOut:"rr7z0ogqx"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"kt1j1bwjg",uiAttribs:{},portsIn:[{name:"Font",value:"a94760d2-804b-4deb-bc26-aefda028b5af"},{name:"Scale",value:.2},{name:"Letter Spacing",value:1},{name:"Line Height",value:1},{name:"Align index",value:1},{name:"Align",value:"Center"},{name:"Vertical Align index",value:2},{name:"Vertical Align",value:"Middle"},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1},{name:"SDF",value:1},{name:"Smoothing",value:.3},{name:"Border",value:0},{name:"Border Width",value:1.1},{name:"Smoothness",value:.25},{name:"Border r",value:0},{name:"Border g",value:0},{name:"Border b",value:0},{name:"Shadow",value:1},{name:"Scalings",value:0},{name:"Rotations",value:0},{name:"Colors",value:0}],portsOut:[{name:"Num Lines",value:1},{name:"Width",value:17.428406249999995},{name:"Height",value:.2606145279255319},{name:"Start Y",value:.15443874667553192},{name:"Num Chars",value:50}],objName:"Ops.Gl.TextMeshMSDF_v2"},{id:"e49dkttoj",uiAttribs:{},portsIn:[{name:"End of string",value:0}],portsOut:[{name:"Result",links:[{portIn:"Text",portOut:"Result",objIn:"kt1j1bwjg",objOut:"e49dkttoj"}]}],objName:"Ops.String.SubString_v2"},{id:"f5o252rjy",uiAttribs:{},portsOut:[{name:"result",links:[{portIn:"End",portOut:"result",objIn:"e49dkttoj",objOut:"f5o252rjy"}]}],objName:"Ops.Math.Sum"},{id:"abnox2e13",uiAttribs:{},portsIn:[{name:"value",value:50}],portsOut:[{name:"result",links:[{portIn:"number2",portOut:"result",objIn:"f5o252rjy",objOut:"abnox2e13"},{portIn:"Array length",portOut:"result",objIn:"3g9m223sy",objOut:"abnox2e13"},{portIn:"Array length",portOut:"result",objIn:"knnts76ct",objOut:"abnox2e13"}]}],objName:"Ops.Number.Number"},{id:"sqoc027ui",uiAttribs:{},portsIn:[{name:"Value",value:.85}],portsOut:[{name:"Result",links:[{portIn:"Array 1",portOut:"Result",objIn:"8yl5hbp8i",objOut:"sqoc027ui"}]}],objName:"Ops.Array.ArrayMultiply"},{id:"8yl5hbp8i",uiAttribs:{},portsOut:[{name:"Trigger out",links:[{portIn:"Render",portOut:"Trigger out",objIn:"kt1j1bwjg",objOut:"8yl5hbp8i"}]},{name:"Array out",links:[{portIn:"Positions",portOut:"Array out",objIn:"kt1j1bwjg",objOut:"8yl5hbp8i"}]},{name:"Num Points",value:50},{name:"Array length",value:150}],objName:"Ops.Array.ArrayPack3"},{id:"rkjovlith",uiAttribs:{},portsIn:[{name:"number2",value:1},{name:"pingpong",value:0}],portsOut:[{name:"result",links:[{portIn:"Value",portOut:"result",objIn:"3is1hrkte",objOut:"rkjovlith"},{portIn:"Number for math",portOut:"result",objIn:"unmqdsrgv",objOut:"rkjovlith"}]}],objName:"Ops.Math.Modulo"},{id:"3is1hrkte",uiAttribs:{},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"Array-x"}],portsOut:[{name:"Array Out",links:[{portIn:"In",portOut:"Array Out",objIn:"sqoc027ui",objOut:"3is1hrkte"}]}],objName:"Ops.Array.ArraySubtract"},{id:"l2zbvqkhg",uiAttribs:{},portsIn:[{name:"posX",value:-1.9},{name:"posY",value:.96},{name:"posZ",value:.2},{name:"scale",value:1},{name:"rotX",value:23.27},{name:"rotY",value:-23.4},{name:"rotZ",value:-9.59}],portsOut:[{name:"trigger",links:[{portIn:"Trigger in",portOut:"trigger",objIn:"8yl5hbp8i",objOut:"l2zbvqkhg"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"kg67pgwzf",uiAttribs:{},portsIn:[{name:"Math function index",value:0},{name:"Math function",value:"Sin"},{name:"Frequency",value:.3},{name:"Amplitude",value:1}],portsOut:[{name:"Array result",links:[{portIn:"Array 2",portOut:"Array result",objIn:"8yl5hbp8i",objOut:"kg67pgwzf"}]}],objName:"Ops.Array.ArraySin"},{id:"unmqdsrgv",uiAttribs:{},portsIn:[{name:"Math function index",value:1},{name:"Math function",value:"-"}],portsOut:[{name:"Array result",links:[{portIn:"array in",portOut:"Array result",objIn:"kg67pgwzf",objOut:"unmqdsrgv"}]},{name:"Array length",value:50}],objName:"Ops.Array.ArrayMath"},{id:"woq1ksfcx",uiAttribs:{},portsIn:[{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"Phase",portOut:"Time",objIn:"kg67pgwzf",objOut:"woq1ksfcx"}]}],objName:"Ops.Anim.Timer_v2"},{id:"0t81rdk35",uiAttribs:{},portsIn:[{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"number1",portOut:"Time",objIn:"94qqo1vlt",objOut:"0t81rdk35"}]}],objName:"Ops.Anim.Timer_v2"},{id:"94qqo1vlt",uiAttribs:{},portsIn:[{name:"pingpong",value:0}],portsOut:[{name:"result",links:[{portIn:"Start",portOut:"result",objIn:"e49dkttoj",objOut:"94qqo1vlt"},{portIn:"number1",portOut:"result",objIn:"f5o252rjy",objOut:"94qqo1vlt"},{portIn:"number1",portOut:"result",objIn:"rkjovlith",objOut:"94qqo1vlt"}]}],objName:"Ops.Math.Modulo"},{id:"a6smd58z2",uiAttribs:{},portsOut:[{name:"Result",links:[{portIn:"number2",portOut:"Result",objIn:"94qqo1vlt",objOut:"a6smd58z2"}]}],objName:"Ops.String.StringLength_v2"},{id:"3g9m223sy",uiAttribs:{},portsIn:[{name:"Mode select index",value:1},{name:"Mode select",value:"1,2,3,4"},{name:"Default Value",value:0},{name:"Reverse",value:0}],portsOut:[{name:"Array",links:[{portIn:"Array In",portOut:"Array",objIn:"3is1hrkte",objOut:"3g9m223sy"},{portIn:"array 0",portOut:"Array",objIn:"unmqdsrgv",objOut:"3g9m223sy"}]},{name:"Array length out",value:50}],objName:"Ops.Array.Array_v3"},{id:"knnts76ct",uiAttribs:{},portsIn:[{name:"Mode select index",value:0},{name:"Mode select",value:"Number"},{name:"Default Value",value:0},{name:"Reverse",value:0}],portsOut:[{name:"Array",links:[{portIn:"Array 3",portOut:"Array",objIn:"8yl5hbp8i",objOut:"knnts76ct"}]},{name:"Array length out",value:50}],objName:"Ops.Array.Array_v3"},{id:"x7t4ttjdp",uiAttribs:{},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"l2zbvqkhg",objOut:"x7t4ttjdp"}]}],objName:"Ops.Trigger.Sequence"},{id:"v03dcp9mp",uiAttribs:{},portsOut:[{name:"Trigger out",links:[{portIn:"exe",portOut:"Trigger out",objIn:"x7t4ttjdp",objOut:"v03dcp9mp"}]}],objName:"Ops.Trigger.GateTrigger"},{id:"pgdut5n4z",uiAttribs:{},portsIn:[{name:"Value",value:9},{name:"Variable",value:"speed"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"fs16bun6l",uiAttribs:{},portsIn:[{name:"Variable",value:"speed"}],portsOut:[{name:"Value",links:[{portIn:"Speed",portOut:"Value",objIn:"0t81rdk35",objOut:"fs16bun6l"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"cgybdcjng",uiAttribs:{},portsIn:[{name:"Value",value:5},{name:"Variable",value:"bump"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"43y03h7f5",uiAttribs:{},portsIn:[{name:"Variable",value:"bump"}],portsOut:[{name:"Value",links:[{portIn:"Speed",portOut:"Value",objIn:"woq1ksfcx",objOut:"43y03h7f5"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"6ad762m19",uiAttribs:{},portsOut:[{name:"trigger 0",links:[{portIn:"Trigger in",portOut:"trigger 0",objIn:"zqrc9mgp6",objOut:"6ad762m19"}]},{name:"trigger 13",links:[{portIn:"render",portOut:"trigger 13",objIn:"0371dlf8p",objOut:"6ad762m19"}]},{name:"trigger 15",links:[{portIn:"In Trigger",portOut:"trigger 15",objIn:"y5nio1yke",objOut:"6ad762m19"}]}],objName:"Ops.Trigger.Sequence"},{id:"n5bglnnn4",uiAttribs:{},portsIn:[{name:"Font",value:"a94760d2-804b-4deb-bc26-aefda028b5af"},{name:"Scale",value:1},{name:"Letter Spacing",value:1},{name:"Line Height",value:1},{name:"Align index",value:1},{name:"Align",value:"Center"},{name:"Vertical Align index",value:2},{name:"Vertical Align",value:"Middle"},{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"a",value:0,animated:true,anim:{keys:[{t:0,v:0,e:0},{t:3.2,v:0,e:0},{t:4.0000000000000036,v:.5,e:0}],loop:false}},{name:"SDF",value:1},{name:"Smoothing",value:.3},{name:"Border",value:0},{name:"Border Width",value:.626},{name:"Smoothness",value:.25},{name:"Border r",value:1},{name:"Border g",value:.0017301782936556265},{name:"Border b",value:.0017301782936556265},{name:"Shadow",value:0},{name:"Scalings",value:0},{name:"Rotations",value:0},{name:"Colors",value:0}],portsOut:[{name:"Num Lines",value:1},{name:"Width",value:445.5459375000013},{name:"Height",value:.9588148271276598},{name:"Start Y",value:.4188148271276597},{name:"Num Chars",value:225}],objName:"Ops.Gl.TextMeshMSDF_v2"},{id:"0371dlf8p",uiAttribs:{},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:0},{name:"scale",value:.32},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"n5bglnnn4",objOut:"0371dlf8p"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"t5obfa01y",uiAttribs:{},portsIn:[{name:"Row Offset",value:0},{name:"Center",value:1}],portsOut:[{name:"Result",links:[{portIn:"Array in xyz",portOut:"Result",objIn:"trc8ccbyd",objOut:"t5obfa01y"}]},{name:"Total points",links:[{portIn:"Array length",portOut:"Total points",objIn:"7005l0z1t",objOut:"t5obfa01y"},{portIn:"Length",portOut:"Total points",objIn:"cijeom9ac",objOut:"t5obfa01y"}]},{name:"Array length",value:675}],objName:"Ops.Array.PointArray.PointsPlane_v2"},{id:"98kgurdrw",uiAttribs:{},portsIn:[{name:"value",value:15}],portsOut:[{name:"result",links:[{portIn:"Rows",portOut:"result",objIn:"t5obfa01y",objOut:"98kgurdrw"},{portIn:"Columns",portOut:"result",objIn:"t5obfa01y",objOut:"98kgurdrw"},{portIn:"value",portOut:"result",objIn:"jwpzg8120",objOut:"98kgurdrw"}]}],objName:"Ops.Number.Number"},{id:"jwpzg8120",uiAttribs:{},portsIn:[{name:"old min",value:1},{name:"old max",value:24.64},{name:"new min",value:0},{name:"new max",value:29.98},{name:"Easing index",value:0},{name:"Easing",value:"Linear"},{name:"Clamp",value:1}],portsOut:[{name:"result",links:[{portIn:"Width",portOut:"result",objIn:"t5obfa01y",objOut:"jwpzg8120"},{portIn:"Height",portOut:"result",objIn:"t5obfa01y",objOut:"jwpzg8120"}]}],objName:"Ops.Math.MapRange"},{id:"y5nio1yke",uiAttribs:{},portsIn:[{name:"Milliseconds",value:450}],portsOut:[{name:"Out Trigger",links:[{portIn:"Set",portOut:"Out Trigger",objIn:"iqqd25x26",objOut:"y5nio1yke"}]},{name:"Progress",value:.22133333325386048}],objName:"Ops.Trigger.TriggerLimiter"},{id:"trc8ccbyd",uiAttribs:{},portsOut:[{name:"Array 1 out",links:[{portIn:"Array 1",portOut:"Array 1 out",objIn:"zqrc9mgp6",objOut:"trc8ccbyd"}]},{name:"Array 2 out",links:[{portIn:"Array 2",portOut:"Array 2 out",objIn:"zqrc9mgp6",objOut:"trc8ccbyd"}]},{name:"Array lengths",value:225}],objName:"Ops.Array.ArrayUnpack3"},{id:"zqrc9mgp6",uiAttribs:{},portsOut:[{name:"Array out",links:[{portIn:"Positions",portOut:"Array out",objIn:"n5bglnnn4",objOut:"zqrc9mgp6"}]},{name:"Num Points",value:225},{name:"Array length",value:675}],objName:"Ops.Array.ArrayPack3"},{id:"7005l0z1t",uiAttribs:{},portsIn:[{name:"Mode select index",value:0},{name:"Mode select",value:"Number"},{name:"Default Value",value:0},{name:"Reverse",value:0}],portsOut:[{name:"Array",links:[{portIn:"Array 3",portOut:"Array",objIn:"zqrc9mgp6",objOut:"7005l0z1t"}]},{name:"Array length out",value:225}],objName:"Ops.Array.Array_v3"},{id:"cijeom9ac",uiAttribs:{},portsIn:[{name:"chars",value:"muu"}],portsOut:[{name:"Result",links:[{portIn:"Text",portOut:"Result",objIn:"n5bglnnn4",objOut:"cijeom9ac"}]}],objName:"Ops.String.RandomString_v3"},{id:"iqqd25x26",uiAttribs:{},portsOut:[{name:"Out Value",links:[{portIn:"Seed",portOut:"Out Value",objIn:"cijeom9ac",objOut:"iqqd25x26"}]}],objName:"Ops.Trigger.TriggerNumber"},{id:"j7msg2abj",uiAttribs:{},portsOut:[{name:"Trigger out",links:[{portIn:"exe",portOut:"Trigger out",objIn:"6ad762m19",objOut:"j7msg2abj"}]}],objName:"Ops.Trigger.GateTrigger"},{id:"rfpj4guxc",uiAttribs:{},portsIn:[{name:"Variable",value:"fft"}],portsOut:[{name:"Value",links:[{portIn:"array",portOut:"Value",objIn:"trznoek4e",objOut:"rfpj4guxc"}]}],objName:"Ops.Vars.VarGetArray_v2"},{id:"trznoek4e",uiAttribs:{},portsIn:[{name:"index",value:30},{name:"Value Invalid Index",value:0}],portsOut:[{name:"value",links:[{portIn:"value",portOut:"value",objIn:"xh1p9151f",objOut:"trznoek4e"}]},{name:"Valid Index",value:1}],objName:"Ops.Array.ArrayGetNumber"},{id:"xh1p9151f",uiAttribs:{},portsIn:[{name:"old min",value:0},{name:"old max",value:255},{name:"new min",value:0},{name:"new max",value:1},{name:"Easing index",value:0},{name:"Easing",value:"Linear"},{name:"Clamp",value:1}],portsOut:[{name:"result",links:[{portIn:"Number",portOut:"result",objIn:"iqqd25x26",objOut:"xh1p9151f"}]}],objName:"Ops.Math.MapRange"},{id:"b27gk6zcj",uiAttribs:{},portsIn:[{name:"Variable",value:"fft"}],portsOut:[{name:"Value",links:[{portIn:"array",portOut:"Value",objIn:"w0rb2lpdq",objOut:"b27gk6zcj"}]}],objName:"Ops.Vars.VarGetArray_v2"},{id:"w0rb2lpdq",uiAttribs:{},portsIn:[{name:"index",value:40},{name:"Value Invalid Index",value:0}],portsOut:[{name:"value",links:[{portIn:"value",portOut:"value",objIn:"vg6n1acye",objOut:"w0rb2lpdq"}]},{name:"Valid Index",value:1}],objName:"Ops.Array.ArrayGetNumber"},{id:"vg6n1acye",uiAttribs:{},portsIn:[{name:"old min",value:10},{name:"old max",value:100},{name:"new min",value:0},{name:"new max",value:100},{name:"Easing index",value:0},{name:"Easing",value:"Linear"},{name:"Clamp",value:1}],portsOut:[{name:"result",value:0}],objName:"Ops.Math.MapRange"},{id:"gs4diqgqa",uiAttribs:{},portsIn:[{name:"Value",value:0,animated:true,anim:{keys:[{t:0,v:0,e:1},{t:21.20000000000002,v:1,e:1},{t:42.43333333333333,v:0,e:1},{t:57.63333333333335,v:1,e:1},{t:80.4666666666668,v:0,e:1}],loop:false}},{name:"Variable",value:"moo",animated:true,anim:{keys:[{t:0,v:"moo",e:0}],loop:false}}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"j13rh29l1",uiAttribs:{},portsIn:[{name:"Variable",value:"moo"}],portsOut:[{name:"Value",links:[{portIn:"Pass Through",portOut:"Value",objIn:"j7msg2abj",objOut:"j13rh29l1"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"2ovhdqoab",uiAttribs:{},portsIn:[{name:"Title",value:"Moo"}],objName:"Ops.Ui.Area"},{id:"zexqhyoti",uiAttribs:{},portsIn:[{name:"Title",value:"Cow"}],objName:"Ops.Ui.Area"},{id:"m2gbrkpg4",uiAttribs:{},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"uoy6ojcg5",objOut:"m2gbrkpg4"}]},{name:"trigger 6",links:[{portIn:"exe",portOut:"trigger 6",objIn:"3nlqb4j6y",objOut:"m2gbrkpg4"}]}],objName:"Ops.Trigger.Sequence"},{id:"xu9a2w955",uiAttribs:{},portsIn:[{name:"Title",value:"Overlay"}],objName:"Ops.Ui.Area"},{id:"63pv82vgx",uiAttribs:{},portsIn:[{name:"Title",value:"Outro"}],objName:"Ops.Ui.Area"},{id:"4avojokjc",uiAttribs:{},portsOut:[{name:"trigger 13",links:[{portIn:"render",portOut:"trigger 13",objIn:"lwi2fnm5w",objOut:"4avojokjc"}]},{name:"trigger 14",links:[{portIn:"render",portOut:"trigger 14",objIn:"ggdtwku2n",objOut:"4avojokjc"}]},{name:"trigger 15",links:[{portIn:"render",portOut:"trigger 15",objIn:"imoxmq2m0",objOut:"4avojokjc"}]}],objName:"Ops.Trigger.Sequence"},{id:"nl9t4bdsf",uiAttribs:{},portsIn:[{name:"r",value:.09803921568627448},{name:"g",value:.8196078431372549},{name:"b",value:.13096078431372538},{name:"a",value:1},{name:"colorizeTexture",value:0},{name:"Vertex Colors",value:0},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Opacity TexCoords Transform",value:0},{name:"Discard Transparent Pixels",value:0},{name:"diffuseRepeatX",value:1},{name:"diffuseRepeatY",value:1},{name:"Tex Offset X",value:0},{name:"Tex Offset Y",value:0},{name:"Crop TexCoords",value:0},{name:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"pvsiigp1y",objOut:"nl9t4bdsf"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"fzzswjwe1",uiAttribs:{},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:-.21},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"nl9t4bdsf",objOut:"fzzswjwe1"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"pvsiigp1y",uiAttribs:{},portsIn:[{name:"radius",value:.35},{name:"innerRadius",value:0},{name:"segments",value:40},{name:"percent",value:1},{name:"steps",value:0},{name:"invertSteps",value:0},{name:"mapping index",value:0},{name:"mapping",value:"flat"},{name:"Spline",value:0},{name:"Draw",value:1,title:"Render mesh"}],objName:"Ops.Gl.Meshes.Circle_v3"},{id:"rgc2hi6nr",uiAttribs:{},portsIn:[{name:"Text",value:"oklien"},{name:"Letter Spacing",value:1},{name:"align index",value:1},{name:"align",value:"center"},{name:"Render",value:1}],objName:"Ops.Gl.LineFont_v2"},{id:"g0l3tk00f",uiAttribs:{},portsIn:[{name:"posX",value:-1},{name:"posY",value:0},{name:"posZ",value:0},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"rgc2hi6nr",objOut:"g0l3tk00f"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"7ofx6q62f",uiAttribs:{},portsIn:[{name:"Text",value:"Skuggemannen"},{name:"Letter Spacing",value:1},{name:"align index",value:1},{name:"align",value:"center"},{name:"Render",value:1}],objName:"Ops.Gl.LineFont_v2"},{id:"s8v034ulr",uiAttribs:{},portsIn:[{name:"posX",value:0},{name:"posY",value:.5},{name:"posZ",value:0},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"7ofx6q62f",objOut:"s8v034ulr"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"s8uge8box",uiAttribs:{},portsIn:[{name:"Text",value:"Xoriath "},{name:"Letter Spacing",value:1},{name:"align index",value:1},{name:"align",value:"center"},{name:"Render",value:1}],objName:"Ops.Gl.LineFont_v2"},{id:"ysxmn4zyc",uiAttribs:{},portsIn:[{name:"posX",value:1},{name:"posY",value:0},{name:"posZ",value:0},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"s8uge8box",objOut:"ysxmn4zyc"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"j8jonpkj4",uiAttribs:{},portsIn:[{name:"Title",value:"Debug"}],objName:"Ops.Ui.Area"},{id:"akr3ebr3m",uiAttribs:{},portsIn:[{name:"Value",value:0,animated:true,anim:{keys:[{t:0,v:0,e:1},{t:6.5,v:1,e:1},{t:21.199999999999992,v:0,e:1},{t:42.43333333333333,v:1,e:1},{t:57.63333333333335,v:0,e:1}],loop:false}},{name:"Variable",value:"overlay"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"agal5axkh",uiAttribs:{},portsIn:[{name:"Value",value:0,animated:true,anim:{keys:[{t:0,v:0,e:1},{t:6.9333333333333345,v:1,e:1},{t:7.8000000000000025,v:2,e:1},{t:8.3,v:3,e:1},{t:9.133333333333335,v:4,e:1},{t:9.633333333333335,v:5,e:1},{t:10,v:6,e:1},{t:10.866666666666669,v:7,e:1},{t:11.833333333333336,v:8,e:1},{t:13.200000000000003,v:9,e:1},{t:14.333333333333334,v:10,e:1},{t:14.866666666666667,v:11,e:1},{t:15.866666666666667,v:12,e:1},{t:16.699999999999996,v:13,e:1},{t:17.26666666666665,v:14,e:1},{t:17.73333333333333,v:15,e:1},{t:18.199999999999992,v:16,e:1},{t:19.13333333333333,v:17,e:1},{t:19.699999999999978,v:18,e:1},{t:20.19999999999999,v:19,e:1},{t:42.199999999999996,v:21,e:1},{t:43.2,v:22,e:1},{t:44.03333333333333,v:23,e:1},{t:44.66666666666667,v:24,e:1},{t:45.3,v:25,e:1},{t:45.833333333333336,v:26,e:1},{t:46.43333333333334,v:27,e:1},{t:47.333333333333336,v:28,e:1},{t:48.2,v:29,e:1},{t:49,v:30,e:1},{t:50.466666666666676,v:31,e:1},{t:51.16666666666668,v:32,e:1},{t:51.96666666666668,v:33,e:1},{t:52.633333333333354,v:34,e:1},{t:53.13333333333335,v:35,e:1},{t:53.66666666666667,v:36,e:1},{t:54.06666666666667,v:37,e:1},{t:54.49999999999999,v:38,e:1},{t:55.46666666666667,v:39,e:1},{t:56.26666666666667,v:40,e:1}],loop:false}},{name:"Variable",value:"sing_index"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"x48lwvmf9",uiAttribs:{},portsIn:[{name:"Title",value:"Sing-along"}],objName:"Ops.Ui.Area"},{id:"xr8rmbf80",uiAttribs:{},portsIn:[{name:"Value",value:0,animated:true,anim:{keys:[{t:0,v:0,e:1},{t:20.63333333333328,v:1,e:1},{t:42.96666666666662,v:0,e:1},{t:57.6,v:1,e:1},{t:78.10000000000022,v:0,e:1}],loop:false}},{name:"Variable",value:"sing_along"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"k9pejgn0q",uiAttribs:{},portsIn:[{name:"Variable",value:"sing_along"}],portsOut:[{name:"Value",links:[{portIn:"Value",portOut:"Value",objIn:"ogmndcheg",objOut:"k9pejgn0q"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"5aujmffm0",uiAttribs:{},portsIn:[{name:"String 0",value:"                    Rauter lett mot vinden. En vakker klimagass. Bajser litt og svinger halen sin. Bonden lever på håpet og statens budsjett. Kine Ku, kjære du. Smelter is og hjerter, Kine Ku.                    "},{name:"String 1",value:"                    Rauter mot vinden, og raper metan. Bajser og svinger halen sin. Bonden lever i håpet på statens budsjett. Kine Ku, kjære ku. Du Smelter is og hjerter, Kine Ku.                    "},{name:"String 2",value:""},{name:"String 3",value:""},{name:"String 4",value:""},{name:"String 5",value:""},{name:"String 6",value:""},{name:"String 7",value:""},{name:"String 8",value:""},{name:"String 9",value:""}],portsOut:[{name:"Result",links:[{portIn:"String",portOut:"Result",objIn:"a6smd58z2",objOut:"5aujmffm0"},{portIn:"String",portOut:"Result",objIn:"e49dkttoj",objOut:"5aujmffm0"}]}],objName:"Ops.String.SwitchString"},{id:"1j99pyhh2",uiAttribs:{},portsIn:[{name:"Value",value:0,animated:true,anim:{keys:[{t:0,v:0,e:1},{t:20.433333333333334,v:0,e:1},{t:57.4,v:1,e:1}],loop:false}},{name:"Variable",value:"refreng"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"wbefj8jbx",uiAttribs:{},portsIn:[{name:"Variable",value:"refreng"}],portsOut:[{name:"Value",links:[{portIn:"Index",portOut:"Value",objIn:"5aujmffm0",objOut:"wbefj8jbx"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"hlpc7t9yb",uiAttribs:{},portsOut:[{name:"Trigger out",links:[{portIn:"exe",portOut:"Trigger out",objIn:"m2gbrkpg4",objOut:"hlpc7t9yb"}]}],objName:"Ops.Trigger.GateTrigger"},{id:"vlrnegvk5",uiAttribs:{},portsIn:[{name:"Variable",value:"cow"}],portsOut:[{name:"Value",links:[{portIn:"Pass Through",portOut:"Value",objIn:"hlpc7t9yb",objOut:"vlrnegvk5"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"5ot447fu3",uiAttribs:{},portsIn:[{name:"Value",value:1,animated:true,anim:{keys:[{t:0,v:1,e:0},{t:80.4666666666668,v:0,e:1}],loop:false}},{name:"Variable",value:"cow"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"hiyun7tcb",uiAttribs:{},portsIn:[{name:"Value",value:0,animated:true,anim:{keys:[{t:0,v:0,e:1},{t:80.4666666666668,v:1,e:1}],loop:false}},{name:"Variable",value:"outro"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"bx2brxqxb",uiAttribs:{},portsOut:[{name:"Trigger out",links:[{portIn:"exe",portOut:"Trigger out",objIn:"4avojokjc",objOut:"bx2brxqxb"}]}],objName:"Ops.Trigger.GateTrigger"},{id:"0y700p7e4",uiAttribs:{},portsIn:[{name:"Variable",value:"outro"}],portsOut:[{name:"Value",links:[{portIn:"Pass Through",portOut:"Value",objIn:"bx2brxqxb",objOut:"0y700p7e4"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"k5cafaqyf",uiAttribs:{},portsIn:[{name:"Samples",value:100},{name:"Y",value:-.36},{name:"Source Strength Map index",value:0},{name:"Source Strength Map",value:"R"},{name:"Invert Strength Map",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"e9ipwj8zz",objOut:"k5cafaqyf"}]}],objName:"Ops.Gl.ImageCompose.ZoomBlur_v2"},{id:"tcoxgteo6",uiAttribs:{},portsIn:[{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1},{name:"colorizeTexture",value:0},{name:"Vertex Colors",value:0},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Opacity TexCoords Transform",value:0},{name:"Discard Transparent Pixels",value:0},{name:"diffuseRepeatX",value:1},{name:"diffuseRepeatY",value:1},{name:"Tex Offset X",value:0},{name:"Tex Offset Y",value:0},{name:"Crop TexCoords",value:0},{name:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"s8v034ulr",objOut:"tcoxgteo6"},{portIn:"render",portOut:"trigger",objIn:"g0l3tk00f",objOut:"tcoxgteo6"},{portIn:"render",portOut:"trigger",objIn:"ysxmn4zyc",objOut:"tcoxgteo6"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"99hjahajk",uiAttribs:{},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:0},{name:"scale",value:1}],portsOut:[{name:"trigger",links:[{portIn:"exe",portOut:"trigger",objIn:"n8671t3b1",objOut:"99hjahajk"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"d2m52l8x5",uiAttribs:{},portsIn:[{name:"Speed",value:1},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"rotX",portOut:"Time",objIn:"99hjahajk",objOut:"d2m52l8x5"},{portIn:"rotY",portOut:"Time",objIn:"99hjahajk",objOut:"d2m52l8x5"},{portIn:"number1",portOut:"Time",objIn:"t9e5dvpyr",objOut:"d2m52l8x5"}]}],objName:"Ops.Anim.Timer_v2"},{id:"ie66n1qdy",uiAttribs:{},portsIn:[{name:"Amount of points",value:500},{name:"Sphere size",value:2},{name:"Random seed",value:0},{name:"Random distance from sphere",value:.5},{name:"Distribution index",value:0},{name:"Distribution",value:"Uniform"}],portsOut:[{name:"Array out",links:[{portIn:"Array",portOut:"Array out",objIn:"n8671t3b1",objOut:"ie66n1qdy"}]},{name:"Total points",value:500},{name:"Array length",value:1500}],objName:"Ops.Array.PointArray.PointsSphereRandom"},{id:"t9e5dvpyr",uiAttribs:{},portsIn:[{name:"number2",value:500}],portsOut:[{name:"result",links:[{portIn:"rotZ",portOut:"result",objIn:"99hjahajk",objOut:"t9e5dvpyr"}]}],objName:"Ops.Math.Sum"},{id:"n8671t3b1",uiAttribs:{},portsIn:[{name:"Array",title:"Positions"},{name:"Num Points",value:0},{name:"Scramble Texcoords",value:1},{name:"Seed",value:0},{name:"Coordinates",value:0,title:"Texture Coordinates"},{name:"Point sizes",value:0},{name:"Vertex Colors",value:0}],objName:"Ops.Gl.Meshes.PointCloudFromArray_v2"},{id:"ggdtwku2n",uiAttribs:{},portsIn:[{name:"PointSize",value:2},{name:"Size in Pixels",value:0},{name:"Random Size",value:10},{name:"Round",value:1},{name:"Round Antialias",value:1},{name:"Scale by Distance",value:1},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1},{name:"Vertex Colors",value:0},{name:"Colorize Texture",value:0},{name:"Mask Channel index",value:0},{name:"Mask Channel",value:"R"},{name:"Colorize Randomize",value:1},{name:"Point Size Channel index",value:0},{name:"Point Size Channel",value:"R"},{name:"Texture Point Size Mul",value:1},{name:"Map Size 0 index",value:0},{name:"Map Size 0",value:"Black"},{name:"Flip Texture",value:0},{name:"Atlas Cross Fade",value:0},{name:"Atlas Repeat X ",value:1},{name:"Min Point Size",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"99hjahajk",objOut:"ggdtwku2n"}]}],objName:"Ops.Gl.Shader.PointMaterial_v6"},{id:"lwi2fnm5w",uiAttribs:{},portsIn:[{name:"posX",value:0},{name:"posY",value:-.2},{name:"posZ",value:0},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"tcoxgteo6",objOut:"lwi2fnm5w"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"6eslwtmmv",uiAttribs:{},portsIn:[{name:"Variable",value:"outro"}],portsOut:[{name:"Value",links:[{portIn:"Strength",portOut:"Value",objIn:"k5cafaqyf",objOut:"6eslwtmmv"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"r8exldps0",uiAttribs:{},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"Sine"},{name:"phase",value:0},{name:"frequency",value:1},{name:"amplitude",value:1}],portsOut:[{name:"result",links:[{portIn:"X",portOut:"result",objIn:"k5cafaqyf",objOut:"r8exldps0"}]}],objName:"Ops.Anim.SineAnim"},{id:"kiw0r56gc",uiAttribs:{},portsIn:[{name:"radius",value:.25},{name:"stacks",value:32},{name:"slices",value:32},{name:"Filloffset",value:1},{name:"Render",value:1}],objName:"Ops.Gl.Meshes.Sphere_v3"},{id:"cesk3heug",uiAttribs:{},portsIn:[{name:"Scale index",value:1},{name:"Scale",value:"Fit"},{name:"Flip Y",value:0},{name:"Flip X",value:0}],objName:"Ops.Gl.Meshes.FullscreenRectangle_v2"},{id:"imoxmq2m0",uiAttribs:{},portsIn:[{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"colorizeTexture",value:0},{name:"Vertex Colors",value:0},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Opacity TexCoords Transform",value:0},{name:"Discard Transparent Pixels",value:0},{name:"diffuseRepeatX",value:1},{name:"diffuseRepeatY",value:1},{name:"Tex Offset X",value:0},{name:"Tex Offset Y",value:0},{name:"Crop TexCoords",value:0},{name:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"cesk3heug",objOut:"imoxmq2m0"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"eqpwb4dpp",uiAttribs:{},portsIn:[{name:"Value",value:0,animated:true,anim:{keys:[{t:0,v:0,e:0},{t:80.3666666666668,v:0,e:0},{t:84.16666666666671,v:1,e:0}],loop:false}},{name:"Variable",value:"fadeout"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"ovkxd9uxk",uiAttribs:{},portsIn:[{name:"Variable",value:"fadeout"}],portsOut:[{name:"Value",links:[{portIn:"a",portOut:"Value",objIn:"imoxmq2m0",objOut:"ovkxd9uxk"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"eye84kfsw",uiAttribs:{},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"rotX",portOut:"result",objIn:"uoy6ojcg5",objOut:"eye84kfsw"}]}],objName:"Ops.Math.Divide"},{id:"bfqskmu5w",uiAttribs:{},portsIn:[{name:"SpeedX",value:2},{name:"SpeedY",value:3},{name:"RepeatX",value:11},{name:"RepeatY",value:11},{name:"Multiply",value:.01},{name:"Source Amount Map index",value:0},{name:"Source Amount Map",value:"R"},{name:"Invert Amount Map",value:0}],portsOut:[{name:"Trigger",links:[{portIn:"render",portOut:"Trigger",objIn:"g6422z26v",objOut:"bfqskmu5w"}]}],objName:"Ops.Gl.ImageCompose.Wobble_v2"},{id:"gkpnwopqs",uiAttribs:{},portsIn:[{name:"Speed",value:.5},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"time",portOut:"Time",objIn:"bfqskmu5w",objOut:"gkpnwopqs"}]}],objName:"Ops.Anim.Timer_v2"},{id:"amopgxgo5",uiAttribs:{},portsIn:[{name:"Separate inc/dec",value:0},{name:"Inc factor",value:4,title:"Inc/Dec factor"},{name:"Dec factor",value:4}],portsOut:[{name:"Result",links:[{portIn:"Value",portOut:"Result",objIn:"qr27mughl",objOut:"amopgxgo5"}]}],objName:"Ops.Anim.Smooth"},{id:"qr27mughl",uiAttribs:{},portsIn:[{name:"Variable",value:"average_volume"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"upselmbdy",uiAttribs:{},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Amount",value:.02},{name:"Threshold",value:0},{name:"Animated",value:0},{name:"RGB",value:0},{name:"Normalize",value:0}],objName:"Ops.Gl.ImageCompose.Noise.Noise_v2"},{id:"v044eejvc",uiAttribs:{},portsIn:[{name:"Variable",value:"average_volume"}],portsOut:[{name:"Value",links:[{portIn:"number1",portOut:"Value",objIn:"1ibf7g98x",objOut:"v044eejvc"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"1ibf7g98x",uiAttribs:{},portsIn:[{name:"number2",value:.6}],portsOut:[{name:"result",value:.005449943125966069}],objName:"Ops.Math.Multiply"},{id:"26t2kc9sc",uiAttribs:{},portsIn:[{name:"Times",value:0},{name:"Manual Timestamps",value:0},{name:"ReRender on Resize",value:1}],portsOut:[{name:"Progress",value:1},{name:"Num Events",value:0}],objName:"Ops.TimeLine.DemoPrerender"},{id:"w01vd836r",uiAttribs:{},portsIn:[{name:"Value",value:1},{name:"Variable",value:"prerender"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"19n0w3hie",uiAttribs:{},portsIn:[{name:"Variable",value:"prerender"}],portsOut:[{name:"Value",links:[{portIn:"Record Events",portOut:"Value",objIn:"26t2kc9sc",objOut:"19n0w3hie"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"8gcw98ngx",uiAttribs:{},portsOut:[{name:"time",links:[{portIn:"number1",portOut:"time",objIn:"87heq8cmj",objOut:"8gcw98ngx"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"87heq8cmj",uiAttribs:{},portsOut:[{name:"result",links:[{portIn:"Value",portOut:"result",objIn:"bc1vrcq1e",objOut:"87heq8cmj"}]}],objName:"Ops.Math.Compare.GreaterThan"},{id:"3apqqqg5g",uiAttribs:{},portsIn:[{name:"Variable",value:"duration"}],portsOut:[{name:"Value",links:[{portIn:"number2",portOut:"Value",objIn:"87heq8cmj",objOut:"3apqqqg5g"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"bc1vrcq1e",uiAttribs:{},portsOut:[{name:"Next",links:[{portIn:"exe",portOut:"Next",objIn:"yt3kulpon",objOut:"bc1vrcq1e"}]}],objName:"Ops.Boolean.TriggerChangedTrue"},{id:"2j2mla7yb",uiAttribs:{},portsIn:[{name:"Set current time",value:0}],portsOut:[{name:"is Playing",value:false},{name:"set time (seconds)",value:0},{name:"current time",value:0},{name:"current frame",value:0}],objName:"Ops.TimeLine.TimeLinePlayer"},{id:"6hi0suu38",uiAttribs:{},portsIn:[{name:"CSS Cursors index",value:2},{name:"CSS Cursors",value:"pointer"},{name:"Set Parent Element",value:1}],objName:"Ops.Html.Cursor_v2"},{id:"0uguzc9ko",uiAttribs:{},portsOut:[{name:"Next",links:[{portIn:"Play",portOut:"Next",objIn:"47sr1uddy",objOut:"0uguzc9ko"}]}],objName:"Ops.TimeLine.TimeLineRewind"},{id:"867t2upoz",uiAttribs:{},portsIn:[{name:"CSS Cursors index",value:17},{name:"CSS Cursors",value:"none"},{name:"Set Parent Element",value:1}],portsOut:[{name:"Next",links:[{portIn:"exe",portOut:"Next",objIn:"0uguzc9ko",objOut:"867t2upoz"}]}],objName:"Ops.Html.Cursor_v2"},{id:"yt3kulpon",uiAttribs:{},portsOut:[{name:"trigger 0",links:[{portIn:"Pause",portOut:"trigger 0",objIn:"2j2mla7yb",objOut:"yt3kulpon"}]},{name:"trigger 1",links:[{portIn:"rewind",portOut:"trigger 1",objIn:"2j2mla7yb",objOut:"yt3kulpon"}]},{name:"trigger 2",links:[{portIn:"Update",portOut:"trigger 2",objIn:"6hi0suu38",objOut:"yt3kulpon"}]},{name:"trigger 15",links:[{portIn:"Reset",portOut:"trigger 15",objIn:"uz88jsinn",objOut:"yt3kulpon"}]}],objName:"Ops.Trigger.Sequence"},{id:"47sr1uddy",uiAttribs:{},portsOut:[{name:"Next",links:[{portIn:"Reset",portOut:"Next",objIn:"fyryn9elv",objOut:"47sr1uddy"}]}],objName:"Ops.TimeLine.TimeLinePlay"},{id:"hbmuwcein",uiAttribs:{},portsIn:[{name:"Font Name",value:"a94760d2-804b-4deb-bc26-aefda028b5af"},{name:"Font Data",value:"assets/MonumentExtended-Ultrabold.ttf.font.json",display:"file"},{name:"Font Image",value:"assets/MonumentExtended-Ultrabold.ttf_0.png",display:"file"},{name:"Font Image 1",value:"assets/MonumentExtended-Ultrabold.ttf_1.png",display:"file"},{name:"Font Image 2",value:"assets/MonumentExtended-Ultrabold.ttf_2.png",display:"file"},{name:"Font Image 3",value:0,display:"file"}],portsOut:[{name:"Loaded",value:true},{name:"Total Chars",value:188},{name:"Chars",value:"%ŒWœæwÆm#ý@¹ºÿ²ªµ³MjXÅ&©}({)»_«[]ŠÔÕÒÚÙÓÛQÌŽÉÀÈÎÑÝÍÊÃÂ§îíì-<>:,`’.·ÁYA¥VŸÄþÜÖKÇÏðËHåÐ€£N¢$ûêãâõéèkáàxšSúòùôóžØUCñOGø/B¶|äTïvf^l~itI!;¡z®°¯'pqüëygöçDJbPhRdonu8Þ0c4es+a6÷9¬=±×2Zß53?¿F7EL1r\"*"}],objName:"Ops.Gl.FontMSDF_v2"},{id:"rc02vet1o",uiAttribs:{},portsIn:[{name:"number1",value:1},{name:"number2",value:.5}],portsOut:[{name:"result",value:.5}],objName:"Ops.Math.Multiply"},{id:"56h7i4cxe",uiAttribs:{},portsIn:[{name:"number1",value:1},{name:"number2",value:.5}],portsOut:[{name:"result",value:.5}],objName:"Ops.Math.Multiply"},{id:"r9htictq7",uiAttribs:{},portsIn:[{name:"Variable",value:"average_volume"}],portsOut:[{name:"Value",links:[{portIn:"Radius",portOut:"Value",objIn:"g6422z26v",objOut:"r9htictq7"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"zwx5bi5od",uiAttribs:{},portsIn:[{name:"file",value:"assets/trist-jord.json",display:"file",title:"URL"},{name:"body",value:""},{name:"HTTP Method index",value:0},{name:"HTTP Method",value:"GET"},{name:"Content-Type",value:"application/json"},{name:"Content index",value:0},{name:"Content",value:"JSON",title:"Response Content"},{name:"Auto request",value:1},{name:"Send Credentials",value:0}],portsOut:[{name:"Response String",links:[{portIn:"JSON String",portOut:"Response String",objIn:"dpoa79qmu",objOut:"zwx5bi5od"}]},{name:"Response Data Url",value:"blob:file:///ff0b194d-1577-4c68-81e4-e9996e091ef8"},{name:"Duration MS",value:152},{name:"Status Code",value:200},{name:"Is Loading",value:0}],objName:"Ops.Json.HttpRequest_v3"},{id:"most2c4r0",uiAttribs:{},portsIn:[{name:"Play Mode index",value:0},{name:"Play Mode",value:"Auto"},{name:"frame",value:0},{name:"play",value:1},{name:"speed",value:1},{name:"texture width",value:1024},{name:"texture height",value:1024},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"wrap index",value:2},{name:"wrap",value:"clamp to edge"},{name:"scale index",value:0},{name:"scale",value:"fit"}],portsOut:[{name:"texture",links:[{portIn:"texture",portOut:"texture",objIn:"18me3cnxz",objOut:"most2c4r0"},{portIn:"Texture In",portOut:"texture",objIn:"1v7hmiqep",objOut:"most2c4r0"}]},{name:"Total Frames",value:176}],objName:"Ops.Extension.Lottie.LottieTexturePlayer_v2"},{id:"18me3cnxz",uiAttribs:{},portsIn:[{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"a",value:0,animated:true,anim:{keys:[{t:0,v:0,e:0},{t:72.63333333333334,v:0,e:25},{t:77.66666666666671,v:1,e:25}],loop:false}},{name:"colorizeTexture",value:0},{name:"Vertex Colors",value:0},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Opacity TexCoords Transform",value:0},{name:"Discard Transparent Pixels",value:1},{name:"diffuseRepeatX",value:1},{name:"diffuseRepeatY",value:1},{name:"Tex Offset X",value:0},{name:"Tex Offset Y",value:0},{name:"Crop TexCoords",value:0},{name:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"5n2axbn4d",objOut:"18me3cnxz"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"5n2axbn4d",uiAttribs:{},portsIn:[{name:"render",title:"Trigger"},{name:"Render Mesh",value:1,title:"Render"},{name:"width",value:1},{name:"height",value:1},{name:"pivot x index",value:1},{name:"pivot x",value:"center"},{name:"pivot y index",value:1},{name:"pivot y",value:"center"},{name:"axis index",value:0},{name:"axis",value:"xy"},{name:"Flip TexCoord X",value:0},{name:"Flip TexCoord Y",value:1},{name:"num columns",value:1},{name:"num rows",value:1}],objName:"Ops.Gl.Meshes.Rectangle_v4"},{id:"mvza4x2pt",uiAttribs:{},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:0},{name:"scale",value:4},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"18me3cnxz",objOut:"mvza4x2pt"},{portIn:"exe",portOut:"trigger",objIn:"most2c4r0",objOut:"mvza4x2pt"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"dpoa79qmu",uiAttribs:{},portsOut:[{name:"Result",links:[{portIn:"JSON Data",portOut:"Result",objIn:"most2c4r0",objOut:"dpoa79qmu"}]},{name:"Valid",value:1}],objName:"Ops.Json.ParseObject_v2"},{id:"7a34hjy3d",uiAttribs:{},portsOut:[{name:"trigger 0",links:[{portIn:"Execute",portOut:"trigger 0",objIn:"rdqa84r7q",objOut:"7a34hjy3d"}]},{name:"trigger 5",links:[{portIn:"Execute",portOut:"trigger 5",objIn:"hbnctjblo",objOut:"7a34hjy3d"}]},{name:"trigger 12",links:[{portIn:"Execute",portOut:"trigger 12",objIn:"va9x9m0bi",objOut:"7a34hjy3d"}]},{name:"trigger 14",links:[{portIn:"Execute",portOut:"trigger 14",objIn:"4tslledqw",objOut:"7a34hjy3d"}]},{name:"trigger 15",links:[{portIn:"Execute",portOut:"trigger 15",objIn:"ehuwjol4j",objOut:"7a34hjy3d"}]}],objName:"Ops.Trigger.Sequence"},{id:"gtz6ej5yh",uiAttribs:{},portsIn:[{name:"file",value:"assets/boom.json",display:"file",title:"URL"},{name:"body",value:""},{name:"HTTP Method index",value:0},{name:"HTTP Method",value:"GET"},{name:"Content-Type",value:"application/json"},{name:"Content index",value:0},{name:"Content",value:"JSON",title:"Response Content"},{name:"Auto request",value:1},{name:"Send Credentials",value:0}],portsOut:[{name:"Response String",links:[{portIn:"JSON String",portOut:"Response String",objIn:"ds567c05w",objOut:"gtz6ej5yh"}]},{name:"Response Data Url",value:""},{name:"Duration MS",value:112},{name:"Status Code",value:200},{name:"Is Loading",value:0}],objName:"Ops.Json.HttpRequest_v3"},{id:"2vqjwcpdb",uiAttribs:{},portsIn:[{name:"Play Mode index",value:1},{name:"Play Mode",value:"Frame"},{name:"play",value:1},{name:"speed",value:1},{name:"texture width",value:1024},{name:"texture height",value:1024},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"wrap index",value:2},{name:"wrap",value:"clamp to edge"},{name:"scale index",value:0},{name:"scale",value:"fit"}],portsOut:[{name:"texture",links:[{portIn:"Texture In",portOut:"texture",objIn:"dc2pzkawa",objOut:"2vqjwcpdb"},{portIn:"texture",portOut:"texture",objIn:"56fqemzoj",objOut:"2vqjwcpdb"}]},{name:"Total Frames",links:[{portIn:"number2",portOut:"Total Frames",objIn:"klygc7pp4",objOut:"2vqjwcpdb"}]}],objName:"Ops.Extension.Lottie.LottieTexturePlayer_v2"},{id:"dc2pzkawa",uiAttribs:{},portsIn:[{name:"Show Info",value:0},{name:"Visualize outside 0-1 index",value:1},{name:"Visualize outside 0-1",value:"Anim"},{name:"Alpha index",value:0},{name:"Alpha",value:"A"},{name:"Show Color",value:0},{name:"X",value:.5},{name:"Y",value:.5}],portsOut:[{name:"Info",value:"1024x1024 RGBA 8bit ubyte mipmap clamp\n"}],objName:"Ops.Ui.VizTexture"},{id:"56fqemzoj",uiAttribs:{},portsIn:[{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"a",value:1},{name:"colorizeTexture",value:0},{name:"Vertex Colors",value:0},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Opacity TexCoords Transform",value:0},{name:"Discard Transparent Pixels",value:1},{name:"diffuseRepeatX",value:1},{name:"diffuseRepeatY",value:1},{name:"Tex Offset X",value:0},{name:"Tex Offset Y",value:0},{name:"Crop TexCoords",value:0},{name:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"lqxhen0gy",objOut:"56fqemzoj"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"lqxhen0gy",uiAttribs:{},portsIn:[{name:"render",title:"Trigger"},{name:"Render Mesh",title:"Render"},{name:"width",value:1},{name:"height",value:1},{name:"pivot x index",value:1},{name:"pivot x",value:"center"},{name:"pivot y index",value:1},{name:"pivot y",value:"center"},{name:"axis index",value:0},{name:"axis",value:"xy"},{name:"Flip TexCoord X",value:0},{name:"Flip TexCoord Y",value:1},{name:"num columns",value:1},{name:"num rows",value:1}],objName:"Ops.Gl.Meshes.Rectangle_v4"},{id:"3knrlhgjo",uiAttribs:{},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:0},{name:"scale",value:4},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"56fqemzoj",objOut:"3knrlhgjo"},{portIn:"exe",portOut:"trigger",objIn:"2vqjwcpdb",objOut:"3knrlhgjo"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"ds567c05w",uiAttribs:{},portsOut:[{name:"Result",links:[{portIn:"JSON Data",portOut:"Result",objIn:"2vqjwcpdb",objOut:"ds567c05w"}]},{name:"Valid",value:1}],objName:"Ops.Json.ParseObject_v2"},{id:"28s2khnhs",uiAttribs:{},portsIn:[{name:"Speed",value:30},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"number1",portOut:"Time",objIn:"4mm9wdp6x",objOut:"28s2khnhs"}]}],objName:"Ops.Anim.Timer_v2"},{id:"klygc7pp4",uiAttribs:{},portsIn:[{name:"pingpong",value:0}],portsOut:[{name:"result",links:[{portIn:"frame",portOut:"result",objIn:"2vqjwcpdb",objOut:"klygc7pp4"}]}],objName:"Ops.Math.Modulo"},{id:"4mm9wdp6x",uiAttribs:{},portsIn:[{name:"number2",value:1}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"klygc7pp4",objOut:"4mm9wdp6x"}]}],objName:"Ops.Math.Multiply"},{id:"5ats20sl7",uiAttribs:{},portsIn:[{name:"Integer",value:1}],portsOut:[{name:"Number out",links:[{portIn:"Play",portOut:"Number out",objIn:"28s2khnhs",objOut:"5ats20sl7"},{portIn:"Render Mesh",portOut:"Number out",objIn:"lqxhen0gy",objOut:"5ats20sl7"}]}],objName:"Ops.Number.Integer"},{id:"rdqa84r7q",uiAttribs:{},portsIn:[{name:"Pass Through",value:0,animated:true,anim:{keys:[{t:0,v:0,e:1},{t:72.73333333333338,v:1,e:1},{t:80.60000000000008,v:0,e:0}],loop:false}}],portsOut:[{name:"Trigger out",links:[{portIn:"render",portOut:"Trigger out",objIn:"mvza4x2pt",objOut:"rdqa84r7q"},{portIn:"Exec",portOut:"Trigger out",objIn:"fyryn9elv",objOut:"rdqa84r7q"}]}],objName:"Ops.Trigger.GateTrigger"},{id:"4tslledqw",uiAttribs:{},portsIn:[{name:"Pass Through",value:0,animated:true,anim:{keys:[{t:0,v:0,e:1},{t:80.46666666666668,v:1,e:1},{t:82.0333333333333,v:0,e:0}],loop:false}}],portsOut:[{name:"Trigger out",links:[{portIn:"render",portOut:"Trigger out",objIn:"3knrlhgjo",objOut:"4tslledqw"}]}],objName:"Ops.Trigger.GateTrigger"},{id:"1v7hmiqep",uiAttribs:{},portsIn:[{name:"Show Info",value:0},{name:"Visualize outside 0-1 index",value:1},{name:"Visualize outside 0-1",value:"Anim"},{name:"Alpha index",value:0},{name:"Alpha",value:"A"},{name:"Show Color",value:0},{name:"X",value:.5},{name:"Y",value:.5}],portsOut:[{name:"Info",value:"1024x1024 RGBA 8bit ubyte mipmap clamp\n"}],objName:"Ops.Ui.VizTexture"},{id:"82zjrfr2v",uiAttribs:{},portsIn:[{name:"file",value:"assets/noter.json",display:"file",title:"URL"},{name:"body",value:""},{name:"HTTP Method index",value:0},{name:"HTTP Method",value:"GET"},{name:"Content-Type",value:"application/json"},{name:"Content index",value:0},{name:"Content",value:"JSON",title:"Response Content"},{name:"Auto request",value:1},{name:"Send Credentials",value:0}],portsOut:[{name:"Response String",links:[{portIn:"JSON String",portOut:"Response String",objIn:"v04s6z9t0",objOut:"82zjrfr2v"}]},{name:"Response Data Url",value:""},{name:"Duration MS",value:100},{name:"Status Code",value:200},{name:"Is Loading",value:0}],objName:"Ops.Json.HttpRequest_v3"},{id:"38z6m71jd",uiAttribs:{},portsIn:[{name:"Play Mode index",value:1},{name:"Play Mode",value:"Frame"},{name:"play",value:1},{name:"speed",value:1},{name:"texture width",value:1024},{name:"texture height",value:1024},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"wrap index",value:2},{name:"wrap",value:"clamp to edge"},{name:"scale index",value:0},{name:"scale",value:"fit"}],portsOut:[{name:"texture",links:[{portIn:"Texture In",portOut:"texture",objIn:"loksxm40a",objOut:"38z6m71jd"},{portIn:"texture",portOut:"texture",objIn:"r1xk31qyu",objOut:"38z6m71jd"}]},{name:"Total Frames",links:[{portIn:"number2",portOut:"Total Frames",objIn:"p78izvote",objOut:"38z6m71jd"}]}],objName:"Ops.Extension.Lottie.LottieTexturePlayer_v2"},{id:"loksxm40a",uiAttribs:{},portsIn:[{name:"Show Info",value:0},{name:"Visualize outside 0-1 index",value:1},{name:"Visualize outside 0-1",value:"Anim"},{name:"Alpha index",value:0},{name:"Alpha",value:"A"},{name:"Show Color",value:0},{name:"X",value:.5},{name:"Y",value:.5}],portsOut:[{name:"Info",value:"1024x1024 RGBA 8bit ubyte mipmap clamp\n"}],objName:"Ops.Ui.VizTexture"},{id:"r1xk31qyu",uiAttribs:{},portsIn:[{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:.85},{name:"colorizeTexture",value:1},{name:"Vertex Colors",value:0},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Opacity TexCoords Transform",value:0},{name:"Discard Transparent Pixels",value:1},{name:"diffuseRepeatX",value:1},{name:"diffuseRepeatY",value:1},{name:"Tex Offset X",value:0},{name:"Tex Offset Y",value:0},{name:"Crop TexCoords",value:0},{name:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"mi0ct5ru3",objOut:"r1xk31qyu"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"mi0ct5ru3",uiAttribs:{},portsIn:[{name:"render",title:"Trigger"},{name:"Render Mesh",value:1,title:"Render"},{name:"width",value:1},{name:"height",value:1},{name:"pivot x index",value:1},{name:"pivot x",value:"center"},{name:"pivot y index",value:1},{name:"pivot y",value:"center"},{name:"axis index",value:0},{name:"axis",value:"xy"},{name:"Flip TexCoord X",value:0},{name:"Flip TexCoord Y",value:1},{name:"num columns",value:1},{name:"num rows",value:1}],objName:"Ops.Gl.Meshes.Rectangle_v4"},{id:"xzmvxqff1",uiAttribs:{},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:.2},{name:"rotX",value:-10},{name:"rotY",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"r1xk31qyu",objOut:"xzmvxqff1"},{portIn:"exe",portOut:"trigger",objIn:"38z6m71jd",objOut:"xzmvxqff1"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"v04s6z9t0",uiAttribs:{},portsOut:[{name:"Result",links:[{portIn:"JSON Data",portOut:"Result",objIn:"38z6m71jd",objOut:"v04s6z9t0"}]},{name:"Valid",value:1}],objName:"Ops.Json.ParseObject_v2"},{id:"8vhof9crt",uiAttribs:{},portsIn:[{name:"Speed",value:30},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"number1",portOut:"Time",objIn:"hgcggiptc",objOut:"8vhof9crt"}]}],objName:"Ops.Anim.Timer_v2"},{id:"p78izvote",uiAttribs:{},portsIn:[{name:"pingpong",value:0}],portsOut:[{name:"result",links:[{portIn:"frame",portOut:"result",objIn:"38z6m71jd",objOut:"p78izvote"}]}],objName:"Ops.Math.Modulo"},{id:"hgcggiptc",uiAttribs:{},portsIn:[{name:"number2",value:.6}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"p78izvote",objOut:"hgcggiptc"}]}],objName:"Ops.Math.Multiply"},{id:"ehuwjol4j",uiAttribs:{},portsIn:[{name:"Pass Through",value:0,animated:true,anim:{keys:[{t:0,v:0,e:1},{t:6.5,v:1,e:1},{t:21.566666666666666,v:0,e:1},{t:42.4,v:1,e:1},{t:57.6,v:0,e:1}],loop:false}}],portsOut:[{name:"Trigger out",links:[{portIn:"render",portOut:"Trigger out",objIn:"xzmvxqff1",objOut:"ehuwjol4j"},{portIn:"exe",portOut:"Trigger out",objIn:"tzhbivhky",objOut:"ehuwjol4j"}]}],objName:"Ops.Trigger.GateTrigger"},{id:"yriykrbwo",uiAttribs:{},portsIn:[{name:"title",value:"noter"},{name:"text",value:""}],objName:"Ops.Ui.Comment_v2"},{id:"tczxw88p0",uiAttribs:{},portsIn:[{name:"title",value:"boom"},{name:"text",value:""}],objName:"Ops.Ui.Comment_v2"},{id:"fkb12mn7e",uiAttribs:{},portsIn:[{name:"title",value:"jord"},{name:"text",value:""}],objName:"Ops.Ui.Comment_v2"},{id:"457r8mxi5",uiAttribs:{},portsIn:[{name:"Variable",value:"average_volume"}],portsOut:[{name:"Value",links:[{portIn:"number1",portOut:"Value",objIn:"dawi27dnl",objOut:"457r8mxi5"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"dawi27dnl",uiAttribs:{},portsIn:[{name:"number2",value:4}],portsOut:[{name:"result",links:[{portIn:"number2",portOut:"result",objIn:"me2z8vkp6",objOut:"dawi27dnl"}]}],objName:"Ops.Math.Multiply"},{id:"me2z8vkp6",uiAttribs:{},portsIn:[{name:"number1",value:4}],portsOut:[{name:"result",links:[{portIn:"scale",portOut:"result",objIn:"xzmvxqff1",objOut:"me2z8vkp6"}]}],objName:"Ops.Math.Sum"},{id:"tzhbivhky",uiAttribs:{},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"Sine"},{name:"phase",value:0},{name:"frequency",value:1},{name:"amplitude",value:20}],portsOut:[{name:"result",links:[{portIn:"rotZ",portOut:"result",objIn:"xzmvxqff1",objOut:"tzhbivhky"}]}],objName:"Ops.Anim.SineAnim"},{id:"6xx6m3wm5",uiAttribs:{},portsIn:[{name:"file",value:"assets/hjerter.json",display:"file",title:"URL"},{name:"body",value:""},{name:"HTTP Method index",value:0},{name:"HTTP Method",value:"GET"},{name:"Content-Type",value:"application/json"},{name:"Content index",value:0},{name:"Content",value:"JSON",title:"Response Content"},{name:"Auto request",value:1},{name:"Send Credentials",value:0}],portsOut:[{name:"Response String",links:[{portIn:"JSON String",portOut:"Response String",objIn:"r0t8hnzn2",objOut:"6xx6m3wm5"}]},{name:"Response Data Url",value:""},{name:"Duration MS",value:145},{name:"Status Code",value:200},{name:"Is Loading",value:0}],objName:"Ops.Json.HttpRequest_v3"},{id:"5izrn7f8o",uiAttribs:{},portsIn:[{name:"Play Mode index",value:1},{name:"Play Mode",value:"Frame"},{name:"play",value:1},{name:"speed",value:1},{name:"texture width",value:1024},{name:"texture height",value:1024},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"wrap index",value:2},{name:"wrap",value:"clamp to edge"},{name:"scale index",value:0},{name:"scale",value:"fit"}],portsOut:[{name:"texture",links:[{portIn:"Texture In",portOut:"texture",objIn:"oi9cush50",objOut:"5izrn7f8o"},{portIn:"texture",portOut:"texture",objIn:"vjcwv9bq1",objOut:"5izrn7f8o"}]},{name:"Total Frames",links:[{portIn:"number2",portOut:"Total Frames",objIn:"gejemmjql",objOut:"5izrn7f8o"}]}],objName:"Ops.Extension.Lottie.LottieTexturePlayer_v2"},{id:"oi9cush50",uiAttribs:{},portsIn:[{name:"Show Info",value:0},{name:"Visualize outside 0-1 index",value:1},{name:"Visualize outside 0-1",value:"Anim"},{name:"Alpha index",value:0},{name:"Alpha",value:"A"},{name:"Show Color",value:0},{name:"X",value:.5},{name:"Y",value:.5}],portsOut:[{name:"Info",value:"1024x1024 RGBA 8bit ubyte mipmap clamp\n"}],objName:"Ops.Ui.VizTexture"},{id:"vjcwv9bq1",uiAttribs:{},portsIn:[{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:0,animated:true,anim:{keys:[{t:0,v:0,e:0},{t:21.533333333333335,v:0,e:0},{t:24.3,v:.6,e:0}],loop:false}},{name:"colorizeTexture",value:0},{name:"Vertex Colors",value:0},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Opacity TexCoords Transform",value:0},{name:"Discard Transparent Pixels",value:1},{name:"diffuseRepeatX",value:1},{name:"diffuseRepeatY",value:1},{name:"Tex Offset X",value:0},{name:"Tex Offset Y",value:0},{name:"Crop TexCoords",value:0},{name:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"vo9ywu2lu",objOut:"vjcwv9bq1"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"vo9ywu2lu",uiAttribs:{},portsIn:[{name:"render",title:"Trigger"},{name:"Render Mesh",value:1,title:"Render"},{name:"width",value:1},{name:"height",value:1},{name:"pivot x index",value:1},{name:"pivot x",value:"center"},{name:"pivot y index",value:1},{name:"pivot y",value:"center"},{name:"axis index",value:0},{name:"axis",value:"xy"},{name:"Flip TexCoord X",value:0},{name:"Flip TexCoord Y",value:1},{name:"num columns",value:1},{name:"num rows",value:1}],objName:"Ops.Gl.Meshes.Rectangle_v4"},{id:"naz733qwn",uiAttribs:{},portsIn:[{name:"posX",value:-.35},{name:"posY",value:0},{name:"posZ",value:1},{name:"rotX",value:-10},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"vjcwv9bq1",objOut:"naz733qwn"},{portIn:"exe",portOut:"trigger",objIn:"5izrn7f8o",objOut:"naz733qwn"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"r0t8hnzn2",uiAttribs:{},portsOut:[{name:"Result",links:[{portIn:"JSON Data",portOut:"Result",objIn:"5izrn7f8o",objOut:"r0t8hnzn2"}]},{name:"Valid",value:1}],objName:"Ops.Json.ParseObject_v2"},{id:"oh97bcqzv",uiAttribs:{},portsIn:[{name:"Speed",value:50},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"number1",portOut:"Time",objIn:"dm54002w7",objOut:"oh97bcqzv"}]}],objName:"Ops.Anim.Timer_v2"},{id:"gejemmjql",uiAttribs:{},portsIn:[{name:"pingpong",value:0}],portsOut:[{name:"result",links:[{portIn:"frame",portOut:"result",objIn:"5izrn7f8o",objOut:"gejemmjql"}]}],objName:"Ops.Math.Modulo"},{id:"dm54002w7",uiAttribs:{},portsIn:[{name:"number2",value:.5}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"gejemmjql",objOut:"dm54002w7"}]}],objName:"Ops.Math.Multiply"},{id:"va9x9m0bi",uiAttribs:{},portsIn:[{name:"Pass Through",value:0,animated:true,anim:{keys:[{t:0,v:0,e:1},{t:21.566666666666666,v:1,e:1},{t:42.43333333333333,v:0,e:1}],loop:false}}],portsOut:[{name:"Trigger out",links:[{portIn:"render",portOut:"Trigger out",objIn:"naz733qwn",objOut:"va9x9m0bi"}]}],objName:"Ops.Trigger.GateTrigger"},{id:"yvqce6m8p",uiAttribs:{},portsIn:[{name:"title",value:"hjerter"},{name:"text",value:""}],objName:"Ops.Ui.Comment_v2"},{id:"lpd5ho8fu",uiAttribs:{},portsIn:[{name:"Variable",value:"average_volume"}],portsOut:[{name:"Value",links:[{portIn:"number1",portOut:"Value",objIn:"gfim96j1g",objOut:"lpd5ho8fu"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"gfim96j1g",uiAttribs:{},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"number2",portOut:"result",objIn:"9twmg5h1t",objOut:"gfim96j1g"}]}],objName:"Ops.Math.Multiply"},{id:"9twmg5h1t",uiAttribs:{},portsIn:[{name:"number1",value:2}],portsOut:[{name:"result",links:[{portIn:"scale",portOut:"result",objIn:"naz733qwn",objOut:"9twmg5h1t"}]}],objName:"Ops.Math.Sum"},{id:"3cxfe7zf1",uiAttribs:{},portsIn:[{name:"file",value:"assets/blomster.json",display:"file",title:"URL"},{name:"body",value:""},{name:"HTTP Method index",value:0},{name:"HTTP Method",value:"GET"},{name:"Content-Type",value:"application/json"},{name:"Content index",value:0},{name:"Content",value:"JSON",title:"Response Content"},{name:"Auto request",value:1},{name:"Send Credentials",value:0}],portsOut:[{name:"Response String",links:[{portIn:"JSON String",portOut:"Response String",objIn:"gpbrd0na7",objOut:"3cxfe7zf1"}]},{name:"Response Data Url",value:""},{name:"Duration MS",value:262},{name:"Status Code",value:200},{name:"Is Loading",value:0}],objName:"Ops.Json.HttpRequest_v3"},{id:"xg16iof05",uiAttribs:{},portsIn:[{name:"Play Mode index",value:1},{name:"Play Mode",value:"Frame"},{name:"play",value:1},{name:"speed",value:1},{name:"texture width",value:1024},{name:"texture height",value:1024},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"wrap index",value:2},{name:"wrap",value:"clamp to edge"},{name:"scale index",value:0},{name:"scale",value:"fit"}],portsOut:[{name:"texture",links:[{portIn:"Texture In",portOut:"texture",objIn:"9lfovqxmo",objOut:"xg16iof05"},{portIn:"texture",portOut:"texture",objIn:"2a0y1mr31",objOut:"xg16iof05"}]},{name:"Total Frames",links:[{portIn:"number2",portOut:"Total Frames",objIn:"plan3wjh8",objOut:"xg16iof05"}]}],objName:"Ops.Extension.Lottie.LottieTexturePlayer_v2"},{id:"9lfovqxmo",uiAttribs:{},portsIn:[{name:"Show Info",value:0},{name:"Visualize outside 0-1 index",value:1},{name:"Visualize outside 0-1",value:"Anim"},{name:"Alpha index",value:0},{name:"Alpha",value:"A"},{name:"Show Color",value:0},{name:"X",value:.5},{name:"Y",value:.5}],portsOut:[{name:"Info",value:"1024x1024 RGBA 8bit ubyte mipmap clamp\n"}],objName:"Ops.Ui.VizTexture"},{id:"2a0y1mr31",uiAttribs:{},portsIn:[{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:0,animated:true,anim:{keys:[{t:0,v:0,e:0},{t:57.4,v:0,e:0},{t:62.20000000000011,v:1,e:0},{t:78.73333333333333,v:0,e:0}],loop:false}},{name:"colorizeTexture",value:0},{name:"Vertex Colors",value:0},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Opacity TexCoords Transform",value:0},{name:"Discard Transparent Pixels",value:1},{name:"diffuseRepeatX",value:1},{name:"diffuseRepeatY",value:1},{name:"Tex Offset X",value:0},{name:"Tex Offset Y",value:0},{name:"Crop TexCoords",value:0},{name:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"k2ws2ifxa",objOut:"2a0y1mr31"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"k2ws2ifxa",uiAttribs:{},portsIn:[{name:"render",title:"Trigger"},{name:"Render Mesh",value:1,title:"Render"},{name:"width",value:1},{name:"height",value:1},{name:"pivot x index",value:1},{name:"pivot x",value:"center"},{name:"pivot y index",value:1},{name:"pivot y",value:"center"},{name:"axis index",value:0},{name:"axis",value:"xy"},{name:"Flip TexCoord X",value:0},{name:"Flip TexCoord Y",value:1},{name:"num columns",value:1},{name:"num rows",value:1}],objName:"Ops.Gl.Meshes.Rectangle_v4"},{id:"2zdxvoqy2",uiAttribs:{},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:0},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"2a0y1mr31",objOut:"2zdxvoqy2"},{portIn:"exe",portOut:"trigger",objIn:"xg16iof05",objOut:"2zdxvoqy2"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"gpbrd0na7",uiAttribs:{},portsOut:[{name:"Result",links:[{portIn:"JSON Data",portOut:"Result",objIn:"xg16iof05",objOut:"gpbrd0na7"}]},{name:"Valid",value:1}],objName:"Ops.Json.ParseObject_v2"},{id:"uzr2vjs22",uiAttribs:{},portsIn:[{name:"Speed",value:50},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"number1",portOut:"Time",objIn:"v4xp1mrib",objOut:"uzr2vjs22"}]}],objName:"Ops.Anim.Timer_v2"},{id:"plan3wjh8",uiAttribs:{},portsIn:[{name:"pingpong",value:0}],portsOut:[{name:"result",links:[{portIn:"frame",portOut:"result",objIn:"xg16iof05",objOut:"plan3wjh8"}]}],objName:"Ops.Math.Modulo"},{id:"v4xp1mrib",uiAttribs:{},portsIn:[{name:"number2",value:1}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"plan3wjh8",objOut:"v4xp1mrib"}]}],objName:"Ops.Math.Multiply"},{id:"hbnctjblo",uiAttribs:{},portsIn:[{name:"Pass Through",value:0,animated:true,anim:{keys:[{t:0,v:0,e:1},{t:57.63333333333335,v:1,e:1},{t:80.33333333333333,v:0,e:1}],loop:false}}],portsOut:[{name:"Trigger out",links:[{portIn:"render",portOut:"Trigger out",objIn:"2zdxvoqy2",objOut:"hbnctjblo"}]}],objName:"Ops.Trigger.GateTrigger"},{id:"20ehypylg",uiAttribs:{},portsIn:[{name:"title",value:"blomster"},{name:"text",value:""}],objName:"Ops.Ui.Comment_v2"},{id:"u1eruqpt4",uiAttribs:{},portsIn:[{name:"Variable",value:"average_volume"}],portsOut:[{name:"Value",links:[{portIn:"number1",portOut:"Value",objIn:"2qeo79mla",objOut:"u1eruqpt4"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"2qeo79mla",uiAttribs:{},portsIn:[{name:"number2",value:1}],portsOut:[{name:"result",links:[{portIn:"number2",portOut:"result",objIn:"0vwg6jej4",objOut:"2qeo79mla"}]}],objName:"Ops.Math.Multiply"},{id:"0vwg6jej4",uiAttribs:{},portsIn:[{name:"number1",value:4}],portsOut:[{name:"result",links:[{portIn:"scale",portOut:"result",objIn:"2zdxvoqy2",objOut:"0vwg6jej4"}]}],objName:"Ops.Math.Sum"},{id:"fyryn9elv",uiAttribs:{},portsOut:[{name:"Next",links:[{portIn:"Rewind",portOut:"Next",objIn:"most2c4r0",objOut:"fyryn9elv"}]},{name:"Was Triggered",value:1}],objName:"Ops.Trigger.TriggerOnce"},{id:"uxnob00p2",uiAttribs:{},portsOut:[{name:"Next",links:[{portIn:"Generate",portOut:"Next",objIn:"q36r8sqjj",objOut:"uxnob00p2"},{portIn:"Generate",portOut:"Next",objIn:"rujg1vqgc",objOut:"uxnob00p2"},{portIn:"Generate",portOut:"Next",objIn:"bzfo2flp7",objOut:"uxnob00p2"}]},{name:"Number",links:[{portIn:"Index",portOut:"Number",objIn:"gxkxqw0a2",objOut:"uxnob00p2"}]}],objName:"Ops.Number.TriggerOnChangeNumber"},{id:"q36r8sqjj",uiAttribs:{},portsIn:[{name:"min",value:-.5},{name:"max",value:.5},{name:"Integer",value:0},{name:"No consecutive duplicates",value:0}],portsOut:[{name:"result",links:[{portIn:"posX",portOut:"result",objIn:"qctr68hay",objOut:"q36r8sqjj"}]}],objName:"Ops.Math.TriggerRandomNumber_v2"},{id:"rujg1vqgc",uiAttribs:{},portsIn:[{name:"min",value:.3},{name:"max",value:.5},{name:"Integer",value:0},{name:"No consecutive duplicates",value:0}],portsOut:[{name:"result",links:[{portIn:"posY",portOut:"result",objIn:"qctr68hay",objOut:"rujg1vqgc"}]}],objName:"Ops.Math.TriggerRandomNumber_v2"},{id:"bzfo2flp7",uiAttribs:{},portsIn:[{name:"min",value:-20},{name:"max",value:10},{name:"Integer",value:0},{name:"No consecutive duplicates",value:0}],portsOut:[{name:"result",links:[{portIn:"rotZ",portOut:"result",objIn:"qctr68hay",objOut:"bzfo2flp7"}]}],objName:"Ops.Math.TriggerRandomNumber_v2"},{id:"ogmndcheg",uiAttribs:{},portsOut:[{name:"Next",links:[{portIn:"Reset",portOut:"Next",objIn:"0t81rdk35",objOut:"ogmndcheg"}]},{name:"Number",links:[{portIn:"Pass Through",portOut:"Number",objIn:"v03dcp9mp",objOut:"ogmndcheg"}]}],objName:"Ops.Number.TriggerOnChangeNumber"}],export:{time:"2025-04-19 02:34",service:"exe",exportNumber:2}};if(!CABLES.exportedPatch){CABLES.exportedPatch=CABLES.exportedPatches["AKyCLI"]}"use strict";var CABLES=CABLES||{};CABLES.OPS=CABLES.OPS||{};var Ops=Ops||{};Ops.Gl=Ops.Gl||{};Ops.Ui=Ops.Ui||{};Ops.Anim=Ops.Anim||{};Ops.Html=Ops.Html||{};Ops.Json=Ops.Json||{};Ops.Math=Ops.Math||{};Ops.Vars=Ops.Vars||{};Ops.Array=Ops.Array||{};Ops.Cables=Ops.Cables||{};Ops.Number=Ops.Number||{};Ops.String=Ops.String||{};Ops.Boolean=Ops.Boolean||{};Ops.Trigger=Ops.Trigger||{};Ops.TimeLine=Ops.TimeLine||{};Ops.WebAudio=Ops.WebAudio||{};Ops.Extension=Ops.Extension||{};Ops.Gl.Matrix=Ops.Gl.Matrix||{};Ops.Gl.Meshes=Ops.Gl.Meshes||{};Ops.Gl.Shader=Ops.Gl.Shader||{};Ops.Html.Utils=Ops.Html.Utils||{};Ops.Gl.Textures=Ops.Gl.Textures||{};Ops.Math.Compare=Ops.Math.Compare||{};Ops.Gl.ImageCompose=Ops.Gl.ImageCompose||{};Ops.Array.PointArray=Ops.Array.PointArray||{};Ops.Extension.Lottie=Ops.Extension.Lottie||{};Ops.Gl.ImageCompose.Noise=Ops.Gl.ImageCompose.Noise||{};Ops.Gl.MainLoop_v2=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={};const t=i.inFloat("Max Pixel Density (DPR)",2),n=i.inValue("FPS Limit",0),r=i.inValueBool("Reduce FPS unfocussed",false),a=i.inValueBool("Transparent",false),s=i.inValueBool("Active",1),o=i.outTrigger("trigger"),l=i.outNumber("width"),u=i.outNumber("height"),h=i.outNumber("Pixel Density");i.onAnimFrame=C;t.onChange=A;const p=i.patch.cgl;let c=0;let m=0;let f=null;let d=false;if(!i.patch.cgl)i.uiAttr({error:"No webgl cgl context"});const g=vec3.create();vec3.set(g,0,0,0);const v=vec3.create();vec3.set(v,0,0,-2);let y=null;let b=true;let x=true;window.addEventListener("blur",()=>{b=false});window.addEventListener("focus",()=>{b=true});document.addEventListener("visibilitychange",()=>{x=!document.hidden});T();i.patch.tempData.mainloopOp=this;function A(){S();if(CABLES.UI){if(t.get()<1)i.patch.cgl.canvas.style.imageRendering="pixelated"}i.patch.cgl.updateSize();if(CABLES.UI)gui.setLayout()}s.onChange=function(){i.patch.removeOnAnimFrame(i);if(s.get()){i.setUiAttrib({extendTitle:""});i.onAnimFrame=C;i.patch.addOnAnimFrame(i);i.log("adding again!")}else{i.setUiAttrib({extendTitle:"Inactive"})}};function _(){if(r.get()){if(!x)return 10;if(!b)return 30}return n.get()}i.onDelete=function(){p.gl.clearColor(0,0,0,0);p.gl.clear(p.gl.COLOR_BUFFER_BIT|p.gl.DEPTH_BUFFER_BIT)};function S(){if(t.get()!=0)i.patch.cgl.pixelDensity=Math.min(t.get(),window.devicePixelRatio);else i.patch.cgl.pixelDensity=window.devicePixelRatio}function C(e){if(!s.get())return;if(p.aborted||p.canvas.clientWidth===0||p.canvas.clientHeight===0)return;i.patch.cg=p;S();const t=performance.now();i.patch.config.fpsLimit=_();if(p.canvasWidth==-1){p.setCanvas(i.patch.config.glCanvasId);return}if(p.canvasWidth!=l.get()||p.canvasHeight!=u.get()){l.set(p.canvasWidth/1);u.set(p.canvasHeight/1)}if(CABLES.now()-m>1e3){CGL.fpsReport=CGL.fpsReport||[];if(i.patch.loading.getProgress()>=1&&m!==0)CGL.fpsReport.push(c);c=0;m=CABLES.now()}CGL.MESH.lastShader=null;CGL.MESH.lastMesh=null;p.renderStart(p,g,v);if(!a.get())p.gl.clearColor(0,0,0,1);else p.gl.clearColor(0,0,0,0);p.gl.clear(p.gl.COLOR_BUFFER_BIT|p.gl.DEPTH_BUFFER_BIT);o.trigger();if(CGL.MESH.lastMesh)CGL.MESH.lastMesh.unBind();if(CGL.Texture.previewTexture){if(!CGL.Texture.texturePreviewer)CGL.Texture.texturePreviewer=new CGL.Texture.texturePreview(p);CGL.Texture.texturePreviewer.render(CGL.Texture.previewTexture)}p.renderEnd(p);i.patch.cg=null;if(!a.get()){p.gl.clearColor(1,1,1,1);p.gl.colorMask(false,false,false,true);p.gl.clear(p.gl.COLOR_BUFFER_BIT);p.gl.colorMask(true,true,true,true)}if(!p.tempData.phong)p.tempData.phong={};c++;h.set(i.patch.cgl.pixelDensity);i.patch.cgl.profileData.profileMainloopMs=performance.now()-t}function T(){clearTimeout(f);f=setTimeout(()=>{if(i.patch.getOpsByObjName(i.name).length>1){i.setUiError("multimainloop","there should only be one mainloop op!");if(!d)d=i.patch.addEventListener("onOpDelete",T)}else i.setUiError("multimainloop",null,1)},500)}};Ops.Gl.MainLoop_v2.prototype=new CABLES.Op;CABLES.OPS["f1029550-d877-42da-9b1e-63a5163a0350"]={f:Ops.Gl.MainLoop_v2,objName:"Ops.Gl.MainLoop_v2"};Ops.Gl.Performance=function(){CABLES.Op.apply(this,arguments);const s=this;const V=s.attachments={};const e=s.inTrigger("exe"),o=s.inValueBool("Active",true),l=s.inValueBool("Visible",true),D=s.inValueBool("Measure GPU",true),u=s.outTrigger("childs"),t=s.inSwitch("Position",["top","bottom"],"top"),i=s.inBool("Open",false),B=s.inBool("Smooth Graph",true),j=s.inFloat("Scale",3),h=s.inFloat("Size",128),F=s.outObject("Canvas"),U=s.outNumber("FPS");const n=s.patch.cgl;const r=document.createElement("div");let a=null;let p=null;let c=false;let m=0;let f=0;let d=0;let g=0;let v=0;const y=[];const b=[];const x=[];const A=[];let _=0;let S=0;let C=null;let G=0;let z=0;const T=["|","/","-","\\"];let I=true;const q="#007f9c";const X="#aaaaaa";const H="#222222";const O="#003f5c";const E="#7a5195";const P="#ef5675";const Y="#ffa600";let W=false;let M=0;let L=0;let N=0;s.toWorkPortsNeedToBeLinked(e,u);const K=s.patch.cgl.gl;const Z=K.getExtension("EXT_disjoint_timer_query_webgl2");o.onChange=e.onLinkChanged=l.onChange=()=>{R();J()};t.onChange=Q;h.onChange=w;r.id="performance";r.style.position="absolute";r.style.left="0px";r.style.opacity="0.8";r.style.padding="10px";r.style.cursor="pointer";r.style.background="#222";r.style.color="white";r.style["font-family"]="monospace";r.style["font-size"]="12px";r.style["z-index"]="99999";r.innerHTML="&nbsp;";r.addEventListener("click",$);const k=s.patch.cgl.canvas.parentElement;k.appendChild(r);w();R();Q();J();s.onDelete=function(){if(C)C.remove();if(r)r.remove()};function Q(){C.style["pointer-events"]="none";if(t.get()=="top"){C.style.top=r.style.top="0px";C.style.bottom=r.style.bottom="initial"}else{C.style.bottom=r.style.bottom="0px";C.style.top=r.style.top="initial"}}function J(){if(!l.get()||!e.isLinked()||!o.get()){r.style.display="none";r.style.opacity=0;C.style.display="none"}else{r.style.display="block";r.style.opacity=1;C.style.display="block"}}function w(){if(!C)return;const t=Math.max(0,parseInt(h.get()));C.width=t;C.height=t;r.style.left=t+"px";y.length=0;b.length=0;x.length=0;A.length=0;for(let e=0;e<t;e++){y[e]=-1;b[e]=-1;x[e]=-1;A[e]=-1}}i.onChange=function(){c=i.get();R()};function $(){if(!l.get())return;r.style.opacity=1;c=!c;R()}function R(){ie();if(!C)te();if(c){C.style.display="block";r.style.left=h.get()+"px";r.style["min-height"]="56px"}else{C.style.display="none";r.style.left="0px";r.style["min-height"]="auto"}}function ee(){const t=C.height;const i=j.get();p.fillStyle=H;p.fillRect(0,0,C.width,t);p.fillStyle=O;let n=0;const r=Math.max(0,parseInt(h.get()));for(n=r;n>=0;n--){if(y[n]>30)p.fillStyle=q;if(y[n]>60)p.fillStyle=X;p.fillRect(r-n,t-y[n]*i,1,y[n]*i);if(y[n]>30)p.fillStyle=O}for(n=r;n>=0;n--){let e=0;p.fillStyle=E;e=b[n];p.fillRect(r-n,t-e*i,1,b[n]*i);p.fillStyle=P;e+=x[n];p.fillRect(r-n,t-e*i,1,x[n]*i);p.fillStyle=Y;e+=A[n];p.fillRect(r-n,t-e*i,1,A[n]*i)}for(let e=10;e<t;e+=10){p.fillStyle="#888";const a=t-e*i;p.fillRect(C.width-5,a,5,1);p.font="8px arial";p.fillText(e+"ms",C.width-27,a+3)}p.fillStyle="#fff";p.fillRect(C.width-5,t-1e3/f*i,5,1);p.fillText(Math.round(1e3/f)+"ms",C.width-27,t-1e3/f*i)}function te(){C=document.createElement("canvas");C.id="performance_"+s.patch.config.glCanvasId;C.width=h.get();C.height=h.get();C.style.display="block";C.style.opacity=.9;C.style.position="absolute";C.style.left="0px";C.style.cursor="pointer";C.style.top="-64px";C.style["z-index"]="99998";k.appendChild(C);p=C.getContext("2d");C.addEventListener("click",$);w()}function ie(){if(!l.get())return;let e="";if(s.patch.cgl.profileData.profileShaderCompiles>0)e+="Shader compile ("+s.patch.cgl.profileData.profileShaderCompileName+") ";if(s.patch.cgl.profileData.profileShaderGetUniform>0)e+="Shader get uni loc! ("+s.patch.cgl.profileData.profileShaderGetUniformName+")";if(s.patch.cgl.profileData.profileTextureResize>0)e+="Texture resize! ";if(s.patch.cgl.profileData.profileFrameBuffercreate>0)e+="Framebuffer create! ";if(s.patch.cgl.profileData.profileEffectBuffercreate>0)e+="Effectbuffer create! ";if(s.patch.cgl.profileData.profileTextureDelete>0)e+="Texture delete! ";if(s.patch.cgl.profileData.profileNonTypedAttrib>0)e+="Not-Typed Buffer Attrib! "+s.patch.cgl.profileData.profileNonTypedAttribNames;if(s.patch.cgl.profileData.profileTextureNew>0)e+="new texture created! ";if(s.patch.cgl.profileData.profileGenMipMap>0)e+="generating mip maps!";if(e.length>0){e='| <span style="color:#f80;">WARNING: '+e+"<span>"}let t="";if(c){t+='<span style="color:'+O+'">■</span> '+f+" fps ";t+='<span style="color:'+E+'">■</span> '+Math.round(L*100)/100+"ms mainloop ";t+='<span style="color:'+P+'">■</span> '+Math.round(N*100)/100+"ms onframe ";if(M)t+='<span style="color:'+Y+'">■</span> '+Math.round(M*100)/100+"ms GPU";t+=e;r.innerHTML=t}else{t+=f+" fps / ";t+="CPU: "+Math.round(s.patch.cgl.profileData.profileOnAnimFrameOps*100)/100+"ms / ";if(M)t+="GPU: "+Math.round(M*100)/100+"ms  ";r.innerHTML=t}if(s.patch.loading.getProgress()!=1){r.innerHTML+="<br/>loading "+Math.round(s.patch.loading.getProgress()*100)+"% "+T[++z%T.length]}if(c){let t=0;_=0;v=0;for(let e=y.length;e>y.length-y.length/3;e--){if(y[e]>-1){_+=y[e];t++}if(b[e]>-1)v+=b[e]}_/=t;v/=t;r.innerHTML+="<br/> "+n.canvasWidth+" x "+n.canvasHeight+" (x"+n.pixelDensity+") ";r.innerHTML+="<br/>frame avg: "+Math.round(v*100)/100+" ms ("+Math.round(v/_*100)+"%) / "+Math.round(_*100)/100+" ms";r.innerHTML+=" (self: "+Math.round(S*100)/100+" ms) ";r.innerHTML+="<br/>shader binds: "+Math.ceil(s.patch.cgl.profileData.profileShaderBinds/f)+" uniforms: "+Math.ceil(s.patch.cgl.profileData.profileUniformCount/f)+" mvp_uni_mat4: "+Math.ceil(s.patch.cgl.profileData.profileMVPMatrixCount/f)+" num glPrimitives: "+Math.ceil(s.patch.cgl.profileData.profileMeshNumElements/f)+" fenced pixelread: "+Math.ceil(s.patch.cgl.profileData.profileFencedPixelRead)+" mesh.setGeom: "+s.patch.cgl.profileData.profileMeshSetGeom+" videos: "+s.patch.cgl.profileData.profileVideosPlaying+" tex preview: "+s.patch.cgl.profileData.profileTexPreviews;r.innerHTML+=" draw meshes: "+Math.ceil(s.patch.cgl.profileData.profileMeshDraw/f)+" framebuffer blit: "+Math.ceil(s.patch.cgl.profileData.profileFramebuffer/f)+" texeffect blit: "+Math.ceil(s.patch.cgl.profileData.profileTextureEffect/f);r.innerHTML+=" all shader compiletime: "+Math.round(s.patch.cgl.profileData.shaderCompileTime*100)/100}s.patch.cgl.profileData.clear()}function ne(e){e.style.padding="0px";e.style.margin="0px"}function re(t,e,i,n){const r=20;t.usedAvg=t.usedAvg||t.used;if(!t.ele||I){const s=document.createElement("div");t.ele=s;if(t.childs&&t.childs.length>0)s.style.height="500px";else s.style.height=r+"px";s.style.overflow="hidden";s.style.display="inline-block";if(!t.isRoot){s.innerHTML='<div style="min-height:'+r+'px;width:100%;overflow:hidden;color:black;position:relative">&nbsp;'+t.name+"</div>";s.style["background-color"]="rgb("+t.colR+","+t.colG+","+t.colB+")";s.style["border-left"]="1px solid black"}e.appendChild(s)}if(!t.isRoot){if(performance.now()-t.lastTime>200){t.ele.style.display="none";t.hidden=true}else{if(t.hidden){t.ele.style.display="inline-block";t.hidden=false}}t.ele.style.float="left";t.ele.style.width=Math.floor(t.usedAvg/i*98)+"%"}else{t.ele.style.width="100%";t.ele.style.clear="both";t.ele.style.float="none"}if(t&&t.childs&&t.childs.length>0){let e=0;for(var a=0;a<t.childs.length;a++){t.childs[a].usedAvg=(t.childs[a].usedAvg||t.childs[a].used)*.95+t.childs[a].used*.05;e+=t.childs[a].usedAvg}for(var a=0;a<t.childs.length;a++){re(t.childs[a],t.ele,e,n+1)}}}function ae(t){for(let e=0;e<t.childs.length;e++)ae(t.childs[e]);t.childs.length=0}function se(){if(!CGL.performanceMeasures)return;if(!a){s.log("create measure ele");a=document.createElement("div");a.style.width="100%";a.style["background-color"]="#444";a.style.bottom="10px";a.style.height="100px";a.style.opacity="1";a.style.position="absolute";a.style["z-index"]="99999";a.innerHTML="";k.appendChild(a)}let t=0;const i=CGL.performanceMeasures[0];for(let e=0;e<i.childs.length;e++)t+=i.childs[e].used;re(CGL.performanceMeasures[0],a,t,0);i.childs.length=0;ae(CGL.performanceMeasures[0]);CGL.performanceMeasures.length=0;I=false}e.onTriggered=oe;function oe(){const e=performance.now();if(o.get()){m++;if(Z&&D.get()&&l.get())s.patch.cgl.profileData.doProfileGlQuery=true;else s.patch.cgl.profileData.doProfileGlQuery=false;if(d===0)d=Date.now();if(Date.now()-d>=1e3){f=m;m=0;U.set(f);if(l.get())ie();d=Date.now()}const i=s.patch.cgl.profileData.glQueryData;M=0;if(i){let t=0;for(let e in i){t++;if(i[e].time)M+=i[e].time}}if(l.get()){se();if(c&&!s.patch.cgl.profileData.pause){y.push(s.patch.cgl.profileData.profileFrameDelta);y.shift();b.push(g);b.shift();x.push(s.patch.cgl.profileData.profileOnAnimFrameOps-s.patch.cgl.profileData.profileMainloopMs);x.shift();A.push(M);A.shift();ee()}}G=performance.now();S=performance.now()-e;F.setRef(C)}const t=performance.now();u.trigger();if(o.get()){const n=performance.now()-t;const r=s.patch.cgl.profileData.profileMainloopMs;const a=s.patch.cgl.profileData.profileOnAnimFrameOps-s.patch.cgl.profileData.profileMainloopMs;if(B.get()){g=g*.9+n*.1;L=L*.5+r*.5;N=N*.5+a*.5}else{g=n;L=r;N=a}s.patch.cgl.profileData.clearGlQuery()}}};Ops.Gl.Performance.prototype=new CABLES.Op;CABLES.OPS["9cd2d9de-000f-4a14-bd13-e7d5f057583c"]={f:Ops.Gl.Performance,objName:"Ops.Gl.Performance"};Ops.Vars.VarSetNumber_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inValueFloat("Value",0);e.varName=e.inDropDown("Variable",[],"",true);new CABLES.VarSetOpWrapper(e,"number",i,e.varName)};Ops.Vars.VarSetNumber_v2.prototype=new CABLES.Op;CABLES.OPS["b5249226-6095-4828-8a1c-080654e192fa"]={f:Ops.Vars.VarSetNumber_v2,objName:"Ops.Vars.VarSetNumber_v2"};Ops.Vars.VarGetNumber_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.outNumber("Value");e.varName=e.inValueSelect("Variable",[],"",true);new CABLES.VarGetOpWrapper(e,"number",e.varName,i)};Ops.Vars.VarGetNumber_v2.prototype=new CABLES.Op;CABLES.OPS["421f5b52-c0fa-47c4-8b7a-012b9e1c864a"]={f:Ops.Vars.VarGetNumber_v2,objName:"Ops.Vars.VarGetNumber_v2"};Ops.Cables.LoadingStatus_v2=function(){CABLES.Op.apply(this,arguments);const n=this;const e=n.attachments={};const t=n.inTrigger("exe"),r=n.inBool("Play Timeline",true),i=n.outTrigger("Next"),a=n.outBoolNum("Finished Initial Loading",false),s=n.outBoolNum("Loading"),o=n.outNumber("Progress"),l=n.outArray("Jobs"),u=n.outTrigger("Trigger Loading Finished ");const h=n.patch.cgl;const p=n.patch;let c=false;const m=[];let f=true;let d=0;document.body.classList.add("cables-loading");let g=h.patch.loading.start("loadingStatusInit","loadingStatusInit",n);n.patch.loading.on("finishedTask",v.bind(this));n.patch.loading.on("startTask",v.bind(this));function v(){const e=n.patch.loading.getListJobs();o.set(p.loading.getProgress());let t=e.length===0;const i=!t;if(i){l.set(n.patch.loading.getListJobs())}if(i){if(f){n.patch.timer.setTime(0);if(r.get()){n.patch.timer.play()}else{n.patch.timer.pause()}}f=false;document.body.classList.remove("cables-loading");document.body.classList.add("cables-loaded")}else{c=true;l.set(n.patch.loading.getListJobs());if(p.loading.getProgress()<1){n.patch.timer.setTime(0);n.patch.timer.pause()}}a.set(c);if(s.get()&&t)u.trigger();s.set(i);n.setUiAttribs({loading:i})}t.onTriggered=()=>{v();i.trigger();if(g){h.patch.loading.finished(g);g=null}}};Ops.Cables.LoadingStatus_v2.prototype=new CABLES.Op;CABLES.OPS["e62f7f4c-7436-437e-8451-6bc3c28545f7"]={f:Ops.Cables.LoadingStatus_v2,objName:"Ops.Cables.LoadingStatus_v2"};Ops.Html.Utils.PlayButton=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={inner_css:"\nborder-style:solid;\nborder-color:transparent transparent transparent #ccc;\nbox-sizing:border-box;\nwidth:50px;\nheight:50px;\nmargin-top:25px;\nmargin-left:36px;\nborder-width:25px 0px 25px 40px;\npointer-events:none;\n",outer_css:"width:100px;\nheight:100px;\nleft:50%;\ntop:50%;\nborder-radius:100%;\nposition:absolute;\ncursor:pointer;\nopacity:0.7;\ntransform:translate(-50%,-50%);\nz-index:999999;\nbackground-color:#333;\nborder:5px solid #333;"};const i=e.inTrigger("Trigger"),n=e.inValueBool("Only if Audio Suspended"),r=e.inTriggerButton("Reset"),a=e.inStringEditor("Style Outer",t.outer_css),s=e.inStringEditor("Style Inner",t.inner_css),o=e.inBool("Active",true),l=e.outTrigger("Next"),u=e.outTrigger("Not Clicked"),h=e.outString("Audiocontext State","unknown"),p=e.outObject("Element"),c=e.outBoolNum("Clicked",false),m=e.outTrigger("Clicked Trigger");e.toWorkPortsNeedToBeLinked(i);let f=CABLES.WEBAUDIO.createAudioContext(e);const d=e.patch.cgl.canvas.parentElement;let g=false;let v=null;let y=null;b();a.onChange=s.onChange=b;f.addEventListener("statechange",x);x();o.onChange=()=>{if(!o.get())v.style.display="none";else v.style.display="block"};function b(){x();if(y)y.remove();if(v)v.remove();v=document.createElement("div");v.style=a.get();p.set(v);d.appendChild(v);y=document.createElement("div");y.style=s.get();v.appendChild(y);v.classList.add("playButton");v.addEventListener("mouseenter",C);v.addEventListener("mouseleave",S);v.addEventListener("click",A);v.addEventListener("touchStart",A);e.onDelete=_}r.onTriggered=function(){b();g=false;c.set(g)};function x(){h.set(f.state);if(n.get()&&f.state=="running")A()}i.onTriggered=function(){if(g)l.trigger();else u.trigger()};function A(){_();if(f&&f.state=="suspended")f.resume();g=true;c.set(g);m.trigger()}function _(){if(y)y.remove();if(v)v.remove()}function S(){if(v)v.style.opacity=.7}function C(){if(v)v.style.opacity=1}};Ops.Html.Utils.PlayButton.prototype=new CABLES.Op;CABLES.OPS["32e53fa2-4545-4c53-a94d-2204aa079246"]={f:Ops.Html.Utils.PlayButton,objName:"Ops.Html.Utils.PlayButton"};Ops.Trigger.GateTrigger=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTrigger("Execute"),n=e.inValueBool("Pass Through",true),r=e.outTrigger("Trigger out");i.onTriggered=function(){if(n.get())r.trigger()}};Ops.Trigger.GateTrigger.prototype=new CABLES.Op;CABLES.OPS["65e8b8a2-ba13-485f-883a-2bcf377989da"]={f:Ops.Trigger.GateTrigger,objName:"Ops.Trigger.GateTrigger"};Ops.Gl.Shader.BasicMaterial_v3=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={basicmaterial_frag:"{{MODULES_HEAD}}\n\nIN vec2 texCoord;\n\n#ifdef VERTEX_COLORS\nIN vec4 vertCol;\n#endif\n\n#ifdef HAS_TEXTURES\n    IN vec2 texCoordOrig;\n    #ifdef HAS_TEXTURE_DIFFUSE\n        UNI sampler2D tex;\n    #endif\n    #ifdef HAS_TEXTURE_OPACITY\n        UNI sampler2D texOpacity;\n   #endif\n#endif\n\n\n\nvoid main()\n{\n    {{MODULE_BEGIN_FRAG}}\n    vec4 col=color;\n\n\n    #ifdef HAS_TEXTURES\n        vec2 uv=texCoord;\n\n        #ifdef CROP_TEXCOORDS\n            if(uv.x<0.0 || uv.x>1.0 || uv.y<0.0 || uv.y>1.0) discard;\n        #endif\n\n        #ifdef HAS_TEXTURE_DIFFUSE\n            col=texture(tex,uv);\n\n            #ifdef COLORIZE_TEXTURE\n                col.r*=color.r;\n                col.g*=color.g;\n                col.b*=color.b;\n            #endif\n        #endif\n        col.a*=color.a;\n        #ifdef HAS_TEXTURE_OPACITY\n            #ifdef TRANSFORMALPHATEXCOORDS\n                uv=texCoordOrig;\n            #endif\n            #ifdef ALPHA_MASK_IR\n                col.a*=1.0-texture(texOpacity,uv).r;\n            #endif\n            #ifdef ALPHA_MASK_IALPHA\n                col.a*=1.0-texture(texOpacity,uv).a;\n            #endif\n            #ifdef ALPHA_MASK_ALPHA\n                col.a*=texture(texOpacity,uv).a;\n            #endif\n            #ifdef ALPHA_MASK_LUMI\n                col.a*=dot(vec3(0.2126,0.7152,0.0722), texture(texOpacity,uv).rgb);\n            #endif\n            #ifdef ALPHA_MASK_R\n                col.a*=texture(texOpacity,uv).r;\n            #endif\n            #ifdef ALPHA_MASK_G\n                col.a*=texture(texOpacity,uv).g;\n            #endif\n            #ifdef ALPHA_MASK_B\n                col.a*=texture(texOpacity,uv).b;\n            #endif\n            // #endif\n        #endif\n    #endif\n\n    {{MODULE_COLOR}}\n\n    #ifdef DISCARDTRANS\n        if(col.a<0.2) discard;\n    #endif\n\n    #ifdef VERTEX_COLORS\n        col*=vertCol;\n    #endif\n\n    outColor = col;\n}\n",basicmaterial_vert:"\n{{MODULES_HEAD}}\n\nOUT vec2 texCoord;\nOUT vec2 texCoordOrig;\n\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\n#ifdef HAS_TEXTURES\n    UNI float diffuseRepeatX;\n    UNI float diffuseRepeatY;\n    UNI float texOffsetX;\n    UNI float texOffsetY;\n#endif\n\n#ifdef VERTEX_COLORS\n    in vec4 attrVertColor;\n    out vec4 vertCol;\n\n#endif\n\n\nvoid main()\n{\n    mat4 mMatrix=modelMatrix;\n    mat4 modelViewMatrix;\n\n    norm=attrVertNormal;\n    texCoordOrig=attrTexCoord;\n    texCoord=attrTexCoord;\n    #ifdef HAS_TEXTURES\n        texCoord.x=texCoord.x*diffuseRepeatX+texOffsetX;\n        texCoord.y=(1.0-texCoord.y)*diffuseRepeatY+texOffsetY;\n    #endif\n\n    #ifdef VERTEX_COLORS\n        vertCol=attrVertColor;\n    #endif\n\n    vec4 pos = vec4(vPosition, 1.0);\n\n    #ifdef BILLBOARD\n       vec3 position=vPosition;\n       modelViewMatrix=viewMatrix*modelMatrix;\n\n       gl_Position = projMatrix * modelViewMatrix * vec4((\n           position.x * vec3(\n               modelViewMatrix[0][0],\n               modelViewMatrix[1][0],\n               modelViewMatrix[2][0] ) +\n           position.y * vec3(\n               modelViewMatrix[0][1],\n               modelViewMatrix[1][1],\n               modelViewMatrix[2][1]) ), 1.0);\n    #endif\n\n    {{MODULE_VERTEX_POSITION}}\n\n    #ifndef BILLBOARD\n        modelViewMatrix=viewMatrix * mMatrix;\n\n        {{MODULE_VERTEX_MODELVIEW}}\n\n    #endif\n\n    // mat4 modelViewMatrix=viewMatrix*mMatrix;\n\n    #ifndef BILLBOARD\n        // gl_Position = projMatrix * viewMatrix * modelMatrix * pos;\n        gl_Position = projMatrix * modelViewMatrix * pos;\n    #endif\n}\n"};const i=e.inTrigger("render");const n=e.outTrigger("trigger");const r=e.outObject("shader",null,"shader");r.ignoreValueSerialize=true;e.toWorkPortsNeedToBeLinked(i);e.toWorkShouldNotBeChild("Ops.Gl.TextureEffects.ImageCompose",CABLES.OP_PORT_TYPE_FUNCTION);const a=e.patch.cgl;const s=new CGL.Shader(a,"basicmaterialnew",this);s.addAttribute({type:"vec3",name:"vPosition"});s.addAttribute({type:"vec2",name:"attrTexCoord"});s.addAttribute({type:"vec3",name:"attrVertNormal",nameFrag:"norm"});s.addAttribute({type:"float",name:"attrVertIndex"});s.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG","MODULE_VERTEX_MODELVIEW"]);s.setSource(t.basicmaterial_vert,t.basicmaterial_frag);r.setRef(s);i.onTriggered=O;const o=e.inValueSlider("r",Math.random());const l=e.inValueSlider("g",Math.random());const u=e.inValueSlider("b",Math.random());const h=e.inValueSlider("a",1);o.setUiAttribs({colorPick:true});const p=s.addUniformFrag("4f","color",o,l,u,h);s.uniformColorDiffuse=p;const c=e.inTexture("texture");let m=null;c.onChange=P;const f=e.inValueBool("colorizeTexture",false);const d=e.inValueBool("Vertex Colors",false);const g=e.inTexture("textureOpacity");let v=null;const y=e.inSwitch("Alpha Mask Source",["Luminance","R","G","B","A","1-A","1-R"],"Luminance");y.setUiAttribs({greyout:true});g.onChange=E;const b=e.inValueBool("Opacity TexCoords Transform",false);const x=e.inValueBool("Discard Transparent Pixels");const A=e.inValue("diffuseRepeatX",1),_=e.inValue("diffuseRepeatY",1),S=e.inValue("Tex Offset X",0),C=e.inValue("Tex Offset Y",0),T=e.inBool("Crop TexCoords",false);s.addUniformFrag("f","diffuseRepeatX",A);s.addUniformFrag("f","diffuseRepeatY",_);s.addUniformFrag("f","texOffsetX",S);s.addUniformFrag("f","texOffsetY",C);const I=e.inValueBool("billboard",false);y.onChange=I.onChange=x.onChange=b.onChange=T.onChange=d.onChange=f.onChange=L;e.setPortGroup("Color",[o,l,u,h]);e.setPortGroup("Color Texture",[c,d,f]);e.setPortGroup("Opacity",[g,y,x,b]);e.setPortGroup("Texture Transform",[A,_,S,C,T]);E();P();e.preRender=function(){s.bind();O()};function O(){if(!s)return;a.pushShader(s);s.popTextures();if(m&&c.get())s.pushTexture(m,c.get());if(v&&g.get())s.pushTexture(v,g.get());n.trigger();a.popShader()}function E(){if(g.get()){if(v!==null)return;s.removeUniform("texOpacity");s.define("HAS_TEXTURE_OPACITY");if(!v)v=new CGL.Uniform(s,"t","texOpacity")}else{s.removeUniform("texOpacity");s.removeDefine("HAS_TEXTURE_OPACITY");v=null}L()}function P(){if(c.get()){if(!s.hasDefine("HAS_TEXTURE_DIFFUSE"))s.define("HAS_TEXTURE_DIFFUSE");if(!m)m=new CGL.Uniform(s,"t","texDiffuse")}else{s.removeUniform("texDiffuse");s.removeDefine("HAS_TEXTURE_DIFFUSE");m=null}M()}function M(){const e=c.isLinked()||g.isLinked();A.setUiAttribs({greyout:!e});_.setUiAttribs({greyout:!e});S.setUiAttribs({greyout:!e});C.setUiAttribs({greyout:!e});f.setUiAttribs({greyout:!e});y.setUiAttribs({greyout:!g.get()});b.setUiAttribs({greyout:!g.get()});let t=true;t=c.get()&&!f.get();o.setUiAttribs({greyout:t});l.setUiAttribs({greyout:t});u.setUiAttribs({greyout:t})}function L(){s.toggleDefine("VERTEX_COLORS",d.get());s.toggleDefine("CROP_TEXCOORDS",T.get());s.toggleDefine("COLORIZE_TEXTURE",f.get());s.toggleDefine("TRANSFORMALPHATEXCOORDS",b.get());s.toggleDefine("DISCARDTRANS",x.get());s.toggleDefine("BILLBOARD",I.get());s.toggleDefine("ALPHA_MASK_ALPHA",y.get()=="A");s.toggleDefine("ALPHA_MASK_IALPHA",y.get()=="1-A");s.toggleDefine("ALPHA_MASK_IR",y.get()=="1-R");s.toggleDefine("ALPHA_MASK_LUMI",y.get()=="Luminance");s.toggleDefine("ALPHA_MASK_R",y.get()=="R");s.toggleDefine("ALPHA_MASK_G",y.get()=="G");s.toggleDefine("ALPHA_MASK_B",y.get()=="B");M()}};Ops.Gl.Shader.BasicMaterial_v3.prototype=new CABLES.Op;CABLES.OPS["ec55d252-3843-41b1-b731-0482dbd9e72b"]={f:Ops.Gl.Shader.BasicMaterial_v3,objName:"Ops.Gl.Shader.BasicMaterial_v3"};Ops.Gl.Matrix.Transform=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={};const t=i.inTrigger("render"),n=i.inValue("posX",0),r=i.inValue("posY",0),a=i.inValue("posZ",0),s=i.inValue("scale",1),o=i.inValue("rotX",0),l=i.inValue("rotY",0),u=i.inValue("rotZ",0),h=i.outTrigger("trigger");i.setPortGroup("Rotation",[o,l,u]);i.setPortGroup("Position",[n,r,a]);i.setPortGroup("Scale",[s]);i.setUiAxisPorts(n,r,a);i.toWorkPortsNeedToBeLinked(t,h);const p=vec3.create();const c=vec3.create();const m=mat4.create();mat4.identity(m);let f=false,d=false,g=true,v=true,y=true;o.onChange=l.onChange=u.onChange=C;n.onChange=r.onChange=a.onChange=_;s.onChange=S;t.onTriggered=function(){let e=false;if(g){x();e=true}if(v){A();e=true}if(y)e=true;if(e)b();const t=i.patch.cg||i.patch.cgl;t.pushModelMatrix();mat4.multiply(t.mMatrix,t.mMatrix,m);h.trigger();t.popModelMatrix();if(CABLES.UI){if(!n.isLinked()&&!r.isLinked()&&!a.isLinked()){gui.setTransform(i.id,n.get(),r.get(),a.get());if(i.isCurrentUiOp())gui.setTransformGizmo({posX:n,posY:r,posZ:a})}}};function b(){mat4.identity(m);if(d)mat4.translate(m,m,p);if(o.get()!==0)mat4.rotateX(m,m,o.get()*CGL.DEG2RAD);if(l.get()!==0)mat4.rotateY(m,m,l.get()*CGL.DEG2RAD);if(u.get()!==0)mat4.rotateZ(m,m,u.get()*CGL.DEG2RAD);if(f)mat4.scale(m,m,c);y=false}function x(){d=false;if(n.get()!==0||r.get()!==0||a.get()!==0)d=true;vec3.set(p,n.get(),r.get(),a.get());g=false}function A(){f=true;vec3.set(c,s.get(),s.get(),s.get());v=false}function _(){g=true}function S(){v=true}function C(){y=true}b()};Ops.Gl.Matrix.Transform.prototype=new CABLES.Op;CABLES.OPS["650baeb1-db2d-4781-9af6-ab4e9d4277be"]={f:Ops.Gl.Matrix.Transform,objName:"Ops.Gl.Matrix.Transform"};Ops.Gl.Meshes.Circle_v3=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTrigger("render"),M=e.inValue("radius",.5),L=e.inValueSlider("innerRadius",0),N=e.inValueInt("segments",40),k=e.inValueSlider("percent",1),w=e.inValue("steps",0),R=e.inValueBool("invertSteps",false),V=e.inSwitch("mapping",["flat","round"]),D=e.inValueBool("Spline",false),n=e.inValueBool("Draw",true),r=e.outTrigger("trigger"),B=e.outObject("geometry",null,"geometry");e.setPortGroup("Size",[M,L]);e.setPortGroup("Display",[k,w,R]);e.toWorkShouldNotBeChild("Ops.Gl.TextureEffects.ImageCompose",CABLES.OP_PORT_TYPE_FUNCTION);n.setUiAttribs({title:"Render mesh"});V.set("flat");V.onChange=N.onChange=M.onChange=L.onChange=k.onChange=w.onChange=R.onChange=D.onChange=p;B.ignoreValueSerialize=true;const a=e.patch.cgl;let j=new CGL.Geometry("circle");let F=null;const s=-1;let o=0;let l=null;let U=true;i.onTriggered=u;e.preRender=()=>{u()};i.onLinkChanged=function(){if(!i.isLinked())B.set(null);else B.setRef(j)};function u(){if(!e.patch.cg)return;if(U)h();if(!CGL.TextureEffect.checkOpNotInTextureEffect(e))return;l=e.patch.cg.getShader();if(!l)return;o=l.glPrimitive;if(D.get())l.glPrimitive=a.gl.LINE_STRIP;if(n.get()&&F){F.render(l)}r.trigger();l.glPrimitive=o}function h(){const i=Math.max(3,Math.floor(N.get()));j.clear();const t=[];const n=[];const r=[];const a=[];const s=[];let o=0,l=0;let u=0,h=0;let p=0,c=0;let m=0,f=0;let d=0,g=0;let v=0,y=0;let b=0,x=0;let A=0,_=0;const S=Math.max(0,k.get());const C=[];if(D.get()){let e=0;let t=0;const T=[];for(o=0;o<=i*S;o++){l=360/i*o*CGL.DEG2RAD;A=Math.cos(l)*M.get();_=Math.sin(l)*M.get();x=.5;if(o>0){C.push(e);C.push(t);C.push(0);b=1-(o-1)/i;T.push(b,x)}C.push(A);C.push(_);C.push(0);e=A;t=_}j.setPointVertices(C)}else if(L.get()<=0){for(o=0;o<=i*S;o++){l=360/i*o*CGL.DEG2RAD;A=Math.cos(l)*M.get();_=Math.sin(l)*M.get();if(V.get()=="flat"){b=(Math.cos(l)+1)/2;x=1-(Math.sin(l)+1)/2;v=.5;y=.5}else if(V.get()=="round"){b=1-o/i;x=0;v=b;y=1}t.push([0,0,0],[u,h,0],[A,_,0]);n.push(v,y,p,c,b,x);r.push(0,0,1,0,0,1,0,0,1);a.push(1,0,0,1,0,0,1,0,0);s.push(0,-1,0,0,-1,0,0,-1,0);p=b;c=x;u=A;h=_}j=CGL.Geometry.buildFromFaces(t,"circle");j.vertexNormals=r;j.tangents=a;j.biTangents=s;j.texCoords=n}else{let e=0;const I=i*S;const O=0;for(o=0;o<=I;o++){e++;l=360/i*o*CGL.DEG2RAD;A=Math.cos(l)*M.get();_=Math.sin(l)*M.get();const E=Math.cos(l)*L.get()*M.get();const P=Math.sin(l)*L.get()*M.get();if(V.get()=="round"){b=1-o/i;x=0;v=b;y=1}if(w.get()===0||e%parseInt(w.get(),10)===0&&!R.get()||e%parseInt(w.get(),10)!==0&&R.get()){t.push([E,P,0],[u,h,0],[A,_,0]);t.push([m,f,0],[u,h,0],[E,P,0]);n.push(b,0,p,0,v,1,b,1,p,0,d,1);r.push(0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1);a.push(1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0);s.push(0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1)}d=v;g=y;p=b;c=x;u=A;h=_;m=E;f=P}j=CGL.Geometry.buildFromFaces(t,"circle");j.vertexNormals=r;j.tangents=a;j.biTangents=s;if(V.get()=="flat")j.mapTexCoords2d();else j.texCoords=n}B.setRef(j);if(j.vertices.length==0)return;if(F)F.dispose();F=null;if(e.patch.cg)F=e.patch.cg.createMesh(j,{opId:e.id});U=false}function p(){U=true}e.onDelete=function(){if(F)F.dispose()}};Ops.Gl.Meshes.Circle_v3.prototype=new CABLES.Op;CABLES.OPS["ae07830b-91c3-4cbe-a7d6-d3b737392c16"]={f:Ops.Gl.Meshes.Circle_v3,objName:"Ops.Gl.Meshes.Circle_v3"};Ops.TimeLine.TimeLinePlayer=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const i=t.inTriggerButton("Play"),n=t.inTriggerButton("Pause"),r=t.inTriggerButton("rewind"),a=t.inFloat("Set current time",0),s=t.outTrigger("play trigger"),o=t.outTrigger("pause trigger"),l=t.outTrigger("rewind trigger"),u=t.outBool("is Playing"),h=t.outNumber("set time (seconds)"),p=t.outNumber("current time"),c=t.outNumber("current frame");i.onTriggered=function(){t.patch.timer.play();t.patch.timer.setTime(a.get());h.set(a.get());s.trigger()};n.onTriggered=function(){t.patch.timer.pause();o.trigger()};t.onAnimFrame=function(e){c.set(Math.round(e*30));p.set(e);u.set(t.patch.timer.isPlaying())};r.onTriggered=function(){t.patch.timer.setTime(0);l.trigger()}};Ops.TimeLine.TimeLinePlayer.prototype=new CABLES.Op;CABLES.OPS["97e57613-6a51-41cf-9de5-fe3dbc2c69b2"]={f:Ops.TimeLine.TimeLinePlayer,objName:"Ops.TimeLine.TimeLinePlayer"};Ops.Trigger.Sequence=function(){CABLES.Op.apply(this,arguments);const a=this;const e=a.attachments={};const t=a.inTrigger("exe"),i=a.inTriggerButton("Clean up connections");a.setUiAttrib({resizable:true,resizableY:false,stretchPorts:true});const n=[],s=[],r=16;let o=null,l=[];t.onTriggered=p;i.onTriggered=c;i.setUiAttribs({hideParam:true,hidePort:true});for(let t=0;t<r;t++){const m=a.outTrigger("trigger "+t);s.push(m);m.onLinkChanged=h;if(t<r-1){let e=a.inTrigger("exe "+t);e.onTriggered=p;n.push(e)}}u();function u(){l.length=0;for(let e=0;e<s.length;e++)if(s[e].links.length>0)l.push(s[e])}function h(){u();clearTimeout(o);o=setTimeout(()=>{let t=false;for(let e=0;e<s.length;e++)if(s[e].links.length>1)t=true;i.setUiAttribs({hideParam:!t});if(a.isCurrentUiOp())a.refreshParams()},60)}function p(){for(let e=0;e<l.length;e++)l[e].trigger()}function c(){let n=0;for(let i=0;i<s.length;i++){let t=[];if(s[i].links.length>1)for(let e=1;e<s[i].links.length;e++){while(s[n].links.length>0)n++;t.push(s[i].links[e]);const r=s[i].links[e].getOtherPort(s[i]);a.patch.link(a,"trigger "+n,r.op,r.name);n++}for(let e=0;e<t.length;e++)t[e].remove()}h();u()}};Ops.Trigger.Sequence.prototype=new CABLES.Op;CABLES.OPS["a466bc1f-06e9-4595-8849-bffb9fe22f99"]={f:Ops.Trigger.Sequence,objName:"Ops.Trigger.Sequence"};Ops.Ui.Area=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inString("Title",""),n=e.inTriggerButton("Delete");i.setUiAttribs({hidePort:true});e.setUiAttrib({hasArea:true});e.init=i.onChange=e.onLoaded=r;r();function r(){if(CABLES.UI){gui.savedState.setUnSaved("areaOp",e.getSubPatch());e.uiAttr({comment_title:i.get()||" "});e.name=i.get()}}n.onTriggered=()=>{e.patch.deleteOp(e.id)}};Ops.Ui.Area.prototype=new CABLES.Op;CABLES.OPS["38f79614-b0de-4960-8da5-2827e7f43415"]={f:Ops.Ui.Area,objName:"Ops.Ui.Area"};Ops.WebAudio.AudioBuffer_v2=function(){CABLES.Op.apply(this,arguments);const n=this;const e=n.attachments={};const r=n.patch.cgl;const t=CABLES.WEBAUDIO.createAudioContext(n),i=n.inUrl("URL","audio"),a=n.inBool("Create Loading Task",true),s=n.outObject("Audio Buffer",null,"audioBuffer"),o=n.outBoolNum("Finished Loading",false),l=n.outNumber("Sample Rate",0),u=n.outNumber("Length",0),h=n.outNumber("Duration",0),p=n.outNumber("Number of Channels",0),c=n.outBool("isLoading",0);let m=null;let f=false;let d=null;let g=null;let v=false;let y=false;let b=false;let x=new FileReader;let A=null;let _=0;if(!s.isLinked()){n.setUiError("notConnected","To play back sound, connect this op to a playback operator such as SamplePlayer or AudioBufferPlayer.",0)}else{n.setUiError("notConnected",null)}s.onLinkChanged=()=>{if(s.isLinked()){n.setUiError("notConnected",null)}else{n.setUiError("notConnected","To play back sound, connect this op to a playback operator such as SamplePlayer or AudioBufferPlayer.",0)}};function S(t,e){d=t;f=true;c.set(f);if(!e){const i=t.substr(t.lastIndexOf(".")+1);if(i==="wav"){n.setUiError("wavFormat","You are using a .wav file. Make sure the .wav file is 16 bit to be supported by all browsers. Safari does not support 24 bit .wav files.",1)}else{n.setUiError("wavFormat",null)}CABLES.WEBAUDIO.loadAudioFile(n.patch,t,I,O,a.get())}else{let e=C(t);if(e.type==="audio/wav"){n.setUiError("wavFormat","You are using a .wav file. Make sure the .wav file is 16 bit to be supported by all browsers. Safari does not support 24 bit .wav files.",1)}else{n.setUiError("wavFormat",null)}if(a.get()){_=r.patch.loading.start("audiobuffer from data-url "+n.id,t,n);if(r.patch.isEditorMode())gui.jobs().start({id:"loadaudio"+_,title:" loading audio data url ("+n.id+")"})}x.readAsArrayBuffer(e)}}function C(e){let t=atob(e.split(",")[1]);let i=e.split(",")[0].split(":")[1].split(";")[0];let n=new ArrayBuffer(t.length);let r=new Uint8Array(n);for(let e=0;e<t.length;e++){r[e]=t.charCodeAt(e)}let a=new Blob([n],{type:i});return a}i.onChange=function(){if(i.get()){y=String(i.get()).indexOf("data:")==0;if(f){b=String(i.get()).indexOf("data:")==0;const t=b?i.get():n.patch.getFilePath(i.get());if(t!==d){g=t}else{g=null}v=false;return}E();const e=y?i.get():n.patch.getFilePath(i.get());S(e,y)}else{if(f){v=true;return}E();n.setUiError("wavFormat",null);n.setUiError("failedLoading",null)}};x.onloadend=()=>{A=x.result;r.patch.loading.finished(_);if(r.patch.isEditorMode())gui.jobs().finish("loadaudio"+_);T()};function T(){if(A)t.decodeAudioData(A,I,O)}function I(e){f=false;c.set(f);if(v){E();v=false;return}if(g){S(g,b);g=null}else{m=e;u.set(e.length);h.set(e.duration);p.set(e.numberOfChannels);l.set(e.sampleRate);s.set(e);n.setUiError("failedLoading",null);o.set(true);y=false;b=false}}function O(e){n.setUiError("failedLoading","The audio file could not be loaded. Make sure the right file URL is used.",2);f=false;E();c.set(f);m=null;if(g){S(g,b);g=null}}function E(){u.set(0);h.set(0);p.set(0);l.set(0);s.set(null);o.set(false)}};Ops.WebAudio.AudioBuffer_v2.prototype=new CABLES.Op;CABLES.OPS["5f1d6a2f-1c04-4744-b0fb-910825beceee"]={f:Ops.WebAudio.AudioBuffer_v2,objName:"Ops.WebAudio.AudioBuffer_v2"};Ops.WebAudio.AudioBufferPlayer_v2=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={};const n=i.inObject("Audio Buffer",null,"audioBuffer");const r=i.inBool("Start / Stop",false);const a=i.inBool("Loop",false);const t=i.inTriggerButton("Restart");const s=i.inFloat("Offset",0);const o=i.inFloat("Playback Rate",1);const l=i.inFloat("Detune",0);i.setPortGroup("Playback Controls",[r,a,t]);i.setPortGroup("Time Controls",[s]);i.setPortGroup("Miscellaneous",[o,l]);const u=i.outObject("Audio Out",null,"audioNode");const h=i.outBool("Is Playing",false);const p=i.outBool("Loading",false);let c=null;let m=false;let f=false;let d=null;let g=null;let v=false;const y=CABLES.WEBAUDIO.createAudioContext(i);const b=y.createGain();if(!n.isLinked()){i.setUiError("inputNotConnected","To be able to play back sound, you need to connect an AudioBuffer to this op.",0)}else{i.setUiError("inputNotConnected",null)}n.onLinkChanged=()=>{if(!n.isLinked()){i.setUiError("inputNotConnected","To be able to play back sound, you need to connect an AudioBuffer to this op.",0)}else{i.setUiError("inputNotConnected",null)}};if(!u.isLinked()){i.setUiError("outputNotConnected","To be able to hear sound playing, you need to connect this op to an Output op.",0)}else{i.setUiError("outputNotConnected",null)}u.onLinkChanged=()=>{if(!u.isLinked()){i.setUiError("outputNotConnected","To be able to hear sound playing, you need to connect this op to an Output op.",0)}else{i.setUiError("outputNotConnected",null)}};n.onChange=function(){if(n.get())S();else{if(v){v=false;p.set(v)}if(m){E(0);if(c)c.buffer=null;c=null}}};r.onChange=function(){if(!n.get())return;if(!c){if(!v)S()}if(r.get()){const e=0;I(e)}else{const t=0;E(t)}};a.onChange=function(){if(c){c.loop=!!a.get()}};l.onChange=x;function x(){if(!c)return;const e=l.get()||0;if(c.detune){c.detune.setValueAtTime(e,y.currentTime)}}o.onChange=A;function A(){if(!c)return;const e=o.get()||0;if(e>=c.playbackRate.minValue&&e<=c.playbackRate.maxValue){c.playbackRate.setValueAtTime(e,y.currentTime)}}let _=false;t.onTriggered=function(){if(!c)return;if(!n.get())return;else{if(!(n.get()instanceof AudioBuffer))return}if(r.get()){if(m){_=true;E(0)}else{I(0)}}};function S(e=false){if(v)return;if(!(n.get()instanceof AudioBuffer))return;v=true;p.set(v);if(c){c.onended=null;if(c.buffer){E(0);c.disconnect(b);c.buffer=null}c=null}c=y.createBufferSource();const t=n.get();if(!t){v=false;p.set(v);return}c.buffer=t;c.onended=P;c.loop=a.get();c.connect(b);A();x();u.set(b);v=false;p.set(v);if(_){I(0);_=false;return}if(r.get()&&!e){I(0)}}let C=false;let T=null;s.onChange=()=>{if(s.get()>=0)i.setUiError("offsetNegative",null);else{i.setUiError("offsetNegative","Offset cannot be negative. Setting to 0.",1)}if(c){if(c.buffer){if(s.get()>c.buffer.duration){i.setUiError("offsetTooLong","Your offset value is higher than the total time of your audio file. Please decrease the duration to be able to hear sound when playing back your buffer.",1)}else{i.setUiError("offsetTooLong",null)}}}};function I(t){try{if(c){let e=Math.max(0,s.get());c.start(t,e);m=true;f=false;h.set(true)}else{i.log("start() but no src...")}}catch(e){i.log("Error on start: ",e.message);h.set(false);m=false}}function O(){let e=!a.get();S(e)}function E(e){try{if(c){c.stop();if(!_)O()}m=false;h.set(false)}catch(e){i.setUiError(e);h.set(false)}}function P(){if(a.get()){m=true;f=false}else{m=false;f=true}h.set(m);O()}};Ops.WebAudio.AudioBufferPlayer_v2.prototype=new CABLES.Op;CABLES.OPS["3abd0dbb-eeee-4c65-ae31-b8bc2345e2d5"]={f:Ops.WebAudio.AudioBufferPlayer_v2,objName:"Ops.WebAudio.AudioBufferPlayer_v2"};Ops.TimeLine.TimeLineControls=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.outBoolNum("Play/Stop");const n=e.outNumber("time");e.patch.timer.on("playPause",r);e.patch.timer.on("timeChange",r);function r(){i.set(false);setTimeout(function(){n.set(e.patch.timer.getTime());i.set(e.patch.timer.isPlaying())},10)}};Ops.TimeLine.TimeLineControls.prototype=new CABLES.Op;CABLES.OPS["53cb7b1a-56c7-405f-b427-12db78fbfd2f"]={f:Ops.TimeLine.TimeLineControls,objName:"Ops.TimeLine.TimeLineControls"};Ops.WebAudio.Output_v2=function(){CABLES.Op.apply(this,arguments);const r=this;const e=r.attachments={};const t=r.inObject("Audio In",null,"audioNode"),a=r.inFloatSlider("Volume",1),s=r.inBool("Mute",false),i=r.inBool("Show Audio Suspended Button",true),o=r.outNumber("Current Volume",0),n=r.outString("Context State","unknown");r.setPortGroup("Volume Settings",[s,a]);let l=false;let u=CABLES.WEBAUDIO.createAudioContext(r);let h=u.createGain();const p=u.destination;let c=null;let m=false;s.onChange=()=>{v(s.get());y()};a.onChange=g;r.onMasterVolumeChanged=g;let f=r.patch.on("pause",g);let d=r.patch.on("resume",g);u.addEventListener("statechange",y);i.onChange=b;y();b();r.onDelete=()=>{if(h)h.disconnect();h=null;if(CABLES.interActionNeededButton)CABLES.interActionNeededButton.remove("audiosuspended");if(f)r.patch.off(f);if(d)r.patch.off(d)};t.onChange=function(){if(!t.get()){if(c){try{if(c.disconnect){c.disconnect(h)}}catch(e){r.logError(e)}}r.setUiError("multipleInputs",null);if(m){if(h)h.disconnect(p);m=false}}else{if(t.links.length>1)r.setUiError("multipleInputs","You have connected multiple inputs. It is possible that you experience unexpected behaviour. Please use a Mixer op to connect multiple audio streams.",1);else r.setUiError("multipleInputs",null);if(t.get().connect)t.get().connect(h)}c=t.get();if(!m){if(h)h.connect(p);m=true}g()};function g(e){const t=r.patch.config.masterVolume||0;let i=a.get()*t;if(r.patch._paused||s.get())i=0;let n=.05;if(e)n=.2;i=CABLES.clamp(i,0,1);if(!h)r.logError("gainNode undefined");if(h)h.gain.linearRampToValueAtTime(i,u.currentTime+n);o.set(i)}function v(e){if(e){if(u.state==="suspended"){if(h){h.gain.cancelScheduledValues(u.currentTime);h.gain.value=0;h.gain.setValueAtTime(0,u.currentTime)}o.set(0);return}}g(true)}function y(){n.set(u.state);r.logVerbose("audioCtx.state change",u.state);r.setUiError("ctxSusp",null);if(u.state=="suspended"){const t="Your Browser suspended audio context, use playButton op to play audio after a user interaction";let e=1;if(s.get())e=0;r.setUiError("ctxSusp",t,e)}b()}function b(){if(u.state=="suspended"){v(true);if(i.get()){l=true;if(CABLES.interActionNeededButton){CABLES.interActionNeededButton.add(r.patch,"audiosuspended",()=>{if(u&&u.state=="suspended"){u.resume();if(CABLES.interActionNeededButton)CABLES.interActionNeededButton.remove("audiosuspended")}})}}else{if(CABLES.interActionNeededButton)CABLES.interActionNeededButton.remove("audiosuspended")}}else{if(CABLES.interActionNeededButton)CABLES.interActionNeededButton.remove("audiosuspended");if(l){r.log("was suspended - set vol");g(true)}}}};Ops.WebAudio.Output_v2.prototype=new CABLES.Op;CABLES.OPS["90b95403-b0c4-4980-ab3b-b6c354771c81"]={f:Ops.WebAudio.Output_v2,objName:"Ops.WebAudio.Output_v2"};Ops.WebAudio.AudioAnalyzer_v2=function(){CABLES.Op.apply(this,arguments);const n=this;const e=n.attachments={};const r=(e,t,i)=>{return Math.min(Math.max(e,t),i)};const a=-144;const t=-96;let i=CABLES.WEBAUDIO.createAudioContext(n);const s=n.inTrigger("Trigger In");const o=i.createAnalyser();o.smoothingTimeConstant=.3;o.fftSize=256;const l=[32,64,128,256,512,1024,2048,4096,8192,16384,32768];const u=n.inObject("Audio In",null,"audioNode");const h=n.inDropDown("FFT size",l,256);const p=n.inFloatSlider("Smoothing",.3);const c=n.inFloat("Min",-90);const m=n.inFloat("Max",0);n.setPortGroup("Inputs",[s,u]);n.setPortGroup("FFT Options",[h,p]);n.setPortGroup("Range (in dBFS)",[c,m]);const f=n.outTrigger("Trigger Out");const d=n.outObject("Audio Out",null,"audioNode");const g=n.outArray("FFT Array");const v=n.outArray("Waveform Array");const y=n.outArray("Frequencies by Index Array");const b=n.outNumber("Array Length");const x=n.outNumber("Average Volume");const A=n.outNumber("Average Volume Time-Domain");const _=n.outNumber("RMS Volume");let S=false;let C=o.frequencyBinCount;let T=new Uint8Array(C);let I=new Uint8Array(C);let O=[];O.length=C;let E=null;u.onChange=()=>{if(u.get()){const e=u.get();if(e.connect){e.connect(o);d.set(o)}}else{if(E){if(E.disconnect)E.disconnect(o);d.set(null)}}E=u.get()};function P(){try{const e=Number(h.get());o.smoothingTimeConstant=r(p.get(),0,1);o.fftSize=e;const t=r(c.get(),a,-1e-4);const i=Math.max(m.get(),o.minDecibels+1e-4);o.minDecibels=t;o.maxDecibels=i;if(t<a){n.setUiError("maxDbRangeMin","Your minimum is below the lowest possible dBFS value: "+a+"dBFS. To make sure your analyser data is correct, try increasing the minimum.",1)}else{n.setUiError("maxDbRangeMin",null)}if(i>0){n.setUiError("maxDbRangeMax","Your maximum is above 0 dBFS. As digital signals only go to 0 dBFS and not above, you should use 0 as your maximum.",1)}else{n.setUiError("maxDbRangeMax",null)}if(l.indexOf(e)>=6){n.setUiError("highFftSize","Please be careful with high FFT sizes as they can slow down rendering. Check the profiler to see if performance is impacted.",1)}else{n.setUiError("highFftSize",null)}}catch(e){n.log(e)}}h.onChange=p.onChange=c.onChange=m.onChange=()=>{if(s.isLinked())S=true;else P()};s.onTriggered=function(){if(S){P();S=false}if(C!=o.frequencyBinCount){C=o.frequencyBinCount;T=new Uint8Array(C);I=new Uint8Array(C);O=[];O.length=C;for(let e=0;e<C;e+=1){O[e]=Math.round(e*i.sampleRate/(o.fftSize*2))}y.set(null);y.set(O)}if(!T)return;if(!I)return;const e=Number(h.get());try{o.getByteFrequencyData(T);o.getByteTimeDomainData(I);let t=0;let i=0;let n=0;for(let e=0;e<o.frequencyBinCount;e++){t+=I[e]*I[e];i+=T[e];n+=I[e]}const r=i/o.frequencyBinCount;const a=n/o.frequencyBinCount;x.set(r/128);A.set(a/256);let e=Math.sqrt(t/o.frequencyBinCount);e=Math.max(e,e*p.get());_.set(e/256)}catch(e){n.log(e)}g.setRef(T);v.setRef(I);b.set(T.length);f.trigger()}};Ops.WebAudio.AudioAnalyzer_v2.prototype=new CABLES.Op;CABLES.OPS["ff9bf46c-676f-4aa1-95bf-5595a6813ed7"]={f:Ops.WebAudio.AudioAnalyzer_v2,objName:"Ops.WebAudio.AudioAnalyzer_v2"};Ops.Vars.VarSetArray_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inArray("Value",null);e.varName=e.inDropDown("Variable",[],"",true);new CABLES.VarSetOpWrapper(e,"array",i,e.varName)};Ops.Vars.VarSetArray_v2.prototype=new CABLES.Op;CABLES.OPS["8088290f-45d4-4312-b4ca-184d34ca4667"]={f:Ops.Vars.VarSetArray_v2,objName:"Ops.Vars.VarSetArray_v2"};Ops.Gl.ForceCanvasSize=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTrigger("Trigger"),l=e.inBool("Active",true),n=e.inSwitch("Force",["Resolution","Aspect Ratio"],"Resolution"),u=e.inBool("Center In Parent",true),h=e.inBool("Scale to fit Parent",true),p=e.inInt("Set Width",300),c=e.inInt("Set Height",200),r=e.inDropDown("Aspect Ratio",["Custom","21:9","2:1","16:9","16:10","4:3","1:1","9:16","1:2","iPhoneXr Vert"],"16:9"),m=e.inFloat("Ratio",0),a=e.inDropDown("Fill Parent",["Auto","Width","Height","Both"],"Auto"),f=e.outTrigger("Next"),d=e.outNumber("Width"),g=e.outNumber("Height"),v=e.outNumber("Margin Left"),y=e.outNumber("Margin Top");e.setPortGroup("Size",[p,c]);e.setPortGroup("Proportions",[m,a,r]);let b=0;const s=0;const x=1;const A=2;const _=3;const S=4;a.onChange=I;n.onChange=o;u.onChange=i.onLinkChanged=O;r.onChange=T;const C=e.patch.cgl;I();function o(){if(n.get()=="Aspect Ratio"){m.set(100);T()}I()}function T(){const e=r.get();if(e=="Custom")return;else if(e=="16:9")m.set(16/9);else if(e=="4:3")m.set(4/3);else if(e=="16:10")m.set(16/10);else if(e=="21:9")m.set(21/9);else if(e=="2:1")m.set(2);else if(e=="1:1")m.set(1);else if(e=="9:16")m.set(9/16);else if(e=="1:2")m.set(.5);else if(e=="iPhoneXr Vert")m.set(9/19.5)}e.on("delete",()=>{O()});m.onChange=()=>{O()};l.onChange=function(){if(!l.get())O()};function I(){const e=n.get()=="Resolution";p.setUiAttribs({greyout:!e});c.setUiAttribs({greyout:!e});r.setUiAttribs({greyout:e});a.setUiAttribs({greyout:e});m.setUiAttribs({greyout:e});b=0;if(!e){const t=a.get();if(t=="Width")b=x;else if(t=="Height")b=A;else if(t=="Both")b=_;else if(t=="Auto")b=S}}function O(){C.canvas.style["margin-top"]="";C.canvas.style["margin-left"]="";C.canvas.styleMarginLeft=0;C.canvas.styleMarginTop=0;v.set(0);y.set(0);const e=C.canvas.parentNode.getBoundingClientRect();C.setSize(e.width,e.height);C.canvas.style.transform="scale(1)";C.canvas.style.position="absolute";C.updateSize()}i.onTriggered=function(){if(!l.get())return f.trigger();let e=p.get();let t=c.get();let i=C.canvas.parentNode.getBoundingClientRect();if(i.height==0){C.canvas.parentNode.style.height="100%";i=C.canvas.parentNode.getBoundingClientRect()}if(i.width==0){C.canvas.parentNode.style.width="100%";i=C.canvas.parentNode.getBoundingClientRect()}if(b==x){e=i.width;t=e*1/m.get()}else if(b==A){t=i.height;e=t*m.get()}else if(b==S){const n=i;t=n.height;e=t*m.get();if(e>n.width){e=n.width;t=e*1/m.get()}}else if(b==_){const n=i;t=n.height;e=t*m.get();if(e<n.width){e=n.width;t=e*1/m.get()}}e=Math.ceil(e);t=Math.ceil(t);if(u.get()){const n=i;const r=(n.height-t)/2;const a=(n.width-e)/2;v.set(a);y.set(r);C.canvas.style["margin-top"]=r+"px";C.canvas.style["margin-left"]=a+"px";C.canvas.styleMarginTop=r;C.canvas.styleMarginLeft=a}else{C.canvas.style["margin-top"]="0";C.canvas.style["margin-left"]="0";C.canvas.styleMarginTop=0;C.canvas.styleMarginLeft=0;v.set(0);y.set(0)}if(h.get()){const n=i;const s=n.width/p.get();const o=n.height/c.get();C.canvas.style.transform="scale("+Math.min(s,o)+")"}else{C.canvas.style.transform="scale(1)"}if(C.canvas.width/C.pixelDensity!=e||C.canvas.height/C.pixelDensity!=t){d.set(e);g.set(t);C.setSize(e,t)}f.trigger()}};Ops.Gl.ForceCanvasSize.prototype=new CABLES.Op;CABLES.OPS["a8b3380e-cd4a-4000-9ee9-1c65a11027dd"]={f:Ops.Gl.ForceCanvasSize,objName:"Ops.Gl.ForceCanvasSize"};Ops.Html.Utils.PlayerControlPanel_v2=function(){CABLES.Op.apply(this,arguments);const r=this;const e=r.attachments={css_progressui_css:".progressUI\n{\n    padding: 10px;\n    position: absolute;\n    border-radius: 10px;\n    background-color: rgba(0,0,0,0.45);\n    margin: 20px;\n    bottom: 10px;\n    height:30px;\n    margin-left:50%;\n    transform: translate(-50%);\n    display: flex;\n    align-items: center;\n}\n\n.progressUI .buttonContainer {\n    display: flex;\n    align-content: center;\n    height: 100%;\n}\n\n.progressUI .progress\n{\n    font-family: Monospace;\n    float:left;\n    color:white;\n    width: auto;\n    margin-left:15px;\n    margin-right: 10px;\n}\n\n.progressUI .progressContainer\n{\n    width:200px;\n    overflow: hidden;\n    background: rgba(0,0,0,0.4);\n    border-radius: 4px;\n    float:left;\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    height: 100%;\n}\n\n.progressUI .button\n{\n    cursor: pointer;\n    box-sizing: border-box;\n    background: rgba(0,0,0,0.4);\n    display: flex;\n    align-content: center;\n    padding: 5px;\n    padding-left: 10px;\n    padding-right: 10px;\n    margin-right: 5px;\n    border-radius: 5px;\n    float:left;\n    display: flex;\n    align-items: center;\n}\n\n.progressUIIcon\n{\n    display: inline-block;\n    vertical-align: middle;\n    width: 15px;\n    height: 15px;\n    background-color: white;\n    -webkit-mask-repeat: no-repeat !important;\n    -webkit-mask-size: 100% !important;\n}\n\n.progressUI .progressContainer .progressbar {\n    height: 100%;\n    width: 97%;\n}\n\n.progressUI_icon-play {\n    -webkit-mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-play'%3E%3Cpath d='M5 3l14 9-14 9V3z'/%3E%3C/svg%3E\");\n    mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-play'%3E%3Cpath d='M5 3l14 9-14 9V3z'/%3E%3C/svg%3E\");\n}\n\n.progressUI_icon-pause {\n    -webkit-mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-pause'%3E%3Cpath d='M6 4h4v16H6zM14 4h4v16h-4z'/%3E%3C/svg%3E\");\n    mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-pause'%3E%3Cpath d='M6 4h4v16H6zM14 4h4v16h-4z'/%3E%3C/svg%3E\");\n}\n\n.progressUI_icon-rewind {\n    -webkit-mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-rewind'%3E%3Cpath d='M11 19l-9-7 9-7v14zM22 19l-9-7 9-7v14z'/%3E%3C/svg%3E\");\n    mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-rewind'%3E%3Cpath d='M11 19l-9-7 9-7v14zM22 19l-9-7 9-7v14z'/%3E%3C/svg%3E\");\n}\n\n.progressUI_icon-fast-forward {\n    -webkit-mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-fast-forward'%3E%3Cpath d='M13 19l9-7-9-7v14zM2 19l9-7-9-7v14z'/%3E%3C/svg%3E\");\n    mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-fast-forward'%3E%3Cpath d='M13 19l9-7-9-7v14zM2 19l9-7-9-7v14z'/%3E%3C/svg%3E\");\n}\n\n.progressUI_icon-skip-back {\n    -webkit-mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-skip-back'%3E%3Cpath d='M19 20L9 12l10-8v16zM5 19V5'/%3E%3C/svg%3E\");\n    mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-skip-back'%3E%3Cpath d='M19 20L9 12l10-8v16zM5 19V5'/%3E%3C/svg%3E\");\n}\n"};const t=r.inFloat("Length",30),n=r.inFloat("Current",0),i=r.inBool("Clamp",false),a=r.inBool("Is Playing",false),s=r.inBool("Visible",true),o=r.inBool("Show Time"),l=r.inBool("Show Skip Buttons"),u=r.outTrigger("Play clicked"),h=r.outTrigger("Pause clicked"),p=r.outTrigger("Rewind clicked"),c=r.outTrigger("Skip Back clicked"),m=r.outTrigger("Skip Forward clicked"),f=r.outTrigger("Dragged"),d=r.outNumber("Current Value"),g=r.outBoolNum("Dragging",false),v=r.outObject("DOM Element",null,"element");let y=r.patch.getDocument().createElement("div");y.id="progressUI_"+r.id;y.classList.add("progressUI");v.set(y);const R=r.patch.cgl;let V=r.patch.cgl.canvas.parentElement;V.appendChild(y);let b=r.patch.getDocument().createElement("div");if(!s.get()){y.style.display="none"}let x=r.patch.getDocument().createElement("input");let A=r.patch.getDocument().createElement("div");const _=r.patch.getDocument().createElement("div");b.classList.add("progressContainer");b.appendChild(x);x.setAttribute("type","range");x.setAttribute("step",.01);x.setAttribute("min",0);x.setAttribute("max",t.get());x.setAttribute("value",n.get());x.classList.add("progressbar");x.addEventListener("input",F);let S=false;let C=false;y.appendChild(_);y.appendChild(b);y.appendChild(A);let D="css_progressui_"+CABLES.uuid();const T=r.patch.getDocument().createElement("style");T.type="text/css";T.id=D;T.classList.add("cablesEle");let B=r.patch.getDocument().getElementsByTagName("body")[0];B.appendChild(T);_.classList.add("buttonContainer");let I=M("","progressUI_icon-skip-back");_.appendChild(I);let O=M("","progressUI_icon-rewind","skip");if(!l.get()){O.style.display="none"}_.appendChild(O);O.addEventListener("pointerdown",()=>{c.trigger()});let E=M("","progressUI_icon-play");_.appendChild(E);let P=M("","progressUI_icon-fast-forward","skip");if(!l.get()){P.style.display="none"}_.appendChild(P);P.addEventListener("pointerdown",()=>{m.trigger()});A.classList.add("progress");A.innerHTML="00:00:000";function M(e,t,i){let n=r.patch.getDocument().createElement("div");n.classList.add("button");n.classList.add(i);n.innerHTML=e;if(t){let e=r.patch.getDocument().createElement("div");e.classList.add("progressUIIcon");e.classList.add(t);n.appendChild(e)}return n}t.onChange=()=>{x.setAttribute("max",t.get())};s.onChange=()=>{if(s.get()){y.style.removeProperty("display")}else{y.style.display="none"}};o.onChange=()=>{if(o.get()){y.classList.add("showValue");A.style.display="block"}else{y.classList.remove("showValue");A.style.display="none"}};l.onChange=()=>{if(l.get()){y.querySelectorAll(".button.skip").forEach(e=>{e.style.display="block"})}else{y.querySelectorAll(".button.skip").forEach(e=>{e.style.display="none"})}};if(!o.get()){A.style.display="none"}x.addEventListener("pointerdown",()=>{C=true;if(a.get()){S=true;h.trigger();L()}});x.addEventListener("pointermove",()=>{const e=x.value;if(C){g.set(C);w(e);d.set(e);f.trigger()}});x.addEventListener("pointerup",()=>{const e=x.value;w(e);d.set(e);if(C){f.trigger()}C=false;g.set(C);if(S){S=false;u.trigger();L()}});function j(){T.textContent=e.css_progressui_css}function L(){E.querySelector(".progressUIIcon").classList.remove("progressUI_icon-play");E.querySelector(".progressUIIcon").classList.remove("progressUI_icon-pause");if(a.get()){E.querySelector(".progressUIIcon").classList.add("progressUI_icon-pause")}else{E.querySelector(".progressUIIcon").classList.add("progressUI_icon-play")}}E.addEventListener("pointerdown",function(){if(a.get()){h.trigger()}else{u.trigger()}L()});I.addEventListener("pointerdown",()=>{d.set(0);p.trigger()});r.onDelete=function(){if(y)y.remove();if(T)T.remove()};function F(e){n.onChange=null;const t=e.target.value;d.set(t);n.onChange=N}function N(){let e=n.get();if(i.get()&&e>t.get()){e=t.get()}x.value=e;d.set(e);w()}let k=0;function w(e=null){let t=e||n.get();let i=t;if(i!=k){A.innerHTML=U(i);k=i}}function U(e){const t=String(new Date(e*1e3).getUTCMinutes()).padStart(2,"0");const i=String(new Date(e*1e3).getUTCSeconds()).padStart(2,"0");const n=String(new Date(e*1e3).getUTCMilliseconds()).padStart(2,"0").padEnd(3,"0");const r=t+":"+i+":"+n;return r}j();L();n.onChange=N;a.onChange=L};Ops.Html.Utils.PlayerControlPanel_v2.prototype=new CABLES.Op;CABLES.OPS["12ac1d94-f043-454d-92a8-60733d2908b2"]={f:Ops.Html.Utils.PlayerControlPanel_v2,objName:"Ops.Html.Utils.PlayerControlPanel_v2"};Ops.TimeLine.TimeLineTime=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.outNumber("time");e.onAnimFrame=function(e){i.set(e)}};Ops.TimeLine.TimeLineTime.prototype=new CABLES.Op;CABLES.OPS["3ab26f26-a12a-4c48-9411-20591a5f569d"]={f:Ops.TimeLine.TimeLineTime,objName:"Ops.TimeLine.TimeLineTime"};Ops.Cables.UIMode=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.outBoolNum("UI",e.patch.isEditorMode()),n=e.outBoolNum("Overlay Mode",false),r=e.outBoolNum("Remote Viewer",window.gui?window.gui.isRemoteClient:false),a=e.outBoolNum("Is Standalone",CABLES.platform&&CABLES.platform.frontendOptions.isStandalone),s=e.outNumber("Canvas Mode"),o=e.outBoolNum("Patch Field Visible");if(CABLES.UI){n.set(gui.shouldDrawOverlay);gui.on("overlaysChanged",e=>{n.set(e)});gui.on("canvasModeChange",()=>{s.set(gui.canvasManager.mode);o.set(gui.patchView.element.classList.contains("hidden"))})}};Ops.Cables.UIMode.prototype=new CABLES.Op;CABLES.OPS["7c110d60-829f-4b06-b3e4-0af911550570"]={f:Ops.Cables.UIMode,objName:"Ops.Cables.UIMode"};Ops.TimeLine.TimeLineSetTime=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTriggerButton("Update"),n=e.inFloat("Time",0),r=e.outTrigger("Next");i.onTriggered=function(){e.patch.timer.setTime(parseFloat(n.get()));r.trigger()}};Ops.TimeLine.TimeLineSetTime.prototype=new CABLES.Op;CABLES.OPS["c65f3975-0901-4252-b040-f21f9b144d70"]={f:Ops.TimeLine.TimeLineSetTime,objName:"Ops.TimeLine.TimeLineSetTime"};Ops.TimeLine.TimeLinePlay=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTriggerButton("Play"),n=e.inTriggerButton("Pause"),r=e.outTrigger("Next");i.onTriggered=function(){e.patch.timer.play();r.trigger()};n.onTriggered=function(){e.patch.timer.pause();r.trigger()}};Ops.TimeLine.TimeLinePlay.prototype=new CABLES.Op;CABLES.OPS["fc75b841-a55f-4474-8746-61218588598d"]={f:Ops.TimeLine.TimeLinePlay,objName:"Ops.TimeLine.TimeLinePlay"};Ops.Gl.RenderToTexture_v3=function(){CABLES.Op.apply(this,arguments);const r=this;const e=r.attachments={};const t=r.inTrigger("render"),i=r.inSwitch("Size",["Canvas","Manual"],"Canvas"),n=r.inValueInt("texture width",512),a=r.inValueInt("texture height",512),s=r.inBool("Auto Aspect",true),o=r.inSwitch("filter",["nearest","linear","mipmap"],"linear"),l=r.inSwitch("Wrap",["Clamp","Repeat","Mirror"],"Repeat"),u=r.inSwitch("MSAA",["none","2x","4x","8x"],"none"),h=r.outTrigger("trigger"),p=r.outTexture("texture"),c=r.outTexture("textureDepth"),m=r.inDropDown("Pixel Format",CGL.Texture.PIXELFORMATS,CGL.Texture.PFORMATSTR_RGBA8UB),f=r.inValueBool("Depth",true),d=r.inValueBool("Clear",true);const g=r.patch.cgl;let v=null;let y=true;r.setPortGroup("Size",[i,n,a,s]);m.onChange=f.onChange=d.onChange=o.onChange=l.onChange=u.onChange=x;i.onChange=b;t.onTriggered=r.preRender=A;b();function b(){n.setUiAttribs({greyout:i.get()!="Manual"});a.setUiAttribs({greyout:i.get()!="Manual"});s.setUiAttribs({greyout:i.get()!="Manual"})}function x(){y=true}function A(){CGL.TextureEffect.checkOpNotInTextureEffect(r);if(!v||y){if(v)v.delete();let i=CGL.Texture.WRAP_REPEAT;if(l.get()=="Clamp")i=CGL.Texture.WRAP_CLAMP_TO_EDGE;else if(l.get()=="Mirror")i=CGL.Texture.WRAP_MIRRORED_REPEAT;let n=CGL.Texture.FILTER_NEAREST;if(o.get()=="nearest")n=CGL.Texture.FILTER_NEAREST;else if(o.get()=="linear")n=CGL.Texture.FILTER_LINEAR;else if(o.get()=="mipmap")n=CGL.Texture.FILTER_MIPMAP;if(m.get().indexOf("loat")&&o.get()=="mipmap")r.setUiError("fpmipmap","Can't use mipmap and float texture at the same time");else r.setUiError("fpmipmap",null);if(g.glVersion>=2){let e=true;let t=4;if(u.get()=="none"){t=0;e=false}if(u.get()=="2x")t=2;if(u.get()=="4x")t=4;if(u.get()=="8x")t=8;v=new CGL.Framebuffer2(g,8,8,{name:"render2texture "+r.id,pixelFormat:m.get(),multisampling:e,multisamplingSamples:t,wrap:i,filter:n,depth:f.get(),clear:d.get()})}else{v=new CGL.Framebuffer(g,8,8,{isFloatingPointTexture:false,clear:d.get()})}if(v&&v.valid){c.setRef(v.getTextureDepth());y=false}else{v=null;y=true}}let e=s.get();if(i.get()=="Canvas"){e=true;n.set(r.patch.cgl.checkTextureSize(g.canvasWidth));a.set(r.patch.cgl.checkTextureSize(g.canvasHeight))}if(v.getWidth()!=r.patch.cgl.checkTextureSize(n.get())||v.getHeight()!=r.patch.cgl.checkTextureSize(a.get())){v.setSize(r.patch.cgl.checkTextureSize(n.get()),r.patch.cgl.checkTextureSize(a.get()))}v.renderStart(g);g.pushViewPort(0,0,n.get(),a.get());if(e)mat4.perspective(g.pMatrix,45,n.get()/a.get(),.1,1e3);h.trigger();v.renderEnd(g);g.popViewPort();c.setRef(v.getTextureDepth());p.setRef(v.getTextureColor())}};Ops.Gl.RenderToTexture_v3.prototype=new CABLES.Op;CABLES.OPS["41eec5c7-c480-477a-be81-04c3efac8357"]={f:Ops.Gl.RenderToTexture_v3,objName:"Ops.Gl.RenderToTexture_v3"};Ops.Gl.ImageCompose.DrawImage_v3=function(){CABLES.Op.apply(this,arguments);const n=this;const e=n.attachments={drawimage_frag:"#ifdef HAS_TEXTURES\n    IN vec2 texCoord;\n    UNI sampler2D tex;\n    UNI sampler2D image;\n#endif\n\n#ifdef TEX_TRANSFORM\n    IN mat3 transform;\n#endif\n// UNI float rotate;\n\n{{CGL.BLENDMODES}}\n\n#ifdef HAS_TEXTUREALPHA\n   UNI sampler2D imageAlpha;\n#endif\n\nUNI float amount;\n\n#ifdef ASPECT_RATIO\n    UNI float aspectTex;\n    UNI float aspectPos;\n#endif\n\nvoid main()\n{\n    vec4 blendRGBA=vec4(0.0,0.0,0.0,1.0);\n\n    #ifdef HAS_TEXTURES\n        vec2 tc=texCoord;\n\n        #ifdef TEX_FLIP_X\n            tc.x=1.0-tc.x;\n        #endif\n        #ifdef TEX_FLIP_Y\n            tc.y=1.0-tc.y;\n        #endif\n\n        #ifdef ASPECT_RATIO\n            #ifdef ASPECT_AXIS_X\n                tc.y=(1.0-aspectPos)-(((1.0-aspectPos)-tc.y)*aspectTex);\n            #endif\n            #ifdef ASPECT_AXIS_Y\n                tc.x=(1.0-aspectPos)-(((1.0-aspectPos)-tc.x)/aspectTex);\n            #endif\n        #endif\n\n        #ifdef TEX_TRANSFORM\n            vec3 coordinates=vec3(tc.x, tc.y,1.0);\n            tc=(transform * coordinates ).xy;\n        #endif\n\n        blendRGBA=texture(image,tc);\n\n        vec3 blend=blendRGBA.rgb;\n        vec4 baseRGBA=texture(tex,texCoord);\n        vec3 base=baseRGBA.rgb;\n\n\n        #ifdef PREMUL\n            blend.rgb = (blend.rgb) + (base.rgb * (1.0 - blendRGBA.a));\n        #endif\n\n        vec3 colNew=_blend(base,blend);\n\n\n\n\n        #ifdef REMOVE_ALPHA_SRC\n            blendRGBA.a=1.0;\n        #endif\n\n        #ifdef HAS_TEXTUREALPHA\n            vec4 colImgAlpha=texture(imageAlpha,tc);\n            float colImgAlphaAlpha=colImgAlpha.a;\n\n            #ifdef ALPHA_FROM_LUMINANCE\n                vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), colImgAlpha.rgb ));\n                colImgAlphaAlpha=(gray.r+gray.g+gray.b)/3.0;\n            #endif\n\n            #ifdef ALPHA_FROM_INV_UMINANCE\n                vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), colImgAlpha.rgb ));\n                colImgAlphaAlpha=1.0-(gray.r+gray.g+gray.b)/3.0;\n            #endif\n\n            #ifdef INVERT_ALPHA\n                colImgAlphaAlpha=clamp(colImgAlphaAlpha,0.0,1.0);\n                colImgAlphaAlpha=1.0-colImgAlphaAlpha;\n            #endif\n\n            blendRGBA.a=colImgAlphaAlpha*blendRGBA.a;\n        #endif\n    #endif\n\n    float am=amount;\n\n    #ifdef CLIP_REPEAT\n        if(tc.y>1.0 || tc.y<0.0 || tc.x>1.0 || tc.x<0.0)\n        {\n            // colNew.rgb=vec3(0.0);\n            am=0.0;\n        }\n    #endif\n\n    #ifdef ASPECT_RATIO\n        #ifdef ASPECT_CROP\n            if(tc.y>1.0 || tc.y<0.0 || tc.x>1.0 || tc.x<0.0)\n            {\n                colNew.rgb=base.rgb;\n                am=0.0;\n            }\n\n        #endif\n    #endif\n\n\n\n    #ifndef PREMUL\n        blendRGBA.rgb=mix(colNew,base,1.0-(am*blendRGBA.a));\n        blendRGBA.a=clamp(baseRGBA.a+(blendRGBA.a*am),0.,1.);\n    #endif\n\n    #ifdef PREMUL\n        // premultiply\n        // blendRGBA.rgb = (blendRGBA.rgb) + (baseRGBA.rgb * (1.0 - blendRGBA.a));\n        blendRGBA=vec4(\n            mix(colNew.rgb,base,1.0-(am*blendRGBA.a)),\n            blendRGBA.a*am+baseRGBA.a\n            );\n    #endif\n\n    #ifdef ALPHA_MASK\n    blendRGBA.a=baseRGBA.a;\n    #endif\n\n    outColor=blendRGBA;\n}\n\n\n\n\n\n\n\n",drawimage_vert:"IN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\n\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\n\nOUT vec2 texCoord;\n// OUT vec3 norm;\n\n#ifdef TEX_TRANSFORM\n    UNI float posX;\n    UNI float posY;\n    UNI float scaleX;\n    UNI float scaleY;\n    UNI float rotate;\n    OUT mat3 transform;\n#endif\n\nvoid main()\n{\n   texCoord=attrTexCoord;\n//   norm=attrVertNormal;\n\n   #ifdef TEX_TRANSFORM\n        vec3 coordinates=vec3(attrTexCoord.x, attrTexCoord.y,1.0);\n        float angle = radians( rotate );\n        vec2 scale= vec2(scaleX,scaleY);\n        vec2 translate= vec2(posX,posY);\n\n        transform = mat3(   scale.x * cos( angle ), scale.x * sin( angle ), 0.0,\n            - scale.y * sin( angle ), scale.y * cos( angle ), 0.0,\n            - 0.5 * scale.x * cos( angle ) + 0.5 * scale.y * sin( angle ) - 0.5 * translate.x*2.0 + 0.5,  - 0.5 * scale.x * sin( angle ) - 0.5 * scale.y * cos( angle ) - 0.5 * translate.y*2.0 + 0.5, 1.0);\n   #endif\n\n   gl_Position = projMatrix * mvMatrix * vec4(vPosition,  1.0);\n}\n"};const t=n.inTrigger("render"),i=CGL.TextureEffect.AddBlendSelect(n,"blendMode"),r=n.inValueSlider("amount",1),a=n.inTexture("Image"),s=n.inValueBool("Premultiplied",false),o=n.inValueBool("Alpha Mask",false),l=n.inValueBool("removeAlphaSrc",false),u=n.inTexture("Mask"),h=n.inValueSelect("Mask Src",["alpha channel","luminance","luminance inv"],"luminance"),p=n.inValueBool("Invert alpha channel"),c=n.inValueBool("Aspect Ratio",false),m=n.inValueSelect("Stretch Axis",["X","Y"],"X"),f=n.inValueSlider("Position",0),d=n.inValueBool("Crop",false),g=n.outTrigger("trigger");i.set("normal");const v=n.patch.cgl;const y=new CGL.Shader(v,"drawimage");u.onLinkChanged=b;n.setPortGroup("Mask",[u,h,p]);n.setPortGroup("Aspect Ratio",[c,f,d,m]);function b(){if(u.isLinked()){l.setUiAttribs({greyout:true});h.setUiAttribs({greyout:false});p.setUiAttribs({greyout:false})}else{l.setUiAttribs({greyout:false});h.setUiAttribs({greyout:true});p.setUiAttribs({greyout:true})}}n.toWorkPortsNeedToBeLinked(a);y.setSource(e.drawimage_vert,e.drawimage_frag);const x=new CGL.Uniform(y,"t","tex",0),R=new CGL.Uniform(y,"t","image",1),V=new CGL.Uniform(y,"t","imageAlpha",2),A=new CGL.Uniform(y,"f","aspectTex",1),D=new CGL.Uniform(y,"f","aspectPos",f);c.onChange=d.onChange=m.onChange=_;function _(){y.removeDefine("ASPECT_AXIS_X");y.removeDefine("ASPECT_AXIS_Y");y.removeDefine("ASPECT_CROP");f.setUiAttribs({greyout:!c.get()});d.setUiAttribs({greyout:!c.get()});m.setUiAttribs({greyout:!c.get()});if(c.get()){y.define("ASPECT_RATIO");if(d.get())y.define("ASPECT_CROP");if(m.get()=="X")y.define("ASPECT_AXIS_X");if(m.get()=="Y")y.define("ASPECT_AXIS_Y")}else{y.removeDefine("ASPECT_RATIO");if(d.get())y.define("ASPECT_CROP");if(m.get()=="X")y.define("ASPECT_AXIS_X");if(m.get()=="Y")y.define("ASPECT_AXIS_Y")}}const S=n.inValueBool("flip x");const C=n.inValueBool("flip y");let T=n.inValueBool("Transform");let I=n.inValueSlider("Scale X",1);let O=n.inValueSlider("Scale Y",1);let E=n.inValue("Position X",0);let P=n.inValue("Position Y",0);let M=n.inValue("Rotation",0);const L=n.inValueBool("Clip Repeat",false);const B=new CGL.Uniform(y,"f","scaleX",I);const j=new CGL.Uniform(y,"f","scaleY",O);const F=new CGL.Uniform(y,"f","posX",E);const U=new CGL.Uniform(y,"f","posY",P);const G=new CGL.Uniform(y,"f","rotate",M);T.onChange=N;function N(){y.toggleDefine("TEX_TRANSFORM",T.get());I.setUiAttribs({greyout:!T.get()});O.setUiAttribs({greyout:!T.get()});E.setUiAttribs({greyout:!T.get()});P.setUiAttribs({greyout:!T.get()});M.setUiAttribs({greyout:!T.get()})}CGL.TextureEffect.setupBlending(n,y,i,r);const z=new CGL.Uniform(y,"f","amount",r);t.onTriggered=w;L.onChange=u.onChange=s.onChange=o.onChange=p.onChange=C.onChange=S.onChange=l.onChange=h.onChange=k;N();b();_();k();function k(){y.toggleDefine("REMOVE_ALPHA_SRC",l.get());y.toggleDefine("ALPHA_MASK",o.get());y.toggleDefine("CLIP_REPEAT",L.get());y.toggleDefine("HAS_TEXTUREALPHA",u.get()&&u.get().tex);y.toggleDefine("TEX_FLIP_X",S.get());y.toggleDefine("TEX_FLIP_Y",C.get());y.toggleDefine("INVERT_ALPHA",p.get());y.toggleDefine("ALPHA_FROM_LUMINANCE",h.get()=="luminance");y.toggleDefine("ALPHA_FROM_INV_UMINANCE",h.get()=="luminance_inv");y.toggleDefine("PREMUL",s.get())}function w(){if(!CGL.TextureEffect.checkOpInEffect(n))return;const e=a.get();if(e&&e.tex&&r.get()>0){v.pushShader(y);v.currentTextureEffect.bind();const t=v.currentTextureEffect.getCurrentSourceTexture();v.setTexture(0,t.tex);const i=1/(v.currentTextureEffect.getWidth()/v.currentTextureEffect.getHeight())*(e.width/e.height);A.setValue(i);v.setTexture(1,e.tex);if(u.get()&&u.get().tex){v.setTexture(2,u.get().tex)}v.pushBlendMode(CGL.BLEND_NONE,true);v.currentTextureEffect.finish();v.popBlendMode();v.popShader()}g.trigger()}};Ops.Gl.ImageCompose.DrawImage_v3.prototype=new CABLES.Op;CABLES.OPS["8f6b2f15-fcb0-4597-90c0-e5173f2969fe"]={f:Ops.Gl.ImageCompose.DrawImage_v3,objName:"Ops.Gl.ImageCompose.DrawImage_v3"};Ops.Gl.Meshes.FullscreenRectangle_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={shader_frag:"UNI sampler2D tex;\nIN vec2 texCoord;\n\nvoid main()\n{\n    outColor= texture(tex,texCoord);\n}\n\n",shader_vert:"{{MODULES_HEAD}}\n\nIN vec3 vPosition;\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\n\nOUT vec2 texCoord;\nIN vec2 attrTexCoord;\n\nvoid main()\n{\n   vec4 pos=vec4(vPosition,  1.0);\n\n   texCoord=vec2(attrTexCoord.x,(1.0-attrTexCoord.y));\n\n   gl_Position = projMatrix * mvMatrix * pos;\n}\n"};const i=e.inTrigger("render"),n=e.inSwitch("Scale",["Stretch","Fit"],"Fit"),r=e.inValueBool("Flip Y"),a=e.inValueBool("Flip X"),s=e.inTexture("Texture"),o=e.outTrigger("trigger");const l=e.patch.cgl;let u=null;let h=new CGL.Geometry("fullscreen rectangle");let p=0,c=0,m=0,f=0;e.toWorkShouldNotBeChild("Ops.Gl.TextureEffects.ImageCompose",CABLES.OP_PORT_TYPE_FUNCTION);e.toWorkPortsNeedToBeLinked(i);a.onChange=S;r.onChange=S;i.onTriggered=_;s.onLinkChanged=b;n.onChange=A;const d=new CGL.Shader(l,"fullscreenrectangle",this);d.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"]);d.setSource(t.shader_vert,t.shader_frag);d.fullscreenRectUniform=new CGL.Uniform(d,"t","tex",0);d.aspectUni=new CGL.Uniform(d,"f","aspectTex",0);let g=false;let v=true;let y=false;b();A();s.onChange=function(){v=true};function b(){if(!CABLES.UI)return;r.setUiAttribs({greyout:!s.isLinked()});a.setUiAttribs({greyout:!s.isLinked()});n.setUiAttribs({greyout:!s.isLinked()})}function x(){let e=s.get();if(e)g=true;else g=false}e.preRender=function(){x();d.bind();if(u)u.render(d);_()};function A(){y=n.get()=="Fit"}function _(){if(l.viewPort[2]!=m||l.viewPort[3]!=f||!u)C();if(v)x();l.pushPMatrix();mat4.identity(l.pMatrix);mat4.ortho(l.pMatrix,0,m,f,0,-10,1e3);l.pushModelMatrix();mat4.identity(l.mMatrix);l.pushViewMatrix();mat4.identity(l.vMatrix);if(y&&s.get()){const i=s.get().width/s.get().height;let e=f;let t=f*i;if(t>m){e=m*1/i;t=m}l.pushViewPort((m-t)/2,(f-e)/2,t,e)}if(g){if(s.get())l.setTexture(0,s.get().tex);u.render(d)}else{u.render(l.getShader())}l.gl.clear(l.gl.DEPTH_BUFFER_BIT);l.popPMatrix();l.popModelMatrix();l.popViewMatrix();if(y&&s.get())l.popViewPort();o.trigger()}function S(){u=null}function C(){if(l.viewPort[2]==m&&l.viewPort[3]==f&&u)return;let e=0,t=0;m=l.viewPort[2];f=l.viewPort[3];h.vertices=new Float32Array([e+m,t+f,0,e,t+f,0,e+m,t,0,e,t,0]);let i=null;if(r.get())i=new Float32Array([1,0,0,0,1,1,0,1]);else i=new Float32Array([1,1,0,1,1,0,0,0]);if(a.get()){i[0]=0;i[2]=1;i[4]=0;i[6]=1}h.setTexCoords(i);h.verticesIndices=new Uint16Array([2,1,0,3,1,2]);h.vertexNormals=new Float32Array([0,0,1,0,0,1,0,0,1,0,0,1]);h.tangents=new Float32Array([-1,0,0,-1,0,0,-1,0,0,-1,0,0]);h.biTangents==new Float32Array([0,-1,0,0,-1,0,0,-1,0,0,-1,0]);if(!u)u=new CGL.Mesh(l,h);else u.setGeom(h)}};Ops.Gl.Meshes.FullscreenRectangle_v2.prototype=new CABLES.Op;CABLES.OPS["fb70721a-eac2-4ff5-a5a2-5c59e2393972"]={f:Ops.Gl.Meshes.FullscreenRectangle_v2,objName:"Ops.Gl.Meshes.FullscreenRectangle_v2"};Ops.Gl.ImageCompose.ImageCompose_v4=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={imgcomp_frag:"IN vec2 texCoord;\nUNI vec4 bgColor;\nUNI sampler2D tex;\n#ifdef USE_UVTEX\nUNI sampler2D UVTex;\n#endif\n\nvoid main()\n{\n\n    #ifndef USE_TEX\n        outColor=bgColor;\n    #endif\n    #ifdef USE_TEX\n        #ifndef USE_UVTEX\n        outColor=texture(tex,texCoord);\n        #else\n        outColor=texture(tex,texture(UVTex,texCoord).xy);\n        #endif\n    #endif\n\n\n\n}\n"};const t=i.patch.cgl,n=i.inTrigger("Render"),r=i.inTexture("Base Texture"),a=i.inTexture("UV Texture"),s=i.inSwitch("Size",["Auto","Canvas","Manual"],"Auto"),o=i.inValueInt("Width",640),l=i.inValueInt("Height",480),u=i.inSwitch("Filter",["nearest","linear","mipmap"],"linear"),h=i.inValueSelect("Wrap",["clamp to edge","repeat","mirrored repeat"],"repeat"),p=i.inSwitch("Anisotropic",["0","1","2","4","8","16"],"0"),c=i.inDropDown("Pixel Format",CGL.Texture.PIXELFORMATS,CGL.Texture.PFORMATSTR_RGBA8UB),m=i.inBool("Clear",true),f=i.inValueSlider("R",0),d=i.inValueSlider("G",0),g=i.inValueSlider("B",0),v=i.inValueSlider("A",0),y=i.outTrigger("Next"),b=i.outTexture("texture_out",CGL.Texture.getEmptyTexture(t)),x=i.outNumber("Aspect Ratio"),R=i.outNumber("Texture Width"),V=i.outNumber("Texture Height");i.setPortGroup("Texture Size",[s,o,l]);i.setPortGroup("Texture Parameters",[h,p,u,c]);f.setUiAttribs({colorPick:true});i.setPortGroup("Color",[f,d,g,v,m]);i.toWorkPortsNeedToBeLinked(n);const D=[0,0,0,0];let A=null;let _=null;let S=true;let B=false;let C=null;let j=null;let F=null;let U=null;h.onChange=u.onChange=p.onChange=c.onChange=G;r.onLinkChanged=m.onChange=s.onChange=a.onChange=N;n.onTriggered=i.preRender=w;N();function T(){if(A)A.delete();if(_)_.delete();_=null;A=new CGL.TextureEffect(t,{isFloatingPointTexture:CGL.Texture.isPixelFormatFloat(c.get()),name:i.name});const e=Math.min(t.maxAnisotropic,parseFloat(p.get()));_=new CGL.Texture(t,{anisotropic:e,name:"image_compose_v2_"+i.id,pixelFormat:c.get(),filter:I(),wrap:O(),width:E(),height:P()});A.setSourceTexture(_);R.set(E());V.set(P());x.set(E()/P());b.set(CGL.Texture.getEmptyTexture(t));S=false;N()}function I(){if(u.get()=="nearest")return CGL.Texture.FILTER_NEAREST;else if(u.get()=="linear")return CGL.Texture.FILTER_LINEAR;else if(u.get()=="mipmap")return CGL.Texture.FILTER_MIPMAP}function O(){if(h.get()=="repeat")return CGL.Texture.WRAP_REPEAT;else if(h.get()=="mirrored repeat")return CGL.Texture.WRAP_MIRRORED_REPEAT;else if(h.get()=="clamp to edge")return CGL.Texture.WRAP_CLAMP_TO_EDGE}function E(){let e=0;if(r.get()&&s.get()=="Auto")e=r.get().width;else if(s.get()=="Auto"||s.get()=="Canvas")e=t.canvasWidth;else if(s.get()=="ViewPort")e=t.getViewPort()[2];else e=Math.ceil(o.get());return i.patch.cgl.checkTextureSize(e)}function P(){let e=0;if(r.get()&&s.get()=="Auto")e=r.get().height;else if(s.get()=="Auto"||s.get()=="Canvas")e=t.canvasHeight;else if(s.get()=="ViewPort")e=t.getViewPort()[3];else e=Math.ceil(l.get());return i.patch.cgl.checkTextureSize(e)}function G(){S=true}function z(){if((E()!=_.width||P()!=_.height||_.pixelFormat!=c.get()||_.filter!=I()||_.wrap!=O())&&(E()!==0&&P()!==0)){T();A.setSourceTexture(_);b.set(CGL.Texture.getEmptyTexture(t));b.set(_);M();k()}}function M(){let e=null;if(s.get()=="Manual"){e=null}else if(s.get()=="Auto"){if(r.get())e="Input Texture";else e="Canvas Size";e+=": "+E()+" x "+P()}let t=false;t=s.uiAttribs.info!=e;s.setUiAttribs({info:e});if(t)i.refreshParams()}function L(){if(C)C.toggleDefine("USE_TEX",r.isLinked()||!m.get());if(C)C.toggleDefine("USE_UVTEX",a.isLinked())}function N(){p.setUiAttribs({greyout:I()!=CGL.Texture.FILTER_MIPMAP});f.setUiAttribs({greyout:r.isLinked()});g.setUiAttribs({greyout:r.isLinked()});d.setUiAttribs({greyout:r.isLinked()});v.setUiAttribs({greyout:r.isLinked()});m.setUiAttribs({greyout:r.isLinked()});o.setUiAttribs({greyout:s.get()!="Manual"});l.setUiAttribs({greyout:s.get()!="Manual"});if(_)if(CGL.Texture.isPixelFormatFloat(c.get())&&I()==CGL.Texture.FILTER_MIPMAP)i.setUiError("fpmipmap","Don't use mipmap and 32bit at the same time, many systems do not support this.");else i.setUiError("fpmipmap",null);M();L();k()}function k(){if(_)if(r.isLinked()&&r.get()&&_.isFloatingPoint()!=r.get().isFloatingPoint())i.setUiError("textypediff","Warning: Mixing floating point and non floating point texture can result in data/precision loss",1);else i.setUiError("textypediff",null)}i.preRender=()=>{w()};function q(){if(!C){C=new CGL.Shader(t,"copytextureshader");C.setSource(C.getDefaultVertexShader(),e.imgcomp_frag);j=new CGL.Uniform(C,"t","tex",0);F=new CGL.Uniform(C,"t","UVTex",1);U=new CGL.Uniform(C,"4f","bgColor",f,d,g,v);L()}t.pushShader(C);t.currentTextureEffect.bind();if(r.get())t.setTexture(0,r.get().tex);else if(!m.get()&&b.get())t.setTexture(0,b.get().tex);if(a.get())t.setTexture(1,a.get().tex);t.currentTextureEffect.finish();t.popShader()}function w(){if(!A||S)T();t.pushBlend(false);z();const e=t.currentTextureEffect;t.currentTextureEffect=A;t.currentTextureEffect.imgCompVer=3;t.currentTextureEffect.width=o.get();t.currentTextureEffect.height=l.get();A.setSourceTexture(_);A.startEffect(r.get()||CGL.Texture.getEmptyTexture(t,B),true);q();y.trigger();t.pushViewPort(0,0,o.get(),l.get());A.endEffect();b.setRef(A.getCurrentSourceTexture());t.popViewPort();t.popBlend();t.currentTextureEffect=e}};Ops.Gl.ImageCompose.ImageCompose_v4.prototype=new CABLES.Op;CABLES.OPS["17212e2b-d692-464c-8f8d-2d511dd3410a"]={f:Ops.Gl.ImageCompose.ImageCompose_v4,objName:"Ops.Gl.ImageCompose.ImageCompose_v4"};Ops.Math.Divide=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inValueFloat("number1",1),n=e.inValueFloat("number2",2),r=e.outNumber("result");e.setUiAttribs({mathTitle:true});i.onChange=n.onChange=a;a();function a(){r.set(i.get()/n.get())}};Ops.Math.Divide.prototype=new CABLES.Op;CABLES.OPS["86fcfd8c-038d-4b91-9820-a08114f6b7eb"]={f:Ops.Math.Divide,objName:"Ops.Math.Divide"};Ops.Gl.ImageCompose.FXAA=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={fxaa_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float FXAA_SPAN_MAX;\nUNI float FXAA_REDUCE_MUL;\nUNI float FXAA_REDUCE_MIN;\nUNI float width;\nUNI float height;\n\nvec4 getColorFXAA(vec2 coord)\n{\n    vec2 invtexsize=vec2(1.0/width,1.0/height);\n\n    float step=1.0;\n\n    vec3 rgbNW = texture(tex, coord.xy + (vec2(-step, -step)*invtexsize )).xyz;\n    vec3 rgbNE = texture(tex, coord.xy + (vec2(+step, -step)*invtexsize )).xyz;\n    vec3 rgbSW = texture(tex, coord.xy + (vec2(-step, +step)*invtexsize )).xyz;\n    vec3 rgbSE = texture(tex, coord.xy + (vec2(+step, +step)*invtexsize )).xyz;\n    vec3 rgbM  = texture(tex, coord.xy).xyz;\n\n    vec3 luma = vec3(0.299, 0.587, 0.114);\n    float lumaNW = dot(rgbNW, luma);\n    float lumaNE = dot(rgbNE, luma);\n    float lumaSW = dot(rgbSW, luma);\n    float lumaSE = dot(rgbSE, luma);\n    float lumaM  = dot( rgbM, luma);\n\n    float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n    float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\n    vec2 dir;\n    dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n    dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n\n    float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n\n    float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);\n\n    dir = min(vec2(FXAA_SPAN_MAX,  FXAA_SPAN_MAX),\n          max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin))*invtexsize ;\n\n    vec3 rgbA = (1.0/2.0) * (\n                texture(tex, coord.xy + dir * (1.0/3.0 - 0.5)).xyz +\n                texture(tex, coord.xy + dir * (2.0/3.0 - 0.5)).xyz);\n    vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (\n                texture(tex, coord.xy + dir * (0.0/3.0 - 0.5)).xyz +\n                texture(tex, coord.xy + dir * (3.0/3.0 - 0.5)).xyz);\n    float lumaB = dot(rgbB, luma);\n\n    vec4 color=texture(tex,coord).rgba;\n\n    if((lumaB < lumaMin) || (lumaB > lumaMax)){\n      color.xyz=rgbA;\n    } else {\n      color.xyz=rgbB;\n    }\n    return color;\n}\n\nvoid main()\n{\n   vec4 col=vec4(1.0,0.0,0.0,1.0);\n   outColor= getColorFXAA(texCoord);\n}"};let i=e.inTrigger("render");let n=e.outTrigger("trigger");let r=e.inValueSelect("span",[0,2,4,8,16,32,64]);let a=e.inValueFloat("reduceMin");let s=e.inValueFloat("reduceMul");let o=e.inValueBool("use viewport size",true);let l=e.inValueInt("width");let u=e.inValueInt("height");let h=e.patch.cgl;let p=new CGL.Shader(h,e.name,e);p.setSource(p.getDefaultVertexShader(),t.fxaa_frag);let c=new CGL.Uniform(p,"t","tex",0);i.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;h.pushShader(p);if(h.getViewPort()[2]!=l.get()||h.getViewPort()[3]!=u.get()){y()}h.currentTextureEffect.bind();h.setTexture(0,h.currentTextureEffect.getCurrentSourceTexture().tex);h.currentTextureEffect.finish();h.popShader();n.trigger()};let m=new CGL.Uniform(p,"f","FXAA_SPAN_MAX",0);let f=new CGL.Uniform(p,"f","FXAA_REDUCE_MUL",0);let d=new CGL.Uniform(p,"f","FXAA_REDUCE_MIN",0);r.onChange=function(){m.setValue(parseInt(r.get(),10))};let g=new CGL.Uniform(p,"f","width",0);let v=new CGL.Uniform(p,"f","height",0);function y(){if(o.get()){let e=h.getViewPort()[2];let t=h.getViewPort()[3];g.setValue(e);v.setValue(t)}else{g.setValue(l.get());v.setValue(u.get())}}l.onChange=y;u.onChange=y;o.onChange=y;e.onResize=y;r.set(8);s.onChange=function(){f.setValue(1/s.get())};a.onChange=function(){d.setValue(1/a.get())};s.set(8);a.set(128)};Ops.Gl.ImageCompose.FXAA.prototype=new CABLES.Op;CABLES.OPS["3e679c17-f050-4bc8-bfe5-5b9190e7ce40"]={f:Ops.Gl.ImageCompose.FXAA,objName:"Ops.Gl.ImageCompose.FXAA"};Ops.Gl.ImageCompose.Blur=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={blur_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float dirX;\nUNI float dirY;\nUNI float amount;\n\n#ifdef HAS_MASK\n    UNI sampler2D imageMask;\n#endif\n\nfloat random(vec3 scale, float seed)\n{\n    return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);\n}\n\nvoid main()\n{\n    vec4 color = vec4(0.0);\n    float total = 0.0;\n\n    float am=amount;\n    #ifdef HAS_MASK\n        am=amount*texture(imageMask,texCoord).r;\n        if(am<=0.02)\n        {\n            outColor=texture(tex, texCoord);\n            return;\n        }\n    #endif\n\n    vec2 delta=vec2(dirX*am*0.01,dirY*am*0.01);\n\n\n    float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);\n\n    #ifdef MOBILE\n        offset = 0.1;\n    #endif\n\n    #if defined(FASTBLUR) && !defined(MOBILE)\n        const float range=5.0;\n    #else\n        const float range=20.0;\n    #endif\n\n    for (float t = -range; t <= range; t+=1.0)\n    {\n        float percent = (t + offset - 0.5) / range;\n        float weight = 1.0 - abs(percent);\n        vec4 smpl = texture(tex, texCoord + delta * percent);\n\n        smpl.rgb *= smpl.a;\n\n        color += smpl * weight;\n        total += weight;\n    }\n\n    outColor= color / total;\n\n    outColor.rgb /= outColor.a + 0.00001;\n\n\n\n}\n"};const i=e.inTrigger("render");const n=e.outTrigger("trigger");const r=e.inValueFloat("amount");const a=e.inSwitch("direction",["both","vertical","horizontal"],"both");const s=e.inValueBool("Fast",true);const o=e.patch.cgl;r.set(10);let l=new CGL.Shader(o,"blur");l.define("FASTBLUR");s.onChange=function(){if(s.get())l.define("FASTBLUR");else l.removeDefine("FASTBLUR")};l.setSource(l.getDefaultVertexShader(),t.blur_frag);let u=new CGL.Uniform(l,"t","tex",0);let h=new CGL.Uniform(l,"f","dirX",0);let p=new CGL.Uniform(l,"f","dirY",0);let c=new CGL.Uniform(l,"f","width",0);let m=new CGL.Uniform(l,"f","height",0);let f=new CGL.Uniform(l,"f","amount",r.get());r.onChange=function(){f.setValue(r.get())};let d=new CGL.Uniform(l,"t","imageMask",1);let g=false;function v(){if(o.currentTextureEffect.getCurrentSourceTexture().width==o.canvasWidth&&o.currentTextureEffect.getCurrentSourceTexture().height==o.canvasHeight){e.setUiError("warning","Full screen blurs are slow! Try reducing the resolution to 1/2 or a 1/4",0)}else{e.setUiError("warning",null)}}let y=0;a.onChange=function(){if(a.get()=="both")y=0;if(a.get()=="horizontal")y=1;if(a.get()=="vertical")y=2};let b=e.inTexture("mask");b.onChange=function(){if(b.get()&&b.get().tex)l.define("HAS_MASK");else l.removeDefine("HAS_MASK")};i.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;o.pushShader(l);c.setValue(o.currentTextureEffect.getCurrentSourceTexture().width);m.setValue(o.currentTextureEffect.getCurrentSourceTexture().height);v();if(y===0||y==2){o.currentTextureEffect.bind();o.setTexture(0,o.currentTextureEffect.getCurrentSourceTexture().tex);if(b.get()&&b.get().tex){o.setTexture(1,b.get().tex)}h.setValue(0);p.setValue(1);o.currentTextureEffect.finish()}if(y===0||y==1){o.currentTextureEffect.bind();o.setTexture(0,o.currentTextureEffect.getCurrentSourceTexture().tex);if(b.get()&&b.get().tex){o.setTexture(1,b.get().tex)}h.setValue(1);p.setValue(0);o.currentTextureEffect.finish()}o.popShader();n.trigger()}};Ops.Gl.ImageCompose.Blur.prototype=new CABLES.Op;CABLES.OPS["54f26f53-f637-44c1-9bfb-a2f2b722e998"]={f:Ops.Gl.ImageCompose.Blur,objName:"Ops.Gl.ImageCompose.Blur"};Ops.Gl.Meshes.Rectangle_v4=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const i=t.inTrigger("render"),n=t.inValueBool("Render Mesh",true),O=t.inValue("width",1),E=t.inValue("height",1),P=t.inSwitch("pivot x",["left","center","right"],"center"),M=t.inSwitch("pivot y",["top","center","bottom"],"center"),L=t.inSwitch("axis",["xy","xz"],"xy"),N=t.inBool("Flip TexCoord X",false),k=t.inBool("Flip TexCoord Y",true),w=t.inValueInt("num columns",1),R=t.inValueInt("num rows",1),r=t.outTrigger("trigger"),V=t.outObject("geometry",null,"geometry");V.ignoreValueSerialize=true;const D=new CGL.Geometry("rectangle");n.setUiAttribs({title:"Render"});i.setUiAttribs({title:"Trigger"});r.setUiAttribs({title:"Next"});t.setPortGroup("Pivot",[P,M,L]);t.setPortGroup("Size",[O,E]);t.setPortGroup("Structure",[w,R]);t.toWorkPortsNeedToBeLinked(i);t.toWorkShouldNotBeChild("Ops.Gl.TextureEffects.ImageCompose",CABLES.OP_PORT_TYPE_TRIGGER);const B=0;const j=1;let F=B;let U=null;let G=true;let z=true;const a=vec3.create();vec3.set(a,1,1,1);L.onChange=P.onChange=M.onChange=N.onChange=k.onChange=R.onChange=w.onChange=s;q();O.onChange=E.onChange=()=>{if(z)q();else G=true};function q(){if(F===B)vec3.set(a,O.get(),E.get(),1);if(F===j)vec3.set(a,O.get(),1,E.get())}V.onLinkChanged=()=>{z=!V.isLinked();q();G=true};function s(){G=true}i.onTriggered=()=>{if(G)o();const e=t.patch.cg;if(e&&U&&n.get()){if(z){e.pushModelMatrix();mat4.scale(e.mMatrix,e.mMatrix,a)}U.render(e.getShader());if(z)e.popModelMatrix()}r.trigger()};t.onDelete=()=>{if(U)U.dispose();s()};function o(){if(L.get()=="xy")F=B;if(L.get()=="xz")F=j;q();let i=O.get();let n=E.get();if(z)i=n=1;let r=0;let a=0;if(P.get()=="center")r=0;else if(P.get()=="right")r=-i/2;else if(P.get()=="left")r=+i/2;if(M.get()=="center")a=0;else if(M.get()=="top")a=-n/2;else if(M.get()=="bottom")a=+n/2;const s=Math.max(1,Math.round(R.get()));const o=Math.max(1,Math.round(w.get()));const l=i/o;const u=n/s;const h=[];const p=new Float32Array((o+1)*(s+1)*2);const c=new Float32Array((o+1)*(s+1)*3);const m=new Float32Array((o+1)*(s+1)*3);const f=new Float32Array((o+1)*(s+1)*3);const d=new Float32Array((o+1)*(s+1)*3);let g=0;let v=0;let y=0;let b=0;let x=0;for(let t=0;t<=s;t++){for(let e=0;e<=o;e++){c[v++]=e*l-i/2+r;if(F==j)c[v++]=0;c[v++]=t*u-n/2+a;if(F==B)c[v++]=0;p[g++]=e/o;p[g++]=t/s;if(F==B){m[y++]=0;m[y++]=0;m[y++]=1;f[b++]=1;f[b++]=0;f[b++]=0;d[x++]=0;d[x++]=1;d[x++]=0}else if(F==j){m[y++]=0;m[y++]=1;m[y++]=0;d[x++]=0;d[x++]=0;d[x++]=1}}}h.length=o*s*6;let A=0;for(let t=0;t<o;t++){for(let e=0;e<s;e++){const _=t+(o+1)*e;const S=_;const C=_+1;const T=_+o+1;const I=_+1+o+1;if(F==B){h[A++]=S;h[A++]=C;h[A++]=T;h[A++]=T;h[A++]=C;h[A++]=I}else if(F==j){h[A++]=S;h[A++]=T;h[A++]=C;h[A++]=C;h[A++]=T;h[A++]=I}}}if(k.get())for(let e=0;e<p.length;e+=2)p[e+1]=1-p[e+1];if(N.get())for(let e=0;e<p.length;e+=2)p[e]=1-p[e];D.clear();D.vertices=c;D.texCoords=p;D.verticesIndices=h;D.vertexNormals=m;D.tangents=f;D.biTangents=d;if(t.patch.cg)if(!U)U=t.patch.cg.createMesh(D,{opId:t.id});else U.setGeom(D);V.setRef(D);G=false}};Ops.Gl.Meshes.Rectangle_v4.prototype=new CABLES.Op;CABLES.OPS["cc8c3ede-7103-410b-849f-a645793cab39"]={f:Ops.Gl.Meshes.Rectangle_v4,objName:"Ops.Gl.Meshes.Rectangle_v4"};Ops.Anim.SineAnim=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTrigger("exe"),n=e.inSwitch("Mode",["Sine","Cosine"],"Sine"),r=e.inValueFloat("phase",0),a=e.inValueFloat("frequency",1),s=e.inValueFloat("amplitude",1),o=e.outTrigger("Trigger out"),l=e.outNumber("result");let u=0;const h=0;const p=1;e.toWorkPortsNeedToBeLinked(i);i.onTriggered=m;n.onChange=c;m();c();function c(){let e=n.get();if(e==="Sine")u=h;else if(e==="Cosine")u=p;m()}function m(){if(u==h)l.set(s.get()*Math.sin(e.patch.freeTimer.get()*a.get()+r.get()));else l.set(s.get()*Math.cos(e.patch.freeTimer.get()*a.get()+r.get()));o.trigger()}};Ops.Anim.SineAnim.prototype=new CABLES.Op;CABLES.OPS["736d3d0e-c920-449e-ade0-f5ca6018fb5c"]={f:Ops.Anim.SineAnim,objName:"Ops.Anim.SineAnim"};Ops.Gl.Texture_v2=function(){CABLES.Op.apply(this,arguments);const r=this;const e=r.attachments={};const a=r.inUrl("File",[".jpg",".png",".webp",".jpeg",".avif"]),t=r.inSwitch("Filter",["nearest","linear","mipmap"]),i=r.inValueSelect("Wrap",["repeat","mirrored repeat","clamp to edge"],"clamp to edge"),n=r.inSwitch("Anisotropic",["0","1","2","4","8","16"],"0"),s=r.inSwitch("Data Format",["R","RG","RGB","RGBA","SRGBA"],"RGBA"),o=r.inValueBool("Flip",false),l=r.inValueBool("Pre Multiplied Alpha",false),u=r.inValueBool("Active",true),h=r.inBool("Save Memory",true),p=r.outTexture("Texture"),c=r.inBool("Add Cachebuster",false),m=r.inTriggerButton("Reload"),f=r.outNumber("Width"),d=r.outNumber("Height"),g=r.outNumber("Aspect Ratio"),v=r.outBoolNum("Loaded",0),y=r.outBoolNum("Loading",0);const b=r.patch.cgl;r.toWorkPortsNeedToBeLinked(p);r.setPortGroup("Size",[f,d]);let x=null;let A=null;let _=null;let S=CGL.Texture.FILTER_MIPMAP;let C=CGL.Texture.WRAP_REPEAT;let T=0;let I=0;l.setUiAttribs({hidePort:true});l.onChange=a.onChange=s.onChange=c.onChange=o.onChange=E;n.onChange=t.onChange=L;i.onChange=N;t.set("mipmap");i.set("repeat");p.setRef(CGL.Texture.getEmptyTexture(b));m.onTriggered=E;u.onChange=function(){if(u.get()){if(x!=a.get()||!_)E();else p.setRef(_)}else{p.setRef(CGL.Texture.getEmptyTexture(b));f.set(CGL.Texture.getEmptyTexture(b).width);d.set(CGL.Texture.getEmptyTexture(b).height);if(_)_.delete();r.setUiAttrib({extendTitle:""});_=null}};const O=function(){const e=CGL.Texture.getTempTexture(b);p.setRef(e)};function E(e){clearTimeout(I);I=setTimeout(function(){M(e)},1)}function P(){if(s.get()=="R")return CGL.Texture.PFORMATSTR_R8UB;if(s.get()=="RG")return CGL.Texture.PFORMATSTR_RG8UB;if(s.get()=="RGB")return CGL.Texture.PFORMATSTR_RGB8UB;if(s.get()=="SRGBA")return CGL.Texture.PFORMATSTR_SRGBA8;return CGL.Texture.PFORMATSTR_RGBA8UB}function M(e){r.checkMainloopExists();if(!u.get())return;if(A)A=b.patch.loading.finished(A);A=b.patch.loading.start(r.objName,a.get(),r);let t=r.patch.getFilePath(String(a.get()));if(c.get()||e===true)t=CABLES.cacheBust(t);if(String(a.get()).indexOf("data:")==0)t=a.get();let i=false;x=a.get();if(a.get()&&a.get().length>1){v.set(false);y.set(true);const n=a.get();r.setUiAttrib({extendTitle:CABLES.basename(t)});if(i)r.refreshParams();b.patch.loading.addAssetLoadingTask(()=>{r.setUiError("urlerror",null);CGL.Texture.load(b,t,function(e,t){b.checkFrameStarted("texture inittexture");if(a.get()!=n){A=b.patch.loading.finished(A);return}if(_)_.delete();if(e){const i=CGL.Texture.getErrorTexture(b);p.setRef(i);r.setUiError("urlerror",'could not load texture: "'+a.get()+'"',2);A=b.patch.loading.finished(A);return}f.set(t.width);d.set(t.height);g.set(t.width/t.height);_=t;p.setRef(_);y.set(false);v.set(true);if(h.get())_.image=null;if(A){A=b.patch.loading.finished(A)}r.checkMainloopExists()},{anisotropic:T,wrap:C,flip:o.get(),unpackAlpha:l.get(),pixelFormat:P(),filter:S});r.checkMainloopExists()})}else{O();A=b.patch.loading.finished(A)}}function L(){if(t.get()=="nearest")S=CGL.Texture.FILTER_NEAREST;else if(t.get()=="linear")S=CGL.Texture.FILTER_LINEAR;else if(t.get()=="mipmap")S=CGL.Texture.FILTER_MIPMAP;else if(t.get()=="Anisotropic")S=CGL.Texture.FILTER_ANISOTROPIC;n.setUiAttribs({greyout:S!=CGL.Texture.FILTER_MIPMAP});T=parseFloat(n.get());E()}function N(){if(i.get()=="repeat")C=CGL.Texture.WRAP_REPEAT;if(i.get()=="mirrored repeat")C=CGL.Texture.WRAP_MIRRORED_REPEAT;if(i.get()=="clamp to edge")C=CGL.Texture.WRAP_CLAMP_TO_EDGE;E()}r.onFileChanged=function(e){if(a.get()&&a.get().indexOf(e)>-1){p.setRef(CGL.Texture.getEmptyTexture(r.patch.cgl));p.setRef(CGL.Texture.getTempTexture(b));M(true)}}};Ops.Gl.Texture_v2.prototype=new CABLES.Op;CABLES.OPS["790f3702-9833-464e-8e37-6f0f813f7e16"]={f:Ops.Gl.Texture_v2,objName:"Ops.Gl.Texture_v2"};Ops.Gl.ClearColor=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTrigger("render"),n=e.outTrigger("trigger"),r=e.inFloatSlider("r",.1),a=e.inFloatSlider("g",.1),s=e.inFloatSlider("b",.1),o=e.inFloatSlider("a",1);r.setUiAttribs({colorPick:true});const l=e.patch.cgl;i.onTriggered=function(){l.gl.clearColor(r.get(),a.get(),s.get(),o.get());l.gl.clear(l.gl.COLOR_BUFFER_BIT|l.gl.DEPTH_BUFFER_BIT);n.trigger()}};Ops.Gl.ClearColor.prototype=new CABLES.Op;CABLES.OPS["19b441eb-9f63-4f35-ba08-b87841517c4d"]={f:Ops.Gl.ClearColor,objName:"Ops.Gl.ClearColor"};Ops.Gl.ImageCompose.Kaleidoscope_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={kaleidoscope_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\n\nUNI float sides;\nUNI float angle;\nUNI float amount;\n\nUNI float slidex;\nUNI float slidey;\nUNI float centerX;\nUNI float centerY;\nUNI float aspect;\n\nconst float tau = 6.28318530718;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n    vec2 center=vec2(centerX,centerY/aspect);\n\n\tvec2 loc = texCoord;\n\tloc.y/=aspect;\n\n\tfloat r = distance(center, loc);\n\tfloat a = atan ((loc.y-center.y),(loc.x-center.x));\n\n\t// kaleidoscope\n\ta = mod(a, tau/sides);\n\ta = abs(a - tau/sides/2.);\n\n\tloc.x = r * cos(a + tau * angle);\n\tloc.y = r * sin(a + tau * angle);\n\n\tloc = (center + loc) *2.1;\n\n\tloc.x = mod(loc.x + slidex, 1.0);\n\tloc.y = mod(loc.y + slidey, 1.0);\n\n\tif(loc.x < 0.0)loc.x = mod(abs(loc.x),1.0);\n\tif(loc.y < 0.0)loc.y = mod(abs(loc.y),1.0);\n\n\tif(loc.x > 1.0) loc.x = mod(abs(1.0-loc.x),1.0);\n\tif(loc.y > 1.0) loc.y = mod(abs(1.0-loc.y),1.0);\n\n\tvec4 col=texture(tex,loc);\n\tvec4 base=texture(tex,texCoord);\n\tbase.a=0.0;\n    outColor= cgl_blendPixel(base,col,amount);\n\n}\n"};const i=e.inTrigger("Render"),n=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),r=e.inValueSlider("Amount",1),a=e.inValue("Sides",10),s=e.inValueSlider("Angle",0),o=e.inValueSlider("Slide X",0),l=e.inValueSlider("Slide Y",0),u=e.inValueSlider("Center X",.5),h=e.inValueSlider("Center Y",.5),p=e.inBool("Aspect Ratio",true),c=e.outTrigger("Next");let m=e.patch.cgl;let f=new CGL.Shader(m,e.name,e);const d=new CGL.Uniform(f,"f","sides",a),g=new CGL.Uniform(f,"f","angle",s),v=new CGL.Uniform(f,"f","slidex",o),y=new CGL.Uniform(f,"f","slidey",l),b=new CGL.Uniform(f,"f","centerX",u),x=new CGL.Uniform(f,"f","centerY",h),A=new CGL.Uniform(f,"f","amount",r),_=new CGL.Uniform(f,"f","aspect",1);CGL.TextureEffect.setupBlending(e,f,n,r);f.setSource(f.getDefaultVertexShader(),t.kaleidoscope_frag);let S=new CGL.Uniform(f,"t","tex",0);i.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;m.pushShader(f);m.currentTextureEffect.bind();m.setTexture(0,m.currentTextureEffect.getCurrentSourceTexture().tex);if(p.get())_.setValue(m.currentTextureEffect.aspectRatio);else _.setValue(1);m.currentTextureEffect.finish();m.popShader();c.trigger()}};Ops.Gl.ImageCompose.Kaleidoscope_v2.prototype=new CABLES.Op;CABLES.OPS["3c900fc2-8508-4531-a365-43224f7751c8"]={f:Ops.Gl.ImageCompose.Kaleidoscope_v2,objName:"Ops.Gl.ImageCompose.Kaleidoscope_v2"};Ops.Gl.ImageCompose.Vignette_v3=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={vignette_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float lensRadius1;\nUNI float aspect;\nUNI float amount;\nUNI float strength;\nUNI float sharp;\n\nUNI vec3 vcol;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n    vec4 base=texture(tex,texCoord);\n    vec4 vvcol=vec4(vcol,1.0);\n    vec4 col=texture(tex,texCoord);\n    vec2 tcPos=vec2(texCoord.x,(texCoord.y-0.5)*aspect+0.5);\n    float dist = distance(tcPos, vec2(0.5,0.5));\n    float am = (1.0-smoothstep( (lensRadius1+0.5), (lensRadius1*0.99+0.5)*sharp, dist));\n\n    col=mix(col,vvcol,am*strength);\n\n    #ifndef ALPHA\n        outColor=cgl_blendPixel(base,col,amount);\n    #endif\n\n    #ifdef ALPHA\n        outColor=vec4(base.rgb,base.a*(1.0-am*strength));\n    #endif\n}\n"};const i=e.inTrigger("Render"),n=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),r=CGL.TextureEffect.AddBlendAlphaMask(e),a=e.inValueSlider("Amount",1),s=e.outTrigger("Trigger"),o=e.inValueSlider("Strength",1),l=e.inValueSlider("Radius",.3),u=e.inValueSlider("Sharp",.25),h=e.inValue("Aspect",1),p=e.inValueSlider("r",0),c=e.inValueSlider("g",0),m=e.inValueSlider("b",0),f=e.inBool("Alpha",false);p.setUiAttribs({colorPick:true});const d=e.patch.cgl;const g=new CGL.Shader(d,"vignette");g.setSource(g.getDefaultVertexShader(),t.vignette_frag);const v=new CGL.Uniform(g,"t","tex",0),y=new CGL.Uniform(g,"f","amount",a),b=new CGL.Uniform(g,"f","lensRadius1",l),x=new CGL.Uniform(g,"f","aspect",h),A=new CGL.Uniform(g,"f","strength",o),_=new CGL.Uniform(g,"f","sharp",u),S=new CGL.Uniform(g,"3f","vcol",p,c,m);CGL.TextureEffect.setupBlending(e,g,n,a,r);f.onChange=C;C();function C(){g.toggleDefine("ALPHA",f.get());p.setUiAttribs({greyout:f.get()});c.setUiAttribs({greyout:f.get()});m.setUiAttribs({greyout:f.get()})}i.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;d.pushShader(g);d.currentTextureEffect.bind();d.setTexture(0,d.currentTextureEffect.getCurrentSourceTexture().tex);d.currentTextureEffect.finish();d.popShader();s.trigger()}};Ops.Gl.ImageCompose.Vignette_v3.prototype=new CABLES.Op;CABLES.OPS["588302cb-f5a7-4129-90d2-ba66212d69e5"]={f:Ops.Gl.ImageCompose.Vignette_v3,objName:"Ops.Gl.ImageCompose.Vignette_v3"};Ops.Gl.ImageCompose.LensDirt_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={lensDirt_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float uOffsetX;\nUNI float uOffsetY;\nUNI float uZoom;\n// UNI int uIterations;\nUNI int uRandomSeed;\nUNI float uSpotEdge;\nUNI float uGamma;\nUNI float uAspect;\nUNI float amount;\n\n{{CGL.BLENDMODES3}}\n\n// https://www.shadertoy.com/view/MdfBRX\nfloat Bokeh(vec2 p, vec2 sp, float size, float mi, float blur)\n{\n    float d = length(p - sp);\n    float c = smoothstep(size, size*(1.-blur), d);\n    c *= mix(mi, 1., smoothstep(size*.8, size, d));\n    return c;\n}\n///  2 out, 2 in... from https://www.shadertoy.com/view/4djSRW\n//stable\nvec2 hash22(vec2 p)\n{\n\tvec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));\n    p3 += dot(p3, p3.yzx+33.33);\n    return fract((p3.xx+p3.yz)*p3.zy)*2.0-1.0;\n\n}\nvec3 dirt(vec2 uv, float n,float density,float hardness)\n{\n    n *= density;\n    vec2 p = fract(uv * n);\n    vec2 st = (floor(uv * n) + 0.5) / n;\n    vec2 rnd = hash22(st);\n    float c = Bokeh(p, vec2(0.5, 0.5) + vec2(0.3) * rnd, 0.2,\n                    abs(rnd.y * 0.35) + 0.3, 0.25 + rnd.x * rnd.y * hardness);\n\n    return vec3(c) * exp(rnd.x * 4.0);\n}\n\nvoid main()\n{\n\tvec3 di = vec3(1.0);\n    float edgeHardness = 0.1;\n    edgeHardness = clamp(uSpotEdge*0.25,0.0,0.2);\n\n    vec2 uv = (texCoord-0.5);\n\n    uv.y/=uAspect;\n    uv *= uZoom;\n    uv -= vec2(uOffsetX,uOffsetY);\n\n    float q = 0.0;\n    for (int i = 1; i < ITERATIONS ; i++)\n    {\n        q = float(i);\n        vec2 h=hash22(vec2(q)+vec2(uRandomSeed));\n        di += dirt(uv-h, h.x, 1.0, edgeHardness);\n    }\n\n    di = pow(di* 0.01,vec3(uGamma));\n    vec4 col = vec4(di,1.0);\n    vec4 base = texture(tex,texCoord);\n\n    outColor = cgl_blendPixel(base,col,amount);\n}"};const i=e.inTrigger("render"),n=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),r=e.inValueSlider("Amount",1),a=CGL.TextureEffect.AddBlendAlphaMask(e),s=e.inFloat("Offset X",0),o=e.inFloat("Offset Y",0),l=e.inFloat("Zoom",5),u=e.inInt("Iterations",50),h=e.inInt("Seed",1),p=e.inFloatSlider("Spot edge",.5),c=e.inFloat("Gamma",.75),m=e.outTrigger("trigger");const f=e.patch.cgl;const d=new CGL.Shader(f,e.name,e);d.setSource(d.getDefaultVertexShader(),t.lensDirt_frag);const g=new CGL.Uniform(d,"t","tex",0),v=new CGL.Uniform(d,"f","uOffsetX",s),y=new CGL.Uniform(d,"f","uOffsetY",o),b=new CGL.Uniform(d,"f","uZoom",l),x=new CGL.Uniform(d,"i","uRandomSeed",h),A=new CGL.Uniform(d,"f","uSpotEdge",p),_=new CGL.Uniform(d,"f","uGamma",c),S=new CGL.Uniform(d,"f","uAspect",1),C=new CGL.Uniform(d,"f","amount",r);CGL.TextureEffect.setupBlending(e,d,n,r,a);u.onChange=T;T();function T(){let e=u.get();e=Math.min(300,Math.max(1,e));d.define("ITERATIONS",e)}i.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;f.pushShader(d);f.currentTextureEffect.bind();S.setValue(f.currentTextureEffect.getCurrentSourceTexture().width/f.currentTextureEffect.getCurrentSourceTexture().height);f.setTexture(0,f.currentTextureEffect.getCurrentSourceTexture().tex);f.currentTextureEffect.finish();f.popShader();m.trigger()}};Ops.Gl.ImageCompose.LensDirt_v2.prototype=new CABLES.Op;CABLES.OPS["a04156f6-f636-430f-810e-9cb27199ceeb"]={f:Ops.Gl.ImageCompose.LensDirt_v2,objName:"Ops.Gl.ImageCompose.LensDirt_v2"};Ops.Gl.ImageCompose.BulgePinch=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={bulgepinch_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\n\nUNI float radius;\nUNI float strength;\nUNI float centerX;\nUNI float centerY;\n\nvoid main()\n{\n   vec2 center=vec2(centerX,centerY);\n   vec2 coord=texCoord;\n   coord -= center;\n   float distance = length(coord);\n   float percent = distance / radius;\n   if (strength > 0.0) coord *= mix(1.0, smoothstep(0.0, radius / distance, percent), strength * 0.75);\n   else coord *= mix(1.0, pow(percent, 1.0 + strength * 0.75) * radius / distance, 1.0 - percent);\n   coord += center;\n   vec4 col=texture(tex,coord);\n   outColor= col;\n}"};const i=e.inTrigger("render"),n=e.inValueFloat("Radius",.5),r=e.inValueFloat("Strength",1),a=e.inValueFloat("Center X",.5),s=e.inValueFloat("Center Y",.5),o=e.outTrigger("trigger");const l=e.patch.cgl;const u=new CGL.Shader(l,"bulgepinch");u.setSource(u.getDefaultVertexShader(),t.bulgepinch_frag);const h=new CGL.Uniform(u,"f","radius",n),p=new CGL.Uniform(u,"f","strength",r),c=new CGL.Uniform(u,"f","centerX",a),m=new CGL.Uniform(u,"f","centerY",s),f=new CGL.Uniform(u,"t","tex",0);i.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;l.pushShader(u);l.currentTextureEffect.bind();l.setTexture(0,l.currentTextureEffect.getCurrentSourceTexture().tex);l.currentTextureEffect.finish();l.popShader();o.trigger()}};Ops.Gl.ImageCompose.BulgePinch.prototype=new CABLES.Op;CABLES.OPS["25696840-bd64-463e-9301-964a81385bfb"]={f:Ops.Gl.ImageCompose.BulgePinch,objName:"Ops.Gl.ImageCompose.BulgePinch"};Ops.Anim.RandomAnim_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTrigger("exe"),n=e.inValue("min",0),r=e.inValue("max",1),a=e.inValue("duration",.5),s=e.inValue("pause between",0),o=e.outTrigger("Next"),l=e.outNumber("result"),u=e.outTrigger("Looped");const h=new CABLES.Anim;h.createPort(e,"easing",f);e.setPortGroup("Timing",[a,s]);e.setPortGroup("Value",[n,r]);e.toWorkPortsNeedToBeLinked(i);n.onChange=r.onChange=s.onChange=a.onChange=c;let p=true;function c(){p=true}function m(){const e=n.get();return Math.random()*(r.get()-e)+e}function f(){d(m());p=false}function d(e){h.clear();h.setValue(CABLES.now()/1e3,e);h.setValue(CABLES.now()/1e3+s.get(),e);h.setValue(a.get()+CABLES.now()/1e3+s.get(),m())}i.onTriggered=g;function g(){if(p)f();const e=CABLES.now()/1e3;const t=h.getValue(e);if(h.hasEnded(e)){h.clear();d(t);u.trigger()}l.set(t);o.trigger()}};Ops.Anim.RandomAnim_v2.prototype=new CABLES.Op;CABLES.OPS["05581579-1cdc-4eaf-8557-9726c6f9a843"]={f:Ops.Anim.RandomAnim_v2,objName:"Ops.Anim.RandomAnim_v2"};Ops.Gl.Textures.TextTexture_v6=function(){CABLES.Op.apply(this,arguments);const g=this;const a=g.attachments={text_frag:"{{MODULES_HEAD}}\n\nUNI sampler2D tex;\nUNI float a;\nUNI vec4 color;\nIN vec2 texCoord;\n\nvoid main()\n{\n\n    vec4 col=texture(tex,vec2(texCoord.x,(1.0-texCoord.y)));\n\n    {{MODULE_COLOR}}\n\n    outColor=col;\n}\n",text_vert:"{{MODULES_HEAD}}\n\nIN vec3 vPosition;\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\nUNI float aspect;\nOUT vec2 texCoord;\nIN vec2 attrTexCoord;\n\nvoid main()\n{\n    vec4 pos=vec4(vPosition,  1.0);\n\n    pos.x*=aspect;\n\n    texCoord=vec2(attrTexCoord.x,1.0-attrTexCoord.y);;\n\n    mat4 mMatrix=modelMatrix;\n\n    {{MODULE_VERTEX_POSITION}}\n    mat4 modelViewMatrix=viewMatrix*mMatrix;\n\n    gl_Position = projMatrix * modelViewMatrix * pos;\n}\n"};const e=g.inTriggerButton("Render"),Y=g.inString("text","cables"),t=g.inValueBool("Draw Mesh",true),i=g.inValueFloat("Scale Mesh",.5),v=g.inSwitch("Size",["Auto","Manual"],"Auto"),y=g.inInt("Width",512),b=g.inInt("Height",512),x=g.inBool("Auto Height",true),A=g.inBool("Auto Line Breaks",true),_=g.inString("font","Arial"),S=g.inString("weight","normal"),C=g.inValueFloat("fontSize",300),T=g.inSwitch("align",["left","center","right"],"center"),I=g.inSwitch("Vertical align",["Top","Middle","Bottom"],"Top"),O=g.inFloat("Letter Spacing",0),E=g.inFloat("Line Height Add",0),W=g.inInt("Padding Y Top",3),K=g.inInt("Padding Y Bottom",3),Z=g.inInt("Padding X",0),P=g.inSwitch("filter",["nearest","linear","mipmap"],"linear"),M=g.inValueSelect("Wrap",["repeat","mirrored repeat","clamp to edge"],"clamp to edge"),L=g.inSwitch("Anisotropic",[0,1,2,4,8,16],0),N=g.inValueBool("Reuse Texture",true),Q=g.inBool("Show Debug",false),s=g.inBool("Redraw On Font Load",true),k=g.inValueSlider("r",1),w=g.inValueSlider("g",1),R=g.inValueSlider("b",1),V=g.inFloatSlider("Opacity",1),D=g.inValueSlider("background R",0),J=g.inValueSlider("background G",0),$=g.inValueSlider("background B",0),ee=g.inValueSlider("background A",1),o=g.inTriggerButton("Force Redraw"),l=g.outTrigger("Next"),te=g.outNumber("Ratio"),B=g.outTexture("texture"),u=g.outObject("Canvas",null,"element"),h=g.outNumber("Aspect",1),ie=g.outNumber("Num Lines");const j=" ";k.setUiAttribs({colorPick:true});D.setUiAttribs({colorPick:true});g.toWorkPortsNeedToBeLinked(e);g.setPortGroup("Text Color",[k,w,R,V]);g.setPortGroup("Background",[D,J,$,ee]);g.setPortGroup("Font",[_,S,C,T,I,O,E]);g.setPortGroup("Texture",[M,P,L,N,Q]);g.setPortGroup("Rendering",[t,i]);e.onLinkChanged=()=>{if(!e.isLinked())B.setRef(CGL.Texture.getEmptyTexture(F));else B.setRef(U)};o.onTriggered=k.onChange=w.onChange=R.onChange=V.onChange=I.onChange=A.onChange=x.onChange=E.onChange=v.onChange=y.onChange=b.onChange=T.onChange=O.onChange=W.onChange=K.onChange=Z.onChange=Y.onChange=C.onChange=S.onChange=L.onChange=_.onChange=Q.onChange=N.onChange=function(){H=true;ue()};B.ignoreValueSerialize=true;const F=g.patch.cgl;let U=new CGL.Texture(F);let G=2;let z=2;const q=document.createElement("canvas");q.id="texturetext_"+CABLES.generateUUID();q.style.display="none";document.body.appendChild(q);q.style.letterSpacing="0px";u.setRef(q);let X=q.getContext("2d");let H=true;const p=CGL.MESHES.getSimpleRect(F,"texttexture rect");const n=vec3.create();const r=new CGL.Shader(F,"texttexture");r.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"]);r.setSource(a.text_vert,a.text_frag);const c=new CGL.Uniform(r,"t","tex");const m=new CGL.Uniform(r,"f","aspect",0);const f=new CGL.Uniform(r,"f","a",V);const d=new CGL.Uniform(r,"4f","color",k,w,R,V);if(g.patch.isEditorMode())CABLES.UI.SIMPLEWIREFRAMERECT=CABLES.UI.SIMPLEWIREFRAMERECT||new CGL.WireframeRect(F);e.onTriggered=ae;t.onChange=ue;ue();g.on("delete",()=>{X=null;q.remove()});L.onChange=P.onChange=M.onChange=()=>{if(U)U.delete();U=null;H=true};D.onChange=J.onChange=$.onChange=ee.onChange=k.onChange=w.onChange=R.onChange=V.onChange=()=>{if(!t.get()||B.isLinked())H=true};B.onLinkChanged=()=>{if(B.isLinked())H=true};g.patch.on("fontLoaded",e=>{if(e==_.get())H=true});document.fonts.ready.then(()=>{if(s.get())H=true});document.fonts.onloadingdone=function(e){if(s.get())H=true};function ne(){return z}function re(){return G}function ae(){let e=0;while(H&&e<10){se();le();e++}if(t.get()){n[0]=n[1]=n[2]=i.get();F.pushBlendMode(CGL.BLEND_NORMAL,false);F.pushModelMatrix();mat4.scale(F.mMatrix,F.mMatrix,n);r.popTextures();r.pushTexture(c,U.tex);m.set(h.get());if(F.shouldDrawHelpers(g))CABLES.UI.SIMPLEWIREFRAMERECT.render(h.get(),1,1);F.pushShader(r);p.render(g.patch.cg.getShader());F.popShader();F.popBlendMode();F.popModelMatrix()}l.trigger()}function se(){if(U)U.setSize(ne(),re());X.canvas.width=q.width=ne();X.canvas.height=q.height=re();h.set(q.width/q.height);H=true}function oe(i){let n="";for(let e=0;e<i.length;e++){if(!i[e]){n+="\n";continue}let t=0;const r=i[e].split(j);for(let e=0;e<r.length;e++){if(!r[e])continue;t+=X.measureText(r[e]+j).width;if(t>y.get()){n+="\n"+r[e]+j;t=X.measureText(r[e]+j).width}else{n+=r[e]+j}}n+="\n"}let e=n;i=e.split("\n");if(i[i.length-1]=="")i.pop();return i}function le(){F.checkFrameStarted("texttrexture refresh");const e="rgba("+Math.floor(D.get()*255)+","+Math.floor(J.get()*255)+","+Math.floor($.get()*255)+","+ee.get()+")";X.fillStyle=e;X.fillRect(0,0,X.canvas.width,X.canvas.height);const t="rgba("+Math.floor(k.get()*255)+","+Math.floor(w.get()*255)+","+Math.floor(R.get()*255)+","+V.get()+")";X.fillStyle=t;let i=parseFloat(C.get());let n=_.get();if(n.indexOf(j)>-1)n='"'+n+'"';X.font=S.get()+j+i+"px "+n+"";X.textBaseline="top";X.textAlign=T.get();X.letterSpacing=O.get()+"px";let r=(Y.get()+"").replace(/<br\/>/g,"\n");r=r.trim();let a=r.split("\n");H=false;let s=Math.max(0,W.get());let o=Math.max(0,K.get());let l=Math.max(0,Z.get());z=0;G=0;if(A.get()&&v.get()=="Manual"){if(y.get()>128){a=oe(a)}}const u=[];for(let e=0;e<a.length;e++){const d=X.measureText(a[e]);u[e]=Math.ceil(d.fontBoundingBoxAscent)+Math.ceil(d.fontBoundingBoxDescent)+E.get()}for(let e=0;e<a.length;e++){const d=X.measureText(a[e]);z=Math.max(z,Math.ceil(d.width));G+=u[e]}z+=l*2;if(E.get()<0)G+=E.get()/2*-1;let h=G;if(v.get()=="Manual"){z=y.get()+l*2;if(!x.get()){G=b.get()}}G=Math.ceil(G);z=Math.ceil(z);if(z>F.maxTexSize||G>F.maxTexSize)g.setUiError("textoobig","Texture too big!");else g.setUiError("textoobig",null);G=Math.min(F.maxTexSize,G);z=Math.min(F.maxTexSize,z);let p=0;if(I.get()=="Middle")p=(G-h)/2;else if(I.get()=="Bottom")p=G-h;p+=s;G+=s+o;if(X.canvas.width!=z||X.canvas.height!=G)se();const c=Q.get();for(let t=0;t<a.length;t++){let e=0+l;if(T.get()=="center")e=X.canvas.width/2;if(T.get()=="right")e=X.canvas.width-l;if(v.get()=="Manual")e+=O.get();X.fillText(a[t],e,p);if(c){X.lineWidth=3;X.strokeStyle="#FF0000";X.beginPath();X.moveTo(0,p);X.lineTo(X.canvas.width,p);X.stroke()}p+=u[t]}let m=CGL.Texture.WRAP_REPEAT;if(M.get()=="mirrored repeat")m=CGL.Texture.WRAP_MIRRORED_REPEAT;else if(M.get()=="clamp to edge")m=CGL.Texture.WRAP_CLAMP_TO_EDGE;let f=CGL.Texture.FILTER_LINEAR;if(P.get()=="nearest")f=CGL.Texture.FILTER_NEAREST;else if(P.get()=="mipmap")f=CGL.Texture.FILTER_MIPMAP;if(!N.get()||!U||!B.get()||U.width!=q.width||U.height!=q.height||U.anisotropic!=parseFloat(L.get())){if(U)U.delete();U=new CGL.Texture.createFromImage(F,q,{filter:f,anisotropic:parseFloat(L.get()),wrap:m})}U.unpackAlpha=false;U.flip=false;U.initTexture(q,f);te.set(X.canvas.height/X.canvas.width);ie.set(a.length);B.setRef(U)}function ue(){y.setUiAttribs({greyout:v.get()!="Manual"});b.setUiAttribs({greyout:v.get()!="Manual"||x.get()});A.setUiAttribs({greyout:v.get()!="Manual"});I.setUiAttribs({greyout:v.get()!="Manual"});x.setUiAttribs({greyout:v.get()!="Manual"});i.setUiAttribs({greyout:!t.get()})}};Ops.Gl.Textures.TextTexture_v6.prototype=new CABLES.Op;CABLES.OPS["2c042efa-3604-4717-b8f4-5ad08d6740e5"]={f:Ops.Gl.Textures.TextTexture_v6,objName:"Ops.Gl.Textures.TextTexture_v6"};Ops.String.SwitchStringMultiPort=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inInt("Index",0),n=e.inMultiPort("Strings",CABLES.OP_PORT_TYPE_STRING),r=e.outString("String"),a=e.outNumber("Num Values");i.onChange=n.onChange=()=>{const e=n.get();const t=Math.ceil(Math.min(e.length-1,Math.max(0,i.get())));r.set(e[t].get());a.set(e.length)}};Ops.String.SwitchStringMultiPort.prototype=new CABLES.Op;CABLES.OPS["cf8a883f-cf09-44a6-ba1c-7f9c1220b618"]={f:Ops.String.SwitchStringMultiPort,objName:"Ops.String.SwitchStringMultiPort"};Ops.Ui.VizString=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inStringEditor("String"),r=e.inBool("ZoomText",false),a=e.inBool("Line Numbers",true),s=e.inBool("Whitespace",false),o=e.inBool("Wrap lines",false),l=e.inValueSelect("Syntax",["text","glsl","css","html","xml","json","javascript","inline-css","sql"],"text"),u=e.inFloat("Font Size",10),h=e.inFloatSlider("Scroll",0);e.setUiAttrib({height:200,width:400,resizable:true,vizLayerMaxZoom:2500});n.ignoreValueSerialize=true;let p=[];n.onLinkChanged=()=>{if(!n.isLinked()){p=[];n.set(null)}};n.onChange=()=>{if(n.get())p=n.get().split("\n");else p=[]};e.renderVizLayer=(e,t,i)=>{i.clear(e,t);if(!n.get())return;e.save();e.scale(t.scale,t.scale);i.renderText(e,t,p,{zoomText:r.get(),showLineNum:a.get(),fontSize:u.get(),scroll:h.get(),syntax:l.get(),showWhitespace:s.get(),wrap:o.get()});e.restore()}};Ops.Ui.VizString.prototype=new CABLES.Op;CABLES.OPS["b4c93fde-85c6-4c7e-9962-a6463a84838b"]={f:Ops.Ui.VizString,objName:"Ops.Ui.VizString"};Ops.Math.Incrementor=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTriggerButton("Increment"),n=e.inTriggerButton("Decrement"),r=e.inBool("Limit",false),a=e.inValueInt("Length"),s=e.inSwitch("Mode",["Rewind","Stop at Max"],"Rewind"),o=e.inValueInt("Default",0),l=e.inTriggerButton("Reset"),u=e.outTrigger("Changed"),h=e.outNumber("Value"),p=e.outTrigger("Restarted");const c=0;const m=1;h.ignoreValueSerialize=true;a.set(10);let f=0;let d=c;h.set(0);a.onTriggered=l;o.onChange=v;l.onTriggered=v;r.onChange=g;g();s.onChange=()=>{if(s.get()=="Rewind"){d=c}if(s.get()=="Stop at Max"){d=m}};function g(){a.setUiAttribs({greyout:!r.get()});s.setUiAttribs({greyout:!r.get()})}function v(){h.set(null);f=o.get();h.set(f);p.trigger()}n.onTriggered=function(){f--;if(r.get()){if(d==c&&f<0)f=a.get()-1;if(d==m&&f<0)f=0}h.set(f);u.trigger()};i.onTriggered=function(){f++;if(r.get()){if(d==c&&f>=a.get()){f=0;p.trigger()}if(d==m&&f>=a.get())f=a.get()-1}h.set(f);u.trigger()}};Ops.Math.Incrementor.prototype=new CABLES.Op;CABLES.OPS["45cc0011-ada8-4423-8f5b-39a3810b8389"]={f:Ops.Math.Incrementor,objName:"Ops.Math.Incrementor"};Ops.Ui.VizNumber=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={};const n=i.inFloat("Number",0);const r=i.outNumber("Result");i.setUiAttrib({widthOnlyGrow:true});n.onChange=t;t();function t(){let t=n.get();if(i.patch.isEditorMode()){let e="";if(t===null)e="null";else if(t===undefined)e="undefined";else{e=""+Math.round(t*1e4)/1e4;if(e[0]!="-")e=" "+e}i.setUiAttribs({extendTitle:e})}r.set(t)}};Ops.Ui.VizNumber.prototype=new CABLES.Op;CABLES.OPS["2b60d12d-2884-4ad0-bda4-0caeb6882f5c"]={f:Ops.Ui.VizNumber,objName:"Ops.Ui.VizNumber"};Ops.Math.Multiply=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inValueFloat("number1",1),n=e.inValueFloat("number2",1),r=e.outNumber("result");e.setUiAttribs({mathTitle:true});i.onChange=n.onChange=a;a();function a(){const e=i.get();const t=n.get();r.set(e*t)}};Ops.Math.Multiply.prototype=new CABLES.Op;CABLES.OPS["1bbdae06-fbb2-489b-9bcc-36c9d65bd441"]={f:Ops.Math.Multiply,objName:"Ops.Math.Multiply"};Ops.Gl.TextMeshMSDF_v2=function(){CABLES.Op.apply(this,arguments);const r=this;const b=r.attachments={textmeshsdf_frag:"\nUNI sampler2D tex0;\nUNI sampler2D tex1;\nUNI sampler2D tex2;\nUNI sampler2D tex3;\n\nIN vec2 texCoord;\nIN vec4 fragAttrColors;\n\nUNI vec4 color;\nUNI vec2 texSize;\n\n#ifdef BORDER\n    UNI float borderWidth;\n    UNI float borderSmooth;\n    UNI vec3 colorBorder;\n#endif\n\n#ifdef TEXTURE_COLOR\nUNI sampler2D texMulColor;\n#endif\n#ifdef TEXTURE_MASK\nUNI sampler2D texMulMask;\n#endif\n\nUNI float smoothing;\nIN float texIndex;\n\n#ifdef SHADOW\n    UNI float shadowWidth;\n#endif\n\n\nfloat median(float r, float g, float b)\n{\n    return max(min(r, g), min(max(r, g), b));\n}\n\nvoid main()\n{\n    vec4 bgColor=vec4(0.0,0.0,0.0,0.0);\n    vec4 fgColor=color;\n    float opacity=1.0;\n\n    #ifndef SDF\n        if(int(texIndex)==0) outColor = texture(tex0, texCoord);\n        if(int(texIndex)==1) outColor = texture(tex1, texCoord);\n        if(int(texIndex)==2) outColor = texture(tex2, texCoord);\n        if(int(texIndex)==3) outColor = texture(tex3, texCoord);\n\n        return;\n    #endif\n\n\n    #ifdef TEXTURE_COLOR\n        fgColor.rgb *= texture(texMulColor, vec2(0.0,0.0)).rgb; //todo texcoords from char positioning\n    #endif\n    #ifdef TEXTURE_MASK\n        opacity *= texture(texMulMask, vec2(0.0,0.0)).r; //todo texcoords from char positioning\n    #endif\n\n\n    #ifdef SHADOW\n        vec2 msdfUnit1 = texSize;\n        vec2 tcv=vec2(texCoord.x-0.002,texCoord.y-0.002);\n        vec3 smpl1;\n        if(int(texIndex)==0) smpl1 = texture(tex0, tcv).rgb;\n        if(int(texIndex)==1) smpl1 = texture(tex1, tcv).rgb;\n        if(int(texIndex)==2) smpl1 = texture(tex2, tcv).rgb;\n        if(int(texIndex)==3) smpl1 = texture(tex3, tcv).rgb;\n\n        float sigDist1 = median(smpl1.r, smpl1.g, smpl1.b) - 0.001;\n        float opacity1 = smoothstep(0.0,0.9,sigDist1*sigDist1);\n        outColor = mix(bgColor, vec4(0.0,0.0,0.0,1.0), opacity1);\n    #endif\n\n    vec2 msdfUnit = 8.0/texSize;\n    vec3 smpl;\n\n    if(int(texIndex)==0) smpl = texture(tex0, texCoord).rgb;\n    if(int(texIndex)==1) smpl = texture(tex1, texCoord).rgb;\n    if(int(texIndex)==2) smpl = texture(tex2, texCoord).rgb;\n    if(int(texIndex)==3) smpl = texture(tex3, texCoord).rgb;\n\n\n    float sigDist = median(smpl.r, smpl.g, smpl.b) - 0.5;\n    sigDist *= dot(msdfUnit, (0.5+(smoothing-0.5))/fwidth(texCoord));\n    opacity *= clamp(sigDist + 0.5, 0.0, 1.0);\n\n    #ifdef BORDER\n        float sigDist2 = median(smpl.r, smpl.g, smpl.b) - 0.01;\n        float bw=borderWidth*0.6+0.24;\n        float opacity2 = smoothstep(bw-borderSmooth,bw+borderSmooth,sigDist2*sigDist2);\n        fgColor=mix(fgColor,vec4(colorBorder,1.0),1.0-opacity2);\n    #endif\n\n    float opa=opacity*color.a;\n\n    if(opa==0.0)discard;\n\n    outColor = mix(outColor, fgColor, opa);\n\n#ifdef HAS_ATTR_COLORS\n    outColor*=fragAttrColors;\n#endif\n}\n\n",textmeshsdf_vert:"UNI sampler2D tex1;\nUNI sampler2D tex2;\nUNI sampler2D tex3;\nUNI sampler2D tex4;\n\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN mat4 instMat;\nIN vec2 attrTexOffsets;\nIN vec2 attrSize;\nIN vec2 attrTcSize;\nIN float attrPage;\nIN vec4 attrColors;\n\nOUT vec2 texCoord;\nOUT float texIndex;\nOUT vec4 fragAttrColors;\n\n\n\n\nconst float mulSize=0.01;\n\nvoid main()\n{\n    texCoord=(attrTexOffsets+attrTexCoord*attrTcSize);\n    texCoord.y=1.0-texCoord.y;\n\n    mat4 instMVMat=instMat;\n    vec4 vert=vec4( vPosition, 1. );\n    vert.x*=attrSize.x*mulSize;\n    vert.y*=attrSize.y*mulSize;\n\n    fragAttrColors=attrColors;\n\n    texIndex=attrPage+0.4; // strange ios rounding errors?!\n\n    mat4 mvMatrix=viewMatrix * modelMatrix * instMVMat;\n\n    gl_Position = projMatrix * mvMatrix * vert;\n}\n"};const x=r.inTrigger("Render"),U=r.inString("Text","cables"),a=r.inDropDown("Font",[],"",true),t=r.inFloat("Scale",.25),C=r.inFloat("Letter Spacing",0),T=r.inFloat("Line Height",1),I=r.inSwitch("Align",["Left","Center","Right"],"Center"),e=r.inSwitch("Vertical Align",["Zero","Top","Middle","Bottom"],"Middle"),i=r.inValueSlider("r",1),A=r.inValueSlider("g",1),_=r.inValueSlider("b",1),S=r.inValueSlider("a",1),n=r.inBool("SDF",true),G=r.inValueSlider("Smoothing",.3),s=r.inBool("Border",false),o=r.inFloatSlider("Border Width",.5),l=r.inFloatSlider("Smoothness",.25),u=r.inValueSlider("Border r",1),z=r.inValueSlider("Border g",1),q=r.inValueSlider("Border b",1),X=r.inBool("Shadow",false),h=r.inTexture("Texture Color"),p=r.inTexture("Texture Mask"),H=r.inArray("Positions"),Y=r.inArray("Scalings"),W=r.inArray("Rotations"),O=r.inArray("Colors"),K=r.outTrigger("Next"),Z=r.outArray("Positions Original",null,3),Q=r.outArray("Scales",null,2),J=r.outNumber("Num Lines"),$=r.outNumber("Width"),ee=r.outNumber("Height"),te=r.outNumber("Start Y"),ie=r.outNumber("Num Chars");r.setPortGroup("Size",[C,T,t]);r.setPortGroup("Character Transformations",[Y,W,H]);r.setPortGroup("Alignment",[I,e]);r.setPortGroup("Color",[i,A,_,S,n]);r.setPortGroup("Border",[u,z,q,l,o,s]);i.setUiAttribs({colorPick:true});u.setUiAttribs({colorPick:true});const E=r.patch.cgl;const ne="font_data_";const re=ne.length;const ae=vec3.create();const se=vec3.create();const c=new CGL.Shader(E,"TextMeshSDF");c.define("INSTANCING");let m=null;let P=null;let M=null;let f=true;let L=null;let N=null;let k=false;let d=1;let g=0,oe=0;let w=0;let R,V,D,B;let j=true;let F=null;let v=0;if(E.glVersion==1){E.gl.getExtension("OES_standard_derivatives");c.enableExtension("GL_OES_standard_derivatives")}c.setSource(b.textmeshsdf_vert,b.textmeshsdf_frag);const le=new CGL.Uniform(c,"t","tex0",0),ue=new CGL.Uniform(c,"t","tex1",1),he=new CGL.Uniform(c,"t","tex2",2),pe=new CGL.Uniform(c,"t","tex3",3),ce=new CGL.Uniform(c,"t","texMulColor",4),me=new CGL.Uniform(c,"t","texMulMask",5),fe=new CGL.Uniform(c,"4f","color",i,A,_,S),de=new CGL.Uniform(c,"3f","colorBorder",u,z,q),ge=new CGL.Uniform(c,"2f","texSize",0,0),ve=new CGL.Uniform(c,"f","smoothing",G),ye=new CGL.Uniform(c,"f","borderSmooth",l),be=new CGL.Uniform(c,"f","borderWidth",o);t.onChange=_e;W.onChange=H.onChange=Y.onChange=function(){j=true};h.onChange=p.onChange=X.onChange=s.onChange=n.onChange=xe;O.onLinkChanged=()=>{xe();j=true;f=true};O.onChange=()=>{f=true;if(N&&O.get()&&O.isLinked())N.setAttribute("attrColors",new Float32Array(O.get()),4,{instanced:true})};I.onChange=U.onChange=C.onChange=T.onChange=function(){f=true};e.onChange=Se;r.patch.addEventListener("variablesChanged",y);r.patch.addEventListener("FontLoadedMSDF",y);a.onChange=Ae;xe();_e();y();function xe(){c.toggleDefine("SDF",n.get());c.toggleDefine("SHADOW",X.get());c.toggleDefine("BORDER",s.get());c.toggleDefine("TEXTURE_COLOR",h.isLinked());c.toggleDefine("TEXTURE_MASK",p.isLinked());c.toggleDefine("HAS_ATTR_COLORS",O.isLinked());u.setUiAttribs({greyout:!s.get()});z.setUiAttribs({greyout:!s.get()});q.setUiAttribs({greyout:!s.get()});l.setUiAttribs({greyout:!s.get()});o.setUiAttribs({greyout:!s.get()})}function Ae(){y();const e=ne+a.get();P=null;m=null;M={};const t=r.patch.getVar(e);if(!t||!t.getValue()){P=null;return}P=t.getValue().data;if(!P){return}const i=t.getValue().basename;const n=r.patch.getVar("font_tex_"+i);if(!n){m=null;P=null;return}m=n.getValue();for(let e=0;e<P.chars.length;e++)M[P.chars[e].char]=P.chars[e];f=true}function y(){const e=r.patch.getVars();const t=["..."];for(const i in e)if(e[i].type=="fontData")t.push(i.substr(re));a.uiAttribs.values=t}function _e(){const e=t.get();vec3.set(se,e,e,e);vec3.set(ae,0,v*e,0);$.set(oe*e);ee.set(g*e);te.set((V+v)*e)}function Se(){if(D==undefined)return;if(e.get()=="Top")d=0;else if(e.get()=="Middle")d=1;else if(e.get()=="Bottom")d=2;else if(e.get()=="Zero")d=3;v=0;oe=Math.abs(D-B);g=Math.abs(R-V);if(d===1)v=g/2;else if(d===2)v=g;if(d!=0)v-=w;_e()}function Ce(){j=false;const t=[];const i=H.get()||Z.get();const n=Y.get();const r=W.get();for(let e=0;e<N.numInstances;e++){const a=mat4.create();mat4.translate(a,a,[i[e*3+0],i[e*3+1],i[e*3+2]]);if(n)mat4.scale(a,a,[n[e*3+0],n[e*3+1],n[e*3+2]]);if(r){mat4.rotateX(a,a,r[e*3+0]*CGL.DEG2RAD);mat4.rotateY(a,a,r[e*3+1]*CGL.DEG2RAD);mat4.rotateZ(a,a,r[e*3+2]*CGL.DEG2RAD)}t.push(Array.prototype.slice.call(a))}F=[].concat.apply([],t)}x.onTriggered=function(){if(!P||!m){Ae()}if(!P){r.setUiError("nodata","No font data!");r.setUiError("msdfhint","Use the FontMSDF op to create font and texture.",0)}if(!m){r.setUiError("nodata","No font texture");r.setUiError("msdfhint","Use the FontMSDF op to create font and texture.",0)}if(m&&P){r.setUiError("nodata",null);r.setUiError("msdfhint",null)}if(f){Ie();f=false}if(N&&N.numInstances>0&&m){E.pushShader(c);E.setTexture(0,CGL.Texture.getEmptyTexture(E).tex);if(m[0])ge.setValue([m[0].width,m[0].height]);if(m[0])E.setTexture(0,m[0].tex);else E.setTexture(0,CGL.Texture.getEmptyTexture(E).tex);if(m[1])E.setTexture(1,m[1].tex);else E.setTexture(1,CGL.Texture.getEmptyTexture(E).tex);if(m[2])E.setTexture(2,m[2].tex);else E.setTexture(2,CGL.Texture.getEmptyTexture(E).tex);if(m[3])E.setTexture(3,m[3].tex);else E.setTexture(3,CGL.Texture.getEmptyTexture(E).tex);if(h.get())E.setTexture(4,h.get().tex);if(p.get())E.setTexture(5,p.get().tex);E.pushModelMatrix();mat4.translate(E.mMatrix,E.mMatrix,ae);if(j)Ce();if(F)N.setAttribute("instMat",new Float32Array(F),16,{instanced:true});if(!k){mat4.scale(E.mMatrix,E.mMatrix,se);N.render(E.getShader())}E.popModelMatrix();E.popShader()}K.trigger()};function Te(e){return M[String(e)]||M["?"]||M._||M.X}function Ie(){if(!P||!M){ie.set(0);return}const e=String(U.get()+"");if(!L){L=new CGL.Geometry("textmesh");L.vertices=[.5,.5,0,-.5,.5,0,.5,-.5,0,-.5,-.5,0];L.normals=[0,0,0,0,0,0,0,0,0,0,0,0];L.texCoords=new Float32Array([1,0,0,0,1,1,0,1]);L.verticesIndices=[0,1,2,2,1,3]}if(N)N.dispose();N=new CGL.Mesh(E,L);const r=e.split("\n");const a=[];const s=[];const o=[];const t=[];const l=[];const u=[];let h=0;const p=[];const c=.01;J.set(r.length);R=99999;V=-99999;D=99999;B=-99999;w=0;for(let e=0;e<P.chars.length;e++){if(P.chars[e].height)w+=P.chars[e].height}w/=P.chars.length;w*=c;for(let n=0;n<r.length;n++){const m=r[n];const f=m.length;let t=0;for(let e=0;e<f;e++){const d=m.substring(e,e+1);const g=Te(d);if(g)t+=g.xadvance*c+C.get()}let i=0;if(I.get()=="Right")i-=t;else if(I.get()=="Center")i-=t/2;for(let t=0;t<f;t++){const v=mat4.create();const d=m.substring(t,t+1);const g=Te(d);if(!g)continue;u.push(g.page||0);o.push(g.width,g.height);s.push(g.x/P.common.scaleW,g.y/P.common.scaleH);const y=g.width/P.common.scaleW;const b=g.height/P.common.scaleH;const x=g.yoffset/P.common.scaleH;const A=g.xoffset/P.common.scaleW;if(d==" ")l.push(0,0);else l.push(y,b);mat4.identity(v);let e=g.xadvance/2*c;i+=e;const _=i+g.xoffset/2*c;const S=n*-T.get()+w-c*(g.yoffset+g.height/2);D=Math.min(_-y,D);B=Math.max(_+y,B);R=Math.min(S-b-w/2,R);V=Math.max(S+b+w/2,V);mat4.translate(v,v,[_,S,0]);p.push(_,S,0);e=g.xadvance/2*c+C.get();i+=e;D=Math.min(i-y,D);B=Math.max(i+y,B);a.push(Array.prototype.slice.call(v));h++}}F=[].concat.apply([],a);k=false;if(F.length==0)k=true;N.numInstances=F.length/16;ie.set(N.numInstances);if(N.numInstances==0){k=true;return}N.setAttribute("instMat",new Float32Array(F),16,{instanced:true});N.setAttribute("attrTexOffsets",new Float32Array(s),2,{instanced:true});N.setAttribute("attrTcSize",new Float32Array(l),2,{instanced:true});N.setAttribute("attrSize",new Float32Array(o),2,{instanced:true});N.setAttribute("attrPage",new Float32Array(u),1,{instanced:true});if(O.isLinked())N.setAttribute("attrColors",new Float32Array(O.get()),4,{instanced:true});Q.set(o);Se();j=true;Z.setRef(p)}};Ops.Gl.TextMeshMSDF_v2.prototype=new CABLES.Op;CABLES.OPS["b5c99363-a749-4040-884b-66f91294bcad"]={f:Ops.Gl.TextMeshMSDF_v2,objName:"Ops.Gl.TextMeshMSDF_v2"};Ops.String.SubString_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inString("String","cables"),r=e.inValueInt("Start",0),a=e.inValueInt("End",4),s=e.inBool("End of string",false),o=e.outString("Result");n.onChange=r.onChange=a.onChange=i;i();s.onChange=()=>{a.setUiAttribs({greyout:s.get()});i()};function i(){let e=r.get();let t=a.get();let i=n.get()+"";if(s.get())o.set(i.substring(e));else o.set(i.substring(e,t))}};Ops.String.SubString_v2.prototype=new CABLES.Op;CABLES.OPS["6e994ba8-01d1-4da6-98b4-af7e822a2e6c"]={f:Ops.String.SubString_v2,objName:"Ops.String.SubString_v2"};Ops.Math.Sum=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inValueFloat("number1",0),n=e.inValueFloat("number2",0),r=e.outNumber("result");e.setUiAttribs({mathTitle:true});i.onChange=n.onChange=a;a();function a(){const e=i.get()+n.get();if(!isNaN(e))r.set(e)}};Ops.Math.Sum.prototype=new CABLES.Op;CABLES.OPS["c8fb181e-0b03-4b41-9e55-06b6267bc634"]={f:Ops.Math.Sum,objName:"Ops.Math.Sum"};Ops.Number.Number=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inValueFloat("value"),n=e.outNumber("result");i.onChange=r;function r(){n.set(Number(i.get()))}};Ops.Number.Number.prototype=new CABLES.Op;CABLES.OPS["8fb2bb5d-665a-4d0a-8079-12710ae453be"]={f:Ops.Number.Number,objName:"Ops.Number.Number"};Ops.Array.ArrayMultiply=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inArray("In"),r=e.inValue("Value",1),a=e.outArray("Result");let s=[];a.set(s);n.onChange=r.onChange=n.onChange=function(){let t=n.get();if(!t)return;let i=r.get();if(s.length!=t.length)s.length=t.length;for(let e=0;e<t.length;e++)s[e]=t[e]*i;a.setRef(s)};n.onLinkChanged=()=>{if(n)n.copyLinkedUiAttrib("stride",a)}};Ops.Array.ArrayMultiply.prototype=new CABLES.Op;CABLES.OPS["a01c344b-4129-4b01-9c8f-36cefe86d7cc"]={f:Ops.Array.ArrayMultiply,objName:"Ops.Array.ArrayMultiply"};Ops.Array.ArrayPack3=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTrigger("Trigger in"),a=e.inArray("Array 1"),s=e.inArray("Array 2"),o=e.inArray("Array 3"),l=e.outTrigger("Trigger out"),u=e.outArray("Array out",3),h=e.outNumber("Num Points"),p=e.outNumber("Array length");let n=false;let c=[];let m=[];let f=true;i.onTriggered=d;a.onChange=s.onChange=o.onChange=r;function r(){f=true}function d(){let i=a.get();let n=s.get();let r=o.get();if(!i&&!n&&!r){u.set(null);h.set(0);return}if(f){let t=0;if(!i||!n||!r){if(i)t=i.length;else if(n)t=n.length;else if(r)t=r.length;if(m.length!=t)for(let e=0;e<t;e++)m[e]=0;if(!i)i=m;if(!n)n=m;if(!r)r=m}if(i.length!==n.length||n.length!==r.length){e.setUiError("arraylen","Arrays do not have the same length !");return}e.setUiError("arraylen",null);c.length=i.length;for(let e=0;e<i.length;e++){c[e*3+0]=i[e];c[e*3+1]=n[e];c[e*3+2]=r[e]}f=false;u.setRef(c);h.set(c.length/3);p.set(c.length)}l.trigger()}};Ops.Array.ArrayPack3.prototype=new CABLES.Op;CABLES.OPS["2bcf32fe-3cbd-48fd-825a-61255bebda9b"]={f:Ops.Array.ArrayPack3,objName:"Ops.Array.ArrayPack3"};Ops.Math.Modulo=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inValueFloat("number1",1),n=e.inValueFloat("number2",2),r=e.inValueBool("pingpong"),a=e.outNumber("result");let s=l;i.onChange=n.onChange=o;r.onChange=h;o();function o(){let e=n.get();let t=i.get();a.set(s(t,e))}function l(e,t){let i=(e%t+t)%t;if(i!=i)i=0;return i}function u(e,t){let i=2*t;e%=i;if(e>=t)return i-e;else return e}function h(){if(r.get())s=u;else s=l}};Ops.Math.Modulo.prototype=new CABLES.Op;CABLES.OPS["ebc13b25-3705-4265-8f06-5f985b6a7bb1"]={f:Ops.Math.Modulo,objName:"Ops.Math.Modulo"};Ops.Array.ArraySubtract=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inArray("Array In"),r=e.inValue("Value",1),i=e.inSwitch("Mode",["Array-x","x-Array"],"Array-x"),a=e.outArray("Array Out");let s=[];let o=true;n.onLinkChanged=()=>{if(n)n.copyLinkedUiAttrib("stride",a)};i.onChange=()=>{o=i.get()==="Array-x";l()};a.set(s);n.onChange=r.onChange=l;function l(){let e=n.get();if(!e)return;let t=r.get();if(s.length!=e.length)s.length=e.length;let i=0;if(o)for(i=0;i<e.length;i++)s[i]=e[i]-t;else for(i=0;i<e.length;i++)s[i]=t-e[i];a.setRef(s)}};Ops.Array.ArraySubtract.prototype=new CABLES.Op;CABLES.OPS["af78ab59-75d5-4ead-9a8d-27a63e1cbf3f"]={f:Ops.Array.ArraySubtract,objName:"Ops.Array.ArraySubtract"};Ops.Array.ArraySin=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const a=e.inArray("array in");const i=e.inValueSelect("Math function",["Sin","Cos"],"Sin");const s=e.outArray("Array result");const o=e.inValue("Phase",0);const l=e.inValue("Frequency",1);const u=e.inValue("Amplitude",1);const h=[];let p=0;const c=0;const m=1;a.onChange=r;l.onChange=r;u.onChange=r;o.onChange=r;i.onChange=n;function n(){const e=i.get();if(e==="Sin")p=c;else if(e==="Cos")p=m;r()}function r(){const e=a.get();if(!e){h.length=0;return}h.length=e.length;const t=u.get();const i=l.get();const n=o.get();let r=0;if(p===c){for(r=0;r<e.length;r++)h[r]=t*Math.sin(e[r]*i+n)}else if(p===m){for(r=0;r<e.length;r++)h[r]=t*Math.cos(e[r]*i+n)}s.setRef(h)}};Ops.Array.ArraySin.prototype=new CABLES.Op;CABLES.OPS["ded44bae-a24e-48c5-9585-4cb31f331ab6"]={f:Ops.Array.ArraySin,objName:"Ops.Array.ArraySin"};Ops.Array.ArrayMath=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=t.inArray("array 0"),r=t.inValueFloat("Number for math",0),i=t.inSwitch("Math function",["+","-","*","/","%","min","max"],"+"),a=t.outArray("Array result"),s=t.outNumber("Array length");t.toWorkPortsNeedToBeLinked(n);let o;let l=false;let u=[];n.onChange=r.onChange=p;i.onChange=h;h();n.onLinkChanged=()=>{if(n)n.copyLinkedUiAttrib("stride",a)};function h(){let e=i.get();if(e==="+")o=function(e,t){return e+t};else if(e==="-")o=function(e,t){return e-t};else if(e==="*")o=function(e,t){return e*t};else if(e==="/")o=function(e,t){return e/t};else if(e==="%")o=function(e,t){return e%t};else if(e==="min")o=function(e,t){return Math.min(e,t)};else if(e==="max")o=function(e,t){return Math.max(e,t)};p();t.setUiAttrib({extendTitle:e})}function p(){let e=n.get();u.length=0;if(!e){s.set(0);a.set(null);return}let t=r.get();u.length=e.length;let i=0;for(i=0;i<e.length;i++){u[i]=o(e[i],t)}a.setRef(u);s.set(u.length)}};Ops.Array.ArrayMath.prototype=new CABLES.Op;CABLES.OPS["c7617717-3114-452f-9625-e4fefd841e88"]={f:Ops.Array.ArrayMath,objName:"Ops.Array.ArrayMath"};Ops.Anim.Timer_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const a=e.inValue("Speed",1),i=e.inValueBool("Play",true),n=e.inTriggerButton("Reset"),r=e.inValueBool("Sync to timeline",false),s=e.outNumber("Time");e.setPortGroup("Controls",[i,n,a]);const o=new CABLES.Timer;let l=null;let u=0;let h=false;i.onChange=p;p();function p(){if(i.get()){o.play();e.patch.addOnAnimFrame(e)}else{o.pause();e.patch.removeOnAnimFrame(e)}}n.onTriggered=c;function c(){u=0;l=null;o.setTime(0);s.set(0)}r.onChange=function(){h=r.get();i.setUiAttribs({greyout:h});n.setUiAttribs({greyout:h})};e.onAnimFrame=function(e,t,i){if(o.isPlaying()){if(CABLES.overwriteTime!==undefined){s.set(CABLES.overwriteTime*a.get())}else if(h){s.set(e*a.get())}else{o.update();const n=o.get();if(l===null){l=n;return}const r=Math.abs(n-l);l=n;u+=r*a.get();if(u!=u)u=0;s.set(u)}}}};Ops.Anim.Timer_v2.prototype=new CABLES.Op;CABLES.OPS["aac7f721-208f-411a-adb3-79adae2e471a"]={f:Ops.Anim.Timer_v2,objName:"Ops.Anim.Timer_v2"};Ops.String.StringLength_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inString("String"),n=e.outNumber("Result");i.onChange=function(){if(!i.get())n.set(0);else n.set(String(i.get()).length)}};Ops.String.StringLength_v2.prototype=new CABLES.Op;CABLES.OPS["aa47bb8b-d5d7-4175-b217-ab0157d3365d"]={f:Ops.String.StringLength_v2,objName:"Ops.String.StringLength_v2"};Ops.Array.Array_v3=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=t.inValueInt("Array length",10),i=t.inSwitch("Mode select",["Number","1,2,3,4","0-1"],"Number"),r=t.inValueFloat("Default Value"),a=t.inBool("Reverse",false),s=t.outArray("Array"),o=t.outNumber("Array length out");let l=[];let u=0;const h=0;const p=1;const c=2;i.onChange=m;a.onChange=r.onChange=n.onChange=f;m();f();function m(){let e=i.get();if(e==="Number")u=h;else if(e==="1,2,3,4")u=p;else if(e==="0-1")u=c;r.setUiAttribs({greyout:u!==h});t.setUiAttrib({extendTitle:i.get()});f()}function f(){l.length=0;let e=n.get();let t=r.get();let i;if(u===h){for(i=0;i<e;i++){l[i]=t}}else if(u===p){for(i=0;i<e;i++){l[i]=i}}else if(u===c){if(e>1){for(i=0;i<e;i++){l[i]=i/(e-1)}}else{l=[0]}}if(a.get())l=l.reverse();s.setRef(l);o.set(l.length)}};Ops.Array.Array_v3.prototype=new CABLES.Op;CABLES.OPS["e4d31a46-bf64-42a8-be34-4cbb2bbc2600"]={f:Ops.Array.Array_v3,objName:"Ops.Array.Array_v3"};Ops.Array.PointArray.PointsPlane_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const h=e.inValueInt("Rows",32),p=e.inValueInt("Columns",32),c=e.inFloat("Width",2),m=e.inFloat("Height",2),f=e.inFloat("Row Offset",0),d=e.inValueBool("Center",true),g=e.outArray("Result",[],3),v=e.outNumber("Total points"),y=e.outNumber("Array length"),b=e.outArray("Row Numbers",[],1),x=e.outArray("Column Numbers",[],1);h.onChange=p.onChange=d.onChange=m.onChange=f.onChange=c.onChange=i;const A=[];const _=[];const S=[];g.setRef(A);i();function i(){A.length=0;const i=Math.floor(Math.max(0,h.get()));const e=Math.floor(Math.max(0,p.get()));if(!CABLES.UTILS.isNumeric(i)||!CABLES.UTILS.isNumeric(e)||i<0||e<0){b.setRef(0);x.setRef(0);g.setRef([]);v.set(0);y.set(0);return}let n=0;let r=0;if(i==1){n=m.get()/i}else{n=m.get()/(i-1)}if(e==1){r=c.get()/e}else{r=c.get()/(e-1)}let a=0;let s=0;let o=0;if(d.get()){s=m.get()/2;o=c.get()/2}const t=Math.floor(i)*Math.floor(e)*3;A.length=t;S.length=t/3;_.length=t/3;let l=f.get();let u=0;for(let t=0;t<e;t++){for(let e=0;e<i;e++){u=0;if(e%2==0&&l)u=l;S[a/3]=t;_[a/3]=e;A[a++]=r*t-o+u;A[a++]=n*e-s;A[a++]=0}}b.setRef(_);x.setRef(S);g.setRef(A);v.set(A.length/3);y.set(A.length)}};Ops.Array.PointArray.PointsPlane_v2.prototype=new CABLES.Op;CABLES.OPS["d453f898-17d4-4e2c-b8c7-7b7b34c0ff68"]={f:Ops.Array.PointArray.PointsPlane_v2,objName:"Ops.Array.PointArray.PointsPlane_v2"};Ops.Math.MapRange=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const c=e.inValueFloat("value",0),m=e.inValueFloat("old min",0),f=e.inValueFloat("old max",1),d=e.inValueFloat("new min",0),g=e.inValueFloat("new max",1),i=e.inValueSelect("Easing",["Linear","Smoothstep","Smootherstep"],"Linear"),n=e.inBool("Clamp",true),v=e.outNumber("result",0);e.setPortGroup("Input Range",[m,f]);e.setPortGroup("Output Range",[d,g]);let y=true;let b=0;let x=0;c.onChange=m.onChange=f.onChange=d.onChange=g.onChange=r;r();n.onChange=()=>{y=n.get();r()};i.onChange=function(){if(i.get()=="Smoothstep")b=1;else if(i.get()=="Smootherstep")b=2;else b=0};function r(){const e=d.get();const t=g.get();const i=m.get();const n=f.get();let r=c.get();if(y){if(r>=Math.max(n,i)){v.set(t);return}else if(r<=Math.min(n,i)){v.set(e);return}}let a=false;const s=Math.min(i,n);const o=Math.max(i,n);if(s!=i)a=true;let l=false;const u=Math.min(e,t);const h=Math.max(e,t);if(u!=e)l=true;let p=0;if(a)p=(o-r)*(h-u)/(o-s);else p=(r-s)*(h-u)/(o-s);if(l)x=h-p;else x=p+u;if(b===0){v.set(x)}else if(b==1){r=Math.max(0,Math.min(1,(x-e)/(t-e)));v.set(e+r*r*(3-2*r)*(t-e))}else if(b==2){r=Math.max(0,Math.min(1,(x-e)/(t-e)));v.set(e+r*r*r*(r*(r*6-15)+10)*(t-e))}}};Ops.Math.MapRange.prototype=new CABLES.Op;CABLES.OPS["2617b407-60a0-4ff6-b4a7-18136cfa7817"]={f:Ops.Math.MapRange,objName:"Ops.Math.MapRange"};Ops.Trigger.TriggerLimiter=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTrigger("In Trigger"),n=e.inValue("Milliseconds",300),r=e.outTrigger("Out Trigger"),a=e.outNumber("Progress");let s=0;i.onTriggered=function(){const e=CABLES.now();let t=(e-s)/n.get();if(t>1)t=1;if(t<0)t=0;a.set(t);if(e>=s+n.get()){s=e;r.trigger()}}};Ops.Trigger.TriggerLimiter.prototype=new CABLES.Op;CABLES.OPS["47641d85-9f81-4287-8aa2-35753b0727e0"]={f:Ops.Trigger.TriggerLimiter,objName:"Ops.Trigger.TriggerLimiter"};Ops.Array.ArrayUnpack3=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inArray("Array in xyz"),n=e.outArray("Array 1 out"),r=e.outArray("Array 2 out"),a=e.outArray("Array 3 out"),s=e.outNumber("Array lengths");let o=false;const l=[];const u=[];const h=[];i.onChange=p;function p(){let t=i.get();if(!t){n.set(null);return}if(t.length%3!==0){if(!o){e.uiAttr({error:"Arrays length not divisible by 3 !"});s.set(0);o=true}return}if(o){o=false;e.uiAttr({error:null})}l.length=Math.floor(t.length/3);u.length=Math.floor(t.length/3);h.length=Math.floor(t.length/3);for(let e=0;e<t.length/3;e++){l[e]=t[e*3];u[e]=t[e*3+1];h[e]=t[e*3+2]}n.setRef(l);r.setRef(u);a.setRef(h);s.set(l.length)}};Ops.Array.ArrayUnpack3.prototype=new CABLES.Op;CABLES.OPS["fa671f66-6957-41e6-ac35-d615b7c29285"]={f:Ops.Array.ArrayUnpack3,objName:"Ops.Array.ArrayUnpack3"};Ops.String.RandomString_v3=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const r=e.inString("chars","cables"),a=e.inInt("Length",10),s=e.inFloat("Seed",0),o=e.outString("Result");a.onChange=r.onChange=s.onChange=i;i();function i(){Math.setRandomSeed(Math.abs(s.get()));const i=Array.from(r.get());let n="";if(i.length>0){let t=i.length-1;for(let e=0;e<Math.abs(a.get());e++)n+=i[Math.round(Math.seededRandom()*t)]}o.set(n)}};Ops.String.RandomString_v3.prototype=new CABLES.Op;CABLES.OPS["d2374316-90b1-4f50-bdb6-0d7296bbea75"]={f:Ops.String.RandomString_v3,objName:"Ops.String.RandomString_v3"};Ops.Trigger.TriggerNumber=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTriggerButton("Set"),n=e.inValueFloat("Number"),r=e.outTrigger("Next"),a=e.outNumber("Out Value");a.changeAlways=true;i.onTriggered=function(){a.set(n.get());r.trigger()}};Ops.Trigger.TriggerNumber.prototype=new CABLES.Op;CABLES.OPS["9989b1c0-1073-4d5f-bfa0-36dd98b66e27"]={f:Ops.Trigger.TriggerNumber,objName:"Ops.Trigger.TriggerNumber"};Ops.Vars.VarGetArray_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.outArray("Value");e.varName=e.inValueSelect("Variable",[],"",true);new CABLES.VarGetOpWrapper(e,"array",e.varName,i)};Ops.Vars.VarGetArray_v2.prototype=new CABLES.Op;CABLES.OPS["afa79294-aa9c-43bc-a49a-cade000a1de5"]={f:Ops.Vars.VarGetArray_v2,objName:"Ops.Vars.VarGetArray_v2"};Ops.Array.ArrayGetNumber=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inArray("array"),n=e.inValueInt("index"),r=e.inFloat("Value Invalid Index",0),a=e.outNumber("value"),s=e.outBoolNum("Valid Index",true);i.ignoreValueSerialize=true;n.onChange=i.onChange=o;function o(){if(i.get()){const e=i.get()[n.get()];if(isNaN(e)){a.set(r.get());s.set(false)}else{s.set(true);a.set(parseFloat(e))}}}};Ops.Array.ArrayGetNumber.prototype=new CABLES.Op;CABLES.OPS["d1189078-70cf-437d-9a37-b2ebe89acdaf"]={f:Ops.Array.ArrayGetNumber,objName:"Ops.Array.ArrayGetNumber"};Ops.Gl.LineFont_v2=function(){CABLES.Op.apply(this,arguments);const l=this;const e=l.attachments={};const t=l.inTrigger("render"),i=l.inString("Text","cables"),u=l.inValue("Letter Spacing",1),n=l.inSwitch("align",["left","center","right"],"left"),r=l.inBool("Render",true),h=l.outArray("Lines",null,3);let p=[];let c=0;const a=[];const m=vec3.create();const f=l.patch.cgl;const d=[{l:[[182.667,349.057,164.167,349.057],[160.333,360.557,171.333,326.89,175.333,326.89,186,360.557]]},{l:[[174.333,343.057,160.255,343.057],[160.333,326.89,175.5,326.89,178.333,330.724,178.333,340.724,174.333,343.057,180.5,346.807,180.5,357.474,176,360.557,160.167,360.557,160.333,326.89]]},{l:[[180.583,331.307,175.917,326.807,166,326.807,160.083,332.557,160.083,354.557,165.833,360.474,175.917,360.474,180.5,355.807]]},{l:[[160.083,327.057,160.083,360.557,175.417,360.557,180.708,355.265,180.708,332.974,175.104,327.057,160.083,327.057]]},{l:[[175.167,343.932,160.436,343.932],[177.917,326.807,164.5,326.807,160.436,330.872,160.436,356.845,164.014,360.422,177.917,360.422]]},{l:[[176.792,326.932,164.125,326.932,160.167,330.891,160.167,360.683],[173.458,345.599,160.167,345.599]]},{l:[[180.455,332.395,175.391,328.33,166.194,328.33,160.167,334.357,160.167,355.933,165.792,360.557,176.038,360.557,181.62,354.976,181.62,344.811,173.122,344.811]]},{l:[[160.167,326.89,160.167,360.557],[160.5,343.723,182.333,343.723],[182.333,326.89,182.333,360.974]]},{l:[[160.167,326.807,160.167,360.641]]},{l:[[159.833,326.89,166.833,326.89,166.833,362.057,163.962,364.928,159.833,364.928]]},{l:[[160.167,326.807,160.167,360.974],[178.917,326.807,160.167,348.474],[164.905,342.998,180.333,360.64]]},{l:[[160.167,326.974,160.167,360.558,176.083,360.558]]},{l:[[160.167,360.557,160.247,326.89,164.997,326.89,175.5,360.557,178,360.557,188.58,326.89,193.33,326.89,193.25,360.557]]},{l:[[160.167,360.599,160.167,326.933,164.629,326.933,178.333,360.599,182.083,360.599,182.083,326.933]]},{l:[[160.283,332.448,165.764,326.967,178.405,326.967,183.668,332.23,183.668,354.365,177.434,360.599,166.367,360.599,160.167,354.399,160.283,332.448]]},{l:[[160.167,360.432,160.167,327.015,175.955,327.015,179.667,330.728,179.667,341.015,175.602,345.08,160.167,345.08]]},{l:[[184.504,361.693,180.517,357.706],[160.283,332.413,165.764,326.932,178.405,326.932,183.668,332.195,183.668,354.33,177.434,360.564,166.367,360.564,160.167,354.364,160.283,332.413]]},{l:[[179.667,360.307,173.5,344.955],[160.167,360.307,160.167,326.89,175.955,326.89,179.667,330.603,179.667,340.89,175.602,344.955,160.167,344.955]]},{l:[[179.979,326.87,165.895,326.87,160.167,332.598,160.167,338.307,179.292,349.057,179.292,355.223,173.917,360.598,160.167,360.598]]},{l:[[170.417,326.89,170.417,360.974],[180.5,326.89,160.167,326.89]]},{l:[[160.167,327.14,160.167,356.845,164.108,360.786,178.125,360.786,182.012,356.899,181.958,327.14]]},{l:[[160.167,326.901,170.167,360.797,174.417,360.797,184.667,326.734]]},{l:[[203.5,326.89,195.208,360.557,191.458,360.557,184,326.89,179.758,326.89,172.208,360.557,168.458,360.557,160.167,326.89]]},{l:[[181.333,360.64,159.667,326.807],[159.667,360.557,181.75,326.807]]},{l:[[160.167,326.891,168.508,347.224,173.992,347.224,182.917,326.891],[171.333,347.224,171.333,360.641]]},{l:[[161.167,326.807,180.5,326.807,180.5,332.473,161.167,355.223,161.167,360.557,180.5,360.557]]},{l:[[167.591,326.89,173.076,326.89,180.5,334.315,180.5,353.132,173.076,360.557,167.591,360.557,160.167,353.132,160.167,334.315,167.591,326.89]]},{l:[[160.167,334.315,167.549,326.932,170.333,326.89,170.417,360.557]]},{l:[[164.066,330.415,167.591,326.89,180.5,326.89,180.5,330.603,160.167,351.224,160.167,360.557,180.5,360.599]]},{l:[[169.583,342.932,180.5,342.932],[163.129,331.353,167.591,326.89,180.5,326.89,180.5,360.557,167.591,360.557,162.837,355.803]]},{l:[[178.076,326.89,178.076,360.599],[160.167,326.89,160.167,338.474,165.104,343.412,178.5,343.412]]},{l:[[180.5,326.89,160.098,326.958,160.167,342.932,180.5,342.932,180.5,353.132,173.076,360.557,160.167,360.557]]},{l:[[173.076,326.89,167.591,326.89,160.167,333.89,160.167,353.132,167.591,360.557,173.417,360.557,180.671,353.303,180.671,342.932,160.167,342.932]]},{l:[[163.591,326.89,180.5,326.89,170.417,360.557]]},{l:[[180.5,334.315,173.076,326.89,167.591,326.89,160.167,334.315,180.5,353.132,173.076,360.557,167.591,360.557,160.167,353.132,180.5,334.315]]},{l:[[167.591,360.557,173.076,360.557,180.5,353.132,180.5,334.315,173.076,326.89,167.591,326.89,160.167,334.315,160.167,342.932,180.5,342.932]]},{l:[[182.496,351.137,173.076,360.557,167.591,360.557,160.167,353.132,160.167,348.087,173.922,339.533,172.229,326.89,165.167,326.89,165.052,339.515,184.292,359.432]]},{l:[[160.167,326.932,160.167,333.557],[162.879,326.932,162.879,333.557]]},{l:[[160.167,342.932,160.167,346.224],[160.167,354.224,160.167,360.557]]},{l:[[160.167,342.932,160.167,346.224],[160.167,354.224,160.167,357.974]]},{l:[[160.167,360.557,170.417,360.557]]},{l:[[160.167,342.932,170,342.932],[164.833,347.849,164.833,338.015]]},{l:[[160.167,342.932,170,342.932]]},{l:[[180.5,326.89,160.167,360.557]]},{l:[[160.167,360.599,163.417,360.599]]},{l:[[165.163,360.557,160.167,365.553]]},{l:[[160.167,360.557,167.591,353.132,167.591,334.315,160.167,326.89]]},{l:[[167.591,326.89,160.167,334.315,160.167,353.132,167.591,360.557]]},{l:[[170.333,363.481,170.333,368.966],[160.167,334.315,167.591,326.89,173.076,326.89,180.5,334.315,180.5,342.932,170.333,353.132,170.333,360.557]]},{l:[[160.167,353.557,160.167,326.89],[160.167,357.64,160.167,360.557]]}];function g(e){y+=e;vec3.set(m,e,0,0);mat4.translate(f.mMatrix,f.mMatrix,m)}let v=0;n.onChange=function(){if(n.get()=="left")v=0;if(n.get()=="center")v=1;if(n.get()=="right")v=2};let s=0;let o=null;let y=0;function b(t,e){o=f.getShader();if(!o)return;s=o.glPrimitive;o.glPrimitive=f.gl.LINE_STRIP;if(t>=d.length)t=0;if(!e){for(let e=0;e<d[t].linesArr.length;e+=3){p.push(d[t].linesArr[e+0]+y,d[t].linesArr[e+1],d[t].linesArr[e+2])}for(let e=0;e<d[t].m.length;e++){if(r.get())d[t].m[e].render(l.patch.cgl.getShader())}g(d[t].w*u.get())}else{c+=d[t].w*u.get()}o.glPrimitive=s}t.onTriggered=function(){c=0;if(!i.get())return;let r=.15;vec3.set(m,.3,0,0);f.pushModelMatrix();let a=97;let s=48;let o=i.get()+"";for(let e=0;e<2;e++){y=0;p.length=0;let n=e===0;if(!n){if(v==1)g(-c/2+.04*u.get());if(v==2)g(-c+.08*u.get())}for(let i=0;i<o.length;i++){let e=0;let t=o.toLowerCase().charCodeAt(i);if(t==38)b(36,n);else if(t==39)b(37,n);else if(t==34)b(37,n);else if(t==59)b(38,n);else if(t==58)b(39,n);else if(t==95)b(40,n);else if(t==43)b(41,n);else if(t==45)b(42,n);else if(t==47)b(43,n);else if(t==46)b(44,n);else if(t==44)b(45,n);else if(t==41)b(46,n);else if(t==40)b(47,n);else if(t==63)b(48,n);else if(t==33)b(49,n);else if(t>=s&&t<=s+10){b(t-s+26,n)}else if(t>=a&&t-a<d.length){b(t-a,n)}else if(t==32){if(n)c+=r;else g(r)}else{b(48,n)}}}h.setRef(p);f.popModelMatrix()};function x(i){let n=0,r=0;let a=0;for(let t=0;t<d[i].l.length;t++){for(let e=0;e<d[i].l[t].length;e+=2){n+=d[i].l[t][e];r+=d[i].l[t][e+1];a++}}n/=a;r/=a;return[n,r]}function A(i){let n=9999999;for(let t=0;t<d[i].l.length;t++){for(let e=0;e<d[i].l[t].length;e+=2){n=Math.min(n,d[i].l[t][e])}}return n}function _(i){let n=9999999;let r=-9999999;for(let t=0;t<d[i].l.length;t++){for(let e=0;e<d[i].l[t].length;e+=2){n=Math.min(n,d[i].l[t][e]);r=Math.max(r,d[i].l[t][e])}}return r-n}a.length=0;let S=[];let C=x(0);let T=x(1);S=[(C[0]+T[0])/2,(C[1]+T[1])/2];for(let o=0;o<d.length;o++){d[o].w=_(o)*.002;d[o].m=[];let s=[];for(let a=0;a<d[o].l.length;a++){let t=0;let i=[];let n=[];for(let e=0;e<d[o].l[a].length-2;e+=2){s.push((d[o].l[a][e]-A(o))*.005,(d[o].l[a][e+1]-S[1])*-.005,0);s.push((d[o].l[a][e+2]-A(o))*.005,(d[o].l[a][e+3]-S[1])*-.005,0)}for(let e=0;e<d[o].l[a].length;e+=2){n.push((d[o].l[a][e]-A(o))*.005);n.push((d[o].l[a][e+1]-S[1])*-.005);n.push(0);i.push(t);t++}d[o].linesArr=s;let e=new CGL.Geometry(l.name);e.vertices=n;e.verticesIndices=i;let r=new CGL.Mesh(l.patch.cgl,e);d[o].m.push(r)}h.set([]);d[o].w+=.1}};Ops.Gl.LineFont_v2.prototype=new CABLES.Op;CABLES.OPS["a3615010-05af-45bc-bf98-6972c2de21bc"]={f:Ops.Gl.LineFont_v2,objName:"Ops.Gl.LineFont_v2"};Ops.String.SwitchString=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inValueInt("Index"),n=e.outString("Result");const r=[];i.onChange=o;for(var a=0;a<10;a++){var s=e.inString("String "+a);r.push(s);s.onChange=o}function o(){if(i.get()>=0&&r[i.get()]){n.set(r[i.get()].get())}}};Ops.String.SwitchString.prototype=new CABLES.Op;CABLES.OPS["2a7a0c68-f7c9-4249-b19a-d2de5cb4862c"]={f:Ops.String.SwitchString,objName:"Ops.String.SwitchString"};Ops.Gl.ImageCompose.ZoomBlur_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={zoomblur_frag:"UNI sampler2D tex;\nUNI float x;\nUNI float y;\nUNI float strength;\nIN vec2 texCoord;\n\n#ifdef HAS_MASK\n    UNI sampler2D texMask;\n#endif\n\nfloat random(vec3 scale, float seed)\n{\n    return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);\n}\n\n#ifdef MASK_SRC_LUM\n    {{CGL.LUMINANCE}}\n#endif\n\nvoid main()\n{\n    float total = 0.0;\n    vec4 color = vec4(0.0);\n    vec2 center=vec2(x,y);\n    center=(center/2.0)+0.5;\n\n    vec2 texSize=vec2(1.0,1.0);\n    vec2 toCenter = center - texCoord * texSize;\n\n    /* randomize the lookup values to hide the fixed number of samples */\n    float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);\n    float am = strength;\n\n    #ifdef HAS_MASK\n\n        float mul=1.0;\n        #ifdef MASK_SRC_R\n            mul=texture(texMask,texCoord).r;\n        #endif\n        #ifdef MASK_SRC_G\n            mul=texture(texMask,texCoord).g;\n        #endif\n        #ifdef MASK_SRC_B\n            mul=texture(texMask,texCoord).b;\n        #endif\n        #ifdef MASK_SRC_A\n            mul=texture(texMask,texCoord).a;\n        #endif\n        #ifdef MASK_SRC_LUM\n            mul=cgl_luminance(texture(texMask,texCoord).rgb);\n        #endif\n\n        #ifdef MASK_INV\n            mul=1.0-mul;\n        #endif\n\n        am=am*mul;\n\n        // if(am<=0.0)\n        // {\n        //     outColor=texture(tex, texCoord);\n        //     return;\n        // }\n    #endif\n\n    for (float t = 0.0; t <= NUM_SAMPLES; t++)\n    {\n        float percent = (t + offset) / NUM_SAMPLES;\n        float weight = 4.0 * (percent - percent * percent);\n        vec4 smpl = texture(tex, texCoord + toCenter * percent * am / texSize);\n\n        smpl.rgb *= smpl.a;\n\n        color += smpl * weight;\n        total += weight;\n    }\n\n    outColor = color / total;\n}"};const i=e.inTrigger("render"),n=e.inValueSlider("Strength",.5),r=e.inInt("Samples",40),a=e.inValue("X",0),s=e.inValue("Y",0),o=e.inTexture("Strength Map"),l=e.inSwitch("Source Strength Map",["R","G","B","A","Lum"],"R"),u=e.inBool("Invert Strength Map",false),h=e.outTrigger("trigger");e.setPortGroup("Strengh Map",[o,l,u]);const p=e.patch.cgl;const c=new CGL.Shader(p,"zoomblur");c.setSource(c.getDefaultVertexShader(),t.zoomblur_frag);const m=new CGL.Uniform(c,"t","tex",0),f=new CGL.Uniform(c,"t","texMask",1),d=new CGL.Uniform(c,"f","x",a),g=new CGL.Uniform(c,"f","y",s),v=new CGL.Uniform(c,"f","strength",n);r.onChange=l.onChange=u.onChange=o.onChange=y;y();function y(){c.toggleDefine("HAS_MASK",o.isLinked());c.toggleDefine("MASK_SRC_R",l.get()=="R");c.toggleDefine("MASK_SRC_G",l.get()=="G");c.toggleDefine("MASK_SRC_B",l.get()=="B");c.toggleDefine("MASK_SRC_A",l.get()=="A");c.toggleDefine("MASK_SRC_LUM",l.get()=="Lum");c.toggleDefine("MASK_INV",u.get());c.define("NUM_SAMPLES",r.get()+".0");l.setUiAttribs({greyout:!o.isLinked()});u.setUiAttribs({greyout:!o.isLinked()})}i.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;if(n.get()>0){p.pushShader(c);p.currentTextureEffect.bind();p.setTexture(0,p.currentTextureEffect.getCurrentSourceTexture().tex);if(o.get()&&o.get().tex)p.setTexture(1,o.get().tex);p.currentTextureEffect.finish();p.popShader()}h.trigger()}};Ops.Gl.ImageCompose.ZoomBlur_v2.prototype=new CABLES.Op;CABLES.OPS["b720a2f5-5501-48ef-90de-94a280ba6fbd"]={f:Ops.Gl.ImageCompose.ZoomBlur_v2,objName:"Ops.Gl.ImageCompose.ZoomBlur_v2"};Ops.Array.PointArray.PointsSphereRandom=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const s=e.inValueInt("Amount of points",100),o=e.inValue("Sphere size",1),l=e.inValue("Random seed",0),u=e.inValueSlider("Random distance from sphere",0),h=e.inValueSelect("Distribution",["Uniform","Poles","Half"],"Uniform"),p=e.outArray("Array out",3),c=e.outNumber("Total points"),m=e.outNumber("Array length");let i=[];p.set(i);l.onChange=s.onChange=o.onChange=h.onChange=u.onChange=p.onLinkChanged=n;n();function n(){const t=[];t.length=Math.max(0,Math.round(s.get())*3);Math.randomSeed=l.get();let i=quat.create();let n=vec3.create();let r=0;if(h.get()=="Poles")r=1;if(h.get()=="Half")r=2;let a=u.get();for(let e=0;e<s.get();e++){if(r==1||r==2){i[0]=Math.seededRandom();i[1]=Math.seededRandom();i[2]=Math.seededRandom();i[3]=Math.seededRandom()}else{i[0]=Math.seededRandom()*2-1;i[1]=Math.seededRandom()*2-1;i[2]=Math.seededRandom()*2-1;i[3]=Math.seededRandom()*2-1}quat.normalize(i,i);if(r==2){n[0]=o.get()}else{if(e%2===0)n[0]=-o.get();else n[0]=o.get()}n[1]=0;n[2]=0;if(a!==0)n[0]-=Math.random()*a;vec3.transformQuat(n,n,i);t[e*3]=n[0];t[e*3+1]=n[1];t[e*3+2]=n[2]}p.set(null);p.set(t);c.set(t.length/3);m.set(t.length)}};Ops.Array.PointArray.PointsSphereRandom.prototype=new CABLES.Op;CABLES.OPS["1ea17de7-adad-4053-943a-4874bccf54e9"]={f:Ops.Array.PointArray.PointsSphereRandom,objName:"Ops.Array.PointArray.PointsSphereRandom"};Ops.Gl.Meshes.PointCloudFromArray_v2=function(){CABLES.Op.apply(this,arguments);const r=this;const e=r.attachments={};const t=r.inTrigger("exe"),a=r.inArray("Array",3),i=r.inValueInt("Num Points"),n=r.outTrigger("Trigger out"),s=r.outObject("Geometry"),o=r.inValueBool("Scramble Texcoords",true),l=r.inValue("Seed",1),u=r.inArray("Coordinates",2),h=r.inArray("Point sizes",1),p=r.inArray("Vertex Colors",4);r.toWorkPortsNeedToBeLinked(a,t);r.setPortGroup("Texture Coordinates",[o,l,u]);const c=r.patch.cgl;const m=new CGL.Geometry("pointcloudfromarray");let f=false;let d=null;let g=[];let v=true;let y=false;a.setUiAttribs({title:"Positions"});u.setUiAttribs({title:"Texture Coordinates"});r.onDelete=T;u.onChange=o.onChange=A;p.onChange=S;i.onChange=C;h.onChange=_;l.onChange=a.onChange=p.onLinkChanged=h.onLinkChanged=x;t.onTriggered=b;function b(){let e=c.getShader();if(CABLES.UI&&e){if(e.glPrimitive!=c.gl.POINTS)r.setUiError("nopointmat","Using a Material not made for point rendering. Try to use PointMaterial.");else r.setUiError("nopointmat",null)}if(v||!d)I();if(!f&&d)d.render(e);n.trigger()}function x(){f=a.get()==null;if(!f)v=true;else v=false}function A(){if(u.isLinked()){l.setUiAttribs({greyout:true});o.setUiAttribs({greyout:true})}else{o.setUiAttribs({greyout:false});if(!o.get())l.setUiAttribs({greyout:true});else l.setUiAttribs({greyout:false})}T();v=true}function _(){if(!h.get())return;if(!m.getAttribute("attrPointSize"))x();if(d)d.setAttribute("attrPointSize",h.get(),1)}function S(){v=true}function C(){if(d){d.setNumVertices(Math.min(m.vertices.length/3,i.get()));if(i.get()==0)d.setNumVertices(m.vertices.length/3)}}function T(){if(d)d.dispose();d=null}function I(){let t=a.get()||[];if(t.length%3!==0){r.setUiError("div3","Array length not multiple of 3");return}else r.setUiError("div3",null);if(m.vertices.length==t.length&&d&&!u.isLinked()&&!p.isLinked()&&!m.getAttribute("attrPointSize")){d.setAttribute(CGL.SHADERVAR_VERTEX_POSITION,t,3);m.vertices=t;v=false;return}m.clear();let i=t.length/3;i=Math.abs(Math.floor(i));if(i==0)return;if(!g||g.length!=i*2)g=new Float32Array(i*2);let n=o.get();if(!u.isLinked()){Math.randomSeed=l.get();g=[];for(let e=0;e<i;e++){if(m.vertices[e*3]!=t[e*3]||m.vertices[e*3+1]!=t[e*3+1]||m.vertices[e*3+2]!=t[e*3+2]){if(n){g[e*2]=Math.seededRandom();g[e*2+1]=Math.seededRandom()}else{g[e*2]=e/i;g[e*2+1]=e/i}}}}if(p.get()){if(p.get().length!=i*4){r.setUiError("vertColWrongLength","Color array does not have the correct length! (should be "+i*4+")");T();return}else r.setUiError("vertColWrongLength",null);m.vertexColors=p.get()}else{r.setUiError("vertColWrongLength",null);m.vertexColors=[]}if(h.get()){if(h.get().length!=i){r.setUiError("pointsizeWrongLength","Color array does not have the correct length! (should be "+i+")");T();return}else r.setUiError("pointsizeWrongLength",null);m.setAttribute("attrPointSize",h.get(),1)}else{r.setUiError("pointsizeWrongLength",null);m.setAttribute("attrPointSize",[],1)}if(u.isLinked())g=u.get();m.setPointVertices(t);m.setTexCoords(g);if(!d)d=new CGL.Mesh(c,m,{glPrimitive:c.gl.POINTS});d.addVertexNumbers=true;d.setGeom(m);s.setRef(m);C();v=false}};Ops.Gl.Meshes.PointCloudFromArray_v2.prototype=new CABLES.Op;CABLES.OPS["53bc6de5-8d22-4687-9f03-ccfd3e50d106"]={f:Ops.Gl.Meshes.PointCloudFromArray_v2,objName:"Ops.Gl.Meshes.PointCloudFromArray_v2"};Ops.Gl.Shader.PointMaterial_v6=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={pointmat_frag:"\n{{MODULES_HEAD}}\n\nUNI vec4 color;\nUNI float atlasNumX;\n\n// IN vec2 pointCoord;\nIN float ps;\nIN vec2 texCoord;\n\n#ifdef HAS_TEXTURE_DIFFUSE\n    UNI sampler2D diffTex;\n#endif\n#ifdef HAS_TEXTURE_MASK\n    UNI sampler2D texMask;\n#endif\n#ifdef HAS_TEXTURE_COLORIZE\n    IN vec4 colorize;\n#endif\n#ifdef HAS_TEXTURE_OPACITY\n    IN float opacity;\n#endif\n\n#ifdef HAS_TEXTURE_ROT\n    UNI sampler2D texRot;\n#endif\n\n\n#ifdef USE_ATLAS\n    IN float randAtlas;\n    #ifdef HAS_TEXTURE_ATLASLOOKUP\n        UNI sampler2D texAtlasLookup;\n    #endif\n#endif\n\n\n#ifdef VERTEX_COLORS\n    IN vec4 vertexColor;\n#endif\n\nvec3 lumcoeff = vec3(0.299,0.587,0.114);\n\n#define PI 3.14159265\n#define TAU (2.0*PI)\n\nvoid pR(inout vec2 p, float a)\n{\n\tp = cos(a)*p + sin(a)*vec2(p.y, -p.x);\n}\n\n\nvoid main()\n{\n    #ifdef FLIP_TEX\n        vec2 pointCoord=vec2(gl_PointCoord.x,(1.0-gl_PointCoord.y));\n    #endif\n    #ifndef FLIP_TEX\n        vec2 pointCoord=gl_PointCoord;\n    #endif\n\n    #ifdef HAS_TEXTURE_ROT\n        float r=texture(texRot,texCoord).r;\n        pointCoord-=vec2(0.5);\n        pR(pointCoord,r*TAU);\n        pointCoord+=vec2(0.5);\n    #endif\n\n    vec2 origPointCoord=pointCoord;\n\n\n    #ifdef USE_ATLAS\n\n        float atlasIdx=randAtlas;\n\n        #ifdef HAS_TEXTURE_ATLASLOOKUP\n            atlasIdx=texture(texAtlasLookup,texCoord).r;\n        #endif\n\n        #ifdef ATLAS_XFADE\n            vec2 pointCoord2=vec2(origPointCoord);\n            pointCoord2.x=origPointCoord.x/atlasNumX+ceil(atlasIdx)*(1.0/atlasNumX);\n        #endif\n\n        pointCoord.x=origPointCoord.x/atlasNumX+floor(atlasIdx)*(1.0/atlasNumX);\n\n\n    #endif\n\n    {{MODULE_BEGIN_FRAG}}\n\n    if(ps<1.0)discard;\n\n    vec4 col=color;\n\n    #ifdef HAS_TEXTURE_MASK\n        float mask;\n        #ifdef TEXTURE_MASK_R\n            mask=texture(texMask,pointCoord).r;\n        #endif\n        #ifdef TEXTURE_MASK_A\n            mask=texture(texMask,pointCoord).a;\n        #endif\n        #ifdef TEXTURE_MASK_LUMI\n        \tmask = dot(texture(texMask,pointCoord).rgb, lumcoeff);\n        #endif\n\n        #ifdef ATLAS_XFADE\n            float mask2=texture(texMask,pointCoord2).r;\n\n            #ifdef TEXTURE_MASK_A\n                mask2=texture(texMask,pointCoord2).a;\n            #endif\n            #ifdef TEXTURE_MASK_LUMI\n            \tmask2 = dot(texture(texMask,pointCoord2).rgb, lumcoeff);\n            #endif\n\n            mask=mix(mask,mask2,fract(atlasIdx));\n        #endif\n    #endif\n\n    #ifdef HAS_TEXTURE_DIFFUSE\n\n        col=texture(diffTex,pointCoord);\n\n        #ifdef ATLAS_XFADE\n            vec4 col2=texture(diffTex,pointCoord2);\n            col=mix(col,col2,fract(atlasIdx));\n        #endif\n\n        #ifdef COLORIZE_TEXTURE\n            col.rgb*=color.rgb;\n        #endif\n    #endif\n\n    col.a*=color.a;\n\n\n    #ifdef MAKE_ROUND\n\n        #ifndef MAKE_ROUNDAA\n            if ((gl_PointCoord.x-0.5)*(gl_PointCoord.x-0.5) + (gl_PointCoord.y-0.5)*(gl_PointCoord.y-0.5) > 0.25) discard; //col.a=0.0;\n        #endif\n\n        #ifdef MAKE_ROUNDAA\n            float circ=(gl_PointCoord.x-0.5)*(gl_PointCoord.x-0.5) + (gl_PointCoord.y-0.5)*(gl_PointCoord.y-0.5);\n\n            float a=smoothstep(0.25,0.25-fwidth(gl_PointCoord.x),circ);\n            if(a==0.0)discard;\n            col.a=a*color.a;\n        #endif\n    #endif\n\n    #ifdef HAS_TEXTURE_COLORIZE\n        col*=colorize;\n    #endif\n\n    #ifdef TEXTURE_COLORIZE_MUL\n        col*=color;\n    #endif\n\n    #ifdef HAS_TEXTURE_MASK\n        col.a*=mask;\n    #endif\n\n    #ifdef HAS_TEXTURE_OPACITY\n        col.a*=opacity;\n    #endif\n\n    #ifdef VERTEX_COLORS\n        col.rgb = vertexColor.rgb;\n        col.a *= vertexColor.a;\n    #endif\n\n    if (col.a <= 0.0) discard;\n\n    #ifdef HAS_TEXTURE_COLORIZE\n        col*=colorize;\n    #endif\n\n    {{MODULE_COLOR}}\n\n\n    outColor = col;\n}\n",pointmat_vert:"{{MODULES_HEAD}}\n\n\n\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\nIN vec3 attrTangent;\nIN vec3 attrBiTangent;\nIN float attrPointSize;\n\n#ifdef VERTEX_COLORS\n    IN vec4 attrVertColor;\n    OUT vec4 vertexColor;\n#endif\n\nOUT vec3 norm;\nOUT float ps;\n\nOUT vec2 texCoord;\n\n\n#ifdef HAS_TEXTURES\n#endif\n\n#ifdef HAS_TEXTURE_COLORIZE\n   UNI sampler2D texColorize;\n   OUT vec4 colorize;\n#endif\n#ifdef HAS_TEXTURE_OPACITY\n    UNI sampler2D texOpacity;\n    OUT float opacity;\n#endif\n\n#ifdef HAS_TEXTURE_POINTSIZE\n   UNI sampler2D texPointSize;\n   UNI float texPointSizeMul;\n#endif\n\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\nUNI float pointSize;\nUNI vec3 camPos;\n\nUNI float canvasWidth;\nUNI float canvasHeight;\nUNI float camDistMul;\nUNI float randomSize;\nUNI float minPointSize;\nUNI float pixelRatio;\n\nIN float attrVertIndex;\n\nUNI float atlasNumX;\n\n#ifdef USE_ATLAS\n    OUT float randAtlas;\n#endif\n\nfloat rand(float n){return fract(sin(n) * 5711.5711123);}\n\n#define POINTMATERIAL\n\nvoid main()\n{\n    norm=attrVertNormal;\n    #ifdef PIXELSIZE\n        float psMul=1.0;\n    #endif\n\n    #ifndef PIXELSIZE\n        float psMul=sqrt(canvasWidth/canvasHeight)+0.00000000001;\n    #endif\n\n    #ifdef USE_ATLAS\n        randAtlas=atlasNumX*rand(attrVertIndex+vPosition.x);\n    #endif\n\n    vec3 tangent=attrTangent;\n    vec3 bitangent=attrBiTangent;\n\n\n    #ifdef VERTEX_COLORS\n        vertexColor=attrVertColor;\n    #endif\n\n    // #ifdef HAS_TEXTURES\n        texCoord=attrTexCoord;\n    // #endif\n\n    #ifdef HAS_TEXTURE_OPACITY\n        // opacity=texture(texOpacity,vec2(rand(attrVertIndex+texCoord.x*texCoord.y+texCoord.y+texCoord.x),rand(texCoord.y*texCoord.x-texCoord.x-texCoord.y-attrVertIndex))).r;\n        opacity=texture(texOpacity,texCoord).r;\n    #endif\n\n\n    #ifdef HAS_TEXTURE_COLORIZE\n        #ifdef RANDOM_COLORIZE\n            colorize=texture(texColorize,vec2(rand(attrVertIndex+texCoord.x*texCoord.y+texCoord.y+texCoord.x),rand(texCoord.y*texCoord.x-texCoord.x-texCoord.y-attrVertIndex)));\n        #endif\n        #ifndef RANDOM_COLORIZE\n            colorize=texture(texColorize,texCoord);\n        #endif\n    #endif\n\n\n\n\n\n    mat4 mMatrix=modelMatrix;\n    vec4 pos = vec4( vPosition, 1. );\n\n    gl_PointSize=0.0;\n\n    {{MODULE_VERTEX_POSITION}}\n\n    vec4 model=mMatrix * pos;\n\n    psMul+=rand(texCoord.x*texCoord.y+texCoord.y*3.0+texCoord.x*2.0+attrVertIndex)*randomSize;\n\n    float addPointSize=0.0;\n    #ifdef HAS_TEXTURE_POINTSIZE\n\n        #ifdef POINTSIZE_CHAN_R\n            addPointSize=texture(texPointSize,texCoord).r;\n        #endif\n        #ifdef POINTSIZE_CHAN_G\n            addPointSize=texture(texPointSize,texCoord).g;\n        #endif\n        #ifdef POINTSIZE_CHAN_B\n            addPointSize=texture(texPointSize,texCoord).b;\n        #endif\n\n        #ifdef DOTSIZEREMAPABS\n            addPointSize=1.0-(distance(addPointSize,0.5)*2.0);\n            addPointSize=addPointSize*addPointSize*addPointSize*2.0;\n        #endif\n\n        addPointSize*=texPointSizeMul;\n\n    #endif\n\n    ps=0.0;\n    #ifndef SCALE_BY_DISTANCE\n        ps = (pointSize+addPointSize+attrPointSize) * psMul;\n    #endif\n    #ifdef SCALE_BY_DISTANCE\n        float cameraDist = distance(model.xyz, camPos);\n        ps = ( (pointSize+addPointSize+attrPointSize) / cameraDist) * psMul;\n    #endif\n    ps=max(minPointSize,ps);\n    ps*=pixelRatio;\n\n    gl_PointSize += ps;\n\n\n    gl_Position = projMatrix * viewMatrix * model;\n}\n"};const i=e.patch.cgl;const n=e.inTrigger("render"),r=e.inValueFloat("PointSize",3),a=e.inBool("Size in Pixels",false),s=e.inValue("Random Size",0),o=e.inValueBool("Round",true),l=e.inValueBool("Round Antialias",false),u=e.inValueBool("Scale by Distance",false),h=e.inValueSlider("r",Math.random()),p=e.inValueSlider("g",Math.random()),c=e.inValueSlider("b",Math.random()),m=e.inValueSlider("a",1),f=e.inBool("Vertex Colors",false),d=e.inTexture("texture"),g=e.inBool("Colorize Texture"),v=e.inTexture("Texture Mask"),y=e.inSwitch("Mask Channel",["R","A","Luminance"],"R"),b=e.inTexture("Texture Colorize"),x=e.inValueBool("Colorize Randomize",false),A=e.inTexture("Texture Opacity"),_=e.inTexture("Texture Point Size"),S=e.inSwitch("Point Size Channel",["R","G","B"],"R"),C=e.inFloat("Texture Point Size Mul",1),T=e.inSwitch("Map Size 0",["Black","Grey"],"Black"),I=e.inValueBool("Flip Texture",false),O=e.inBool("Atlas Cross Fade",false),E=e.inFloat("Atlas Repeat X ",1),P=e.inTexture("Atlas Lookup"),M=e.inTexture("Rotate Texture"),V=e.inValueFloat("Min Point Size",0),D=e.outTrigger("trigger"),L=e.outObject("shader",null,"shader");e.setPortGroup("Texture",[d,g,v,y,b,A,x]);e.setPortGroup("Color",[h,p,c,m,f]);e.setPortGroup("Size",[r,s,o,l,u,a,_,C,S,T]);e.setPortGroup("Atlas",[E,P,O]);h.setUiAttribs({colorPick:true});const N=new CGL.Shader(i,"PointMaterial",this);N.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"]);N.define("MAKE_ROUND");e.toWorkPortsNeedToBeLinked(n);const B=new CGL.Uniform(N,"f","pointSize",r),j=new CGL.Uniform(N,"f","texPointSizeMul",C),F=new CGL.Uniform(N,"f","randomSize",s),U=new CGL.Uniform(N,"f","minPointSize",V),G=new CGL.Uniform(N,"4f","color",h,p,c,m),z=new CGL.Uniform(N,"f","atlasNumX",E),q=new CGL.Uniform(N,"f","pixelRatio",1),X=new CGL.Uniform(N,"f","canvasWidth",i.canvasWidth),H=new CGL.Uniform(N,"f","canvasHeight",i.canvasHeight),Y=new CGL.Uniform(N,"t","diffTex"),W=new CGL.Uniform(N,"t","texColorize"),K=new CGL.Uniform(N,"t","texOpacity"),Z=new CGL.Uniform(N,"t","texPointSize"),Q=new CGL.Uniform(N,"t","texPointSize"),J=new CGL.Uniform(N,"t","texMask"),$=new CGL.Uniform(N,"t","texAtlasLookup"),ee=new CGL.Uniform(N,"t","texRot");N.setSource(t.pointmat_vert,t.pointmat_frag);N.glPrimitive=i.gl.POINTS;L.set(N);L.ignoreValueSerialize=true;u.onChange=E.onChange=o.onChange=l.onChange=d.onChange=b.onChange=v.onChange=x.onChange=I.onChange=y.onChange=a.onChange=A.onChange=_.onChange=T.onChange=S.onChange=g.onChange=P.onLinkChanged=M.onLinkChanged=f.onChange=te;n.onTriggered=k;R();e.preRender=function(){if(N)N.bind();k()};function k(){X.setValue(i.canvasWidth);H.setValue(i.canvasHeight);i.pushShader(N);N.popTextures();if(d.get()&&!d.get().deleted)N.pushTexture(Y,d.get());if(v.get())N.pushTexture(J,v.get());if(b.get())N.pushTexture(W,b.get());if(A.get())N.pushTexture(K,A.get());if(_.get())N.pushTexture(Q,_.get());if(P.get())N.pushTexture($,P.get());if(M.get())N.pushTexture(ee,M.get());q.set(i.pixelDensity);D.trigger();i.popShader()}function w(){return E.get()>0||P.isLinked()}function R(){E.setUiAttribs({greyout:!w()});y.setUiAttribs({greyout:!v.isLinked()});S.setUiAttribs({greyout:!_.isLinked()});C.setUiAttribs({greyout:!_.isLinked()});T.setUiAttribs({greyout:!_.isLinked()})}function te(){N.toggleDefine("USE_ATLAS",w());N.toggleDefine("SCALE_BY_DISTANCE",u.get());N.toggleDefine("MAKE_ROUND",o.get());N.toggleDefine("MAKE_ROUNDAA",l.get());N.toggleDefine("ATLAS_XFADE",O.get());N.toggleDefine("VERTEX_COLORS",f.get());N.toggleDefine("RANDOM_COLORIZE",x.get());N.toggleDefine("HAS_TEXTURE_DIFFUSE",d.get());N.toggleDefine("HAS_TEXTURE_MASK",v.isLinked());N.toggleDefine("HAS_TEXTURE_COLORIZE",b.isLinked());N.toggleDefine("HAS_TEXTURE_OPACITY",A.isLinked());N.toggleDefine("HAS_TEXTURE_POINTSIZE",_.isLinked());N.toggleDefine("HAS_TEXTURE_ATLASLOOKUP",P.isLinked());N.toggleDefine("HAS_TEXTURE_ROT",M.isLinked());N.toggleDefine("TEXTURE_COLORIZE_MUL",g.get());N.toggleDefine("FLIP_TEX",I.get());N.toggleDefine("TEXTURE_MASK_R",y.get()=="R");N.toggleDefine("TEXTURE_MASK_A",y.get()=="A");N.toggleDefine("TEXTURE_MASK_LUMI",y.get()=="Luminance");N.toggleDefine("PIXELSIZE",a.get());N.toggleDefine("POINTSIZE_CHAN_R",S.get()=="R");N.toggleDefine("POINTSIZE_CHAN_G",S.get()=="G");N.toggleDefine("POINTSIZE_CHAN_B",S.get()=="B");N.toggleDefine("DOTSIZEREMAPABS",T.get()=="Grey");R()}};Ops.Gl.Shader.PointMaterial_v6.prototype=new CABLES.Op;CABLES.OPS["e44df958-00c7-46e4-95bb-3e6ac6c4188f"]={f:Ops.Gl.Shader.PointMaterial_v6,objName:"Ops.Gl.Shader.PointMaterial_v6"};Ops.Gl.Meshes.Sphere_v3=function(){CABLES.Op.apply(this,arguments);const A=this;const e=A.attachments={};const _=Math.PI*2,t=A.inTrigger("render"),S=A.inValue("radius",.5),C=A.inValue("stacks",32),T=A.inValue("slices",32),I=A.inValueSlider("Filloffset",1),i=A.inValueBool("Render",true),n=A.outTrigger("trigger"),O=A.outObject("geometry",null,"geometry"),E=vec3.fromValues(0,1,0),P=vec3.fromValues(1,0,0);let r=null,M=new CGL.Geometry("Sphere"),L=vec3.create(),N=vec3.create(),k=true,w=0,R=true,a=vec3.create(),V=null;s();A.onDelete=function(){if(V)V.dispose()};t.onTriggered=function(){r=A.patch.cg||A.patch.cgl;if(k)o();if(R){r.pushModelMatrix();mat4.scale(r.mMatrix,r.mMatrix,a)}if(i.get())V.render(r.getShader());if(R){r.popModelMatrix()}n.trigger()};C.onChange=T.onChange=I.onChange=()=>{k=true};O.onLinkChanged=S.onChange=()=>{if(O.isLinked())R=false;else R=true;if(R)s();else k=true};function s(){if(R&&w!=1)k=true;vec3.set(a,S.get(),S.get(),S.get())}function o(){const e=Math.ceil(Math.max(C.get(),2)),t=Math.ceil(Math.max(T.get(),3)),i=Math.min(Math.max(I.get()*e,1),e);let n=S.get();if(R)n=1;w=n;let r=[],a=[],s=[],o=[],l=[],u=[],h,p,c,m,f,d,g,v,y,b,x;for(b=g=0;b<e+1;b++){y=(b/e-.5)*Math.PI;p=Math.sin(y);d=Math.cos(y);for(x=t;x>=0;x--){v=x/t*_;h=Math.cos(v)*d;c=Math.sin(v)*d;r.push(h*n,p*n,c*n);a.push(x/t,b/(e+1));m=Math.sqrt(h*h+p*p+c*c);s.push(L[0]=h/m,L[1]=p/m,L[2]=c/m);if(p==m)f=P;else f=E;vec3.cross(N,L,f);vec3.normalize(N,N);Array.prototype.push.apply(o,N);vec3.cross(N,N,L);Array.prototype.push.apply(l,N)}if(b==0||b>i)continue;for(x=0;x<t;x++,g++){u.push(g,g+1,g+t+1,g+1,g+t+2,g+t+1)}g++}M.clear();M.vertices=r;M.texCoords=a;M.vertexNormals=s;M.tangents=o;M.biTangents=l;M.verticesIndices=u;O.setRef(M);if(A.patch.cg)if(!V)V=A.patch.cg.createMesh(M,{opId:A.id});else V.setGeom(M);k=false}};Ops.Gl.Meshes.Sphere_v3.prototype=new CABLES.Op;CABLES.OPS["6ee346d0-614e-4709-91a5-dc21ae975caf"]={f:Ops.Gl.Meshes.Sphere_v3,objName:"Ops.Gl.Meshes.Sphere_v3"};Ops.Gl.ImageCompose.Wobble_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={wobble_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D texMask;\nUNI float time;\nUNI float speedX;\nUNI float speedY;\nUNI float repeatX;\nUNI float repeatY;\nUNI float mul;\n\n{{CGL.LUMINANCE}}\n\nvoid main()\n{\n    float mult=1.0;\n    #ifdef HAS_MASK\n        #ifdef MASK_SRC_R\n            mult*=texture(texMask,texCoord).r;\n        #endif\n        #ifdef MASK_SRC_G\n            mult*=texture(texMask,texCoord).g;\n        #endif\n        #ifdef MASK_SRC_B\n            mult*=texture(texMask,texCoord).b;\n        #endif\n        #ifdef MASK_SRC_A\n            mult*=texture(texMask,texCoord).a;\n        #endif\n        #ifdef MASK_SRC_LUM\n            mult*=cgl_luminance(texture(texMask,texCoord).rgb);\n        #endif\n        #ifdef MASK_INV\n            mult=1.0-mult;\n        #endif\n    #endif\n\n    mult*=mul;\n\n    vec2 tc = texCoord + cos( (time*vec2(speedX, speedY) + vec2(texCoord.s*repeatX,texCoord.t*repeatY)))*mult;\n    vec4 col=texture(tex,tc);\n\n    outColor= col;\n}"};const i=e.inTrigger("Render"),n=e.inValue("time",0),r=e.inValue("SpeedX",4),a=e.inValue("SpeedY",8),s=e.inValue("RepeatX",11),o=e.inValue("RepeatY",11),l=e.inValue("Multiply",.01),u=e.inTexture("Amount Map"),h=e.inSwitch("Source Amount Map",["R","G","B","A","Lum"],"R"),p=e.inBool("Invert Amount Map",false),c=e.outTrigger("Trigger");e.setPortGroup("Amount Map",[u,h,p]);const m=e.patch.cgl;const f=new CGL.Shader(m,e.name,e);f.setSource(f.getDefaultVertexShader(),t.wobble_frag);const d=new CGL.Uniform(f,"t","tex",0),g=new CGL.Uniform(f,"f","time",n),v=new CGL.Uniform(f,"f","speedX",r),y=new CGL.Uniform(f,"f","speedY",a),b=new CGL.Uniform(f,"f","repeatX",s),x=new CGL.Uniform(f,"f","repeatY",o),A=new CGL.Uniform(f,"f","mul",l),_=new CGL.Uniform(f,"t","texMask",1);u.onChange=h.onChange=p.onChange=()=>{f.toggleDefine("HAS_MASK",u.isLinked());f.toggleDefine("MASK_SRC_R",h.get()=="R");f.toggleDefine("MASK_SRC_G",h.get()=="G");f.toggleDefine("MASK_SRC_B",h.get()=="B");f.toggleDefine("MASK_SRC_A",h.get()=="A");f.toggleDefine("MASK_SRC_LUM",h.get()=="Lum");f.toggleDefine("MASK_INV",p.get());h.setUiAttribs({greyout:!u.isLinked()});p.setUiAttribs({greyout:!u.isLinked()})};i.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;m.pushShader(f);m.currentTextureEffect.bind();m.setTexture(0,m.currentTextureEffect.getCurrentSourceTexture().tex);if(u.get())m.setTexture(1,u.get().tex);m.currentTextureEffect.finish();m.popShader();c.trigger()}};Ops.Gl.ImageCompose.Wobble_v2.prototype=new CABLES.Op;CABLES.OPS["04a8a8bc-feb9-4791-8724-ee24bbb150db"]={f:Ops.Gl.ImageCompose.Wobble_v2,objName:"Ops.Gl.ImageCompose.Wobble_v2"};Ops.Anim.Smooth=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTrigger("Update"),n=e.inBool("Separate inc/dec",false),r=e.inValue("Value"),a=e.outTrigger("Next"),s=e.inValue("Inc factor",4),o=e.inValue("Dec factor",4),l=e.outNumber("Result",0);let u=0;let h=0;let p=0;let c=0;e.toWorkPortsNeedToBeLinked(i);let m;let f;let d=4;let g=true;let v=0;const y=0;const b=1;x();A();n.setUiAttribs({hidePort:true});s.onChange=o.onChange=A;n.onChange=x;_();function x(){const e=n.get();if(!e)v=y;else v=b;if(v==y){o.setUiAttribs({greyout:true});s.setUiAttribs({title:"Inc/Dec factor"})}else if(v==b){o.setUiAttribs({greyout:false});s.setUiAttribs({title:"Inc factor"})}A();_()}function A(){if(v==y){m=s.get();f=s.get()}else if(v==b){m=s.get();f=o.get()}if(m<=.2||m!=m)m=.2;if(f<=.2||f!=f)f=.2}r.onChange=function(){g=false;let e=h;h=r.get()};s.onChange=function(){A()};function _(){let e=1;if(performance.now()-c>500||c===0)u=r.get()||0;else e=(performance.now()-c)/(performance.now()-c);c=performance.now();if(u!=u)u=0;if(d<=0)d=1e-4;const t=h-u;if(t>=0)u+=t/(f*e);else u+=t/(m*e);if(Math.abs(t)<1e-5)u=h;if(d!=d)u=0;if(u!=u||u==-Infinity||u==Infinity)u=r.get();if(p!=u){l.set(u);p=u}if(u==h&&!g){g=true;l.set(u)}a.trigger()}i.onTriggered=function(){_()}};Ops.Anim.Smooth.prototype=new CABLES.Op;CABLES.OPS["5677b5b5-753a-4fbf-9e91-64c81ec68a2f"]={f:Ops.Anim.Smooth,objName:"Ops.Anim.Smooth"};Ops.Gl.ImageCompose.Noise.Noise_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={noise_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float time;\nUNI float thresh;\n\n#ifdef HAS_MULMASK\n    UNI sampler2D texMul;\n#endif\n\n{{CGL.BLENDMODES3}}\n{{MODULES_HEAD}}\n\n{{CGL.RANDOM_TEX}}\n\nvoid main()\n{\n    vec4 rnd;\n\n    #ifdef RGB\n        rnd=vec4(cgl_random3(texCoord.xy+vec2(time)),1.0);\n    #else\n        float r=cgl_random(texCoord.xy+vec2(time));\n        rnd=vec4( r,r,r,1.0 );\n    #endif\n\n    vec4 base=texture(tex,texCoord);\n    vec4 col=rnd;//( _blend(base.rgb,rnd.rgb) ,1.0);\n\n    #ifdef NORMALIZE\n        col.rgb=(col.rgb-0.5)*2.0;\n    #endif\n\n    #ifdef HAS_MULMASK\n        col.rgb*=texture(texMul,texCoord).rgb;\n    #endif\n\n    col*=step(thresh,cgl_random(texCoord.xy*11.0+vec2(time)));\n\n\n    outColor=cgl_blendPixel(base,col,amount);\n}"};const i=e.inTrigger("Render"),n=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),r=CGL.TextureEffect.AddBlendAlphaMask(e),a=e.inValueSlider("Amount",1),s=e.inValueSlider("Threshold",0),o=e.inValueBool("Animated",true),l=e.inValueBool("RGB",false),u=e.inValueBool("Normalize",false),h=e.inTexture("Multiply"),p=e.outTrigger("Next");const c=e.patch.cgl,m=new CGL.Shader(c,e.name),f=new CGL.Uniform(m,"f","amount",a),d=new CGL.Uniform(m,"f","time",1),g=new CGL.Uniform(m,"f","thresh",s),v=new CGL.Uniform(m,"t","tex",0),y=new CGL.Uniform(m,"t","texMul",1);m.setSource(m.getDefaultVertexShader(),t.noise_frag);CGL.TextureEffect.setupBlending(e,m,n,a,r);e.toWorkPortsNeedToBeLinked(i);h.onChange=u.onChange=l.onChange=function(){m.toggleDefine("HAS_MULMASK",h.get());m.toggleDefine("RGB",l.get());m.toggleDefine("NORMALIZE",u.get())};i.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;if(o.get())d.setValue(e.patch.freeTimer.get()/1e3%100);else d.setValue(0);c.pushShader(m);c.setTexture(0,c.currentTextureEffect.getCurrentSourceTexture().tex);if(h.get())c.setTexture(1,h.get().tex);c.currentTextureEffect.bind();c.currentTextureEffect.finish();c.popShader();p.trigger()}};Ops.Gl.ImageCompose.Noise.Noise_v2.prototype=new CABLES.Op;CABLES.OPS["b1d9aacc-dc52-43a6-a00f-414f08768800"]={f:Ops.Gl.ImageCompose.Noise.Noise_v2,objName:"Ops.Gl.ImageCompose.Noise.Noise_v2"};Ops.TimeLine.DemoPrerender=function(){CABLES.Op.apply(this,arguments);const r=this;const e=r.attachments={};const t=r.inTrigger("Render"),i=r.inArray("Times"),n=r.inArray("Manual Timestamps"),a=r.inBool("Record Events",false),s=r.inTriggerButton("Reset"),o=r.inTriggerButton("Clear"),l=r.inBool("ReRender on Resize",true),u=r.outTrigger("Next"),h=r.outTrigger("Prerendered Frame"),p=r.outNumber("Progress",0),c=r.outNumber("Num Events");t.onTriggered=_;i.setUiAttribs({hidePort:true,hideParam:true});let m=true;let f=0;let d=false;let g=0;let v=0;let y=[0];r.patch.cgl.on("resize",()=>{if(l.get()){if(!m&&p.get()==1){g=r.patch.timer.getTime();v=r.patch.freeTimer.getTime();m=true;f=0}}});n.onChange=i.onChange=()=>{c.set(A().length);y=i.get()||[0]};r.patch.cgl.on("heavyEvent",e=>{if(a.get()&&!m&&CABLES.uniqueArray){y.push(Math.round(r.patch.timer.getTime()*60)/60);y=CABLES.uniqueArray(y);i.set(y)}});let b=0;s.onTriggered=()=>{m=true};o.onTriggered=()=>{y=[0];i.set(y)};function x(){return b*1e3}function A(){let e=[];e=e.concat(i.get()||[0]);if(n.get())e=e.concat(n.get());return e}function _(){if(a.get()){m=false;p.set(1);u.trigger();return}if(m){let e=A();if(f<e.length){const i=CABLES.internalNow;CABLES.internalNow=x;b=e[f];r.patch._frameNum=f+22;CABLES.overwriteTime=b;r.patch.timer.setTime(b);r.patch.freeTimer.setTime(b);CABLES.overwriteTime=undefined;CABLES.internalNow=i}const t=30;if(f>=e.length){const n=(t-(f-e.length))/t;r.patch.timer.setTime(n);r.patch.freeTimer.setTime(n)}u.trigger();u.trigger();p.set(Math.min(1,f/(e.length+t)));h.trigger();if(f>=e.length+t){r.patch.timer.setTime(g);r.patch.freeTimer.setTime(v);m=false}else f++}else{u.trigger()}}};Ops.TimeLine.DemoPrerender.prototype=new CABLES.Op;CABLES.OPS["962ea9e5-39ee-448c-9a2b-b71ceee47c11"]={f:Ops.TimeLine.DemoPrerender,objName:"Ops.TimeLine.DemoPrerender"};Ops.Math.Compare.GreaterThan=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inValueFloat("number1"),n=e.inValueFloat("number2"),r=e.outBoolNum("result");e.setUiAttribs({mathTitle:true});i.onChange=n.onChange=a;function a(){r.set(i.get()>n.get())}};Ops.Math.Compare.GreaterThan.prototype=new CABLES.Op;CABLES.OPS["b250d606-f7f8-44d3-b099-c29efff2608a"]={f:Ops.Math.Compare.GreaterThan,objName:"Ops.Math.Compare.GreaterThan"};Ops.Boolean.TriggerChangedTrue=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};let i=e.inValueBool("Value",false);let n=e.outTrigger("Next");let r=0;i.onChange=function(){let e=i.get();if(!r&&e){r=true;n.trigger()}else{r=false}}};Ops.Boolean.TriggerChangedTrue.prototype=new CABLES.Op;CABLES.OPS["385197e1-8b34-4d1c-897f-d1386d99e3b3"]={f:Ops.Boolean.TriggerChangedTrue,objName:"Ops.Boolean.TriggerChangedTrue"};Ops.Html.Cursor_v2=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const i=t.inTriggerButton("Update"),n=t.inDropDown("CSS Cursors",["auto","crosshair","pointer","hand","move","n-resize","ne-resize","e-resize","se-resize","s-resize","sw-resize","w-resize","nw-resize","ew-resize","text","wait","help","none"],"pointer"),r=t.inBool("Set Parent Element",true),a=t.outTrigger("Next");const s="";i.onTriggered=l;let o="";i.onLinkChanged=a.onLinkChanged=()=>{t.patch.cgl.setCursor("auto")};r.onChange=()=>{if(!r.get()){o="auto";t.patch.cgl.canvas.parentElement.style.cursor="auto"}};function l(){let e=null;t.patch.cgl.setCursor(n.get(),e);if(r.get()&&o!=n.get())t.patch.cgl.canvas.parentElement.style.cursor=n.get();a.trigger()}};Ops.Html.Cursor_v2.prototype=new CABLES.Op;CABLES.OPS["39486799-bdad-42d3-a300-4642c23578a8"]={f:Ops.Html.Cursor_v2,objName:"Ops.Html.Cursor_v2"};Ops.TimeLine.TimeLineRewind=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTriggerButton("exe"),n=e.outTrigger("Next");i.onTriggered=function(){e.patch.timer.setTime(0);n.trigger()}};Ops.TimeLine.TimeLineRewind.prototype=new CABLES.Op;CABLES.OPS["d3408604-858c-4226-8d4c-1ef669956f35"]={f:Ops.TimeLine.TimeLineRewind,objName:"Ops.TimeLine.TimeLineRewind"};Ops.Gl.FontMSDF_v2=function(){CABLES.Op.apply(this,arguments);const o=this;const e=o.attachments={};let t=null;let i=null;if(CABLES.UI){t="/assets/library/fonts_msdf/worksans-regular_int.png";i="/assets/library/fonts_msdf/worksans-regular_int.json"}const l=o.inString("Font Name",CABLES.uuid()),u=o.inUrl("Font Data",[".json"],i),h=o.inUrl("Font Image",[".png"],t),p=o.inUrl("Font Image 1",[".png"]),c=o.inUrl("Font Image 2",[".png"]),m=o.inUrl("Font Image 3",[".png"]),f=o.outBool("Loaded"),d=o.outNumber("Total Chars"),g=o.outString("Chars"),v=o.patch.cgl;let y=false,b=false,x=0;l.onChange=u.onChange=h.onChange=p.onChange=c.onChange=m.onChange=n;const A=[];function _(){const e=y&&b;if(!f.get()&&e)o.patch.emitEvent("FontLoadedMSDF");f.set(e)}o.onFileChanged=function(e){if(h.get()&&h.get().indexOf(e)>-1||p.get()&&p.get().indexOf(e)>-1||c.get()&&c.get().indexOf(e)>-1||m.get()&&m.get().indexOf(e)>-1){n()}};function n(){v.addNextFrameOnceCallback(r)}let S="";function r(){if(!u.get()||!h.get())return;A.length=0;o.patch.deleteVar("font_data_"+S);o.patch.deleteVar("font_tex_"+S);S=l.get();const r="font_data_"+l.get();const i="font_tex_"+l.get();o.patch.setVarValue(r,{});o.patch.setVarValue(i,A);o.patch.getVar(r).type="fontData";o.patch.getVar(i).type="fontTexture";y=b=false;_();o.patch.loading.finished(x);x=o.patch.loading.start("jsonFile",""+u.get(),o);o.setUiError("invaliddata",null);o.setUiError("jsonerr",null);o.setUiError("texurlerror",null);const e=o.patch.getFilePath(String(u.get()));v.patch.loading.addAssetLoadingTask(()=>{CABLES.ajax(e,(e,n,t)=>{if(e){return}try{let t=n;if(typeof t==="string")t=JSON.parse(n);if(!t.chars||!t.info||!t.info.face){o.setUiError("invaliddata","data file is invalid");return}d.set(t.chars.length);let i="";for(let e=0;e<t.chars.length;e++)i+=t.chars[e].char;g.set(i);o.setUiAttrib({extendTitle:t.info.face});o.patch.setVarValue(r,null);o.patch.setVarValue(r,{name:CABLES.basename(u.get()),basename:l.get(),data:t});o.patch.loading.finished(x);y=true;_()}catch(e){o.patch.setVarValue(r,null);o.patch.setVarValue(i,null);o.setUiError("jsonerr","Problem while loading json:<br/>"+e);o.patch.loading.finished(x);_();f.set(false)}})});for(let t=0;t<4;t++){const n=t;let e=h;if(t==1)e=p;if(t==2)e=c;if(t==3)e=m;if(!e.get())continue;const a=v.patch.loading.start(o.objName,e.get(),o);const s=o.patch.getFilePath(String(e.get()));CGL.Texture.load(v,s,function(e,t){if(e){o.setUiError("texurlerror","could not load texture");v.patch.loading.finished(a);b=false;return}A[n]=t;o.patch.setVarValue(i,null);o.patch.setVarValue(i,A);b=true;v.patch.loading.finished(a);_()},{filter:CGL.Texture.FILTER_LINEAR,flip:false})}}};Ops.Gl.FontMSDF_v2.prototype=new CABLES.Op;CABLES.OPS["6cbd5d67-25d5-4936-a2ad-3ee8ed478570"]={f:Ops.Gl.FontMSDF_v2,objName:"Ops.Gl.FontMSDF_v2"};Ops.Json.HttpRequest_v3=function(){CABLES.Op.apply(this,arguments);const a=this;const e=a.attachments={};const n=a.inUrl("file"),s=a.inObject("headers",{}),o=a.inStringEditor("body",""),l=a.inDropDown("HTTP Method",["GET","POST","PUT","DELETE","PATCH","HEAD","CONNECT","OPTIONS","TRACE"],"GET"),u=a.inString("Content-Type","application/json"),h=a.inSwitch("Content",["JSON","String","Binary","Binary Base64"],"JSON"),p=a.inBool("Auto request",true),c=a.inBool("Send Credentials",false),t=a.inTriggerButton("reload"),m=a.outObject("Response Json Object"),f=a.outString("Response String"),d=a.outString("Response Data Url"),g=a.outNumber("Duration MS",0),v=a.outNumber("Status Code",0),y=a.outBoolNum("Is Loading",false),b=a.outTrigger("Loaded");h.setUiAttribs({title:"Response Content"});n.setUiAttribs({title:"URL"});t.setUiAttribs({buttonTitle:"trigger request"});m.ignoreValueSerialize=true;f.ignoreValueSerialize=true;f.onLinkChanged=d.onLinkChanged=m.onLinkChanged=x;h.onChange=()=>{const e=h.get()==="Binary";l.setUiAttribs({greyout:e});r(false)};p.onChange=n.onChange=s.onChange=l.onChange=()=>{r(false)};t.onTriggered=()=>{r(true)};let i=0;function r(e=false){clearTimeout(i);i=setTimeout(()=>{A(null,e)},100)}a.onFileChanged=e=>{if(n.get()&&n.get().indexOf(e)>-1)A(true)};function x(){if(!n.get())a.setUiError("nourl","URL is empty",1);else a.setUiError("nourl",null)}function A(e,t=false){if(!p.get()&&!t)return;x();if(!n.get()){return}const r=a.patch.loading.start(a.objName,""+n.get(),a);y.set(true);a.setUiAttrib({extendTitle:CABLES.basename(n.get())});a.setUiError("jsonerr",null);a.setUiError("jsonParse",null);let i=a.patch.getFilePath(n.get());if(e)i+="?rnd="+CABLES.generateUUID();a.patch.loading.addAssetLoadingTask(()=>{const e=o.get();const n=performance.now();const t={};if(c.get())t.credentials="include";if(h.get().contains("Binary")){fetch(i,t).then(e=>{g.set(Math.round(performance.now()-n));v.set(e.status);e.blob().then(e=>{d.set(URL.createObjectURL(e));if(h.get().contains("Base64")){const t=new FileReader;t.onloadend=function(){const e=t.result;d.set(e);y.set(false);b.trigger();a.patch.loading.finished(r)};t.readAsDataURL(e)}else{y.set(false);b.trigger();a.patch.loading.finished(r)}}).catch(e=>{a.logError(e);a.setUiError("jsonerr","Problem while loading data:<br/>"+e,1);y.set(false);m.setRef(null);f.set("");b.trigger();a.patch.loading.finished(r)})}).catch(e=>{a.logError(e);a.setUiError("jsonerr","Problem while loading data:<br/>"+e,1);y.set(false);m.setRef(null);f.set("");b.trigger();a.patch.loading.finished(r)})}else{CABLES.ajax(i,(e,t,i)=>{g.set(Math.round(performance.now()-n));v.set(i.status);try{let e=t;if(typeof e==="string"&&h.get()==="JSON"){try{e=JSON.parse(t);m.setRef(e)}catch(e){a.setUiError("jsonParse","could not parse json"+e.message,1);m.setRef({})}}f.set(t);a.uiAttr({error:null});b.trigger();y.set(false);a.patch.loading.finished(r)}catch(e){a.logError(e);a.setUiError("jsonerr","Problem while loading data:<br/>"+e,1);y.set(false);m.setRef(null);f.set("");a.patch.loading.finished(r)}},l.get(),e&&e.length>0?e:null,u.get(),null,s.get()||{},t)}})}};Ops.Json.HttpRequest_v3.prototype=new CABLES.Op;CABLES.OPS["ba2131a6-782d-40fe-9710-57a8e57051bb"]={f:Ops.Json.HttpRequest_v3,objName:"Ops.Json.HttpRequest_v3"};Ops.Extension.Lottie.LottieTexturePlayer_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTrigger("exe"),n=e.inObject("JSON Data"),r=e.inSwitch("Play Mode",["Auto","Frame"],"Auto"),a=e.inFloat("frame"),s=e.inBool("play"),o=e.inTriggerButton("Rewind"),l=e.inFloat("speed",1),u=e.inInt("texture width",1280),h=e.inInt("texture height",720),p=e.inDropDown("Filter",["nearest","linear","mipmap"],"linear"),c=e.inDropDown("wrap",["repeat","mirrored repeat","clamp to edge"],"repeat"),m=e.inSwitch("scale",["fit","nofit"],"fit"),f=e.outTexture("texture"),d=e.outNumber("Total Frames");const g=e.patch.cgl;const v="bodymovin_"+CABLES.generateUUID();let y=false;let b=null;let x=null;let A=null;let _=null;let S=CGL.Texture.FILTER_LINEAR;let C=CGL.Texture.WRAP_REPEAT;let T=-2;let I=true;let O=true;let E=null;e.toWorkPortsNeedToBeLinked(i,n);e.setPortGroup("Player Timing",[r,a,s,o,l]);e.setPortGroup("Texture Settings",[p,c,u,h,m]);r.onChange=L;p.onChange=P;n.onChange=N;m.onChange=u.onChange=h.onChange=M;s.onChange=function(){if(x)if(s.get())x.play();else x.pause()};o.onTriggered=function(){if(s.get())x.goToAndPlay(0,true);else x.goToAndStop(0,true)};l.onChange=function(){if(x)x.setSpeed(l.get())};c.onChange=function(){if(c.get()=="repeat")C=CGL.Texture.WRAP_REPEAT;if(c.get()=="mirrored repeat")C=CGL.Texture.WRAP_MIRRORED_REPEAT;if(c.get()=="clamp to edge")C=CGL.Texture.WRAP_CLAMP_TO_EDGE;y=true};function P(){S=CGL.Texture.FILTER_NEAREST;if(p.get()=="linear")S=CGL.Texture.FILTER_LINEAR;if(p.get()=="mipmap")S=CGL.Texture.FILTER_MIPMAP;y=true}i.onTriggered=function(){if(!x)return;d.set(x.totalFrames);if(!b||!_)return;if(I){O=true}else{if(T!=a.get()){T=a.get();if(a.get()!=-1){x.goToAndStop(a.get(),true)}O=true}}if(!f.get()||y){const e={wrap:C,filter:S,unpackAlpha:false};if(E)E.delete();E=new CGL.Texture.createFromImage(g,b,e);f.set(E);y=false}if(O&&E){E.initTexture(b);O=false}};e.onDelete=function(){if(x)x.stop();x=null};function M(){y=true;N(true)}function L(){I=r.get()==="Auto";s.setUiAttribs({greyout:!I});o.setUiAttribs({greyout:!I});l.setUiAttribs({greyout:!I});a.setUiAttribs({greyout:I});if(x){if(I)if(s.get())x.play();if(!I)x.stop()}}function N(e){if(!n.get()||Object.keys(n.get()).length===0){if(x)x.stop();x=null;if(E)E.delete();E=null;y=true;b=null;T=-2;O=true;return}L();d.set(0);if(x)x.stop();if(!b||e){if(E)E=E.delete();if(_)_.remove();_=document.createElement("canvas");_.id=v;_.width=u.get();_.height=h.get();_.style.display="none";const i=document.getElementsByTagName("body")[0];i.appendChild(_);b=document.getElementById(_.id);A=b.getContext("2d")}const t={animType:"canvas",loop:false,prerender:true,autoplay:I&&s.get(),animationData:n.get(),rendererSettings:{context:A,clearCanvas:true,scaleMode:m.get()}};x=bodymovin.loadAnimation(t);x.setSpeed(l.get());x.addEventListener("DOMLoaded",function(e){k()});k()}function k(){if(!I){x.goToAndPlay(0,true);T=-2}if(I&&s.get())x.play()}};Ops.Extension.Lottie.LottieTexturePlayer_v2.prototype=new CABLES.Op;CABLES.OPS["2fc89999-18bc-4d68-a81e-79d2280051c0"]={f:Ops.Extension.Lottie.LottieTexturePlayer_v2,objName:"Ops.Extension.Lottie.LottieTexturePlayer_v2"};Ops.Json.ParseObject_v2=function(){CABLES.Op.apply(this,arguments);const o=this;const e=o.attachments={};const l=o.inStringEditor("JSON String","{}","json"),t=o.outObject("Result"),u=o.outBoolNum("Valid");l.onChange=i;i();function i(){if(!l.get()){t.set(null);u.set(false);return}try{const e=JSON.parse(l.get());t.setRef(e);u.set(true);o.setUiError("invalidjson",null)}catch(e){o.logWarn(e);u.set(false);let t="";const i=e.message.split(" ");for(let e=0;e<i.length-1;e++){const n=parseFloat(i[e+1]);if(n&&i[e]=="position"){const r=l.get().substring(n-15,n);const a=l.get().substring(n,n+1);const s=l.get().substring(n+1,n+15);t='<span style="font-family:monospace;background-color:black;">'+r+'<span style="font-weight:bold;background-color:red;">'+a+"</span>"+s+" </span>"}}o.setUiError("invalidjson","INVALID JSON<br/>can not parse string to object:<br/><b> "+e.message+"</b><br/>"+t)}}};Ops.Json.ParseObject_v2.prototype=new CABLES.Op;CABLES.OPS["2ce8a4d3-37d3-4cdc-abd1-a560fbe841ee"]={f:Ops.Json.ParseObject_v2,objName:"Ops.Json.ParseObject_v2"};Ops.Ui.VizTexture=function(){CABLES.Op.apply(this,arguments);const V=this;const i=V.attachments={viztex_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI samplerCube cubeMap;\nUNI float width;\nUNI float height;\nUNI float type;\nUNI float time;\n\nfloat LinearizeDepth(float d,float zNear,float zFar)\n{\n    float z_n = 2.0 * d - 1.0;\n    return 2.0 * zNear / (zFar + zNear - z_n * (zFar - zNear));\n}\n\nvoid main()\n{\n    vec4 col=vec4(vec3(0.),0.0);\n\n    vec4 colTex=texture(tex,texCoord);\n\n\n\n    if(type==1.0)\n    {\n        vec4 depth=vec4(0.);\n        vec2 localST=texCoord;\n        localST.y = 1. - localST.y;\n\n        localST.t = mod(localST.t*3.,1.);\n        localST.s = mod(localST.s*4.,1.);\n\n        #ifdef WEBGL2\n            #define texCube texture\n        #endif\n        #ifdef WEBGL1\n            #define texCube textureCube\n        #endif\n\n//         //Due to the way my depth-cubeMap is rendered, objects to the -x,y,z side is projected to the positive x,y,z side\n//         //Inside where top/bottom is to be drawn?\n        if (texCoord.s*4.> 1. && texCoord.s*4.<2.)\n        {\n            //Bottom (-y) quad\n            if (texCoord.t*3. < 1.)\n            {\n                vec3 dir=vec3(localST.s*2.-1.,-1.,-localST.t*2.+1.);//Due to the (arbitrary) way I choose as up in my depth-viewmatrix, i her emultiply the latter coordinate with -1\n                depth = texCube(cubeMap, dir);\n            }\n            //top (+y) quad\n            else if (texCoord.t*3. > 2.)\n            {\n                vec3 dir=vec3(localST.s*2.-1.,1.,localST.t*2.-1.);//Get lower y texture, which is projected to the +y part of my cubeMap\n                depth = texCube(cubeMap, dir);\n            }\n            else//Front (-z) quad\n            {\n                vec3 dir=vec3(localST.s*2.-1.,-localST.t*2.+1.,1.);\n                depth = texCube(cubeMap, dir);\n            }\n        }\n//         //If not, only these ranges should be drawn\n        else if (texCoord.t*3. > 1. && texCoord.t*3. < 2.)\n        {\n            if (texCoord.x*4. < 1.)//left (-x) quad\n            {\n                vec3 dir=vec3(-1.,-localST.t*2.+1.,localST.s*2.-1.);\n                depth = texCube(cubeMap, dir);\n            }\n            else if (texCoord.x*4. < 3.)//right (+x) quad (front was done above)\n            {\n                vec3 dir=vec3(1,-localST.t*2.+1.,-localST.s*2.+1.);\n                depth = texCube(cubeMap, dir);\n            }\n            else //back (+z) quad\n            {\n                vec3 dir=vec3(-localST.s*2.+1.,-localST.t*2.+1.,-1.);\n                depth = texCube(cubeMap, dir);\n            }\n        }\n        // colTex = vec4(vec3(depth),1.);\n        colTex = vec4(depth);\n    }\n\n    if(type==2.0)\n    {\n       float near = 0.1;\n       float far = 50.;\n       float depth = LinearizeDepth(colTex.r, near, far);\n       colTex.rgb = vec3(depth);\n    }\n\n\n\n\n    #ifdef ANIM_RANGE\n\n        if(colTex.r>1.0 || colTex.r<0.0)\n            colTex.r=mod(colTex.r,1.0)*0.5+(sin(colTex.r+mod(colTex.r*3.0,1.0)+time*5.0)*0.5+0.5)*0.5;\n        if(colTex.g>1.0 || colTex.g<0.0)\n            colTex.g=mod(colTex.g,1.0)*0.5+(sin(colTex.g+mod(colTex.g*3.0,1.0)+time*5.0)*0.5+0.5)*0.5;\n        if(colTex.b>1.0 || colTex.b<0.0)\n            colTex.b=mod(colTex.b,1.0)*0.5+(sin(colTex.b+mod(colTex.b*3.0,1.0)+time*5.0)*0.5+0.5)*0.5;\n\n    #endif\n\n\n    // #ifdef ANIM_RANGE\n    //     if(colTex.r>1.0 || colTex.r<0.0)\n    //     {\n    //         float r=mod( time+colTex.r,1.0)*0.5+0.5;\n    //         colTex.r=r;\n    //     }\n    //     if(colTex.g>1.0 || colTex.g<0.0)\n    //     {\n    //         float r=mod( time+colTex.g,1.0)*0.5+0.5;\n    //         colTex.g=r;\n    //     }\n    //     if(colTex.b>1.0 || colTex.b<0.0)\n    //     {\n    //         float r=mod( time+colTex.b,1.0)*0.5+0.5;\n    //         colTex.b=r;\n    //     }\n    // #endif\n\n    #ifdef MOD_RANGE\n        colTex.r=mod(colTex.r,1.0001);\n        colTex.g=mod(colTex.g,1.0001);\n        colTex.b=mod(colTex.b,1.0001);\n\n    #endif\n\n    #ifdef ALPHA_ONE\n        colTex.a=1.0;\n    #endif\n    #ifdef ALPHA_INV\n        colTex.a=1.0-colTex.a;\n    #endif\n\n    outColor = mix(col,colTex,colTex.a);\n}\n\n",viztex_vert:"IN vec3 vPosition;\nIN vec2 attrTexCoord;\nOUT vec2 texCoord;\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\nvoid main()\n{\n    texCoord=vec2(attrTexCoord.x,1.0-attrTexCoord.y);\n    vec4 pos = vec4( vPosition, 1. );\n    mat4 mvMatrix=viewMatrix * modelMatrix;\n    gl_Position = projMatrix * mvMatrix * pos;\n}"};const D=V.inTexture("Texture In"),B=V.inBool("Show Info",false),e=V.inSwitch("Visualize outside 0-1",["Off","Anim","Modulo"],"Anim"),t=V.inSwitch("Alpha",["A","1","1-A"],"A"),j=V.inBool("Show Color",false),F=V.inFloatSlider("X",.5),U=V.inFloatSlider("Y",.5),n=V.outTexture("Texture Out"),G=V.outString("Info");V.setUiAttrib({height:150,resizable:true});const z=new CABLES.Timer;let r=null;let q=null;let X=null;let H="";let a=true;t.onChange=e.onChange=o;j.onChange=s;s();if(CABLES.UI){z.play()}function s(){F.setUiAttribs({greyout:!j.get()});U.setUiAttribs({greyout:!j.get()})}D.onChange=()=>{const e=D.get();n.setRef(e);let t="";if(D.get()&&D.isLinked())t=D.links[0].getOtherPort(D).name;V.setUiAttrib({extendTitle:t})};function o(){if(!r)return;r.toggleDefine("MOD_RANGE",e.get()=="Modulo");r.toggleDefine("ANIM_RANGE",e.get()=="Anim");r.toggleDefine("ALPHA_INV",t.get()=="1-A");r.toggleDefine("ALPHA_ONE",t.get()=="1")}V.renderVizLayerGl=(h,p)=>{if(!D.isLinked())return;if(!p.useGl)return;const c=D;const m=5;const f=m+1;const e=CABLES.UI.uiProfiler.start("previewlayer texture");const d=c.op.patch.cgl;if(!this._emptyCubemap)this._emptyCubemap=CGL.Texture.getEmptyCubemapTexture(d);c.op.patch.cgl.profileData.profileTexPreviews++;const g=c.get()||CGL.Texture.getEmptyTexture(d);if(!this._mesh){const t=new CGL.Geometry("vizTexture rect");t.vertices=[1,1,0,-1,1,0,1,-1,0,-1,-1,0];t.texCoords=[1,1,0,1,1,0,0,0];t.verticesIndices=[0,1,2,3,1,2];this._mesh=new CGL.Mesh(d,t)}if(!this._shader){this._shader=new CGL.Shader(d,"glpreviewtex");this._shader.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"]);this._shader.setSource(i.viztex_vert,i.viztex_frag);this._shaderTexUniform=new CGL.Uniform(this._shader,"t","tex",m);this._shaderTexCubemapUniform=new CGL.Uniform(this._shader,"tc","cubeMap",f);r=this._shader;o();this._shaderTexUniformW=new CGL.Uniform(this._shader,"f","width",g.width);this._shaderTexUniformH=new CGL.Uniform(this._shader,"f","height",g.height);this._shaderTypeUniform=new CGL.Uniform(this._shader,"f","type",0);this._shaderTimeUniform=new CGL.Uniform(this._shader,"f","time",0)}d.pushPMatrix();const v=[g.width,g.height];const y=c.op.patch.cgl.canvasWidth>v[0]&&c.op.patch.cgl.canvasHeight>v[1];if(y){mat4.ortho(d.pMatrix,0,c.op.patch.cgl.canvasWidth,c.op.patch.cgl.canvasHeight,0,.001,11)}else mat4.ortho(d.pMatrix,-1,1,1,-1,.001,11);const b=d.getTexture(m);const x=d.getTexture(f);let A=0;if(g){if(g.cubemap)A=1;if(g.textureType==CGL.Texture.TYPE_DEPTH)A=2;if(A==0||A==2){d.setTexture(m,g.tex);d.setTexture(f,this._emptyCubemap.cubemap,d.gl.TEXTURE_CUBE_MAP)}else if(A==1){d.setTexture(f,g.cubemap,d.gl.TEXTURE_CUBE_MAP)}z.update();this._shaderTimeUniform.setValue(z.get());this._shaderTypeUniform.setValue(A);let t=[c.op.patch.cgl.canvasWidth,c.op.patch.cgl.canvasHeight];d.gl.clearColor(0,0,0,0);d.gl.clear(d.gl.COLOR_BUFFER_BIT|d.gl.DEPTH_BUFFER_BIT);d.pushModelMatrix();if(y){t=v;mat4.translate(d.mMatrix,d.mMatrix,[v[0]/2,v[1]/2,0]);mat4.scale(d.mMatrix,d.mMatrix,[v[0]/2,v[1]/2,0])}this._mesh.render(this._shader);d.popModelMatrix();if(A==0)d.setTexture(m,b);if(A==1)d.setTexture(f,x);d.popPMatrix();d.resetViewPort();const _=[p.width,p.height];const S=false;if(g.width>g.height)_[1]=p.width*v[1]/v[0];else{_[1]=p.width*(v[1]/v[0]);if(_[1]>p.height){const O=p.height/_[1];_[0]*=O;_[1]*=O}}const C=_[0]>v[0]&&_[1]>v[1];h.imageSmoothingEnabled=true;h.fillStyle="#ffffff";h.fillRect(p.x,p.y-10,10,10);h.fillStyle="#000000";h.fillRect(p.x,p.y-10,5,5);h.fillRect(p.x+5,p.y-10+5,5,5);let e=p.height;let i=10*p.width/e;let n=e/10;let r=p.width/i;for(let t=0;t<i;t++)for(let e=0;e<10;e++){if((t+e)%2==0)h.fillStyle="#333333";else h.fillStyle="#393939";h.fillRect(p.x+r*t,p.y+n*e,r,n)}h.fillStyle="#222";const T=(p.width-_[0])/2;const I=(e-_[1])/2;let a=p.x+(p.width-_[0])/2;let s=p.y+(e-_[1])/2;let o=_[0];let l=_[1];if(e-_[1]<0){a=p.x+(p.width-_[0]*e/_[1])/2;s=p.y;o=_[0]*e/_[1];l=e}h.fillRect(p.x,p.y,a-p.x,e);h.fillRect(p.x+o+a-p.x,p.y,o,e);h.fillRect(p.x,p.y,p.width,I);h.fillRect(p.x,p.y+_[1]+I,p.width,I);if(d.canvas&&d.canvasWidth>0&&d.canvasHeight>0&&d.canvas.width>0&&d.canvas.height>0){try{const E=o/t[0]>3||l/t[1]>3;const P=o/t[0]>10||l/t[1]>10;if(v[1]==1){h.imageSmoothingEnabled=false;h.drawImage(d.canvas,0,0,t[0],t[1],p.x,p.y,p.width,e);h.imageSmoothingEnabled=true}else if(v[0]==1){h.imageSmoothingEnabled=false;h.drawImage(d.canvas,0,0,t[0],t[1],p.x,p.y,p.width,e);h.imageSmoothingEnabled=true}else if(_[0]!=0&&_[1]!=0&&p.width!=0&&e!=0&&o!=0&&l!=0){h.imageSmoothingEnabled=!E;h.drawImage(d.canvas,0,0,t[0],t[1],a,s,o,l)}if(P){const M=o/t[0];const L=l/t[1];h.imageSmoothingEnabled=true;h.lineWidth=1;h.globalAlpha=.5;h.beginPath();for(let e=0;e<=t[0];e++){h.moveTo(a+e*M,s);h.lineTo(a+e*M,s+l)}for(let e=0;e<=t[1];e++){h.moveTo(a,s+e*L);h.lineTo(a+o,s+e*L)}h.strokeStyle="#555";h.stroke();h.globalAlpha=1}}catch(e){console.error("canvas drawimage exception...",e)}}let u="";if(c.get()&&c.get().getInfoOneLine)u+=c.get().getInfoOneLine()+"\n";G.set(u);if(j.get()){u+=H+"\n";const N=a+o*F.get();const k=s+l*U.get();h.fillStyle="#000";h.fillRect(N-1,k-10,3,20);h.fillRect(N,k-1,20,3);h.fillStyle="#fff";h.fillRect(N-1,k-10,1,20);h.fillRect(N-10,k-1,20,1)}if(B.get()){V.setUiAttrib({comment:u})}if(j.get()){const w=d.gl;const R=D.get();if(!R){H="";return}if(!q)q=w.createFramebuffer();if(!X)X=new CGL.PixelReader;w.bindFramebuffer(w.FRAMEBUFFER,q);w.framebufferTexture2D(w.FRAMEBUFFER,w.COLOR_ATTACHMENT0,w.TEXTURE_2D,R.tex,0);w.bindFramebuffer(w.FRAMEBUFFER,null);X.read(d,q,R.pixelFormat,F.get()*R.width,R.height-U.get()*R.height,1,1,e=>{if(!CGL.Texture.isPixelFormatFloat(R.pixelFormat)){H="Pixel Float: "+Math.floor(e[0]/255*100)/100;if(!isNaN(e[1]))H+=", "+Math.floor(e[1]/255*100)/100;if(!isNaN(e[2]))H+=", "+Math.floor(e[2]/255*100)/100;if(!isNaN(e[3]))H+=", "+Math.floor(e[3]/255*100)/100;H+="\n";if(R.pixelFormat.indexOf("ubyte")>0){H+="Pixel UByte: ";H+=Math.round(e[0]);if(!isNaN(e[1]))H+=", "+Math.round(e[1]);if(!isNaN(e[2]))H+=", "+Math.round(e[2]);if(!isNaN(e[3]))H+=", "+Math.round(e[3]);H+="\n"}}else{H="Pixel Float: "+Math.round(e[0]*100)/100+", "+Math.round(e[1]*100)/100+", "+Math.round(e[2]*100)/100+", "+Math.round(e[3]*100)/100;H+="\n"}})}}d.gl.clearColor(0,0,0,0);d.gl.clear(d.gl.COLOR_BUFFER_BIT|d.gl.DEPTH_BUFFER_BIT);e.finish()}};Ops.Ui.VizTexture.prototype=new CABLES.Op;CABLES.OPS["4ea2d7b0-ca74-45db-962b-4d1965ac20c0"]={f:Ops.Ui.VizTexture,objName:"Ops.Ui.VizTexture"};Ops.Number.Integer=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inInt("Integer",0),n=e.outNumber("Number out");i.onChange=function(){n.set(Math.floor(i.get()))}};Ops.Number.Integer.prototype=new CABLES.Op;CABLES.OPS["17bc01d7-04ad-4aab-b88b-bb09744c4a69"]={f:Ops.Number.Integer,objName:"Ops.Number.Integer"};Ops.Ui.Comment_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inString("title","New comment"),n=e.inTextarea("text");i.setUiAttribs({hidePort:true});n.setUiAttribs({hidePort:true});e.init=i.onChange=n.onChange=e.onLoaded=r;r();function r(){if(CABLES.UI){e.uiAttr({comment_title:i.get(),comment_text:n.get(),extendTitle:i.get()})}}};Ops.Ui.Comment_v2.prototype=new CABLES.Op;CABLES.OPS["93492eeb-bf35-4a62-98f7-d85b0b79bfe5"]={f:Ops.Ui.Comment_v2,objName:"Ops.Ui.Comment_v2"};Ops.Trigger.TriggerOnce=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTriggerButton("Exec"),n=e.inTriggerButton("Reset"),r=e.outTrigger("Next"),a=e.outBoolNum("Was Triggered");let s=false;e.toWorkPortsNeedToBeLinked(i);n.onTriggered=function(){s=false;a.set(s)};i.onTriggered=function(){if(s)return;s=true;r.trigger();a.set(s)}};Ops.Trigger.TriggerOnce.prototype=new CABLES.Op;CABLES.OPS["cf3544e4-e392-432b-89fd-fcfb5c974388"]={f:Ops.Trigger.TriggerOnce,objName:"Ops.Trigger.TriggerOnce"};Ops.Number.TriggerOnChangeNumber=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inFloat("Value"),n=e.outTrigger("Next"),r=e.outNumber("Number");i.onChange=function(){r.set(i.get());n.trigger()}};Ops.Number.TriggerOnChangeNumber.prototype=new CABLES.Op;CABLES.OPS["f5c8c433-ce13-49c4-9a33-74e98f110ed0"]={f:Ops.Number.TriggerOnChangeNumber,objName:"Ops.Number.TriggerOnChangeNumber"};Ops.Math.TriggerRandomNumber_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const i=e.inTriggerButton("Generate"),n=e.inValue("min",0),r=e.inValue("max",1),a=e.outTrigger("next"),s=e.outNumber("result"),o=e.inValueBool("Integer",false),l=e.inValueBool("No consecutive duplicates",false);e.setPortGroup("Value Range",[n,r]);i.onTriggered=r.onChange=n.onChange=o.onChange=u;u();function u(){let e=Math.random()*(r.get()-n.get())+n.get();if(o.get())e=h();if(n.get()!=r.get()&&r.get()>n.get())while(l.get()&&e==s.get())e=h();s.set(e);a.trigger()}function h(){return Math.floor(Math.random()*(r.get()-n.get()+1)+n.get())}};Ops.Math.TriggerRandomNumber_v2.prototype=new CABLES.Op;CABLES.OPS["26f446cc-9107-4164-8209-5254487fa132"]={f:Ops.Math.TriggerRandomNumber_v2,objName:"Ops.Math.TriggerRandomNumber_v2"};window.addEventListener("load",function(e){CABLES.jsLoaded=new Event("CABLES.jsLoaded");document.dispatchEvent(CABLES.jsLoaded)});"undefined"!=typeof navigator&&function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).lottie=t()}(this,function(){"use strict";var svgNS="http://www.w3.org/2000/svg",locationHref="",_useWebWorker=!1,initialDefaultFrame=-999999,setWebWorker=function(e){_useWebWorker=!!e},getWebWorker=function(){return _useWebWorker},setLocationHref=function(e){locationHref=e},getLocationHref=function(){return locationHref};function createTag(e){return document.createElement(e)}function extendPrototype(e,t){var i,n,r=e.length;for(i=0;i<r;i+=1)for(var a in n=e[i].prototype)Object.prototype.hasOwnProperty.call(n,a)&&(t.prototype[a]=n[a])}function getDescriptor(e,t){return Object.getOwnPropertyDescriptor(e,t)}function createProxyFunction(e){function t(){}return t.prototype=e,t}var audioControllerFactory=function(){function e(e){this.audios=[],this.audioFactory=e,this._volume=1,this._isMuted=!1}return e.prototype={addAudio:function(e){this.audios.push(e)},pause:function(){var e,t=this.audios.length;for(e=0;e<t;e+=1)this.audios[e].pause()},resume:function(){var e,t=this.audios.length;for(e=0;e<t;e+=1)this.audios[e].resume()},setRate:function(e){var t,i=this.audios.length;for(t=0;t<i;t+=1)this.audios[t].setRate(e)},createAudio:function(e){return this.audioFactory?this.audioFactory(e):window.Howl?new window.Howl({src:[e]}):{isPlaying:!1,play:function(){this.isPlaying=!0},seek:function(){this.isPlaying=!1},playing:function(){},rate:function(){},setVolume:function(){}}},setAudioFactory:function(e){this.audioFactory=e},setVolume:function(e){this._volume=e,this._updateVolume()},mute:function(){this._isMuted=!0,this._updateVolume()},unmute:function(){this._isMuted=!1,this._updateVolume()},getVolume:function(){return this._volume},_updateVolume:function(){var e,t=this.audios.length;for(e=0;e<t;e+=1)this.audios[e].volume(this._volume*(this._isMuted?0:1))}},function(){return new e}}(),createTypedArray=function(){function i(e,t){var i,n=0,r=[];switch(e){case"int16":case"uint8c":i=1;break;default:i=1.1}for(n=0;n<t;n+=1)r.push(i);return r}return"function"==typeof Uint8ClampedArray&&"function"==typeof Float32Array?function(e,t){return"float32"===e?new Float32Array(t):"int16"===e?new Int16Array(t):"uint8c"===e?new Uint8ClampedArray(t):i(e,t)}:i}();function createSizedArray(e){return Array.apply(null,{length:e})}function _typeof$6(e){return _typeof$6="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof$6(e)}var subframeEnabled=!0,expressionsPlugin=null,expressionsInterfaces=null,idPrefix$1="",isSafari=/^((?!chrome|android).)*safari/i.test(navigator.userAgent),_shouldRoundValues=!1,bmPow=Math.pow,bmSqrt=Math.sqrt,bmFloor=Math.floor,bmMax=Math.max,bmMin=Math.min,BMMath={};function ProjectInterface$1(){return{}}!function(){var e,t=["abs","acos","acosh","asin","asinh","atan","atanh","atan2","ceil","cbrt","expm1","clz32","cos","cosh","exp","floor","fround","hypot","imul","log","log1p","log2","log10","max","min","pow","random","round","sign","sin","sinh","sqrt","tan","tanh","trunc","E","LN10","LN2","LOG10E","LOG2E","PI","SQRT1_2","SQRT2"],i=t.length;for(e=0;e<i;e+=1)BMMath[t[e]]=Math[t[e]]}(),BMMath.random=Math.random,BMMath.abs=function(e){if("object"===_typeof$6(e)&&e.length){var t,i=createSizedArray(e.length),n=e.length;for(t=0;t<n;t+=1)i[t]=Math.abs(e[t]);return i}return Math.abs(e)};var defaultCurveSegments=150,degToRads=Math.PI/180,roundCorner=.5519;function roundValues(e){_shouldRoundValues=!!e}function bmRnd(e){return _shouldRoundValues?Math.round(e):e}function styleDiv(e){e.style.position="absolute",e.style.top=0,e.style.left=0,e.style.display="block",e.style.transformOrigin="0 0",e.style.webkitTransformOrigin="0 0",e.style.backfaceVisibility="visible",e.style.webkitBackfaceVisibility="visible",e.style.transformStyle="preserve-3d",e.style.webkitTransformStyle="preserve-3d",e.style.mozTransformStyle="preserve-3d"}function BMEnterFrameEvent(e,t,i,n){this.type=e,this.currentTime=t,this.totalTime=i,this.direction=n<0?-1:1}function BMCompleteEvent(e,t){this.type=e,this.direction=t<0?-1:1}function BMCompleteLoopEvent(e,t,i,n){this.type=e,this.currentLoop=i,this.totalLoops=t,this.direction=n<0?-1:1}function BMSegmentStartEvent(e,t,i){this.type=e,this.firstFrame=t,this.totalFrames=i}function BMDestroyEvent(e,t){this.type=e,this.target=t}function BMRenderFrameErrorEvent(e,t){this.type="renderFrameError",this.nativeError=e,this.currentTime=t}function BMConfigErrorEvent(e){this.type="configError",this.nativeError=e}function BMAnimationConfigErrorEvent(e,t){this.type=e,this.nativeError=t}var createElementID=(_count=0,function(){return idPrefix$1+"__lottie_element_"+(_count+=1)}),_count;function HSVtoRGB(e,t,i){var n,r,a,s,o,l,u,h;switch(l=i*(1-t),u=i*(1-(o=6*e-(s=Math.floor(6*e)))*t),h=i*(1-(1-o)*t),s%6){case 0:n=i,r=h,a=l;break;case 1:n=u,r=i,a=l;break;case 2:n=l,r=i,a=h;break;case 3:n=l,r=u,a=i;break;case 4:n=h,r=l,a=i;break;case 5:n=i,r=l,a=u}return[n,r,a]}function RGBtoHSV(e,t,i){var n,r=Math.max(e,t,i),a=Math.min(e,t,i),s=r-a,o=0===r?0:s/r,l=r/255;switch(r){case a:n=0;break;case e:n=t-i+s*(t<i?6:0),n/=6*s;break;case t:n=i-e+2*s,n/=6*s;break;case i:n=e-t+4*s,n/=6*s}return[n,o,l]}function addSaturationToRGB(e,t){var i=RGBtoHSV(255*e[0],255*e[1],255*e[2]);return i[1]+=t,i[1]>1?i[1]=1:i[1]<=0&&(i[1]=0),HSVtoRGB(i[0],i[1],i[2])}function addBrightnessToRGB(e,t){var i=RGBtoHSV(255*e[0],255*e[1],255*e[2]);return i[2]+=t,i[2]>1?i[2]=1:i[2]<0&&(i[2]=0),HSVtoRGB(i[0],i[1],i[2])}function addHueToRGB(e,t){var i=RGBtoHSV(255*e[0],255*e[1],255*e[2]);return i[0]+=t/360,i[0]>1?i[0]-=1:i[0]<0&&(i[0]+=1),HSVtoRGB(i[0],i[1],i[2])}var rgbToHex=function(){var e,t,n=[];for(e=0;e<256;e+=1)t=e.toString(16),n[e]=1===t.length?"0"+t:t;return function(e,t,i){return e<0&&(e=0),t<0&&(t=0),i<0&&(i=0),"#"+n[e]+n[t]+n[i]}}(),setSubframeEnabled=function(e){subframeEnabled=!!e},getSubframeEnabled=function(){return subframeEnabled},setExpressionsPlugin=function(e){expressionsPlugin=e},getExpressionsPlugin=function(){return expressionsPlugin},setExpressionInterfaces=function(e){expressionsInterfaces=e},getExpressionInterfaces=function(){return expressionsInterfaces},setDefaultCurveSegments=function(e){defaultCurveSegments=e},getDefaultCurveSegments=function(){return defaultCurveSegments},setIdPrefix=function(e){idPrefix$1=e},getIdPrefix=function(){return idPrefix$1};function createNS(e){return document.createElementNS(svgNS,e)}function _typeof$5(e){return _typeof$5="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof$5(e)}var dataManager=function(){var n,r,a=1,s=[],o={onmessage:function(){},postMessage:function(e){n({data:e})}},i={postMessage:function(e){o.onmessage({data:e})}};function l(){r||(r=function(e){if(window.Worker&&window.Blob&&getWebWorker()){var t=new Blob(["var _workerSelf = self; self.onmessage = ",e.toString()],{type:"text/javascript"}),i=URL.createObjectURL(t);return new Worker(i)}return n=e,o}(function(t){if(i.dataManager||(i.dataManager=function(){function h(e,t){var i,n,r,a,s,o,l=e.length;for(n=0;n<l;n+=1)if("ks"in(i=e[n])&&!i.completed){if(i.completed=!0,i.hasMask){var u=i.masksProperties;for(a=u.length,r=0;r<a;r+=1)if(u[r].pt.k.i)m(u[r].pt.k);else for(o=u[r].pt.k.length,s=0;s<o;s+=1)u[r].pt.k[s].s&&m(u[r].pt.k[s].s[0]),u[r].pt.k[s].e&&m(u[r].pt.k[s].e[0])}0===i.ty?(i.layers=p(i.refId,t),h(i.layers,t)):4===i.ty?c(i.shapes):5===i.ty&&f(i)}}function p(e,t){var i=function(e,t){for(var i=0,n=t.length;i<n;){if(t[i].id===e)return t[i];i+=1}return null}(e,t);return i?i.layers.__used?JSON.parse(JSON.stringify(i.layers)):(i.layers.__used=!0,i.layers):null}function c(e){var t,i,n;for(t=e.length-1;t>=0;t-=1)if("sh"===e[t].ty)if(e[t].ks.k.i)m(e[t].ks.k);else for(n=e[t].ks.k.length,i=0;i<n;i+=1)e[t].ks.k[i].s&&m(e[t].ks.k[i].s[0]),e[t].ks.k[i].e&&m(e[t].ks.k[i].e[0]);else"gr"===e[t].ty&&c(e[t].it)}function m(e){var t,i=e.i.length;for(t=0;t<i;t+=1)e.i[t][0]+=e.v[t][0],e.i[t][1]+=e.v[t][1],e.o[t][0]+=e.v[t][0],e.o[t][1]+=e.v[t][1]}function s(e,t){var i=t?t.split("."):[100,100,100];return e[0]>i[0]||!(i[0]>e[0])&&(e[1]>i[1]||!(i[1]>e[1])&&(e[2]>i[2]||!(i[2]>e[2])&&null))}var r,t=function(){var n=[4,4,14];function r(e){var t,i,n,r=e.length;for(t=0;t<r;t+=1)5===e[t].ty&&(n=void 0,n=(i=e[t]).t.d,i.t.d={k:[{s:n,t:0}]})}return function(e){if(s(n,e.v)&&(r(e.layers),e.assets)){var t,i=e.assets.length;for(t=0;t<i;t+=1)e.assets[t].layers&&r(e.assets[t].layers)}}}(),i=(r=[4,7,99],function(e){if(e.chars&&!s(r,e.v)){var t,i=e.chars.length;for(t=0;t<i;t+=1){var n=e.chars[t];n.data&&n.data.shapes&&(c(n.data.shapes),n.data.ip=0,n.data.op=99999,n.data.st=0,n.data.sr=1,n.data.ks={p:{k:[0,0],a:0},s:{k:[100,100],a:0},a:{k:[0,0],a:0},r:{k:0,a:0},o:{k:100,a:0}},e.chars[t].t||(n.data.shapes.push({ty:"no"}),n.data.shapes[0].it.push({p:{k:[0,0],a:0},s:{k:[100,100],a:0},a:{k:[0,0],a:0},r:{k:0,a:0},o:{k:100,a:0},sk:{k:0,a:0},sa:{k:0,a:0},ty:"tr"})))}}}),n=function(){var n=[5,7,15];function r(e){var t,i,n=e.length;for(t=0;t<n;t+=1)5===e[t].ty&&(i=void 0,"number"==typeof(i=e[t].t.p).a&&(i.a={a:0,k:i.a}),"number"==typeof i.p&&(i.p={a:0,k:i.p}),"number"==typeof i.r&&(i.r={a:0,k:i.r}))}return function(e){if(s(n,e.v)&&(r(e.layers),e.assets)){var t,i=e.assets.length;for(t=0;t<i;t+=1)e.assets[t].layers&&r(e.assets[t].layers)}}}(),a=function(){var n=[4,1,9];function a(e){var t,i,n,r=e.length;for(t=0;t<r;t+=1)if("gr"===e[t].ty)a(e[t].it);else if("fl"===e[t].ty||"st"===e[t].ty)if(e[t].c.k&&e[t].c.k[0].i)for(n=e[t].c.k.length,i=0;i<n;i+=1)e[t].c.k[i].s&&(e[t].c.k[i].s[0]/=255,e[t].c.k[i].s[1]/=255,e[t].c.k[i].s[2]/=255,e[t].c.k[i].s[3]/=255),e[t].c.k[i].e&&(e[t].c.k[i].e[0]/=255,e[t].c.k[i].e[1]/=255,e[t].c.k[i].e[2]/=255,e[t].c.k[i].e[3]/=255);else e[t].c.k[0]/=255,e[t].c.k[1]/=255,e[t].c.k[2]/=255,e[t].c.k[3]/=255}function r(e){var t,i=e.length;for(t=0;t<i;t+=1)4===e[t].ty&&a(e[t].shapes)}return function(e){if(s(n,e.v)&&(r(e.layers),e.assets)){var t,i=e.assets.length;for(t=0;t<i;t+=1)e.assets[t].layers&&r(e.assets[t].layers)}}}(),o=function(){var n=[4,4,18];function u(e){var t,i,n;for(t=e.length-1;t>=0;t-=1)if("sh"===e[t].ty)if(e[t].ks.k.i)e[t].ks.k.c=e[t].closed;else for(n=e[t].ks.k.length,i=0;i<n;i+=1)e[t].ks.k[i].s&&(e[t].ks.k[i].s[0].c=e[t].closed),e[t].ks.k[i].e&&(e[t].ks.k[i].e[0].c=e[t].closed);else"gr"===e[t].ty&&u(e[t].it)}function r(e){var t,i,n,r,a,s,o=e.length;for(i=0;i<o;i+=1){if((t=e[i]).hasMask){var l=t.masksProperties;for(r=l.length,n=0;n<r;n+=1)if(l[n].pt.k.i)l[n].pt.k.c=l[n].cl;else for(s=l[n].pt.k.length,a=0;a<s;a+=1)l[n].pt.k[a].s&&(l[n].pt.k[a].s[0].c=l[n].cl),l[n].pt.k[a].e&&(l[n].pt.k[a].e[0].c=l[n].cl)}4===t.ty&&u(t.shapes)}}return function(e){if(s(n,e.v)&&(r(e.layers),e.assets)){var t,i=e.assets.length;for(t=0;t<i;t+=1)e.assets[t].layers&&r(e.assets[t].layers)}}}();function f(e){0===e.t.a.length&&e.t.p}var e={completeData:function(e){e.__complete||(a(e),t(e),i(e),n(e),o(e),h(e.layers,e.assets),function(e,t){if(e){var i=0,n=e.length;for(i=0;i<n;i+=1)1===e[i].t&&(e[i].data.layers=p(e[i].data.refId,t),h(e[i].data.layers,t))}}(e.chars,e.assets),e.__complete=!0)}};return e.checkColors=a,e.checkChars=i,e.checkPathProperties=n,e.checkShapes=o,e.completeLayers=h,e}()),i.assetLoader||(i.assetLoader=function(){function s(e){var t=e.getResponseHeader("content-type");return t&&"json"===e.responseType&&-1!==t.indexOf("json")||e.response&&"object"===_typeof$5(e.response)?e.response:e.response&&"string"==typeof e.response?JSON.parse(e.response):e.responseText?JSON.parse(e.responseText):null}return{load:function(t,i,e,n){var r,a=new XMLHttpRequest;try{a.responseType="json"}catch(e){}a.onreadystatechange=function(){if(4===a.readyState)if(200===a.status)r=s(a),e(r);else try{r=s(a),e(r)}catch(e){n&&n(e)}};try{a.open(["G","E","T"].join(""),t,!0)}catch(e){a.open(["G","E","T"].join(""),i+"/"+t,!0)}a.send()}}}()),"loadAnimation"===t.data.type)i.assetLoader.load(t.data.path,t.data.fullPath,function(e){i.dataManager.completeData(e),i.postMessage({id:t.data.id,payload:e,status:"success"})},function(){i.postMessage({id:t.data.id,status:"error"})});else if("complete"===t.data.type){var e=t.data.animation;i.dataManager.completeData(e),i.postMessage({id:t.data.id,payload:e,status:"success"})}else"loadData"===t.data.type&&i.assetLoader.load(t.data.path,t.data.fullPath,function(e){i.postMessage({id:t.data.id,payload:e,status:"success"})},function(){i.postMessage({id:t.data.id,status:"error"})})}),r.onmessage=function(e){var t=e.data,i=t.id,n=s[i];s[i]=null,"success"===t.status?n.onComplete(t.payload):n.onError&&n.onError()})}function u(e,t){var i="processId_"+(a+=1);return s[i]={onComplete:e,onError:t},i}return{loadAnimation:function(e,t,i){l();var n=u(t,i);r.postMessage({type:"loadAnimation",path:e,fullPath:window.location.origin+window.location.pathname,id:n})},loadData:function(e,t,i){l();var n=u(t,i);r.postMessage({type:"loadData",path:e,fullPath:window.location.origin+window.location.pathname,id:n})},completeAnimation:function(e,t,i){l();var n=u(t,i);r.postMessage({type:"complete",animation:e,id:n})}}}(),ImagePreloader=function(){var r=function(){var e=createTag("canvas");e.width=1,e.height=1;var t=e.getContext("2d");return t.fillStyle="rgba(0,0,0,0)",t.fillRect(0,0,1,1),e}();function e(){this.loadedAssets+=1,this.loadedAssets===this.totalImages&&this.loadedFootagesCount===this.totalFootages&&this.imagesLoadedCb&&this.imagesLoadedCb(null)}function t(){this.loadedFootagesCount+=1,this.loadedAssets===this.totalImages&&this.loadedFootagesCount===this.totalFootages&&this.imagesLoadedCb&&this.imagesLoadedCb(null)}function a(e,t,i){var n="";if(e.e)n=e.p;else if(t){var r=e.p;-1!==r.indexOf("images/")&&(r=r.split("/")[1]),n=t+r}else n=i,n+=e.u?e.u:"",n+=e.p;return n}function i(e){var t=0,i=setInterval(function(){(e.getBBox().width||t>500)&&(this._imageLoaded(),clearInterval(i)),t+=1}.bind(this),50)}function n(e){var t={assetData:e},i=a(e,this.assetsPath,this.path);return dataManager.loadData(i,function(e){t.img=e,this._footageLoaded()}.bind(this),function(){t.img={},this._footageLoaded()}.bind(this)),t}function s(){this._imageLoaded=e.bind(this),this._footageLoaded=t.bind(this),this.testImageLoaded=i.bind(this),this.createFootageData=n.bind(this),this.assetsPath="",this.path="",this.totalImages=0,this.totalFootages=0,this.loadedAssets=0,this.loadedFootagesCount=0,this.imagesLoadedCb=null,this.images=[]}return s.prototype={loadAssets:function(e,t){var i;this.imagesLoadedCb=t;var n=e.length;for(i=0;i<n;i+=1)e[i].layers||(e[i].t&&"seq"!==e[i].t?3===e[i].t&&(this.totalFootages+=1,this.images.push(this.createFootageData(e[i]))):(this.totalImages+=1,this.images.push(this._createImageData(e[i]))))},setAssetsPath:function(e){this.assetsPath=e||""},setPath:function(e){this.path=e||""},loadedImages:function(){return this.totalImages===this.loadedAssets},loadedFootages:function(){return this.totalFootages===this.loadedFootagesCount},destroy:function(){this.imagesLoadedCb=null,this.images.length=0},getAsset:function(e){for(var t=0,i=this.images.length;t<i;){if(this.images[t].assetData===e)return this.images[t].img;t+=1}return null},createImgData:function(e){var t=a(e,this.assetsPath,this.path),i=createTag("img");i.crossOrigin="anonymous",i.addEventListener("load",this._imageLoaded,!1),i.addEventListener("error",function(){n.img=r,this._imageLoaded()}.bind(this),!1),i.src=t;var n={img:i,assetData:e};return n},createImageData:function(e){var t=a(e,this.assetsPath,this.path),i=createNS("image");isSafari?this.testImageLoaded(i):i.addEventListener("load",this._imageLoaded,!1),i.addEventListener("error",function(){n.img=r,this._imageLoaded()}.bind(this),!1),i.setAttributeNS("http://www.w3.org/1999/xlink","href",t),this._elementHelper.append?this._elementHelper.append(i):this._elementHelper.appendChild(i);var n={img:i,assetData:e};return n},imageLoaded:e,footageLoaded:t,setCacheType:function(e,t){"svg"===e?(this._elementHelper=t,this._createImageData=this.createImageData.bind(this)):this._createImageData=this.createImgData.bind(this)}},s}();function BaseEvent(){}BaseEvent.prototype={triggerEvent:function(e,t){if(this._cbs[e])for(var i=this._cbs[e],n=0;n<i.length;n+=1)i[n](t)},addEventListener:function(e,t){return this._cbs[e]||(this._cbs[e]=[]),this._cbs[e].push(t),function(){this.removeEventListener(e,t)}.bind(this)},removeEventListener:function(e,t){if(t){if(this._cbs[e]){for(var i=0,n=this._cbs[e].length;i<n;)this._cbs[e][i]===t&&(this._cbs[e].splice(i,1),i-=1,n-=1),i+=1;this._cbs[e].length||(this._cbs[e]=null)}}else this._cbs[e]=null}};var markerParser=function(){function a(e){for(var t,i=e.split("\r\n"),n={},r=0,a=0;a<i.length;a+=1)2===(t=i[a].split(":")).length&&(n[t[0]]=t[1].trim(),r+=1);if(0===r)throw new Error;return n}return function(t){for(var e=[],i=0;i<t.length;i+=1){var n=t[i],r={time:n.tm,duration:n.dr};try{r.payload=JSON.parse(t[i].cm)}catch(e){try{r.payload=a(t[i].cm)}catch(e){r.payload={name:t[i].cm}}}e.push(r)}return e}}(),ProjectInterface=function(){function t(e){this.compositions.push(e)}return function(){function e(e){for(var t=0,i=this.compositions.length;t<i;){if(this.compositions[t].data&&this.compositions[t].data.nm===e)return this.compositions[t].prepareFrame&&this.compositions[t].data.xt&&this.compositions[t].prepareFrame(this.currentFrame),this.compositions[t].compInterface;t+=1}return null}return e.compositions=[],e.currentFrame=0,e.registerComposition=t,e}}(),renderers={},registerRenderer=function(e,t){renderers[e]=t};function getRenderer(e){return renderers[e]}function _typeof$4(e){return _typeof$4="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof$4(e)}var AnimationItem=function(){this._cbs=[],this.name="",this.path="",this.isLoaded=!1,this.currentFrame=0,this.currentRawFrame=0,this.firstFrame=0,this.totalFrames=0,this.frameRate=0,this.frameMult=0,this.playSpeed=1,this.playDirection=1,this.playCount=0,this.animationData={},this.assets=[],this.isPaused=!0,this.autoplay=!1,this.loop=!0,this.renderer=null,this.animationID=createElementID(),this.assetsPath="",this.timeCompleted=0,this.segmentPos=0,this.isSubframeEnabled=getSubframeEnabled(),this.segments=[],this._idle=!0,this._completedLoop=!1,this.projectInterface=ProjectInterface(),this.imagePreloader=new ImagePreloader,this.audioController=audioControllerFactory(),this.markers=[],this.configAnimation=this.configAnimation.bind(this),this.onSetupError=this.onSetupError.bind(this),this.onSegmentComplete=this.onSegmentComplete.bind(this),this.drawnFrameEvent=new BMEnterFrameEvent("drawnFrame",0,0,0)};extendPrototype([BaseEvent],AnimationItem),AnimationItem.prototype.setParams=function(e){(e.wrapper||e.container)&&(this.wrapper=e.wrapper||e.container);var t="svg";e.animType?t=e.animType:e.renderer&&(t=e.renderer);var i=getRenderer(t);this.renderer=new i(this,e.rendererSettings),this.imagePreloader.setCacheType(t,this.renderer.globalData.defs),this.renderer.setProjectInterface(this.projectInterface),this.animType=t,""===e.loop||null===e.loop||void 0===e.loop||!0===e.loop?this.loop=!0:!1===e.loop?this.loop=!1:this.loop=parseInt(e.loop,10),this.autoplay=!("autoplay"in e)||e.autoplay,this.name=e.name?e.name:"",this.autoloadSegments=!Object.prototype.hasOwnProperty.call(e,"autoloadSegments")||e.autoloadSegments,this.assetsPath=e.assetsPath,this.initialSegment=e.initialSegment,e.audioFactory&&this.audioController.setAudioFactory(e.audioFactory),e.animationData?this.setupAnimation(e.animationData):e.path&&(-1!==e.path.lastIndexOf("\\")?this.path=e.path.substr(0,e.path.lastIndexOf("\\")+1):this.path=e.path.substr(0,e.path.lastIndexOf("/")+1),this.fileName=e.path.substr(e.path.lastIndexOf("/")+1),this.fileName=this.fileName.substr(0,this.fileName.lastIndexOf(".json")),dataManager.loadAnimation(e.path,this.configAnimation,this.onSetupError))},AnimationItem.prototype.onSetupError=function(){this.trigger("data_failed")},AnimationItem.prototype.setupAnimation=function(e){dataManager.completeAnimation(e,this.configAnimation)},AnimationItem.prototype.setData=function(e,t){t&&"object"!==_typeof$4(t)&&(t=JSON.parse(t));var i={wrapper:e,animationData:t},n=e.attributes;i.path=n.getNamedItem("data-animation-path")?n.getNamedItem("data-animation-path").value:n.getNamedItem("data-bm-path")?n.getNamedItem("data-bm-path").value:n.getNamedItem("bm-path")?n.getNamedItem("bm-path").value:"",i.animType=n.getNamedItem("data-anim-type")?n.getNamedItem("data-anim-type").value:n.getNamedItem("data-bm-type")?n.getNamedItem("data-bm-type").value:n.getNamedItem("bm-type")?n.getNamedItem("bm-type").value:n.getNamedItem("data-bm-renderer")?n.getNamedItem("data-bm-renderer").value:n.getNamedItem("bm-renderer")?n.getNamedItem("bm-renderer").value:"canvas";var r=n.getNamedItem("data-anim-loop")?n.getNamedItem("data-anim-loop").value:n.getNamedItem("data-bm-loop")?n.getNamedItem("data-bm-loop").value:n.getNamedItem("bm-loop")?n.getNamedItem("bm-loop").value:"";"false"===r?i.loop=!1:"true"===r?i.loop=!0:""!==r&&(i.loop=parseInt(r,10));var a=n.getNamedItem("data-anim-autoplay")?n.getNamedItem("data-anim-autoplay").value:n.getNamedItem("data-bm-autoplay")?n.getNamedItem("data-bm-autoplay").value:!n.getNamedItem("bm-autoplay")||n.getNamedItem("bm-autoplay").value;i.autoplay="false"!==a,i.name=n.getNamedItem("data-name")?n.getNamedItem("data-name").value:n.getNamedItem("data-bm-name")?n.getNamedItem("data-bm-name").value:n.getNamedItem("bm-name")?n.getNamedItem("bm-name").value:"","false"===(n.getNamedItem("data-anim-prerender")?n.getNamedItem("data-anim-prerender").value:n.getNamedItem("data-bm-prerender")?n.getNamedItem("data-bm-prerender").value:n.getNamedItem("bm-prerender")?n.getNamedItem("bm-prerender").value:"")&&(i.prerender=!1),this.setParams(i)},AnimationItem.prototype.includeLayers=function(e){e.op>this.animationData.op&&(this.animationData.op=e.op,this.totalFrames=Math.floor(e.op-this.animationData.ip));var t,i,n=this.animationData.layers,r=n.length,a=e.layers,s=a.length;for(i=0;i<s;i+=1)for(t=0;t<r;){if(n[t].id===a[i].id){n[t]=a[i];break}t+=1}if((e.chars||e.fonts)&&(this.renderer.globalData.fontManager.addChars(e.chars),this.renderer.globalData.fontManager.addFonts(e.fonts,this.renderer.globalData.defs)),e.assets)for(r=e.assets.length,t=0;t<r;t+=1)this.animationData.assets.push(e.assets[t]);this.animationData.__complete=!1,dataManager.completeAnimation(this.animationData,this.onSegmentComplete)},AnimationItem.prototype.onSegmentComplete=function(e){this.animationData=e;var t=getExpressionsPlugin();t&&t.initExpressions(this),this.loadNextSegment()},AnimationItem.prototype.loadNextSegment=function(){var e=this.animationData.segments;if(!e||0===e.length||!this.autoloadSegments)return this.trigger("data_ready"),void(this.timeCompleted=this.totalFrames);var t=e.shift();this.timeCompleted=t.time*this.frameRate;var i=this.path+this.fileName+"_"+this.segmentPos+".json";this.segmentPos+=1,dataManager.loadData(i,this.includeLayers.bind(this),function(){this.trigger("data_failed")}.bind(this))},AnimationItem.prototype.loadSegments=function(){this.animationData.segments||(this.timeCompleted=this.totalFrames),this.loadNextSegment()},AnimationItem.prototype.imagesLoaded=function(){this.trigger("loaded_images"),this.checkLoaded()},AnimationItem.prototype.preloadImages=function(){this.imagePreloader.setAssetsPath(this.assetsPath),this.imagePreloader.setPath(this.path),this.imagePreloader.loadAssets(this.animationData.assets,this.imagesLoaded.bind(this))},AnimationItem.prototype.configAnimation=function(e){if(this.renderer)try{this.animationData=e,this.initialSegment?(this.totalFrames=Math.floor(this.initialSegment[1]-this.initialSegment[0]),this.firstFrame=Math.round(this.initialSegment[0])):(this.totalFrames=Math.floor(this.animationData.op-this.animationData.ip),this.firstFrame=Math.round(this.animationData.ip)),this.renderer.configAnimation(e),e.assets||(e.assets=[]),this.assets=this.animationData.assets,this.frameRate=this.animationData.fr,this.frameMult=this.animationData.fr/1e3,this.renderer.searchExtraCompositions(e.assets),this.markers=markerParser(e.markers||[]),this.trigger("config_ready"),this.preloadImages(),this.loadSegments(),this.updaFrameModifier(),this.waitForFontsLoaded(),this.isPaused&&this.audioController.pause()}catch(e){this.triggerConfigError(e)}},AnimationItem.prototype.waitForFontsLoaded=function(){this.renderer&&(this.renderer.globalData.fontManager.isLoaded?this.checkLoaded():setTimeout(this.waitForFontsLoaded.bind(this),20))},AnimationItem.prototype.checkLoaded=function(){if(!this.isLoaded&&this.renderer.globalData.fontManager.isLoaded&&(this.imagePreloader.loadedImages()||"canvas"!==this.renderer.rendererType)&&this.imagePreloader.loadedFootages()){this.isLoaded=!0;var e=getExpressionsPlugin();e&&e.initExpressions(this),this.renderer.initItems(),setTimeout(function(){this.trigger("DOMLoaded")}.bind(this),0),this.gotoFrame(),this.autoplay&&this.play()}},AnimationItem.prototype.resize=function(e,t){var i="number"==typeof e?e:void 0,n="number"==typeof t?t:void 0;this.renderer.updateContainerSize(i,n)},AnimationItem.prototype.setSubframe=function(e){this.isSubframeEnabled=!!e},AnimationItem.prototype.gotoFrame=function(){this.currentFrame=this.isSubframeEnabled?this.currentRawFrame:~~this.currentRawFrame,this.timeCompleted!==this.totalFrames&&this.currentFrame>this.timeCompleted&&(this.currentFrame=this.timeCompleted),this.trigger("enterFrame"),this.renderFrame(),this.trigger("drawnFrame")},AnimationItem.prototype.renderFrame=function(){if(!1!==this.isLoaded&&this.renderer)try{this.renderer.renderFrame(this.currentFrame+this.firstFrame)}catch(e){this.triggerRenderFrameError(e)}},AnimationItem.prototype.play=function(e){e&&this.name!==e||!0===this.isPaused&&(this.isPaused=!1,this.trigger("_pause"),this.audioController.resume(),this._idle&&(this._idle=!1,this.trigger("_active")))},AnimationItem.prototype.pause=function(e){e&&this.name!==e||!1===this.isPaused&&(this.isPaused=!0,this.trigger("_play"),this._idle=!0,this.trigger("_idle"),this.audioController.pause())},AnimationItem.prototype.togglePause=function(e){e&&this.name!==e||(!0===this.isPaused?this.play():this.pause())},AnimationItem.prototype.stop=function(e){e&&this.name!==e||(this.pause(),this.playCount=0,this._completedLoop=!1,this.setCurrentRawFrameValue(0))},AnimationItem.prototype.getMarkerData=function(e){for(var t,i=0;i<this.markers.length;i+=1)if((t=this.markers[i]).payload&&t.payload.name===e)return t;return null},AnimationItem.prototype.goToAndStop=function(e,t,i){if(!i||this.name===i){var n=Number(e);if(isNaN(n)){var r=this.getMarkerData(e);r&&this.goToAndStop(r.time,!0)}else t?this.setCurrentRawFrameValue(e):this.setCurrentRawFrameValue(e*this.frameModifier);this.pause()}},AnimationItem.prototype.goToAndPlay=function(e,t,i){if(!i||this.name===i){var n=Number(e);if(isNaN(n)){var r=this.getMarkerData(e);r&&(r.duration?this.playSegments([r.time,r.time+r.duration],!0):this.goToAndStop(r.time,!0))}else this.goToAndStop(n,t,i);this.play()}},AnimationItem.prototype.advanceTime=function(e){if(!0!==this.isPaused&&!1!==this.isLoaded){var t=this.currentRawFrame+e*this.frameModifier,i=!1;t>=this.totalFrames-1&&this.frameModifier>0?this.loop&&this.playCount!==this.loop?t>=this.totalFrames?(this.playCount+=1,this.checkSegments(t%this.totalFrames)||(this.setCurrentRawFrameValue(t%this.totalFrames),this._completedLoop=!0,this.trigger("loopComplete"))):this.setCurrentRawFrameValue(t):this.checkSegments(t>this.totalFrames?t%this.totalFrames:0)||(i=!0,t=this.totalFrames-1):t<0?this.checkSegments(t%this.totalFrames)||(!this.loop||this.playCount--<=0&&!0!==this.loop?(i=!0,t=0):(this.setCurrentRawFrameValue(this.totalFrames+t%this.totalFrames),this._completedLoop?this.trigger("loopComplete"):this._completedLoop=!0)):this.setCurrentRawFrameValue(t),i&&(this.setCurrentRawFrameValue(t),this.pause(),this.trigger("complete"))}},AnimationItem.prototype.adjustSegment=function(e,t){this.playCount=0,e[1]<e[0]?(this.frameModifier>0&&(this.playSpeed<0?this.setSpeed(-this.playSpeed):this.setDirection(-1)),this.totalFrames=e[0]-e[1],this.timeCompleted=this.totalFrames,this.firstFrame=e[1],this.setCurrentRawFrameValue(this.totalFrames-.001-t)):e[1]>e[0]&&(this.frameModifier<0&&(this.playSpeed<0?this.setSpeed(-this.playSpeed):this.setDirection(1)),this.totalFrames=e[1]-e[0],this.timeCompleted=this.totalFrames,this.firstFrame=e[0],this.setCurrentRawFrameValue(.001+t)),this.trigger("segmentStart")},AnimationItem.prototype.setSegment=function(e,t){var i=-1;this.isPaused&&(this.currentRawFrame+this.firstFrame<e?i=e:this.currentRawFrame+this.firstFrame>t&&(i=t-e)),this.firstFrame=e,this.totalFrames=t-e,this.timeCompleted=this.totalFrames,-1!==i&&this.goToAndStop(i,!0)},AnimationItem.prototype.playSegments=function(e,t){if(t&&(this.segments.length=0),"object"===_typeof$4(e[0])){var i,n=e.length;for(i=0;i<n;i+=1)this.segments.push(e[i])}else this.segments.push(e);this.segments.length&&t&&this.adjustSegment(this.segments.shift(),0),this.isPaused&&this.play()},AnimationItem.prototype.resetSegments=function(e){this.segments.length=0,this.segments.push([this.animationData.ip,this.animationData.op]),e&&this.checkSegments(0)},AnimationItem.prototype.checkSegments=function(e){return!!this.segments.length&&(this.adjustSegment(this.segments.shift(),e),!0)},AnimationItem.prototype.destroy=function(e){e&&this.name!==e||!this.renderer||(this.renderer.destroy(),this.imagePreloader.destroy(),this.trigger("destroy"),this._cbs=null,this.onEnterFrame=null,this.onLoopComplete=null,this.onComplete=null,this.onSegmentStart=null,this.onDestroy=null,this.renderer=null,this.renderer=null,this.imagePreloader=null,this.projectInterface=null)},AnimationItem.prototype.setCurrentRawFrameValue=function(e){this.currentRawFrame=e,this.gotoFrame()},AnimationItem.prototype.setSpeed=function(e){this.playSpeed=e,this.updaFrameModifier()},AnimationItem.prototype.setDirection=function(e){this.playDirection=e<0?-1:1,this.updaFrameModifier()},AnimationItem.prototype.setLoop=function(e){this.loop=e},AnimationItem.prototype.setVolume=function(e,t){t&&this.name!==t||this.audioController.setVolume(e)},AnimationItem.prototype.getVolume=function(){return this.audioController.getVolume()},AnimationItem.prototype.mute=function(e){e&&this.name!==e||this.audioController.mute()},AnimationItem.prototype.unmute=function(e){e&&this.name!==e||this.audioController.unmute()},AnimationItem.prototype.updaFrameModifier=function(){this.frameModifier=this.frameMult*this.playSpeed*this.playDirection,this.audioController.setRate(this.playSpeed*this.playDirection)},AnimationItem.prototype.getPath=function(){return this.path},AnimationItem.prototype.getAssetsPath=function(e){var t="";if(e.e)t=e.p;else if(this.assetsPath){var i=e.p;-1!==i.indexOf("images/")&&(i=i.split("/")[1]),t=this.assetsPath+i}else t=this.path,t+=e.u?e.u:"",t+=e.p;return t},AnimationItem.prototype.getAssetData=function(e){for(var t=0,i=this.assets.length;t<i;){if(e===this.assets[t].id)return this.assets[t];t+=1}return null},AnimationItem.prototype.hide=function(){this.renderer.hide()},AnimationItem.prototype.show=function(){this.renderer.show()},AnimationItem.prototype.getDuration=function(e){return e?this.totalFrames:this.totalFrames/this.frameRate},AnimationItem.prototype.updateDocumentData=function(e,t,i){try{this.renderer.getElementByPath(e).updateDocumentData(t,i)}catch(e){}},AnimationItem.prototype.trigger=function(e){if(this._cbs&&this._cbs[e])switch(e){case"enterFrame":this.triggerEvent(e,new BMEnterFrameEvent(e,this.currentFrame,this.totalFrames,this.frameModifier));break;case"drawnFrame":this.drawnFrameEvent.currentTime=this.currentFrame,this.drawnFrameEvent.totalTime=this.totalFrames,this.drawnFrameEvent.direction=this.frameModifier,this.triggerEvent(e,this.drawnFrameEvent);break;case"loopComplete":this.triggerEvent(e,new BMCompleteLoopEvent(e,this.loop,this.playCount,this.frameMult));break;case"complete":this.triggerEvent(e,new BMCompleteEvent(e,this.frameMult));break;case"segmentStart":this.triggerEvent(e,new BMSegmentStartEvent(e,this.firstFrame,this.totalFrames));break;case"destroy":this.triggerEvent(e,new BMDestroyEvent(e,this));break;default:this.triggerEvent(e)}"enterFrame"===e&&this.onEnterFrame&&this.onEnterFrame.call(this,new BMEnterFrameEvent(e,this.currentFrame,this.totalFrames,this.frameMult)),"loopComplete"===e&&this.onLoopComplete&&this.onLoopComplete.call(this,new BMCompleteLoopEvent(e,this.loop,this.playCount,this.frameMult)),"complete"===e&&this.onComplete&&this.onComplete.call(this,new BMCompleteEvent(e,this.frameMult)),"segmentStart"===e&&this.onSegmentStart&&this.onSegmentStart.call(this,new BMSegmentStartEvent(e,this.firstFrame,this.totalFrames)),"destroy"===e&&this.onDestroy&&this.onDestroy.call(this,new BMDestroyEvent(e,this))},AnimationItem.prototype.triggerRenderFrameError=function(e){var t=new BMRenderFrameErrorEvent(e,this.currentFrame);this.triggerEvent("error",t),this.onError&&this.onError.call(this,t)},AnimationItem.prototype.triggerConfigError=function(e){var t=new BMConfigErrorEvent(e,this.currentFrame);this.triggerEvent("error",t),this.onError&&this.onError.call(this,t)};var animationManager=function(){var e={},r=[],n=0,a=0,s=0,o=!0,l=!1;function i(e){for(var t=0,i=e.target;t<a;)r[t].animation===i&&(r.splice(t,1),t-=1,a-=1,i.isPaused||p()),t+=1}function u(e,t){if(!e)return null;for(var i=0;i<a;){if(r[i].elem===e&&null!==r[i].elem)return r[i].animation;i+=1}var n=new AnimationItem;return c(n,e),n.setData(e,t),n}function h(){s+=1,f()}function p(){s-=1}function c(e,t){e.addEventListener("destroy",i),e.addEventListener("_active",h),e.addEventListener("_idle",p),r.push({elem:t,animation:e}),a+=1}function m(e){var t,i=e-n;for(t=0;t<a;t+=1)r[t].animation.advanceTime(i);n=e,s&&!l?window.requestAnimationFrame(m):o=!0}function t(e){n=e,window.requestAnimationFrame(m)}function f(){!l&&s&&o&&(window.requestAnimationFrame(t),o=!1)}return e.registerAnimation=u,e.loadAnimation=function(e){var t=new AnimationItem;return c(t,null),t.setParams(e),t},e.setSpeed=function(e,t){var i;for(i=0;i<a;i+=1)r[i].animation.setSpeed(e,t)},e.setDirection=function(e,t){var i;for(i=0;i<a;i+=1)r[i].animation.setDirection(e,t)},e.play=function(e){var t;for(t=0;t<a;t+=1)r[t].animation.play(e)},e.pause=function(e){var t;for(t=0;t<a;t+=1)r[t].animation.pause(e)},e.stop=function(e){var t;for(t=0;t<a;t+=1)r[t].animation.stop(e)},e.togglePause=function(e){var t;for(t=0;t<a;t+=1)r[t].animation.togglePause(e)},e.searchAnimations=function(e,t,i){var n,r=[].concat([].slice.call(document.getElementsByClassName("lottie")),[].slice.call(document.getElementsByClassName("bodymovin"))),a=r.length;for(n=0;n<a;n+=1)i&&r[n].setAttribute("data-bm-type",i),u(r[n],e);if(t&&0===a){i||(i="svg");var s=document.getElementsByTagName("body")[0];s.innerText="";var o=createTag("div");o.style.width="100%",o.style.height="100%",o.setAttribute("data-bm-type",i),s.appendChild(o),u(o,e)}},e.resize=function(){var e;for(e=0;e<a;e+=1)r[e].animation.resize()},e.goToAndStop=function(e,t,i){var n;for(n=0;n<a;n+=1)r[n].animation.goToAndStop(e,t,i)},e.destroy=function(e){var t;for(t=a-1;t>=0;t-=1)r[t].animation.destroy(e)},e.freeze=function(){l=!0},e.unfreeze=function(){l=!1,f()},e.setVolume=function(e,t){var i;for(i=0;i<a;i+=1)r[i].animation.setVolume(e,t)},e.mute=function(e){var t;for(t=0;t<a;t+=1)r[t].animation.mute(e)},e.unmute=function(e){var t;for(t=0;t<a;t+=1)r[t].animation.unmute(e)},e.getRegisteredAnimations=function(){var e,t=r.length,i=[];for(e=0;e<t;e+=1)i.push(r[e].animation);return i},e}(),BezierFactory=function(){var e={getBezierEasing:function(e,t,i,n,r){var a=r||("bez_"+e+"_"+t+"_"+i+"_"+n).replace(/\./g,"p");if(o[a])return o[a];var s=new p([e,t,i,n]);return o[a]=s,s}},o={};var l=.1,t="function"==typeof Float32Array;function n(e,t){return 1-3*t+3*e}function r(e,t){return 3*t-6*e}function a(e){return 3*e}function u(e,t,i){return((n(t,i)*e+r(t,i))*e+a(t))*e}function h(e,t,i){return 3*n(t,i)*e*e+2*r(t,i)*e+a(t)}function p(e){this._p=e,this._mSampleValues=t?new Float32Array(11):new Array(11),this._precomputed=!1,this.get=this.get.bind(this)}return p.prototype={get:function(e){var t=this._p[0],i=this._p[1],n=this._p[2],r=this._p[3];return this._precomputed||this._precompute(),t===i&&n===r?e:0===e?0:1===e?1:u(this._getTForX(e),i,r)},_precompute:function(){var e=this._p[0],t=this._p[1],i=this._p[2],n=this._p[3];this._precomputed=!0,e===t&&i===n||this._calcSampleValues()},_calcSampleValues:function(){for(var e=this._p[0],t=this._p[2],i=0;i<11;++i)this._mSampleValues[i]=u(i*l,e,t)},_getTForX:function(e){for(var t=this._p[0],i=this._p[2],n=this._mSampleValues,r=0,a=1;10!==a&&n[a]<=e;++a)r+=l;var s=r+(e-n[--a])/(n[a+1]-n[a])*l,o=h(s,t,i);return o>=.001?function(e,t,i,n){for(var r=0;r<4;++r){var a=h(t,i,n);if(0===a)return t;t-=(u(t,i,n)-e)/a}return t}(e,s,t,i):0===o?s:function(e,t,i,n,r){var a,s,o=0;do{(a=u(s=t+(i-t)/2,n,r)-e)>0?i=s:t=s}while(Math.abs(a)>1e-7&&++o<10);return s}(e,r,r+l,t,i)}},e}(),pooling={double:function(e){return e.concat(createSizedArray(e.length))}},poolFactory=function(e,t,i){var n=0,r=e,a=createSizedArray(r);return{newElement:function(){return n?a[n-=1]:t()},release:function(e){n===r&&(a=pooling.double(a),r*=2),i&&i(e),a[n]=e,n+=1}}},bezierLengthPool=poolFactory(8,function(){return{addedLength:0,percents:createTypedArray("float32",getDefaultCurveSegments()),lengths:createTypedArray("float32",getDefaultCurveSegments())}}),segmentsLengthPool=poolFactory(8,function(){return{lengths:[],totalLength:0}},function(e){var t,i=e.lengths.length;for(t=0;t<i;t+=1)bezierLengthPool.release(e.lengths[t]);e.lengths.length=0});function bezFunction(){var P=Math;function g(e,t,i,n,r,a){var s=e*n+t*r+i*a-r*n-a*e-i*t;return s>-.001&&s<.001}var h=function(e,t,i,n){var r,a,s,o,l,u,h=getDefaultCurveSegments(),p=0,c=[],m=[],f=bezierLengthPool.newElement();for(s=i.length,r=0;r<h;r+=1){for(l=r/(h-1),u=0,a=0;a<s;a+=1)o=bmPow(1-l,3)*e[a]+3*bmPow(1-l,2)*l*i[a]+3*(1-l)*bmPow(l,2)*n[a]+bmPow(l,3)*t[a],c[a]=o,null!==m[a]&&(u+=bmPow(c[a]-m[a],2)),m[a]=c[a];u&&(p+=u=bmSqrt(u)),f.percents[r]=l,f.lengths[r]=p}return f.addedLength=p,f};function v(e){this.segmentLength=0,this.points=new Array(e)}function y(e,t){this.partialLength=e,this.point=t}var b,e=(b={},function(e,t,i,n){var r=(e[0]+"_"+e[1]+"_"+t[0]+"_"+t[1]+"_"+i[0]+"_"+i[1]+"_"+n[0]+"_"+n[1]).replace(/\./g,"p");if(!b[r]){var a,s,o,l,u,h,p,c=getDefaultCurveSegments(),m=0,f=null;2===e.length&&(e[0]!==t[0]||e[1]!==t[1])&&g(e[0],e[1],t[0],t[1],e[0]+i[0],e[1]+i[1])&&g(e[0],e[1],t[0],t[1],t[0]+n[0],t[1]+n[1])&&(c=2);var d=new v(c);for(o=i.length,a=0;a<c;a+=1){for(p=createSizedArray(o),u=a/(c-1),h=0,s=0;s<o;s+=1)l=bmPow(1-u,3)*e[s]+3*bmPow(1-u,2)*u*(e[s]+i[s])+3*(1-u)*bmPow(u,2)*(t[s]+n[s])+bmPow(u,3)*t[s],p[s]=l,null!==f&&(h+=bmPow(p[s]-f[s],2));m+=h=bmSqrt(h),d.points[a]=new y(h,p),f=p}d.segmentLength=m,b[r]=d}return b[r]});function M(e,t){var i=t.percents,n=t.lengths,r=i.length,a=bmFloor((r-1)*e),s=e*t.addedLength,o=0;if(a===r-1||0===a||s===n[a])return i[a];for(var l=n[a]>s?-1:1,u=!0;u;)if(n[a]<=s&&n[a+1]>s?(o=(s-n[a])/(n[a+1]-n[a]),u=!1):a+=l,a<0||a>=r-1){if(a===r-1)return i[a];u=!1}return i[a]+(i[a+1]-i[a])*o}var L=createTypedArray("float32",8);return{getSegmentsLength:function(e){var t,i=segmentsLengthPool.newElement(),n=e.c,r=e.v,a=e.o,s=e.i,o=e._length,l=i.lengths,u=0;for(t=0;t<o-1;t+=1)l[t]=h(r[t],r[t+1],a[t],s[t+1]),u+=l[t].addedLength;return n&&o&&(l[t]=h(r[t],r[0],a[t],s[0]),u+=l[t].addedLength),i.totalLength=u,i},getNewSegment:function(e,t,i,n,r,a,s){r<0?r=0:r>1&&(r=1);var o,l=M(r,s),u=M(a=a>1?1:a,s),h=e.length,p=1-l,c=1-u,m=p*p*p,f=l*p*p*3,d=l*l*p*3,g=l*l*l,v=p*p*c,y=l*p*c+p*l*c+p*p*u,b=l*l*c+p*l*u+l*p*u,x=l*l*u,A=p*c*c,_=l*c*c+p*u*c+p*c*u,S=l*u*c+p*u*u+l*c*u,C=l*u*u,T=c*c*c,I=u*c*c+c*u*c+c*c*u,O=u*u*c+c*u*u+u*c*u,E=u*u*u;for(o=0;o<h;o+=1)L[4*o]=P.round(1e3*(m*e[o]+f*i[o]+d*n[o]+g*t[o]))/1e3,L[4*o+1]=P.round(1e3*(v*e[o]+y*i[o]+b*n[o]+x*t[o]))/1e3,L[4*o+2]=P.round(1e3*(A*e[o]+_*i[o]+S*n[o]+C*t[o]))/1e3,L[4*o+3]=P.round(1e3*(T*e[o]+I*i[o]+O*n[o]+E*t[o]))/1e3;return L},getPointInSegment:function(e,t,i,n,r,a){var s=M(r,a),o=1-s;return[P.round(1e3*(o*o*o*e[0]+(s*o*o+o*s*o+o*o*s)*i[0]+(s*s*o+o*s*s+s*o*s)*n[0]+s*s*s*t[0]))/1e3,P.round(1e3*(o*o*o*e[1]+(s*o*o+o*s*o+o*o*s)*i[1]+(s*s*o+o*s*s+s*o*s)*n[1]+s*s*s*t[1]))/1e3]},buildBezierData:e,pointOnLine2D:g,pointOnLine3D:function(e,t,i,n,r,a,s,o,l){if(0===i&&0===a&&0===l)return g(e,t,n,r,s,o);var u,h=P.sqrt(P.pow(n-e,2)+P.pow(r-t,2)+P.pow(a-i,2)),p=P.sqrt(P.pow(s-e,2)+P.pow(o-t,2)+P.pow(l-i,2)),c=P.sqrt(P.pow(s-n,2)+P.pow(o-r,2)+P.pow(l-a,2));return(u=h>p?h>c?h-p-c:c-p-h:c>p?c-p-h:p-h-c)>-1e-4&&u<1e-4}}}var bez=bezFunction(),PropertyFactory=function(){var p=initialDefaultFrame,r=Math.abs;function c(e,t){var i,n=this.offsetTime;"multidimensional"===this.propType&&(i=createTypedArray("float32",this.pv.length));for(var r,a,s,o,l,u,h,p,c,m=t.lastIndex,f=m,d=this.keyframes.length-1,g=!0;g;){if(r=this.keyframes[f],a=this.keyframes[f+1],f===d-1&&e>=a.t-n){r.h&&(r=a),m=0;break}if(a.t-n>e){m=f;break}f<d-1?f+=1:(m=0,g=!1)}s=this.keyframesMetadata[f]||{};var v,y,b,x,A,_,S,C,T,V,I=a.t-n,O=r.t-n;if(r.to){s.bezierData||(s.bezierData=bez.buildBezierData(r.s,a.s||r.e,r.to,r.ti));var E=s.bezierData;if(e>=I||e<O){var D=e>=I?E.points.length-1:0;for(l=E.points[D].point.length,o=0;o<l;o+=1)i[o]=E.points[D].point[o]}else{s.__fnct?c=s.__fnct:(c=BezierFactory.getBezierEasing(r.o.x,r.o.y,r.i.x,r.i.y,r.n).get,s.__fnct=c),u=c((e-O)/(I-O));var B,P=E.segmentLength*u,M=t.lastFrame<e&&t._lastKeyframeIndex===f?t._lastAddedLength:0;for(p=t.lastFrame<e&&t._lastKeyframeIndex===f?t._lastPoint:0,g=!0,h=E.points.length;g;){if(M+=E.points[p].partialLength,0===P||0===u||p===E.points.length-1){for(l=E.points[p].point.length,o=0;o<l;o+=1)i[o]=E.points[p].point[o];break}if(P>=M&&P<M+E.points[p+1].partialLength){for(B=(P-M)/E.points[p+1].partialLength,l=E.points[p].point.length,o=0;o<l;o+=1)i[o]=E.points[p].point[o]+(E.points[p+1].point[o]-E.points[p].point[o])*B;break}p<h-1?p+=1:g=!1}t._lastPoint=p,t._lastAddedLength=M-E.points[p].partialLength,t._lastKeyframeIndex=f}}else{var L,N,k,w,R;if(d=r.s.length,v=a.s||r.e,this.sh&&1!==r.h)if(e>=I)i[0]=v[0],i[1]=v[1],i[2]=v[2];else if(e<=O)i[0]=r.s[0],i[1]=r.s[1],i[2]=r.s[2];else{var j=U(r.s),F=U(v);y=i,b=function(e,t,i){var n,r,a,s,o,l=[],u=e[0],h=e[1],p=e[2],c=e[3],m=t[0],f=t[1],d=t[2],g=t[3];return(r=u*m+h*f+p*d+c*g)<0&&(r=-r,m=-m,f=-f,d=-d,g=-g),1-r>1e-6?(n=Math.acos(r),a=Math.sin(n),s=Math.sin((1-i)*n)/a,o=Math.sin(i*n)/a):(s=1-i,o=i),l[0]=s*u+o*m,l[1]=s*h+o*f,l[2]=s*p+o*d,l[3]=s*c+o*g,l}(j,F,(e-O)/(I-O)),x=b[0],A=b[1],_=b[2],S=b[3],C=Math.atan2(2*A*S-2*x*_,1-2*A*A-2*_*_),T=Math.asin(2*x*A+2*_*S),V=Math.atan2(2*x*S-2*A*_,1-2*x*x-2*_*_),y[0]=C/degToRads,y[1]=T/degToRads,y[2]=V/degToRads}else for(f=0;f<d;f+=1)1!==r.h&&(e>=I?u=1:e<O?u=0:(r.o.x.constructor===Array?(s.__fnct||(s.__fnct=[]),s.__fnct[f]?c=s.__fnct[f]:(L=void 0===r.o.x[f]?r.o.x[0]:r.o.x[f],N=void 0===r.o.y[f]?r.o.y[0]:r.o.y[f],k=void 0===r.i.x[f]?r.i.x[0]:r.i.x[f],w=void 0===r.i.y[f]?r.i.y[0]:r.i.y[f],c=BezierFactory.getBezierEasing(L,N,k,w).get,s.__fnct[f]=c)):s.__fnct?c=s.__fnct:(L=r.o.x,N=r.o.y,k=r.i.x,w=r.i.y,c=BezierFactory.getBezierEasing(L,N,k,w).get,r.keyframeMetadata=c),u=c((e-O)/(I-O)))),v=a.s||r.e,R=1===r.h?r.s[f]:r.s[f]+(v[f]-r.s[f])*u,"multidimensional"===this.propType?i[f]=R:i=R}return t.lastIndex=m,i}function U(e){var t=e[0]*degToRads,i=e[1]*degToRads,n=e[2]*degToRads,r=Math.cos(t/2),a=Math.cos(i/2),s=Math.cos(n/2),o=Math.sin(t/2),l=Math.sin(i/2),u=Math.sin(n/2);return[o*l*s+r*a*u,o*a*s+r*l*u,r*l*s-o*a*u,r*a*s-o*l*u]}function m(){var e=this.comp.renderedFrame-this.offsetTime,t=this.keyframes[0].t-this.offsetTime,i=this.keyframes[this.keyframes.length-1].t-this.offsetTime;if(!(e===this._caching.lastFrame||this._caching.lastFrame!==p&&(this._caching.lastFrame>=i&&e>=i||this._caching.lastFrame<t&&e<t))){this._caching.lastFrame>=e&&(this._caching._lastKeyframeIndex=-1,this._caching.lastIndex=0);var n=this.interpolateValue(e,this._caching);this.pv=n}return this._caching.lastFrame=e,this.pv}function f(e){var t;if("unidimensional"===this.propType)t=e*this.mult,r(this.v-t)>1e-5&&(this.v=t,this._mdf=!0);else for(var i=0,n=this.v.length;i<n;)t=e[i]*this.mult,r(this.v[i]-t)>1e-5&&(this.v[i]=t,this._mdf=!0),i+=1}function d(){if(this.elem.globalData.frameId!==this.frameId&&this.effectsSequence.length)if(this.lock)this.setVValue(this.pv);else{var e;this.lock=!0,this._mdf=this._isFirstFrame;var t=this.effectsSequence.length,i=this.kf?this.pv:this.data.k;for(e=0;e<t;e+=1)i=this.effectsSequence[e](i);this.setVValue(i),this._isFirstFrame=!1,this.lock=!1,this.frameId=this.elem.globalData.frameId}}function g(e){this.effectsSequence.push(e),this.container.addDynamicProperty(this)}function s(e,t,i,n){this.propType="unidimensional",this.mult=i||1,this.data=t,this.v=i?t.k*i:t.k,this.pv=t.k,this._mdf=!1,this.elem=e,this.container=n,this.comp=e.comp,this.k=!1,this.kf=!1,this.vel=0,this.effectsSequence=[],this._isFirstFrame=!0,this.getValue=d,this.setVValue=f,this.addEffect=g}function o(e,t,i,n){var r;this.propType="multidimensional",this.mult=i||1,this.data=t,this._mdf=!1,this.elem=e,this.container=n,this.comp=e.comp,this.k=!1,this.kf=!1,this.frameId=-1;var a=t.k.length;for(this.v=createTypedArray("float32",a),this.pv=createTypedArray("float32",a),this.vel=createTypedArray("float32",a),r=0;r<a;r+=1)this.v[r]=t.k[r]*this.mult,this.pv[r]=t.k[r];this._isFirstFrame=!0,this.effectsSequence=[],this.getValue=d,this.setVValue=f,this.addEffect=g}function l(e,t,i,n){this.propType="unidimensional",this.keyframes=t.k,this.keyframesMetadata=[],this.offsetTime=e.data.st,this.frameId=-1,this._caching={lastFrame:p,lastIndex:0,value:0,_lastKeyframeIndex:-1},this.k=!0,this.kf=!0,this.data=t,this.mult=i||1,this.elem=e,this.container=n,this.comp=e.comp,this.v=p,this.pv=p,this._isFirstFrame=!0,this.getValue=d,this.setVValue=f,this.interpolateValue=c,this.effectsSequence=[m.bind(this)],this.addEffect=g}function u(e,t,i,n){var r;this.propType="multidimensional";var a,s,o,l,u=t.k.length;for(r=0;r<u-1;r+=1)t.k[r].to&&t.k[r].s&&t.k[r+1]&&t.k[r+1].s&&(a=t.k[r].s,s=t.k[r+1].s,o=t.k[r].to,l=t.k[r].ti,(2===a.length&&(a[0]!==s[0]||a[1]!==s[1])&&bez.pointOnLine2D(a[0],a[1],s[0],s[1],a[0]+o[0],a[1]+o[1])&&bez.pointOnLine2D(a[0],a[1],s[0],s[1],s[0]+l[0],s[1]+l[1])||3===a.length&&(a[0]!==s[0]||a[1]!==s[1]||a[2]!==s[2])&&bez.pointOnLine3D(a[0],a[1],a[2],s[0],s[1],s[2],a[0]+o[0],a[1]+o[1],a[2]+o[2])&&bez.pointOnLine3D(a[0],a[1],a[2],s[0],s[1],s[2],s[0]+l[0],s[1]+l[1],s[2]+l[2]))&&(t.k[r].to=null,t.k[r].ti=null),a[0]===s[0]&&a[1]===s[1]&&0===o[0]&&0===o[1]&&0===l[0]&&0===l[1]&&(2===a.length||a[2]===s[2]&&0===o[2]&&0===l[2])&&(t.k[r].to=null,t.k[r].ti=null));this.effectsSequence=[m.bind(this)],this.data=t,this.keyframes=t.k,this.keyframesMetadata=[],this.offsetTime=e.data.st,this.k=!0,this.kf=!0,this._isFirstFrame=!0,this.mult=i||1,this.elem=e,this.container=n,this.comp=e.comp,this.getValue=d,this.setVValue=f,this.interpolateValue=c,this.frameId=-1;var h=t.k[0].s.length;for(this.v=createTypedArray("float32",h),this.pv=createTypedArray("float32",h),r=0;r<h;r+=1)this.v[r]=p,this.pv[r]=p;this._caching={lastFrame:p,lastIndex:0,value:createTypedArray("float32",h)},this.addEffect=g}return{getProp:function(e,t,i,n,r){var a;if(t.k.length)if("number"==typeof t.k[0])a=new o(e,t,n,r);else switch(i){case 0:a=new l(e,t,n,r);break;case 1:a=new u(e,t,n,r)}else a=new s(e,t,n,r);return a.effectsSequence.length&&r.addDynamicProperty(a),a}}}();function DynamicPropertyContainer(){}DynamicPropertyContainer.prototype={addDynamicProperty:function(e){-1===this.dynamicProperties.indexOf(e)&&(this.dynamicProperties.push(e),this.container.addDynamicProperty(this),this._isAnimated=!0)},iterateDynamicProperties:function(){var e;this._mdf=!1;var t=this.dynamicProperties.length;for(e=0;e<t;e+=1)this.dynamicProperties[e].getValue(),this.dynamicProperties[e]._mdf&&(this._mdf=!0)},initDynamicPropertyContainer:function(e){this.container=e,this.dynamicProperties=[],this._mdf=!1,this._isAnimated=!1}};var pointPool=poolFactory(8,function(){return createTypedArray("float32",2)});function ShapePath(){this.c=!1,this._length=0,this._maxLength=8,this.v=createSizedArray(this._maxLength),this.o=createSizedArray(this._maxLength),this.i=createSizedArray(this._maxLength)}ShapePath.prototype.setPathData=function(e,t){this.c=e,this.setLength(t);for(var i=0;i<t;)this.v[i]=pointPool.newElement(),this.o[i]=pointPool.newElement(),this.i[i]=pointPool.newElement(),i+=1},ShapePath.prototype.setLength=function(e){for(;this._maxLength<e;)this.doubleArrayLength();this._length=e},ShapePath.prototype.doubleArrayLength=function(){this.v=this.v.concat(createSizedArray(this._maxLength)),this.i=this.i.concat(createSizedArray(this._maxLength)),this.o=this.o.concat(createSizedArray(this._maxLength)),this._maxLength*=2},ShapePath.prototype.setXYAt=function(e,t,i,n,r){var a;switch(this._length=Math.max(this._length,n+1),this._length>=this._maxLength&&this.doubleArrayLength(),i){case"v":a=this.v;break;case"i":a=this.i;break;case"o":a=this.o;break;default:a=[]}(!a[n]||a[n]&&!r)&&(a[n]=pointPool.newElement()),a[n][0]=e,a[n][1]=t},ShapePath.prototype.setTripleAt=function(e,t,i,n,r,a,s,o){this.setXYAt(e,t,"v",s,o),this.setXYAt(i,n,"o",s,o),this.setXYAt(r,a,"i",s,o)},ShapePath.prototype.reverse=function(){var e=new ShapePath;e.setPathData(this.c,this._length);var t=this.v,i=this.o,n=this.i,r=0;this.c&&(e.setTripleAt(t[0][0],t[0][1],n[0][0],n[0][1],i[0][0],i[0][1],0,!1),r=1);var a,s=this._length-1,o=this._length;for(a=r;a<o;a+=1)e.setTripleAt(t[s][0],t[s][1],n[s][0],n[s][1],i[s][0],i[s][1],a,!1),s-=1;return e},ShapePath.prototype.length=function(){return this._length};var shapePool=(factory=poolFactory(4,function(){return new ShapePath},function(e){var t,i=e._length;for(t=0;t<i;t+=1)pointPool.release(e.v[t]),pointPool.release(e.i[t]),pointPool.release(e.o[t]),e.v[t]=null,e.i[t]=null,e.o[t]=null;e._length=0,e.c=!1}),factory.clone=function(e){var t,i=factory.newElement(),n=void 0===e._length?e.v.length:e._length;for(i.setLength(n),i.c=e.c,t=0;t<n;t+=1)i.setTripleAt(e.v[t][0],e.v[t][1],e.o[t][0],e.o[t][1],e.i[t][0],e.i[t][1],t);return i},factory),factory;function ShapeCollection(){this._length=0,this._maxLength=4,this.shapes=createSizedArray(this._maxLength)}ShapeCollection.prototype.addShape=function(e){this._length===this._maxLength&&(this.shapes=this.shapes.concat(createSizedArray(this._maxLength)),this._maxLength*=2),this.shapes[this._length]=e,this._length+=1},ShapeCollection.prototype.releaseShapes=function(){var e;for(e=0;e<this._length;e+=1)shapePool.release(this.shapes[e]);this._length=0};var shapeCollectionPool=(ob={newShapeCollection:function(){return _length?pool[_length-=1]:new ShapeCollection},release:function(e){var t,i=e._length;for(t=0;t<i;t+=1)shapePool.release(e.shapes[t]);e._length=0,_length===_maxLength&&(pool=pooling.double(pool),_maxLength*=2),pool[_length]=e,_length+=1}},_length=0,_maxLength=4,pool=createSizedArray(_maxLength),ob),ob,_length,_maxLength,pool,ShapePropertyFactory=function(){var r=-999999;function e(e,t,i){var n,r,a,s,o,l,u,h,p,c=i.lastIndex,m=this.keyframes;if(e<m[0].t-this.offsetTime)n=m[0].s[0],a=!0,c=0;else if(e>=m[m.length-1].t-this.offsetTime)n=m[m.length-1].s?m[m.length-1].s[0]:m[m.length-2].e[0],a=!0;else{for(var f,d,g,v=c,y=m.length-1,b=!0;b&&(f=m[v],!((d=m[v+1]).t-this.offsetTime>e));)v<y-1?v+=1:b=!1;if(g=this.keyframesMetadata[v]||{},c=v,!(a=1===f.h)){if(e>=d.t-this.offsetTime)h=1;else if(e<f.t-this.offsetTime)h=0;else{var x;g.__fnct?x=g.__fnct:(x=BezierFactory.getBezierEasing(f.o.x,f.o.y,f.i.x,f.i.y).get,g.__fnct=x),h=x((e-(f.t-this.offsetTime))/(d.t-this.offsetTime-(f.t-this.offsetTime)))}r=d.s?d.s[0]:f.e[0]}n=f.s[0]}for(l=t._length,u=n.i[0].length,i.lastIndex=c,s=0;s<l;s+=1)for(o=0;o<u;o+=1)p=a?n.i[s][o]:n.i[s][o]+(r.i[s][o]-n.i[s][o])*h,t.i[s][o]=p,p=a?n.o[s][o]:n.o[s][o]+(r.o[s][o]-n.o[s][o])*h,t.o[s][o]=p,p=a?n.v[s][o]:n.v[s][o]+(r.v[s][o]-n.v[s][o])*h,t.v[s][o]=p}function a(){var e=this.comp.renderedFrame-this.offsetTime,t=this.keyframes[0].t-this.offsetTime,i=this.keyframes[this.keyframes.length-1].t-this.offsetTime,n=this._caching.lastFrame;return n!==r&&(n<t&&e<t||n>i&&e>i)||(this._caching.lastIndex=n<e?this._caching.lastIndex:0,this.interpolateShape(e,this.pv,this._caching)),this._caching.lastFrame=e,this.pv}function o(){this.paths=this.localShapeCollection}function t(e){(function(e,t){if(e._length!==t._length||e.c!==t.c)return!1;var i,n=e._length;for(i=0;i<n;i+=1)if(e.v[i][0]!==t.v[i][0]||e.v[i][1]!==t.v[i][1]||e.o[i][0]!==t.o[i][0]||e.o[i][1]!==t.o[i][1]||e.i[i][0]!==t.i[i][0]||e.i[i][1]!==t.i[i][1])return!1;return!0})(this.v,e)||(this.v=shapePool.clone(e),this.localShapeCollection.releaseShapes(),this.localShapeCollection.addShape(this.v),this._mdf=!0,this.paths=this.localShapeCollection)}function i(){if(this.elem.globalData.frameId!==this.frameId)if(this.effectsSequence.length)if(this.lock)this.setVValue(this.pv);else{var e,t;this.lock=!0,this._mdf=!1,e=this.kf?this.pv:this.data.ks?this.data.ks.k:this.data.pt.k;var i=this.effectsSequence.length;for(t=0;t<i;t+=1)e=this.effectsSequence[t](e);this.setVValue(e),this.lock=!1,this.frameId=this.elem.globalData.frameId}else this._mdf=!1}function s(e,t,i){this.propType="shape",this.comp=e.comp,this.container=e,this.elem=e,this.data=t,this.k=!1,this.kf=!1,this._mdf=!1;var n=3===i?t.pt.k:t.ks.k;this.v=shapePool.clone(n),this.pv=shapePool.clone(this.v),this.localShapeCollection=shapeCollectionPool.newShapeCollection(),this.paths=this.localShapeCollection,this.paths.addShape(this.v),this.reset=o,this.effectsSequence=[]}function n(e){this.effectsSequence.push(e),this.container.addDynamicProperty(this)}function l(e,t,i){this.propType="shape",this.comp=e.comp,this.elem=e,this.container=e,this.offsetTime=e.data.st,this.keyframes=3===i?t.pt.k:t.ks.k,this.keyframesMetadata=[],this.k=!0,this.kf=!0;var n=this.keyframes[0].s[0].i.length;this.v=shapePool.newElement(),this.v.setPathData(this.keyframes[0].s[0].c,n),this.pv=shapePool.clone(this.v),this.localShapeCollection=shapeCollectionPool.newShapeCollection(),this.paths=this.localShapeCollection,this.paths.addShape(this.v),this.lastFrame=r,this.reset=o,this._caching={lastFrame:r,lastIndex:0},this.effectsSequence=[a.bind(this)]}s.prototype.interpolateShape=e,s.prototype.getValue=i,s.prototype.setVValue=t,s.prototype.addEffect=n,l.prototype.getValue=i,l.prototype.interpolateShape=e,l.prototype.setVValue=t,l.prototype.addEffect=n;var u=function(){var s=roundCorner;function e(e,t){this.v=shapePool.newElement(),this.v.setPathData(!0,4),this.localShapeCollection=shapeCollectionPool.newShapeCollection(),this.paths=this.localShapeCollection,this.localShapeCollection.addShape(this.v),this.d=t.d,this.elem=e,this.comp=e.comp,this.frameId=-1,this.initDynamicPropertyContainer(e),this.p=PropertyFactory.getProp(e,t.p,1,0,this),this.s=PropertyFactory.getProp(e,t.s,1,0,this),this.dynamicProperties.length?this.k=!0:(this.k=!1,this.convertEllToPath())}return e.prototype={reset:o,getValue:function(){this.elem.globalData.frameId!==this.frameId&&(this.frameId=this.elem.globalData.frameId,this.iterateDynamicProperties(),this._mdf&&this.convertEllToPath())},convertEllToPath:function(){var e=this.p.v[0],t=this.p.v[1],i=this.s.v[0]/2,n=this.s.v[1]/2,r=3!==this.d,a=this.v;a.v[0][0]=e,a.v[0][1]=t-n,a.v[1][0]=r?e+i:e-i,a.v[1][1]=t,a.v[2][0]=e,a.v[2][1]=t+n,a.v[3][0]=r?e-i:e+i,a.v[3][1]=t,a.i[0][0]=r?e-i*s:e+i*s,a.i[0][1]=t-n,a.i[1][0]=r?e+i:e-i,a.i[1][1]=t-n*s,a.i[2][0]=r?e+i*s:e-i*s,a.i[2][1]=t+n,a.i[3][0]=r?e-i:e+i,a.i[3][1]=t+n*s,a.o[0][0]=r?e+i*s:e-i*s,a.o[0][1]=t-n,a.o[1][0]=r?e+i:e-i,a.o[1][1]=t+n*s,a.o[2][0]=r?e-i*s:e+i*s,a.o[2][1]=t+n,a.o[3][0]=r?e-i:e+i,a.o[3][1]=t-n*s}},extendPrototype([DynamicPropertyContainer],e),e}(),h=function(){function e(e,t){this.v=shapePool.newElement(),this.v.setPathData(!0,0),this.elem=e,this.comp=e.comp,this.data=t,this.frameId=-1,this.d=t.d,this.initDynamicPropertyContainer(e),1===t.sy?(this.ir=PropertyFactory.getProp(e,t.ir,0,0,this),this.is=PropertyFactory.getProp(e,t.is,0,.01,this),this.convertToPath=this.convertStarToPath):this.convertToPath=this.convertPolygonToPath,this.pt=PropertyFactory.getProp(e,t.pt,0,0,this),this.p=PropertyFactory.getProp(e,t.p,1,0,this),this.r=PropertyFactory.getProp(e,t.r,0,degToRads,this),this.or=PropertyFactory.getProp(e,t.or,0,0,this),this.os=PropertyFactory.getProp(e,t.os,0,.01,this),this.localShapeCollection=shapeCollectionPool.newShapeCollection(),this.localShapeCollection.addShape(this.v),this.paths=this.localShapeCollection,this.dynamicProperties.length?this.k=!0:(this.k=!1,this.convertToPath())}return e.prototype={reset:o,getValue:function(){this.elem.globalData.frameId!==this.frameId&&(this.frameId=this.elem.globalData.frameId,this.iterateDynamicProperties(),this._mdf&&this.convertToPath())},convertStarToPath:function(){var e,t,i,n,r=2*Math.floor(this.pt.v),a=2*Math.PI/r,s=!0,o=this.or.v,l=this.ir.v,u=this.os.v,h=this.is.v,p=2*Math.PI*o/(2*r),c=2*Math.PI*l/(2*r),m=-Math.PI/2;m+=this.r.v;var f=3===this.data.d?-1:1;for(this.v._length=0,e=0;e<r;e+=1){i=s?u:h,n=s?p:c;var d=(t=s?o:l)*Math.cos(m),g=t*Math.sin(m),v=0===d&&0===g?0:g/Math.sqrt(d*d+g*g),y=0===d&&0===g?0:-d/Math.sqrt(d*d+g*g);d+=+this.p.v[0],g+=+this.p.v[1],this.v.setTripleAt(d,g,d-v*n*i*f,g-y*n*i*f,d+v*n*i*f,g+y*n*i*f,e,!0),s=!s,m+=a*f}},convertPolygonToPath:function(){var e,t=Math.floor(this.pt.v),i=2*Math.PI/t,n=this.or.v,r=this.os.v,a=2*Math.PI*n/(4*t),s=.5*-Math.PI,o=3===this.data.d?-1:1;for(s+=this.r.v,this.v._length=0,e=0;e<t;e+=1){var l=n*Math.cos(s),u=n*Math.sin(s),h=0===l&&0===u?0:u/Math.sqrt(l*l+u*u),p=0===l&&0===u?0:-l/Math.sqrt(l*l+u*u);l+=+this.p.v[0],u+=+this.p.v[1],this.v.setTripleAt(l,u,l-h*a*r*o,u-p*a*r*o,l+h*a*r*o,u+p*a*r*o,e,!0),s+=i*o}this.paths.length=0,this.paths[0]=this.v}},extendPrototype([DynamicPropertyContainer],e),e}(),p=function(){function e(e,t){this.v=shapePool.newElement(),this.v.c=!0,this.localShapeCollection=shapeCollectionPool.newShapeCollection(),this.localShapeCollection.addShape(this.v),this.paths=this.localShapeCollection,this.elem=e,this.comp=e.comp,this.frameId=-1,this.d=t.d,this.initDynamicPropertyContainer(e),this.p=PropertyFactory.getProp(e,t.p,1,0,this),this.s=PropertyFactory.getProp(e,t.s,1,0,this),this.r=PropertyFactory.getProp(e,t.r,0,0,this),this.dynamicProperties.length?this.k=!0:(this.k=!1,this.convertRectToPath())}return e.prototype={convertRectToPath:function(){var e=this.p.v[0],t=this.p.v[1],i=this.s.v[0]/2,n=this.s.v[1]/2,r=bmMin(i,n,this.r.v),a=r*(1-roundCorner);this.v._length=0,2===this.d||1===this.d?(this.v.setTripleAt(e+i,t-n+r,e+i,t-n+r,e+i,t-n+a,0,!0),this.v.setTripleAt(e+i,t+n-r,e+i,t+n-a,e+i,t+n-r,1,!0),0!==r?(this.v.setTripleAt(e+i-r,t+n,e+i-r,t+n,e+i-a,t+n,2,!0),this.v.setTripleAt(e-i+r,t+n,e-i+a,t+n,e-i+r,t+n,3,!0),this.v.setTripleAt(e-i,t+n-r,e-i,t+n-r,e-i,t+n-a,4,!0),this.v.setTripleAt(e-i,t-n+r,e-i,t-n+a,e-i,t-n+r,5,!0),this.v.setTripleAt(e-i+r,t-n,e-i+r,t-n,e-i+a,t-n,6,!0),this.v.setTripleAt(e+i-r,t-n,e+i-a,t-n,e+i-r,t-n,7,!0)):(this.v.setTripleAt(e-i,t+n,e-i+a,t+n,e-i,t+n,2),this.v.setTripleAt(e-i,t-n,e-i,t-n+a,e-i,t-n,3))):(this.v.setTripleAt(e+i,t-n+r,e+i,t-n+a,e+i,t-n+r,0,!0),0!==r?(this.v.setTripleAt(e+i-r,t-n,e+i-r,t-n,e+i-a,t-n,1,!0),this.v.setTripleAt(e-i+r,t-n,e-i+a,t-n,e-i+r,t-n,2,!0),this.v.setTripleAt(e-i,t-n+r,e-i,t-n+r,e-i,t-n+a,3,!0),this.v.setTripleAt(e-i,t+n-r,e-i,t+n-a,e-i,t+n-r,4,!0),this.v.setTripleAt(e-i+r,t+n,e-i+r,t+n,e-i+a,t+n,5,!0),this.v.setTripleAt(e+i-r,t+n,e+i-a,t+n,e+i-r,t+n,6,!0),this.v.setTripleAt(e+i,t+n-r,e+i,t+n-r,e+i,t+n-a,7,!0)):(this.v.setTripleAt(e-i,t-n,e-i+a,t-n,e-i,t-n,1,!0),this.v.setTripleAt(e-i,t+n,e-i,t+n-a,e-i,t+n,2,!0),this.v.setTripleAt(e+i,t+n,e+i-a,t+n,e+i,t+n,3,!0)))},getValue:function(){this.elem.globalData.frameId!==this.frameId&&(this.frameId=this.elem.globalData.frameId,this.iterateDynamicProperties(),this._mdf&&this.convertRectToPath())},reset:o},extendPrototype([DynamicPropertyContainer],e),e}();var c={getShapeProp:function(e,t,i){var n;return 3===i||4===i?n=(3===i?t.pt:t.ks).k.length?new l(e,t,i):new s(e,t,i):5===i?n=new p(e,t):6===i?n=new u(e,t):7===i&&(n=new h(e,t)),n.k&&e.addDynamicProperty(n),n},getConstructorFunction:function(){return s},getKeyframedConstructorFunction:function(){return l}};return c}(),Matrix=function(){var r=Math.cos,a=Math.sin,s=Math.tan,n=Math.round;function e(){return this.props[0]=1,this.props[1]=0,this.props[2]=0,this.props[3]=0,this.props[4]=0,this.props[5]=1,this.props[6]=0,this.props[7]=0,this.props[8]=0,this.props[9]=0,this.props[10]=1,this.props[11]=0,this.props[12]=0,this.props[13]=0,this.props[14]=0,this.props[15]=1,this}function t(e){if(0===e)return this;var t=r(e),i=a(e);return this._t(t,-i,0,0,i,t,0,0,0,0,1,0,0,0,0,1)}function i(e){if(0===e)return this;var t=r(e),i=a(e);return this._t(1,0,0,0,0,t,-i,0,0,i,t,0,0,0,0,1)}function o(e){if(0===e)return this;var t=r(e),i=a(e);return this._t(t,0,i,0,0,1,0,0,-i,0,t,0,0,0,0,1)}function l(e){if(0===e)return this;var t=r(e),i=a(e);return this._t(t,-i,0,0,i,t,0,0,0,0,1,0,0,0,0,1)}function u(e,t){return this._t(1,t,e,1,0,0)}function h(e,t){return this.shear(s(e),s(t))}function p(e,t){var i=r(t),n=a(t);return this._t(i,n,0,0,-n,i,0,0,0,0,1,0,0,0,0,1)._t(1,0,0,0,s(e),1,0,0,0,0,1,0,0,0,0,1)._t(i,-n,0,0,n,i,0,0,0,0,1,0,0,0,0,1)}function c(e,t,i){return i||0===i||(i=1),1===e&&1===t&&1===i?this:this._t(e,0,0,0,0,t,0,0,0,0,i,0,0,0,0,1)}function m(e,t,i,n,r,a,s,o,l,u,h,p,c,m,f,d){return this.props[0]=e,this.props[1]=t,this.props[2]=i,this.props[3]=n,this.props[4]=r,this.props[5]=a,this.props[6]=s,this.props[7]=o,this.props[8]=l,this.props[9]=u,this.props[10]=h,this.props[11]=p,this.props[12]=c,this.props[13]=m,this.props[14]=f,this.props[15]=d,this}function f(e,t,i){return i=i||0,0!==e||0!==t||0!==i?this._t(1,0,0,0,0,1,0,0,0,0,1,0,e,t,i,1):this}function d(e,t,i,n,r,a,s,o,l,u,h,p,c,m,f,d){var g=this.props;if(1===e&&0===t&&0===i&&0===n&&0===r&&1===a&&0===s&&0===o&&0===l&&0===u&&1===h&&0===p)return g[12]=g[12]*e+g[15]*c,g[13]=g[13]*a+g[15]*m,g[14]=g[14]*h+g[15]*f,g[15]*=d,this._identityCalculated=!1,this;var v=g[0],y=g[1],b=g[2],x=g[3],A=g[4],_=g[5],S=g[6],C=g[7],T=g[8],I=g[9],O=g[10],E=g[11],P=g[12],M=g[13],L=g[14],N=g[15];return g[0]=v*e+y*r+b*l+x*c,g[1]=v*t+y*a+b*u+x*m,g[2]=v*i+y*s+b*h+x*f,g[3]=v*n+y*o+b*p+x*d,g[4]=A*e+_*r+S*l+C*c,g[5]=A*t+_*a+S*u+C*m,g[6]=A*i+_*s+S*h+C*f,g[7]=A*n+_*o+S*p+C*d,g[8]=T*e+I*r+O*l+E*c,g[9]=T*t+I*a+O*u+E*m,g[10]=T*i+I*s+O*h+E*f,g[11]=T*n+I*o+O*p+E*d,g[12]=P*e+M*r+L*l+N*c,g[13]=P*t+M*a+L*u+N*m,g[14]=P*i+M*s+L*h+N*f,g[15]=P*n+M*o+L*p+N*d,this._identityCalculated=!1,this}function g(){return this._identityCalculated||(this._identity=!(1!==this.props[0]||0!==this.props[1]||0!==this.props[2]||0!==this.props[3]||0!==this.props[4]||1!==this.props[5]||0!==this.props[6]||0!==this.props[7]||0!==this.props[8]||0!==this.props[9]||1!==this.props[10]||0!==this.props[11]||0!==this.props[12]||0!==this.props[13]||0!==this.props[14]||1!==this.props[15]),this._identityCalculated=!0),this._identity}function v(e){for(var t=0;t<16;){if(e.props[t]!==this.props[t])return!1;t+=1}return!0}function y(e){var t;for(t=0;t<16;t+=1)e.props[t]=this.props[t];return e}function b(e){var t;for(t=0;t<16;t+=1)this.props[t]=e[t]}function x(e,t,i){return{x:e*this.props[0]+t*this.props[4]+i*this.props[8]+this.props[12],y:e*this.props[1]+t*this.props[5]+i*this.props[9]+this.props[13],z:e*this.props[2]+t*this.props[6]+i*this.props[10]+this.props[14]}}function A(e,t,i){return e*this.props[0]+t*this.props[4]+i*this.props[8]+this.props[12]}function _(e,t,i){return e*this.props[1]+t*this.props[5]+i*this.props[9]+this.props[13]}function S(e,t,i){return e*this.props[2]+t*this.props[6]+i*this.props[10]+this.props[14]}function C(){var e=this.props[0]*this.props[5]-this.props[1]*this.props[4],t=this.props[5]/e,i=-this.props[1]/e,n=-this.props[4]/e,r=this.props[0]/e,a=(this.props[4]*this.props[13]-this.props[5]*this.props[12])/e,s=-(this.props[0]*this.props[13]-this.props[1]*this.props[12])/e,o=new Matrix;return o.props[0]=t,o.props[1]=i,o.props[4]=n,o.props[5]=r,o.props[12]=a,o.props[13]=s,o}function T(e){return this.getInverseMatrix().applyToPointArray(e[0],e[1],e[2]||0)}function I(e){var t,i=e.length,n=[];for(t=0;t<i;t+=1)n[t]=T(e[t]);return n}function O(e,t,i){var n=createTypedArray("float32",6);if(this.isIdentity())n[0]=e[0],n[1]=e[1],n[2]=t[0],n[3]=t[1],n[4]=i[0],n[5]=i[1];else{var r=this.props[0],a=this.props[1],s=this.props[4],o=this.props[5],l=this.props[12],u=this.props[13];n[0]=e[0]*r+e[1]*s+l,n[1]=e[0]*a+e[1]*o+u,n[2]=t[0]*r+t[1]*s+l,n[3]=t[0]*a+t[1]*o+u,n[4]=i[0]*r+i[1]*s+l,n[5]=i[0]*a+i[1]*o+u}return n}function E(e,t,i){return this.isIdentity()?[e,t,i]:[e*this.props[0]+t*this.props[4]+i*this.props[8]+this.props[12],e*this.props[1]+t*this.props[5]+i*this.props[9]+this.props[13],e*this.props[2]+t*this.props[6]+i*this.props[10]+this.props[14]]}function P(e,t){if(this.isIdentity())return e+","+t;var i=this.props;return Math.round(100*(e*i[0]+t*i[4]+i[12]))/100+","+Math.round(100*(e*i[1]+t*i[5]+i[13]))/100}function M(){for(var e=0,t=this.props,i="matrix3d(";e<16;)i+=n(1e4*t[e])/1e4,i+=15===e?")":",",e+=1;return i}function L(e){return e<1e-6&&e>0||e>-1e-6&&e<0?n(1e4*e)/1e4:e}function N(){var e=this.props;return"matrix("+L(e[0])+","+L(e[1])+","+L(e[4])+","+L(e[5])+","+L(e[12])+","+L(e[13])+")"}return function(){this.reset=e,this.rotate=t,this.rotateX=i,this.rotateY=o,this.rotateZ=l,this.skew=h,this.skewFromAxis=p,this.shear=u,this.scale=c,this.setTransform=m,this.translate=f,this.transform=d,this.applyToPoint=x,this.applyToX=A,this.applyToY=_,this.applyToZ=S,this.applyToPointArray=E,this.applyToTriplePoints=O,this.applyToPointStringified=P,this.toCSS=M,this.to2dCSS=N,this.clone=y,this.cloneFromProps=b,this.equals=v,this.inversePoints=I,this.inversePoint=T,this.getInverseMatrix=C,this._t=this.transform,this.isIdentity=g,this._identity=!0,this._identityCalculated=!1,this.props=createTypedArray("float32",16),this.reset()}}();function _typeof$3(e){return _typeof$3="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof$3(e)}var lottie={},standalone="__[STANDALONE]__",animationData="__[ANIMATIONDATA]__",renderer="";function setLocation(e){setLocationHref(e)}function searchAnimations(){!0===standalone?animationManager.searchAnimations(animationData,standalone,renderer):animationManager.searchAnimations()}function setSubframeRendering(e){setSubframeEnabled(e)}function setPrefix(e){setIdPrefix(e)}function loadAnimation(e){return!0===standalone&&(e.animationData=JSON.parse(animationData)),animationManager.loadAnimation(e)}function setQuality(e){if("string"==typeof e)switch(e){case"high":setDefaultCurveSegments(200);break;default:case"medium":setDefaultCurveSegments(50);break;case"low":setDefaultCurveSegments(10)}else!isNaN(e)&&e>1&&setDefaultCurveSegments(e);getDefaultCurveSegments()>=50?roundValues(!1):roundValues(!0)}function inBrowser(){return"undefined"!=typeof navigator}function installPlugin(e,t){"expressions"===e&&setExpressionsPlugin(t)}function getFactory(e){switch(e){case"propertyFactory":return PropertyFactory;case"shapePropertyFactory":return ShapePropertyFactory;case"matrix":return Matrix;default:return null}}function checkReady(){"complete"===document.readyState&&(clearInterval(readyStateCheckInterval),searchAnimations())}function getQueryVariable(e){for(var t=queryString.split("&"),i=0;i<t.length;i+=1){var n=t[i].split("=");if(decodeURIComponent(n[0])==e)return decodeURIComponent(n[1])}return null}lottie.play=animationManager.play,lottie.pause=animationManager.pause,lottie.setLocationHref=setLocation,lottie.togglePause=animationManager.togglePause,lottie.setSpeed=animationManager.setSpeed,lottie.setDirection=animationManager.setDirection,lottie.stop=animationManager.stop,lottie.searchAnimations=searchAnimations,lottie.registerAnimation=animationManager.registerAnimation,lottie.loadAnimation=loadAnimation,lottie.setSubframeRendering=setSubframeRendering,lottie.resize=animationManager.resize,lottie.goToAndStop=animationManager.goToAndStop,lottie.destroy=animationManager.destroy,lottie.setQuality=setQuality,lottie.inBrowser=inBrowser,lottie.installPlugin=installPlugin,lottie.freeze=animationManager.freeze,lottie.unfreeze=animationManager.unfreeze,lottie.setVolume=animationManager.setVolume,lottie.mute=animationManager.mute,lottie.unmute=animationManager.unmute,lottie.getRegisteredAnimations=animationManager.getRegisteredAnimations,lottie.useWebWorker=setWebWorker,lottie.setIDPrefix=setPrefix,lottie.__getFactory=getFactory,lottie.version="5.10.2";var queryString="";if(standalone){var scripts=document.getElementsByTagName("script"),index=scripts.length-1,myScript=scripts[index]||{src:""};queryString=myScript.src?myScript.src.replace(/^[^\?]+\??/,""):"",renderer=getQueryVariable("renderer")}var readyStateCheckInterval=setInterval(checkReady,100);try{"object"===("undefined"==typeof exports?"undefined":_typeof$3(exports))&&"undefined"!=typeof module||"function"==typeof define&&define.amd||(window.bodymovin=lottie)}catch(t){}var ShapeModifiers=function(){var e={},n={};return e.registerModifier=function(e,t){n[e]||(n[e]=t)},e.getModifier=function(e,t,i){return new n[e](t,i)},e}();function ShapeModifier(){}function TrimModifier(){}function PuckerAndBloatModifier(){}ShapeModifier.prototype.initModifierProperties=function(){},ShapeModifier.prototype.addShapeToModifier=function(){},ShapeModifier.prototype.addShape=function(e){if(!this.closed){e.sh.container.addDynamicProperty(e.sh);var t={shape:e.sh,data:e,localShapeCollection:shapeCollectionPool.newShapeCollection()};this.shapes.push(t),this.addShapeToModifier(t),this._isAnimated&&e.setAsAnimated()}},ShapeModifier.prototype.init=function(e,t){this.shapes=[],this.elem=e,this.initDynamicPropertyContainer(e),this.initModifierProperties(e,t),this.frameId=initialDefaultFrame,this.closed=!1,this.k=!1,this.dynamicProperties.length?this.k=!0:this.getValue(!0)},ShapeModifier.prototype.processKeys=function(){this.elem.globalData.frameId!==this.frameId&&(this.frameId=this.elem.globalData.frameId,this.iterateDynamicProperties())},extendPrototype([DynamicPropertyContainer],ShapeModifier),extendPrototype([ShapeModifier],TrimModifier),TrimModifier.prototype.initModifierProperties=function(e,t){this.s=PropertyFactory.getProp(e,t.s,0,.01,this),this.e=PropertyFactory.getProp(e,t.e,0,.01,this),this.o=PropertyFactory.getProp(e,t.o,0,0,this),this.sValue=0,this.eValue=0,this.getValue=this.processKeys,this.m=t.m,this._isAnimated=!!this.s.effectsSequence.length||!!this.e.effectsSequence.length||!!this.o.effectsSequence.length},TrimModifier.prototype.addShapeToModifier=function(e){e.pathsData=[]},TrimModifier.prototype.calculateShapeEdges=function(e,t,i,n,r){var a=[];t<=1?a.push({s:e,e:t}):e>=1?a.push({s:e-1,e:t-1}):(a.push({s:e,e:1}),a.push({s:0,e:t-1}));var s,o,l=[],u=a.length;for(s=0;s<u;s+=1){var h,p;if(!((o=a[s]).e*r<n||o.s*r>n+i))h=o.s*r<=n?0:(o.s*r-n)/i,p=o.e*r>=n+i?1:(o.e*r-n)/i,l.push([h,p])}return l.length||l.push([0,0]),l},TrimModifier.prototype.releasePathsData=function(e){var t,i=e.length;for(t=0;t<i;t+=1)segmentsLengthPool.release(e[t]);return e.length=0,e},TrimModifier.prototype.processShapes=function(e){var t,i,n,r;if(this._mdf||e){var a=this.o.v%360/360;if(a<0&&(a+=1),(t=this.s.v>1?1+a:this.s.v<0?0+a:this.s.v+a)>(i=this.e.v>1?1+a:this.e.v<0?0+a:this.e.v+a)){var s=t;t=i,i=s}t=1e-4*Math.round(1e4*t),i=1e-4*Math.round(1e4*i),this.sValue=t,this.eValue=i}else t=this.sValue,i=this.eValue;var o,l,u,h,p,c=this.shapes.length,m=0;if(i===t)for(r=0;r<c;r+=1)this.shapes[r].localShapeCollection.releaseShapes(),this.shapes[r].shape._mdf=!0,this.shapes[r].shape.paths=this.shapes[r].localShapeCollection,this._mdf&&(this.shapes[r].pathsData.length=0);else if(1===i&&0===t||0===i&&1===t){if(this._mdf)for(r=0;r<c;r+=1)this.shapes[r].pathsData.length=0,this.shapes[r].shape._mdf=!0}else{var f,d,g=[];for(r=0;r<c;r+=1)if((f=this.shapes[r]).shape._mdf||this._mdf||e||2===this.m){if(l=(n=f.shape.paths)._length,p=0,!f.shape._mdf&&f.pathsData.length)p=f.totalShapeLength;else{for(u=this.releasePathsData(f.pathsData),o=0;o<l;o+=1)h=bez.getSegmentsLength(n.shapes[o]),u.push(h),p+=h.totalLength;f.totalShapeLength=p,f.pathsData=u}m+=p,f.shape._mdf=!0}else f.shape.paths=f.localShapeCollection;var v,y=t,b=i,x=0;for(r=c-1;r>=0;r-=1)if((f=this.shapes[r]).shape._mdf){for((d=f.localShapeCollection).releaseShapes(),2===this.m&&c>1?(v=this.calculateShapeEdges(t,i,f.totalShapeLength,x,m),x+=f.totalShapeLength):v=[[y,b]],l=v.length,o=0;o<l;o+=1){y=v[o][0],b=v[o][1],g.length=0,b<=1?g.push({s:f.totalShapeLength*y,e:f.totalShapeLength*b}):y>=1?g.push({s:f.totalShapeLength*(y-1),e:f.totalShapeLength*(b-1)}):(g.push({s:f.totalShapeLength*y,e:f.totalShapeLength}),g.push({s:0,e:f.totalShapeLength*(b-1)}));var A=this.addShapes(f,g[0]);if(g[0].s!==g[0].e){if(g.length>1)if(f.shape.paths.shapes[f.shape.paths._length-1].c){var _=A.pop();this.addPaths(A,d),A=this.addShapes(f,g[1],_)}else this.addPaths(A,d),A=this.addShapes(f,g[1]);this.addPaths(A,d)}}f.shape.paths=d}}},TrimModifier.prototype.addPaths=function(e,t){var i,n=e.length;for(i=0;i<n;i+=1)t.addShape(e[i])},TrimModifier.prototype.addSegment=function(e,t,i,n,r,a,s){r.setXYAt(t[0],t[1],"o",a),r.setXYAt(i[0],i[1],"i",a+1),s&&r.setXYAt(e[0],e[1],"v",a),r.setXYAt(n[0],n[1],"v",a+1)},TrimModifier.prototype.addSegmentFromArray=function(e,t,i,n){t.setXYAt(e[1],e[5],"o",i),t.setXYAt(e[2],e[6],"i",i+1),n&&t.setXYAt(e[0],e[4],"v",i),t.setXYAt(e[3],e[7],"v",i+1)},TrimModifier.prototype.addShapes=function(e,t,i){var n,r,a,s,o,l,u,h,p=e.pathsData,c=e.shape.paths.shapes,m=e.shape.paths._length,f=0,d=[],g=!0;for(i?(o=i._length,h=i._length):(i=shapePool.newElement(),o=0,h=0),d.push(i),n=0;n<m;n+=1){for(l=p[n].lengths,i.c=c[n].c,a=c[n].c?l.length:l.length+1,r=1;r<a;r+=1)if(f+(s=l[r-1]).addedLength<t.s)f+=s.addedLength,i.c=!1;else{if(f>t.e){i.c=!1;break}t.s<=f&&t.e>=f+s.addedLength?(this.addSegment(c[n].v[r-1],c[n].o[r-1],c[n].i[r],c[n].v[r],i,o,g),g=!1):(u=bez.getNewSegment(c[n].v[r-1],c[n].v[r],c[n].o[r-1],c[n].i[r],(t.s-f)/s.addedLength,(t.e-f)/s.addedLength,l[r-1]),this.addSegmentFromArray(u,i,o,g),g=!1,i.c=!1),f+=s.addedLength,o+=1}if(c[n].c&&l.length){if(s=l[r-1],f<=t.e){var v=l[r-1].addedLength;t.s<=f&&t.e>=f+v?(this.addSegment(c[n].v[r-1],c[n].o[r-1],c[n].i[0],c[n].v[0],i,o,g),g=!1):(u=bez.getNewSegment(c[n].v[r-1],c[n].v[0],c[n].o[r-1],c[n].i[0],(t.s-f)/v,(t.e-f)/v,l[r-1]),this.addSegmentFromArray(u,i,o,g),g=!1,i.c=!1)}else i.c=!1;f+=s.addedLength,o+=1}if(i._length&&(i.setXYAt(i.v[h][0],i.v[h][1],"i",h),i.setXYAt(i.v[i._length-1][0],i.v[i._length-1][1],"o",i._length-1)),f>t.e)break;n<m-1&&(i=shapePool.newElement(),g=!0,d.push(i),o=0)}return d},extendPrototype([ShapeModifier],PuckerAndBloatModifier),PuckerAndBloatModifier.prototype.initModifierProperties=function(e,t){this.getValue=this.processKeys,this.amount=PropertyFactory.getProp(e,t.a,0,null,this),this._isAnimated=!!this.amount.effectsSequence.length},PuckerAndBloatModifier.prototype.processPath=function(e,t){var i=t/100,n=[0,0],r=e._length,a=0;for(a=0;a<r;a+=1)n[0]+=e.v[a][0],n[1]+=e.v[a][1];n[0]/=r,n[1]/=r;var s,o,l,u,h,p,c=shapePool.newElement();for(c.c=e.c,a=0;a<r;a+=1)s=e.v[a][0]+(n[0]-e.v[a][0])*i,o=e.v[a][1]+(n[1]-e.v[a][1])*i,l=e.o[a][0]+(n[0]-e.o[a][0])*-i,u=e.o[a][1]+(n[1]-e.o[a][1])*-i,h=e.i[a][0]+(n[0]-e.i[a][0])*-i,p=e.i[a][1]+(n[1]-e.i[a][1])*-i,c.setTripleAt(s,o,l,u,h,p,a);return c},PuckerAndBloatModifier.prototype.processShapes=function(e){var t,i,n,r,a,s,o=this.shapes.length,l=this.amount.v;if(0!==l)for(i=0;i<o;i+=1){if(s=(a=this.shapes[i]).localShapeCollection,a.shape._mdf||this._mdf||e)for(s.releaseShapes(),a.shape._mdf=!0,t=a.shape.paths.shapes,r=a.shape.paths._length,n=0;n<r;n+=1)s.addShape(this.processPath(t[n],l));a.shape.paths=a.localShapeCollection}this.dynamicProperties.length||(this._mdf=!1)};var TransformPropertyFactory=function(){var s=[0,0];function n(e,t,i){if(this.elem=e,this.frameId=-1,this.propType="transform",this.data=t,this.v=new Matrix,this.pre=new Matrix,this.appliedTransformations=0,this.initDynamicPropertyContainer(i||e),t.p&&t.p.s?(this.px=PropertyFactory.getProp(e,t.p.x,0,0,this),this.py=PropertyFactory.getProp(e,t.p.y,0,0,this),t.p.z&&(this.pz=PropertyFactory.getProp(e,t.p.z,0,0,this))):this.p=PropertyFactory.getProp(e,t.p||{k:[0,0,0]},1,0,this),t.rx){if(this.rx=PropertyFactory.getProp(e,t.rx,0,degToRads,this),this.ry=PropertyFactory.getProp(e,t.ry,0,degToRads,this),this.rz=PropertyFactory.getProp(e,t.rz,0,degToRads,this),t.or.k[0].ti){var n,r=t.or.k.length;for(n=0;n<r;n+=1)t.or.k[n].to=null,t.or.k[n].ti=null}this.or=PropertyFactory.getProp(e,t.or,1,degToRads,this),this.or.sh=!0}else this.r=PropertyFactory.getProp(e,t.r||{k:0},0,degToRads,this);t.sk&&(this.sk=PropertyFactory.getProp(e,t.sk,0,degToRads,this),this.sa=PropertyFactory.getProp(e,t.sa,0,degToRads,this)),this.a=PropertyFactory.getProp(e,t.a||{k:[0,0,0]},1,0,this),this.s=PropertyFactory.getProp(e,t.s||{k:[100,100,100]},1,.01,this),t.o?this.o=PropertyFactory.getProp(e,t.o,0,.01,e):this.o={_mdf:!1,v:1},this._isDirty=!0,this.dynamicProperties.length||this.getValue(!0)}return n.prototype={applyToMatrix:function(e){var t=this._mdf;this.iterateDynamicProperties(),this._mdf=this._mdf||t,this.a&&e.translate(-this.a.v[0],-this.a.v[1],this.a.v[2]),this.s&&e.scale(this.s.v[0],this.s.v[1],this.s.v[2]),this.sk&&e.skewFromAxis(-this.sk.v,this.sa.v),this.r?e.rotate(-this.r.v):e.rotateZ(-this.rz.v).rotateY(this.ry.v).rotateX(this.rx.v).rotateZ(-this.or.v[2]).rotateY(this.or.v[1]).rotateX(this.or.v[0]),this.data.p.s?this.data.p.z?e.translate(this.px.v,this.py.v,-this.pz.v):e.translate(this.px.v,this.py.v,0):e.translate(this.p.v[0],this.p.v[1],-this.p.v[2])},getValue:function(e){if(this.elem.globalData.frameId!==this.frameId){if(this._isDirty&&(this.precalculateMatrix(),this._isDirty=!1),this.iterateDynamicProperties(),this._mdf||e){var t;if(this.v.cloneFromProps(this.pre.props),this.appliedTransformations<1&&this.v.translate(-this.a.v[0],-this.a.v[1],this.a.v[2]),this.appliedTransformations<2&&this.v.scale(this.s.v[0],this.s.v[1],this.s.v[2]),this.sk&&this.appliedTransformations<3&&this.v.skewFromAxis(-this.sk.v,this.sa.v),this.r&&this.appliedTransformations<4?this.v.rotate(-this.r.v):!this.r&&this.appliedTransformations<4&&this.v.rotateZ(-this.rz.v).rotateY(this.ry.v).rotateX(this.rx.v).rotateZ(-this.or.v[2]).rotateY(this.or.v[1]).rotateX(this.or.v[0]),this.autoOriented){var i,n;if(t=this.elem.globalData.frameRate,this.p&&this.p.keyframes&&this.p.getValueAtTime)this.p._caching.lastFrame+this.p.offsetTime<=this.p.keyframes[0].t?(i=this.p.getValueAtTime((this.p.keyframes[0].t+.01)/t,0),n=this.p.getValueAtTime(this.p.keyframes[0].t/t,0)):this.p._caching.lastFrame+this.p.offsetTime>=this.p.keyframes[this.p.keyframes.length-1].t?(i=this.p.getValueAtTime(this.p.keyframes[this.p.keyframes.length-1].t/t,0),n=this.p.getValueAtTime((this.p.keyframes[this.p.keyframes.length-1].t-.05)/t,0)):(i=this.p.pv,n=this.p.getValueAtTime((this.p._caching.lastFrame+this.p.offsetTime-.01)/t,this.p.offsetTime));else if(this.px&&this.px.keyframes&&this.py.keyframes&&this.px.getValueAtTime&&this.py.getValueAtTime){i=[],n=[];var r=this.px,a=this.py;r._caching.lastFrame+r.offsetTime<=r.keyframes[0].t?(i[0]=r.getValueAtTime((r.keyframes[0].t+.01)/t,0),i[1]=a.getValueAtTime((a.keyframes[0].t+.01)/t,0),n[0]=r.getValueAtTime(r.keyframes[0].t/t,0),n[1]=a.getValueAtTime(a.keyframes[0].t/t,0)):r._caching.lastFrame+r.offsetTime>=r.keyframes[r.keyframes.length-1].t?(i[0]=r.getValueAtTime(r.keyframes[r.keyframes.length-1].t/t,0),i[1]=a.getValueAtTime(a.keyframes[a.keyframes.length-1].t/t,0),n[0]=r.getValueAtTime((r.keyframes[r.keyframes.length-1].t-.01)/t,0),n[1]=a.getValueAtTime((a.keyframes[a.keyframes.length-1].t-.01)/t,0)):(i=[r.pv,a.pv],n[0]=r.getValueAtTime((r._caching.lastFrame+r.offsetTime-.01)/t,r.offsetTime),n[1]=a.getValueAtTime((a._caching.lastFrame+a.offsetTime-.01)/t,a.offsetTime))}else i=n=s;this.v.rotate(-Math.atan2(i[1]-n[1],i[0]-n[0]))}this.data.p&&this.data.p.s?this.data.p.z?this.v.translate(this.px.v,this.py.v,-this.pz.v):this.v.translate(this.px.v,this.py.v,0):this.v.translate(this.p.v[0],this.p.v[1],-this.p.v[2])}this.frameId=this.elem.globalData.frameId}},precalculateMatrix:function(){if(!this.a.k&&(this.pre.translate(-this.a.v[0],-this.a.v[1],this.a.v[2]),this.appliedTransformations=1,!this.s.effectsSequence.length)){if(this.pre.scale(this.s.v[0],this.s.v[1],this.s.v[2]),this.appliedTransformations=2,this.sk){if(this.sk.effectsSequence.length||this.sa.effectsSequence.length)return;this.pre.skewFromAxis(-this.sk.v,this.sa.v),this.appliedTransformations=3}this.r?this.r.effectsSequence.length||(this.pre.rotate(-this.r.v),this.appliedTransformations=4):this.rz.effectsSequence.length||this.ry.effectsSequence.length||this.rx.effectsSequence.length||this.or.effectsSequence.length||(this.pre.rotateZ(-this.rz.v).rotateY(this.ry.v).rotateX(this.rx.v).rotateZ(-this.or.v[2]).rotateY(this.or.v[1]).rotateX(this.or.v[0]),this.appliedTransformations=4)}},autoOrient:function(){}},extendPrototype([DynamicPropertyContainer],n),n.prototype.addDynamicProperty=function(e){this._addDynamicProperty(e),this.elem.addDynamicProperty(e),this._isDirty=!0},n.prototype._addDynamicProperty=DynamicPropertyContainer.prototype.addDynamicProperty,{getTransformProperty:function(e,t,i){return new n(e,t,i)}}}();function RepeaterModifier(){}function RoundCornersModifier(){}function floatEqual(e,t){return 1e5*Math.abs(e-t)<=Math.min(Math.abs(e),Math.abs(t))}function floatZero(e){return Math.abs(e)<=1e-5}function lerp(e,t,i){return e*(1-i)+t*i}function lerpPoint(e,t,i){return[lerp(e[0],t[0],i),lerp(e[1],t[1],i)]}function quadRoots(e,t,i){if(0===e)return[];var n=t*t-4*e*i;if(n<0)return[];var r=-t/(2*e);if(0===n)return[r];var a=Math.sqrt(n)/(2*e);return[r-a,r+a]}function polynomialCoefficients(e,t,i,n){return[3*t-e-3*i+n,3*e-6*t+3*i,-3*e+3*t,e]}function singlePoint(e){return new PolynomialBezier(e,e,e,e,!1)}function PolynomialBezier(e,t,i,n,r){r&&pointEqual(e,t)&&(t=lerpPoint(e,n,1/3)),r&&pointEqual(i,n)&&(i=lerpPoint(e,n,2/3));var a=polynomialCoefficients(e[0],t[0],i[0],n[0]),s=polynomialCoefficients(e[1],t[1],i[1],n[1]);this.a=[a[0],s[0]],this.b=[a[1],s[1]],this.c=[a[2],s[2]],this.d=[a[3],s[3]],this.points=[e,t,i,n]}function extrema(e,t){var i=e.points[0][t],n=e.points[e.points.length-1][t];if(i>n){var r=n;n=i,i=r}for(var a=quadRoots(3*e.a[t],2*e.b[t],e.c[t]),s=0;s<a.length;s+=1)if(a[s]>0&&a[s]<1){var o=e.point(a[s])[t];o<i?i=o:o>n&&(n=o)}return{min:i,max:n}}function intersectData(e,t,i){var n=e.boundingBox();return{cx:n.cx,cy:n.cy,width:n.width,height:n.height,bez:e,t:(t+i)/2,t1:t,t2:i}}function splitData(e){var t=e.bez.split(.5);return[intersectData(t[0],e.t1,e.t),intersectData(t[1],e.t,e.t2)]}function boxIntersect(e,t){return 2*Math.abs(e.cx-t.cx)<e.width+t.width&&2*Math.abs(e.cy-t.cy)<e.height+t.height}function intersectsImpl(e,t,i,n,r,a){if(boxIntersect(e,t))if(i>=a||e.width<=n&&e.height<=n&&t.width<=n&&t.height<=n)r.push([e.t,t.t]);else{var s=splitData(e),o=splitData(t);intersectsImpl(s[0],o[0],i+1,n,r,a),intersectsImpl(s[0],o[1],i+1,n,r,a),intersectsImpl(s[1],o[0],i+1,n,r,a),intersectsImpl(s[1],o[1],i+1,n,r,a)}}function crossProduct(e,t){return[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]]}function lineIntersection(e,t,i,n){var r=[e[0],e[1],1],a=[t[0],t[1],1],s=[i[0],i[1],1],o=[n[0],n[1],1],l=crossProduct(crossProduct(r,a),crossProduct(s,o));return floatZero(l[2])?null:[l[0]/l[2],l[1]/l[2]]}function polarOffset(e,t,i){return[e[0]+Math.cos(t)*i,e[1]-Math.sin(t)*i]}function pointDistance(e,t){return Math.hypot(e[0]-t[0],e[1]-t[1])}function pointEqual(e,t){return floatEqual(e[0],t[0])&&floatEqual(e[1],t[1])}function ZigZagModifier(){}function setPoint(e,t,i,n,r,a,s){var o=i-Math.PI/2,l=i+Math.PI/2,u=t[0]+Math.cos(i)*n*r,h=t[1]-Math.sin(i)*n*r;e.setTripleAt(u,h,u+Math.cos(o)*a,h-Math.sin(o)*a,u+Math.cos(l)*s,h-Math.sin(l)*s,e.length())}function getPerpendicularVector(e,t){var i=[t[0]-e[0],t[1]-e[1]],n=.5*-Math.PI;return[Math.cos(n)*i[0]-Math.sin(n)*i[1],Math.sin(n)*i[0]+Math.cos(n)*i[1]]}function getProjectingAngle(e,t){var i=0===t?e.length()-1:t-1,n=(t+1)%e.length(),r=getPerpendicularVector(e.v[i],e.v[n]);return Math.atan2(0,1)-Math.atan2(r[1],r[0])}function zigZagCorner(e,t,i,n,r,a,s){var o=getProjectingAngle(t,i),l=t.v[i%t._length],u=t.v[0===i?t._length-1:i-1],h=t.v[(i+1)%t._length],p=2===a?Math.sqrt(Math.pow(l[0]-u[0],2)+Math.pow(l[1]-u[1],2)):0,c=2===a?Math.sqrt(Math.pow(l[0]-h[0],2)+Math.pow(l[1]-h[1],2)):0;setPoint(e,t.v[i%t._length],o,s,n,c/(2*(r+1)),p/(2*(r+1)),a)}function zigZagSegment(e,t,i,n,r,a){for(var s=0;s<n;s+=1){var o=(s+1)/(n+1),l=2===r?Math.sqrt(Math.pow(t.points[3][0]-t.points[0][0],2)+Math.pow(t.points[3][1]-t.points[0][1],2)):0,u=t.normalAngle(o);setPoint(e,t.point(o),u,a,i,l/(2*(n+1)),l/(2*(n+1)),r),a=-a}return a}function linearOffset(e,t,i){var n=Math.atan2(t[0]-e[0],t[1]-e[1]);return[polarOffset(e,n,i),polarOffset(t,n,i)]}function offsetSegment(e,t){var i,n,r,a,s,o,l;i=(l=linearOffset(e.points[0],e.points[1],t))[0],n=l[1],r=(l=linearOffset(e.points[1],e.points[2],t))[0],a=l[1],s=(l=linearOffset(e.points[2],e.points[3],t))[0],o=l[1];var u=lineIntersection(i,n,r,a);null===u&&(u=n);var h=lineIntersection(s,o,r,a);return null===h&&(h=s),new PolynomialBezier(i,u,h,o)}function joinLines(e,t,i,n,r){var a=t.points[3],s=i.points[0];if(3===n)return a;if(pointEqual(a,s))return a;if(2===n){var o=-t.tangentAngle(1),l=-i.tangentAngle(0)+Math.PI,u=lineIntersection(a,polarOffset(a,o+Math.PI/2,100),s,polarOffset(s,o+Math.PI/2,100)),h=u?pointDistance(u,a):pointDistance(a,s)/2,p=polarOffset(a,o,2*h*roundCorner);return e.setXYAt(p[0],p[1],"o",e.length()-1),p=polarOffset(s,l,2*h*roundCorner),e.setTripleAt(s[0],s[1],s[0],s[1],p[0],p[1],e.length()),s}var c=lineIntersection(pointEqual(a,t.points[2])?t.points[0]:t.points[2],a,s,pointEqual(s,i.points[1])?i.points[3]:i.points[1]);return c&&pointDistance(c,a)<r?(e.setTripleAt(c[0],c[1],c[0],c[1],c[0],c[1],e.length()),c):a}function getIntersection(e,t){var i=e.intersections(t);return i.length&&floatEqual(i[0][0],1)&&i.shift(),i.length?i[0]:null}function pruneSegmentIntersection(e,t){var i=e.slice(),n=t.slice(),r=getIntersection(e[e.length-1],t[0]);return r&&(i[e.length-1]=e[e.length-1].split(r[0])[0],n[0]=t[0].split(r[1])[1]),e.length>1&&t.length>1&&(r=getIntersection(e[0],t[t.length-1]))?[[e[0].split(r[0])[0]],[t[t.length-1].split(r[1])[1]]]:[i,n]}function pruneIntersections(e){for(var t,i=1;i<e.length;i+=1)t=pruneSegmentIntersection(e[i-1],e[i]),e[i-1]=t[0],e[i]=t[1];return e.length>1&&(t=pruneSegmentIntersection(e[e.length-1],e[0]),e[e.length-1]=t[0],e[0]=t[1]),e}function offsetSegmentSplit(e,t){var i,n,r,a,s=e.inflectionPoints();if(0===s.length)return[offsetSegment(e,t)];if(1===s.length||floatEqual(s[1],1))return i=(r=e.split(s[0]))[0],n=r[1],[offsetSegment(i,t),offsetSegment(n,t)];i=(r=e.split(s[0]))[0];var o=(s[1]-s[0])/(1-s[0]);return a=(r=r[1].split(o))[0],n=r[1],[offsetSegment(i,t),offsetSegment(a,t),offsetSegment(n,t)]}function OffsetPathModifier(){}function getFontProperties(e){for(var t=e.fStyle?e.fStyle.split(" "):[],i="normal",n="normal",r=t.length,a=0;a<r;a+=1)switch(t[a].toLowerCase()){case"italic":n="italic";break;case"bold":i="700";break;case"black":i="900";break;case"medium":i="500";break;case"regular":case"normal":i="400";break;case"light":case"thin":i="200"}return{style:n,weight:e.fWeight||i}}extendPrototype([ShapeModifier],RepeaterModifier),RepeaterModifier.prototype.initModifierProperties=function(e,t){this.getValue=this.processKeys,this.c=PropertyFactory.getProp(e,t.c,0,null,this),this.o=PropertyFactory.getProp(e,t.o,0,null,this),this.tr=TransformPropertyFactory.getTransformProperty(e,t.tr,this),this.so=PropertyFactory.getProp(e,t.tr.so,0,.01,this),this.eo=PropertyFactory.getProp(e,t.tr.eo,0,.01,this),this.data=t,this.dynamicProperties.length||this.getValue(!0),this._isAnimated=!!this.dynamicProperties.length,this.pMatrix=new Matrix,this.rMatrix=new Matrix,this.sMatrix=new Matrix,this.tMatrix=new Matrix,this.matrix=new Matrix},RepeaterModifier.prototype.applyTransforms=function(e,t,i,n,r,a){var s=a?-1:1,o=n.s.v[0]+(1-n.s.v[0])*(1-r),l=n.s.v[1]+(1-n.s.v[1])*(1-r);e.translate(n.p.v[0]*s*r,n.p.v[1]*s*r,n.p.v[2]),t.translate(-n.a.v[0],-n.a.v[1],n.a.v[2]),t.rotate(-n.r.v*s*r),t.translate(n.a.v[0],n.a.v[1],n.a.v[2]),i.translate(-n.a.v[0],-n.a.v[1],n.a.v[2]),i.scale(a?1/o:o,a?1/l:l),i.translate(n.a.v[0],n.a.v[1],n.a.v[2])},RepeaterModifier.prototype.init=function(e,t,i,n){for(this.elem=e,this.arr=t,this.pos=i,this.elemsData=n,this._currentCopies=0,this._elements=[],this._groups=[],this.frameId=-1,this.initDynamicPropertyContainer(e),this.initModifierProperties(e,t[i]);i>0;)i-=1,this._elements.unshift(t[i]);this.dynamicProperties.length?this.k=!0:this.getValue(!0)},RepeaterModifier.prototype.resetElements=function(e){var t,i=e.length;for(t=0;t<i;t+=1)e[t]._processed=!1,"gr"===e[t].ty&&this.resetElements(e[t].it)},RepeaterModifier.prototype.cloneElements=function(e){var t=JSON.parse(JSON.stringify(e));return this.resetElements(t),t},RepeaterModifier.prototype.changeGroupRender=function(e,t){var i,n=e.length;for(i=0;i<n;i+=1)e[i]._render=t,"gr"===e[i].ty&&this.changeGroupRender(e[i].it,t)},RepeaterModifier.prototype.processShapes=function(e){var t,i,n,r,a,s=!1;if(this._mdf||e){var o,l=Math.ceil(this.c.v);if(this._groups.length<l){for(;this._groups.length<l;){var u={it:this.cloneElements(this._elements),ty:"gr"};u.it.push({a:{a:0,ix:1,k:[0,0]},nm:"Transform",o:{a:0,ix:7,k:100},p:{a:0,ix:2,k:[0,0]},r:{a:1,ix:6,k:[{s:0,e:0,t:0},{s:0,e:0,t:1}]},s:{a:0,ix:3,k:[100,100]},sa:{a:0,ix:5,k:0},sk:{a:0,ix:4,k:0},ty:"tr"}),this.arr.splice(0,0,u),this._groups.splice(0,0,u),this._currentCopies+=1}this.elem.reloadShapes(),s=!0}for(a=0,n=0;n<=this._groups.length-1;n+=1){if(o=a<l,this._groups[n]._render=o,this.changeGroupRender(this._groups[n].it,o),!o){var h=this.elemsData[n].it,p=h[h.length-1];0!==p.transform.op.v?(p.transform.op._mdf=!0,p.transform.op.v=0):p.transform.op._mdf=!1}a+=1}this._currentCopies=l;var c=this.o.v,m=c%1,f=c>0?Math.floor(c):Math.ceil(c),d=this.pMatrix.props,g=this.rMatrix.props,v=this.sMatrix.props;this.pMatrix.reset(),this.rMatrix.reset(),this.sMatrix.reset(),this.tMatrix.reset(),this.matrix.reset();var y,b,x=0;if(c>0){for(;x<f;)this.applyTransforms(this.pMatrix,this.rMatrix,this.sMatrix,this.tr,1,!1),x+=1;m&&(this.applyTransforms(this.pMatrix,this.rMatrix,this.sMatrix,this.tr,m,!1),x+=m)}else if(c<0){for(;x>f;)this.applyTransforms(this.pMatrix,this.rMatrix,this.sMatrix,this.tr,1,!0),x-=1;m&&(this.applyTransforms(this.pMatrix,this.rMatrix,this.sMatrix,this.tr,-m,!0),x-=m)}for(n=1===this.data.m?0:this._currentCopies-1,r=1===this.data.m?1:-1,a=this._currentCopies;a;){if(b=(i=(t=this.elemsData[n].it)[t.length-1].transform.mProps.v.props).length,t[t.length-1].transform.mProps._mdf=!0,t[t.length-1].transform.op._mdf=!0,t[t.length-1].transform.op.v=1===this._currentCopies?this.so.v:this.so.v+(this.eo.v-this.so.v)*(n/(this._currentCopies-1)),0!==x){for((0!==n&&1===r||n!==this._currentCopies-1&&-1===r)&&this.applyTransforms(this.pMatrix,this.rMatrix,this.sMatrix,this.tr,1,!1),this.matrix.transform(g[0],g[1],g[2],g[3],g[4],g[5],g[6],g[7],g[8],g[9],g[10],g[11],g[12],g[13],g[14],g[15]),this.matrix.transform(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]),this.matrix.transform(d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7],d[8],d[9],d[10],d[11],d[12],d[13],d[14],d[15]),y=0;y<b;y+=1)i[y]=this.matrix.props[y];this.matrix.reset()}else for(this.matrix.reset(),y=0;y<b;y+=1)i[y]=this.matrix.props[y];x+=1,a-=1,n+=r}}else for(a=this._currentCopies,n=0,r=1;a;)i=(t=this.elemsData[n].it)[t.length-1].transform.mProps.v.props,t[t.length-1].transform.mProps._mdf=!1,t[t.length-1].transform.op._mdf=!1,a-=1,n+=r;return s},RepeaterModifier.prototype.addShape=function(){},extendPrototype([ShapeModifier],RoundCornersModifier),RoundCornersModifier.prototype.initModifierProperties=function(e,t){this.getValue=this.processKeys,this.rd=PropertyFactory.getProp(e,t.r,0,null,this),this._isAnimated=!!this.rd.effectsSequence.length},RoundCornersModifier.prototype.processPath=function(e,t){var i,n=shapePool.newElement();n.c=e.c;var r,a,s,o,l,u,h,p,c,m,f,d,g=e._length,v=0;for(i=0;i<g;i+=1)r=e.v[i],s=e.o[i],a=e.i[i],r[0]===s[0]&&r[1]===s[1]&&r[0]===a[0]&&r[1]===a[1]?0!==i&&i!==g-1||e.c?(o=0===i?e.v[g-1]:e.v[i-1],u=(l=Math.sqrt(Math.pow(r[0]-o[0],2)+Math.pow(r[1]-o[1],2)))?Math.min(l/2,t)/l:0,h=f=r[0]+(o[0]-r[0])*u,p=d=r[1]-(r[1]-o[1])*u,c=h-(h-r[0])*roundCorner,m=p-(p-r[1])*roundCorner,n.setTripleAt(h,p,c,m,f,d,v),v+=1,o=i===g-1?e.v[0]:e.v[i+1],u=(l=Math.sqrt(Math.pow(r[0]-o[0],2)+Math.pow(r[1]-o[1],2)))?Math.min(l/2,t)/l:0,h=c=r[0]+(o[0]-r[0])*u,p=m=r[1]+(o[1]-r[1])*u,f=h-(h-r[0])*roundCorner,d=p-(p-r[1])*roundCorner,n.setTripleAt(h,p,c,m,f,d,v),v+=1):(n.setTripleAt(r[0],r[1],s[0],s[1],a[0],a[1],v),v+=1):(n.setTripleAt(e.v[i][0],e.v[i][1],e.o[i][0],e.o[i][1],e.i[i][0],e.i[i][1],v),v+=1);return n},RoundCornersModifier.prototype.processShapes=function(e){var t,i,n,r,a,s,o=this.shapes.length,l=this.rd.v;if(0!==l)for(i=0;i<o;i+=1){if(s=(a=this.shapes[i]).localShapeCollection,a.shape._mdf||this._mdf||e)for(s.releaseShapes(),a.shape._mdf=!0,t=a.shape.paths.shapes,r=a.shape.paths._length,n=0;n<r;n+=1)s.addShape(this.processPath(t[n],l));a.shape.paths=a.localShapeCollection}this.dynamicProperties.length||(this._mdf=!1)},PolynomialBezier.prototype.point=function(e){return[((this.a[0]*e+this.b[0])*e+this.c[0])*e+this.d[0],((this.a[1]*e+this.b[1])*e+this.c[1])*e+this.d[1]]},PolynomialBezier.prototype.derivative=function(e){return[(3*e*this.a[0]+2*this.b[0])*e+this.c[0],(3*e*this.a[1]+2*this.b[1])*e+this.c[1]]},PolynomialBezier.prototype.tangentAngle=function(e){var t=this.derivative(e);return Math.atan2(t[1],t[0])},PolynomialBezier.prototype.normalAngle=function(e){var t=this.derivative(e);return Math.atan2(t[0],t[1])},PolynomialBezier.prototype.inflectionPoints=function(){var e=this.a[1]*this.b[0]-this.a[0]*this.b[1];if(floatZero(e))return[];var t=-.5*(this.a[1]*this.c[0]-this.a[0]*this.c[1])/e,i=t*t-1/3*(this.b[1]*this.c[0]-this.b[0]*this.c[1])/e;if(i<0)return[];var n=Math.sqrt(i);return floatZero(n)?n>0&&n<1?[t]:[]:[t-n,t+n].filter(function(e){return e>0&&e<1})},PolynomialBezier.prototype.split=function(e){if(e<=0)return[singlePoint(this.points[0]),this];if(e>=1)return[this,singlePoint(this.points[this.points.length-1])];var t=lerpPoint(this.points[0],this.points[1],e),i=lerpPoint(this.points[1],this.points[2],e),n=lerpPoint(this.points[2],this.points[3],e),r=lerpPoint(t,i,e),a=lerpPoint(i,n,e),s=lerpPoint(r,a,e);return[new PolynomialBezier(this.points[0],t,r,s,!0),new PolynomialBezier(s,a,n,this.points[3],!0)]},PolynomialBezier.prototype.bounds=function(){return{x:extrema(this,0),y:extrema(this,1)}},PolynomialBezier.prototype.boundingBox=function(){var e=this.bounds();return{left:e.x.min,right:e.x.max,top:e.y.min,bottom:e.y.max,width:e.x.max-e.x.min,height:e.y.max-e.y.min,cx:(e.x.max+e.x.min)/2,cy:(e.y.max+e.y.min)/2}},PolynomialBezier.prototype.intersections=function(e,t,i){void 0===t&&(t=2),void 0===i&&(i=7);var n=[];return intersectsImpl(intersectData(this,0,1),intersectData(e,0,1),0,t,n,i),n},PolynomialBezier.shapeSegment=function(e,t){var i=(t+1)%e.length();return new PolynomialBezier(e.v[t],e.o[t],e.i[i],e.v[i],!0)},PolynomialBezier.shapeSegmentInverted=function(e,t){var i=(t+1)%e.length();return new PolynomialBezier(e.v[i],e.i[i],e.o[t],e.v[t],!0)},extendPrototype([ShapeModifier],ZigZagModifier),ZigZagModifier.prototype.initModifierProperties=function(e,t){this.getValue=this.processKeys,this.amplitude=PropertyFactory.getProp(e,t.s,0,null,this),this.frequency=PropertyFactory.getProp(e,t.r,0,null,this),this.pointsType=PropertyFactory.getProp(e,t.pt,0,null,this),this._isAnimated=0!==this.amplitude.effectsSequence.length||0!==this.frequency.effectsSequence.length||0!==this.pointsType.effectsSequence.length},ZigZagModifier.prototype.processPath=function(e,t,i,n){var r=e._length,a=shapePool.newElement();if(a.c=e.c,e.c||(r-=1),0===r)return a;var s=-1,o=PolynomialBezier.shapeSegment(e,0);zigZagCorner(a,e,0,t,i,n,s);for(var l=0;l<r;l+=1)s=zigZagSegment(a,o,t,i,n,-s),o=l!==r-1||e.c?PolynomialBezier.shapeSegment(e,(l+1)%r):null,zigZagCorner(a,e,l+1,t,i,n,s);return a},ZigZagModifier.prototype.processShapes=function(e){var t,i,n,r,a,s,o=this.shapes.length,l=this.amplitude.v,u=Math.max(0,Math.round(this.frequency.v)),h=this.pointsType.v;if(0!==l)for(i=0;i<o;i+=1){if(s=(a=this.shapes[i]).localShapeCollection,a.shape._mdf||this._mdf||e)for(s.releaseShapes(),a.shape._mdf=!0,t=a.shape.paths.shapes,r=a.shape.paths._length,n=0;n<r;n+=1)s.addShape(this.processPath(t[n],l,u,h));a.shape.paths=a.localShapeCollection}this.dynamicProperties.length||(this._mdf=!1)},extendPrototype([ShapeModifier],OffsetPathModifier),OffsetPathModifier.prototype.initModifierProperties=function(e,t){this.getValue=this.processKeys,this.amount=PropertyFactory.getProp(e,t.a,0,null,this),this.miterLimit=PropertyFactory.getProp(e,t.ml,0,null,this),this.lineJoin=t.lj,this._isAnimated=0!==this.amount.effectsSequence.length},OffsetPathModifier.prototype.processPath=function(e,t,i,n){var r=shapePool.newElement();r.c=e.c;var a,s,o,l=e.length();e.c||(l-=1);var u=[];for(a=0;a<l;a+=1)o=PolynomialBezier.shapeSegment(e,a),u.push(offsetSegmentSplit(o,t));if(!e.c)for(a=l-1;a>=0;a-=1)o=PolynomialBezier.shapeSegmentInverted(e,a),u.push(offsetSegmentSplit(o,t));u=pruneIntersections(u);var h=null,p=null;for(a=0;a<u.length;a+=1){var c=u[a];for(p&&(h=joinLines(r,p,c[0],i,n)),p=c[c.length-1],s=0;s<c.length;s+=1)o=c[s],h&&pointEqual(o.points[0],h)?r.setXYAt(o.points[1][0],o.points[1][1],"o",r.length()-1):r.setTripleAt(o.points[0][0],o.points[0][1],o.points[1][0],o.points[1][1],o.points[0][0],o.points[0][1],r.length()),r.setTripleAt(o.points[3][0],o.points[3][1],o.points[3][0],o.points[3][1],o.points[2][0],o.points[2][1],r.length()),h=o.points[3]}return u.length&&joinLines(r,p,u[0][0],i,n),r},OffsetPathModifier.prototype.processShapes=function(e){var t,i,n,r,a,s,o=this.shapes.length,l=this.amount.v,u=this.miterLimit.v,h=this.lineJoin;if(0!==l)for(i=0;i<o;i+=1){if(s=(a=this.shapes[i]).localShapeCollection,a.shape._mdf||this._mdf||e)for(s.releaseShapes(),a.shape._mdf=!0,t=a.shape.paths.shapes,r=a.shape.paths._length,n=0;n<r;n+=1)s.addShape(this.processPath(t[n],l,h,u));a.shape.paths=a.localShapeCollection}this.dynamicProperties.length||(this._mdf=!1)};var FontManager=function(){var a={w:0,size:0,shapes:[],data:{shapes:[]}},t=[];t=t.concat([2304,2305,2306,2307,2362,2363,2364,2364,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,2387,2388,2389,2390,2391,2402,2403]);var n=["d83cdffb","d83cdffc","d83cdffd","d83cdffe","d83cdfff"],i=[65039,8205];function c(e,t){var i=createTag("span");i.setAttribute("aria-hidden",!0),i.style.fontFamily=t;var n=createTag("span");n.innerText="giItT1WQy@!-/#",i.style.position="absolute",i.style.left="-10000px",i.style.top="-10000px",i.style.fontSize="300px",i.style.fontVariant="normal",i.style.fontStyle="normal",i.style.fontWeight="normal",i.style.letterSpacing="0",i.appendChild(n),document.body.appendChild(i);var r=n.offsetWidth;return n.style.fontFamily=function(e){var t,i=e.split(","),n=i.length,r=[];for(t=0;t<n;t+=1)"sans-serif"!==i[t]&&"monospace"!==i[t]&&r.push(i[t]);return r.join(",")}(e)+", "+t,{node:n,w:r,parent:i}}function m(e,t){var i,n=document.body&&t?"svg":"canvas",r=getFontProperties(e);if("svg"===n){var a=createNS("text");a.style.fontSize="100px",a.setAttribute("font-family",e.fFamily),a.setAttribute("font-style",r.style),a.setAttribute("font-weight",r.weight),a.textContent="1",e.fClass?(a.style.fontFamily="inherit",a.setAttribute("class",e.fClass)):a.style.fontFamily=e.fFamily,t.appendChild(a),i=a}else{var s=new OffscreenCanvas(500,500).getContext("2d");s.font=r.style+" "+r.weight+" 100px "+e.fFamily,i=s}return{measureText:function(e){return"svg"===n?(i.textContent=e,i.getComputedTextLength()):i.measureText(e).width}}}var e=function(){this.fonts=[],this.chars=null,this.typekitLoaded=0,this.isLoaded=!1,this._warned=!1,this.initTime=Date.now(),this.setIsLoadedBinded=this.setIsLoaded.bind(this),this.checkLoadedFontsBinded=this.checkLoadedFonts.bind(this)};e.isModifier=function(e,t){var i=e.toString(16)+t.toString(16);return-1!==n.indexOf(i)},e.isZeroWidthJoiner=function(e,t){return t?e===i[0]&&t===i[1]:e===i[1]},e.isCombinedCharacter=function(e){return-1!==t.indexOf(e)};var r={addChars:function(e){if(e){var t;this.chars||(this.chars=[]);var i,n,r=e.length,a=this.chars.length;for(t=0;t<r;t+=1){for(i=0,n=!1;i<a;)this.chars[i].style===e[t].style&&this.chars[i].fFamily===e[t].fFamily&&this.chars[i].ch===e[t].ch&&(n=!0),i+=1;n||(this.chars.push(e[t]),a+=1)}}},addFonts:function(e,t){if(e){if(this.chars)return this.isLoaded=!0,void(this.fonts=e.list);if(!document.body)return this.isLoaded=!0,e.list.forEach(function(e){e.helper=m(e),e.cache={}}),void(this.fonts=e.list);var i,n=e.list,r=n.length,a=r;for(i=0;i<r;i+=1){var s,o,l=!0;if(n[i].loaded=!1,n[i].monoCase=c(n[i].fFamily,"monospace"),n[i].sansCase=c(n[i].fFamily,"sans-serif"),n[i].fPath){if("p"===n[i].fOrigin||3===n[i].origin){if((s=document.querySelectorAll('style[f-forigin="p"][f-family="'+n[i].fFamily+'"], style[f-origin="3"][f-family="'+n[i].fFamily+'"]')).length>0&&(l=!1),l){var u=createTag("style");u.setAttribute("f-forigin",n[i].fOrigin),u.setAttribute("f-origin",n[i].origin),u.setAttribute("f-family",n[i].fFamily),u.type="text/css",u.innerText="@font-face {font-family: "+n[i].fFamily+"; font-style: normal; src: url('"+n[i].fPath+"');}",t.appendChild(u)}}else if("g"===n[i].fOrigin||1===n[i].origin){for(s=document.querySelectorAll('link[f-forigin="g"], link[f-origin="1"]'),o=0;o<s.length;o+=1)-1!==s[o].href.indexOf(n[i].fPath)&&(l=!1);if(l){var h=createTag("link");h.setAttribute("f-forigin",n[i].fOrigin),h.setAttribute("f-origin",n[i].origin),h.type="text/css",h.rel="stylesheet",h.href=n[i].fPath,document.body.appendChild(h)}}else if("t"===n[i].fOrigin||2===n[i].origin){for(s=document.querySelectorAll('script[f-forigin="t"], script[f-origin="2"]'),o=0;o<s.length;o+=1)n[i].fPath===s[o].src&&(l=!1);if(l){var p=createTag("link");p.setAttribute("f-forigin",n[i].fOrigin),p.setAttribute("f-origin",n[i].origin),p.setAttribute("rel","stylesheet"),p.setAttribute("href",n[i].fPath),t.appendChild(p)}}}else n[i].loaded=!0,a-=1;n[i].helper=m(n[i],t),n[i].cache={},this.fonts.push(n[i])}0===a?this.isLoaded=!0:setTimeout(this.checkLoadedFonts.bind(this),100)}else this.isLoaded=!0},getCharData:function(e,t,i){for(var n=0,r=this.chars.length;n<r;){if(this.chars[n].ch===e&&this.chars[n].style===t&&this.chars[n].fFamily===i)return this.chars[n];n+=1}return("string"==typeof e&&13!==e.charCodeAt(0)||!e)&&console&&console.warn&&!this._warned&&(this._warned=!0,console.warn("Missing character from exported characters list: ",e,t,i)),a},getFontByName:function(e){for(var t=0,i=this.fonts.length;t<i;){if(this.fonts[t].fName===e)return this.fonts[t];t+=1}return this.fonts[0]},measureText:function(e,t,i){var n=this.getFontByName(t),r=e.charCodeAt(0);if(!n.cache[r+1]){var a=n.helper;if(" "===e){var s=a.measureText("|"+e+"|"),o=a.measureText("||");n.cache[r+1]=(s-o)/100}else n.cache[r+1]=a.measureText(e)/100}return n.cache[r+1]*i},checkLoadedFonts:function(){var e,t,i,n=this.fonts.length,r=n;for(e=0;e<n;e+=1)this.fonts[e].loaded?r-=1:"n"===this.fonts[e].fOrigin||0===this.fonts[e].origin?this.fonts[e].loaded=!0:(t=this.fonts[e].monoCase.node,i=this.fonts[e].monoCase.w,t.offsetWidth!==i?(r-=1,this.fonts[e].loaded=!0):(t=this.fonts[e].sansCase.node,i=this.fonts[e].sansCase.w,t.offsetWidth!==i&&(r-=1,this.fonts[e].loaded=!0)),this.fonts[e].loaded&&(this.fonts[e].sansCase.parent.parentNode.removeChild(this.fonts[e].sansCase.parent),this.fonts[e].monoCase.parent.parentNode.removeChild(this.fonts[e].monoCase.parent)));0!==r&&Date.now()-this.initTime<5e3?setTimeout(this.checkLoadedFontsBinded,20):setTimeout(this.setIsLoadedBinded,10)},setIsLoaded:function(){this.isLoaded=!0}};return e.prototype=r,e}();function RenderableElement(){}RenderableElement.prototype={initRenderable:function(){this.isInRange=!1,this.hidden=!1,this.isTransparent=!1,this.renderableComponents=[]},addRenderableComponent:function(e){-1===this.renderableComponents.indexOf(e)&&this.renderableComponents.push(e)},removeRenderableComponent:function(e){-1!==this.renderableComponents.indexOf(e)&&this.renderableComponents.splice(this.renderableComponents.indexOf(e),1)},prepareRenderableFrame:function(e){this.checkLayerLimits(e)},checkTransparency:function(){this.finalTransform.mProp.o.v<=0?!this.isTransparent&&this.globalData.renderConfig.hideOnTransparent&&(this.isTransparent=!0,this.hide()):this.isTransparent&&(this.isTransparent=!1,this.show())},checkLayerLimits:function(e){this.data.ip-this.data.st<=e&&this.data.op-this.data.st>e?!0!==this.isInRange&&(this.globalData._mdf=!0,this._mdf=!0,this.isInRange=!0,this.show()):!1!==this.isInRange&&(this.globalData._mdf=!0,this.isInRange=!1,this.hide())},renderRenderable:function(){var e,t=this.renderableComponents.length;for(e=0;e<t;e+=1)this.renderableComponents[e].renderFrame(this._isFirstFrame)},sourceRectAtTime:function(){return{top:0,left:0,width:100,height:100}},getLayerSize:function(){return 5===this.data.ty?{w:this.data.textData.width,h:this.data.textData.height}:{w:this.data.width,h:this.data.height}}};var getBlendMode=(blendModeEnums={0:"source-over",1:"multiply",2:"screen",3:"overlay",4:"darken",5:"lighten",6:"color-dodge",7:"color-burn",8:"hard-light",9:"soft-light",10:"difference",11:"exclusion",12:"hue",13:"saturation",14:"color",15:"luminosity"},function(e){return blendModeEnums[e]||""}),blendModeEnums;function SliderEffect(e,t,i){this.p=PropertyFactory.getProp(t,e.v,0,0,i)}function AngleEffect(e,t,i){this.p=PropertyFactory.getProp(t,e.v,0,0,i)}function ColorEffect(e,t,i){this.p=PropertyFactory.getProp(t,e.v,1,0,i)}function PointEffect(e,t,i){this.p=PropertyFactory.getProp(t,e.v,1,0,i)}function LayerIndexEffect(e,t,i){this.p=PropertyFactory.getProp(t,e.v,0,0,i)}function MaskIndexEffect(e,t,i){this.p=PropertyFactory.getProp(t,e.v,0,0,i)}function CheckboxEffect(e,t,i){this.p=PropertyFactory.getProp(t,e.v,0,0,i)}function NoValueEffect(){this.p={}}function EffectsManager(e,t){var i,n=e.ef||[];this.effectElements=[];var r,a=n.length;for(i=0;i<a;i+=1)r=new GroupEffect(n[i],t),this.effectElements.push(r)}function GroupEffect(e,t){this.init(e,t)}function BaseElement(){}function FrameElement(){}function FootageElement(e,t,i){this.initFrame(),this.initRenderable(),this.assetData=t.getAssetData(e.refId),this.footageData=t.imageLoader.getAsset(this.assetData),this.initBaseData(e,t,i)}function AudioElement(e,t,i){this.initFrame(),this.initRenderable(),this.assetData=t.getAssetData(e.refId),this.initBaseData(e,t,i),this._isPlaying=!1,this._canPlay=!1;var n=this.globalData.getAssetsPath(this.assetData);this.audio=this.globalData.audioController.createAudio(n),this._currentTime=0,this.globalData.audioController.addAudio(this),this._volumeMultiplier=1,this._volume=1,this._previousVolume=null,this.tm=e.tm?PropertyFactory.getProp(this,e.tm,0,t.frameRate,this):{_placeholder:!0},this.lv=PropertyFactory.getProp(this,e.au&&e.au.lv?e.au.lv:{k:[100]},1,.01,this)}function BaseRenderer(){}function TransformElement(){}function MaskElement(e,t,i){this.data=e,this.element=t,this.globalData=i,this.storedData=[],this.masksProperties=this.data.masksProperties||[],this.maskElement=null;var n,r,a=this.globalData.defs,s=this.masksProperties?this.masksProperties.length:0;this.viewData=createSizedArray(s),this.solidPath="";var o,l,u,h,p,c,m=this.masksProperties,f=0,d=[],g=createElementID(),v="clipPath",y="clip-path";for(n=0;n<s;n+=1)if(("a"!==m[n].mode&&"n"!==m[n].mode||m[n].inv||100!==m[n].o.k||m[n].o.x)&&(v="mask",y="mask"),"s"!==m[n].mode&&"i"!==m[n].mode||0!==f?u=null:((u=createNS("rect")).setAttribute("fill","#ffffff"),u.setAttribute("width",this.element.comp.data.w||0),u.setAttribute("height",this.element.comp.data.h||0),d.push(u)),r=createNS("path"),"n"===m[n].mode)this.viewData[n]={op:PropertyFactory.getProp(this.element,m[n].o,0,.01,this.element),prop:ShapePropertyFactory.getShapeProp(this.element,m[n],3),elem:r,lastPath:""},a.appendChild(r);else{var b;if(f+=1,r.setAttribute("fill","s"===m[n].mode?"#000000":"#ffffff"),r.setAttribute("clip-rule","nonzero"),0!==m[n].x.k?(v="mask",y="mask",c=PropertyFactory.getProp(this.element,m[n].x,0,null,this.element),b=createElementID(),(h=createNS("filter")).setAttribute("id",b),(p=createNS("feMorphology")).setAttribute("operator","erode"),p.setAttribute("in","SourceGraphic"),p.setAttribute("radius","0"),h.appendChild(p),a.appendChild(h),r.setAttribute("stroke","s"===m[n].mode?"#000000":"#ffffff")):(p=null,c=null),this.storedData[n]={elem:r,x:c,expan:p,lastPath:"",lastOperator:"",filterId:b,lastRadius:0},"i"===m[n].mode){l=d.length;var x=createNS("g");for(o=0;o<l;o+=1)x.appendChild(d[o]);var A=createNS("mask");A.setAttribute("mask-type","alpha"),A.setAttribute("id",g+"_"+f),A.appendChild(r),a.appendChild(A),x.setAttribute("mask","url("+getLocationHref()+"#"+g+"_"+f+")"),d.length=0,d.push(x)}else d.push(r);m[n].inv&&!this.solidPath&&(this.solidPath=this.createLayerSolidPath()),this.viewData[n]={elem:r,lastPath:"",op:PropertyFactory.getProp(this.element,m[n].o,0,.01,this.element),prop:ShapePropertyFactory.getShapeProp(this.element,m[n],3),invRect:u},this.viewData[n].prop.k||this.drawPath(m[n],this.viewData[n].prop.v,this.viewData[n])}for(this.maskElement=createNS(v),s=d.length,n=0;n<s;n+=1)this.maskElement.appendChild(d[n]);f>0&&(this.maskElement.setAttribute("id",g),this.element.maskedElement.setAttribute(y,"url("+getLocationHref()+"#"+g+")"),a.appendChild(this.maskElement)),this.viewData.length&&this.element.addRenderableComponent(this)}extendPrototype([DynamicPropertyContainer],GroupEffect),GroupEffect.prototype.getValue=GroupEffect.prototype.iterateDynamicProperties,GroupEffect.prototype.init=function(e,t){var i;this.data=e,this.effectElements=[],this.initDynamicPropertyContainer(t);var n,r=this.data.ef.length,a=this.data.ef;for(i=0;i<r;i+=1){switch(n=null,a[i].ty){case 0:n=new SliderEffect(a[i],t,this);break;case 1:n=new AngleEffect(a[i],t,this);break;case 2:n=new ColorEffect(a[i],t,this);break;case 3:n=new PointEffect(a[i],t,this);break;case 4:case 7:n=new CheckboxEffect(a[i],t,this);break;case 10:n=new LayerIndexEffect(a[i],t,this);break;case 11:n=new MaskIndexEffect(a[i],t,this);break;case 5:n=new EffectsManager(a[i],t,this);break;default:n=new NoValueEffect(a[i],t,this)}n&&this.effectElements.push(n)}},BaseElement.prototype={checkMasks:function(){if(!this.data.hasMask)return!1;for(var e=0,t=this.data.masksProperties.length;e<t;){if("n"!==this.data.masksProperties[e].mode&&!1!==this.data.masksProperties[e].cl)return!0;e+=1}return!1},initExpressions:function(){var e=getExpressionInterfaces();if(e){var t=e("layer"),i=e("effects"),n=e("shape"),r=e("text"),a=e("comp");this.layerInterface=t(this),this.data.hasMask&&this.maskManager&&this.layerInterface.registerMaskInterface(this.maskManager);var s=i.createEffectsInterface(this,this.layerInterface);this.layerInterface.registerEffectsInterface(s),0===this.data.ty||this.data.xt?this.compInterface=a(this):4===this.data.ty?(this.layerInterface.shapeInterface=n(this.shapesData,this.itemsData,this.layerInterface),this.layerInterface.content=this.layerInterface.shapeInterface):5===this.data.ty&&(this.layerInterface.textInterface=r(this),this.layerInterface.text=this.layerInterface.textInterface)}},setBlendMode:function(){var e=getBlendMode(this.data.bm);(this.baseElement||this.layerElement).style["mix-blend-mode"]=e},initBaseData:function(e,t,i){this.globalData=t,this.comp=i,this.data=e,this.layerId=createElementID(),this.data.sr||(this.data.sr=1),this.effectsManager=new EffectsManager(this.data,this,this.dynamicProperties)},getType:function(){return this.type},sourceRectAtTime:function(){}},FrameElement.prototype={initFrame:function(){this._isFirstFrame=!1,this.dynamicProperties=[],this._mdf=!1},prepareProperties:function(e,t){var i,n=this.dynamicProperties.length;for(i=0;i<n;i+=1)(t||this._isParent&&"transform"===this.dynamicProperties[i].propType)&&(this.dynamicProperties[i].getValue(),this.dynamicProperties[i]._mdf&&(this.globalData._mdf=!0,this._mdf=!0))},addDynamicProperty:function(e){-1===this.dynamicProperties.indexOf(e)&&this.dynamicProperties.push(e)}},FootageElement.prototype.prepareFrame=function(){},extendPrototype([RenderableElement,BaseElement,FrameElement],FootageElement),FootageElement.prototype.getBaseElement=function(){return null},FootageElement.prototype.renderFrame=function(){},FootageElement.prototype.destroy=function(){},FootageElement.prototype.initExpressions=function(){var e=getExpressionInterfaces();if(e){var t=e("footage");this.layerInterface=t(this)}},FootageElement.prototype.getFootageData=function(){return this.footageData},AudioElement.prototype.prepareFrame=function(e){if(this.prepareRenderableFrame(e,!0),this.prepareProperties(e,!0),this.tm._placeholder)this._currentTime=e/this.data.sr;else{var t=this.tm.v;this._currentTime=t}this._volume=this.lv.v[0];var i=this._volume*this._volumeMultiplier;this._previousVolume!==i&&(this._previousVolume=i,this.audio.volume(i))},extendPrototype([RenderableElement,BaseElement,FrameElement],AudioElement),AudioElement.prototype.renderFrame=function(){this.isInRange&&this._canPlay&&(this._isPlaying?(!this.audio.playing()||Math.abs(this._currentTime/this.globalData.frameRate-this.audio.seek())>.1)&&this.audio.seek(this._currentTime/this.globalData.frameRate):(this.audio.play(),this.audio.seek(this._currentTime/this.globalData.frameRate),this._isPlaying=!0))},AudioElement.prototype.show=function(){},AudioElement.prototype.hide=function(){this.audio.pause(),this._isPlaying=!1},AudioElement.prototype.pause=function(){this.audio.pause(),this._isPlaying=!1,this._canPlay=!1},AudioElement.prototype.resume=function(){this._canPlay=!0},AudioElement.prototype.setRate=function(e){this.audio.rate(e)},AudioElement.prototype.volume=function(e){this._volumeMultiplier=e,this._previousVolume=e*this._volume,this.audio.volume(this._previousVolume)},AudioElement.prototype.getBaseElement=function(){return null},AudioElement.prototype.destroy=function(){},AudioElement.prototype.sourceRectAtTime=function(){},AudioElement.prototype.initExpressions=function(){},BaseRenderer.prototype.checkLayers=function(e){var t,i,n=this.layers.length;for(this.completeLayers=!0,t=n-1;t>=0;t-=1)this.elements[t]||(i=this.layers[t]).ip-i.st<=e-this.layers[t].st&&i.op-i.st>e-this.layers[t].st&&this.buildItem(t),this.completeLayers=!!this.elements[t]&&this.completeLayers;this.checkPendingElements()},BaseRenderer.prototype.createItem=function(e){switch(e.ty){case 2:return this.createImage(e);case 0:return this.createComp(e);case 1:return this.createSolid(e);case 3:default:return this.createNull(e);case 4:return this.createShape(e);case 5:return this.createText(e);case 6:return this.createAudio(e);case 13:return this.createCamera(e);case 15:return this.createFootage(e)}},BaseRenderer.prototype.createCamera=function(){throw new Error("You're using a 3d camera. Try the html renderer.")},BaseRenderer.prototype.createAudio=function(e){return new AudioElement(e,this.globalData,this)},BaseRenderer.prototype.createFootage=function(e){return new FootageElement(e,this.globalData,this)},BaseRenderer.prototype.buildAllItems=function(){var e,t=this.layers.length;for(e=0;e<t;e+=1)this.buildItem(e);this.checkPendingElements()},BaseRenderer.prototype.includeLayers=function(e){var t;this.completeLayers=!1;var i,n=e.length,r=this.layers.length;for(t=0;t<n;t+=1)for(i=0;i<r;){if(this.layers[i].id===e[t].id){this.layers[i]=e[t];break}i+=1}},BaseRenderer.prototype.setProjectInterface=function(e){this.globalData.projectInterface=e},BaseRenderer.prototype.initItems=function(){this.globalData.progressiveLoad||this.buildAllItems()},BaseRenderer.prototype.buildElementParenting=function(e,t,i){for(var n=this.elements,r=this.layers,a=0,s=r.length;a<s;)r[a].ind==t&&(n[a]&&!0!==n[a]?(i.push(n[a]),n[a].setAsParent(),void 0!==r[a].parent?this.buildElementParenting(e,r[a].parent,i):e.setHierarchy(i)):(this.buildItem(a),this.addPendingElement(e))),a+=1},BaseRenderer.prototype.addPendingElement=function(e){this.pendingElements.push(e)},BaseRenderer.prototype.searchExtraCompositions=function(e){var t,i=e.length;for(t=0;t<i;t+=1)if(e[t].xt){var n=this.createComp(e[t]);n.initExpressions(),this.globalData.projectInterface.registerComposition(n)}},BaseRenderer.prototype.getElementById=function(e){var t,i=this.elements.length;for(t=0;t<i;t+=1)if(this.elements[t].data.ind===e)return this.elements[t];return null},BaseRenderer.prototype.getElementByPath=function(e){var t,i=e.shift();if("number"==typeof i)t=this.elements[i];else{var n,r=this.elements.length;for(n=0;n<r;n+=1)if(this.elements[n].data.nm===i){t=this.elements[n];break}}return 0===e.length?t:t.getElementByPath(e)},BaseRenderer.prototype.setupGlobalData=function(e,t){this.globalData.fontManager=new FontManager,this.globalData.fontManager.addChars(e.chars),this.globalData.fontManager.addFonts(e.fonts,t),this.globalData.getAssetData=this.animationItem.getAssetData.bind(this.animationItem),this.globalData.getAssetsPath=this.animationItem.getAssetsPath.bind(this.animationItem),this.globalData.imageLoader=this.animationItem.imagePreloader,this.globalData.audioController=this.animationItem.audioController,this.globalData.frameId=0,this.globalData.frameRate=e.fr,this.globalData.nm=e.nm,this.globalData.compSize={w:e.w,h:e.h}},TransformElement.prototype={initTransform:function(){this.finalTransform={mProp:this.data.ks?TransformPropertyFactory.getTransformProperty(this,this.data.ks,this):{o:0},_matMdf:!1,_opMdf:!1,mat:new Matrix},this.data.ao&&(this.finalTransform.mProp.autoOriented=!0),this.data.ty},renderTransform:function(){if(this.finalTransform._opMdf=this.finalTransform.mProp.o._mdf||this._isFirstFrame,this.finalTransform._matMdf=this.finalTransform.mProp._mdf||this._isFirstFrame,this.hierarchy){var e,t=this.finalTransform.mat,i=0,n=this.hierarchy.length;if(!this.finalTransform._matMdf)for(;i<n;){if(this.hierarchy[i].finalTransform.mProp._mdf){this.finalTransform._matMdf=!0;break}i+=1}if(this.finalTransform._matMdf)for(e=this.finalTransform.mProp.v.props,t.cloneFromProps(e),i=0;i<n;i+=1)e=this.hierarchy[i].finalTransform.mProp.v.props,t.transform(e[0],e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[8],e[9],e[10],e[11],e[12],e[13],e[14],e[15])}},globalToLocal:function(e){var t=[];t.push(this.finalTransform);for(var i,n=!0,r=this.comp;n;)r.finalTransform?(r.data.hasMask&&t.splice(0,0,r.finalTransform),r=r.comp):n=!1;var a,s=t.length;for(i=0;i<s;i+=1)a=t[i].mat.applyToPointArray(0,0,0),e=[e[0]-a[0],e[1]-a[1],0];return e},mHelper:new Matrix},MaskElement.prototype.getMaskProperty=function(e){return this.viewData[e].prop},MaskElement.prototype.renderFrame=function(e){var t,i=this.element.finalTransform.mat,n=this.masksProperties.length;for(t=0;t<n;t+=1)if((this.viewData[t].prop._mdf||e)&&this.drawPath(this.masksProperties[t],this.viewData[t].prop.v,this.viewData[t]),(this.viewData[t].op._mdf||e)&&this.viewData[t].elem.setAttribute("fill-opacity",this.viewData[t].op.v),"n"!==this.masksProperties[t].mode&&(this.viewData[t].invRect&&(this.element.finalTransform.mProp._mdf||e)&&this.viewData[t].invRect.setAttribute("transform",i.getInverseMatrix().to2dCSS()),this.storedData[t].x&&(this.storedData[t].x._mdf||e))){var r=this.storedData[t].expan;this.storedData[t].x.v<0?("erode"!==this.storedData[t].lastOperator&&(this.storedData[t].lastOperator="erode",this.storedData[t].elem.setAttribute("filter","url("+getLocationHref()+"#"+this.storedData[t].filterId+")")),r.setAttribute("radius",-this.storedData[t].x.v)):("dilate"!==this.storedData[t].lastOperator&&(this.storedData[t].lastOperator="dilate",this.storedData[t].elem.setAttribute("filter",null)),this.storedData[t].elem.setAttribute("stroke-width",2*this.storedData[t].x.v))}},MaskElement.prototype.getMaskelement=function(){return this.maskElement},MaskElement.prototype.createLayerSolidPath=function(){var e="M0,0 ";return e+=" h"+this.globalData.compSize.w,e+=" v"+this.globalData.compSize.h,e+=" h-"+this.globalData.compSize.w,e+=" v-"+this.globalData.compSize.h+" "},MaskElement.prototype.drawPath=function(e,t,i){var n,r,a=" M"+t.v[0][0]+","+t.v[0][1];for(r=t._length,n=1;n<r;n+=1)a+=" C"+t.o[n-1][0]+","+t.o[n-1][1]+" "+t.i[n][0]+","+t.i[n][1]+" "+t.v[n][0]+","+t.v[n][1];if(t.c&&r>1&&(a+=" C"+t.o[n-1][0]+","+t.o[n-1][1]+" "+t.i[0][0]+","+t.i[0][1]+" "+t.v[0][0]+","+t.v[0][1]),i.lastPath!==a){var s="";i.elem&&(t.c&&(s=e.inv?this.solidPath+a:a),i.elem.setAttribute("d",s)),i.lastPath=a}},MaskElement.prototype.destroy=function(){this.element=null,this.globalData=null,this.maskElement=null,this.data=null,this.masksProperties=null};var filtersFactory=function(){var e={};return e.createFilter=function(e,t){var i=createNS("filter");i.setAttribute("id",e),!0!==t&&(i.setAttribute("filterUnits","objectBoundingBox"),i.setAttribute("x","0%"),i.setAttribute("y","0%"),i.setAttribute("width","100%"),i.setAttribute("height","100%"));return i},e.createAlphaToLuminanceFilter=function(){var e=createNS("feColorMatrix");return e.setAttribute("type","matrix"),e.setAttribute("color-interpolation-filters","sRGB"),e.setAttribute("values","0 0 0 1 0  0 0 0 1 0  0 0 0 1 0  0 0 0 1 1"),e},e}(),featureSupport=function(){var e={maskType:!0,svgLumaHidden:!0,offscreenCanvas:"undefined"!=typeof OffscreenCanvas};return(/MSIE 10/i.test(navigator.userAgent)||/MSIE 9/i.test(navigator.userAgent)||/rv:11.0/i.test(navigator.userAgent)||/Edge\/\d./i.test(navigator.userAgent))&&(e.maskType=!1),/firefox/i.test(navigator.userAgent)&&(e.svgLumaHidden=!1),e}(),registeredEffects={},idPrefix="filter_result_";function SVGEffects(e){var t,i,n="SourceGraphic",r=e.data.ef?e.data.ef.length:0,a=createElementID(),s=filtersFactory.createFilter(a,!0),o=0;for(this.filters=[],t=0;t<r;t+=1){i=null;var l=e.data.ef[t].ty;if(registeredEffects[l])i=new(0,registeredEffects[l].effect)(s,e.effectsManager.effectElements[t],e,idPrefix+o,n),n=idPrefix+o,registeredEffects[l].countsAsEffect&&(o+=1);i&&this.filters.push(i)}o&&(e.globalData.defs.appendChild(s),e.layerElement.setAttribute("filter","url("+getLocationHref()+"#"+a+")")),this.filters.length&&e.addRenderableComponent(this)}function registerEffect(e,t,i){registeredEffects[e]={effect:t,countsAsEffect:i}}function SVGBaseElement(){}function HierarchyElement(){}function RenderableDOMElement(){}function IImageElement(e,t,i){this.assetData=t.getAssetData(e.refId),this.initElement(e,t,i),this.sourceRect={top:0,left:0,width:this.assetData.w,height:this.assetData.h}}function ProcessedElement(e,t){this.elem=e,this.pos=t}function IShapeElement(){}SVGEffects.prototype.renderFrame=function(e){var t,i=this.filters.length;for(t=0;t<i;t+=1)this.filters[t].renderFrame(e)},SVGBaseElement.prototype={initRendererElement:function(){this.layerElement=createNS("g")},createContainerElements:function(){this.matteElement=createNS("g"),this.transformedElement=this.layerElement,this.maskedElement=this.layerElement,this._sizeChanged=!1;var e=null;if(this.data.td){this.matteMasks={};var t=createNS("g");t.setAttribute("id",this.layerId),t.appendChild(this.layerElement),e=t,this.globalData.defs.appendChild(t)}else this.data.tt?(this.matteElement.appendChild(this.layerElement),e=this.matteElement,this.baseElement=this.matteElement):this.baseElement=this.layerElement;if(this.data.ln&&this.layerElement.setAttribute("id",this.data.ln),this.data.cl&&this.layerElement.setAttribute("class",this.data.cl),0===this.data.ty&&!this.data.hd){var i=createNS("clipPath"),n=createNS("path");n.setAttribute("d","M0,0 L"+this.data.w+",0 L"+this.data.w+","+this.data.h+" L0,"+this.data.h+"z");var r=createElementID();if(i.setAttribute("id",r),i.appendChild(n),this.globalData.defs.appendChild(i),this.checkMasks()){var a=createNS("g");a.setAttribute("clip-path","url("+getLocationHref()+"#"+r+")"),a.appendChild(this.layerElement),this.transformedElement=a,e?e.appendChild(this.transformedElement):this.baseElement=this.transformedElement}else this.layerElement.setAttribute("clip-path","url("+getLocationHref()+"#"+r+")")}0!==this.data.bm&&this.setBlendMode()},renderElement:function(){this.finalTransform._matMdf&&this.transformedElement.setAttribute("transform",this.finalTransform.mat.to2dCSS()),this.finalTransform._opMdf&&this.transformedElement.setAttribute("opacity",this.finalTransform.mProp.o.v)},destroyBaseElement:function(){this.layerElement=null,this.matteElement=null,this.maskManager.destroy()},getBaseElement:function(){return this.data.hd?null:this.baseElement},createRenderableComponents:function(){this.maskManager=new MaskElement(this.data,this,this.globalData),this.renderableEffectsManager=new SVGEffects(this)},getMatte:function(e){if(this.matteMasks||(this.matteMasks={}),!this.matteMasks[e]){var t,i,n,r,a=this.layerId+"_"+e;if(1===e||3===e){var s=createNS("mask");s.setAttribute("id",a),s.setAttribute("mask-type",3===e?"luminance":"alpha"),(n=createNS("use")).setAttributeNS("http://www.w3.org/1999/xlink","href","#"+this.layerId),s.appendChild(n),this.globalData.defs.appendChild(s),featureSupport.maskType||1!==e||(s.setAttribute("mask-type","luminance"),t=createElementID(),i=filtersFactory.createFilter(t),this.globalData.defs.appendChild(i),i.appendChild(filtersFactory.createAlphaToLuminanceFilter()),(r=createNS("g")).appendChild(n),s.appendChild(r),r.setAttribute("filter","url("+getLocationHref()+"#"+t+")"))}else if(2===e){var o=createNS("mask");o.setAttribute("id",a),o.setAttribute("mask-type","alpha");var l=createNS("g");o.appendChild(l),t=createElementID(),i=filtersFactory.createFilter(t);var u=createNS("feComponentTransfer");u.setAttribute("in","SourceGraphic"),i.appendChild(u);var h=createNS("feFuncA");h.setAttribute("type","table"),h.setAttribute("tableValues","1.0 0.0"),u.appendChild(h),this.globalData.defs.appendChild(i);var p=createNS("rect");p.setAttribute("width",this.comp.data.w),p.setAttribute("height",this.comp.data.h),p.setAttribute("x","0"),p.setAttribute("y","0"),p.setAttribute("fill","#ffffff"),p.setAttribute("opacity","0"),l.setAttribute("filter","url("+getLocationHref()+"#"+t+")"),l.appendChild(p),(n=createNS("use")).setAttributeNS("http://www.w3.org/1999/xlink","href","#"+this.layerId),l.appendChild(n),featureSupport.maskType||(o.setAttribute("mask-type","luminance"),i.appendChild(filtersFactory.createAlphaToLuminanceFilter()),r=createNS("g"),l.appendChild(p),r.appendChild(this.layerElement),l.appendChild(r)),this.globalData.defs.appendChild(o)}this.matteMasks[e]=a}return this.matteMasks[e]},setMatte:function(e){this.matteElement&&this.matteElement.setAttribute("mask","url("+getLocationHref()+"#"+e+")")}},HierarchyElement.prototype={initHierarchy:function(){this.hierarchy=[],this._isParent=!1,this.checkParenting()},setHierarchy:function(e){this.hierarchy=e},setAsParent:function(){this._isParent=!0},checkParenting:function(){void 0!==this.data.parent&&this.comp.buildElementParenting(this,this.data.parent,[])}},extendPrototype([RenderableElement,createProxyFunction({initElement:function(e,t,i){this.initFrame(),this.initBaseData(e,t,i),this.initTransform(e,t,i),this.initHierarchy(),this.initRenderable(),this.initRendererElement(),this.createContainerElements(),this.createRenderableComponents(),this.createContent(),this.hide()},hide:function(){this.hidden||this.isInRange&&!this.isTransparent||((this.baseElement||this.layerElement).style.display="none",this.hidden=!0)},show:function(){this.isInRange&&!this.isTransparent&&(this.data.hd||((this.baseElement||this.layerElement).style.display="block"),this.hidden=!1,this._isFirstFrame=!0)},renderFrame:function(){this.data.hd||this.hidden||(this.renderTransform(),this.renderRenderable(),this.renderElement(),this.renderInnerContent(),this._isFirstFrame&&(this._isFirstFrame=!1))},renderInnerContent:function(){},prepareFrame:function(e){this._mdf=!1,this.prepareRenderableFrame(e),this.prepareProperties(e,this.isInRange),this.checkTransparency()},destroy:function(){this.innerElem=null,this.destroyBaseElement()}})],RenderableDOMElement),extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement],IImageElement),IImageElement.prototype.createContent=function(){var e=this.globalData.getAssetsPath(this.assetData);this.innerElem=createNS("image"),this.innerElem.setAttribute("width",this.assetData.w+"px"),this.innerElem.setAttribute("height",this.assetData.h+"px"),this.innerElem.setAttribute("preserveAspectRatio",this.assetData.pr||this.globalData.renderConfig.imagePreserveAspectRatio),this.innerElem.setAttributeNS("http://www.w3.org/1999/xlink","href",e),this.layerElement.appendChild(this.innerElem)},IImageElement.prototype.sourceRectAtTime=function(){return this.sourceRect},IShapeElement.prototype={addShapeToModifiers:function(e){var t,i=this.shapeModifiers.length;for(t=0;t<i;t+=1)this.shapeModifiers[t].addShape(e)},isShapeInAnimatedModifiers:function(e){for(var t=this.shapeModifiers.length;0<t;)if(this.shapeModifiers[0].isAnimatedWithShape(e))return!0;return!1},renderModifiers:function(){if(this.shapeModifiers.length){var e,t=this.shapes.length;for(e=0;e<t;e+=1)this.shapes[e].sh.reset();for(e=(t=this.shapeModifiers.length)-1;e>=0&&!this.shapeModifiers[e].processShapes(this._isFirstFrame);e-=1);}},searchProcessedElement:function(e){for(var t=this.processedElements,i=0,n=t.length;i<n;){if(t[i].elem===e)return t[i].pos;i+=1}return 0},addProcessedElement:function(e,t){for(var i=this.processedElements,n=i.length;n;)if(i[n-=1].elem===e)return void(i[n].pos=t);i.push(new ProcessedElement(e,t))},prepareFrame:function(e){this.prepareRenderableFrame(e),this.prepareProperties(e,this.isInRange)}};var lineCapEnum={1:"butt",2:"round",3:"square"},lineJoinEnum={1:"miter",2:"round",3:"bevel"};function SVGShapeData(e,t,i){this.caches=[],this.styles=[],this.transformers=e,this.lStr="",this.sh=i,this.lvl=t,this._isAnimated=!!i.k;for(var n=0,r=e.length;n<r;){if(e[n].mProps.dynamicProperties.length){this._isAnimated=!0;break}n+=1}}function SVGStyleData(e,t){this.data=e,this.type=e.ty,this.d="",this.lvl=t,this._mdf=!1,this.closed=!0===e.hd,this.pElem=createNS("path"),this.msElem=null}function DashProperty(e,t,i,n){var r;this.elem=e,this.frameId=-1,this.dataProps=createSizedArray(t.length),this.renderer=i,this.k=!1,this.dashStr="",this.dashArray=createTypedArray("float32",t.length?t.length-1:0),this.dashoffset=createTypedArray("float32",1),this.initDynamicPropertyContainer(n);var a,s=t.length||0;for(r=0;r<s;r+=1)a=PropertyFactory.getProp(e,t[r].v,0,0,this),this.k=a.k||this.k,this.dataProps[r]={n:t[r].n,p:a};this.k||this.getValue(!0),this._isAnimated=this.k}function SVGStrokeStyleData(e,t,i){this.initDynamicPropertyContainer(e),this.getValue=this.iterateDynamicProperties,this.o=PropertyFactory.getProp(e,t.o,0,.01,this),this.w=PropertyFactory.getProp(e,t.w,0,null,this),this.d=new DashProperty(e,t.d||{},"svg",this),this.c=PropertyFactory.getProp(e,t.c,1,255,this),this.style=i,this._isAnimated=!!this._isAnimated}function SVGFillStyleData(e,t,i){this.initDynamicPropertyContainer(e),this.getValue=this.iterateDynamicProperties,this.o=PropertyFactory.getProp(e,t.o,0,.01,this),this.c=PropertyFactory.getProp(e,t.c,1,255,this),this.style=i}function SVGNoStyleData(e,t,i){this.initDynamicPropertyContainer(e),this.getValue=this.iterateDynamicProperties,this.style=i}function GradientProperty(e,t,i){this.data=t,this.c=createTypedArray("uint8c",4*t.p);var n=t.k.k[0].s?t.k.k[0].s.length-4*t.p:t.k.k.length-4*t.p;this.o=createTypedArray("float32",n),this._cmdf=!1,this._omdf=!1,this._collapsable=this.checkCollapsable(),this._hasOpacity=n,this.initDynamicPropertyContainer(i),this.prop=PropertyFactory.getProp(e,t.k,1,null,this),this.k=this.prop.k,this.getValue(!0)}function SVGGradientFillStyleData(e,t,i){this.initDynamicPropertyContainer(e),this.getValue=this.iterateDynamicProperties,this.initGradientData(e,t,i)}function SVGGradientStrokeStyleData(e,t,i){this.initDynamicPropertyContainer(e),this.getValue=this.iterateDynamicProperties,this.w=PropertyFactory.getProp(e,t.w,0,null,this),this.d=new DashProperty(e,t.d||{},"svg",this),this.initGradientData(e,t,i),this._isAnimated=!!this._isAnimated}function ShapeGroupData(){this.it=[],this.prevViewData=[],this.gr=createNS("g")}function SVGTransformData(e,t,i){this.transform={mProps:e,op:t,container:i},this.elements=[],this._isAnimated=this.transform.mProps.dynamicProperties.length||this.transform.op.effectsSequence.length}SVGShapeData.prototype.setAsAnimated=function(){this._isAnimated=!0},SVGStyleData.prototype.reset=function(){this.d="",this._mdf=!1},DashProperty.prototype.getValue=function(e){if((this.elem.globalData.frameId!==this.frameId||e)&&(this.frameId=this.elem.globalData.frameId,this.iterateDynamicProperties(),this._mdf=this._mdf||e,this._mdf)){var t=0,i=this.dataProps.length;for("svg"===this.renderer&&(this.dashStr=""),t=0;t<i;t+=1)"o"!==this.dataProps[t].n?"svg"===this.renderer?this.dashStr+=" "+this.dataProps[t].p.v:this.dashArray[t]=this.dataProps[t].p.v:this.dashoffset[0]=this.dataProps[t].p.v}},extendPrototype([DynamicPropertyContainer],DashProperty),extendPrototype([DynamicPropertyContainer],SVGStrokeStyleData),extendPrototype([DynamicPropertyContainer],SVGFillStyleData),extendPrototype([DynamicPropertyContainer],SVGNoStyleData),GradientProperty.prototype.comparePoints=function(e,t){for(var i=0,n=this.o.length/2;i<n;){if(Math.abs(e[4*i]-e[4*t+2*i])>.01)return!1;i+=1}return!0},GradientProperty.prototype.checkCollapsable=function(){if(this.o.length/2!=this.c.length/4)return!1;if(this.data.k.k[0].s)for(var e=0,t=this.data.k.k.length;e<t;){if(!this.comparePoints(this.data.k.k[e].s,this.data.p))return!1;e+=1}else if(!this.comparePoints(this.data.k.k,this.data.p))return!1;return!0},GradientProperty.prototype.getValue=function(e){if(this.prop.getValue(),this._mdf=!1,this._cmdf=!1,this._omdf=!1,this.prop._mdf||e){var t,i,n,r=4*this.data.p;for(t=0;t<r;t+=1)i=t%4==0?100:255,n=Math.round(this.prop.v[t]*i),this.c[t]!==n&&(this.c[t]=n,this._cmdf=!e);if(this.o.length)for(r=this.prop.v.length,t=4*this.data.p;t<r;t+=1)i=t%2==0?100:1,n=t%2==0?Math.round(100*this.prop.v[t]):this.prop.v[t],this.o[t-4*this.data.p]!==n&&(this.o[t-4*this.data.p]=n,this._omdf=!e);this._mdf=!e}},extendPrototype([DynamicPropertyContainer],GradientProperty),SVGGradientFillStyleData.prototype.initGradientData=function(e,t,i){this.o=PropertyFactory.getProp(e,t.o,0,.01,this),this.s=PropertyFactory.getProp(e,t.s,1,null,this),this.e=PropertyFactory.getProp(e,t.e,1,null,this),this.h=PropertyFactory.getProp(e,t.h||{k:0},0,.01,this),this.a=PropertyFactory.getProp(e,t.a||{k:0},0,degToRads,this),this.g=new GradientProperty(e,t.g,this),this.style=i,this.stops=[],this.setGradientData(i.pElem,t),this.setGradientOpacity(t,i),this._isAnimated=!!this._isAnimated},SVGGradientFillStyleData.prototype.setGradientData=function(e,t){var i=createElementID(),n=createNS(1===t.t?"linearGradient":"radialGradient");n.setAttribute("id",i),n.setAttribute("spreadMethod","pad"),n.setAttribute("gradientUnits","userSpaceOnUse");var r,a,s,o=[];for(s=4*t.g.p,a=0;a<s;a+=4)r=createNS("stop"),n.appendChild(r),o.push(r);e.setAttribute("gf"===t.ty?"fill":"stroke","url("+getLocationHref()+"#"+i+")"),this.gf=n,this.cst=o},SVGGradientFillStyleData.prototype.setGradientOpacity=function(e,t){if(this.g._hasOpacity&&!this.g._collapsable){var i,n,r,a=createNS("mask"),s=createNS("path");a.appendChild(s);var o=createElementID(),l=createElementID();a.setAttribute("id",l);var u=createNS(1===e.t?"linearGradient":"radialGradient");u.setAttribute("id",o),u.setAttribute("spreadMethod","pad"),u.setAttribute("gradientUnits","userSpaceOnUse"),r=e.g.k.k[0].s?e.g.k.k[0].s.length:e.g.k.k.length;var h=this.stops;for(n=4*e.g.p;n<r;n+=2)(i=createNS("stop")).setAttribute("stop-color","rgb(255,255,255)"),u.appendChild(i),h.push(i);s.setAttribute("gf"===e.ty?"fill":"stroke","url("+getLocationHref()+"#"+o+")"),"gs"===e.ty&&(s.setAttribute("stroke-linecap",lineCapEnum[e.lc||2]),s.setAttribute("stroke-linejoin",lineJoinEnum[e.lj||2]),1===e.lj&&s.setAttribute("stroke-miterlimit",e.ml)),this.of=u,this.ms=a,this.ost=h,this.maskId=l,t.msElem=s}},extendPrototype([DynamicPropertyContainer],SVGGradientFillStyleData),extendPrototype([SVGGradientFillStyleData,DynamicPropertyContainer],SVGGradientStrokeStyleData);var buildShapeString=function(e,t,i,n){if(0===t)return"";var r,a=e.o,s=e.i,o=e.v,l=" M"+n.applyToPointStringified(o[0][0],o[0][1]);for(r=1;r<t;r+=1)l+=" C"+n.applyToPointStringified(a[r-1][0],a[r-1][1])+" "+n.applyToPointStringified(s[r][0],s[r][1])+" "+n.applyToPointStringified(o[r][0],o[r][1]);return i&&t&&(l+=" C"+n.applyToPointStringified(a[r-1][0],a[r-1][1])+" "+n.applyToPointStringified(s[0][0],s[0][1])+" "+n.applyToPointStringified(o[0][0],o[0][1]),l+="z"),l},SVGElementsRenderer=function(){var g=new Matrix,v=new Matrix;function t(e,t,i){(i||t.transform.op._mdf)&&t.transform.container.setAttribute("opacity",t.transform.op.v),(i||t.transform.mProps._mdf)&&t.transform.container.setAttribute("transform",t.transform.mProps.v.to2dCSS())}function i(){}function n(e,t,i){var n,r,a,s,o,l,u,h,p,c,m,f=t.styles.length,d=t.lvl;for(l=0;l<f;l+=1){if(s=t.sh._mdf||i,t.styles[l].lvl<d){for(h=v.reset(),c=d-t.styles[l].lvl,m=t.transformers.length-1;!s&&c>0;)s=t.transformers[m].mProps._mdf||s,c-=1,m-=1;if(s)for(c=d-t.styles[l].lvl,m=t.transformers.length-1;c>0;)p=t.transformers[m].mProps.v.props,h.transform(p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]),c-=1,m-=1}else h=g;if(r=(u=t.sh.paths)._length,s){for(a="",n=0;n<r;n+=1)(o=u.shapes[n])&&o._length&&(a+=buildShapeString(o,o._length,o.c,h));t.caches[l]=a}else a=t.caches[l];t.styles[l].d+=!0===e.hd?"":a,t.styles[l]._mdf=s||t.styles[l]._mdf}}function r(e,t,i){var n=t.style;(t.c._mdf||i)&&n.pElem.setAttribute("fill","rgb("+bmFloor(t.c.v[0])+","+bmFloor(t.c.v[1])+","+bmFloor(t.c.v[2])+")"),(t.o._mdf||i)&&n.pElem.setAttribute("fill-opacity",t.o.v)}function a(e,t,i){s(e,t,i),o(e,t,i)}function s(e,t,i){var n,r,a,s,o,l=t.gf,u=t.g._hasOpacity,h=t.s.v,p=t.e.v;if(t.o._mdf||i){var c="gf"===e.ty?"fill-opacity":"stroke-opacity";t.style.pElem.setAttribute(c,t.o.v)}if(t.s._mdf||i){var m=1===e.t?"x1":"cx",f="x1"===m?"y1":"cy";l.setAttribute(m,h[0]),l.setAttribute(f,h[1]),u&&!t.g._collapsable&&(t.of.setAttribute(m,h[0]),t.of.setAttribute(f,h[1]))}if(t.g._cmdf||i){n=t.cst;var d=t.g.c;for(a=n.length,r=0;r<a;r+=1)(s=n[r]).setAttribute("offset",d[4*r]+"%"),s.setAttribute("stop-color","rgb("+d[4*r+1]+","+d[4*r+2]+","+d[4*r+3]+")")}if(u&&(t.g._omdf||i)){var g=t.g.o;for(a=(n=t.g._collapsable?t.cst:t.ost).length,r=0;r<a;r+=1)s=n[r],t.g._collapsable||s.setAttribute("offset",g[2*r]+"%"),s.setAttribute("stop-opacity",g[2*r+1])}if(1===e.t)(t.e._mdf||i)&&(l.setAttribute("x2",p[0]),l.setAttribute("y2",p[1]),u&&!t.g._collapsable&&(t.of.setAttribute("x2",p[0]),t.of.setAttribute("y2",p[1])));else if((t.s._mdf||t.e._mdf||i)&&(o=Math.sqrt(Math.pow(h[0]-p[0],2)+Math.pow(h[1]-p[1],2)),l.setAttribute("r",o),u&&!t.g._collapsable&&t.of.setAttribute("r",o)),t.e._mdf||t.h._mdf||t.a._mdf||i){o||(o=Math.sqrt(Math.pow(h[0]-p[0],2)+Math.pow(h[1]-p[1],2)));var v=Math.atan2(p[1]-h[1],p[0]-h[0]),y=t.h.v;y>=1?y=.99:y<=-1&&(y=-.99);var b=o*y,x=Math.cos(v+t.a.v)*b+h[0],A=Math.sin(v+t.a.v)*b+h[1];l.setAttribute("fx",x),l.setAttribute("fy",A),u&&!t.g._collapsable&&(t.of.setAttribute("fx",x),t.of.setAttribute("fy",A))}}function o(e,t,i){var n=t.style,r=t.d;r&&(r._mdf||i)&&r.dashStr&&(n.pElem.setAttribute("stroke-dasharray",r.dashStr),n.pElem.setAttribute("stroke-dashoffset",r.dashoffset[0])),t.c&&(t.c._mdf||i)&&n.pElem.setAttribute("stroke","rgb("+bmFloor(t.c.v[0])+","+bmFloor(t.c.v[1])+","+bmFloor(t.c.v[2])+")"),(t.o._mdf||i)&&n.pElem.setAttribute("stroke-opacity",t.o.v),(t.w._mdf||i)&&(n.pElem.setAttribute("stroke-width",t.w.v),n.msElem&&n.msElem.setAttribute("stroke-width",t.w.v))}return{createRenderFunction:function(e){switch(e.ty){case"fl":return r;case"gf":return s;case"gs":return a;case"st":return o;case"sh":case"el":case"rc":case"sr":return n;case"tr":return t;case"no":return i;default:return null}}}}();function SVGShapeElement(e,t,i){this.shapes=[],this.shapesData=e.shapes,this.stylesList=[],this.shapeModifiers=[],this.itemsData=[],this.processedElements=[],this.animatedContents=[],this.initElement(e,t,i),this.prevViewData=[]}function LetterProps(e,t,i,n,r,a){this.o=e,this.sw=t,this.sc=i,this.fc=n,this.m=r,this.p=a,this._mdf={o:!0,sw:!!t,sc:!!i,fc:!!n,m:!0,p:!0}}function TextProperty(e,t){this._frameId=initialDefaultFrame,this.pv="",this.v="",this.kf=!1,this._isFirstFrame=!0,this._mdf=!1,this.data=t,this.elem=e,this.comp=this.elem.comp,this.keysIndex=0,this.canResize=!1,this.minimumFontSize=1,this.effectsSequence=[],this.currentData={ascent:0,boxWidth:this.defaultBoxWidth,f:"",fStyle:"",fWeight:"",fc:"",j:"",justifyOffset:"",l:[],lh:0,lineWidths:[],ls:"",of:"",s:"",sc:"",sw:0,t:0,tr:0,sz:0,ps:null,fillColorAnim:!1,strokeColorAnim:!1,strokeWidthAnim:!1,yOffset:0,finalSize:0,finalText:[],finalLineHeight:0,__complete:!1},this.copyData(this.currentData,this.data.d.k[0].s),this.searchProperty()||this.completeTextData(this.currentData)}extendPrototype([BaseElement,TransformElement,SVGBaseElement,IShapeElement,HierarchyElement,FrameElement,RenderableDOMElement],SVGShapeElement),SVGShapeElement.prototype.initSecondaryElement=function(){},SVGShapeElement.prototype.identityMatrix=new Matrix,SVGShapeElement.prototype.buildExpressionInterface=function(){},SVGShapeElement.prototype.createContent=function(){this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.layerElement,0,[],!0),this.filterUniqueShapes()},SVGShapeElement.prototype.filterUniqueShapes=function(){var e,t,i,n,r=this.shapes.length,a=this.stylesList.length,s=[],o=!1;for(i=0;i<a;i+=1){for(n=this.stylesList[i],o=!1,s.length=0,e=0;e<r;e+=1)-1!==(t=this.shapes[e]).styles.indexOf(n)&&(s.push(t),o=t._isAnimated||o);s.length>1&&o&&this.setShapesAsAnimated(s)}},SVGShapeElement.prototype.setShapesAsAnimated=function(e){var t,i=e.length;for(t=0;t<i;t+=1)e[t].setAsAnimated()},SVGShapeElement.prototype.createStyleElement=function(e,t){var i,n=new SVGStyleData(e,t),r=n.pElem;if("st"===e.ty)i=new SVGStrokeStyleData(this,e,n);else if("fl"===e.ty)i=new SVGFillStyleData(this,e,n);else if("gf"===e.ty||"gs"===e.ty){i=new("gf"===e.ty?SVGGradientFillStyleData:SVGGradientStrokeStyleData)(this,e,n),this.globalData.defs.appendChild(i.gf),i.maskId&&(this.globalData.defs.appendChild(i.ms),this.globalData.defs.appendChild(i.of),r.setAttribute("mask","url("+getLocationHref()+"#"+i.maskId+")"))}else"no"===e.ty&&(i=new SVGNoStyleData(this,e,n));return"st"!==e.ty&&"gs"!==e.ty||(r.setAttribute("stroke-linecap",lineCapEnum[e.lc||2]),r.setAttribute("stroke-linejoin",lineJoinEnum[e.lj||2]),r.setAttribute("fill-opacity","0"),1===e.lj&&r.setAttribute("stroke-miterlimit",e.ml)),2===e.r&&r.setAttribute("fill-rule","evenodd"),e.ln&&r.setAttribute("id",e.ln),e.cl&&r.setAttribute("class",e.cl),e.bm&&(r.style["mix-blend-mode"]=getBlendMode(e.bm)),this.stylesList.push(n),this.addToAnimatedContents(e,i),i},SVGShapeElement.prototype.createGroupElement=function(e){var t=new ShapeGroupData;return e.ln&&t.gr.setAttribute("id",e.ln),e.cl&&t.gr.setAttribute("class",e.cl),e.bm&&(t.gr.style["mix-blend-mode"]=getBlendMode(e.bm)),t},SVGShapeElement.prototype.createTransformElement=function(e,t){var i=TransformPropertyFactory.getTransformProperty(this,e,this),n=new SVGTransformData(i,i.o,t);return this.addToAnimatedContents(e,n),n},SVGShapeElement.prototype.createShapeElement=function(e,t,i){var n=4;"rc"===e.ty?n=5:"el"===e.ty?n=6:"sr"===e.ty&&(n=7);var r=new SVGShapeData(t,i,ShapePropertyFactory.getShapeProp(this,e,n,this));return this.shapes.push(r),this.addShapeToModifiers(r),this.addToAnimatedContents(e,r),r},SVGShapeElement.prototype.addToAnimatedContents=function(e,t){for(var i=0,n=this.animatedContents.length;i<n;){if(this.animatedContents[i].element===t)return;i+=1}this.animatedContents.push({fn:SVGElementsRenderer.createRenderFunction(e),element:t,data:e})},SVGShapeElement.prototype.setElementStyles=function(e){var t,i=e.styles,n=this.stylesList.length;for(t=0;t<n;t+=1)this.stylesList[t].closed||i.push(this.stylesList[t])},SVGShapeElement.prototype.reloadShapes=function(){var e;this._isFirstFrame=!0;var t=this.itemsData.length;for(e=0;e<t;e+=1)this.prevViewData[e]=this.itemsData[e];for(this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.layerElement,0,[],!0),this.filterUniqueShapes(),t=this.dynamicProperties.length,e=0;e<t;e+=1)this.dynamicProperties[e].getValue();this.renderModifiers()},SVGShapeElement.prototype.searchShapes=function(e,t,i,n,r,a,s){var o,l,u,h,p,c,m=[].concat(a),f=e.length-1,d=[],g=[];for(o=f;o>=0;o-=1){if((c=this.searchProcessedElement(e[o]))?t[o]=i[c-1]:e[o]._render=s,"fl"===e[o].ty||"st"===e[o].ty||"gf"===e[o].ty||"gs"===e[o].ty||"no"===e[o].ty)c?t[o].style.closed=!1:t[o]=this.createStyleElement(e[o],r),e[o]._render&&t[o].style.pElem.parentNode!==n&&n.appendChild(t[o].style.pElem),d.push(t[o].style);else if("gr"===e[o].ty){if(c)for(u=t[o].it.length,l=0;l<u;l+=1)t[o].prevViewData[l]=t[o].it[l];else t[o]=this.createGroupElement(e[o]);this.searchShapes(e[o].it,t[o].it,t[o].prevViewData,t[o].gr,r+1,m,s),e[o]._render&&t[o].gr.parentNode!==n&&n.appendChild(t[o].gr)}else"tr"===e[o].ty?(c||(t[o]=this.createTransformElement(e[o],n)),h=t[o].transform,m.push(h)):"sh"===e[o].ty||"rc"===e[o].ty||"el"===e[o].ty||"sr"===e[o].ty?(c||(t[o]=this.createShapeElement(e[o],m,r)),this.setElementStyles(t[o])):"tm"===e[o].ty||"rd"===e[o].ty||"ms"===e[o].ty||"pb"===e[o].ty||"zz"===e[o].ty||"op"===e[o].ty?(c?(p=t[o]).closed=!1:((p=ShapeModifiers.getModifier(e[o].ty)).init(this,e[o]),t[o]=p,this.shapeModifiers.push(p)),g.push(p)):"rp"===e[o].ty&&(c?(p=t[o]).closed=!0:(p=ShapeModifiers.getModifier(e[o].ty),t[o]=p,p.init(this,e,o,t),this.shapeModifiers.push(p),s=!1),g.push(p));this.addProcessedElement(e[o],o+1)}for(f=d.length,o=0;o<f;o+=1)d[o].closed=!0;for(f=g.length,o=0;o<f;o+=1)g[o].closed=!0},SVGShapeElement.prototype.renderInnerContent=function(){var e;this.renderModifiers();var t=this.stylesList.length;for(e=0;e<t;e+=1)this.stylesList[e].reset();for(this.renderShape(),e=0;e<t;e+=1)(this.stylesList[e]._mdf||this._isFirstFrame)&&(this.stylesList[e].msElem&&(this.stylesList[e].msElem.setAttribute("d",this.stylesList[e].d),this.stylesList[e].d="M0 0"+this.stylesList[e].d),this.stylesList[e].pElem.setAttribute("d",this.stylesList[e].d||"M0 0"))},SVGShapeElement.prototype.renderShape=function(){var e,t,i=this.animatedContents.length;for(e=0;e<i;e+=1)t=this.animatedContents[e],(this._isFirstFrame||t.element._isAnimated)&&!0!==t.data&&t.fn(t.data,t.element,this._isFirstFrame)},SVGShapeElement.prototype.destroy=function(){this.destroyBaseElement(),this.shapesData=null,this.itemsData=null},LetterProps.prototype.update=function(e,t,i,n,r,a){this._mdf.o=!1,this._mdf.sw=!1,this._mdf.sc=!1,this._mdf.fc=!1,this._mdf.m=!1,this._mdf.p=!1;var s=!1;return this.o!==e&&(this.o=e,this._mdf.o=!0,s=!0),this.sw!==t&&(this.sw=t,this._mdf.sw=!0,s=!0),this.sc!==i&&(this.sc=i,this._mdf.sc=!0,s=!0),this.fc!==n&&(this.fc=n,this._mdf.fc=!0,s=!0),this.m!==r&&(this.m=r,this._mdf.m=!0,s=!0),!a.length||this.p[0]===a[0]&&this.p[1]===a[1]&&this.p[4]===a[4]&&this.p[5]===a[5]&&this.p[12]===a[12]&&this.p[13]===a[13]||(this.p=a,this._mdf.p=!0,s=!0),s},TextProperty.prototype.defaultBoxWidth=[0,0],TextProperty.prototype.copyData=function(e,t){for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e},TextProperty.prototype.setCurrentData=function(e){e.__complete||this.completeTextData(e),this.currentData=e,this.currentData.boxWidth=this.currentData.boxWidth||this.defaultBoxWidth,this._mdf=!0},TextProperty.prototype.searchProperty=function(){return this.searchKeyframes()},TextProperty.prototype.searchKeyframes=function(){return this.kf=this.data.d.k.length>1,this.kf&&this.addEffect(this.getKeyframeValue.bind(this)),this.kf},TextProperty.prototype.addEffect=function(e){this.effectsSequence.push(e),this.elem.addDynamicProperty(this)},TextProperty.prototype.getValue=function(e){if(this.elem.globalData.frameId!==this.frameId&&this.effectsSequence.length||e){this.currentData.t=this.data.d.k[this.keysIndex].s.t;var t=this.currentData,i=this.keysIndex;if(this.lock)this.setCurrentData(this.currentData);else{var n;this.lock=!0,this._mdf=!1;var r=this.effectsSequence.length,a=e||this.data.d.k[this.keysIndex].s;for(n=0;n<r;n+=1)a=i!==this.keysIndex?this.effectsSequence[n](a,a.t):this.effectsSequence[n](this.currentData,a.t);t!==a&&this.setCurrentData(a),this.v=this.currentData,this.pv=this.v,this.lock=!1,this.frameId=this.elem.globalData.frameId}}},TextProperty.prototype.getKeyframeValue=function(){for(var e=this.data.d.k,t=this.elem.comp.renderedFrame,i=0,n=e.length;i<=n-1&&!(i===n-1||e[i+1].t>t);)i+=1;return this.keysIndex!==i&&(this.keysIndex=i),this.data.d.k[this.keysIndex].s},TextProperty.prototype.buildFinalText=function(e){for(var t,i,n=[],r=0,a=e.length,s=!1;r<a;)t=e.charCodeAt(r),FontManager.isCombinedCharacter(t)?n[n.length-1]+=e.charAt(r):t>=55296&&t<=56319?(i=e.charCodeAt(r+1))>=56320&&i<=57343?(s||FontManager.isModifier(t,i)?(n[n.length-1]+=e.substr(r,2),s=!1):n.push(e.substr(r,2)),r+=1):n.push(e.charAt(r)):t>56319?(i=e.charCodeAt(r+1),FontManager.isZeroWidthJoiner(t,i)?(s=!0,n[n.length-1]+=e.substr(r,2),r+=1):n.push(e.charAt(r))):FontManager.isZeroWidthJoiner(t)?(n[n.length-1]+=e.charAt(r),s=!0):n.push(e.charAt(r)),r+=1;return n},TextProperty.prototype.completeTextData=function(e){e.__complete=!0;var t,i,n,r,a,s,o,l=this.elem.globalData.fontManager,u=this.data,h=[],p=0,c=u.m.g,m=0,f=0,d=0,g=[],v=0,y=0,b=l.getFontByName(e.f),x=0,A=getFontProperties(b);e.fWeight=A.weight,e.fStyle=A.style,e.finalSize=e.s,e.finalText=this.buildFinalText(e.t),i=e.finalText.length,e.finalLineHeight=e.lh;var _,S=e.tr/1e3*e.finalSize;if(e.sz)for(var C,T,I=!0,V=e.sz[0],D=e.sz[1];I;){C=0,v=0,i=(T=this.buildFinalText(e.t)).length,S=e.tr/1e3*e.finalSize;var O=-1;for(t=0;t<i;t+=1)_=T[t].charCodeAt(0),n=!1," "===T[t]?O=t:13!==_&&3!==_||(v=0,n=!0,C+=e.finalLineHeight||1.2*e.finalSize),l.chars?(o=l.getCharData(T[t],b.fStyle,b.fFamily),x=n?0:o.w*e.finalSize/100):x=l.measureText(T[t],e.f,e.finalSize),v+x>V&&" "!==T[t]?(-1===O?i+=1:t=O,C+=e.finalLineHeight||1.2*e.finalSize,T.splice(t,O===t?1:0,"\r"),O=-1,v=0):(v+=x,v+=S);C+=b.ascent*e.finalSize/100,this.canResize&&e.finalSize>this.minimumFontSize&&D<C?(e.finalSize-=1,e.finalLineHeight=e.finalSize*e.lh/e.s):(e.finalText=T,i=e.finalText.length,I=!1)}v=-S,x=0;var E,P=0;for(t=0;t<i;t+=1)if(n=!1,13===(_=(E=e.finalText[t]).charCodeAt(0))||3===_?(P=0,g.push(v),y=v>y?v:y,v=-2*S,r="",n=!0,d+=1):r=E,l.chars?(o=l.getCharData(E,b.fStyle,l.getFontByName(e.f).fFamily),x=n?0:o.w*e.finalSize/100):x=l.measureText(r,e.f,e.finalSize)," "===E?P+=x+S:(v+=x+S+P,P=0),h.push({l:x,an:x,add:m,n:n,anIndexes:[],val:r,line:d,animatorJustifyOffset:0}),2==c){if(m+=x,""===r||" "===r||t===i-1){for(""!==r&&" "!==r||(m-=x);f<=t;)h[f].an=m,h[f].ind=p,h[f].extra=x,f+=1;p+=1,m=0}}else if(3==c){if(m+=x,""===r||t===i-1){for(""===r&&(m-=x);f<=t;)h[f].an=m,h[f].ind=p,h[f].extra=x,f+=1;m=0,p+=1}}else h[p].ind=p,h[p].extra=0,p+=1;if(e.l=h,y=v>y?v:y,g.push(v),e.sz)e.boxWidth=e.sz[0],e.justifyOffset=0;else switch(e.boxWidth=y,e.j){case 1:e.justifyOffset=-e.boxWidth;break;case 2:e.justifyOffset=-e.boxWidth/2;break;default:e.justifyOffset=0}e.lineWidths=g;var M,L,N,k,w=u.a;s=w.length;var R=[];for(a=0;a<s;a+=1){for((M=w[a]).a.sc&&(e.strokeColorAnim=!0),M.a.sw&&(e.strokeWidthAnim=!0),(M.a.fc||M.a.fh||M.a.fs||M.a.fb)&&(e.fillColorAnim=!0),k=0,N=M.s.b,t=0;t<i;t+=1)(L=h[t]).anIndexes[a]=k,(1==N&&""!==L.val||2==N&&""!==L.val&&" "!==L.val||3==N&&(L.n||" "==L.val||t==i-1)||4==N&&(L.n||t==i-1))&&(1===M.s.rn&&R.push(k),k+=1);u.a[a].s.totalChars=k;var B,j=-1;if(1===M.s.rn)for(t=0;t<i;t+=1)j!=(L=h[t]).anIndexes[a]&&(j=L.anIndexes[a],B=R.splice(Math.floor(Math.random()*R.length),1)[0]),L.anIndexes[a]=B}e.yOffset=e.finalLineHeight||1.2*e.finalSize,e.ls=e.ls||0,e.ascent=b.ascent*e.finalSize/100},TextProperty.prototype.updateDocumentData=function(e,t){t=void 0===t?this.keysIndex:t;var i=this.copyData({},this.data.d.k[t].s);i=this.copyData(i,e),this.data.d.k[t].s=i,this.recalculate(t),this.elem.addDynamicProperty(this)},TextProperty.prototype.recalculate=function(e){var t=this.data.d.k[e].s;t.__complete=!1,this.keysIndex=0,this._isFirstFrame=!0,this.getValue(t)},TextProperty.prototype.canResizeFont=function(e){this.canResize=e,this.recalculate(this.keysIndex),this.elem.addDynamicProperty(this)},TextProperty.prototype.setMinimumFontSize=function(e){this.minimumFontSize=Math.floor(e)||1,this.recalculate(this.keysIndex),this.elem.addDynamicProperty(this)};var TextSelectorProp=function(){var d=Math.max,g=Math.min,v=Math.floor;function n(e,t){this._currentTextLength=-1,this.k=!1,this.data=t,this.elem=e,this.comp=e.comp,this.finalS=0,this.finalE=0,this.initDynamicPropertyContainer(e),this.s=PropertyFactory.getProp(e,t.s||{k:0},0,0,this),this.e="e"in t?PropertyFactory.getProp(e,t.e,0,0,this):{v:100},this.o=PropertyFactory.getProp(e,t.o||{k:0},0,0,this),this.xe=PropertyFactory.getProp(e,t.xe||{k:0},0,0,this),this.ne=PropertyFactory.getProp(e,t.ne||{k:0},0,0,this),this.sm=PropertyFactory.getProp(e,t.sm||{k:100},0,0,this),this.a=PropertyFactory.getProp(e,t.a,0,.01,this),this.dynamicProperties.length||this.getValue()}return n.prototype={getMult:function(e){this._currentTextLength!==this.elem.textProperty.currentData.l.length&&this.getValue();var t=0,i=0,n=1,r=1;this.ne.v>0?t=this.ne.v/100:i=-this.ne.v/100,this.xe.v>0?n=1-this.xe.v/100:r=1+this.xe.v/100;var a=BezierFactory.getBezierEasing(t,i,n,r).get,s=0,o=this.finalS,l=this.finalE,u=this.data.sh;if(2===u)s=a(s=l===o?e>=l?1:0:d(0,g(.5/(l-o)+(e-o)/(l-o),1)));else if(3===u)s=a(s=l===o?e>=l?0:1:1-d(0,g(.5/(l-o)+(e-o)/(l-o),1)));else if(4===u)l===o?s=0:(s=d(0,g(.5/(l-o)+(e-o)/(l-o),1)))<.5?s*=2:s=1-2*(s-.5),s=a(s);else if(5===u){if(l===o)s=0;else{var h=l-o,p=-h/2+(e=g(d(0,e+.5-o),l-o)),c=h/2;s=Math.sqrt(1-p*p/(c*c))}s=a(s)}else 6===u?(l===o?s=0:(e=g(d(0,e+.5-o),l-o),s=(1+Math.cos(Math.PI+2*Math.PI*e/(l-o)))/2),s=a(s)):(e>=v(o)&&(s=d(0,g(e-o<0?g(l,1)-(o-e):l-e,1))),s=a(s));if(100!==this.sm.v){var m=.01*this.sm.v;0===m&&(m=1e-8);var f=.5-.5*m;s<f?s=0:(s=(s-f)/m)>1&&(s=1)}return s*this.a.v},getValue:function(e){this.iterateDynamicProperties(),this._mdf=e||this._mdf,this._currentTextLength=this.elem.textProperty.currentData.l.length||0,e&&2===this.data.r&&(this.e.v=this._currentTextLength);var t=2===this.data.r?1:100/this.data.totalChars,i=this.o.v/t,n=this.s.v/t+i,r=this.e.v/t+i;if(n>r){var a=n;n=r,r=a}this.finalS=n,this.finalE=r}},extendPrototype([DynamicPropertyContainer],n),{getTextSelectorProp:function(e,t,i){return new n(e,t,i)}}}();function TextAnimatorDataProperty(e,t,i){var n={propType:!1},r=PropertyFactory.getProp,a=t.a;this.a={r:a.r?r(e,a.r,0,degToRads,i):n,rx:a.rx?r(e,a.rx,0,degToRads,i):n,ry:a.ry?r(e,a.ry,0,degToRads,i):n,sk:a.sk?r(e,a.sk,0,degToRads,i):n,sa:a.sa?r(e,a.sa,0,degToRads,i):n,s:a.s?r(e,a.s,1,.01,i):n,a:a.a?r(e,a.a,1,0,i):n,o:a.o?r(e,a.o,0,.01,i):n,p:a.p?r(e,a.p,1,0,i):n,sw:a.sw?r(e,a.sw,0,0,i):n,sc:a.sc?r(e,a.sc,1,0,i):n,fc:a.fc?r(e,a.fc,1,0,i):n,fh:a.fh?r(e,a.fh,0,0,i):n,fs:a.fs?r(e,a.fs,0,.01,i):n,fb:a.fb?r(e,a.fb,0,.01,i):n,t:a.t?r(e,a.t,0,0,i):n},this.s=TextSelectorProp.getTextSelectorProp(e,t.s,i),this.s.t=t.s.t}function TextAnimatorProperty(e,t,i){this._isFirstFrame=!0,this._hasMaskedPath=!1,this._frameId=-1,this._textData=e,this._renderType=t,this._elem=i,this._animatorsData=createSizedArray(this._textData.a.length),this._pathData={},this._moreOptions={alignment:{}},this.renderedLetters=[],this.lettersChangedFlag=!1,this.initDynamicPropertyContainer(i)}function ITextElement(){}TextAnimatorProperty.prototype.searchProperties=function(){var e,t,i=this._textData.a.length,n=PropertyFactory.getProp;for(e=0;e<i;e+=1)t=this._textData.a[e],this._animatorsData[e]=new TextAnimatorDataProperty(this._elem,t,this);this._textData.p&&"m"in this._textData.p?(this._pathData={a:n(this._elem,this._textData.p.a,0,0,this),f:n(this._elem,this._textData.p.f,0,0,this),l:n(this._elem,this._textData.p.l,0,0,this),r:n(this._elem,this._textData.p.r,0,0,this),p:n(this._elem,this._textData.p.p,0,0,this),m:this._elem.maskManager.getMaskProperty(this._textData.p.m)},this._hasMaskedPath=!0):this._hasMaskedPath=!1,this._moreOptions.alignment=n(this._elem,this._textData.m.a,1,0,this)},TextAnimatorProperty.prototype.getMeasures=function(e,V){if(this.lettersChangedFlag=V,this._mdf||this._isFirstFrame||V||this._hasMaskedPath&&this._pathData.m._mdf){this._isFirstFrame=!1;var t,i,n,r,a,s,o,l,D,u,h,p,c,m,B,f,j,F,d,g=this._moreOptions.alignment.v,v=this._animatorsData,y=this._textData,b=this.mHelper,U=this._renderType,G=this.renderedLetters.length,x=e.l;if(this._hasMaskedPath){if(d=this._pathData.m,!this._pathData.n||this._pathData._mdf){var A,_=d.v;for(this._pathData.r.v&&(_=_.reverse()),a={tLength:0,segments:[]},r=_._length-1,f=0,n=0;n<r;n+=1)A=bez.buildBezierData(_.v[n],_.v[n+1],[_.o[n][0]-_.v[n][0],_.o[n][1]-_.v[n][1]],[_.i[n+1][0]-_.v[n+1][0],_.i[n+1][1]-_.v[n+1][1]]),a.tLength+=A.segmentLength,a.segments.push(A),f+=A.segmentLength;n=r,d.v.c&&(A=bez.buildBezierData(_.v[n],_.v[0],[_.o[n][0]-_.v[n][0],_.o[n][1]-_.v[n][1]],[_.i[0][0]-_.v[0][0],_.i[0][1]-_.v[0][1]]),a.tLength+=A.segmentLength,a.segments.push(A),f+=A.segmentLength),this._pathData.pi=a}if(a=this._pathData.pi,s=this._pathData.f.v,h=0,u=1,l=0,D=!0,m=a.segments,s<0&&d.v.c)for(a.tLength<Math.abs(s)&&(s=-Math.abs(s)%a.tLength),u=(c=m[h=m.length-1].points).length-1;s<0;)s+=c[u].partialLength,(u-=1)<0&&(u=(c=m[h-=1].points).length-1);p=(c=m[h].points)[u-1],B=(o=c[u]).partialLength}r=x.length,t=0,i=0;var S,C,T,z,I,q=1.2*e.finalSize*.714,X=!0;T=v.length;var O,H,Y,E,P,W,M,L,K,Z,Q,J,N=-1,$=s,ee=h,te=u,ie=-1,ne="",re=this.defaultPropsArray;if(2===e.j||1===e.j){var k=0,ae=0,se=2===e.j?-.5:-1,w=0,oe=!0;for(n=0;n<r;n+=1)if(x[n].n){for(k&&(k+=ae);w<n;)x[w].animatorJustifyOffset=k,w+=1;k=0,oe=!0}else{for(C=0;C<T;C+=1)(S=v[C].a).t.propType&&(oe&&2===e.j&&(ae+=S.t.v*se),(I=v[C].s.getMult(x[n].anIndexes[C],y.a[C].s.totalChars)).length?k+=S.t.v*I[0]*se:k+=S.t.v*I*se);oe=!1}for(k&&(k+=ae);w<n;)x[w].animatorJustifyOffset=k,w+=1}for(n=0;n<r;n+=1){if(b.reset(),E=1,x[n].n)t=0,i+=e.yOffset,i+=X?1:0,s=$,X=!1,this._hasMaskedPath&&(u=te,p=(c=m[h=ee].points)[u-1],B=(o=c[u]).partialLength,l=0),ne="",Q="",K="",J="",re=this.defaultPropsArray;else{if(this._hasMaskedPath){if(ie!==x[n].line){switch(e.j){case 1:s+=f-e.lineWidths[x[n].line];break;case 2:s+=(f-e.lineWidths[x[n].line])/2}ie=x[n].line}N!==x[n].ind&&(x[N]&&(s+=x[N].extra),s+=x[n].an/2,N=x[n].ind),s+=g[0]*x[n].an*.005;var R=0;for(C=0;C<T;C+=1)(S=v[C].a).p.propType&&((I=v[C].s.getMult(x[n].anIndexes[C],y.a[C].s.totalChars)).length?R+=S.p.v[0]*I[0]:R+=S.p.v[0]*I),S.a.propType&&((I=v[C].s.getMult(x[n].anIndexes[C],y.a[C].s.totalChars)).length?R+=S.a.v[0]*I[0]:R+=S.a.v[0]*I);for(D=!0,this._pathData.a.v&&(s=.5*x[0].an+(f-this._pathData.f.v-.5*x[0].an-.5*x[x.length-1].an)*N/(r-1),s+=this._pathData.f.v);D;)l+B>=s+R||!c?(j=(s+R-l)/o.partialLength,H=p.point[0]+(o.point[0]-p.point[0])*j,Y=p.point[1]+(o.point[1]-p.point[1])*j,b.translate(-g[0]*x[n].an*.005,-g[1]*q*.01),D=!1):c&&(l+=o.partialLength,(u+=1)>=c.length&&(u=0,m[h+=1]?c=m[h].points:d.v.c?(u=0,c=m[h=0].points):(l-=o.partialLength,c=null)),c&&(p=o,B=(o=c[u]).partialLength));O=x[n].an/2-x[n].add,b.translate(-O,0,0)}else O=x[n].an/2-x[n].add,b.translate(-O,0,0),b.translate(-g[0]*x[n].an*.005,-g[1]*q*.01,0);for(C=0;C<T;C+=1)(S=v[C].a).t.propType&&(I=v[C].s.getMult(x[n].anIndexes[C],y.a[C].s.totalChars),0===t&&0===e.j||(this._hasMaskedPath?I.length?s+=S.t.v*I[0]:s+=S.t.v*I:I.length?t+=S.t.v*I[0]:t+=S.t.v*I));for(e.strokeWidthAnim&&(W=e.sw||0),e.strokeColorAnim&&(P=e.sc?[e.sc[0],e.sc[1],e.sc[2]]:[0,0,0]),e.fillColorAnim&&e.fc&&(M=[e.fc[0],e.fc[1],e.fc[2]]),C=0;C<T;C+=1)(S=v[C].a).a.propType&&((I=v[C].s.getMult(x[n].anIndexes[C],y.a[C].s.totalChars)).length?b.translate(-S.a.v[0]*I[0],-S.a.v[1]*I[1],S.a.v[2]*I[2]):b.translate(-S.a.v[0]*I,-S.a.v[1]*I,S.a.v[2]*I));for(C=0;C<T;C+=1)(S=v[C].a).s.propType&&((I=v[C].s.getMult(x[n].anIndexes[C],y.a[C].s.totalChars)).length?b.scale(1+(S.s.v[0]-1)*I[0],1+(S.s.v[1]-1)*I[1],1):b.scale(1+(S.s.v[0]-1)*I,1+(S.s.v[1]-1)*I,1));for(C=0;C<T;C+=1){if(S=v[C].a,I=v[C].s.getMult(x[n].anIndexes[C],y.a[C].s.totalChars),S.sk.propType&&(I.length?b.skewFromAxis(-S.sk.v*I[0],S.sa.v*I[1]):b.skewFromAxis(-S.sk.v*I,S.sa.v*I)),S.r.propType&&(I.length?b.rotateZ(-S.r.v*I[2]):b.rotateZ(-S.r.v*I)),S.ry.propType&&(I.length?b.rotateY(S.ry.v*I[1]):b.rotateY(S.ry.v*I)),S.rx.propType&&(I.length?b.rotateX(S.rx.v*I[0]):b.rotateX(S.rx.v*I)),S.o.propType&&(I.length?E+=(S.o.v*I[0]-E)*I[0]:E+=(S.o.v*I-E)*I),e.strokeWidthAnim&&S.sw.propType&&(I.length?W+=S.sw.v*I[0]:W+=S.sw.v*I),e.strokeColorAnim&&S.sc.propType)for(L=0;L<3;L+=1)I.length?P[L]+=(S.sc.v[L]-P[L])*I[0]:P[L]+=(S.sc.v[L]-P[L])*I;if(e.fillColorAnim&&e.fc){if(S.fc.propType)for(L=0;L<3;L+=1)I.length?M[L]+=(S.fc.v[L]-M[L])*I[0]:M[L]+=(S.fc.v[L]-M[L])*I;S.fh.propType&&(M=I.length?addHueToRGB(M,S.fh.v*I[0]):addHueToRGB(M,S.fh.v*I)),S.fs.propType&&(M=I.length?addSaturationToRGB(M,S.fs.v*I[0]):addSaturationToRGB(M,S.fs.v*I)),S.fb.propType&&(M=I.length?addBrightnessToRGB(M,S.fb.v*I[0]):addBrightnessToRGB(M,S.fb.v*I))}}for(C=0;C<T;C+=1)(S=v[C].a).p.propType&&(I=v[C].s.getMult(x[n].anIndexes[C],y.a[C].s.totalChars),this._hasMaskedPath?I.length?b.translate(0,S.p.v[1]*I[0],-S.p.v[2]*I[1]):b.translate(0,S.p.v[1]*I,-S.p.v[2]*I):I.length?b.translate(S.p.v[0]*I[0],S.p.v[1]*I[1],-S.p.v[2]*I[2]):b.translate(S.p.v[0]*I,S.p.v[1]*I,-S.p.v[2]*I));if(e.strokeWidthAnim&&(K=W<0?0:W),e.strokeColorAnim&&(Z="rgb("+Math.round(255*P[0])+","+Math.round(255*P[1])+","+Math.round(255*P[2])+")"),e.fillColorAnim&&e.fc&&(Q="rgb("+Math.round(255*M[0])+","+Math.round(255*M[1])+","+Math.round(255*M[2])+")"),this._hasMaskedPath){if(b.translate(0,-e.ls),b.translate(0,g[1]*q*.01+i,0),this._pathData.p.v){F=(o.point[1]-p.point[1])/(o.point[0]-p.point[0]);var le=180*Math.atan(F)/Math.PI;o.point[0]<p.point[0]&&(le+=180),b.rotate(-le*Math.PI/180)}b.translate(H,Y,0),s-=g[0]*x[n].an*.005,x[n+1]&&N!==x[n+1].ind&&(s+=x[n].an/2,s+=.001*e.tr*e.finalSize)}else{switch(b.translate(t,i,0),e.ps&&b.translate(e.ps[0],e.ps[1]+e.ascent,0),e.j){case 1:b.translate(x[n].animatorJustifyOffset+e.justifyOffset+(e.boxWidth-e.lineWidths[x[n].line]),0,0);break;case 2:b.translate(x[n].animatorJustifyOffset+e.justifyOffset+(e.boxWidth-e.lineWidths[x[n].line])/2,0,0)}b.translate(0,-e.ls),b.translate(O,0,0),b.translate(g[0]*x[n].an*.005,g[1]*q*.01,0),t+=x[n].l+.001*e.tr*e.finalSize}"html"===U?ne=b.toCSS():"svg"===U?ne=b.to2dCSS():re=[b.props[0],b.props[1],b.props[2],b.props[3],b.props[4],b.props[5],b.props[6],b.props[7],b.props[8],b.props[9],b.props[10],b.props[11],b.props[12],b.props[13],b.props[14],b.props[15]],J=E}G<=n?(z=new LetterProps(J,K,Z,Q,ne,re),this.renderedLetters.push(z),G+=1,this.lettersChangedFlag=!0):(z=this.renderedLetters[n],this.lettersChangedFlag=z.update(J,K,Z,Q,ne,re)||this.lettersChangedFlag)}}},TextAnimatorProperty.prototype.getValue=function(){this._elem.globalData.frameId!==this._frameId&&(this._frameId=this._elem.globalData.frameId,this.iterateDynamicProperties())},TextAnimatorProperty.prototype.mHelper=new Matrix,TextAnimatorProperty.prototype.defaultPropsArray=[],extendPrototype([DynamicPropertyContainer],TextAnimatorProperty),ITextElement.prototype.initElement=function(e,t,i){this.lettersChangedFlag=!0,this.initFrame(),this.initBaseData(e,t,i),this.textProperty=new TextProperty(this,e.t,this.dynamicProperties),this.textAnimator=new TextAnimatorProperty(e.t,this.renderType,this),this.initTransform(e,t,i),this.initHierarchy(),this.initRenderable(),this.initRendererElement(),this.createContainerElements(),this.createRenderableComponents(),this.createContent(),this.hide(),this.textAnimator.searchProperties(this.dynamicProperties)},ITextElement.prototype.prepareFrame=function(e){this._mdf=!1,this.prepareRenderableFrame(e),this.prepareProperties(e,this.isInRange),(this.textProperty._mdf||this.textProperty._isFirstFrame)&&(this.buildNewText(),this.textProperty._isFirstFrame=!1,this.textProperty._mdf=!1)},ITextElement.prototype.createPathShape=function(e,t){var i,n,r=t.length,a="";for(i=0;i<r;i+=1)"sh"===t[i].ty&&(n=t[i].ks.k,a+=buildShapeString(n,n.i.length,!0,e));return a},ITextElement.prototype.updateDocumentData=function(e,t){this.textProperty.updateDocumentData(e,t)},ITextElement.prototype.canResizeFont=function(e){this.textProperty.canResizeFont(e)},ITextElement.prototype.setMinimumFontSize=function(e){this.textProperty.setMinimumFontSize(e)},ITextElement.prototype.applyTextPropertiesToMatrix=function(e,t,i,n,r){switch(e.ps&&t.translate(e.ps[0],e.ps[1]+e.ascent,0),t.translate(0,-e.ls,0),e.j){case 1:t.translate(e.justifyOffset+(e.boxWidth-e.lineWidths[i]),0,0);break;case 2:t.translate(e.justifyOffset+(e.boxWidth-e.lineWidths[i])/2,0,0)}t.translate(n,r,0)},ITextElement.prototype.buildColor=function(e){return"rgb("+Math.round(255*e[0])+","+Math.round(255*e[1])+","+Math.round(255*e[2])+")"},ITextElement.prototype.emptyProp=new LetterProps,ITextElement.prototype.destroy=function(){};var emptyShapeData={shapes:[]};function SVGTextLottieElement(e,t,i){this.textSpans=[],this.renderType="svg",this.initElement(e,t,i)}function ISolidElement(e,t,i){this.initElement(e,t,i)}function NullElement(e,t,i){this.initFrame(),this.initBaseData(e,t,i),this.initFrame(),this.initTransform(e,t,i),this.initHierarchy()}function SVGRendererBase(){}function ICompElement(){}function SVGCompElement(e,t,i){this.layers=e.layers,this.supports3d=!0,this.completeLayers=!1,this.pendingElements=[],this.elements=this.layers?createSizedArray(this.layers.length):[],this.initElement(e,t,i),this.tm=e.tm?PropertyFactory.getProp(this,e.tm,0,t.frameRate,this):{_placeholder:!0}}function SVGRenderer(e,t){this.animationItem=e,this.layers=null,this.renderedFrame=-1,this.svgElement=createNS("svg");var i="";if(t&&t.title){var n=createNS("title"),r=createElementID();n.setAttribute("id",r),n.textContent=t.title,this.svgElement.appendChild(n),i+=r}if(t&&t.description){var a=createNS("desc"),s=createElementID();a.setAttribute("id",s),a.textContent=t.description,this.svgElement.appendChild(a),i+=" "+s}i&&this.svgElement.setAttribute("aria-labelledby",i);var o=createNS("defs");this.svgElement.appendChild(o);var l=createNS("g");this.svgElement.appendChild(l),this.layerElement=l,this.renderConfig={preserveAspectRatio:t&&t.preserveAspectRatio||"xMidYMid meet",imagePreserveAspectRatio:t&&t.imagePreserveAspectRatio||"xMidYMid slice",contentVisibility:t&&t.contentVisibility||"visible",progressiveLoad:t&&t.progressiveLoad||!1,hideOnTransparent:!(t&&!1===t.hideOnTransparent),viewBoxOnly:t&&t.viewBoxOnly||!1,viewBoxSize:t&&t.viewBoxSize||!1,className:t&&t.className||"",id:t&&t.id||"",focusable:t&&t.focusable,filterSize:{width:t&&t.filterSize&&t.filterSize.width||"100%",height:t&&t.filterSize&&t.filterSize.height||"100%",x:t&&t.filterSize&&t.filterSize.x||"0%",y:t&&t.filterSize&&t.filterSize.y||"0%"},width:t&&t.width,height:t&&t.height,runExpressions:!t||void 0===t.runExpressions||t.runExpressions},this.globalData={_mdf:!1,frameNum:-1,defs:o,renderConfig:this.renderConfig},this.elements=[],this.pendingElements=[],this.destroyed=!1,this.rendererType="svg"}function CVContextData(){var e;this.saved=[],this.cArrPos=0,this.cTr=new Matrix,this.cO=1;for(this.savedOp=createTypedArray("float32",15),e=0;e<15;e+=1)this.saved[e]=createTypedArray("float32",16);this._length=15}function ShapeTransformManager(){this.sequences={},this.sequenceList=[],this.transform_key_count=0}extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement,ITextElement],SVGTextLottieElement),SVGTextLottieElement.prototype.createContent=function(){this.data.singleShape&&!this.globalData.fontManager.chars&&(this.textContainer=createNS("text"))},SVGTextLottieElement.prototype.buildTextContents=function(e){for(var t=0,i=e.length,n=[],r="";t<i;)e[t]===String.fromCharCode(13)||e[t]===String.fromCharCode(3)?(n.push(r),r=""):r+=e[t],t+=1;return n.push(r),n},SVGTextLottieElement.prototype.buildShapeData=function(e,t){if(e.shapes&&e.shapes.length){var i=e.shapes[0];if(i.it){var n=i.it[i.it.length-1];n.s&&(n.s.k[0]=t,n.s.k[1]=t)}}return e},SVGTextLottieElement.prototype.buildNewText=function(){var e,t;this.addDynamicProperty(this);var i=this.textProperty.currentData;this.renderedLetters=createSizedArray(i?i.l.length:0),i.fc?this.layerElement.setAttribute("fill",this.buildColor(i.fc)):this.layerElement.setAttribute("fill","rgba(0,0,0,0)"),i.sc&&(this.layerElement.setAttribute("stroke",this.buildColor(i.sc)),this.layerElement.setAttribute("stroke-width",i.sw)),this.layerElement.setAttribute("font-size",i.finalSize);var n=this.globalData.fontManager.getFontByName(i.f);if(n.fClass)this.layerElement.setAttribute("class",n.fClass);else{this.layerElement.setAttribute("font-family",n.fFamily);var r=i.fWeight,a=i.fStyle;this.layerElement.setAttribute("font-style",a),this.layerElement.setAttribute("font-weight",r)}this.layerElement.setAttribute("aria-label",i.t);var s,o=i.l||[],l=!!this.globalData.fontManager.chars;t=o.length;var u=this.mHelper,h=this.data.singleShape,p=0,c=0,m=!0,f=.001*i.tr*i.finalSize;if(!h||l||i.sz){var d,g=this.textSpans.length;for(e=0;e<t;e+=1){if(this.textSpans[e]||(this.textSpans[e]={span:null,childSpan:null,glyph:null}),!l||!h||0===e){if(s=g>e?this.textSpans[e].span:createNS(l?"g":"text"),g<=e){if(s.setAttribute("stroke-linecap","butt"),s.setAttribute("stroke-linejoin","round"),s.setAttribute("stroke-miterlimit","4"),this.textSpans[e].span=s,l){var v=createNS("g");s.appendChild(v),this.textSpans[e].childSpan=v}this.textSpans[e].span=s,this.layerElement.appendChild(s)}s.style.display="inherit"}if(u.reset(),h&&(o[e].n&&(p=-f,c+=i.yOffset,c+=m?1:0,m=!1),this.applyTextPropertiesToMatrix(i,u,o[e].line,p,c),p+=o[e].l||0,p+=f),l){var y;if(1===(d=this.globalData.fontManager.getCharData(i.finalText[e],n.fStyle,this.globalData.fontManager.getFontByName(i.f).fFamily)).t)y=new SVGCompElement(d.data,this.globalData,this);else{var b=emptyShapeData;d.data&&d.data.shapes&&(b=this.buildShapeData(d.data,i.finalSize)),y=new SVGShapeElement(b,this.globalData,this)}if(this.textSpans[e].glyph){var x=this.textSpans[e].glyph;this.textSpans[e].childSpan.removeChild(x.layerElement),x.destroy()}this.textSpans[e].glyph=y,y._debug=!0,y.prepareFrame(0),y.renderFrame(),this.textSpans[e].childSpan.appendChild(y.layerElement),1===d.t&&this.textSpans[e].childSpan.setAttribute("transform","scale("+i.finalSize/100+","+i.finalSize/100+")")}else h&&s.setAttribute("transform","translate("+u.props[12]+","+u.props[13]+")"),s.textContent=o[e].val,s.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve")}h&&s&&s.setAttribute("d","")}else{var A=this.textContainer,_="start";switch(i.j){case 1:_="end";break;case 2:_="middle";break;default:_="start"}A.setAttribute("text-anchor",_),A.setAttribute("letter-spacing",f);var S=this.buildTextContents(i.finalText);for(t=S.length,c=i.ps?i.ps[1]+i.ascent:0,e=0;e<t;e+=1)(s=this.textSpans[e].span||createNS("tspan")).textContent=S[e],s.setAttribute("x",0),s.setAttribute("y",c),s.style.display="inherit",A.appendChild(s),this.textSpans[e]||(this.textSpans[e]={span:null,glyph:null}),this.textSpans[e].span=s,c+=i.finalLineHeight;this.layerElement.appendChild(A)}for(;e<this.textSpans.length;)this.textSpans[e].span.style.display="none",e+=1;this._sizeChanged=!0},SVGTextLottieElement.prototype.sourceRectAtTime=function(){if(this.prepareFrame(this.comp.renderedFrame-this.data.st),this.renderInnerContent(),this._sizeChanged){this._sizeChanged=!1;var e=this.layerElement.getBBox();this.bbox={top:e.y,left:e.x,width:e.width,height:e.height}}return this.bbox},SVGTextLottieElement.prototype.getValue=function(){var e,t,i=this.textSpans.length;for(this.renderedFrame=this.comp.renderedFrame,e=0;e<i;e+=1)(t=this.textSpans[e].glyph)&&(t.prepareFrame(this.comp.renderedFrame-this.data.st),t._mdf&&(this._mdf=!0))},SVGTextLottieElement.prototype.renderInnerContent=function(){if((!this.data.singleShape||this._mdf)&&(this.textAnimator.getMeasures(this.textProperty.currentData,this.lettersChangedFlag),this.lettersChangedFlag||this.textAnimator.lettersChangedFlag)){var e,t;this._sizeChanged=!0;var i,n,r,a=this.textAnimator.renderedLetters,s=this.textProperty.currentData.l;for(t=s.length,e=0;e<t;e+=1)s[e].n||(i=a[e],n=this.textSpans[e].span,(r=this.textSpans[e].glyph)&&r.renderFrame(),i._mdf.m&&n.setAttribute("transform",i.m),i._mdf.o&&n.setAttribute("opacity",i.o),i._mdf.sw&&n.setAttribute("stroke-width",i.sw),i._mdf.sc&&n.setAttribute("stroke",i.sc),i._mdf.fc&&n.setAttribute("fill",i.fc))}},extendPrototype([IImageElement],ISolidElement),ISolidElement.prototype.createContent=function(){var e=createNS("rect");e.setAttribute("width",this.data.sw),e.setAttribute("height",this.data.sh),e.setAttribute("fill",this.data.sc),this.layerElement.appendChild(e)},NullElement.prototype.prepareFrame=function(e){this.prepareProperties(e,!0)},NullElement.prototype.renderFrame=function(){},NullElement.prototype.getBaseElement=function(){return null},NullElement.prototype.destroy=function(){},NullElement.prototype.sourceRectAtTime=function(){},NullElement.prototype.hide=function(){},extendPrototype([BaseElement,TransformElement,HierarchyElement,FrameElement],NullElement),extendPrototype([BaseRenderer],SVGRendererBase),SVGRendererBase.prototype.createNull=function(e){return new NullElement(e,this.globalData,this)},SVGRendererBase.prototype.createShape=function(e){return new SVGShapeElement(e,this.globalData,this)},SVGRendererBase.prototype.createText=function(e){return new SVGTextLottieElement(e,this.globalData,this)},SVGRendererBase.prototype.createImage=function(e){return new IImageElement(e,this.globalData,this)},SVGRendererBase.prototype.createSolid=function(e){return new ISolidElement(e,this.globalData,this)},SVGRendererBase.prototype.configAnimation=function(e){this.svgElement.setAttribute("xmlns","http://www.w3.org/2000/svg"),this.svgElement.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink"),this.renderConfig.viewBoxSize?this.svgElement.setAttribute("viewBox",this.renderConfig.viewBoxSize):this.svgElement.setAttribute("viewBox","0 0 "+e.w+" "+e.h),this.renderConfig.viewBoxOnly||(this.svgElement.setAttribute("width",e.w),this.svgElement.setAttribute("height",e.h),this.svgElement.style.width="100%",this.svgElement.style.height="100%",this.svgElement.style.transform="translate3d(0,0,0)",this.svgElement.style.contentVisibility=this.renderConfig.contentVisibility),this.renderConfig.width&&this.svgElement.setAttribute("width",this.renderConfig.width),this.renderConfig.height&&this.svgElement.setAttribute("height",this.renderConfig.height),this.renderConfig.className&&this.svgElement.setAttribute("class",this.renderConfig.className),this.renderConfig.id&&this.svgElement.setAttribute("id",this.renderConfig.id),void 0!==this.renderConfig.focusable&&this.svgElement.setAttribute("focusable",this.renderConfig.focusable),this.svgElement.setAttribute("preserveAspectRatio",this.renderConfig.preserveAspectRatio),this.animationItem.wrapper.appendChild(this.svgElement);var t=this.globalData.defs;this.setupGlobalData(e,t),this.globalData.progressiveLoad=this.renderConfig.progressiveLoad,this.data=e;var i=createNS("clipPath"),n=createNS("rect");n.setAttribute("width",e.w),n.setAttribute("height",e.h),n.setAttribute("x",0),n.setAttribute("y",0);var r=createElementID();i.setAttribute("id",r),i.appendChild(n),this.layerElement.setAttribute("clip-path","url("+getLocationHref()+"#"+r+")"),t.appendChild(i),this.layers=e.layers,this.elements=createSizedArray(e.layers.length)},SVGRendererBase.prototype.destroy=function(){var e;this.animationItem.wrapper&&(this.animationItem.wrapper.innerText=""),this.layerElement=null,this.globalData.defs=null;var t=this.layers?this.layers.length:0;for(e=0;e<t;e+=1)this.elements[e]&&this.elements[e].destroy();this.elements.length=0,this.destroyed=!0,this.animationItem=null},SVGRendererBase.prototype.updateContainerSize=function(){},SVGRendererBase.prototype.findIndexByInd=function(e){var t=0,i=this.layers.length;for(t=0;t<i;t+=1)if(this.layers[t].ind===e)return t;return-1},SVGRendererBase.prototype.buildItem=function(e){var t=this.elements;if(!t[e]&&99!==this.layers[e].ty){t[e]=!0;var i=this.createItem(this.layers[e]);if(t[e]=i,getExpressionsPlugin()&&(0===this.layers[e].ty&&this.globalData.projectInterface.registerComposition(i),i.initExpressions()),this.appendElementInPos(i,e),this.layers[e].tt){var n="tp"in this.layers[e]?this.findIndexByInd(this.layers[e].tp):e-1;if(-1===n)return;if(this.elements[n]&&!0!==this.elements[n]){var r=t[n].getMatte(this.layers[e].tt);i.setMatte(r)}else this.buildItem(n),this.addPendingElement(i)}}},SVGRendererBase.prototype.checkPendingElements=function(){for(;this.pendingElements.length;){var e=this.pendingElements.pop();if(e.checkParenting(),e.data.tt)for(var t=0,i=this.elements.length;t<i;){if(this.elements[t]===e){var n="tp"in e.data?this.findIndexByInd(e.data.tp):t-1,r=this.elements[n].getMatte(this.layers[t].tt);e.setMatte(r);break}t+=1}}},SVGRendererBase.prototype.renderFrame=function(e){if(this.renderedFrame!==e&&!this.destroyed){var t;null===e?e=this.renderedFrame:this.renderedFrame=e,this.globalData.frameNum=e,this.globalData.frameId+=1,this.globalData.projectInterface.currentFrame=e,this.globalData._mdf=!1;var i=this.layers.length;for(this.completeLayers||this.checkLayers(e),t=i-1;t>=0;t-=1)(this.completeLayers||this.elements[t])&&this.elements[t].prepareFrame(e-this.layers[t].st);if(this.globalData._mdf)for(t=0;t<i;t+=1)(this.completeLayers||this.elements[t])&&this.elements[t].renderFrame()}},SVGRendererBase.prototype.appendElementInPos=function(e,t){var i=e.getBaseElement();if(i){for(var n,r=0;r<t;)this.elements[r]&&!0!==this.elements[r]&&this.elements[r].getBaseElement()&&(n=this.elements[r].getBaseElement()),r+=1;n?this.layerElement.insertBefore(i,n):this.layerElement.appendChild(i)}},SVGRendererBase.prototype.hide=function(){this.layerElement.style.display="none"},SVGRendererBase.prototype.show=function(){this.layerElement.style.display="block"},extendPrototype([BaseElement,TransformElement,HierarchyElement,FrameElement,RenderableDOMElement],ICompElement),ICompElement.prototype.initElement=function(e,t,i){this.initFrame(),this.initBaseData(e,t,i),this.initTransform(e,t,i),this.initRenderable(),this.initHierarchy(),this.initRendererElement(),this.createContainerElements(),this.createRenderableComponents(),!this.data.xt&&t.progressiveLoad||this.buildAllItems(),this.hide()},ICompElement.prototype.prepareFrame=function(e){if(this._mdf=!1,this.prepareRenderableFrame(e),this.prepareProperties(e,this.isInRange),this.isInRange||this.data.xt){if(this.tm._placeholder)this.renderedFrame=e/this.data.sr;else{var t=this.tm.v;t===this.data.op&&(t=this.data.op-1),this.renderedFrame=t}var i,n=this.elements.length;for(this.completeLayers||this.checkLayers(this.renderedFrame),i=n-1;i>=0;i-=1)(this.completeLayers||this.elements[i])&&(this.elements[i].prepareFrame(this.renderedFrame-this.layers[i].st),this.elements[i]._mdf&&(this._mdf=!0))}},ICompElement.prototype.renderInnerContent=function(){var e,t=this.layers.length;for(e=0;e<t;e+=1)(this.completeLayers||this.elements[e])&&this.elements[e].renderFrame()},ICompElement.prototype.setElements=function(e){this.elements=e},ICompElement.prototype.getElements=function(){return this.elements},ICompElement.prototype.destroyElements=function(){var e,t=this.layers.length;for(e=0;e<t;e+=1)this.elements[e]&&this.elements[e].destroy()},ICompElement.prototype.destroy=function(){this.destroyElements(),this.destroyBaseElement()},extendPrototype([SVGRendererBase,ICompElement,SVGBaseElement],SVGCompElement),SVGCompElement.prototype.createComp=function(e){return new SVGCompElement(e,this.globalData,this)},extendPrototype([SVGRendererBase],SVGRenderer),SVGRenderer.prototype.createComp=function(e){return new SVGCompElement(e,this.globalData,this)},CVContextData.prototype.duplicate=function(){var e=2*this._length,t=this.savedOp;this.savedOp=createTypedArray("float32",e),this.savedOp.set(t);var i=0;for(i=this._length;i<e;i+=1)this.saved[i]=createTypedArray("float32",16);this._length=e},CVContextData.prototype.reset=function(){this.cArrPos=0,this.cTr.reset(),this.cO=1},CVContextData.prototype.popTransform=function(){var e,t=this.saved[this.cArrPos],i=this.cTr.props;for(e=0;e<16;e+=1)i[e]=t[e];return t},CVContextData.prototype.popOpacity=function(){var e=this.savedOp[this.cArrPos];return this.cO=e,e},CVContextData.prototype.pop=function(){return this.cArrPos-=1,{transform:this.popTransform(),opacity:this.popOpacity()}},CVContextData.prototype.push=function(){var e,t=this.cTr.props;this._length<=this.cArrPos&&this.duplicate();var i=this.saved[this.cArrPos];for(e=0;e<16;e+=1)i[e]=t[e];this.savedOp[this.cArrPos]=this.cO,this.cArrPos+=1},CVContextData.prototype.getTransform=function(){return this.cTr},CVContextData.prototype.getOpacity=function(){return this.cO},CVContextData.prototype.setOpacity=function(e){this.cO=e},ShapeTransformManager.prototype={addTransformSequence:function(e){var t,i=e.length,n="_";for(t=0;t<i;t+=1)n+=e[t].transform.key+"_";var r=this.sequences[n];return r||(r={transforms:[].concat(e),finalTransform:new Matrix,_mdf:!1},this.sequences[n]=r,this.sequenceList.push(r)),r},processSequence:function(e,t){for(var i,n=0,r=e.transforms.length,a=t;n<r&&!t;){if(e.transforms[n].transform.mProps._mdf){a=!0;break}n+=1}if(a)for(e.finalTransform.reset(),n=r-1;n>=0;n-=1)i=e.transforms[n].transform.mProps.v.props,e.finalTransform.transform(i[0],i[1],i[2],i[3],i[4],i[5],i[6],i[7],i[8],i[9],i[10],i[11],i[12],i[13],i[14],i[15]);e._mdf=a},processSequences:function(e){var t,i=this.sequenceList.length;for(t=0;t<i;t+=1)this.processSequence(this.sequenceList[t],e)},getNewKey:function(){return this.transform_key_count+=1,"_"+this.transform_key_count}};var lumaLoader=function(){var n="__lottie_element_luma_buffer",r=null,a=null,s=null;function t(){var e,t,i;r||(e=createNS("svg"),t=createNS("filter"),i=createNS("feColorMatrix"),t.setAttribute("id",n),i.setAttribute("type","matrix"),i.setAttribute("color-interpolation-filters","sRGB"),i.setAttribute("values","0.3, 0.3, 0.3, 0, 0, 0.3, 0.3, 0.3, 0, 0, 0.3, 0.3, 0.3, 0, 0, 0.3, 0.3, 0.3, 0, 0"),t.appendChild(i),e.appendChild(t),e.setAttribute("id",n+"_svg"),featureSupport.svgLumaHidden&&(e.style.display="none"),s=e,document.body.appendChild(s),r=createTag("canvas"),(a=r.getContext("2d")).filter="url(#"+n+")",a.fillStyle="rgba(0,0,0,0)",a.fillRect(0,0,1,1))}return{load:t,get:function(e){return r||t(),r.width=e.width,r.height=e.height,a.filter="url(#"+n+")",r}}};function createCanvas(e,t){if(featureSupport.offscreenCanvas)return new OffscreenCanvas(e,t);var i=createTag("canvas");return i.width=e,i.height=t,i}var assetLoader={loadLumaCanvas:lumaLoader.load,getLumaCanvas:lumaLoader.get,createCanvas:createCanvas};function CVEffects(){}function CVMaskElement(e,t){var i;this.data=e,this.element=t,this.masksProperties=this.data.masksProperties||[],this.viewData=createSizedArray(this.masksProperties.length);var n=this.masksProperties.length,r=!1;for(i=0;i<n;i+=1)"n"!==this.masksProperties[i].mode&&(r=!0),this.viewData[i]=ShapePropertyFactory.getShapeProp(this.element,this.masksProperties[i],3);this.hasMasks=r,r&&this.element.addRenderableComponent(this)}function CVBaseElement(){}CVEffects.prototype.renderFrame=function(){},CVMaskElement.prototype.renderFrame=function(){if(this.hasMasks){var e,t,i,n,r=this.element.finalTransform.mat,a=this.element.canvasContext,s=this.masksProperties.length;for(a.beginPath(),e=0;e<s;e+=1)if("n"!==this.masksProperties[e].mode){var o;this.masksProperties[e].inv&&(a.moveTo(0,0),a.lineTo(this.element.globalData.compSize.w,0),a.lineTo(this.element.globalData.compSize.w,this.element.globalData.compSize.h),a.lineTo(0,this.element.globalData.compSize.h),a.lineTo(0,0)),n=this.viewData[e].v,t=r.applyToPointArray(n.v[0][0],n.v[0][1],0),a.moveTo(t[0],t[1]);var l=n._length;for(o=1;o<l;o+=1)i=r.applyToTriplePoints(n.o[o-1],n.i[o],n.v[o]),a.bezierCurveTo(i[0],i[1],i[2],i[3],i[4],i[5]);i=r.applyToTriplePoints(n.o[o-1],n.i[0],n.v[0]),a.bezierCurveTo(i[0],i[1],i[2],i[3],i[4],i[5])}this.element.globalData.renderer.save(!0),a.clip()}},CVMaskElement.prototype.getMaskProperty=MaskElement.prototype.getMaskProperty,CVMaskElement.prototype.destroy=function(){this.element=null};var operationsMap={1:"source-in",2:"source-out",3:"source-in",4:"source-out"};function CVShapeData(e,t,i,n){this.styledShapes=[],this.tr=[0,0,0,0,0,0];var r,a=4;"rc"===t.ty?a=5:"el"===t.ty?a=6:"sr"===t.ty&&(a=7),this.sh=ShapePropertyFactory.getShapeProp(e,t,a,e);var s,o=i.length;for(r=0;r<o;r+=1)i[r].closed||(s={transforms:n.addTransformSequence(i[r].transforms),trNodes:[]},this.styledShapes.push(s),i[r].elements.push(s))}function CVShapeElement(e,t,i){this.shapes=[],this.shapesData=e.shapes,this.stylesList=[],this.itemsData=[],this.prevViewData=[],this.shapeModifiers=[],this.processedElements=[],this.transformsManager=new ShapeTransformManager,this.initElement(e,t,i)}function CVTextElement(e,t,i){this.textSpans=[],this.yOffset=0,this.fillColorAnim=!1,this.strokeColorAnim=!1,this.strokeWidthAnim=!1,this.stroke=!1,this.fill=!1,this.justifyOffset=0,this.currentRender=null,this.renderType="canvas",this.values={fill:"rgba(0,0,0,0)",stroke:"rgba(0,0,0,0)",sWidth:0,fValue:""},this.initElement(e,t,i)}function CVImageElement(e,t,i){this.assetData=t.getAssetData(e.refId),this.img=t.imageLoader.getAsset(this.assetData),this.initElement(e,t,i)}function CVSolidElement(e,t,i){this.initElement(e,t,i)}function CanvasRendererBase(e,t){this.animationItem=e,this.renderConfig={clearCanvas:!t||void 0===t.clearCanvas||t.clearCanvas,context:t&&t.context||null,progressiveLoad:t&&t.progressiveLoad||!1,preserveAspectRatio:t&&t.preserveAspectRatio||"xMidYMid meet",imagePreserveAspectRatio:t&&t.imagePreserveAspectRatio||"xMidYMid slice",contentVisibility:t&&t.contentVisibility||"visible",className:t&&t.className||"",id:t&&t.id||""},this.renderConfig.dpr=t&&t.dpr||1,this.animationItem.wrapper&&(this.renderConfig.dpr=t&&t.dpr||window.devicePixelRatio||1),this.renderedFrame=-1,this.globalData={frameNum:-1,_mdf:!1,renderConfig:this.renderConfig,currentGlobalAlpha:-1},this.contextData=new CVContextData,this.elements=[],this.pendingElements=[],this.transformMat=new Matrix,this.completeLayers=!1,this.rendererType="canvas"}function CVCompElement(e,t,i){this.completeLayers=!1,this.layers=e.layers,this.pendingElements=[],this.elements=createSizedArray(this.layers.length),this.initElement(e,t,i),this.tm=e.tm?PropertyFactory.getProp(this,e.tm,0,t.frameRate,this):{_placeholder:!0}}function CanvasRenderer(e,t){this.animationItem=e,this.renderConfig={clearCanvas:!t||void 0===t.clearCanvas||t.clearCanvas,context:t&&t.context||null,progressiveLoad:t&&t.progressiveLoad||!1,preserveAspectRatio:t&&t.preserveAspectRatio||"xMidYMid meet",imagePreserveAspectRatio:t&&t.imagePreserveAspectRatio||"xMidYMid slice",contentVisibility:t&&t.contentVisibility||"visible",className:t&&t.className||"",id:t&&t.id||"",runExpressions:!t||void 0===t.runExpressions||t.runExpressions},this.renderConfig.dpr=t&&t.dpr||1,this.animationItem.wrapper&&(this.renderConfig.dpr=t&&t.dpr||window.devicePixelRatio||1),this.renderedFrame=-1,this.globalData={frameNum:-1,_mdf:!1,renderConfig:this.renderConfig,currentGlobalAlpha:-1},this.contextData=new CVContextData,this.elements=[],this.pendingElements=[],this.transformMat=new Matrix,this.completeLayers=!1,this.rendererType="canvas"}CVBaseElement.prototype={createElements:function(){},initRendererElement:function(){},createContainerElements:function(){if(this.data.tt>=1){this.buffers=[];var e=this.globalData.canvasContext,t=assetLoader.createCanvas(e.canvas.width,e.canvas.height);this.buffers.push(t);var i=assetLoader.createCanvas(e.canvas.width,e.canvas.height);this.buffers.push(i),this.data.tt>=3&&!document._isProxy&&assetLoader.loadLumaCanvas()}this.canvasContext=this.globalData.canvasContext,this.transformCanvas=this.globalData.transformCanvas,this.renderableEffectsManager=new CVEffects(this)},createContent:function(){},setBlendMode:function(){var e=this.globalData;if(e.blendMode!==this.data.bm){e.blendMode=this.data.bm;var t=getBlendMode(this.data.bm);e.canvasContext.globalCompositeOperation=t}},createRenderableComponents:function(){this.maskManager=new CVMaskElement(this.data,this)},hideElement:function(){this.hidden||this.isInRange&&!this.isTransparent||(this.hidden=!0)},showElement:function(){this.isInRange&&!this.isTransparent&&(this.hidden=!1,this._isFirstFrame=!0,this.maskManager._isFirstFrame=!0)},clearCanvas:function(e){e.clearRect(this.transformCanvas.tx,this.transformCanvas.ty,this.transformCanvas.w*this.transformCanvas.sx,this.transformCanvas.h*this.transformCanvas.sy)},prepareLayer:function(){if(this.data.tt>=1){var e=this.buffers[0].getContext("2d");this.clearCanvas(e),e.drawImage(this.canvasContext.canvas,0,0),this.currentTransform=this.canvasContext.getTransform(),this.canvasContext.setTransform(1,0,0,1,0,0),this.clearCanvas(this.canvasContext),this.canvasContext.setTransform(this.currentTransform)}},exitLayer:function(){if(this.data.tt>=1){var e=this.buffers[1],t=e.getContext("2d");if(this.clearCanvas(t),t.drawImage(this.canvasContext.canvas,0,0),this.canvasContext.setTransform(1,0,0,1,0,0),this.clearCanvas(this.canvasContext),this.canvasContext.setTransform(this.currentTransform),this.comp.getElementById("tp"in this.data?this.data.tp:this.data.ind-1).renderFrame(!0),this.canvasContext.setTransform(1,0,0,1,0,0),this.data.tt>=3&&!document._isProxy){var i=assetLoader.getLumaCanvas(this.canvasContext.canvas);i.getContext("2d").drawImage(this.canvasContext.canvas,0,0),this.clearCanvas(this.canvasContext),this.canvasContext.drawImage(i,0,0)}this.canvasContext.globalCompositeOperation=operationsMap[this.data.tt],this.canvasContext.drawImage(e,0,0),this.canvasContext.globalCompositeOperation="destination-over",this.canvasContext.drawImage(this.buffers[0],0,0),this.canvasContext.setTransform(this.currentTransform),this.canvasContext.globalCompositeOperation="source-over"}},renderFrame:function(e){if(!this.hidden&&!this.data.hd&&(1!==this.data.td||e)){this.renderTransform(),this.renderRenderable(),this.setBlendMode();var t=0===this.data.ty;this.prepareLayer(),this.globalData.renderer.save(t),this.globalData.renderer.ctxTransform(this.finalTransform.mat.props),this.globalData.renderer.ctxOpacity(this.finalTransform.mProp.o.v),this.renderInnerContent(),this.globalData.renderer.restore(t),this.exitLayer(),this.maskManager.hasMasks&&this.globalData.renderer.restore(!0),this._isFirstFrame&&(this._isFirstFrame=!1)}},destroy:function(){this.canvasContext=null,this.data=null,this.globalData=null,this.maskManager.destroy()},mHelper:new Matrix},CVBaseElement.prototype.hide=CVBaseElement.prototype.hideElement,CVBaseElement.prototype.show=CVBaseElement.prototype.showElement,CVShapeData.prototype.setAsAnimated=SVGShapeData.prototype.setAsAnimated,extendPrototype([BaseElement,TransformElement,CVBaseElement,IShapeElement,HierarchyElement,FrameElement,RenderableElement],CVShapeElement),CVShapeElement.prototype.initElement=RenderableDOMElement.prototype.initElement,CVShapeElement.prototype.transformHelper={opacity:1,_opMdf:!1},CVShapeElement.prototype.dashResetter=[],CVShapeElement.prototype.createContent=function(){this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,!0,[])},CVShapeElement.prototype.createStyleElement=function(e,t){var i={data:e,type:e.ty,preTransforms:this.transformsManager.addTransformSequence(t),transforms:[],elements:[],closed:!0===e.hd},n={};if("fl"===e.ty||"st"===e.ty?(n.c=PropertyFactory.getProp(this,e.c,1,255,this),n.c.k||(i.co="rgb("+bmFloor(n.c.v[0])+","+bmFloor(n.c.v[1])+","+bmFloor(n.c.v[2])+")")):"gf"!==e.ty&&"gs"!==e.ty||(n.s=PropertyFactory.getProp(this,e.s,1,null,this),n.e=PropertyFactory.getProp(this,e.e,1,null,this),n.h=PropertyFactory.getProp(this,e.h||{k:0},0,.01,this),n.a=PropertyFactory.getProp(this,e.a||{k:0},0,degToRads,this),n.g=new GradientProperty(this,e.g,this)),n.o=PropertyFactory.getProp(this,e.o,0,.01,this),"st"===e.ty||"gs"===e.ty){if(i.lc=lineCapEnum[e.lc||2],i.lj=lineJoinEnum[e.lj||2],1==e.lj&&(i.ml=e.ml),n.w=PropertyFactory.getProp(this,e.w,0,null,this),n.w.k||(i.wi=n.w.v),e.d){var r=new DashProperty(this,e.d,"canvas",this);n.d=r,n.d.k||(i.da=n.d.dashArray,i.do=n.d.dashoffset[0])}}else i.r=2===e.r?"evenodd":"nonzero";return this.stylesList.push(i),n.style=i,n},CVShapeElement.prototype.createGroupElement=function(){return{it:[],prevViewData:[]}},CVShapeElement.prototype.createTransformElement=function(e){return{transform:{opacity:1,_opMdf:!1,key:this.transformsManager.getNewKey(),op:PropertyFactory.getProp(this,e.o,0,.01,this),mProps:TransformPropertyFactory.getTransformProperty(this,e,this)}}},CVShapeElement.prototype.createShapeElement=function(e){var t=new CVShapeData(this,e,this.stylesList,this.transformsManager);return this.shapes.push(t),this.addShapeToModifiers(t),t},CVShapeElement.prototype.reloadShapes=function(){var e;this._isFirstFrame=!0;var t=this.itemsData.length;for(e=0;e<t;e+=1)this.prevViewData[e]=this.itemsData[e];for(this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,!0,[]),t=this.dynamicProperties.length,e=0;e<t;e+=1)this.dynamicProperties[e].getValue();this.renderModifiers(),this.transformsManager.processSequences(this._isFirstFrame)},CVShapeElement.prototype.addTransformToStyleList=function(e){var t,i=this.stylesList.length;for(t=0;t<i;t+=1)this.stylesList[t].closed||this.stylesList[t].transforms.push(e)},CVShapeElement.prototype.removeTransformFromStyleList=function(){var e,t=this.stylesList.length;for(e=0;e<t;e+=1)this.stylesList[e].closed||this.stylesList[e].transforms.pop()},CVShapeElement.prototype.closeStyles=function(e){var t,i=e.length;for(t=0;t<i;t+=1)e[t].closed=!0},CVShapeElement.prototype.searchShapes=function(e,t,i,n,r){var a,s,o,l,u,h,p=e.length-1,c=[],m=[],f=[].concat(r);for(a=p;a>=0;a-=1){if((l=this.searchProcessedElement(e[a]))?t[a]=i[l-1]:e[a]._shouldRender=n,"fl"===e[a].ty||"st"===e[a].ty||"gf"===e[a].ty||"gs"===e[a].ty)l?t[a].style.closed=!1:t[a]=this.createStyleElement(e[a],f),c.push(t[a].style);else if("gr"===e[a].ty){if(l)for(o=t[a].it.length,s=0;s<o;s+=1)t[a].prevViewData[s]=t[a].it[s];else t[a]=this.createGroupElement(e[a]);this.searchShapes(e[a].it,t[a].it,t[a].prevViewData,n,f)}else"tr"===e[a].ty?(l||(h=this.createTransformElement(e[a]),t[a]=h),f.push(t[a]),this.addTransformToStyleList(t[a])):"sh"===e[a].ty||"rc"===e[a].ty||"el"===e[a].ty||"sr"===e[a].ty?l||(t[a]=this.createShapeElement(e[a])):"tm"===e[a].ty||"rd"===e[a].ty||"pb"===e[a].ty||"zz"===e[a].ty||"op"===e[a].ty?(l?(u=t[a]).closed=!1:((u=ShapeModifiers.getModifier(e[a].ty)).init(this,e[a]),t[a]=u,this.shapeModifiers.push(u)),m.push(u)):"rp"===e[a].ty&&(l?(u=t[a]).closed=!0:(u=ShapeModifiers.getModifier(e[a].ty),t[a]=u,u.init(this,e,a,t),this.shapeModifiers.push(u),n=!1),m.push(u));this.addProcessedElement(e[a],a+1)}for(this.removeTransformFromStyleList(),this.closeStyles(c),p=m.length,a=0;a<p;a+=1)m[a].closed=!0},CVShapeElement.prototype.renderInnerContent=function(){this.transformHelper.opacity=1,this.transformHelper._opMdf=!1,this.renderModifiers(),this.transformsManager.processSequences(this._isFirstFrame),this.renderShape(this.transformHelper,this.shapesData,this.itemsData,!0)},CVShapeElement.prototype.renderShapeTransform=function(e,t){(e._opMdf||t.op._mdf||this._isFirstFrame)&&(t.opacity=e.opacity,t.opacity*=t.op.v,t._opMdf=!0)},CVShapeElement.prototype.drawLayer=function(){var e,t,i,n,r,a,s,o,l,u=this.stylesList.length,h=this.globalData.renderer,p=this.globalData.canvasContext;for(e=0;e<u;e+=1)if(("st"!==(o=(l=this.stylesList[e]).type)&&"gs"!==o||0!==l.wi)&&l.data._shouldRender&&0!==l.coOp&&0!==this.globalData.currentGlobalAlpha){for(h.save(),a=l.elements,"st"===o||"gs"===o?(p.strokeStyle="st"===o?l.co:l.grd,p.lineWidth=l.wi,p.lineCap=l.lc,p.lineJoin=l.lj,p.miterLimit=l.ml||0):p.fillStyle="fl"===o?l.co:l.grd,h.ctxOpacity(l.coOp),"st"!==o&&"gs"!==o&&p.beginPath(),h.ctxTransform(l.preTransforms.finalTransform.props),i=a.length,t=0;t<i;t+=1){for("st"!==o&&"gs"!==o||(p.beginPath(),l.da&&(p.setLineDash(l.da),p.lineDashOffset=l.do)),r=(s=a[t].trNodes).length,n=0;n<r;n+=1)"m"===s[n].t?p.moveTo(s[n].p[0],s[n].p[1]):"c"===s[n].t?p.bezierCurveTo(s[n].pts[0],s[n].pts[1],s[n].pts[2],s[n].pts[3],s[n].pts[4],s[n].pts[5]):p.closePath();"st"!==o&&"gs"!==o||(p.stroke(),l.da&&p.setLineDash(this.dashResetter))}"st"!==o&&"gs"!==o&&p.fill(l.r),h.restore()}},CVShapeElement.prototype.renderShape=function(e,t,i,n){var r,a;for(a=e,r=t.length-1;r>=0;r-=1)"tr"===t[r].ty?(a=i[r].transform,this.renderShapeTransform(e,a)):"sh"===t[r].ty||"el"===t[r].ty||"rc"===t[r].ty||"sr"===t[r].ty?this.renderPath(t[r],i[r]):"fl"===t[r].ty?this.renderFill(t[r],i[r],a):"st"===t[r].ty?this.renderStroke(t[r],i[r],a):"gf"===t[r].ty||"gs"===t[r].ty?this.renderGradientFill(t[r],i[r],a):"gr"===t[r].ty?this.renderShape(a,t[r].it,i[r].it):t[r].ty;n&&this.drawLayer()},CVShapeElement.prototype.renderStyledShape=function(e,t){if(this._isFirstFrame||t._mdf||e.transforms._mdf){var i,n,r,a=e.trNodes,s=t.paths,o=s._length;a.length=0;var l=e.transforms.finalTransform;for(r=0;r<o;r+=1){var u=s.shapes[r];if(u&&u.v){for(n=u._length,i=1;i<n;i+=1)1===i&&a.push({t:"m",p:l.applyToPointArray(u.v[0][0],u.v[0][1],0)}),a.push({t:"c",pts:l.applyToTriplePoints(u.o[i-1],u.i[i],u.v[i])});1===n&&a.push({t:"m",p:l.applyToPointArray(u.v[0][0],u.v[0][1],0)}),u.c&&n&&(a.push({t:"c",pts:l.applyToTriplePoints(u.o[i-1],u.i[0],u.v[0])}),a.push({t:"z"}))}}e.trNodes=a}},CVShapeElement.prototype.renderPath=function(e,t){if(!0!==e.hd&&e._shouldRender){var i,n=t.styledShapes.length;for(i=0;i<n;i+=1)this.renderStyledShape(t.styledShapes[i],t.sh)}},CVShapeElement.prototype.renderFill=function(e,t,i){var n=t.style;(t.c._mdf||this._isFirstFrame)&&(n.co="rgb("+bmFloor(t.c.v[0])+","+bmFloor(t.c.v[1])+","+bmFloor(t.c.v[2])+")"),(t.o._mdf||i._opMdf||this._isFirstFrame)&&(n.coOp=t.o.v*i.opacity)},CVShapeElement.prototype.renderGradientFill=function(e,t,i){var n,r=t.style;if(!r.grd||t.g._mdf||t.s._mdf||t.e._mdf||1!==e.t&&(t.h._mdf||t.a._mdf)){var a,s=this.globalData.canvasContext,o=t.s.v,l=t.e.v;if(1===e.t)n=s.createLinearGradient(o[0],o[1],l[0],l[1]);else{var u=Math.sqrt(Math.pow(o[0]-l[0],2)+Math.pow(o[1]-l[1],2)),h=Math.atan2(l[1]-o[1],l[0]-o[0]),p=t.h.v;p>=1?p=.99:p<=-1&&(p=-.99);var c=u*p,m=Math.cos(h+t.a.v)*c+o[0],f=Math.sin(h+t.a.v)*c+o[1];n=s.createRadialGradient(m,f,0,o[0],o[1],u)}var d=e.g.p,g=t.g.c,v=1;for(a=0;a<d;a+=1)t.g._hasOpacity&&t.g._collapsable&&(v=t.g.o[2*a+1]),n.addColorStop(g[4*a]/100,"rgba("+g[4*a+1]+","+g[4*a+2]+","+g[4*a+3]+","+v+")");r.grd=n}r.coOp=t.o.v*i.opacity},CVShapeElement.prototype.renderStroke=function(e,t,i){var n=t.style,r=t.d;r&&(r._mdf||this._isFirstFrame)&&(n.da=r.dashArray,n.do=r.dashoffset[0]),(t.c._mdf||this._isFirstFrame)&&(n.co="rgb("+bmFloor(t.c.v[0])+","+bmFloor(t.c.v[1])+","+bmFloor(t.c.v[2])+")"),(t.o._mdf||i._opMdf||this._isFirstFrame)&&(n.coOp=t.o.v*i.opacity),(t.w._mdf||this._isFirstFrame)&&(n.wi=t.w.v)},CVShapeElement.prototype.destroy=function(){this.shapesData=null,this.globalData=null,this.canvasContext=null,this.stylesList.length=0,this.itemsData.length=0},extendPrototype([BaseElement,TransformElement,CVBaseElement,HierarchyElement,FrameElement,RenderableElement,ITextElement],CVTextElement),CVTextElement.prototype.tHelper=createTag("canvas").getContext("2d"),CVTextElement.prototype.buildNewText=function(){var e=this.textProperty.currentData;this.renderedLetters=createSizedArray(e.l?e.l.length:0);var t=!1;e.fc?(t=!0,this.values.fill=this.buildColor(e.fc)):this.values.fill="rgba(0,0,0,0)",this.fill=t;var i=!1;e.sc&&(i=!0,this.values.stroke=this.buildColor(e.sc),this.values.sWidth=e.sw);var n,r,a,s,o,l,u,h,p,c,m,f,d=this.globalData.fontManager.getFontByName(e.f),g=e.l,v=this.mHelper;this.stroke=i,this.values.fValue=e.finalSize+"px "+this.globalData.fontManager.getFontByName(e.f).fFamily,r=e.finalText.length;var y=this.data.singleShape,b=.001*e.tr*e.finalSize,x=0,A=0,_=!0,S=0;for(n=0;n<r;n+=1){s=(a=this.globalData.fontManager.getCharData(e.finalText[n],d.fStyle,this.globalData.fontManager.getFontByName(e.f).fFamily))&&a.data||{},v.reset(),y&&g[n].n&&(x=-b,A+=e.yOffset,A+=_?1:0,_=!1),p=(u=s.shapes?s.shapes[0].it:[]).length,v.scale(e.finalSize/100,e.finalSize/100),y&&this.applyTextPropertiesToMatrix(e,v,g[n].line,x,A),m=createSizedArray(p-1);var C=0;for(h=0;h<p;h+=1)if("sh"===u[h].ty){for(l=u[h].ks.k.i.length,c=u[h].ks.k,f=[],o=1;o<l;o+=1)1===o&&f.push(v.applyToX(c.v[0][0],c.v[0][1],0),v.applyToY(c.v[0][0],c.v[0][1],0)),f.push(v.applyToX(c.o[o-1][0],c.o[o-1][1],0),v.applyToY(c.o[o-1][0],c.o[o-1][1],0),v.applyToX(c.i[o][0],c.i[o][1],0),v.applyToY(c.i[o][0],c.i[o][1],0),v.applyToX(c.v[o][0],c.v[o][1],0),v.applyToY(c.v[o][0],c.v[o][1],0));f.push(v.applyToX(c.o[o-1][0],c.o[o-1][1],0),v.applyToY(c.o[o-1][0],c.o[o-1][1],0),v.applyToX(c.i[0][0],c.i[0][1],0),v.applyToY(c.i[0][0],c.i[0][1],0),v.applyToX(c.v[0][0],c.v[0][1],0),v.applyToY(c.v[0][0],c.v[0][1],0)),m[C]=f,C+=1}y&&(x+=g[n].l,x+=b),this.textSpans[S]?this.textSpans[S].elem=m:this.textSpans[S]={elem:m},S+=1}},CVTextElement.prototype.renderInnerContent=function(){var e,t,i,n,r,a,s=this.canvasContext;s.font=this.values.fValue,s.lineCap="butt",s.lineJoin="miter",s.miterLimit=4,this.data.singleShape||this.textAnimator.getMeasures(this.textProperty.currentData,this.lettersChangedFlag);var o,l=this.textAnimator.renderedLetters,u=this.textProperty.currentData.l;t=u.length;var h,p,c=null,m=null,f=null;for(e=0;e<t;e+=1)if(!u[e].n){if((o=l[e])&&(this.globalData.renderer.save(),this.globalData.renderer.ctxTransform(o.p),this.globalData.renderer.ctxOpacity(o.o)),this.fill){for(o&&o.fc?c!==o.fc&&(c=o.fc,s.fillStyle=o.fc):c!==this.values.fill&&(c=this.values.fill,s.fillStyle=this.values.fill),n=(h=this.textSpans[e].elem).length,this.globalData.canvasContext.beginPath(),i=0;i<n;i+=1)for(a=(p=h[i]).length,this.globalData.canvasContext.moveTo(p[0],p[1]),r=2;r<a;r+=6)this.globalData.canvasContext.bezierCurveTo(p[r],p[r+1],p[r+2],p[r+3],p[r+4],p[r+5]);this.globalData.canvasContext.closePath(),this.globalData.canvasContext.fill()}if(this.stroke){for(o&&o.sw?f!==o.sw&&(f=o.sw,s.lineWidth=o.sw):f!==this.values.sWidth&&(f=this.values.sWidth,s.lineWidth=this.values.sWidth),o&&o.sc?m!==o.sc&&(m=o.sc,s.strokeStyle=o.sc):m!==this.values.stroke&&(m=this.values.stroke,s.strokeStyle=this.values.stroke),n=(h=this.textSpans[e].elem).length,this.globalData.canvasContext.beginPath(),i=0;i<n;i+=1)for(a=(p=h[i]).length,this.globalData.canvasContext.moveTo(p[0],p[1]),r=2;r<a;r+=6)this.globalData.canvasContext.bezierCurveTo(p[r],p[r+1],p[r+2],p[r+3],p[r+4],p[r+5]);this.globalData.canvasContext.closePath(),this.globalData.canvasContext.stroke()}o&&this.globalData.renderer.restore()}},extendPrototype([BaseElement,TransformElement,CVBaseElement,HierarchyElement,FrameElement,RenderableElement],CVImageElement),CVImageElement.prototype.initElement=SVGShapeElement.prototype.initElement,CVImageElement.prototype.prepareFrame=IImageElement.prototype.prepareFrame,CVImageElement.prototype.createContent=function(){if(this.img.width&&(this.assetData.w!==this.img.width||this.assetData.h!==this.img.height)){var e=createTag("canvas");e.width=this.assetData.w,e.height=this.assetData.h;var t,i,n=e.getContext("2d"),r=this.img.width,a=this.img.height,s=r/a,o=this.assetData.w/this.assetData.h,l=this.assetData.pr||this.globalData.renderConfig.imagePreserveAspectRatio;s>o&&"xMidYMid slice"===l||s<o&&"xMidYMid slice"!==l?t=(i=a)*o:i=(t=r)/o,n.drawImage(this.img,(r-t)/2,(a-i)/2,t,i,0,0,this.assetData.w,this.assetData.h),this.img=e}},CVImageElement.prototype.renderInnerContent=function(){this.canvasContext.drawImage(this.img,0,0)},CVImageElement.prototype.destroy=function(){this.img=null},extendPrototype([BaseElement,TransformElement,CVBaseElement,HierarchyElement,FrameElement,RenderableElement],CVSolidElement),CVSolidElement.prototype.initElement=SVGShapeElement.prototype.initElement,CVSolidElement.prototype.prepareFrame=IImageElement.prototype.prepareFrame,CVSolidElement.prototype.renderInnerContent=function(){var e=this.canvasContext;e.fillStyle=this.data.sc,e.fillRect(0,0,this.data.sw,this.data.sh)},extendPrototype([BaseRenderer],CanvasRendererBase),CanvasRendererBase.prototype.createShape=function(e){return new CVShapeElement(e,this.globalData,this)},CanvasRendererBase.prototype.createText=function(e){return new CVTextElement(e,this.globalData,this)},CanvasRendererBase.prototype.createImage=function(e){return new CVImageElement(e,this.globalData,this)},CanvasRendererBase.prototype.createSolid=function(e){return new CVSolidElement(e,this.globalData,this)},CanvasRendererBase.prototype.createNull=SVGRenderer.prototype.createNull,CanvasRendererBase.prototype.ctxTransform=function(e){if(1!==e[0]||0!==e[1]||0!==e[4]||1!==e[5]||0!==e[12]||0!==e[13])if(this.renderConfig.clearCanvas){this.transformMat.cloneFromProps(e);var t=this.contextData.getTransform(),i=t.props;this.transformMat.transform(i[0],i[1],i[2],i[3],i[4],i[5],i[6],i[7],i[8],i[9],i[10],i[11],i[12],i[13],i[14],i[15]),t.cloneFromProps(this.transformMat.props);var n=t.props;this.canvasContext.setTransform(n[0],n[1],n[4],n[5],n[12],n[13])}else this.canvasContext.transform(e[0],e[1],e[4],e[5],e[12],e[13])},CanvasRendererBase.prototype.ctxOpacity=function(e){var t=this.contextData.getOpacity();if(!this.renderConfig.clearCanvas)return this.canvasContext.globalAlpha*=e<0?0:e,void(this.globalData.currentGlobalAlpha=t);t*=e<0?0:e,this.contextData.setOpacity(t),this.globalData.currentGlobalAlpha!==t&&(this.canvasContext.globalAlpha=t,this.globalData.currentGlobalAlpha=t)},CanvasRendererBase.prototype.reset=function(){this.renderConfig.clearCanvas?this.contextData.reset():this.canvasContext.restore()},CanvasRendererBase.prototype.save=function(e){this.renderConfig.clearCanvas?(e&&this.canvasContext.save(),this.contextData.push()):this.canvasContext.save()},CanvasRendererBase.prototype.restore=function(e){if(this.renderConfig.clearCanvas){e&&(this.canvasContext.restore(),this.globalData.blendMode="source-over");var t=this.contextData.pop(),i=t.transform,n=t.opacity;this.canvasContext.setTransform(i[0],i[1],i[4],i[5],i[12],i[13]),this.globalData.currentGlobalAlpha!==n&&(this.canvasContext.globalAlpha=n,this.globalData.currentGlobalAlpha=n)}else this.canvasContext.restore()},CanvasRendererBase.prototype.configAnimation=function(e){if(this.animationItem.wrapper){this.animationItem.container=createTag("canvas");var t=this.animationItem.container.style;t.width="100%",t.height="100%";var i="0px 0px 0px";t.transformOrigin=i,t.mozTransformOrigin=i,t.webkitTransformOrigin=i,t["-webkit-transform"]=i,t.contentVisibility=this.renderConfig.contentVisibility,this.animationItem.wrapper.appendChild(this.animationItem.container),this.canvasContext=this.animationItem.container.getContext("2d"),this.renderConfig.className&&this.animationItem.container.setAttribute("class",this.renderConfig.className),this.renderConfig.id&&this.animationItem.container.setAttribute("id",this.renderConfig.id)}else this.canvasContext=this.renderConfig.context;this.data=e,this.layers=e.layers,this.transformCanvas={w:e.w,h:e.h,sx:0,sy:0,tx:0,ty:0},this.setupGlobalData(e,document.body),this.globalData.canvasContext=this.canvasContext,this.globalData.renderer=this,this.globalData.isDashed=!1,this.globalData.progressiveLoad=this.renderConfig.progressiveLoad,this.globalData.transformCanvas=this.transformCanvas,this.elements=createSizedArray(e.layers.length),this.updateContainerSize()},CanvasRendererBase.prototype.updateContainerSize=function(e,t){var i,n,r,a;if(this.reset(),e?(i=e,n=t,this.canvasContext.canvas.width=i,this.canvasContext.canvas.height=n):(this.animationItem.wrapper&&this.animationItem.container?(i=this.animationItem.wrapper.offsetWidth,n=this.animationItem.wrapper.offsetHeight):(i=this.canvasContext.canvas.width,n=this.canvasContext.canvas.height),this.canvasContext.canvas.width=i*this.renderConfig.dpr,this.canvasContext.canvas.height=n*this.renderConfig.dpr),-1!==this.renderConfig.preserveAspectRatio.indexOf("meet")||-1!==this.renderConfig.preserveAspectRatio.indexOf("slice")){var s=this.renderConfig.preserveAspectRatio.split(" "),o=s[1]||"meet",l=s[0]||"xMidYMid",u=l.substr(0,4),h=l.substr(4);r=i/n,(a=this.transformCanvas.w/this.transformCanvas.h)>r&&"meet"===o||a<r&&"slice"===o?(this.transformCanvas.sx=i/(this.transformCanvas.w/this.renderConfig.dpr),this.transformCanvas.sy=i/(this.transformCanvas.w/this.renderConfig.dpr)):(this.transformCanvas.sx=n/(this.transformCanvas.h/this.renderConfig.dpr),this.transformCanvas.sy=n/(this.transformCanvas.h/this.renderConfig.dpr)),this.transformCanvas.tx="xMid"===u&&(a<r&&"meet"===o||a>r&&"slice"===o)?(i-this.transformCanvas.w*(n/this.transformCanvas.h))/2*this.renderConfig.dpr:"xMax"===u&&(a<r&&"meet"===o||a>r&&"slice"===o)?(i-this.transformCanvas.w*(n/this.transformCanvas.h))*this.renderConfig.dpr:0,this.transformCanvas.ty="YMid"===h&&(a>r&&"meet"===o||a<r&&"slice"===o)?(n-this.transformCanvas.h*(i/this.transformCanvas.w))/2*this.renderConfig.dpr:"YMax"===h&&(a>r&&"meet"===o||a<r&&"slice"===o)?(n-this.transformCanvas.h*(i/this.transformCanvas.w))*this.renderConfig.dpr:0}else"none"===this.renderConfig.preserveAspectRatio?(this.transformCanvas.sx=i/(this.transformCanvas.w/this.renderConfig.dpr),this.transformCanvas.sy=n/(this.transformCanvas.h/this.renderConfig.dpr),this.transformCanvas.tx=0,this.transformCanvas.ty=0):(this.transformCanvas.sx=this.renderConfig.dpr,this.transformCanvas.sy=this.renderConfig.dpr,this.transformCanvas.tx=0,this.transformCanvas.ty=0);this.transformCanvas.props=[this.transformCanvas.sx,0,0,0,0,this.transformCanvas.sy,0,0,0,0,1,0,this.transformCanvas.tx,this.transformCanvas.ty,0,1],this.ctxTransform(this.transformCanvas.props),this.canvasContext.beginPath(),this.canvasContext.rect(0,0,this.transformCanvas.w,this.transformCanvas.h),this.canvasContext.closePath(),this.canvasContext.clip(),this.renderFrame(this.renderedFrame,!0)},CanvasRendererBase.prototype.destroy=function(){var e;for(this.renderConfig.clearCanvas&&this.animationItem.wrapper&&(this.animationItem.wrapper.innerText=""),e=(this.layers?this.layers.length:0)-1;e>=0;e-=1)this.elements[e]&&this.elements[e].destroy();this.elements.length=0,this.globalData.canvasContext=null,this.animationItem.container=null,this.destroyed=!0},CanvasRendererBase.prototype.renderFrame=function(e,t){if((this.renderedFrame!==e||!0!==this.renderConfig.clearCanvas||t)&&!this.destroyed&&-1!==e){var i;this.renderedFrame=e,this.globalData.frameNum=e-this.animationItem._isFirstFrame,this.globalData.frameId+=1,this.globalData._mdf=!this.renderConfig.clearCanvas||t,this.globalData.projectInterface.currentFrame=e;var n=this.layers.length;for(this.completeLayers||this.checkLayers(e),i=0;i<n;i+=1)(this.completeLayers||this.elements[i])&&this.elements[i].prepareFrame(e-this.layers[i].st);if(this.globalData._mdf){for(!0===this.renderConfig.clearCanvas?this.canvasContext.clearRect(0,0,this.transformCanvas.w,this.transformCanvas.h):this.save(),i=n-1;i>=0;i-=1)(this.completeLayers||this.elements[i])&&this.elements[i].renderFrame();!0!==this.renderConfig.clearCanvas&&this.restore()}}},CanvasRendererBase.prototype.buildItem=function(e){var t=this.elements;if(!t[e]&&99!==this.layers[e].ty){var i=this.createItem(this.layers[e],this,this.globalData);t[e]=i,i.initExpressions()}},CanvasRendererBase.prototype.checkPendingElements=function(){for(;this.pendingElements.length;){this.pendingElements.pop().checkParenting()}},CanvasRendererBase.prototype.hide=function(){this.animationItem.container.style.display="none"},CanvasRendererBase.prototype.show=function(){this.animationItem.container.style.display="block"},extendPrototype([CanvasRendererBase,ICompElement,CVBaseElement],CVCompElement),CVCompElement.prototype.renderInnerContent=function(){var e,t=this.canvasContext;for(t.beginPath(),t.moveTo(0,0),t.lineTo(this.data.w,0),t.lineTo(this.data.w,this.data.h),t.lineTo(0,this.data.h),t.lineTo(0,0),t.clip(),e=this.layers.length-1;e>=0;e-=1)(this.completeLayers||this.elements[e])&&this.elements[e].renderFrame()},CVCompElement.prototype.destroy=function(){var e;for(e=this.layers.length-1;e>=0;e-=1)this.elements[e]&&this.elements[e].destroy();this.layers=null,this.elements=null},CVCompElement.prototype.createComp=function(e){return new CVCompElement(e,this.globalData,this)},extendPrototype([CanvasRendererBase],CanvasRenderer),CanvasRenderer.prototype.createComp=function(e){return new CVCompElement(e,this.globalData,this)},registerRenderer("canvas",CanvasRenderer),ShapeModifiers.registerModifier("tm",TrimModifier),ShapeModifiers.registerModifier("pb",PuckerAndBloatModifier),ShapeModifiers.registerModifier("rp",RepeaterModifier),ShapeModifiers.registerModifier("rd",RoundCornersModifier),ShapeModifiers.registerModifier("zz",ZigZagModifier),ShapeModifiers.registerModifier("op",OffsetPathModifier);var CompExpressionInterface=function(n){function e(e){for(var t=0,i=n.layers.length;t<i;){if(n.layers[t].nm===e||n.layers[t].ind===e)return n.elements[t].layerInterface;t+=1}return null}return Object.defineProperty(e,"_name",{value:n.data.nm}),e.layer=e,e.pixelAspect=1,e.height=n.data.h||n.globalData.compSize.h,e.width=n.data.w||n.globalData.compSize.w,e.pixelAspect=1,e.frameDuration=1/n.globalData.frameRate,e.displayStartTime=0,e.numLayers=n.layers.length,e},Expressions=function(){var e={};return e.initExpressions=function(e){var t=0,i=[];e.renderer.compInterface=CompExpressionInterface(e.renderer),e.renderer.globalData.projectInterface.registerComposition(e.renderer),e.renderer.globalData.pushExpression=function(){t+=1},e.renderer.globalData.popExpression=function(){0==(t-=1)&&function(){var e,t=i.length;for(e=0;e<t;e+=1)i[e].release();i.length=0}()},e.renderer.globalData.registerExpressionProperty=function(e){-1===i.indexOf(e)&&i.push(e)}},e}(),MaskManagerInterface=function(){function e(e,t){this._mask=e,this._data=t}Object.defineProperty(e.prototype,"maskPath",{get:function(){return this._mask.prop.k&&this._mask.prop.getValue(),this._mask.prop}}),Object.defineProperty(e.prototype,"maskOpacity",{get:function(){return this._mask.op.k&&this._mask.op.getValue(),100*this._mask.op.v}});return function(t){var i,n=createSizedArray(t.viewData.length),r=t.viewData.length;for(i=0;i<r;i+=1)n[i]=new e(t.viewData[i],t.masksProperties[i]);return function(e){for(i=0;i<r;){if(t.masksProperties[i].nm===e)return n[i];i+=1}return null}}}(),ExpressionPropertyInterface=function(){var r={pv:0,v:0,mult:1},s={pv:[0,0,0],v:[0,0,0],mult:1};function o(n,r,a){Object.defineProperty(n,"velocity",{get:function(){return r.getVelocityAtTime(r.comp.currentFrame)}}),n.numKeys=r.keyframes?r.keyframes.length:0,n.key=function(e){if(!n.numKeys)return 0;var t="";t="s"in r.keyframes[e-1]?r.keyframes[e-1].s:"e"in r.keyframes[e-2]?r.keyframes[e-2].e:r.keyframes[e-2].s;var i="unidimensional"===a?new Number(t):Object.assign({},t);return i.time=r.keyframes[e-1].t/r.elem.comp.globalData.frameRate,i.value="unidimensional"===a?t[0]:t,i},n.valueAtTime=r.getValueAtTime,n.speedAtTime=r.getSpeedAtTime,n.velocityAtTime=r.getVelocityAtTime,n.propertyGroup=r.propertyGroup}function t(){return r}return function(e){return e?"unidimensional"===e.propType?function(e){e&&"pv"in e||(e=r);var t=1/e.mult,i=e.pv*t,n=new Number(i);return n.value=i,o(n,e,"unidimensional"),function(){return e.k&&e.getValue(),i=e.v*t,n.value!==i&&((n=new Number(i)).value=i,o(n,e,"unidimensional")),n}}(e):function(t){t&&"pv"in t||(t=s);var i=1/t.mult,n=t.data&&t.data.l||t.pv.length,r=createTypedArray("float32",n),a=createTypedArray("float32",n);return r.value=a,o(r,t,"multidimensional"),function(){t.k&&t.getValue();for(var e=0;e<n;e+=1)a[e]=t.v[e]*i,r[e]=a[e];return r}}(e):t}}(),TransformExpressionInterface=function(e){function t(e){switch(e){case"scale":case"Scale":case"ADBE Scale":case 6:return t.scale;case"rotation":case"Rotation":case"ADBE Rotation":case"ADBE Rotate Z":case 10:return t.rotation;case"ADBE Rotate X":return t.xRotation;case"ADBE Rotate Y":return t.yRotation;case"position":case"Position":case"ADBE Position":case 2:return t.position;case"ADBE Position_0":return t.xPosition;case"ADBE Position_1":return t.yPosition;case"ADBE Position_2":return t.zPosition;case"anchorPoint":case"AnchorPoint":case"Anchor Point":case"ADBE AnchorPoint":case 1:return t.anchorPoint;case"opacity":case"Opacity":case 11:return t.opacity;default:return null}}var i,n,r,a;return Object.defineProperty(t,"rotation",{get:ExpressionPropertyInterface(e.r||e.rz)}),Object.defineProperty(t,"zRotation",{get:ExpressionPropertyInterface(e.rz||e.r)}),Object.defineProperty(t,"xRotation",{get:ExpressionPropertyInterface(e.rx)}),Object.defineProperty(t,"yRotation",{get:ExpressionPropertyInterface(e.ry)}),Object.defineProperty(t,"scale",{get:ExpressionPropertyInterface(e.s)}),e.p?a=ExpressionPropertyInterface(e.p):(i=ExpressionPropertyInterface(e.px),n=ExpressionPropertyInterface(e.py),e.pz&&(r=ExpressionPropertyInterface(e.pz))),Object.defineProperty(t,"position",{get:function(){return e.p?a():[i(),n(),r?r():0]}}),Object.defineProperty(t,"xPosition",{get:ExpressionPropertyInterface(e.px)}),Object.defineProperty(t,"yPosition",{get:ExpressionPropertyInterface(e.py)}),Object.defineProperty(t,"zPosition",{get:ExpressionPropertyInterface(e.pz)}),Object.defineProperty(t,"anchorPoint",{get:ExpressionPropertyInterface(e.a)}),Object.defineProperty(t,"opacity",{get:ExpressionPropertyInterface(e.o)}),Object.defineProperty(t,"skew",{get:ExpressionPropertyInterface(e.sk)}),Object.defineProperty(t,"skewAxis",{get:ExpressionPropertyInterface(e.sa)}),Object.defineProperty(t,"orientation",{get:ExpressionPropertyInterface(e.or)}),t},LayerExpressionInterface=function(){function r(e){var t=new Matrix;void 0!==e?this._elem.finalTransform.mProp.getValueAtTime(e).clone(t):this._elem.finalTransform.mProp.applyToMatrix(t);return t}function a(e,t){var i=this.getMatrix(t);return i.props[12]=0,i.props[13]=0,i.props[14]=0,this.applyPoint(i,e)}function s(e,t){var i=this.getMatrix(t);return this.applyPoint(i,e)}function o(e,t){var i=this.getMatrix(t);return i.props[12]=0,i.props[13]=0,i.props[14]=0,this.invertPoint(i,e)}function l(e,t){var i=this.getMatrix(t);return this.invertPoint(i,e)}function u(e,t){if(this._elem.hierarchy&&this._elem.hierarchy.length){var i,n=this._elem.hierarchy.length;for(i=0;i<n;i+=1)this._elem.hierarchy[i].finalTransform.mProp.applyToMatrix(e)}return e.applyToPointArray(t[0],t[1],t[2]||0)}function h(e,t){if(this._elem.hierarchy&&this._elem.hierarchy.length){var i,n=this._elem.hierarchy.length;for(i=0;i<n;i+=1)this._elem.hierarchy[i].finalTransform.mProp.applyToMatrix(e)}return e.inversePoint(t)}function p(e){var t=new Matrix;if(t.reset(),this._elem.finalTransform.mProp.applyToMatrix(t),this._elem.hierarchy&&this._elem.hierarchy.length){var i,n=this._elem.hierarchy.length;for(i=0;i<n;i+=1)this._elem.hierarchy[i].finalTransform.mProp.applyToMatrix(t);return t.inversePoint(e)}return t.inversePoint(e)}function c(){return[1,1,1,1]}return function(t){var i;function n(e){switch(e){case"ADBE Root Vectors Group":case"Contents":case 2:return n.shapeInterface;case 1:case 6:case"Transform":case"transform":case"ADBE Transform Group":return i;case 4:case"ADBE Effect Parade":case"effects":case"Effects":return n.effect;case"ADBE Text Properties":return n.textInterface;default:return null}}n.getMatrix=r,n.invertPoint=h,n.applyPoint=u,n.toWorld=s,n.toWorldVec=a,n.fromWorld=l,n.fromWorldVec=o,n.toComp=s,n.fromComp=p,n.sampleImage=c,n.sourceRectAtTime=t.sourceRectAtTime.bind(t),n._elem=t;var e=getDescriptor(i=TransformExpressionInterface(t.finalTransform.mProp),"anchorPoint");return Object.defineProperties(n,{hasParent:{get:function(){return t.hierarchy.length}},parent:{get:function(){return t.hierarchy[0].layerInterface}},rotation:getDescriptor(i,"rotation"),scale:getDescriptor(i,"scale"),position:getDescriptor(i,"position"),opacity:getDescriptor(i,"opacity"),anchorPoint:e,anchor_point:e,transform:{get:function(){return i}},active:{get:function(){return t.isInRange}}}),n.startTime=t.data.st,n.index=t.data.ind,n.source=t.data.refId,n.height=0===t.data.ty?t.data.h:100,n.width=0===t.data.ty?t.data.w:100,n.inPoint=t.data.ip/t.comp.globalData.frameRate,n.outPoint=t.data.op/t.comp.globalData.frameRate,n._name=t.data.nm,n.registerMaskInterface=function(e){n.mask=new MaskManagerInterface(e,t)},n.registerEffectsInterface=function(e){n.effect=e},n}}(),propertyGroupFactory=function(t,i){return function(e){return(e=void 0===e?1:e)<=0?t:i(e-1)}},PropertyInterface=function(e,t){var i={_name:e};return function(e){return(e=void 0===e?1:e)<=0?i:t(e-1)}},EffectsExpressionInterface=function(){function u(r,e,t,i){function n(e){for(var t=r.ef,i=0,n=t.length;i<n;){if(e===t[i].nm||e===t[i].mn||e===t[i].ix)return 5===t[i].ty?o[i]:o[i]();i+=1}throw new Error}var a,s=propertyGroupFactory(n,t),o=[],l=r.ef.length;for(a=0;a<l;a+=1)5===r.ef[a].ty?o.push(u(r.ef[a],e.effectElements[a],e.effectElements[a].propertyGroup,i)):o.push(h(e.effectElements[a],r.ef[a].ty,i,s));return"ADBE Color Control"===r.mn&&Object.defineProperty(n,"color",{get:function(){return o[0]()}}),Object.defineProperties(n,{numProperties:{get:function(){return r.np}},_name:{value:r.nm},propertyGroup:{value:s}}),n.enabled=0!==r.en,n.active=n.enabled,n}function h(e,t,i,n){var r=ExpressionPropertyInterface(e.p);return e.p.setGroupProperty&&e.p.setGroupProperty(PropertyInterface("",n)),function(){return 10===t?i.comp.compInterface(e.p.v):r()}}return{createEffectsInterface:function(e,t){if(e.effectsManager){var i,n=[],r=e.data.ef,a=e.effectsManager.effectElements.length;for(i=0;i<a;i+=1)n.push(u(r[i],e.effectsManager.effectElements[i],t,e));var s=e.data.ef||[],o=function(e){for(i=0,a=s.length;i<a;){if(e===s[i].nm||e===s[i].mn||e===s[i].ix)return n[i];i+=1}return null};return Object.defineProperty(o,"numProperties",{get:function(){return s.length}}),o}return null}}}(),ShapePathInterface=function(e,t,i){var n=t.sh;function r(e){return"Shape"===e||"shape"===e||"Path"===e||"path"===e||"ADBE Vector Shape"===e||2===e?r.path:null}var a=propertyGroupFactory(r,i);return n.setGroupProperty(PropertyInterface("Path",a)),Object.defineProperties(r,{path:{get:function(){return n.k&&n.getValue(),n}},shape:{get:function(){return n.k&&n.getValue(),n}},_name:{value:e.nm},ix:{value:e.ix},propertyIndex:{value:e.ix},mn:{value:e.mn},propertyGroup:{value:i}}),r},ShapeExpressionInterface=function(){function s(e,t,i){var n,r=[],a=e?e.length:0;for(n=0;n<a;n+=1)"gr"===e[n].ty?r.push(o(e[n],t[n],i)):"fl"===e[n].ty?r.push(l(e[n],t[n],i)):"st"===e[n].ty?r.push(p(e[n],t[n],i)):"tm"===e[n].ty?r.push(c(e[n],t[n],i)):"tr"===e[n].ty||("el"===e[n].ty?r.push(f(e[n],t[n],i)):"sr"===e[n].ty?r.push(d(e[n],t[n],i)):"sh"===e[n].ty?r.push(ShapePathInterface(e[n],t[n],i)):"rc"===e[n].ty?r.push(g(e[n],t[n],i)):"rd"===e[n].ty?r.push(v(e[n],t[n],i)):"rp"===e[n].ty?r.push(y(e[n],t[n],i)):"gf"===e[n].ty?r.push(u(e[n],t[n],i)):r.push(h(e[n],t[n])));return r}function o(e,t,i){var n=function(e){switch(e){case"ADBE Vectors Group":case"Contents":case 2:return n.content;default:return n.transform}};n.propertyGroup=propertyGroupFactory(n,i);var r=function(e,t,i){var n,r=function(e){for(var t=0,i=n.length;t<i;){if(n[t]._name===e||n[t].mn===e||n[t].propertyIndex===e||n[t].ix===e||n[t].ind===e)return n[t];t+=1}return"number"==typeof e?n[e-1]:null};r.propertyGroup=propertyGroupFactory(r,i),n=s(e.it,t.it,r.propertyGroup),r.numProperties=n.length;var a=m(e.it[e.it.length-1],t.it[t.it.length-1],r.propertyGroup);return r.transform=a,r.propertyIndex=e.cix,r._name=e.nm,r}(e,t,n.propertyGroup),a=m(e.it[e.it.length-1],t.it[t.it.length-1],n.propertyGroup);return n.content=r,n.transform=a,Object.defineProperty(n,"_name",{get:function(){return e.nm}}),n.numProperties=e.np,n.propertyIndex=e.ix,n.nm=e.nm,n.mn=e.mn,n}function l(e,t,i){function n(e){return"Color"===e||"color"===e?n.color:"Opacity"===e||"opacity"===e?n.opacity:null}return Object.defineProperties(n,{color:{get:ExpressionPropertyInterface(t.c)},opacity:{get:ExpressionPropertyInterface(t.o)},_name:{value:e.nm},mn:{value:e.mn}}),t.c.setGroupProperty(PropertyInterface("Color",i)),t.o.setGroupProperty(PropertyInterface("Opacity",i)),n}function u(e,t,i){function n(e){return"Start Point"===e||"start point"===e?n.startPoint:"End Point"===e||"end point"===e?n.endPoint:"Opacity"===e||"opacity"===e?n.opacity:null}return Object.defineProperties(n,{startPoint:{get:ExpressionPropertyInterface(t.s)},endPoint:{get:ExpressionPropertyInterface(t.e)},opacity:{get:ExpressionPropertyInterface(t.o)},type:{get:function(){return"a"}},_name:{value:e.nm},mn:{value:e.mn}}),t.s.setGroupProperty(PropertyInterface("Start Point",i)),t.e.setGroupProperty(PropertyInterface("End Point",i)),t.o.setGroupProperty(PropertyInterface("Opacity",i)),n}function h(){return function(){return null}}function p(t,i,e){var n,r=propertyGroupFactory(u,e),a=propertyGroupFactory(l,r);function s(e){Object.defineProperty(l,t.d[e].nm,{get:ExpressionPropertyInterface(i.d.dataProps[e].p)})}var o=t.d?t.d.length:0,l={};for(n=0;n<o;n+=1)s(n),i.d.dataProps[n].p.setGroupProperty(a);function u(e){return"Color"===e||"color"===e?u.color:"Opacity"===e||"opacity"===e?u.opacity:"Stroke Width"===e||"stroke width"===e?u.strokeWidth:null}return Object.defineProperties(u,{color:{get:ExpressionPropertyInterface(i.c)},opacity:{get:ExpressionPropertyInterface(i.o)},strokeWidth:{get:ExpressionPropertyInterface(i.w)},dash:{get:function(){return l}},_name:{value:t.nm},mn:{value:t.mn}}),i.c.setGroupProperty(PropertyInterface("Color",r)),i.o.setGroupProperty(PropertyInterface("Opacity",r)),i.w.setGroupProperty(PropertyInterface("Stroke Width",r)),u}function c(t,e,i){function n(e){return e===t.e.ix||"End"===e||"end"===e?n.end:e===t.s.ix?n.start:e===t.o.ix?n.offset:null}var r=propertyGroupFactory(n,i);return n.propertyIndex=t.ix,e.s.setGroupProperty(PropertyInterface("Start",r)),e.e.setGroupProperty(PropertyInterface("End",r)),e.o.setGroupProperty(PropertyInterface("Offset",r)),n.propertyIndex=t.ix,n.propertyGroup=i,Object.defineProperties(n,{start:{get:ExpressionPropertyInterface(e.s)},end:{get:ExpressionPropertyInterface(e.e)},offset:{get:ExpressionPropertyInterface(e.o)},_name:{value:t.nm}}),n.mn=t.mn,n}function m(t,e,i){function n(e){return t.a.ix===e||"Anchor Point"===e?n.anchorPoint:t.o.ix===e||"Opacity"===e?n.opacity:t.p.ix===e||"Position"===e?n.position:t.r.ix===e||"Rotation"===e||"ADBE Vector Rotation"===e?n.rotation:t.s.ix===e||"Scale"===e?n.scale:t.sk&&t.sk.ix===e||"Skew"===e?n.skew:t.sa&&t.sa.ix===e||"Skew Axis"===e?n.skewAxis:null}var r=propertyGroupFactory(n,i);return e.transform.mProps.o.setGroupProperty(PropertyInterface("Opacity",r)),e.transform.mProps.p.setGroupProperty(PropertyInterface("Position",r)),e.transform.mProps.a.setGroupProperty(PropertyInterface("Anchor Point",r)),e.transform.mProps.s.setGroupProperty(PropertyInterface("Scale",r)),e.transform.mProps.r.setGroupProperty(PropertyInterface("Rotation",r)),e.transform.mProps.sk&&(e.transform.mProps.sk.setGroupProperty(PropertyInterface("Skew",r)),e.transform.mProps.sa.setGroupProperty(PropertyInterface("Skew Angle",r))),e.transform.op.setGroupProperty(PropertyInterface("Opacity",r)),Object.defineProperties(n,{opacity:{get:ExpressionPropertyInterface(e.transform.mProps.o)},position:{get:ExpressionPropertyInterface(e.transform.mProps.p)},anchorPoint:{get:ExpressionPropertyInterface(e.transform.mProps.a)},scale:{get:ExpressionPropertyInterface(e.transform.mProps.s)},rotation:{get:ExpressionPropertyInterface(e.transform.mProps.r)},skew:{get:ExpressionPropertyInterface(e.transform.mProps.sk)},skewAxis:{get:ExpressionPropertyInterface(e.transform.mProps.sa)},_name:{value:t.nm}}),n.ty="tr",n.mn=t.mn,n.propertyGroup=i,n}function f(t,e,i){function n(e){return t.p.ix===e?n.position:t.s.ix===e?n.size:null}var r=propertyGroupFactory(n,i);n.propertyIndex=t.ix;var a="tm"===e.sh.ty?e.sh.prop:e.sh;return a.s.setGroupProperty(PropertyInterface("Size",r)),a.p.setGroupProperty(PropertyInterface("Position",r)),Object.defineProperties(n,{size:{get:ExpressionPropertyInterface(a.s)},position:{get:ExpressionPropertyInterface(a.p)},_name:{value:t.nm}}),n.mn=t.mn,n}function d(t,e,i){function n(e){return t.p.ix===e?n.position:t.r.ix===e?n.rotation:t.pt.ix===e?n.points:t.or.ix===e||"ADBE Vector Star Outer Radius"===e?n.outerRadius:t.os.ix===e?n.outerRoundness:!t.ir||t.ir.ix!==e&&"ADBE Vector Star Inner Radius"!==e?t.is&&t.is.ix===e?n.innerRoundness:null:n.innerRadius}var r=propertyGroupFactory(n,i),a="tm"===e.sh.ty?e.sh.prop:e.sh;return n.propertyIndex=t.ix,a.or.setGroupProperty(PropertyInterface("Outer Radius",r)),a.os.setGroupProperty(PropertyInterface("Outer Roundness",r)),a.pt.setGroupProperty(PropertyInterface("Points",r)),a.p.setGroupProperty(PropertyInterface("Position",r)),a.r.setGroupProperty(PropertyInterface("Rotation",r)),t.ir&&(a.ir.setGroupProperty(PropertyInterface("Inner Radius",r)),a.is.setGroupProperty(PropertyInterface("Inner Roundness",r))),Object.defineProperties(n,{position:{get:ExpressionPropertyInterface(a.p)},rotation:{get:ExpressionPropertyInterface(a.r)},points:{get:ExpressionPropertyInterface(a.pt)},outerRadius:{get:ExpressionPropertyInterface(a.or)},outerRoundness:{get:ExpressionPropertyInterface(a.os)},innerRadius:{get:ExpressionPropertyInterface(a.ir)},innerRoundness:{get:ExpressionPropertyInterface(a.is)},_name:{value:t.nm}}),n.mn=t.mn,n}function g(t,e,i){function n(e){return t.p.ix===e?n.position:t.r.ix===e?n.roundness:t.s.ix===e||"Size"===e||"ADBE Vector Rect Size"===e?n.size:null}var r=propertyGroupFactory(n,i),a="tm"===e.sh.ty?e.sh.prop:e.sh;return n.propertyIndex=t.ix,a.p.setGroupProperty(PropertyInterface("Position",r)),a.s.setGroupProperty(PropertyInterface("Size",r)),a.r.setGroupProperty(PropertyInterface("Rotation",r)),Object.defineProperties(n,{position:{get:ExpressionPropertyInterface(a.p)},roundness:{get:ExpressionPropertyInterface(a.r)},size:{get:ExpressionPropertyInterface(a.s)},_name:{value:t.nm}}),n.mn=t.mn,n}function v(t,e,i){function n(e){return t.r.ix===e||"Round Corners 1"===e?n.radius:null}var r=propertyGroupFactory(n,i),a=e;return n.propertyIndex=t.ix,a.rd.setGroupProperty(PropertyInterface("Radius",r)),Object.defineProperties(n,{radius:{get:ExpressionPropertyInterface(a.rd)},_name:{value:t.nm}}),n.mn=t.mn,n}function y(t,e,i){function n(e){return t.c.ix===e||"Copies"===e?n.copies:t.o.ix===e||"Offset"===e?n.offset:null}var r=propertyGroupFactory(n,i),a=e;return n.propertyIndex=t.ix,a.c.setGroupProperty(PropertyInterface("Copies",r)),a.o.setGroupProperty(PropertyInterface("Offset",r)),Object.defineProperties(n,{copies:{get:ExpressionPropertyInterface(a.c)},offset:{get:ExpressionPropertyInterface(a.o)},_name:{value:t.nm}}),n.mn=t.mn,n}return function(e,t,n){var r;function i(e){if("number"==typeof e)return 0===(e=void 0===e?1:e)?n:r[e-1];for(var t=0,i=r.length;t<i;){if(r[t]._name===e)return r[t];t+=1}return null}return i.propertyGroup=propertyGroupFactory(i,function(){return n}),r=s(e,t,i.propertyGroup),i.numProperties=r.length,i._name="Contents",i}}(),TextExpressionInterface=function(t){var i,n;function r(e){return"ADBE Text Document"===e?r.sourceText:null}return Object.defineProperty(r,"sourceText",{get:function(){t.textProperty.getValue();var e=t.textProperty.currentData.t;return e!==i&&(i=t.textProperty.currentData.t,(n=new String(e)).value=e||new String(e),Object.defineProperty(n,"style",{get:function(){return{fillColor:t.textProperty.currentData.fc}}})),n}}),r};function _typeof$2(e){return _typeof$2="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof$2(e)}var FootageInterface=(dataInterfaceFactory=function(e){function t(e){return"Outline"===e?t.outlineInterface():null}return t._name="Outline",t.outlineInterface=function(e){var n="",r=e.getFootageData();function a(e){if(r[e])return n=e,"object"===_typeof$2(r=r[e])?a:r;var t=e.indexOf(n);if(-1!==t){var i=parseInt(e.substr(t+n.length),10);return"object"===_typeof$2(r=r[i])?a:r}return""}return function(){return n="",r=e.getFootageData(),a}}(e),t},function(e){function t(e){return"Data"===e?t.dataInterface:null}return t._name="Data",t.dataInterface=dataInterfaceFactory(e),t}),dataInterfaceFactory,interfaces={layer:LayerExpressionInterface,effects:EffectsExpressionInterface,comp:CompExpressionInterface,shape:ShapeExpressionInterface,text:TextExpressionInterface,footage:FootageInterface};function getInterface(e){return interfaces[e]||null}function _typeof$1(e){return _typeof$1="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof$1(e)}function seedRandom(o,l){var u,h=this,p=256,c=l.pow(p,6),m=l.pow(2,52),f=2*m,d=255;function g(e){var t,i=e.length,s=this,n=0,r=s.i=s.j=0,a=s.S=[];for(i||(e=[i++]);n<p;)a[n]=n++;for(n=0;n<p;n++)a[n]=a[r=d&r+e[n%i]+(t=a[n])],a[r]=t;s.g=function(e){for(var t,i=0,n=s.i,r=s.j,a=s.S;e--;)t=a[n=d&n+1],i=i*p+a[d&(a[n]=a[r=d&r+t])+(a[r]=t)];return s.i=n,s.j=r,i}}function v(e,t){return t.i=e.i,t.j=e.j,t.S=e.S.slice(),t}function y(e,t){var i,n=[],r=_typeof$1(e);if(t&&"object"==r)for(i in e)try{n.push(y(e[i],t-1))}catch(e){}return n.length?n:"string"==r?e:e+"\0"}function b(e,t){for(var i,n=e+"",r=0;r<n.length;)t[d&r]=d&(i^=19*t[d&r])+n.charCodeAt(r++);return x(t)}function x(e){return String.fromCharCode.apply(0,e)}l.seedrandom=function(e,t,i){var n=[],r=b(y((t=!0===t?{entropy:!0}:t||{}).entropy?[e,x(o)]:null===e?function(){try{u;var e=new Uint8Array(p);return(h.crypto||h.msCrypto).getRandomValues(e),x(e)}catch(e){var t=h.navigator,i=t&&t.plugins;return[+new Date,h,i,h.screen,x(o)]}}():e,3),n),a=new g(n),s=function(){for(var e=a.g(6),t=c,i=0;e<m;)e=(e+i)*p,t*=p,i=a.g(1);for(;e>=f;)e/=2,t/=2,i>>>=1;return(e+i)/t};return s.int32=function(){return 0|a.g(4)},s.quick=function(){return a.g(4)/4294967296},s.double=s,b(x(a.S),o),(t.pass||i||function(e,t,i,n){return n&&(n.S&&v(n,a),e.state=function(){return v(a,{})}),i?(l.random=e,t):e})(s,r,"global"in t?t.global:this==l,t.state)},b(l.random(),o)}function initialize$2(e){seedRandom([],e)}var propTypes={SHAPE:"shape"};function _typeof(e){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof(e)}var ExpressionManager=function(){var ob={},Math=BMMath,window=null,document=null,XMLHttpRequest=null,fetch=null,frames=null;function $bm_isInstanceOfArray(e){return e.constructor===Array||e.constructor===Float32Array}function isNumerable(e,t){return"number"===e||"boolean"===e||"string"===e||t instanceof Number}function $bm_neg(e){var t=_typeof(e);if("number"===t||"boolean"===t||e instanceof Number)return-e;if($bm_isInstanceOfArray(e)){var i,n=e.length,r=[];for(i=0;i<n;i+=1)r[i]=-e[i];return r}return e.propType?e.v:-e}initialize$2(BMMath);var easeInBez=BezierFactory.getBezierEasing(.333,0,.833,.833,"easeIn").get,easeOutBez=BezierFactory.getBezierEasing(.167,.167,.667,1,"easeOut").get,easeInOutBez=BezierFactory.getBezierEasing(.33,0,.667,1,"easeInOut").get;function sum(e,t){var i=_typeof(e),n=_typeof(t);if("string"===i||"string"===n)return e+t;if(isNumerable(i,e)&&isNumerable(n,t))return e+t;if($bm_isInstanceOfArray(e)&&isNumerable(n,t))return(e=e.slice(0))[0]+=t,e;if(isNumerable(i,e)&&$bm_isInstanceOfArray(t))return(t=t.slice(0))[0]=e+t[0],t;if($bm_isInstanceOfArray(e)&&$bm_isInstanceOfArray(t)){for(var r=0,a=e.length,s=t.length,o=[];r<a||r<s;)("number"==typeof e[r]||e[r]instanceof Number)&&("number"==typeof t[r]||t[r]instanceof Number)?o[r]=e[r]+t[r]:o[r]=void 0===t[r]?e[r]:e[r]||t[r],r+=1;return o}return 0}var add=sum;function sub(e,t){var i=_typeof(e),n=_typeof(t);if(isNumerable(i,e)&&isNumerable(n,t))return"string"===i&&(e=parseInt(e,10)),"string"===n&&(t=parseInt(t,10)),e-t;if($bm_isInstanceOfArray(e)&&isNumerable(n,t))return(e=e.slice(0))[0]-=t,e;if(isNumerable(i,e)&&$bm_isInstanceOfArray(t))return(t=t.slice(0))[0]=e-t[0],t;if($bm_isInstanceOfArray(e)&&$bm_isInstanceOfArray(t)){for(var r=0,a=e.length,s=t.length,o=[];r<a||r<s;)("number"==typeof e[r]||e[r]instanceof Number)&&("number"==typeof t[r]||t[r]instanceof Number)?o[r]=e[r]-t[r]:o[r]=void 0===t[r]?e[r]:e[r]||t[r],r+=1;return o}return 0}function mul(e,t){var i,n,r,a=_typeof(e),s=_typeof(t);if(isNumerable(a,e)&&isNumerable(s,t))return e*t;if($bm_isInstanceOfArray(e)&&isNumerable(s,t)){for(r=e.length,i=createTypedArray("float32",r),n=0;n<r;n+=1)i[n]=e[n]*t;return i}if(isNumerable(a,e)&&$bm_isInstanceOfArray(t)){for(r=t.length,i=createTypedArray("float32",r),n=0;n<r;n+=1)i[n]=e*t[n];return i}return 0}function div(e,t){var i,n,r,a=_typeof(e),s=_typeof(t);if(isNumerable(a,e)&&isNumerable(s,t))return e/t;if($bm_isInstanceOfArray(e)&&isNumerable(s,t)){for(r=e.length,i=createTypedArray("float32",r),n=0;n<r;n+=1)i[n]=e[n]/t;return i}if(isNumerable(a,e)&&$bm_isInstanceOfArray(t)){for(r=t.length,i=createTypedArray("float32",r),n=0;n<r;n+=1)i[n]=e/t[n];return i}return 0}function mod(e,t){return"string"==typeof e&&(e=parseInt(e,10)),"string"==typeof t&&(t=parseInt(t,10)),e%t}var $bm_sum=sum,$bm_sub=sub,$bm_mul=mul,$bm_div=div,$bm_mod=mod;function clamp(e,t,i){if(t>i){var n=i;i=t,t=n}return Math.min(Math.max(e,t),i)}function radiansToDegrees(e){return e/degToRads}var radians_to_degrees=radiansToDegrees;function degreesToRadians(e){return e*degToRads}var degrees_to_radians=radiansToDegrees,helperLengthArray=[0,0,0,0,0,0];function length(e,t){if("number"==typeof e||e instanceof Number)return t=t||0,Math.abs(e-t);var i;t||(t=helperLengthArray);var n=Math.min(e.length,t.length),r=0;for(i=0;i<n;i+=1)r+=Math.pow(t[i]-e[i],2);return Math.sqrt(r)}function normalize(e){return div(e,length(e))}function rgbToHsl(e){var t,i,n=e[0],r=e[1],a=e[2],s=Math.max(n,r,a),o=Math.min(n,r,a),l=(s+o)/2;if(s===o)t=0,i=0;else{var u=s-o;switch(i=l>.5?u/(2-s-o):u/(s+o),s){case n:t=(r-a)/u+(r<a?6:0);break;case r:t=(a-n)/u+2;break;case a:t=(n-r)/u+4}t/=6}return[t,i,l,e[3]]}function hue2rgb(e,t,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?e+6*(t-e)*i:i<.5?t:i<2/3?e+(t-e)*(2/3-i)*6:e}function hslToRgb(e){var t,i,n,r=e[0],a=e[1],s=e[2];if(0===a)t=s,n=s,i=s;else{var o=s<.5?s*(1+a):s+a-s*a,l=2*s-o;t=hue2rgb(l,o,r+1/3),i=hue2rgb(l,o,r),n=hue2rgb(l,o,r-1/3)}return[t,i,n,e[3]]}function linear(e,t,i,n,r){if(void 0!==n&&void 0!==r||(n=t,r=i,t=0,i=1),i<t){var a=i;i=t,t=a}if(e<=t)return n;if(e>=i)return r;var s,o=i===t?0:(e-t)/(i-t);if(!n.length)return n+(r-n)*o;var l=n.length,u=createTypedArray("float32",l);for(s=0;s<l;s+=1)u[s]=n[s]+(r[s]-n[s])*o;return u}function random(e,t){if(void 0===t&&(void 0===e?(e=0,t=1):(t=e,e=void 0)),t.length){var i,n=t.length;e||(e=createTypedArray("float32",n));var r=createTypedArray("float32",n),a=BMMath.random();for(i=0;i<n;i+=1)r[i]=e[i]+a*(t[i]-e[i]);return r}return void 0===e&&(e=0),e+BMMath.random()*(t-e)}function createPath(e,t,i,n){var r,a=e.length,s=shapePool.newElement();s.setPathData(!!n,a);var o,l,u=[0,0];for(r=0;r<a;r+=1)o=t&&t[r]?t[r]:u,l=i&&i[r]?i[r]:u,s.setTripleAt(e[r][0],e[r][1],l[0]+e[r][0],l[1]+e[r][1],o[0]+e[r][0],o[1]+e[r][1],r,!0);return s}function initiateExpression(elem,data,property){function noOp(e){return e}if(!elem.globalData.renderConfig.runExpressions)return noOp;var val=data.x,needsVelocity=/velocity(?![\w\d])/.test(val),_needsRandom=-1!==val.indexOf("random"),elemType=elem.data.ty,transform,$bm_transform,content,effect,thisProperty=property;thisProperty.valueAtTime=thisProperty.getValueAtTime,Object.defineProperty(thisProperty,"value",{get:function(){return thisProperty.v}}),elem.comp.frameDuration=1/elem.comp.globalData.frameRate,elem.comp.displayStartTime=0;var inPoint=elem.data.ip/elem.comp.globalData.frameRate,outPoint=elem.data.op/elem.comp.globalData.frameRate,width=elem.data.sw?elem.data.sw:0,height=elem.data.sh?elem.data.sh:0,name=elem.data.nm,loopIn,loop_in,loopOut,loop_out,smooth,toWorld,fromWorld,fromComp,toComp,fromCompToSurface,position,rotation,anchorPoint,scale,thisLayer,thisComp,mask,valueAtTime,velocityAtTime,scoped_bm_rt,expression_function=eval("[function _expression_function(){"+val+";scoped_bm_rt=$bm_rt}]")[0],numKeys=property.kf?data.k.length:0,active=!this.data||!0!==this.data.hd,wiggle=function(e,t){var i,n,r=this.pv.length?this.pv.length:1,a=createTypedArray("float32",r);var s=Math.floor(5*time);for(i=0,n=0;i<s;){for(n=0;n<r;n+=1)a[n]+=-t+2*t*BMMath.random();i+=1}var o=5*time,l=o-Math.floor(o),u=createTypedArray("float32",r);if(r>1){for(n=0;n<r;n+=1)u[n]=this.pv[n]+a[n]+(-t+2*t*BMMath.random())*l;return u}return this.pv+a[0]+(-t+2*t*BMMath.random())*l}.bind(this);function loopInDuration(e,t){return loopIn(e,t,!0)}function loopOutDuration(e,t){return loopOut(e,t,!0)}thisProperty.loopIn&&(loopIn=thisProperty.loopIn.bind(thisProperty),loop_in=loopIn),thisProperty.loopOut&&(loopOut=thisProperty.loopOut.bind(thisProperty),loop_out=loopOut),thisProperty.smooth&&(smooth=thisProperty.smooth.bind(thisProperty)),this.getValueAtTime&&(valueAtTime=this.getValueAtTime.bind(this)),this.getVelocityAtTime&&(velocityAtTime=this.getVelocityAtTime.bind(this));var comp=elem.comp.globalData.projectInterface.bind(elem.comp.globalData.projectInterface),time,velocity,value,text,textIndex,textTotal,selectorValue;function lookAt(e,t){var i=[t[0]-e[0],t[1]-e[1],t[2]-e[2]],n=Math.atan2(i[0],Math.sqrt(i[1]*i[1]+i[2]*i[2]))/degToRads;return[-Math.atan2(i[1],i[2])/degToRads,n,0]}function easeOut(e,t,i,n,r){return applyEase(easeOutBez,e,t,i,n,r)}function easeIn(e,t,i,n,r){return applyEase(easeInBez,e,t,i,n,r)}function ease(e,t,i,n,r){return applyEase(easeInOutBez,e,t,i,n,r)}function applyEase(e,t,i,n,r,a){void 0===r?(r=i,a=n):t=(t-i)/(n-i),t>1?t=1:t<0&&(t=0);var s=e(t);if($bm_isInstanceOfArray(r)){var o,l=r.length,u=createTypedArray("float32",l);for(o=0;o<l;o+=1)u[o]=(a[o]-r[o])*s+r[o];return u}return(a-r)*s+r}function nearestKey(e){var t,i,n,r=data.k.length;if(data.k.length&&"number"!=typeof data.k[0])if(i=-1,(e*=elem.comp.globalData.frameRate)<data.k[0].t)i=1,n=data.k[0].t;else{for(t=0;t<r-1;t+=1){if(e===data.k[t].t){i=t+1,n=data.k[t].t;break}if(e>data.k[t].t&&e<data.k[t+1].t){e-data.k[t].t>data.k[t+1].t-e?(i=t+2,n=data.k[t+1].t):(i=t+1,n=data.k[t].t);break}}-1===i&&(i=t+1,n=data.k[t].t)}else i=0,n=0;var a={};return a.index=i,a.time=n/elem.comp.globalData.frameRate,a}function key(e){var t,i,n;if(!data.k.length||"number"==typeof data.k[0])throw new Error("The property has no keyframe at index "+e);e-=1,t={time:data.k[e].t/elem.comp.globalData.frameRate,value:[]};var r=Object.prototype.hasOwnProperty.call(data.k[e],"s")?data.k[e].s:data.k[e-1].e;for(n=r.length,i=0;i<n;i+=1)t[i]=r[i],t.value[i]=r[i];return t}function framesToTime(e,t){return t||(t=elem.comp.globalData.frameRate),e/t}function timeToFrames(e,t){return e||0===e||(e=time),t||(t=elem.comp.globalData.frameRate),e*t}function seedRandom(e){BMMath.seedrandom(randSeed+e)}function sourceRectAtTime(){return elem.sourceRectAtTime()}function substring(e,t){return"string"==typeof value?void 0===t?value.substring(e):value.substring(e,t):""}function substr(e,t){return"string"==typeof value?void 0===t?value.substr(e):value.substr(e,t):""}function posterizeTime(e){time=0===e?0:Math.floor(time*e)/e,value=valueAtTime(time)}var index=elem.data.ind,hasParent=!(!elem.hierarchy||!elem.hierarchy.length),parent,randSeed=Math.floor(1e6*Math.random()),globalData=elem.globalData;function executeExpression(e){return value=e,this.frameExpressionId===elem.globalData.frameId&&"textSelector"!==this.propType?value:("textSelector"===this.propType&&(textIndex=this.textIndex,textTotal=this.textTotal,selectorValue=this.selectorValue),thisLayer||(text=elem.layerInterface.text,thisLayer=elem.layerInterface,thisComp=elem.comp.compInterface,toWorld=thisLayer.toWorld.bind(thisLayer),fromWorld=thisLayer.fromWorld.bind(thisLayer),fromComp=thisLayer.fromComp.bind(thisLayer),toComp=thisLayer.toComp.bind(thisLayer),mask=thisLayer.mask?thisLayer.mask.bind(thisLayer):null,fromCompToSurface=fromComp),transform||(transform=elem.layerInterface("ADBE Transform Group"),$bm_transform=transform,transform&&(anchorPoint=transform.anchorPoint)),4!==elemType||content||(content=thisLayer("ADBE Root Vectors Group")),effect||(effect=thisLayer(4)),(hasParent=!(!elem.hierarchy||!elem.hierarchy.length))&&!parent&&(parent=elem.hierarchy[0].layerInterface),time=this.comp.renderedFrame/this.comp.globalData.frameRate,_needsRandom&&seedRandom(randSeed+time),needsVelocity&&(velocity=velocityAtTime(time)),expression_function(),this.frameExpressionId=elem.globalData.frameId,scoped_bm_rt=scoped_bm_rt.propType===propTypes.SHAPE?scoped_bm_rt.v:scoped_bm_rt)}return executeExpression.__preventDeadCodeRemoval=[$bm_transform,anchorPoint,time,velocity,inPoint,outPoint,width,height,name,loop_in,loop_out,smooth,toComp,fromCompToSurface,toWorld,fromWorld,mask,position,rotation,scale,thisComp,numKeys,active,wiggle,loopInDuration,loopOutDuration,comp,lookAt,easeOut,easeIn,ease,nearestKey,key,text,textIndex,textTotal,selectorValue,framesToTime,timeToFrames,sourceRectAtTime,substring,substr,posterizeTime,index,globalData],executeExpression}return ob.initiateExpression=initiateExpression,ob.__preventDeadCodeRemoval=[window,document,XMLHttpRequest,fetch,frames,$bm_neg,add,$bm_sum,$bm_sub,$bm_mul,$bm_div,$bm_mod,clamp,radians_to_degrees,degreesToRadians,degrees_to_radians,normalize,rgbToHsl,hslToRgb,linear,random,createPath],ob}(),expressionHelpers={searchExpressions:function(e,t,i){t.x&&(i.k=!0,i.x=!0,i.initiateExpression=ExpressionManager.initiateExpression,i.effectsSequence.push(i.initiateExpression(e,t,i).bind(i)))},getSpeedAtTime:function(e){var t=this.getValueAtTime(e),i=this.getValueAtTime(e+-.01),n=0;if(t.length){var r;for(r=0;r<t.length;r+=1)n+=Math.pow(i[r]-t[r],2);n=100*Math.sqrt(n)}else n=0;return n},getVelocityAtTime:function(e){if(void 0!==this.vel)return this.vel;var t,i,n=-.001,r=this.getValueAtTime(e),a=this.getValueAtTime(e+n);if(r.length)for(t=createTypedArray("float32",r.length),i=0;i<r.length;i+=1)t[i]=(a[i]-r[i])/n;else t=(a-r)/n;return t},getValueAtTime:function(e){return e*=this.elem.globalData.frameRate,(e-=this.offsetTime)!==this._cachingAtTime.lastFrame&&(this._cachingAtTime.lastIndex=this._cachingAtTime.lastFrame<e?this._cachingAtTime.lastIndex:0,this._cachingAtTime.value=this.interpolateValue(e,this._cachingAtTime),this._cachingAtTime.lastFrame=e),this._cachingAtTime.value},getStaticValueAtTime:function(){return this.pv},setGroupProperty:function(e){this.propertyGroup=e}};function addPropertyDecorator(){function o(e,t,i){if(!this.k||!this.keyframes)return this.pv;e=e?e.toLowerCase():"";var n,r,a,s,o,l=this.comp.renderedFrame,u=this.keyframes,h=u[u.length-1].t;if(l<=h)return this.pv;if(i?r=h-(n=t?Math.abs(h-this.elem.comp.globalData.frameRate*t):Math.max(0,h-this.elem.data.ip)):((!t||t>u.length-1)&&(t=u.length-1),n=h-(r=u[u.length-1-t].t)),"pingpong"===e){if(Math.floor((l-r)/n)%2!=0)return this.getValueAtTime((n-(l-r)%n+r)/this.comp.globalData.frameRate,0)}else{if("offset"===e){var p=this.getValueAtTime(r/this.comp.globalData.frameRate,0),c=this.getValueAtTime(h/this.comp.globalData.frameRate,0),m=this.getValueAtTime(((l-r)%n+r)/this.comp.globalData.frameRate,0),f=Math.floor((l-r)/n);if(this.pv.length){for(s=(o=new Array(p.length)).length,a=0;a<s;a+=1)o[a]=(c[a]-p[a])*f+m[a];return o}return(c-p)*f+m}if("continue"===e){var d=this.getValueAtTime(h/this.comp.globalData.frameRate,0),g=this.getValueAtTime((h-.001)/this.comp.globalData.frameRate,0);if(this.pv.length){for(s=(o=new Array(d.length)).length,a=0;a<s;a+=1)o[a]=d[a]+(d[a]-g[a])*((l-h)/this.comp.globalData.frameRate)/5e-4;return o}return d+(l-h)/.001*(d-g)}}return this.getValueAtTime(((l-r)%n+r)/this.comp.globalData.frameRate,0)}function l(e,t,i){if(!this.k)return this.pv;e=e?e.toLowerCase():"";var n,r,a,s,o,l=this.comp.renderedFrame,u=this.keyframes,h=u[0].t;if(l>=h)return this.pv;if(i?r=h+(n=t?Math.abs(this.elem.comp.globalData.frameRate*t):Math.max(0,this.elem.data.op-h)):((!t||t>u.length-1)&&(t=u.length-1),n=(r=u[t].t)-h),"pingpong"===e){if(Math.floor((h-l)/n)%2==0)return this.getValueAtTime(((h-l)%n+h)/this.comp.globalData.frameRate,0)}else{if("offset"===e){var p=this.getValueAtTime(h/this.comp.globalData.frameRate,0),c=this.getValueAtTime(r/this.comp.globalData.frameRate,0),m=this.getValueAtTime((n-(h-l)%n+h)/this.comp.globalData.frameRate,0),f=Math.floor((h-l)/n)+1;if(this.pv.length){for(s=(o=new Array(p.length)).length,a=0;a<s;a+=1)o[a]=m[a]-(c[a]-p[a])*f;return o}return m-(c-p)*f}if("continue"===e){var d=this.getValueAtTime(h/this.comp.globalData.frameRate,0),g=this.getValueAtTime((h+.001)/this.comp.globalData.frameRate,0);if(this.pv.length){for(s=(o=new Array(d.length)).length,a=0;a<s;a+=1)o[a]=d[a]+(d[a]-g[a])*(h-l)/.001;return o}return d+(d-g)*(h-l)/.001}}return this.getValueAtTime((n-((h-l)%n+h))/this.comp.globalData.frameRate,0)}function u(e,t){if(!this.k)return this.pv;if(e=.5*(e||.4),(t=Math.floor(t||5))<=1)return this.pv;var i,n,r=this.comp.renderedFrame/this.comp.globalData.frameRate,a=r-e,s=t>1?(r+e-a)/(t-1):1,o=0,l=0;for(i=this.pv.length?createTypedArray("float32",this.pv.length):0;o<t;){if(n=this.getValueAtTime(a+o*s),this.pv.length)for(l=0;l<this.pv.length;l+=1)i[l]+=n[l];else i+=n;o+=1}if(this.pv.length)for(l=0;l<this.pv.length;l+=1)i[l]/=t;else i/=t;return i}function r(e){this._transformCachingAtTime||(this._transformCachingAtTime={v:new Matrix});var t=this._transformCachingAtTime.v;if(t.cloneFromProps(this.pre.props),this.appliedTransformations<1){var i=this.a.getValueAtTime(e);t.translate(-i[0]*this.a.mult,-i[1]*this.a.mult,i[2]*this.a.mult)}if(this.appliedTransformations<2){var n=this.s.getValueAtTime(e);t.scale(n[0]*this.s.mult,n[1]*this.s.mult,n[2]*this.s.mult)}if(this.sk&&this.appliedTransformations<3){var r=this.sk.getValueAtTime(e),a=this.sa.getValueAtTime(e);t.skewFromAxis(-r*this.sk.mult,a*this.sa.mult)}if(this.r&&this.appliedTransformations<4){var s=this.r.getValueAtTime(e);t.rotate(-s*this.r.mult)}else if(!this.r&&this.appliedTransformations<4){var o=this.rz.getValueAtTime(e),l=this.ry.getValueAtTime(e),u=this.rx.getValueAtTime(e),h=this.or.getValueAtTime(e);t.rotateZ(-o*this.rz.mult).rotateY(l*this.ry.mult).rotateX(u*this.rx.mult).rotateZ(-h[2]*this.or.mult).rotateY(h[1]*this.or.mult).rotateX(h[0]*this.or.mult)}if(this.data.p&&this.data.p.s){var p=this.px.getValueAtTime(e),c=this.py.getValueAtTime(e);if(this.data.p.z){var m=this.pz.getValueAtTime(e);t.translate(p*this.px.mult,c*this.py.mult,-m*this.pz.mult)}else t.translate(p*this.px.mult,c*this.py.mult,0)}else{var f=this.p.getValueAtTime(e);t.translate(f[0]*this.p.mult,f[1]*this.p.mult,-f[2]*this.p.mult)}return t}function a(){return this.v.clone(new Matrix)}var s=TransformPropertyFactory.getTransformProperty;TransformPropertyFactory.getTransformProperty=function(e,t,i){var n=s(e,t,i);return n.dynamicProperties.length?n.getValueAtTime=r.bind(n):n.getValueAtTime=a.bind(n),n.setGroupProperty=expressionHelpers.setGroupProperty,n};var h=PropertyFactory.getProp;PropertyFactory.getProp=function(e,t,i,n,r){var a=h(e,t,i,n,r);a.kf?a.getValueAtTime=expressionHelpers.getValueAtTime.bind(a):a.getValueAtTime=expressionHelpers.getStaticValueAtTime.bind(a),a.setGroupProperty=expressionHelpers.setGroupProperty,a.loopOut=o,a.loopIn=l,a.smooth=u,a.getVelocityAtTime=expressionHelpers.getVelocityAtTime.bind(a),a.getSpeedAtTime=expressionHelpers.getSpeedAtTime.bind(a),a.numKeys=1===t.a?t.k.length:0,a.propertyIndex=t.ix;var s=0;return 0!==i&&(s=createTypedArray("float32",1===t.a?t.k[0].s.length:t.k.length)),a._cachingAtTime={lastFrame:initialDefaultFrame,lastIndex:0,value:s},expressionHelpers.searchExpressions(e,t,a),a.k&&r.addDynamicProperty(a),a};var e=ShapePropertyFactory.getConstructorFunction(),t=ShapePropertyFactory.getKeyframedConstructorFunction();function i(){}i.prototype={vertices:function(e,t){this.k&&this.getValue();var i,n=this.v;void 0!==t&&(n=this.getValueAtTime(t,0));var r=n._length,a=n[e],s=n.v,o=createSizedArray(r);for(i=0;i<r;i+=1)o[i]="i"===e||"o"===e?[a[i][0]-s[i][0],a[i][1]-s[i][1]]:[a[i][0],a[i][1]];return o},points:function(e){return this.vertices("v",e)},inTangents:function(e){return this.vertices("i",e)},outTangents:function(e){return this.vertices("o",e)},isClosed:function(){return this.v.c},pointOnPath:function(e,t){var i=this.v;void 0!==t&&(i=this.getValueAtTime(t,0)),this._segmentsLength||(this._segmentsLength=bez.getSegmentsLength(i));for(var n,r=this._segmentsLength,a=r.lengths,s=r.totalLength*e,o=0,l=a.length,u=0;o<l;){if(u+a[o].addedLength>s){var h=o,p=i.c&&o===l-1?0:o+1,c=(s-u)/a[o].addedLength;n=bez.getPointInSegment(i.v[h],i.v[p],i.o[h],i.i[p],c,a[o]);break}u+=a[o].addedLength,o+=1}return n||(n=i.c?[i.v[0][0],i.v[0][1]]:[i.v[i._length-1][0],i.v[i._length-1][1]]),n},vectorOnPath:function(e,t,i){1==e?e=this.v.c:0==e&&(e=.999);var n=this.pointOnPath(e,t),r=this.pointOnPath(e+.001,t),a=r[0]-n[0],s=r[1]-n[1],o=Math.sqrt(Math.pow(a,2)+Math.pow(s,2));return 0===o?[0,0]:"tangent"===i?[a/o,s/o]:[-s/o,a/o]},tangentOnPath:function(e,t){return this.vectorOnPath(e,t,"tangent")},normalOnPath:function(e,t){return this.vectorOnPath(e,t,"normal")},setGroupProperty:expressionHelpers.setGroupProperty,getValueAtTime:expressionHelpers.getStaticValueAtTime},extendPrototype([i],e),extendPrototype([i],t),t.prototype.getValueAtTime=function(e){return this._cachingAtTime||(this._cachingAtTime={shapeValue:shapePool.clone(this.pv),lastIndex:0,lastTime:initialDefaultFrame}),e*=this.elem.globalData.frameRate,(e-=this.offsetTime)!==this._cachingAtTime.lastTime&&(this._cachingAtTime.lastIndex=this._cachingAtTime.lastTime<e?this._caching.lastIndex:0,this._cachingAtTime.lastTime=e,this.interpolateShape(e,this._cachingAtTime.shapeValue,this._cachingAtTime)),this._cachingAtTime.shapeValue},t.prototype.initiateExpression=ExpressionManager.initiateExpression;var p=ShapePropertyFactory.getShapeProp;ShapePropertyFactory.getShapeProp=function(e,t,i,n,r){var a=p(e,t,i,n,r);return a.propertyIndex=t.ix,a.lock=!1,3===i?expressionHelpers.searchExpressions(e,t.pt,a):4===i&&expressionHelpers.searchExpressions(e,t.ks,a),a.k&&e.addDynamicProperty(a),a}}function initialize$1(){addPropertyDecorator()}function addDecorator(){TextProperty.prototype.getExpressionValue=function(e,t){var i=this.calculateExpression(t);if(e.t!==i){var n={};return this.copyData(n,e),n.t=i.toString(),n.__complete=!1,n}return e},TextProperty.prototype.searchProperty=function(){var e=this.searchKeyframes(),t=this.searchExpressions();return this.kf=e||t,this.kf},TextProperty.prototype.searchExpressions=function(){return this.data.d.x?(this.calculateExpression=ExpressionManager.initiateExpression.bind(this)(this.elem,this.data.d,this),this.addEffect(this.getExpressionValue.bind(this)),!0):null}}function initialize(){addDecorator()}return setExpressionsPlugin(Expressions),setExpressionInterfaces(getInterface),initialize$1(),initialize(),lottie});(()=>{"use strict";var e={};const s={ANIM:{EASINGS:["linear","absolute","smoothstep","smootherstep","Cubic In","Cubic Out","Cubic In Out","Expo In","Expo Out","Expo In Out","Sin In","Sin Out","Sin In Out","Quart In","Quart Out","Quart In Out","Quint In","Quint Out","Quint In Out","Back In","Back Out","Back In Out","Elastic In","Elastic Out","Bounce In","Bounce Out"],EASING_LINEAR:0,EASING_ABSOLUTE:1,EASING_SMOOTHSTEP:2,EASING_SMOOTHERSTEP:3,EASING_CUBICSPLINE:4,EASING_CUBIC_IN:5,EASING_CUBIC_OUT:6,EASING_CUBIC_INOUT:7,EASING_EXPO_IN:8,EASING_EXPO_OUT:9,EASING_EXPO_INOUT:10,EASING_SIN_IN:11,EASING_SIN_OUT:12,EASING_SIN_INOUT:13,EASING_BACK_IN:14,EASING_BACK_OUT:15,EASING_BACK_INOUT:16,EASING_ELASTIC_IN:17,EASING_ELASTIC_OUT:18,EASING_BOUNCE_IN:19,EASING_BOUNCE_OUT:21,EASING_QUART_IN:22,EASING_QUART_OUT:23,EASING_QUART_INOUT:24,EASING_QUINT_IN:25,EASING_QUINT_OUT:26,EASING_QUINT_INOUT:27},OP:{OP_PORT_TYPE_VALUE:0,OP_PORT_TYPE_NUMBER:0,OP_PORT_TYPE_FUNCTION:1,OP_PORT_TYPE_TRIGGER:1,OP_PORT_TYPE_OBJECT:2,OP_PORT_TYPE_TEXTURE:2,OP_PORT_TYPE_ARRAY:3,OP_PORT_TYPE_DYNAMIC:4,OP_PORT_TYPE_STRING:5,OP_VERSION_PREFIX:"_v"},PORT:{PORT_DIR_IN:0,PORT_DIR_OUT:1},PACO:{PACO_CLEAR:0,PACO_VALUECHANGE:1,PACO_OP_DELETE:2,PACO_UNLINK:3,PACO_LINK:4,PACO_LOAD:5,PACO_OP_CREATE:6,PACO_OP_ENABLE:7,PACO_OP_DISABLE:8,PACO_UIATTRIBS:9,PACO_VARIABLES:10,PACO_TRIGGERS:11,PACO_PORT_SETVARIABLE:12,PACO_PORT_SETANIMATED:13,PACO_PORT_ANIM_UPDATED:14,PACO_DESERIALIZE:15,PACO_OP_RELOAD:16}};const t=class{constructor(t,e,i,n,r,a){this._valuePort=i;this._varNamePort=n;this._op=t;this._type=e;this._typeId=-1;this._triggerPort=r;this._nextPort=a;this._btnCreate=t.inTriggerButton("Create new variable");this._btnCreate.setUiAttribs({hidePort:true});this._btnCreate.onTriggered=this._createVar.bind(this);this._helper=t.inUiTriggerButtons("",["Rename"]);this._helper.setUiAttribs({hidePort:true});this._helper.onTriggered=e=>{if(e=="Rename")CABLES.CMD.PATCH.renameVariable(t.varName.get())};this._op.setPortGroup("Variable",[this._helper,this._varNamePort,this._btnCreate]);n.setUiAttribs({_variableSelect:true});this._op.on("uiParamPanel",this._updateVarNamesDropdown.bind(this));this._op.patch.addEventListener("variablesChanged",this._updateName.bind(this));this._op.patch.addEventListener("variableRename",this._renameVar.bind(this));this._varNamePort.onChange=this._updateName.bind(this);this._isTexture=this._valuePort.uiAttribs.objType==="texture";this._valuePort.changeAlways=true;if(this._triggerPort){this._triggerPort.onTriggered=()=>{this._setVarValue(true)}}else{this._valuePort.onChange=this._setVarValue.bind(this)}this._op.init=()=>{this._updateName();if(!this._triggerPort)this._setVarValue();this._updateErrorUi()};if(e=="array")this._typeId=s.OP.OP_PORT_TYPE_ARRAY;else if(e=="object")this._typeId=s.OP.OP_PORT_TYPE_OBJECT;else if(e=="string")this._typeId=s.OP.OP_PORT_TYPE_STRING;else if(e=="texture")this._typeId=s.OP.OP_PORT_TYPE_TEXTURE;else this._typeId=s.OP.OP_PORT_TYPE_VALUE}_updateErrorUi(){if(CABLES.UI){if(!this._varNamePort.get())this._op.setUiError("novarname","no variable selected");else{if(this._op.hasUiErrors){this._op.setUiError("novarname",null)}}}}_updateName(){const e=this._varNamePort.get();this._op.setTitle("var set");this._op.setUiAttrib({extendTitle:"#"+e});this._updateErrorUi();const t=this._op.patch.getVar(e);if(t&&!t.type)t.type=this._type;if(!this._op.patch.hasVar(e)&&e!=0&&!this._triggerPort){this._setVarValue()}if(!this._op.patch.hasVar(e)&&e!=0&&this._triggerPort){if(this._type=="string")this._op.patch.setVarValue(e,"");else if(this._type=="number")this._op.patch.setVarValue(e,"");else this._op.patch.setVarValue(e,null)}if(this._op.isCurrentUiOp()){this._updateVarNamesDropdown();this._op.refreshParams()}this._updateDisplay();this._op.patch.emitEvent("opVariableNameChanged",this._op,this._varNamePort.get())}_createVar(){CABLES.CMD.PATCH.createVariable(this._op,this._type,()=>{this._updateName()})}_updateDisplay(){this._valuePort.setUiAttribs({greyout:!this._varNamePort.get()})}_updateVarNamesDropdown(){if(CABLES.UI&&CABLES.UI.loaded&&CABLES.UI.loaded){const e=CABLES.UI.uiProfiler.start("[vars] _updateVarNamesDropdown");const t=[];const i=this._op.patch.getVars();for(const n in i)if(i[n].type==this._type&&n!="0")t.push(n);this._varNamePort.uiAttribs.values=t;e.finish()}}_renameVar(e,t){if(e!=this._varNamePort.get())return;this._varNamePort.set(t);this._updateName()}_setVarValue(e){const t=this._varNamePort.get();if(!t)return;const i=this._valuePort.get();if(this._typeId==s.OP.OP_PORT_TYPE_VALUE||this._typeId==s.OP.OP_PORT_TYPE_STRING){this._op.patch.setVarValue(t,i)}else if(this._typeId==s.OP.OP_PORT_TYPE_ARRAY){this._arr=[];CABLES.copyArray(i,this._arr);this._op.patch.setVarValue(t,this._arr)}else{if(this._typeId==s.OP.OP_PORT_TYPE_OBJECT){if(this._isTexture)this._op.patch.setVarValue(t,CGL.Texture.getEmptyTexture(this._op.patch.cgl));else this._op.patch.setVarValue(t,null);if(i&&i.tex&&i._cgl&&!this._isTexture)this._op.setUiError("texobj","Dont use object variables for textures, use varSetTexture");else this._op.setUiError("texobj",null)}this._op.patch.setVarValue(t,i)}if(e&&this._nextPort)this._nextPort.trigger()}};const i=class{constructor(e,t,i,n){this._op=e;this._type=t;this._varnamePort=i;this._variable=null;this._valueOutPort=n;this._listenerId=null;this._op.on("uiParamPanel",this._updateVarNamesDropdown.bind(this));this._op.on("uiErrorChange",this._updateTitle.bind(this));this._op.patch.on("variableRename",this._renameVar.bind(this));this._op.patch.on("variableDeleted",e=>{if(this._op.isCurrentUiOp())this._op.refreshParams()});i.setUiAttribs({_variableSelect:true});i.setUiAttribs({_variableSelectGet:true});this._varnamePort.onChange=this._changeVar.bind(this);this._op.patch.addEventListener("variablesChanged",this._init.bind(this));this._op.onDelete=()=>{if(this._variable&&this._listenerId)this._variable.off(this._listenerId)};this._op.init=()=>{this._init()}}get variable(){return this._variable}_changeVar(){if(this._variable&&this._listenerId){this._variable.off(this._listenerId)}this._init()}_renameVar(e,t){if(e!=this._varnamePort.get())return;this._varnamePort.set(t);this._updateVarNamesDropdown();this._updateTitle();this._listenerId=this._variable.on("change",this._setValueOut.bind(this))}_updateVarNamesDropdown(){if(CABLES.UI&&CABLES.UI.loaded){const e=[];const t=this._op.patch.getVars();for(const i in t)if(t[i].type==this._type&&i!="0")e.push(i);this._op.varName.uiAttribs.values=e}}_setValueOut(e){if(this._valueOutPort)if(this._typeId==s.OP.OP_PORT_TYPE_ARRAY&&this._typeId==s.OP.OP_PORT_TYPE_OBJECT)this._valueOutPort.setRef(e);else this._valueOutPort.set(e)}_updateTitle(){if(this._variable){this._op.setUiError("unknownvar",null);this._op.setTitle("var get");this._op.setUiAttrib({extendTitle:"#"+this._varnamePort.get()});if(this._valueOutPort)this._valueOutPort.set(this._variable.getValue())}else{this._op.setUiError("unknownvar","unknown variable! - there is no setVariable with this name ("+this._varnamePort.get()+")");this._op.setUiAttrib({extendTitle:"#invalid"});if(this._valueOutPort)this._valueOutPort.set(0)}}_init(){this._updateVarNamesDropdown();if(this._variable&&this._listenerId)this._variable.off(this._listenerId);this._variable=this._op.patch.getVar(this._op.varName.get());if(this._variable)this._listenerId=this._variable.on("change",this._setValueOut.bind(this));this._updateTitle();this._op.patch.emitEvent("opVariableNameChanged",this._op,this._varnamePort.get())}};CABLES.VarSetOpWrapper=t;CABLES.VarGetOpWrapper=i;((this.CABLES=this.CABLES||{}).COREMODULES=this.CABLES.COREMODULES||{}).Vargetset=e.Cables})();(()=>{"use strict";var e={};const t=class{constructor(){this.patch=null;this.fsElement=null;this.callbacks={}}add(e,t,i){this.patch=e;this.callbacks[t]=i;this.show()}remove(e){delete this.callbacks[e];if(Object.keys(this.callbacks).length==0){if(this.fsElement)this.fsElement.remove();this.fsElement=null}}show(){if(!this.fsElement){this.fsElement=document.createElement("div");const e=this.patch.cgl.canvas.parentElement;if(e)e.appendChild(this.fsElement);this.fsElement.addEventListener("pointerdown",e=>{for(const t in this.callbacks)this.callbacks[t]()})}this.fsElement.style.padding="10px";this.fsElement.style.position="absolute";this.fsElement.style.right="20px";this.fsElement.style.bottom="20px";this.fsElement.style.width="24px";this.fsElement.style.height="24px";this.fsElement.style.cursor="pointer";this.fsElement.style["border-radius"]="40px";this.fsElement.style.background="#444";this.fsElement.style["z-index"]="9999";this.fsElement.style.display="block";this.fsElement.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather feather-volume-2"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon><path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path></svg>'}};CABLES.interActionNeededButton=CABLES.interActionNeededButton||new t;((this.CABLES=this.CABLES||{}).COREMODULES=this.CABLES.COREMODULES||{}).Interactionneededbutton=e.Cables})();(()=>{"use strict";var e={};class h{constructor(e,t){this.initiator=e;this._options=t}stack(e){console.info("["+this.initiator+"] ",e);console.log((new Error).stack)}groupCollapsed(e){if(CABLES.UI&&CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:0},...arguments)||!CABLES.logSilent)console.log("["+this.initiator+"]",...arguments);console.groupCollapsed("["+this.initiator+"] "+e)}table(e){console.table(e)}groupEnd(){console.groupEnd()}error(){if(CABLES.UI&&CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:2},...arguments)||!CABLES.UI){console.error("["+this.initiator+"]",...arguments)}if(this._options&&this._options.onError){this._options.onError(this.initiator,...arguments)}}errorGui(){if(CABLES.UI)CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:2},...arguments)}warn(){if(CABLES.UI&&CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:1},...arguments)||!CABLES.logSilent)console.warn("["+this.initiator+"]",...arguments)}verbose(){if(CABLES.UI&&CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:0},...arguments)||!CABLES.logSilent)console.log("["+this.initiator+"]",...arguments)}info(){if(CABLES.UI&&CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:0},...arguments)||!CABLES.logSilent)console.info("["+this.initiator+"]",...arguments)}log(){if(CABLES.UI&&CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:0},...arguments)||!CABLES.logSilent)console.log("["+this.initiator+"]",...arguments)}logGui(){if(CABLES.UI)CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:0},...arguments)}userInteraction(e){}}const r={};r.float32Concat=function(e,t){if(!(e instanceof Float32Array))e=new Float32Array(e);if(!(t instanceof Float32Array))t=new Float32Array(t);const i=new Float32Array(e.length+t.length);i.set(e);i.set(t,e.length);return i};const V=function(e){let t=e.split(".")[e.split(".").length-1];if(t.contains(CONSTANTS.OP.OP_VERSION_PREFIX)){const i=t.split(CONSTANTS.OP.OP_VERSION_PREFIX)[1];t=t.substring(0,t.length-(CONSTANTS.OP.OP_VERSION_PREFIX+i).length)}return t};const D=function(t){for(let e=t.length-1;e>0;e--){const i=Math.floor(Math.seededRandom()*(e+1));const n=t[e];t[e]=t[i];t[i]=n}return t};const t={};const i=function(){let e=Math.random().toString(36).substr(2,9);if(t.hasOwnProperty(e))e=i();t[e]=true;return e};const B=null&&i;const n=function(){let i=(new Date).getTime();const e="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=(i+Math.random()*16)%16|0;i=Math.floor(i/16);return(e=="x"?t:t&3|8).toString(16)});return e};const j=null&&n;const F=null&&n;function a(e){for(const t in e){if(e[t]&&typeof objValue==="object"&&e[t].constructor===Object)e[t]=a(e[t]);if(e[t]===null||e[t]===undefined)delete e[t];else if(Array.isArray(e[t])&&e[t].length==0)delete e[t]}return e}const s=function(i,e="id"){let n=0;if(Array.prototype.reduce){n=i.split("").reduce((e,t)=>{e=(e<<5)-e+t.charCodeAt(0);return e&e},0)}else{if(i.length>0){for(let t=0;t<i.length;t++){let e=i.charCodeAt(t);n=(n<<5)-n+e;n&=n}}}return e+""+n};const U=null&&s;let o=0;const G=function(){o++;return o};const z=function(e){const t=Math.max(0,Math.min(1,(e-0)/(1-0)));e=t*t*(3-2*t);return e};const q=function(e){const t=Math.max(0,Math.min(1,(e-0)/(1-0)));e=t*t*t*(t*(t*6-15)+10);return e};const X=function(e,t,i){return Math.min(Math.max(e,t),i)};const H=function(e,t,i,n,r,a){if(e>=i)return r;if(e<=t)return n;let s=false;const o=Math.min(t,i);const l=Math.max(t,i);if(o!=t)s=true;let u=false;const h=Math.min(n,r);const p=Math.max(n,r);if(h!=n)u=true;let c=0;let m=0;if(s)c=(l-e)*(p-h)/(l-o);else c=(e-o)*(p-h)/(l-o);if(u)m=p-c;else m=c+h;if(!a)return m;if(a==1){e=Math.max(0,Math.min(1,(m-n)/(r-n)));return n+e*e*(3-2*e)*(r-n)}if(a==2){e=Math.max(0,Math.min(1,(m-n)/(r-n)));return n+e*e*e*(e*(e*6-15)+10)*(r-n)}return m};Math.randomSeed=1;Math.setRandomSeed=function(e){Math.randomSeed=e*50728129;if(e!=0){Math.randomSeed=Math.seededRandom()*17624813;Math.randomSeed=Math.seededRandom()*9737333}};Math.seededRandom=function(e,t){if(Math.randomSeed===0)Math.randomSeed=Math.random()*999;e=e||1;t=t||0;Math.randomSeed=(Math.randomSeed*9301+49297)%233280;const i=Math.randomSeed/233280;return t+i*(e-t)};r.isNumeric=function(e){return!isNaN(parseFloat(e))&&isFinite(e)};r.isArray=function(e){return Object.prototype.toString.call(e)==="[object Array]"};String.prototype.endl=function(){return this+"\n"};String.prototype.startsWith=function(e){if(!this||!e)return false;if(this.length>=e.length){if(this.substring(0,e.length)==e)return true}return false};String.prototype.endsWith=String.prototype.endsWith||function(e){return this.match(e+"$")==e};String.prototype.contains=String.prototype.contains||function(e){return this.indexOf(e)>-1};const Y=function(e=""){if(!e)return"";if(e.startsWith("data:"))return;if(e.contains("?"))e+="&";else e+="?";return e+"cache="+CABLES.uuid()};const W=function(t,i){if(!t)return null;i=i||[];i.length=t.length;for(let e=0;e<t.length;e++){i[e]=t[e]}return i};const K=function(e){let t=CABLES.filename(e);const i=t.split(".");t=i[0];return t};const Z=function(){console.log("logstack",(new Error).stack)};const Q=function(e){let t="";if(!e)return"";if(e.startsWith("data:")&&e.contains(":")){const i=e.split(",");return i[0]}let i=(e+"").split("/");if(i.length>0){const n=i[i.length-1];let e=n.split("?");t=e[0]}return t||""};const J=function(e,t,i,n,r){u({url:e,cb:t,method:i,data:n,contenttype:r,sync:true})};const $=function(e,t,i,n,r,a,s={},o={}){const l={url:e,cb:t,method:i,data:n,contenttype:r,sync:false,jsonP:a,headers:s};if(o&&o.credentials)l.credentials=o.credentials;u(l)};const u=function(t){if(!t.hasOwnProperty("asynch"))t.asynch=true;let i;try{i=new XMLHttpRequest}catch(e){}i.onreadystatechange=function(){if(i.readyState!=4)return;if(t.cb){if(i.status==200||i.status==0)t.cb(false,i.responseText,i);else t.cb(true,i.responseText,i)}};try{i.open(t.method?t.method.toUpperCase():"GET",t.url,!t.sync)}catch(e){if(t.cb&&e)t.cb(true,e.msg,i)}if(typeof t.headers==="object"){if(t.headers){const n=Object.keys(t.headers);for(let e=0;e<n.length;e++){const r=n[e];const a=t.headers[r];i.setRequestHeader(r,a)}}}if(t.credentials&&t.credentials!=="omit"){i.withCredentials=true}try{if(!t.post&&!t.data){i.send()}else{i.setRequestHeader("Content-type",t.contenttype?t.contenttype:"application/x-www-form-urlencoded");i.send(t.data||t.post)}}catch(e){if(t.cb)t.cb(true,e.msg,i)}};const ee=function(e){if(!e&&e!==0)return"Unidentified";const t={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"};if(t[e]){return t[e]}else{return String.fromCharCode(e)}};window.performance=window.performance||{offset:Date.now(),now:function e(){return Date.now()-this.offset}};const te=function(e){CABLES.errorConsole=CABLES.errorConsole||{log:[]};CABLES.errorConsole.log.push({initiator:e,arguments:arguments});if(!CABLES.errorConsole.ele){const t=document.createElement("div");t.id="cablesErrorConsole";t.style.width="90%";t.style.height="300px";t.style.zIndex="9999999";t.style.display="inline-block";t.style.position="absolute";t.style.padding="10px";t.style.fontFamily="monospace";t.style.color="red";t.style.backgroundColor="#200";CABLES.errorConsole.ele=t;document.body.appendChild(t)}let n="ERROR<br/>for more info, open your browsers dev tools console (Ctrl+Shift+I or Command+Alt+I)<br/>";for(let i=0;i<CABLES.errorConsole.log.length;i++){n+=CABLES.errorConsole.log[i].initiator+" ";for(let e=1;e<CABLES.errorConsole.log[i].arguments.length;e++){if(e>2)n+=", ";let t=CABLES.errorConsole.log[i].arguments[e];if(t.constructor.name.indexOf("Error")>-1||t.constructor.name.indexOf("error")>-1){let e="Uncaught ErrorEvent ";if(t.message)e+=" message: "+t.message;n+=e}else if(typeof t=="string")n+=t;else if(typeof t=="number")n+=String(t)+" "}n+="<br/>"}CABLES.errorConsole.ele.innerHTML=n};class l{constructor(e){this._init();this._first=true;this._wireMesh=null;if(e)this.apply(e)}_init(){this._max=[-0,-0,-0];this._min=[0,0,0];this._center=[0,0,0];this._size=[0,0,0];this._maxAxis=0;this._first=true}get maxAxis(){return this._maxAxis||1}get size(){return this._size}get center(){return this._center}get x(){return this._center[0]}get y(){return this._center[1]}get z(){return this._center[2]}get minX(){return this._min[0]}get minY(){return this._min[1]}get minZ(){return this._min[2]}get maxX(){return this._max[0]}get maxY(){return this._max[1]}get maxZ(){return this._max[2]}apply(t,e){if(!t){return}if(t instanceof l){const i=t;this.applyPos(i.maxX,i.maxY,i.maxZ);this.applyPos(i.minX,i.minY,i.minZ)}else{for(let e=0;e<t.vertices.length;e+=3)this.applyPos(t.vertices[e],t.vertices[e+1],t.vertices[e+2])}this.calcCenterSize()}copy(){return new l(this)}get changed(){return!(this._max[0]==-Number.MAX_VALUE&&this._max[1]==-Number.MAX_VALUE&&this._max[2]==-Number.MAX_VALUE)}applyPos(e,t,i){if(e==Number.MAX_VALUE||e==-Number.MAX_VALUE||t==Number.MAX_VALUE||t==-Number.MAX_VALUE||i==Number.MAX_VALUE||i==-Number.MAX_VALUE)return;if(!CABLES.UTILS.isNumeric(e)||!CABLES.UTILS.isNumeric(t)||!CABLES.UTILS.isNumeric(i))return;if(this._first){this._max[0]=e;this._max[1]=t;this._max[2]=i;this._min[0]=e;this._min[1]=t;this._min[2]=i;this._first=false;return}this._max[0]=Math.max(this._max[0],e);this._max[1]=Math.max(this._max[1],t);this._max[2]=Math.max(this._max[2],i);this._min[0]=Math.min(this._min[0],e);this._min[1]=Math.min(this._min[1],t);this._min[2]=Math.min(this._min[2],i)}calcCenterSize(){if(this._first)return;this._size[0]=this._max[0]-this._min[0];this._size[1]=this._max[1]-this._min[1];this._size[2]=this._max[2]-this._min[2];this._center[0]=(this._min[0]+this._max[0])/2;this._center[1]=(this._min[1]+this._max[1])/2;this._center[2]=(this._min[2]+this._max[2])/2;this._maxAxis=Math.max(this._size[2],Math.max(this._size[0],this._size[1]))}mulMat4(e){if(this._first){this._max[0]=0;this._max[1]=0;this._max[2]=0;this._min[0]=0;this._min[1]=0;this._min[2]=0;this._first=false}vec3.transformMat4(this._max,this._max,e);vec3.transformMat4(this._min,this._min,e);this.calcCenterSize()}render(e,t,i){if(!this._wireMesh)this._wireMesh=new CGL.WireCube(e);e.pushModelMatrix();mat4.translate(e.mMatrix,e.mMatrix,this._center);if(CABLES.UI&&i){CABLES.UI.OverlayMeshes.drawCube(i,this._size[0]/2,this._size[1]/2,this._size[2]/2)}e.popModelMatrix()}}const p=function(e){this.name=e||"unknown";this._log=new h("cgl_geometry");this.faceVertCount=3;this.glPrimitive=null;this._attributes={};this._vertices=[];this.verticesIndices=[];this.isGeometry=true;this.morphTargets=[];Object.defineProperty(this,"vertices",{get(){return this._vertices},set(e){this.setVertices(e)}});Object.defineProperty(this,"texCoords",{get(){const e=this.getAttribute("texCoords");if(!e)return[];return e.data},set(e){this.setAttribute("texCoords",e,2)}});Object.defineProperty(this,"vertexNormals",{get(){const e=this.getAttribute("vertexNormals");if(!e)return[];return e.data},set(e){this.setAttribute("vertexNormals",e,3)}});Object.defineProperty(this,"tangents",{get(){const e=this.getAttribute("tangents");if(!e)return[];return e.data},set(e){this.setAttribute("tangents",e,3)}});Object.defineProperty(this,"biTangents",{get(){const e=this.getAttribute("biTangents");if(!e)return[];return e.data},set(e){this.setAttribute("biTangents",e,3)}});Object.defineProperty(this,"vertexColors",{get(){const e=this.getAttribute("vertexColors");if(!e)return[];return e.data},set(e){this.setAttribute("vertexColors",e,4)}})};p.prototype.clear=function(){this._vertices=new Float32Array([]);this.verticesIndices=[];this.texCoords=new Float32Array([]);this.vertexNormals=new Float32Array([]);this.tangents=[];this.biTangents=[];this._attributes={}};p.prototype.getAttributes=function(){return this._attributes};p.prototype.getAttribute=function(e){for(const t in this._attributes){if(this._attributes[t].name==e)return this._attributes[t]}return null};p.prototype.setAttribute=function(e,t,i){let n="";if(!i||i>4){console.log("itemsize wrong?",i,e);this._log.stack("itemsize");i=3}if(i==1)n="float";else if(i==2)n="vec2";else if(i==3)n="vec3";else if(i==4)n="vec4";const r={name:e,data:t,itemSize:i,type:n};this._attributes[e]=r};p.prototype.copyAttribute=function(e,t){const i=this.getAttribute(e);t.setAttribute(e,new Float32Array(i.data),i.itemSize)};p.prototype.setVertices=function(e){if(e instanceof Float32Array)this._vertices=e;else this._vertices=new Float32Array(e)};p.prototype.setTexCoords=function(e){if(e instanceof Float32Array)this.texCoords=e;else this.texCoords=new Float32Array(e)};p.prototype.calcNormals=function(e){const t={smooth:e};this.calculateNormals(t)};p.prototype.flipNormals=function(t,i,n){let r=vec3.create();if(t==undefined)t=1;if(i==undefined)i=1;if(n==undefined)n=1;for(let e=0;e<this.vertexNormals.length;e+=3){vec3.set(r,this.vertexNormals[e+0],this.vertexNormals[e+1],this.vertexNormals[e+2]);r[0]*=-t;r[1]*=-i;r[2]*=-n;vec3.normalize(r,r);this.vertexNormals[e+0]=r[0];this.vertexNormals[e+1]=r[1];this.vertexNormals[e+2]=r[2]}};p.prototype.getNumTriangles=function(){if(this.verticesIndices&&this.verticesIndices.length)return this.verticesIndices.length/3;return this.vertices.length/3};p.prototype.flipVertDir=function(){const t=[];t.length=this.verticesIndices.length;for(let e=0;e<this.verticesIndices.length;e+=3){t[e]=this.verticesIndices[e+2];t[e+1]=this.verticesIndices[e+1];t[e+2]=this.verticesIndices[e]}this.verticesIndices=t};p.prototype.setPointVertices=function(t){if(t.length%3!==0){this._log.error("SetPointVertices: Array must be multiple of three.");return}if(!(t instanceof Float32Array))this.vertices=new Float32Array(t);else this.vertices=t;if(!(this.texCoords instanceof Float32Array))this.texCoords=new Float32Array(t.length/3*2);this.verticesIndices.length=t.length/3;for(let e=0;e<t.length/3;e++){this.verticesIndices[e]=e;this.texCoords[e*2]=0;this.texCoords[e*2+1]=0}};p.prototype.merge=function(t){if(!t)return;if(this.isIndexed()!=t.isIndexed()){if(this.isIndexed()){this.unIndex(false,true)}if(t.isIndexed()){const e=t.copy();e.unIndex(false,true);t=e}}const i=this.verticesIndices.length;const n=this._vertices.length/3;this.verticesIndices.length+=t.verticesIndices.length;for(let e=0;e<t.verticesIndices.length;e++)this.verticesIndices[i+e]=t.verticesIndices[e]+n;this.vertices=r.float32Concat(this._vertices,t.vertices);this.texCoords=r.float32Concat(this.texCoords,t.texCoords);this.vertexNormals=r.float32Concat(this.vertexNormals,t.vertexNormals);this.tangents=r.float32Concat(this.tangents,t.tangents);this.biTangents=r.float32Concat(this.biTangents,t.biTangents)};p.prototype.copy=function(){const t=new p(this.name+" copy");t.faceVertCount=this.faceVertCount;t.glPrimitive=this.glPrimitive;t.setVertices(this._vertices.slice(0));if(this.verticesIndices){t.verticesIndices.length=this.verticesIndices.length;for(let e=0;e<this.verticesIndices.length;e++)t.verticesIndices[e]=this.verticesIndices[e]}for(let e in this._attributes)this.copyAttribute(e,t);t.morphTargets.length=this.morphTargets.length;for(let e=0;e<this.morphTargets.length;e++)t.morphTargets[e]=this.morphTargets[e];return t};p.prototype.calculateNormals=function(t){t=t||{};if(t.smooth===false)this.unIndex();const i=vec3.create();const n=vec3.create();const r=vec3.create();function a(e){vec3.subtract(i,e[0],e[1]);vec3.subtract(n,e[0],e[2]);vec3.cross(r,i,n);vec3.normalize(r,r);if(t&&t.forceZUp){if(r[2]<0){r[0]*=-1;r[1]*=-1;r[2]*=-1}}return r}this.getVertexVec=function(e){const t=[0,0,0];t[0]=this.vertices[e*3+0];t[1]=this.vertices[e*3+1];t[2]=this.vertices[e*3+2];return t};if(!(this.vertexNormals instanceof Float32Array)||this.vertexNormals.length!=this.vertices.length)this.vertexNormals=new Float32Array(this.vertices.length);for(let e=0;e<this.vertices.length;e++){this.vertexNormals[e]=0}if(!this.isIndexed()){const s=[];for(let e=0;e<this.vertices.length;e+=9){const o=[[this.vertices[e+0],this.vertices[e+1],this.vertices[e+2]],[this.vertices[e+3],this.vertices[e+4],this.vertices[e+5]],[this.vertices[e+6],this.vertices[e+7],this.vertices[e+8]]];const l=a(o);s.push(l[0],l[1],l[2],l[0],l[1],l[2],l[0],l[1],l[2])}this.vertexNormals=s}else{const u=[];u.length=Math.floor(this.verticesIndices.length/3);for(let e=0;e<this.verticesIndices.length;e+=3){const o=[this.getVertexVec(this.verticesIndices[e+0]),this.getVertexVec(this.verticesIndices[e+1]),this.getVertexVec(this.verticesIndices[e+2])];u[e/3]=a(o);this.vertexNormals[this.verticesIndices[e+0]*3+0]+=u[e/3][0];this.vertexNormals[this.verticesIndices[e+0]*3+1]+=u[e/3][1];this.vertexNormals[this.verticesIndices[e+0]*3+2]+=u[e/3][2];this.vertexNormals[this.verticesIndices[e+1]*3+0]+=u[e/3][0];this.vertexNormals[this.verticesIndices[e+1]*3+1]+=u[e/3][1];this.vertexNormals[this.verticesIndices[e+1]*3+2]+=u[e/3][2];this.vertexNormals[this.verticesIndices[e+2]*3+0]+=u[e/3][0];this.vertexNormals[this.verticesIndices[e+2]*3+1]+=u[e/3][1];this.vertexNormals[this.verticesIndices[e+2]*3+2]+=u[e/3][2]}for(let t=0;t<this.verticesIndices.length;t+=3){for(let e=0;e<3;e++){const h=[this.vertexNormals[this.verticesIndices[t+e]*3+0],this.vertexNormals[this.verticesIndices[t+e]*3+1],this.vertexNormals[this.verticesIndices[t+e]*3+2]];vec3.normalize(h,h);this.vertexNormals[this.verticesIndices[t+e]*3+0]=h[0];this.vertexNormals[this.verticesIndices[t+e]*3+1]=h[1];this.vertexNormals[this.verticesIndices[t+e]*3+2]=h[2]}}}};p.prototype.calcTangentsBitangents=function(){if(!this.vertices.length){return}if(!this.vertexNormals.length){return}if(!this.texCoords.length){const x=this.vertices.length/3*2;this.texCoords=new Float32Array(x);for(let e=0;e<x;e+=1)this.texCoords[e]=0}if(!this.verticesIndices||!this.verticesIndices.length){return}if(this.verticesIndices.length%3!==0){this._log.error("Vertex indices mismatch!");return}const t=this.verticesIndices.length/3;const i=this.vertices.length/3;this.tangents=new Float32Array(this.vertexNormals.length);this.biTangents=new Float32Array(this.vertexNormals.length);const n=[];n.length=i*2;const r=vec3.create();const a=vec3.create();const s=vec3.create();const o=vec2.create();const l=vec2.create();const u=vec2.create();const h=vec3.create();const p=vec3.create();for(let e=0;e<t;e+=1){const A=this.verticesIndices[e*3];const _=this.verticesIndices[e*3+1];const S=this.verticesIndices[e*3+2];vec3.set(r,this.vertices[A*3],this.vertices[A*3+1],this.vertices[A*3+2]);vec3.set(a,this.vertices[_*3],this.vertices[_*3+1],this.vertices[_*3+2]);vec3.set(s,this.vertices[S*3],this.vertices[S*3+1],this.vertices[S*3+2]);vec2.set(o,this.texCoords[A*2],this.texCoords[A*2+1]);vec2.set(l,this.texCoords[_*2],this.texCoords[_*2+1]);vec2.set(u,this.texCoords[S*2],this.texCoords[S*2+1]);const C=a[0]-r[0];const T=s[0]-r[0];const I=a[1]-r[1];const O=s[1]-r[1];const E=a[2]-r[2];const P=s[2]-r[2];const M=l[0]-o[0];const L=u[0]-o[0];const N=l[1]-o[1];const k=u[1]-o[1];const w=1/(M*k-L*N);vec3.set(h,(k*C-N*T)*w,(k*I-N*O)*w,(k*E-N*P)*w);vec3.set(p,(M*T-L*C)*w,(M*O-L*I)*w,(M*P-L*E)*w);n[A]=h;n[_]=h;n[S]=h;n[A+i]=p;n[_+i]=p;n[S+i]=p}const c=vec3.create();const m=vec3.create();const f=vec3.create();const d=vec3.create();const g=vec3.create();const v=vec3.create();const y=vec3.create();const b=vec3.create();for(let e=0;e<i;e+=1){if(!n[e])continue;vec3.set(c,this.vertexNormals[e*3],this.vertexNormals[e*3+1],this.vertexNormals[e*3+2]);vec3.set(m,n[e][0],n[e][1],n[e][2]);const R=vec3.dot(c,m);vec3.scale(g,c,R);vec3.subtract(v,m,g);vec3.normalize(b,v);vec3.cross(y,c,m);const V=1;vec3.scale(f,b,1/V);vec3.cross(d,c,f);this.tangents[e*3+0]=f[0];this.tangents[e*3+1]=f[1];this.tangents[e*3+2]=f[2];this.biTangents[e*3+0]=d[0];this.biTangents[e*3+1]=d[1];this.biTangents[e*3+2]=d[2]}};p.prototype.isIndexed=function(){if(this._vertices.length==0)return true;return this.verticesIndices.length!=0};p.prototype.unIndex=function(e,t){const i=[];const n=[];let r=0;for(let e in this._attributes){const a=this._attributes[e];let i=[];for(let t=0;t<this.verticesIndices.length;t+=3){for(let e=0;e<3;e++){if(a.itemSize==3)i.push(a.data[this.verticesIndices[t+e]*3+0],a.data[this.verticesIndices[t+e]*3+1],a.data[this.verticesIndices[t+e]*3+2]);else if(a.itemSize==4)i.push(a.data[this.verticesIndices[t+e]*4+0],a.data[this.verticesIndices[t+e]*4+1],a.data[this.verticesIndices[t+e]*4+2],a.data[this.verticesIndices[t+e]*4+3]);else if(a.itemSize==2)i.push(a.data[this.verticesIndices[t+e]*2+0],a.data[this.verticesIndices[t+e]*2+1]);else if(a.itemSize==1)i.push(a.data[this.verticesIndices[t+e]]);else console.log("unknown attr",a)}}this.setAttribute(a.name,i,a.itemSize)}for(let e=0;e<this.verticesIndices.length;e+=3){i.push(this.vertices[this.verticesIndices[e+0]*3+0],this.vertices[this.verticesIndices[e+0]*3+1],this.vertices[this.verticesIndices[e+0]*3+2]);n.push(r);r++;i.push(this.vertices[this.verticesIndices[e+1]*3+0],this.vertices[this.verticesIndices[e+1]*3+1],this.vertices[this.verticesIndices[e+1]*3+2]);n.push(r);r++;i.push(this.vertices[this.verticesIndices[e+2]*3+0],this.vertices[this.verticesIndices[e+2]*3+1],this.vertices[this.verticesIndices[e+2]*3+2]);n.push(r);r++}this.vertices=i;this.verticesIndices=[];if(e)this.verticesIndices=n;if(!t)this.calculateNormals()};p.prototype.calcBarycentric=function(){let t=[];t.length=this.vertices.length;for(let e=0;e<this.vertices.length;e++)t[e]=0;let i=0;for(let e=0;e<this.vertices.length;e+=3){t[e+i]=1;i++;if(i==3)i=0}this.setAttribute("attrBarycentric",t,3)};p.prototype.getBounds=function(){return new l(this)};p.prototype.center=function(e,t,i){if(e===undefined){e=true;t=true;i=true}let n=0;const r=this.getBounds();const a=[r.minX+(r.maxX-r.minX)/2,r.minY+(r.maxY-r.minY)/2,r.minZ+(r.maxZ-r.minZ)/2];for(n=0;n<this.vertices.length;n+=3){if(this.vertices[n+0]==this.vertices[n+0]){if(e)this.vertices[n+0]-=a[0];if(t)this.vertices[n+1]-=a[1];if(i)this.vertices[n+2]-=a[2]}}return a};p.prototype.mapTexCoords2d=function(){const t=this.getBounds();const i=this.vertices.length/3;this.texCoords=new Float32Array(i*2);for(let e=0;e<i;e++){const n=this.vertices[e*3+0];const r=this.vertices[e*3+1];this.texCoords[e*2+0]=n/(t.maxX-t.minX)+.5;this.texCoords[e*2+1]=1-r/(t.maxY-t.minY)+.5}};p.prototype.getInfoOneLine=function(){let e="";if(this.faceVertCount==3&&this.verticesIndices)e+=this.verticesIndices.length/3;else e+=0;e+=" tris ";if(this.vertices)e+=this.vertices.length/3;else e+=0;e+=" verts";return e};p.prototype.getInfo=function(){const e={};if(this.faceVertCount==3&&this.verticesIndices)e.numFaces=this.verticesIndices.length/3;else e.numFaces=0;if(this.verticesIndices&&this.verticesIndices.length)e.indices=this.verticesIndices.length;if(this.vertices)e.numVerts=this.vertices.length/3;else e.numVerts=0;if(this.vertexNormals)e.numNormals=this.vertexNormals.length/3;else e.numNormals=0;if(this.texCoords)e.numTexCoords=this.texCoords.length/2;else e.numTexCoords=0;if(this.tangents)e.numTangents=this.tangents.length/3;else e.numTangents=0;if(this.biTangents)e.numBiTangents=this.biTangents.length/3;else e.numBiTangents=0;if(this.biTangents)e.numBiTangents=this.biTangents.length/3;else e.numBiTangents=0;if(this.vertexColors)e.numVertexColors=this.vertexColors.length/4;else e.numVertexColors=0;if(this.getAttributes())e.numAttribs=Object.keys(this.getAttributes()).length;else e.numAttribs=0;e.isIndexed=this.isIndexed();return e};p.buildFromFaces=function(t,e,i){const n=[];const r=[];for(let e=0;e<t.length;e+=3){const s=t[e+0];const o=t[e+1];const l=t[e+2];const u=[-1,-1,-1];if(i)for(let e=0;e<n.length;e+=3){if(n[e+0]==s[0]&&n[e+1]==s[1]&&n[e+2]==s[2])u[0]=e/3;if(n[e+0]==o[0]&&n[e+1]==o[1]&&n[e+2]==o[2])u[1]=e/3;if(n[e+0]==l[0]&&n[e+1]==l[1]&&n[e+2]==l[2])u[2]=e/3}if(u[0]==-1){n.push(s[0],s[1],s[2]);u[0]=(n.length-1)/3}if(u[1]==-1){n.push(o[0],o[1],o[2]);u[1]=(n.length-1)/3}if(u[2]==-1){n.push(l[0],l[1],l[2]);u[2]=(n.length-1)/3}r.push(parseInt(u[0],10));r.push(parseInt(u[1],10));r.push(parseInt(u[2],10))}const a=new p(e);a.name=e;a.vertices=n;a.verticesIndices=r;return a};const c=function(){this._log=new h("eventtarget");this._eventCallbacks={};this._logName="";this._logEvents=false;this._listeners={};this.addEventListener=this.on=function(e,t,i){const n={id:(i||"")+CABLES.simpleId(),name:e,cb:t};if(!this._eventCallbacks[e])this._eventCallbacks[e]=[n];else this._eventCallbacks[e].push(n);this._listeners[n.id]=n;return n.id};this.hasEventListener=function(e,t){if(e&&!t){if(this._listeners[e])return true;else return false}else{this._log.warn("old eventtarget function haseventlistener!");if(e&&t){if(this._eventCallbacks[e]){const i=this._eventCallbacks[e].indexOf(t);if(i==-1)return false;return true}}}};this.hasListenerForEventName=function(e){return this._eventCallbacks[e]&&this._eventCallbacks[e].length>0};this.removeEventListener=this.off=function(n,t){if(n===null||n===undefined)return;if(!t){const r=this._listeners[n];if(!r){this._log.log("removeEvent: could not find event...",n,this);return}let i=true;while(i){i=false;let t=-1;for(let e=0;e<this._eventCallbacks[r.name].length;e++){if(this._eventCallbacks[r.name][e].id.startsWith(n)){i=true;t=e}}if(t!==-1){this._eventCallbacks[r.name].splice(t,1);delete this._listeners[n]}}return}this._log.info("[eventtaget] ","old function signature: removeEventListener! use listener id");this._log.log((new Error).stack);let i=null;for(let e=0;e<this._eventCallbacks[n].length;e++)if(this._eventCallbacks[n][e].cb==t)i=e;if(i!==null){delete this._eventCallbacks[i]}else this._log.warn("removeEventListener not found "+n)};this.logEvents=function(e,t){this._logEvents=e;this._logName=t};this.emitEvent=function(t,i,n,r,a,s,o){if(this._logEvents)this._log.log("[event] ",this._logName,t,this._eventCallbacks);if(this._eventCallbacks[t]){for(let e=0;e<this._eventCallbacks[t].length;e++){if(this._eventCallbacks[t][e]){this._eventCallbacks[t][e].cb(i,n,r,a,s,o)}}}else{if(this._logEvents)this._log.log("[event] has no event callback",t,this._eventCallbacks)}}};const m={ANIM:{EASINGS:["linear","absolute","smoothstep","smootherstep","Cubic In","Cubic Out","Cubic In Out","Expo In","Expo Out","Expo In Out","Sin In","Sin Out","Sin In Out","Quart In","Quart Out","Quart In Out","Quint In","Quint Out","Quint In Out","Back In","Back Out","Back In Out","Elastic In","Elastic Out","Bounce In","Bounce Out"],EASING_LINEAR:0,EASING_ABSOLUTE:1,EASING_SMOOTHSTEP:2,EASING_SMOOTHERSTEP:3,EASING_CUBICSPLINE:4,EASING_CUBIC_IN:5,EASING_CUBIC_OUT:6,EASING_CUBIC_INOUT:7,EASING_EXPO_IN:8,EASING_EXPO_OUT:9,EASING_EXPO_INOUT:10,EASING_SIN_IN:11,EASING_SIN_OUT:12,EASING_SIN_INOUT:13,EASING_BACK_IN:14,EASING_BACK_OUT:15,EASING_BACK_INOUT:16,EASING_ELASTIC_IN:17,EASING_ELASTIC_OUT:18,EASING_BOUNCE_IN:19,EASING_BOUNCE_OUT:21,EASING_QUART_IN:22,EASING_QUART_OUT:23,EASING_QUART_INOUT:24,EASING_QUINT_IN:25,EASING_QUINT_OUT:26,EASING_QUINT_INOUT:27},OP:{OP_PORT_TYPE_VALUE:0,OP_PORT_TYPE_NUMBER:0,OP_PORT_TYPE_FUNCTION:1,OP_PORT_TYPE_TRIGGER:1,OP_PORT_TYPE_OBJECT:2,OP_PORT_TYPE_TEXTURE:2,OP_PORT_TYPE_ARRAY:3,OP_PORT_TYPE_DYNAMIC:4,OP_PORT_TYPE_STRING:5,OP_VERSION_PREFIX:"_v"},PORT:{PORT_DIR_IN:0,PORT_DIR_OUT:1},PACO:{PACO_CLEAR:0,PACO_VALUECHANGE:1,PACO_OP_DELETE:2,PACO_UNLINK:3,PACO_LINK:4,PACO_LOAD:5,PACO_OP_CREATE:6,PACO_OP_ENABLE:7,PACO_OP_DISABLE:8,PACO_UIATTRIBS:9,PACO_VARIABLES:10,PACO_TRIGGERS:11,PACO_PORT_SETVARIABLE:12,PACO_PORT_SETANIMATED:13,PACO_PORT_ANIM_UPDATED:14,PACO_DESERIALIZE:15,PACO_OP_RELOAD:16}};const f=function(e){this.time=0;this.value=0;this.onChange=null;this._easing=0;this.cb=null;this.cbTriggered=false;this.setEasing(m.ANIM.EASING_LINEAR);this.set(e)};f.cubicSpline=function(e,t,i){let n=t.value,r=t.bezTangOut,a=i.value,s=i.bezTangIn;let o=e;let l=o*o;let u=l*o;return(2*u-3*l+1)*n+(u-2*l+o)*r+(-2*u+3*l)*a+(u-l)*s};f.easeCubicSpline=function(e,t){return f.cubicSpline(e,this,t)};f.linear=function(e,t,i){return parseFloat(t.value)+parseFloat(i.value-t.value)*e};f.easeLinear=function(e,t){return f.linear(e,this,t)};f.easeAbsolute=function(e,t){return this.value};const d=function(e){return e=2**(10*(e-1))};f.easeExpoIn=function(e,t){e=d(e);return f.linear(e,this,t)};const g=function(e){e=-(2**(-10*e))+1;return e};f.easeExpoOut=function(e,t){e=g(e);return f.linear(e,this,t)};const v=function(e){e*=2;if(e<1){e=.5*2**(10*(e-1))}else{e--;e=.5*(-(2**(-10*e))+2)}return e};f.easeExpoInOut=function(e,t){e=v(e);return f.linear(e,this,t)};f.easeSinIn=function(e,t){e=-1*Math.cos(e*Math.PI/2)+1;return f.linear(e,this,t)};f.easeSinOut=function(e,t){e=Math.sin(e*Math.PI/2);return f.linear(e,this,t)};f.easeSinInOut=function(e,t){e=-.5*(Math.cos(Math.PI*e)-1);return f.linear(e,this,t)};const y=function(e){e=e*e*e;return e};f.easeCubicIn=function(e,t){e=y(e);return f.linear(e,this,t)};f.easeInQuint=function(e,t){e=e*e*e*e*e;return f.linear(e,this,t)};f.easeOutQuint=function(e,t){e=(e-=1)*e*e*e*e+1;return f.linear(e,this,t)};f.easeInOutQuint=function(e,t){if((e/=.5)<1)e=.5*e*e*e*e*e;else e=.5*((e-=2)*e*e*e*e+2);return f.linear(e,this,t)};f.easeInQuart=function(e,t){e=e*e*e*e;return f.linear(e,this,t)};f.easeOutQuart=function(e,t){e=-1*((e-=1)*e*e*e-1);return f.linear(e,this,t)};f.easeInOutQuart=function(e,t){if((e/=.5)<1)e=.5*e*e*e*e;else e=-.5*((e-=2)*e*e*e-2);return f.linear(e,this,t)};f.bounce=function(e){if((e/=1)<1/2.75)e=7.5625*e*e;else if(e<2/2.75)e=7.5625*(e-=1.5/2.75)*e+.75;else if(e<2.5/2.75)e=7.5625*(e-=2.25/2.75)*e+.9375;else e=7.5625*(e-=2.625/2.75)*e+.984375;return e};f.easeInBounce=function(e,t){return f.linear(f.bounce(e),this,t)};f.easeOutBounce=function(e,t){return f.linear(f.bounce(e),this,t)};f.easeInElastic=function(e,t){let i=1.70158;let n=0;let r=1;const a=0;const s=1;const o=1;if(e===0)e=a;else if((e/=s)==1)e=a+o;else{if(!n)n=s*.3;if(r<Math.abs(o)){r=o;i=n/4}else i=n/(2*Math.PI)*Math.asin(o/r);e=-(r*2**(10*(e-=1))*Math.sin((e*s-i)*(2*Math.PI)/n))+a}return f.linear(e,this,t)};f.easeOutElastic=function(e,t){let i=1.70158;let n=0;let r=1;const a=0;const s=1;const o=1;if(e===0)e=a;else if((e/=s)==1)e=a+o;else{if(!n)n=s*.3;if(r<Math.abs(o)){r=o;i=n/4}else i=n/(2*Math.PI)*Math.asin(o/r);e=r*2**(-10*e)*Math.sin((e*s-i)*(2*Math.PI)/n)+o+a}return f.linear(e,this,t)};f.easeInBack=function(e,t){const i=1.70158;e=e*e*((i+1)*e-i);return f.linear(e,this,t)};f.easeOutBack=function(e,t){const i=1.70158;e=(e=e/1-1)*e*((i+1)*e+i)+1;return f.linear(e,this,t)};f.easeInOutBack=function(e,t){let i=1.70158;const n=1/2;if((e/=1/2)<1)e=n*(e*e*(((i*=1.525)+1)*e-i));else e=n*((e-=2)*e*(((i*=1.525)+1)*e+i)+2);return f.linear(e,this,t)};const b=function(e){e--;e=e*e*e+1;return e};f.easeCubicOut=function(e,t){e=b(e);return f.linear(e,this,t)};const x=function(e){e*=2;if(e<1)e=.5*e*e*e;else{e-=2;e=.5*(e*e*e+2)}return e};f.easeCubicInOut=function(e,t){e=x(e);return f.linear(e,this,t)};f.easeSmoothStep=function(e,t){const i=Math.max(0,Math.min(1,e));e=i*i*(3-2*i);return f.linear(e,this,t)};f.easeSmootherStep=function(e,t){const i=Math.max(0,Math.min(1,(e-0)/(1-0)));e=i*i*i*(i*(i*6-15)+10);return f.linear(e,this,t)};f.prototype.setEasing=function(e){this._easing=e;if(this._easing==m.ANIM.EASING_LINEAR)this.ease=f.easeLinear;else if(this._easing==m.ANIM.EASING_ABSOLUTE)this.ease=f.easeAbsolute;else if(this._easing==m.ANIM.EASING_SMOOTHSTEP)this.ease=f.easeSmoothStep;else if(this._easing==m.ANIM.EASING_SMOOTHERSTEP)this.ease=f.easeSmootherStep;else if(this._easing==m.ANIM.EASING_CUBIC_IN)this.ease=f.easeCubicIn;else if(this._easing==m.ANIM.EASING_CUBIC_OUT)this.ease=f.easeCubicOut;else if(this._easing==m.ANIM.EASING_CUBIC_INOUT)this.ease=f.easeCubicInOut;else if(this._easing==m.ANIM.EASING_EXPO_IN)this.ease=f.easeExpoIn;else if(this._easing==m.ANIM.EASING_EXPO_OUT)this.ease=f.easeExpoOut;else if(this._easing==m.ANIM.EASING_EXPO_INOUT)this.ease=f.easeExpoInOut;else if(this._easing==m.ANIM.EASING_SIN_IN)this.ease=f.easeSinIn;else if(this._easing==m.ANIM.EASING_SIN_OUT)this.ease=f.easeSinOut;else if(this._easing==m.ANIM.EASING_SIN_INOUT)this.ease=f.easeSinInOut;else if(this._easing==m.ANIM.EASING_BACK_OUT)this.ease=f.easeOutBack;else if(this._easing==m.ANIM.EASING_BACK_IN)this.ease=f.easeInBack;else if(this._easing==m.ANIM.EASING_BACK_INOUT)this.ease=f.easeInOutBack;else if(this._easing==m.ANIM.EASING_ELASTIC_IN)this.ease=f.easeInElastic;else if(this._easing==m.ANIM.EASING_ELASTIC_OUT)this.ease=f.easeOutElastic;else if(this._easing==m.ANIM.EASING_ELASTIC_INOUT)this.ease=f.easeElasticInOut;else if(this._easing==m.ANIM.EASING_BOUNCE_IN)this.ease=f.easeInBounce;else if(this._easing==m.ANIM.EASING_BOUNCE_OUT)this.ease=f.easeOutBounce;else if(this._easing==m.ANIM.EASING_QUART_OUT)this.ease=f.easeOutQuart;else if(this._easing==m.ANIM.EASING_QUART_IN)this.ease=f.easeInQuart;else if(this._easing==m.ANIM.EASING_QUART_INOUT)this.ease=f.easeInOutQuart;else if(this._easing==m.ANIM.EASING_QUINT_OUT)this.ease=f.easeOutQuint;else if(this._easing==m.ANIM.EASING_QUINT_IN)this.ease=f.easeInQuint;else if(this._easing==m.ANIM.EASING_QUINT_INOUT)this.ease=f.easeInOutQuint;else if(this._easing==m.ANIM.EASING_CUBICSPLINE){this.ease=f.easeCubicSpline}else{this._easing=m.ANIM.EASING_LINEAR;this.ease=f.easeLinear}};f.prototype.trigger=function(){this.cb();this.cbTriggered=true};f.prototype.setValue=function(e){this.value=e;if(this.onChange!==null)this.onChange()};f.prototype.set=function(e){if(e){if(e.e)this.setEasing(e.e);if(e.cb){this.cb=e.cb;this.cbTriggered=false}if(e.b){}if(e.hasOwnProperty("t"))this.time=e.t;if(e.hasOwnProperty("time"))this.time=e.time;if(e.hasOwnProperty("v"))this.value=e.v;else if(e.hasOwnProperty("value"))this.value=e.value}if(this.onChange!==null)this.onChange()};f.prototype.getSerialized=function(){const e={};e.t=this.time;e.v=this.value;e.e=this._easing;return e};f.prototype.getEasing=function(){return this._easing};const A=function(e){c.apply(this);e=e||{};this.keys=[];this.onChange=null;this.stayInTimeline=false;this.loop=false;this._log=new h("Anim");this._lastKeyIndex=0;this._cachedIndex=0;this.name=e.name||null;this.defaultEasing=e.defaultEasing||m.ANIM.EASING_LINEAR;this.onLooped=null;this._timesLooped=0;this._needsSort=false};A.prototype.forceChangeCallback=function(){if(this.onChange!==null)this.onChange();this.emitEvent("onChange",this)};A.prototype.getLoop=function(){return this.loop};A.prototype.setLoop=function(e){this.loop=e;this.emitEvent("onChange",this)};A.prototype.hasEnded=function(e){if(this.keys.length===0)return true;if(this.keys[this._lastKeyIndex].time<=e)return true;return false};A.prototype.isRising=function(e){if(this.hasEnded(e))return false;const t=this.getKeyIndex(e);if(this.keys[t].value<this.keys[t+1].value)return true;return false};A.prototype.clearBefore=function(e){const t=this.getValue(e);const i=this.getKeyIndex(e);this.setValue(e,t);if(i>1)this.keys.splice(0,i);this._updateLastIndex()};A.prototype.clear=function(e){let t=0;if(e)t=this.getValue(e);this.keys.length=0;this._updateLastIndex();if(e)this.setValue(e,t);if(this.onChange!==null)this.onChange();this.emitEvent("onChange",this)};A.prototype.sortKeys=function(){this.keys.sort((e,t)=>{return parseFloat(e.time)-parseFloat(t.time)});this._updateLastIndex();this._needsSort=false;if(this.keys.length%1e3==0)console.log(this.name,this.keys.length)};A.prototype.getLength=function(){if(this.keys.length===0)return 0;return this.keys[this.keys.length-1].time};A.prototype.getKeyIndex=function(t){let i=0;let n=0;if(this._cachedIndex&&this.keys.length>this._cachedIndex&&t>=this.keys[this._cachedIndex].time)n=this._cachedIndex;for(let e=n;e<this.keys.length;e++){if(t>=this.keys[e].time)i=e;if(this.keys[e].time>t){if(t!=0)this._cachedIndex=i;return i}}return i};A.prototype.setValue=function(t,i,n){let r=null;if(this.keys.length==0||t<=this.keys[this.keys.length-1].time)for(let e=0;e<this.keys.length;e++)if(this.keys[e].time==t){r=this.keys[e];this.keys[e].setValue(i);this.keys[e].cb=n;break}if(!r){r=new f({time:t,value:i,e:this.defaultEasing,cb:n});this.keys.push(r);this._updateLastIndex()}if(this.onChange)this.onChange();this.emitEvent("onChange",this);this._needsSort=true;return r};A.prototype.setKeyEasing=function(e,t){if(this.keys[e]){this.keys[e].setEasing(t);this.emitEvent("onChange",this)}};A.prototype.getSerialized=function(){const t={};t.keys=[];t.loop=this.loop;for(let e=0;e<this.keys.length;e++)t.keys.push(this.keys[e].getSerialized());return t};A.prototype.getKey=function(e){const t=this.getKeyIndex(e);return this.keys[t]};A.prototype.getNextKey=function(e){let t=this.getKeyIndex(e)+1;if(t>=this.keys.length)t=this.keys.length-1;return this.keys[t]};A.prototype.isFinished=function(e){if(this.keys.length<=0)return true;return e>this.keys[this.keys.length-1].time};A.prototype.isStarted=function(e){if(this.keys.length<=0)return false;return e>=this.keys[0].time};A.prototype.getValue=function(e){if(this.keys.length===0){return 0}if(this._needsSort)this.sortKeys();if(!this.loop&&e>this.keys[this._lastKeyIndex].time){if(this.keys[this._lastKeyIndex].cb&&!this.keys[this._lastKeyIndex].cbTriggered)this.keys[this._lastKeyIndex].trigger();return this.keys[this._lastKeyIndex].value}if(e<this.keys[0].time){return this.keys[0].value}if(this.loop&&e>this.keys[this._lastKeyIndex].time){const s=e/this.keys[this._lastKeyIndex].time;if(s>this._timesLooped){this._timesLooped++;if(this.onLooped)this.onLooped()}e=(e-this.keys[0].time)%(this.keys[this._lastKeyIndex].time-this.keys[0].time);e+=this.keys[0].time}const t=this.getKeyIndex(e);if(t>=this._lastKeyIndex){if(this.keys[this._lastKeyIndex].cb&&!this.keys[this._lastKeyIndex].cbTriggered)this.keys[this._lastKeyIndex].trigger();return this.keys[this._lastKeyIndex].value}const i=t+1;const n=this.keys[t];const r=this.keys[i];if(n.cb&&!n.cbTriggered)n.trigger();if(!r)return-1;const a=(e-n.time)/(r.time-n.time);if(!n.ease)this.log._warn("has no ease",n,r);return n.ease(a,r)};A.prototype._updateLastIndex=function(){this._lastKeyIndex=this.keys.length-1};A.prototype.addKey=function(e){if(e.time===undefined){this.log.warn("key time undefined, ignoring!")}else{this.keys.push(e);if(this.onChange!==null)this.onChange();this.emitEvent("onChange",this)}this._updateLastIndex()};A.prototype.easingFromString=function(e){if(e=="linear")return m.ANIM.EASING_LINEAR;if(e=="absolute")return m.ANIM.EASING_ABSOLUTE;if(e=="smoothstep")return m.ANIM.EASING_SMOOTHSTEP;if(e=="smootherstep")return m.ANIM.EASING_SMOOTHERSTEP;if(e=="Cubic In")return m.ANIM.EASING_CUBIC_IN;if(e=="Cubic Out")return m.ANIM.EASING_CUBIC_OUT;if(e=="Cubic In Out")return m.ANIM.EASING_CUBIC_INOUT;if(e=="Expo In")return m.ANIM.EASING_EXPO_IN;if(e=="Expo Out")return m.ANIM.EASING_EXPO_OUT;if(e=="Expo In Out")return m.ANIM.EASING_EXPO_INOUT;if(e=="Sin In")return m.ANIM.EASING_SIN_IN;if(e=="Sin Out")return m.ANIM.EASING_SIN_OUT;if(e=="Sin In Out")return m.ANIM.EASING_SIN_INOUT;if(e=="Back In")return m.ANIM.EASING_BACK_IN;if(e=="Back Out")return m.ANIM.EASING_BACK_OUT;if(e=="Back In Out")return m.ANIM.EASING_BACK_INOUT;if(e=="Elastic In")return m.ANIM.EASING_ELASTIC_IN;if(e=="Elastic Out")return m.ANIM.EASING_ELASTIC_OUT;if(e=="Bounce In")return m.ANIM.EASING_BOUNCE_IN;if(e=="Bounce Out")return m.ANIM.EASING_BOUNCE_OUT;if(e=="Quart Out")return m.ANIM.EASING_QUART_OUT;if(e=="Quart In")return m.ANIM.EASING_QUART_IN;if(e=="Quart In Out")return m.ANIM.EASING_QUART_INOUT;if(e=="Quint Out")return m.ANIM.EASING_QUINT_OUT;if(e=="Quint In")return m.ANIM.EASING_QUINT_IN;if(e=="Quint In Out")return m.ANIM.EASING_QUINT_INOUT};A.prototype.createPort=function(e,t,i){const n=e.inDropDown(t,m.ANIM.EASINGS,"Cubic Out");n.set("linear");n.defaultValue="linear";n.onChange=function(){this.defaultEasing=this.easingFromString(n.get());this.emitEvent("onChangeDefaultEasing",this);if(i)i()}.bind(this);return n};A.slerpQuaternion=function(e,t,i,n,r,a){if(!A.slerpQuaternion.q1){A.slerpQuaternion.q1=quat.create();A.slerpQuaternion.q2=quat.create()}const s=i.getKeyIndex(e);let o=s+1;if(o>=i.keys.length)o=i.keys.length-1;if(s==o){quat.set(t,i.keys[s].value,n.keys[s].value,r.keys[s].value,a.keys[s].value)}else{const l=i.keys[s].time;const u=i.keys[o].time;const h=(e-l)/(u-l);quat.set(A.slerpQuaternion.q1,i.keys[s].value,n.keys[s].value,r.keys[s].value,a.keys[s].value);quat.set(A.slerpQuaternion.q2,i.keys[o].value,n.keys[o].value,r.keys[o].value,a.keys[o].value);quat.slerp(t,A.slerpQuaternion.q1,A.slerpQuaternion.q2,h)}return t};const _={Key:f};const S=function(e,t,i,n){c.apply(this);this.data={};this._log=new h("core_port");this.direction=m.PORT.PORT_DIR_IN;this.id=String(CABLES.simpleId());this._op=e;this.links=[];this.value=0;this.name=t;this.type=i||m.OP.OP_PORT_TYPE_VALUE;this.uiAttribs=n||{};this.anim=null;this._oldAnimVal=-5711;this.defaultValue=null;this._uiActiveState=true;this.ignoreValueSerialize=false;this.onLinkChanged=null;this.crashed=false;this._valueBeforeLink=null;this._lastAnimFrame=-1;this._animated=false;this.onValueChanged=null;this.onTriggered=null;this.onUiActiveStateChange=null;this.changeAlways=false;this.forceRefChange=false;this._useVariableName=null;this.activityCounter=0;this.apf=0;this.activityCounterStartFrame=0;this._tempLastUiValue=null;Object.defineProperty(this,"title",{get(){return this.uiAttribs.title||this.name}});Object.defineProperty(this,"parent",{get(){this._log.stack("use port.op, not .parent");return this._op}});Object.defineProperty(this,"op",{get(){return this._op}});Object.defineProperty(this,"val",{get(){return this.get()},set(e){this.setValue(e)}})};S.prototype.copyLinkedUiAttrib=function(e,t){if(!CABLES.UI)return;if(!this.isLinked())return;const i={};i[e]=this.links[0].getOtherPort(this).getUiAttrib(e);t.setUiAttribs(i)};S.prototype.getValueForDisplay=function(){let e=this.value;if(typeof this.value==="string"||this.value instanceof String){if(e.length>1e3){e=e.substring(0,999);e+="..."}if(this.uiAttribs&&this.uiAttribs.display=="boolnum"){e+=" - ";if(!this.value)e+="false";else e+="true"}e=e.replace(/[\u00A0-\u9999<>\&]/g,function(e){return"&#"+e.charCodeAt(0)+";"});if(e.length>100)e=e.substring(0,100)}else{e=this.value}return e};S.prototype.onAnimToggle=function(){};S.prototype._onAnimToggle=function(){this.onAnimToggle()};S.prototype.remove=function(){this.removeLinks();this._op.removePort(this)};S.prototype.setUiAttribs=function(e){let t=false;if(!this.uiAttribs)this.uiAttribs={};for(const i in e){if(e[i]===undefined){delete this.uiAttribs[i];continue}if(this.uiAttribs[i]!=e[i])t=true;this.uiAttribs[i]=e[i];if(i=="group"&&this.indexPort)this.indexPort.setUiAttribs({group:e[i]})}if(e.hasOwnProperty("expose"))this._op.patch.emitEvent("subpatchExpose",this._op.uiAttribs.subPatch);if(t)this.emitEvent("onUiAttrChange",e,this)};S.prototype.getUiAttribs=function(){return this.uiAttribs};S.prototype.getUiAttrib=function(e){if(!this.uiAttribs||!this.uiAttribs.hasOwnProperty(e)){return null}return this.uiAttribs[e]};S.prototype.get=function(){if(this._animated&&this._lastAnimFrame!=this._op.patch.getFrameNum()){this._lastAnimFrame=this._op.patch.getFrameNum();let e=this.anim.getValue(this._op.patch.timer.getTime());if(this.value!=e){this.value=e;this._oldAnimVal=this.value;this.forceChange()}}return this.value};S.prototype.setRef=function(e){this.forceRefChange=true;this.set(e)};S.prototype.set=S.prototype.setValue=function(e){if(e===undefined)e=null;if(CABLES.UI&&CABLES.UI.showDevInfos)if(this.direction==m.PORT.PORT_DIR_OUT&&this.type==m.OP.OP_PORT_TYPE_OBJECT&&e&&!this.forceRefChange)this._log.warn("object port uses .set",this.name,this.op.objName);if(this._op.enabled&&!this.crashed){if(e!==this.value||this.changeAlways||this.type==m.OP.OP_PORT_TYPE_TEXTURE||this.type==m.OP.OP_PORT_TYPE_ARRAY){if(this._animated){this.anim.setValue(this._op.patch.timer.getTime(),e)}else{try{this.value=e;this.forceChange()}catch(e){this.crashed=true;this.setValue=function(e){};this.onTriggered=function(){};this._log.error("exception in ",this._op);this._log.error(e);this._op.patch.emitEvent("exception",e,this._op)}if(this._op&&this._op.patch&&this._op.patch.isEditorMode()&&this.type==m.OP.OP_PORT_TYPE_TEXTURE)gui.texturePreview().updateTexturePort(this)}if(this.direction==m.PORT.PORT_DIR_OUT)for(let e=0;e<this.links.length;++e)this.links[e].setValue()}}};S.prototype.updateAnim=function(){if(this._animated){this.value=this.get();if(this._oldAnimVal!=this.value||this.changeAlways){this._oldAnimVal=this.value;this.forceChange()}this._oldAnimVal=this.value}};S.prototype.forceChange=function(){if(this.onValueChanged||this.onChange){}this._activity();this.emitEvent("change",this.value,this);if(this.onChange)this.onChange(this,this.value);else if(this.onValueChanged)this.onValueChanged(this,this.value)};S.prototype.getTypeString=function(){if(this.type==m.OP.OP_PORT_TYPE_VALUE)return"Number";if(this.type==m.OP.OP_PORT_TYPE_FUNCTION)return"Trigger";if(this.type==m.OP.OP_PORT_TYPE_OBJECT)return"Object";if(this.type==m.OP.OP_PORT_TYPE_DYNAMIC)return"Dynamic";if(this.type==m.OP.OP_PORT_TYPE_ARRAY)return"Array";if(this.type==m.OP.OP_PORT_TYPE_STRING)return"String";return"Unknown"};S.prototype.deSerializeSettings=function(e){if(!e)return;if(e.animated)this.setAnimated(e.animated);if(e.useVariable)this.setVariableName(e.useVariable);if(e.title)this.setUiAttribs({title:e.title});if(e.expose)this.setUiAttribs({expose:true});if(e.order)this.setUiAttribs({order:e.order});if(e.multiPortManual)this.setUiAttribs({multiPortManual:e.multiPortManual});if(e.multiPortNum)this.setUiAttribs({multiPortNum:e.multiPortNum});if(e.anim){if(!this.anim)this.anim=new A({name:"port "+this.name});this._op._hasAnimPort=true;this.anim.addEventListener("onChange",()=>{this._op.patch.emitEvent("portAnimUpdated",this._op,this,this.anim)});if(e.anim.loop)this.anim.loop=e.anim.loop;for(const t in e.anim.keys){this.anim.keys.push(new _.Key(e.anim.keys[t]))}this.anim.sortKeys()}};S.prototype.setInitialValue=function(e){if(this.op.preservedPortLinks[this.name]){for(let e=0;e<this.op.preservedPortLinks[this.name].length;e++){const t=this.op.preservedPortLinks[this.name][e];this.op.patch._addLink(t.objIn,t.objOut,t.portIn,t.portOut)}}if(this.op.preservedPortValues&&this.op.preservedPortValues.hasOwnProperty(this.name)&&this.op.preservedPortValues[this.name]!==undefined){this.set(this.op.preservedPortValues[this.name])}else if(e!==undefined)this.set(e);if(e!==undefined)this.defaultValue=e};S.prototype.getSerialized=function(){let e={name:this.getName()};if(!this.ignoreValueSerialize&&this.links.length===0){if(this.type==m.OP.OP_PORT_TYPE_OBJECT&&this.value&&this.value.tex){}else e.value=this.value}if(this._useVariableName)e.useVariable=this._useVariableName;if(this._animated)e.animated=true;if(this.anim)e.anim=this.anim.getSerialized();if(this.uiAttribs.multiPortNum)e.multiPortNum=this.uiAttribs.multiPortNum;if(this.uiAttribs.multiPortManual)e.multiPortManual=this.uiAttribs.multiPortManual;if(this.uiAttribs.display=="file")e.display=this.uiAttribs.display;if(this.uiAttribs.expose){e.expose=true;if(this.uiAttribs.hasOwnProperty("order"))e.order=this.uiAttribs.order}if(this.uiAttribs.title)e.title=this.uiAttribs.title;if((this.preserveLinks||this.direction==m.PORT.PORT_DIR_OUT)&&this.links.length>0){e.links=[];for(const t in this.links){if(!this.links[t].ignoreInSerialize&&(this.links[t].portIn&&this.links[t].portOut))e.links.push(this.links[t].getSerialized())}}if(this.direction==m.PORT.PORT_DIR_IN&&this.links.length>0){for(const t in this.links){if(!this.links[t].portIn||!this.links[t].portOut)continue;const i=this.links[t].getOtherPort(this);if(i.op.isInBlueprint2&&this.op.isInBlueprint2){if(i.op.isInBlueprint2()&&!this.op.isInBlueprint2()){e.links=e.links||[];e.links.push(this.links[t].getSerialized())}}}}if(e.links&&e.links.length==0)delete e.links;if(this.type===m.OP.OP_PORT_TYPE_FUNCTION)delete e.value;if(this.type===m.OP.OP_PORT_TYPE_FUNCTION&&this.links.length==0)e=null;if(e&&Object.keys(e).length==1&&e.name)e=null;a(e);return e};S.prototype.shouldLink=function(){return true};S.prototype.removeLinks=function(){let e=0;while(this.links.length>0){e++;if(e>5e3){this._log.warn("could not delete links... / infinite loop");this.links.length=0;break}this.links[0].remove()}};S.prototype.removeLink=function(e){for(const t in this.links)if(this.links[t]==e)this.links.splice(t,1);if(this.direction==m.PORT.PORT_DIR_IN){if(this.type==m.OP.OP_PORT_TYPE_VALUE)this.setValue(this._valueBeforeLink||0);else this.setValue(this._valueBeforeLink||null)}if(CABLES.UI&&this._op.checkLinkTimeWarnings)this._op.checkLinkTimeWarnings();try{if(this.onLinkChanged)this.onLinkChanged();this.emitEvent("onLinkChanged");this.emitEvent("onLinkRemoved");this._op.emitEvent("onLinkChanged")}catch(e){this._log.error(e)}};S.prototype.getName=function(){return this.name};S.prototype.getTitle=function(){if(this.uiAttribs.title)return this.uiAttribs.title;return this.name};S.prototype.addLink=function(e){this._valueBeforeLink=this.value;this.links.push(e);if(CABLES.UI&&this._op.checkLinkTimeWarnings)this._op.checkLinkTimeWarnings();try{if(this.onLinkChanged)this.onLinkChanged();this.emitEvent("onLinkChanged");this._op.emitEvent("onLinkChanged")}catch(e){this._log.error(e)}};S.prototype.getLinkTo=function(e){for(const t in this.links)if(this.links[t].portIn==e||this.links[t].portOut==e)return this.links[t]};S.prototype.removeLinkTo=function(e){for(const t in this.links){if(this.links[t].portIn==e||this.links[t].portOut==e){this.links[t].remove();if(CABLES.UI&&this._op.checkLinkTimeWarnings)this._op.checkLinkTimeWarnings();if(this.onLinkChanged)this.onLinkChanged();this.emitEvent("onLinkChanged");this.emitEvent("onLinkRemoved");return}}};S.prototype.isLinkedTo=function(e){for(const t in this.links)if(this.links[t].portIn==e||this.links[t].portOut==e)return true;return false};S.prototype._activity=function(){this.activityCounter++};S.prototype.trigger=function(){const t=this.links.length;this._activity();if(t===0)return;if(!this._op.enabled)return;let i=null;try{for(let e=0;e<t;++e){if(this.links[e].portIn){i=this.links[e].portIn;i.op.patch.pushTriggerStack(i);i._onTriggered();i.op.patch.popTriggerStack()}if(this.links[e])this.links[e].activity()}}catch(e){i.op.enabled=false;if(this._op.patch.isEditorMode()){if(i.op.onError)i.op.onError(e)}this._log.error("exception in port: ",i.name,i.op.name,i.op);this._log.error(e)}};S.prototype.call=function(){this._log.warn("call deprecated - use trigger() ");this.trigger()};S.prototype.execute=function(){this._log.warn("### execute port: "+this.getName(),this.goals.length)};S.prototype.setVariableName=function(e){this._useVariableName=e;this._op.patch.on("variableRename",(e,t)=>{if(e!=this._useVariableName)return;this._useVariableName=t})};S.prototype.getVariableName=function(){return this._useVariableName};S.prototype.setVariable=function(e){this.setAnimated(false);const t={useVariable:false};if(this._variableIn&&this._varChangeListenerId){this._variableIn.off(this._varChangeListenerId);this._variableIn=null}if(e){this._variableIn=this._op.patch.getVar(e);if(!this._variableIn){this._log.warn("PORT VAR NOT FOUND!!!",e)}else{if(this.type==m.OP.OP_PORT_TYPE_OBJECT){this._varChangeListenerId=this._variableIn.on("change",()=>{this.set(null);this.set(this._variableIn.getValue())})}else{this._varChangeListenerId=this._variableIn.on("change",this.set.bind(this))}this.set(this._variableIn.getValue())}this._useVariableName=e;t.useVariable=true;t.variableName=this._useVariableName}else{t.variableName=this._useVariableName=null;t.useVariable=false}this.setUiAttribs(t);this._op.patch.emitEvent("portSetVariable",this._op,this,e)};S.prototype._handleNoTriggerOpAnimUpdates=function(e){let t=false;for(let e=0;e<this._op.portsIn.length;e++){if(this._op.portsIn.type==m.OP.OP_PORT_TYPE_FUNCTION){t=true;break}}if(!t){if(e)this._notriggerAnimUpdate=this._op.patch.on("onRenderFrame",()=>{this.updateAnim()});else this._op.patch.removeEventListener(this._notriggerAnimUpdate)}};S.prototype.setAnimated=function(e){if(this._animated!=e){this._animated=e;this._op._hasAnimPort=true;if(this._animated&&!this.anim){this.anim=new A({name:"port "+this.name});this.anim.addEventListener("onChange",()=>{this._op.patch.emitEvent("portAnimUpdated",this._op,this,this.anim)})}this._onAnimToggle()}this._handleNoTriggerOpAnimUpdates(e);if(!e){this.anim=null}this.setUiAttribs({isAnimated:this._animated})};S.prototype.toggleAnim=function(){this._animated=!this._animated;if(this._animated&&!this.anim){this.anim=new A({name:"port "+this.name});this.anim.addEventListener("onChange",()=>{this._op.patch.emitEvent("portAnimUpdated",this._op,this,this.anim)})}this.setAnimated(this._animated);this._onAnimToggle();this.setUiAttribs({isAnimated:this._animated})};S.prototype.getType=function(){return this.type};S.prototype.isLinked=function(){return this.links.length>0||this._animated||this._useVariableName!=null};S.prototype.isBoundToVar=function(){const e=this._useVariableName!=null;this.uiAttribs.boundToVar=e;return e};S.prototype.isAnimated=function(){return this._animated};S.prototype.isHidden=function(){return this.uiAttribs.hidePort};S.prototype._onTriggered=function(e){this._activity();this._op.updateAnims();if(this._op.enabled&&this.onTriggered)this.onTriggered(e);if(this._op.enabled)this.emitEvent("trigger")};S.prototype._onSetProfiling=function(e){this._op.patch.profiler.add("port",this);this.setValue(e);this._op.patch.profiler.add("port",null)};S.prototype._onTriggeredProfiling=function(){if(this._op.enabled&&this.onTriggered){this._op.patch.profiler.add("port",this);this.onTriggered();this._op.patch.profiler.add("port",null)}};S.prototype.getUiActiveState=function(){return this._uiActiveState};S.prototype.setUiActiveState=function(e){this._uiActiveState=e;if(this.onUiActiveStateChange)this.onUiActiveStateChange()};S.prototype.onValueChange=function(e){this.onChange=e};S.prototype.hidePort=function(){};S.portTypeNumberToString=function(e){if(e==m.OP.OP_PORT_TYPE_VALUE)return"value";if(e==m.OP.OP_PORT_TYPE_FUNCTION)return"function";if(e==m.OP.OP_PORT_TYPE_OBJECT)return"object";if(e==m.OP.OP_PORT_TYPE_ARRAY)return"array";if(e==m.OP.OP_PORT_TYPE_STRING)return"string";if(e==m.OP.OP_PORT_TYPE_DYNAMIC)return"dynamic";return"unknown"};class C{constructor(e,t,i,n,r,a,s,o,l,u){this._log=new h("cg_uniform");this._type=t;this._name=i;this._shader=e;this._value=1e-5;this._oldValue=null;this._port=null;this._structName=l;this._structUniformName=o;this._propertyName=u;this._shader._addUniform(this);this.needsUpdate=true;this.shaderType=null;this.comment=null;if(t=="f"){this.set=this.setValue=this.setValueF.bind(this);this.updateValue=this.updateValueF.bind(this)}else if(t=="f[]"){this.set=this.setValue=this.setValueArrayF.bind(this);this.updateValue=this.updateValueArrayF.bind(this)}else if(t=="2f[]"){this.set=this.setValue=this.setValueArray2F.bind(this);this.updateValue=this.updateValueArray2F.bind(this)}else if(t=="3f[]"){this.set=this.setValue=this.setValueArray3F.bind(this);this.updateValue=this.updateValueArray3F.bind(this)}else if(t=="4f[]"){this.set=this.setValue=this.setValueArray4F.bind(this);this.updateValue=this.updateValueArray4F.bind(this)}else if(t=="i"){this.set=this.setValue=this.setValueI.bind(this);this.updateValue=this.updateValueI.bind(this)}else if(t=="2i"){this.set=this.setValue=this.setValue2I.bind(this);this.updateValue=this.updateValue2I.bind(this)}else if(t=="3i"){this.set=this.setValue=this.setValue3I.bind(this);this.updateValue=this.updateValue3I.bind(this)}else if(t=="4i"){this.set=this.setValue=this.setValue4I.bind(this);this.updateValue=this.updateValue4I.bind(this)}else if(t=="b"){this.set=this.setValue=this.setValueBool.bind(this);this.updateValue=this.updateValueBool.bind(this)}else if(t=="4f"){this.set=this.setValue=this.setValue4F.bind(this);this.updateValue=this.updateValue4F.bind(this)}else if(t=="3f"){this.set=this.setValue=this.setValue3F.bind(this);this.updateValue=this.updateValue3F.bind(this)}else if(t=="2f"){this.set=this.setValue=this.setValue2F.bind(this);this.updateValue=this.updateValue2F.bind(this)}else if(t=="t"){this.set=this.setValue=this.setValueT.bind(this);this.updateValue=this.updateValueT.bind(this)}else if(t=="sampler"){if(this.setValueAny){this.set=this.setValue=this.setValueAny.bind(this);this.updateValue=this.updateValueAny.bind(this)}}else if(t=="tc"){this.set=this.setValue=this.setValueT.bind(this);this.updateValue=this.updateValueT.bind(this)}else if(t=="t[]"){this.set=this.setValue=this.setValueArrayT.bind(this);this.updateValue=this.updateValueArrayT.bind(this)}else if(t=="m4"||t=="m4[]"){this.set=this.setValue=this.setValueM4.bind(this);this.updateValue=this.updateValueM4.bind(this)}else{this._log.error("Unknown uniform type "+t)}if(typeof n=="object"&&n instanceof S){this._port=n;this._value=this._port.get();if(r&&a&&s){if(!(r instanceof S)||!(a instanceof S)||!(s instanceof S)){this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ",this._name)}this._value=[0,0,0,0];this._port2=r;this._port3=a;this._port4=s;this._port.on("change",this.updateFromPort4f.bind(this));this._port2.on("change",this.updateFromPort4f.bind(this));this._port3.on("change",this.updateFromPort4f.bind(this));this._port4.on("change",this.updateFromPort4f.bind(this));this.updateFromPort4f()}else if(r&&a){if(!(r instanceof S)||!(a instanceof S)){this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ",this._name)}this._value=[0,0,0];this._port2=r;this._port3=a;this._port.on("change",this.updateFromPort3f.bind(this));this._port2.on("change",this.updateFromPort3f.bind(this));this._port3.on("change",this.updateFromPort3f.bind(this));this.updateFromPort3f()}else if(r){if(!(r instanceof S)){this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ",this._name)}this._value=[0,0];this._port2=r;this._port.on("change",this.updateFromPort2f.bind(this));this._port2.on("change",this.updateFromPort2f.bind(this));this.updateFromPort2f()}else{this._port.on("change",this.updateFromPort.bind(this))}}else this._value=n;if(this._value==undefined){console.log("value undefined",this);this._value=0}this.setValue(this._value);this.needsUpdate=true}getType(){return this._type}get type(){return this._type}get name(){return this._name}getName(){return this._name}getValue(){return this._value}getShaderType(){return this.shaderType}isStructMember(){return!!this._structName}updateFromPort4f(){this._value[0]=this._port.get();this._value[1]=this._port2.get();this._value[2]=this._port3.get();this._value[3]=this._port4.get();this.setValue(this._value)}updateFromPort3f(){this._value[0]=this._port.get();this._value[1]=this._port2.get();this._value[2]=this._port3.get();this.setValue(this._value)}updateFromPort2f(){this._value[0]=this._port.get();this._value[1]=this._port2.get();this.setValue(this._value)}updateFromPort(){this.setValue(this._port.get())}}const T=C;class I extends T{constructor(e,t,i,n,r,a,s,o,l,u){super(e,t,i,n,r,a,s,o,l,u);this._loc=-1;this._cgl=e._cgl}get name(){return this._name}copy(e){const t=new I(e,this._type,this._name,this._value,this._port2,this._port3,this._port4,this._structUniformName,this._structName,this._propertyName);t.shaderType=this.shaderType;return t}getGlslTypeString(){return I.glslTypeString(this._type)}_isValidLoc(){return this._loc!=-1}resetLoc(){this._loc=-1;this.needsUpdate=true}bindTextures(){}getLoc(){return this._loc}updateFromPort4f(){this._value[0]=this._port.get();this._value[1]=this._port2.get();this._value[2]=this._port3.get();this._value[3]=this._port4.get();this.setValue(this._value)}updateFromPort3f(){this._value[0]=this._port.get();this._value[1]=this._port2.get();this._value[2]=this._port3.get();this.setValue(this._value)}updateFromPort2f(){this._value[0]=this._port.get();this._value[1]=this._port2.get();this.setValue(this._value)}updateFromPort(){this.setValue(this._port.get())}updateValueF(){if(!this._isValidLoc())this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);else this.needsUpdate=false;this._shader.getCgl().gl.uniform1f(this._loc,this._value);this._cgl.profileData.profileUniformCount++}setValueF(e){if(e!=this._value){this.needsUpdate=true;this._value=e}}updateValueI(){if(!this._isValidLoc())this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);else this.needsUpdate=false;this._shader.getCgl().gl.uniform1i(this._loc,this._value);this._cgl.profileData.profileUniformCount++}updateValue2I(){if(!this._value)return;if(!this._isValidLoc()){this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);this._cgl.profileData.profileShaderGetUniform++;this._cgl.profileData.profileShaderGetUniformName=this._name}this._shader.getCgl().gl.uniform2i(this._loc,this._value[0],this._value[1]);this.needsUpdate=false;this._cgl.profileData.profileUniformCount++}updateValue3I(){if(!this._value)return;if(!this._isValidLoc()){this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);this._cgl.profileData.profileShaderGetUniform++;this._cgl.profileData.profileShaderGetUniformName=this._name}this._shader.getCgl().gl.uniform3i(this._loc,this._value[0],this._value[1],this._value[2]);this.needsUpdate=false;this._cgl.profileData.profileUniformCount++}updateValue4I(){if(!this._isValidLoc()){this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);this._cgl.profileData.profileShaderGetUniform++;this._cgl.profileData.profileShaderGetUniformName=this._name}this._shader.getCgl().gl.uniform4i(this._loc,this._value[0],this._value[1],this._value[2],this._value[3]);this._cgl.profileData.profileUniformCount++}setValueI(e){if(e!=this._value){this.needsUpdate=true;this._value=e}}setValue2I(e){if(!e)return;if(!this._oldValue){this._oldValue=[e[0]-1,1];this.needsUpdate=true}else if(e[0]!=this._oldValue[0]||e[1]!=this._oldValue[1]){this._oldValue[0]=e[0];this._oldValue[1]=e[1];this.needsUpdate=true}this._value=e}setValue3I(e){if(!e)return;if(!this._oldValue){this._oldValue=[e[0]-1,1,2];this.needsUpdate=true}else if(e[0]!=this._oldValue[0]||e[1]!=this._oldValue[1]||e[2]!=this._oldValue[2]){this._oldValue[0]=e[0];this._oldValue[1]=e[1];this._oldValue[2]=e[2];this.needsUpdate=true}this._value=e}setValue4I(e){this.needsUpdate=true;this._value=e||vec4.create()}updateValueBool(){if(!this._isValidLoc())this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);else this.needsUpdate=false;this._shader.getCgl().gl.uniform1i(this._loc,this._value?1:0);this._cgl.profileData.profileUniformCount++}setValueBool(e){if(e!=this._value){this.needsUpdate=true;this._value=e}}setValueArray4F(e){this.needsUpdate=true;this._value=e}updateValueArray4F(){if(!this._isValidLoc())this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);else this.needsUpdate=false;if(!this._value)return;this._shader.getCgl().gl.uniform4fv(this._loc,this._value);this._cgl.profileData.profileUniformCount++}setValueArray3F(e){this.needsUpdate=true;this._value=e}updateValueArray3F(){if(!this._isValidLoc())this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);else this.needsUpdate=false;if(!this._value)return;this._shader.getCgl().gl.uniform3fv(this._loc,this._value);this._cgl.profileData.profileUniformCount++}setValueArray2F(e){this.needsUpdate=true;this._value=e}updateValueArray2F(){if(!this._isValidLoc())this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);else this.needsUpdate=false;if(!this._value)return;this._shader.getCgl().gl.uniform2fv(this._loc,this._value);this._cgl.profileData.profileUniformCount++}setValueArrayF(e){this.needsUpdate=true;this._value=e}updateValueArrayF(){if(!this._isValidLoc())this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);else this.needsUpdate=false;if(!this._value)return;this._shader.getCgl().gl.uniform1fv(this._loc,this._value);this._cgl.profileData.profileUniformCount++}setValueArrayT(e){this.needsUpdate=true;this._value=e}updateValue3F(){if(!this._value)return;if(!this._isValidLoc()){this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);this._cgl.profileData.profileShaderGetUniform++;this._cgl.profileData.profileShaderGetUniformName=this._name}this._shader.getCgl().gl.uniform3f(this._loc,this._value[0],this._value[1],this._value[2]);this.needsUpdate=false;this._cgl.profileData.profileUniformCount++}setValue3F(e){if(!e)return;if(!this._oldValue){this._oldValue=[e[0]-1,1,2];this.needsUpdate=true}else if(e[0]!=this._oldValue[0]||e[1]!=this._oldValue[1]||e[2]!=this._oldValue[2]){this._oldValue[0]=e[0];this._oldValue[1]=e[1];this._oldValue[2]=e[2];this.needsUpdate=true}this._value=e}updateValue2F(){if(!this._value)return;if(!this._isValidLoc()){this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);this._cgl.profileData.profileShaderGetUniform++;this._cgl.profileData.profileShaderGetUniformName=this._name}this._shader.getCgl().gl.uniform2f(this._loc,this._value[0],this._value[1]);this.needsUpdate=false;this._cgl.profileData.profileUniformCount++}setValue2F(e){if(!e)return;if(!this._oldValue){this._oldValue=[e[0]-1,1];this.needsUpdate=true}else if(e[0]!=this._oldValue[0]||e[1]!=this._oldValue[1]){this._oldValue[0]=e[0];this._oldValue[1]=e[1];this.needsUpdate=true}this._value=e}updateValue4F(){if(!this._isValidLoc()){this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);this._cgl.profileData.profileShaderGetUniform++;this._cgl.profileData.profileShaderGetUniformName=this._name}if(!this._value){this._log.warn("no value for uniform",this._name,this);this._value=[0,0,0,0]}this.needsUpdate=false;this._shader.getCgl().gl.uniform4f(this._loc,this._value[0],this._value[1],this._value[2],this._value[3]);this._cgl.profileData.profileUniformCount++}setValue4F(e){if(typeof this.value=="number")this.value=vec4.create();if(!e)return;if(!this._oldValue){this._oldValue=[e[0]-1,1,2,3];this.needsUpdate=true}else if(e[0]!=this._oldValue[0]||e[1]!=this._oldValue[1]||e[2]!=this._oldValue[2]||e[3]!=this._oldValue[3]){this._oldValue[0]=e[0];this._oldValue[1]=e[1];this._oldValue[2]=e[2];this.needsUpdate=true}this._value=e}updateValueM4(){if(!this._isValidLoc()){this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);this._cgl.profileData.profileShaderGetUniform++;this._cgl.profileData.profileShaderGetUniformName=this._name}if(!this._value||this._value.length%16!=0)return console.log("this.name",this._name,this._value);this._shader.getCgl().gl.uniformMatrix4fv(this._loc,false,this._value);this._cgl.profileData.profileUniformCount++}setValueM4(e){this.needsUpdate=true;this._value=e||mat4.create()}updateValueArrayT(){if(!this._isValidLoc())this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);else this.needsUpdate=false;if(!this._value)return;this._shader.getCgl().gl.uniform1iv(this._loc,this._value);this._cgl.profileData.profileUniformCount++}updateValueT(){if(!this._isValidLoc()){this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name);this._cgl.profileData.profileShaderGetUniform++;this._cgl.profileData.profileShaderGetUniformName=this._name}this._cgl.profileData.profileUniformCount++;this._shader.getCgl().gl.uniform1i(this._loc,this._value);this.needsUpdate=false}setValueT(e){this.needsUpdate=true;this._value=e}}I.glslTypeString=e=>{if(e=="f")return"float";if(e=="b")return"bool";if(e=="i")return"int";if(e=="2i")return"ivec2";if(e=="2f")return"vec2";if(e=="3f")return"vec3";if(e=="4f")return"vec4";if(e=="m4")return"mat4";if(e=="t")return"sampler2D";if(e=="tc")return"samplerCube";if(e=="3f[]")return null;if(e=="m4[]")return null;if(e=="f[]")return null;console.warn("[CGL UNIFORM] unknown glsl type string ",e)};const O={SHADERVAR_VERTEX_POSITION:"vPosition",SHADERVAR_VERTEX_NUMBER:"attrVertIndex",SHADERVAR_VERTEX_NORMAL:"attrVertNormal",SHADERVAR_VERTEX_TEXCOORD:"attrTexCoord",SHADERVAR_INSTANCE_MMATRIX:"instMat",SHADERVAR_VERTEX_COLOR:"attrVertColor",SHADERVAR_INSTANCE_INDEX:"instanceIndex",SHADERVAR_UNI_PROJMAT:"projMatrix",SHADERVAR_UNI_VIEWMAT:"viewMatrix",SHADERVAR_UNI_MODELMAT:"modelMatrix",SHADERVAR_UNI_NORMALMAT:"normalMatrix",SHADERVAR_UNI_INVVIEWMAT:"inverseViewMatrix",SHADERVAR_UNI_INVPROJMAT:"invProjMatrix",SHADERVAR_UNI_MATERIALID:"materialId",SHADERVAR_UNI_OBJECTID:"objectId",SHADERVAR_UNI_VIEWPOS:"camPos"};const E={BLEND_NONE:0,BLEND_NORMAL:1,BLEND_ADD:2,BLEND_SUB:3,BLEND_MUL:4};const P=180/Math.PI;const M=Math.PI/180;const L={MATH:{DEG2RAD:M,RAD2DEG:P},SHADER:O,BLEND_MODES:E};const N={};N.lastMesh=null;const k=function(e,t,i){this._cgl=e;let n=i||{};if(CABLES.UTILS.isNumeric(n))n={glPrimitive:i};this._log=new h("cgl_mesh");this._bufVertexAttrib=null;this._bufVerticesIndizes=this._cgl.gl.createBuffer();this._indexType=this._cgl.gl.UNSIGNED_SHORT;this._attributes=[];this._attribLocs={};this._geom=null;this._lastShader=null;this._numInstances=0;this._glPrimitive=n.glPrimitive;this.opId=n.opId||"";this._preWireframeGeom=null;this.addVertexNumbers=false;this._name="unknown";this.feedBackAttributes=[];this.setGeom(t);this._feedBacks=[];this._feedBacksChanged=false;this._transformFeedBackLoc=-1;this._lastAttrUpdate=0;this.memFreed=false;this._cgl.profileData.addHeavyEvent("mesh constructed",this._name);this._queryExt=null;Object.defineProperty(this,"numInstances",{get(){return this._numInstances},set(e){this.setNumInstances(e)}})};k.prototype.freeMem=function(){this.memFreed=true;for(let e=0;e<this._attributes.length;e++){this._attributes[e].floatArray=null}};k.prototype.updateVertices=function(e){this.setAttribute(L.SHADER.SHADERVAR_VERTEX_POSITION,e.vertices,3);this._numVerts=e.vertices.length/3};k.prototype.setAttributePointer=function(t,i,n,r){for(let e=0;e<this._attributes.length;e++){if(this._attributes[e].name==t){if(!this._attributes[e].pointer)this._attributes[e].pointer=[];this._attributes[e].pointer.push({loc:-1,name:i,stride:n,offset:r,instanced:t==L.SHADER.SHADERVAR_INSTANCE_MMATRIX})}}};k.prototype.getAttribute=function(t){for(let e=0;e<this._attributes.length;e++)if(this._attributes[e].name==t)return this._attributes[e]};k.prototype.setAttributeRange=function(e,t,i,n){if(!e)return;if(!i&&!n)return;if(!e.name){this._log.stack("no attrname?!")}this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER,e.buffer);this._cgl.profileData.profileMeshAttributes+=n-i||0;this._cgl.profileData.profileSingleMeshAttribute[this._name]=this._cgl.profileData.profileSingleMeshAttribute[this._name]||0;this._cgl.profileData.profileSingleMeshAttribute[this._name]+=n-i||0;if(e.numItems<t.length/e.itemSize){this._resizeAttr(t,e)}if(n>t.length){if(CABLES.platform.isDevEnv())this._log.log(this._cgl.canvas.id+" "+e.name+" buffersubdata out of bounds ?",t.length,n,i,e);return}if(this._cgl.glVersion==1)this._cgl.gl.bufferSubData(this._cgl.gl.ARRAY_BUFFER,0,t);else this._cgl.gl.bufferSubData(this._cgl.gl.ARRAY_BUFFER,i*4,t,i,n-i)};k.prototype._resizeAttr=function(e,t){if(t.buffer)this._cgl.gl.deleteBuffer(t.buffer);t.buffer=this._cgl.gl.createBuffer();this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER,t.buffer);this._bufferArray(e,t);t.numItems=e.length/t.itemSize};k.prototype._bufferArray=function(e,t){let i=t.floatArray||null;if(!e)return;if(this._cgl.debugOneFrame){console.log("_bufferArray",e.length,t.name)}if(!(e instanceof Float32Array)){if(t&&i&&i.length==e.length){i.set(e)}else{i=new Float32Array(e);if(this._cgl.debugOneFrame){console.log("_bufferArray create new float32array",e.length,t.name)}if(e.length>1e4){this._cgl.profileData.profileNonTypedAttrib++;this._cgl.profileData.profileNonTypedAttribNames="("+this._name+":"+t.name+")"}}}else i=e;t.arrayLength=i.length;t.floatArray=null;this._cgl.gl.bufferData(this._cgl.gl.ARRAY_BUFFER,i,this._cgl.gl.DYNAMIC_DRAW)};k.prototype.addAttribute=k.prototype.updateAttribute=k.prototype.setAttribute=function(e,t,i,n){if(!t){this._log.error("mesh addAttribute - no array given! "+e);throw new Error}let r=null;let a=false;let s=0;const o=t.length/i;this._cgl.profileData.profileMeshAttributes+=o||0;if(typeof n=="function"){r=n}if(typeof n=="object"){if(n.cb)r=n.cb;if(n.instanced)a=n.instanced}if(e==L.SHADER.SHADERVAR_INSTANCE_MMATRIX)a=true;for(s=0;s<this._attributes.length;s++){const h=this._attributes[s];if(h.name==e){if(h.numItems===o){}else{this._resizeAttr(t,h)}this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER,h.buffer);this._bufferArray(t,h);return h}}const l=this._cgl.gl.createBuffer();this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER,l);let u=this._cgl.gl.FLOAT;if(n&&n.type)u=n.type;const h={buffer:l,name:e,cb:r,itemSize:i,numItems:o,startItem:0,instanced:a,type:u};this._bufferArray(t,h);if(e==L.SHADER.SHADERVAR_VERTEX_POSITION)this._bufVertexAttrib=h;this._attributes.push(h);this._attribLocs={};return h};k.prototype.getAttributes=function(){return this._attributes};k.prototype.updateTexCoords=function(e){if(e.texCoords&&e.texCoords.length>0){this.setAttribute(L.SHADER.SHADERVAR_VERTEX_TEXCOORD,e.texCoords,2)}else{const t=new Float32Array(Math.round(e.vertices.length/3*2));this.setAttribute(L.SHADER.SHADERVAR_VERTEX_TEXCOORD,t,2)}};k.prototype.updateNormals=function(e){if(e.vertexNormals&&e.vertexNormals.length>0){this.setAttribute(L.SHADER.SHADERVAR_VERTEX_NORMAL,e.vertexNormals,3)}else{const t=new Float32Array(Math.round(e.vertices.length));this.setAttribute(L.SHADER.SHADERVAR_VERTEX_NORMAL,t,3)}};k.prototype._setVertexNumbers=function(e){if(!this._verticesNumbers||this._verticesNumbers.length!=this._numVerts||e){if(e)this._verticesNumbers=e;else{this._verticesNumbers=new Float32Array(this._numVerts);for(let e=0;e<this._numVerts;e++)this._verticesNumbers[e]=e}this.setAttribute(L.SHADER.SHADERVAR_VERTEX_NUMBER,this._verticesNumbers,1,(e,t,i)=>{if(!i.uniformNumVertices)i.uniformNumVertices=new I(i,"f","numVertices",this._numVerts);i.uniformNumVertices.setValue(this._numVerts)})}};k.prototype.setVertexIndices=function(t){if(!this._bufVerticesIndizes){this._log.warn("no bufVerticesIndizes: "+this._name);return}if(t.length>0){if(t instanceof Float32Array)this._log.warn("vertIndices float32Array: "+this._name);for(let e=0;e<t.length;e++){if(t[e]>=this._numVerts){this._log.warn("invalid index in "+this._name,e,t[e]);return}}this._cgl.gl.bindBuffer(this._cgl.gl.ELEMENT_ARRAY_BUFFER,this._bufVerticesIndizes);if(t.length>65535){this.vertIndicesTyped=new Uint32Array(t);this._indexType=this._cgl.gl.UNSIGNED_INT}else if(t instanceof Uint32Array){this.vertIndicesTyped=t;this._indexType=this._cgl.gl.UNSIGNED_INT}else if(!(t instanceof Uint16Array)){this.vertIndicesTyped=new Uint16Array(t);this._indexType=this._cgl.gl.UNSIGNED_SHORT}else this.vertIndicesTyped=t;this._cgl.gl.bufferData(this._cgl.gl.ELEMENT_ARRAY_BUFFER,this.vertIndicesTyped,this._cgl.gl.DYNAMIC_DRAW);this._bufVerticesIndizes.itemSize=1;this._bufVerticesIndizes.numItems=t.length}else this._bufVerticesIndizes.numItems=0};k.prototype.setGeom=function(e,t){this._geom=e;if(e.glPrimitive!=null)this._glPrimitive=e.glPrimitive;if(this._geom&&this._geom.name)this._name="mesh "+this._geom.name;N.lastMesh=null;this._cgl.profileData.profileMeshSetGeom++;this._disposeAttributes();this.updateVertices(this._geom);this.setVertexIndices(this._geom.verticesIndices);if(this.addVertexNumbers)this._setVertexNumbers();const i=this._geom.getAttributes();const n={texCoords:L.SHADER.SHADERVAR_VERTEX_TEXCOORD,vertexNormals:L.SHADER.SHADERVAR_VERTEX_NORMAL,vertexColors:L.SHADER.SHADERVAR_VERTEX_COLOR,tangents:"attrTangent",biTangents:"attrBiTangent"};for(const r in i)if(i[r].data&&i[r].data.length)this.setAttribute(n[r]||r,i[r].data,i[r].itemSize);if(t){this._geom=null}};k.prototype._preBind=function(t){for(let e=0;e<this._attributes.length;e++)if(this._attributes[e].cb)this._attributes[e].cb(this._attributes[e],this._geom,t)};k.prototype._checkAttrLengths=function(){if(this.memFreed)return;for(let e=0;e<this._attributes.length;e++){if(this._attributes[e].arrayLength/this._attributes[e].itemSize<this._attributes[0].arrayLength/this._attributes[0].itemSize){let e="unknown";if(this._geom)e=this._geom.name}}};k.prototype._bind=function(t){if(!t.isValid())return;let i=[];if(this._attribLocs[t.id])i=this._attribLocs[t.id];else this._attribLocs[t.id]=i;this._lastShader=t;if(t.lastCompile>this._lastAttrUpdate||i.length!=this._attributes.length){this._lastAttrUpdate=t.lastCompile;for(let e=0;e<this._attributes.length;e++)i[e]=-1}for(let e=0;e<this._attributes.length;e++){const n=this._attributes[e];if(i[e]==-1){if(n._attrLocationLastShaderTime!=t.lastCompile){n._attrLocationLastShaderTime=t.lastCompile;i[e]=this._cgl.glGetAttribLocation(t.getProgram(),n.name);this._cgl.profileData.profileAttrLoc++}}if(i[e]!=-1){this._cgl.gl.enableVertexAttribArray(i[e]);this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER,n.buffer);if(n.instanced){if(n.itemSize<=4){if(!n.itemSize||n.itemSize==0)this._log.warn("instanced attrib itemsize error",this._geom.name,n);this._cgl.gl.vertexAttribPointer(i[e],n.itemSize,n.type,false,n.itemSize*4,0);this._cgl.gl.vertexAttribDivisor(i[e],1)}else if(n.itemSize==16){const r=16*4;this._cgl.gl.vertexAttribPointer(i[e],4,n.type,false,r,0);this._cgl.gl.enableVertexAttribArray(i[e]+1);this._cgl.gl.vertexAttribPointer(i[e]+1,4,n.type,false,r,4*4*1);this._cgl.gl.enableVertexAttribArray(i[e]+2);this._cgl.gl.vertexAttribPointer(i[e]+2,4,n.type,false,r,4*4*2);this._cgl.gl.enableVertexAttribArray(i[e]+3);this._cgl.gl.vertexAttribPointer(i[e]+3,4,n.type,false,r,4*4*3);this._cgl.gl.vertexAttribDivisor(i[e],1);this._cgl.gl.vertexAttribDivisor(i[e]+1,1);this._cgl.gl.vertexAttribDivisor(i[e]+2,1);this._cgl.gl.vertexAttribDivisor(i[e]+3,1)}else{this._log.warn("unknown instance attrib size",n.name)}}else{if(!n.itemSize||n.itemSize==0)this._log.warn("attrib itemsize error",this._name,n);this._cgl.gl.vertexAttribPointer(i[e],n.itemSize,n.type,false,n.itemSize*4,0);if(n.pointer){for(let e=0;e<n.pointer.length;e++){const a=n.pointer[e];if(a.loc==-1)a.loc=this._cgl.glGetAttribLocation(t.getProgram(),a.name);this._cgl.profileData.profileAttrLoc++;this._cgl.gl.enableVertexAttribArray(a.loc);this._cgl.gl.vertexAttribPointer(a.loc,n.itemSize,n.type,false,a.stride,a.offset)}}if(this.bindFeedback)this.bindFeedback(n)}}}if(this._bufVerticesIndizes&&this._bufVerticesIndizes.numItems!==0)this._cgl.gl.bindBuffer(this._cgl.gl.ELEMENT_ARRAY_BUFFER,this._bufVerticesIndizes)};k.prototype.unBind=function(){const e=this._lastShader;this._lastShader=null;if(!e)return;let t=[];if(this._attribLocs[e.id])t=this._attribLocs[e.id];else this._attribLocs[e.id]=t;N.lastMesh=null;for(let e=0;e<this._attributes.length;e++){if(this._attributes[e].instanced){if(this._attributes[e].itemSize<=4){if(t[e]!=-1)this._cgl.gl.vertexAttribDivisor(t[e],0);if(t[e]>=0)this._cgl.gl.disableVertexAttribArray(t[e])}else{this._cgl.gl.vertexAttribDivisor(t[e],0);this._cgl.gl.vertexAttribDivisor(t[e]+1,0);this._cgl.gl.vertexAttribDivisor(t[e]+2,0);this._cgl.gl.vertexAttribDivisor(t[e]+3,0);this._cgl.gl.disableVertexAttribArray(t[e]+1);this._cgl.gl.disableVertexAttribArray(t[e]+2);this._cgl.gl.disableVertexAttribArray(t[e]+3)}}if(t[e]!=-1)this._cgl.gl.disableVertexAttribArray(t[e])}};k.prototype.meshChanged=function(){return this._cgl.lastMesh&&this._cgl.lastMesh!=this};k.prototype.printDebug=function(e){console.log("--attributes");for(let e=0;e<this._attributes.length;e++){console.log("attribute "+e+" "+this._attributes[e].name)}};k.prototype.setNumVertices=function(e){this._bufVertexAttrib.numItems=e};k.prototype.getNumVertices=function(){return this._bufVertexAttrib.numItems};k.prototype.render=function(i){if(!i||!i.isValid()||this._cgl.aborted)return;this._checkAttrLengths();if(this._geom){if(this._preWireframeGeom&&!i.wireframe&&!this._geom.isIndexed()){this.setGeom(this._preWireframeGeom);this._preWireframeGeom=null}if(i.wireframe){let e=false;if(this._geom.isIndexed()){if(!this._preWireframeGeom){this._preWireframeGeom=this._geom;this._geom=this._geom.copy()}this._geom.unIndex();e=true}if(!this._geom.getAttribute("attrBarycentric")){if(!this._preWireframeGeom){this._preWireframeGeom=this._geom;this._geom=this._geom.copy()}e=true;this._geom.calcBarycentric()}if(e)this.setGeom(this._geom)}}let e=false;if(N.lastMesh!=this){if(N.lastMesh)N.lastMesh.unBind();e=true}if(e)this._preBind(i);if(!i.bind())return;this._bind(i);if(this.addVertexNumbers)this._setVertexNumbers();N.lastMesh=this;let t=this._cgl.gl.TRIANGLES;if(this._glPrimitive!==undefined)t=this._glPrimitive;if(i.glPrimitive!==null)t=i.glPrimitive;let n=1;let r=this._cgl.profileData.doProfileGlQuery;let a=false;if(r){let e=this._name+" - "+i.getName()+" #"+i.id;if(this._numInstances)e+=" instanced "+this._numInstances+"x";let t=this._cgl.profileData.glQueryData[e];if(!t)t={id:e,num:0};if(i.opId)t.shaderOp=i.opId;if(this.opId)t.meshOp=this.opId;this._cgl.profileData.glQueryData[e]=t;if(!this._queryExt&&this._queryExt!==false)this._queryExt=this._cgl.enableExtension("EXT_disjoint_timer_query_webgl2")||false;if(this._queryExt){if(t._drawQuery){const s=this._cgl.gl.getQueryParameter(t._drawQuery,this._cgl.gl.QUERY_RESULT_AVAILABLE);if(s){const o=this._cgl.gl.getQueryParameter(t._drawQuery,this._cgl.gl.QUERY_RESULT);const l=o/1e6;t._times=t._times||0;t._times+=l;t._numcount++;t.when=performance.now();t._drawQuery=null;t.queryStarted=false}}if(!t.queryStarted){t._drawQuery=this._cgl.gl.createQuery();this._cgl.gl.beginQuery(this._queryExt.TIME_ELAPSED_EXT,t._drawQuery);a=t.queryStarted=true}}}if(this.hasFeedbacks&&this.hasFeedbacks())this.drawFeedbacks(i,t);else if(!this._bufVerticesIndizes||this._bufVerticesIndizes.numItems===0){if(t==this._cgl.gl.TRIANGLES)n=3;if(this._numInstances===0)this._cgl.gl.drawArrays(t,this._bufVertexAttrib.startItem,this._bufVertexAttrib.numItems-this._bufVertexAttrib.startItem);else this._cgl.gl.drawArraysInstanced(t,this._bufVertexAttrib.startItem,this._bufVertexAttrib.numItems,this._numInstances)}else{if(t==this._cgl.gl.TRIANGLES)n=3;if(this._numInstances===0){this._cgl.gl.drawElements(t,this._bufVerticesIndizes.numItems,this._indexType,0)}else{this._cgl.gl.drawElementsInstanced(t,this._bufVerticesIndizes.numItems,this._indexType,0,this._numInstances)}}if(this._cgl.debugOneFrame&&this._cgl.gl.getError()!=this._cgl.gl.NO_ERROR){this._log.error("mesh draw gl error");this._log.error("mesh",this);this._log.error("shader",i);const u=[];for(let e=0;e<this._cgl.gl.getProgramParameter(i.getProgram(),this._cgl.gl.ACTIVE_ATTRIBUTES);e++){const h=this._cgl.gl.getActiveAttrib(i.getProgram(),e).name;this._log.error("attrib ",h)}}this._cgl.profileData.profileMeshNumElements+=this._bufVertexAttrib.numItems/n*(this._numInstances||1);this._cgl.profileData.profileMeshDraw++;if(r&&a){this._cgl.gl.endQuery(this._queryExt.TIME_ELAPSED_EXT)}this._cgl.printError("mesh render "+this._name);this.unBind()};k.prototype.setNumInstances=function(t){t=Math.max(0,t);if(this._numInstances!=t){this._numInstances=t;const i=new Float32Array(t);for(let e=0;e<t;e++)i[e]=e;this.setAttribute(L.SHADER.SHADERVAR_INSTANCE_INDEX,i,1,{instanced:true})}};k.prototype._disposeAttributes=function(){if(!this._attributes)return;for(let e=0;e<this._attributes.length;e++){if(this._attributes[e].buffer){this._cgl.gl.deleteBuffer(this._attributes[e].buffer);this._attributes[e].buffer=null}}this._attributes.length=0};k.prototype.dispose=function(){if(this._bufVertexAttrib&&this._bufVertexAttrib.buffer)this._cgl.gl.deleteBuffer(this._bufVertexAttrib.buffer);if(this._bufVerticesIndizes)this._cgl.gl.deleteBuffer(this._bufVerticesIndizes);this._bufVerticesIndizes=null;this._disposeAttributes()};const w={};w.getSimpleRect=function(e,t,i=1){const n=new p(t);n.vertices=[1*i,1*i,0,-1*i,1*i,0,1*i,-1*i,0,-1*i,-1*i,0];n.texCoords=[1,1,0,1,1,0,0,0];n.verticesIndices=[0,1,2,2,1,3];n.vertexNormals=[0,0,0,0,0,0,0,0,0,0,0,0];return e.createMesh(n)};w.getSimpleCube=function(e,t){const i=new p(t);i.vertices=[-1,-1,1,1,-1,1,1,1,1,-1,1,1,-1,-1,-1,1,-1,-1,1,1,-1,-1,1,-1,-1,1,-1,1,1,-1,1,1,1,-1,1,1,-1,-1,-1,1,-1,-1,1,-1,1,-1,-1,1,1,-1,-1,1,-1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,1,-1,1,1,-1,1,-1];i.setTexCoords([0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,1,0,0,0,1,1,1,1,0,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,0,1,1,1,1,0,0,0]);i.verticesIndices=[0,1,2,0,2,3,4,5,6,4,6,7,8,9,10,8,10,11,12,13,14,12,14,15,16,17,18,16,18,19,20,21,22,20,22,23];i.vertexNormals=new Float32Array([0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0]);i.tangents=new Float32Array([0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1]);i.biTangents=new Float32Array([-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1]);return new k(e,i)};class R{constructor(e,t,i){this.cgl=e;this._options=i;this.fb=null;let n=i.shader;this._useDefaultShader=true;if(i.shader)this._useDefaultShader=false;i.numRenderBuffers=i.numRenderBuffers||1;if(!n){n="".endl()+"IN vec2 texCoord;";for(let e=0;e<i.numRenderBuffers;e++){n=n.endl()+"UNI sampler2D tex"+e+";".endl()}n=n.endl()+"void main()".endl()+"{";if(i.numRenderBuffers==1){n=n.endl()+"    outColor= texture(tex0,texCoord);".endl()}else for(let e=0;e<i.numRenderBuffers;e++){n=n.endl()+"outColor"+e+" = texture(tex"+e+",texCoord);".endl()}n=n.endl()+"}"}const r=i.vertexShader||"".endl()+"IN vec3 vPosition;".endl()+"IN vec2 attrTexCoord;".endl()+"OUT vec2 texCoord;".endl()+"void main()".endl()+"{".endl()+"   texCoord=attrTexCoord;".endl()+"   gl_Position = vec4(vPosition,  1.0);".endl()+"}";this.bgShader=new CGL.Shader(e,"corelib copytexture "+t);this.bgShader.setSource(r,n);if(!i.vertexShader)this.bgShader.ignoreMissingUniforms=true;new CGL.Uniform(this.bgShader,"t","tex",0);new CGL.Uniform(this.bgShader,"t","tex1",1);new CGL.Uniform(this.bgShader,"t","tex2",2);new CGL.Uniform(this.bgShader,"t","tex3",3);this.mesh=w.getSimpleRect(this.cgl,"texEffectRect")}setSize(e,t){this._options.width=e;this._options.height=t}copy(e,t,i,n,r){const a=this.cgl;if(!e)e=CGL.Texture.getEmptyTexture(this.cgl);let s=this._options.width||e.width,o=this._options.height||e.height;if(this.fb){if(s<=0)s=8;if(o<=0)o=8;if(this.fb.getWidth()!=s||this.fb.getHeight()!=o)this.fb.setSize(s,o)}else{let e=CGL.Texture.FILTER_LINEAR;let t=CGL.Texture.WRAP_CLAMP_TO_EDGE;if(this._options.isFloatingPointTexture)e=CGL.Texture.FILTER_NEAREST;if(this._options.hasOwnProperty("filter"))e=this._options.filter;if(this._options.hasOwnProperty("wrap"))t=this._options.wrap;const l={isFloatingPointTexture:this._options.isFloatingPointTexture,pixelFormat:this._options.pixelFormat,numRenderBuffers:this._options.numRenderBuffers||1,filter:e,wrap:t};if(a.glVersion==1)this.fb=new CGL.Framebuffer(a,s,o,l);else this.fb=new CGL.Framebuffer2(a,s,o,l)}a.tempData.renderOffscreen=true;this.fb.renderStart(a);a.setTexture(0,e.tex);if(t)a.setTexture(1,t.tex);if(i)a.setTexture(2,i.tex);if(n)a.setTexture(3,n.tex);if(r)a.setTexture(4,r.tex);a.pushShader(this.bgShader);this.mesh.render(this.bgShader);a.popShader();this.fb.renderEnd();a.tempData.renderOffscreen=false;return this.fb.getTextureColor()}dispose(){if(this.fb)this.fb.dispose();if(this.bgShader)this.bgShader.dispose();if(this.mesh)this.mesh.dispose()}}CGL.CopyTexture=R;((this.CGL=this.CGL||{}).COREMODULES=this.CGL.COREMODULES||{}).Copytexture=e.Copytexture})();(()=>{"use strict";var e={};class t{constructor(e){this.cgl=e;this.geom=new CGL.Geometry("marker");this.geom.setPointVertices([-1,-1,1,1,-1,1,1,1,1,-1,1,1,-1,-1,-1,1,-1,-1,-1,1,-1,1,1,-1,1,-1,-1,1,1,-1,-1,1,-1,-1,-1,-1,1,1,1,1,-1,1,-1,1,1,-1,-1,1,1,1,-1,1,1,1,-1,1,-1,-1,1,1,1,-1,1,1,-1,-1,-1,-1,1,-1,-1,-1]);this.mesh=new CGL.Mesh(this.cgl,this.geom,this.cgl.gl.LINES);this.mesh.setGeom(this.geom);this.colorShader=new CGL.UniColorShader(this.cgl);this.colorShader.setColor([0,1,1,1]);this._vScale=vec3.create()}render(e,t,i){this.cgl.pushModelMatrix();this.cgl.pushShader(this.colorShader.shader);this.cgl.pushDepthTest(false);if(e==undefined)e=1;if(t==undefined)t=e;if(i==undefined)i=e;vec3.set(this._vScale,e,t,i);mat4.scale(this.cgl.mvMatrix,this.cgl.mvMatrix,this._vScale);this.mesh.render(this.cgl.getShader());this.cgl.popDepthTest();this.cgl.popShader();this.cgl.popModelMatrix()}}class i{constructor(e){this.cgl=e;this.geom=new CGL.Geometry("marker");const t=-1;const i=1;this.geom.setPointVertices([t,t,0,i,t,0,i,t,0,i,i,0,i,i,0,t,i,0,t,i,0,t,t,0]);this.mesh=new CGL.Mesh(this.cgl,this.geom,this.cgl.gl.LINES);this.mesh.setGeom(this.geom);this.colorShader=new CGL.UniColorShader(this.cgl);this.colorShader.setColor([0,1,1,1]);this._vScale=vec3.create()}render(e,t,i){this.cgl.pushModelMatrix();this.cgl.pushShader(this.colorShader.shader);this.cgl.pushDepthTest(false);vec3.set(this._vScale,e||1,t||e||1,i||e||1);mat4.scale(this.cgl.mvMatrix,this.cgl.mvMatrix,this._vScale);this.mesh.render(this.cgl.getShader());this.cgl.popDepthTest();this.cgl.popShader();this.cgl.popModelMatrix()}}CGL.WireframeCube=t;CGL.WireframeRect=i;((this.CGL=this.CGL||{}).COREMODULES=this.CGL.COREMODULES||{}).Wireframes=e.Wireframes})();(()=>{"use strict";var e={};class t{constructor(e,t){this.initiator=e;this._options=t}stack(e){console.info("["+this.initiator+"] ",e);console.log((new Error).stack)}groupCollapsed(e){if(CABLES.UI&&CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:0},...arguments)||!CABLES.logSilent)console.log("["+this.initiator+"]",...arguments);console.groupCollapsed("["+this.initiator+"] "+e)}table(e){console.table(e)}groupEnd(){console.groupEnd()}error(){if(CABLES.UI&&CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:2},...arguments)||!CABLES.UI){console.error("["+this.initiator+"]",...arguments)}if(this._options&&this._options.onError){this._options.onError(this.initiator,...arguments)}}errorGui(){if(CABLES.UI)CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:2},...arguments)}warn(){if(CABLES.UI&&CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:1},...arguments)||!CABLES.logSilent)console.warn("["+this.initiator+"]",...arguments)}verbose(){if(CABLES.UI&&CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:0},...arguments)||!CABLES.logSilent)console.log("["+this.initiator+"]",...arguments)}info(){if(CABLES.UI&&CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:0},...arguments)||!CABLES.logSilent)console.info("["+this.initiator+"]",...arguments)}log(){if(CABLES.UI&&CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:0},...arguments)||!CABLES.logSilent)console.log("["+this.initiator+"]",...arguments)}logGui(){if(CABLES.UI)CABLES.UI.logFilter.filterLog({initiator:this.initiator,level:0},...arguments)}userInteraction(e){}}class i{constructor(){this._log=new t("LoadingStatus");this.pixelData=null;this._finishedFence=true;this._size=0;this._pbo=null}_fence(a){const s=a.gl;this._finishedFence=false;return new Promise(function(t,i){if(a.aborted)return;let n=s.fenceSync(s.SYNC_GPU_COMMANDS_COMPLETE,0);if(!n)return;s.flush();function r(){if(a.aborted)return;const e=s.clientWaitSync(n,0,0);if(e==s.WAIT_FAILED){console.error("fence wait failed");if(i)i()}else if(e==s.TIMEOUT_EXPIRED){return setTimeout(r,0)}else if(e==s.CONDITION_SATISFIED){t();s.deleteSync(n)}else if(e==s.ALREADY_SIGNALED){t();s.deleteSync(n)}else{this._log.log("unknown fence status",e)}}r()})}read(i,n,e,r,a,s,o,t){if(CABLES.UI)if(!CABLES.UI.loaded||performance.now()-CABLES.UI.loadedTime<1e3)return;if(!this._finishedFence)return;const l=i.gl;let u=1;if(i.aborted)return;if(!n)return;if(e===CGL.Texture.TYPE_FLOAT)e=CGL.Texture.PFORMATSTR_RGBA32F;let h=CGL.Texture.isPixelFormatFloat(e);if(h)u=4;if(CGL.Texture.isPixelFormatHalfFloat(e))u=2;const p=CGL.Texture.setUpGlPixelFormat(i,e);const c=p.numColorChannels*s*o;if(s==0||o==0||c==0)return;if(!this._pixelData||this._size!=c*u){if(u>1)this._pixelData=new Float32Array(c);else this._pixelData=new Uint8Array(c);this._size=c*u}let m=l.UNSIGNED_BYTE;if(u>1)m=l.FLOAT;if(this._size==0||!this._pixelData){this._log.error("readpixel size 0",this._size,s,o);return}if(this._finishedFence){this._pbo=l.createBuffer();l.bindBuffer(l.PIXEL_PACK_BUFFER,this._pbo);l.bufferData(l.PIXEL_PACK_BUFFER,this._pixelData.byteLength,l.DYNAMIC_READ);l.bindFramebuffer(l.FRAMEBUFFER,n);l.bindBuffer(l.PIXEL_PACK_BUFFER,this._pbo);i.profileData.profileFencedPixelRead++;if(this._size!=c*u)this._log.error("buffer size invalid",c,s,o,u);let e=p.glDataType;if(u>1)e=i.gl.FLOAT;let t=p.glDataFormat;l.readPixels(r,a,s,o,t,e,0);l.bindBuffer(l.PIXEL_PACK_BUFFER,null);l.bindFramebuffer(l.FRAMEBUFFER,null)}let f=this._pixelData.byteLength;if(this._finishedFence&&this._pbo)this._fence(i).then(e=>{this._wasTriggered=false;this._finishedFence=true;if(!e&&this._pixelData&&this._pixelData.byteLength==f){l.bindBuffer(l.PIXEL_PACK_BUFFER,this._pbo);l.getBufferSubData(l.PIXEL_PACK_BUFFER,0,this._pixelData);l.bindBuffer(l.PIXEL_PACK_BUFFER,null);if(t)t(this._pixelData)}l.deleteBuffer(this._pbo);this._pbo=null});return true}}CGL.PixelReader=i;((this.CGL=this.CGL||{}).COREMODULES=this.CGL.COREMODULES||{}).Pixelreader=e.Pixelreader})();