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 (!CABLES.UI && 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("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 (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();

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

/**
 * @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();

    if (this.onLinkChanged) this.onLinkChanged();
    this.emitEvent("onLinkChanged");
    this._op.emitEvent("onLinkChanged");
};

/**
 * @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.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.cgl.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.storage) return (this.storage.subPatchVer || 0);
    };

    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.set(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;

        this.setValue(this._value);
        this.needsUpdate = true;
    }


    getType()
    {
        return this._type;
    }

    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 = [-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE];
        this._min = [Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE];
        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)
                // if (geom.vertices[i] == geom.vertices[i] || geom.vertices[i] != null)
                // {
            // if(mat)
            // {
                this.applyPos(geom.vertices[i], geom.vertices[i + 1], geom.vertices[i + 2]);
            // }
            // else
            // {
            //     this.applyPos(geom.vertices[i + 0],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]=Math.abs(this._min[0])+Math.abs(this._max[0]);
        // this._size[1]=Math.abs(this._min[1])+Math.abs(this._max[1]);
        // this._size[2]=Math.abs(this._min[2])+Math.abs(this._max[2]);
        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://docs.cables.gl/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 = [];
    }

    /**
     * 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;
            }
        }
    }
}



;// 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._moduleNames = [];
        this._modules = [];
        this._moduleNumId = 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 = "";

        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.frameStore.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()
    {
    };

    /**
     * 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;
    };

    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;
    };

    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("no uniform given to texturestack", uniform);
            return;
        }
        if (!t)
        {
            console.log("no tex...");
            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





// const CGState ()
class CGState extends Events
{
    constructor(_patch)
    {
        super();
        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);
        // EventTarget.apply(this);
        // CGState.apply(this);

        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.frameStore = {};
        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.frameStore || ((this.frameStore.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.frameStore.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.frameStore.forceShaderMods)
        {
            for (let i = 0; i < this.frameStore.forceShaderMods.length; i++)
            {
                // if (!currentShader.forcedMod && currentShader != this.frameStore.forceShaderMods[i])
                // {
                //     currentShader.forcedMod = this.frameStore.forceShaderMods[i];
                shader = this.frameStore.forceShaderMods[i].bind(shader, false);
                // }
                // return currentShader;
                // if (this.frameStore.forceShaderMods[i].currentShader() && shader != this.frameStore.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.frameStore.forceShaderMods)
        {
            for (let i = 0; i < this.frameStore.forceShaderMods.length; i++)
            {
                // const a =
                this.frameStore.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.frameStore.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'
 * });
 */

const Patch = function (cfg)
{
    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.instancing = new Instancing();
    this.onOneFrameRendered = null;
    this.namedTriggers = {};

    this._origData = null;
    this._frameNext = 0;
    this._frameInterval = 0;
    this._lastFrameTime = 0;
    this._frameWasdelayed = true;
    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
};

Patch.prototype.isPlaying = function ()
{
    return !this._paused;
};

Patch.prototype.isRenderingOneFrame = function ()
{
    return this._renderOneFrame;
};


Patch.prototype.renderOneFrame = function ()
{
    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
 */
Patch.prototype.getFPS = function ()
{
    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
 */
Patch.prototype.isEditorMode = function ()
{
    return this.config.editorMode === true;
};

/**
 * pauses patch execution
 * @function pause
 * @memberof Patch
 * @instance
 */
Patch.prototype.pause = function ()
{
    cancelAnimationFrame(this._animReq);
    this.emitEvent("pause");
    this._animReq = null;
    this._paused = true;
    this.freeTimer.pause();
};

/**
 * resumes patch execution
 * @function resume
 * @memberof Patch
 * @instance
 */
Patch.prototype.resume = function ()
{
    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
 */
Patch.prototype.setVolume = function (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
 */
Patch.prototype.getAssetPath = function (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
 */
Patch.prototype.getJsPath = function ()
{
    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
 */
Patch.prototype.getFilePath = function (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 || "");
};

Patch.prototype.clear = function ()
{
    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");
};

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.prototype.createOp = function (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(e);
        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 });
 */
Patch.prototype.addOp = function (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;
};

Patch.prototype.addOnAnimFrame = function (op)
{
    for (let i = 0; i < this.animFrameOps.length; i++) if (this.animFrameOps[i] == op) { return; }

    this.animFrameOps.push(op);
};

Patch.prototype.removeOnAnimFrame = function (op)
{
    for (let i = 0; i < this.animFrameOps.length; i++)
    {
        if (this.animFrameOps[i] == op)
        {
            this.animFrameOps.splice(i, 1);
            return;
        }
    }
};

Patch.prototype.addOnAnimFrameCallback = function (cb)
{
    this.animFrameCallbacks.push(cb);
};

Patch.prototype.removeOnAnimCallback = function (cb)
{
    for (let i = 0; i < this.animFrameCallbacks.length; i++)
    {
        if (this.animFrameCallbacks[i] == cb)
        {
            this.animFrameCallbacks.splice(i, 1);
            return;
        }
    }
};

Patch.prototype.deleteOp = function (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);
};

Patch.prototype.getFrameNum = function ()
{
    return this._frameNum;
};

Patch.prototype.emitOnAnimFrameEvent = function (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);
};

Patch.prototype.renderFrame = function (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();
    }
};

Patch.prototype.exec = function (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
 */
Patch.prototype.link = function (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;
    }
};

Patch.prototype.serialize = function (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);
};

Patch.prototype.getOpsByRefId = function (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;
};

Patch.prototype.getOpById = function (opid)
{
    return this._opIdCache[opid];
};

Patch.prototype.getOpsByName = function (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;
};

Patch.prototype.getOpsByObjName = function (name)
{
    const arr = [];
    for (const i in this.ops)
        if (this.ops[i].objName == name) arr.push(this.ops[i]);
    return arr;
};

Patch.prototype.getOpsByOpId = function (opid)
{
    const arr = [];
    for (const i in this.ops)
        if (this.ops[i].opId == opid) arr.push(this.ops[i]);
    return arr;
};

Patch.prototype.loadLib = function (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",
    );
};

Patch.prototype.getSubPatchOpsByName = function (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;
};

Patch.prototype.getSubPatchOp =
Patch.prototype.getFirstSubPatchOpByName = function (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;
};

Patch.prototype._addLink = function (opinid, opoutid, inName, outName)
{
    return this.link(this.getOpById(opinid), inName, this.getOpById(opoutid), outName, false, true);
};

Patch.prototype.deSerialize = function (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);
};

Patch.prototype.profile = function (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
 */
Patch.prototype.setVariable = function (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!");
    }
};

Patch.prototype._sortVars = function ()
{
    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
 */
Patch.prototype.hasVar = function (name)
{
    return this._variables[name] !== undefined;

    // return this._variables.hasOwnProperty(name);
};

// used internally
Patch.prototype.setVarValue = function (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?
Patch.prototype.getVarValue = function (name, val)
{
    if (this._variables.hasOwnProperty(name)) return this._variables[name].getValue();
};

/**
 * @function getVar
 * @memberof Patch
 * @instance
 * @param {String} name
 * @return {Variable} variable
 */
Patch.prototype.getVar = function (name)
{
    if (this._variables.hasOwnProperty(name)) return this._variables[name];
};


Patch.prototype.deleteVar = function (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
 */
Patch.prototype.getVars = function (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
 */
Patch.prototype.preRenderOps = function ()
{
    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
 */
Patch.prototype.dispose = function ()
{
    this.pause();
    this.clear();
    this.cgl.dispose();
};

Patch.prototype.pushTriggerStack = function (p)
{
    this._triggerStack.push(p);
};

Patch.prototype.popTriggerStack = function ()
{
    this._triggerStack.pop();
};

Patch.prototype.printTriggerStack = function ()
{
    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
 */
Patch.prototype.getDocument = function ()
{
    return this.cgl.canvas.ownerDocument;
};

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 (this.getType() == "t" && !_value) this._value = this._cgp.getEmptyTexture();

        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)
    {
        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);
        }
    }

    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;
    }
}

;// 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 (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 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, idx, name, options = {})
    {
        this.idx = idx;
        this._name = name;
        this._cgp = cgp;
        this._log = new Logger("cgp_binding");
        this.uniforms = [];
        // this.cGpuBuffer = null;
        this.cGpuBuffers = [];

        this.shader = null;

        if (typeof options != "object") this._log.error("binding options is not an object");


        this.bindingInstances = [];
        this.stageStr = options.stage;
        this.bindingType = options.bindingType || "uniform"; // "uniform", "storage", "read-only-storage",

        this.stage = GPUShaderStage.VERTEX;
        if (this.stageStr == "frag") this.stage = GPUShaderStage.FRAGMENT;

        if (options.shader) this.shader = options.shader;

        this._buffer = null;
        this.isValid = true;
        this.changed = 0;

        if (options.shader)
        {
            if (this.stageStr == "frag") options.shader.bindingsFrag.push(this);
            if (this.stageStr == "vert") options.shader.bindingsVert.push(this);
        }

        this._cgp.on("deviceChange", () =>
        {
            // this.reInit();
        });
    }

    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;
    }

    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.idx,
            "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.idx,
            "size": this.getSizeBytes(),
            "visibility": this.stage,
        };

        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")
        {
            const sampler = this.uniforms[0]._cgp.device.createSampler({
                "addressModeU": "repeat",
                "addressModeV": "repeat",
                "magFilter": "linear",
                "minFilter": "linear",
                "mipmapFilter": "linear",
            });
            o.resource = sampler;
        }
        else
        {
            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, "buff", null, { "buffCfg": buffCfg });

            if (this.uniforms[0].gpuBuffer) this.cGpuBuffers[inst] = this.uniforms[0].gpuBuffer;

            o.resource = {
                "buffer": this.cGpuBuffers[inst].gpuBuffer,
                "minBindingSize": this.getSizeBytes(),
                "hasDynamicOffset": 0
            };
        }

        this.isValid = true;
        this.bindingInstances[inst] = o;

        return o;
    }



    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
                {
                    b.resource = CABLES.errorTexture.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;
            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?
                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.defaultBindingVert = new Binding(_cgp, 0, "defaultVert", { "stage": "vert", "bindingType": "uniform" });
        this.defaultBindingFrag = new Binding(_cgp, 1, "defaultFrag", { "stage": "frag", "bindingType": "uniform" });
        this.defaultBindingComp = new Binding(_cgp, 1, "defaultComp", { "bindingType": "uniform" });
        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.bindingCounter = 0;
        this.bindCountlastFrame = -1;

        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;
    }

    setSource(src)
    {
        this._src = src;
        this.setWhyCompile("Source changed");
        this._needsRecompile = true;
    }

    compile()
    {
        this._isValid = true;
        this._cgp.pushErrorScope("cgp_shader " + this._name);

        const defs = {};
        for (let i = 0; i < this._defines.length; i++)
            defs[this._defines[i][0]] = this._defines[i][1] || true;

        const src = preproc(this._src, defs);

        this.gpuShaderModule = this._cgp.device.createShaderModule({ "code": src, "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];
        }
    }
}

;// CONCATENATED MODULE: ./src/core/cgp/cgl_shader_default.wgsl
/* harmony default export */ const cgl_shader_default = ("struct VSUniforms\n{\n    modelMatrix: mat4x4<f32>,\n    viewMatrix: mat4x4<f32>,\n    projMatrix: mat4x4<f32>,\n};\n\nstruct FSUniforms\n{\n    color:vec4<f32>\n};\n\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\n@group(0) @binding(1) var<uniform> fsUniforms: FSUniforms;\n\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._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();
    }

    /**
     * @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 });
    }
}


/**
 * @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 (mesh.needsPipelineUpdate)needsRebuildReason = "mesh needs update";
        if (this.shaderNeedsPipelineUpdate)needsRebuildReason = "shader needs update: " + 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":1731661366759,"created":"2024-11-15T09:02:46.759Z","git":{"branch":"master","commit":"60f9e20b823994ef1a4163be50bb10cfe7e1e894","date":"1730989279","message":"fftarea v3"}};
(()=>{"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["SG56Nv"]={_id:"674d8185aad02a2f6faf8036",ops:[{id:"b57de6bd-4cef-4196-84b0-866a8f912d39",uiAttribs:{},portsIn:[{name:"FPS Limit",value:60},{name:"Reduce FPS not focussed",value:0},{name:"Reduce FPS loading",value:0},{name:"Clear",value:1},{name:"ClearAlpha",value:1},{name:"Fullscreen Button",value:0},{name:"Active",value:1},{name:"Hires Displays",value:0},{name:"Pixel Unit index",value:0},{name:"Pixel Unit",value:"Display"}],portsOut:[{name:"trigger",links:[{portIn:"Trigger",portOut:"trigger",objIn:"f67f3a4e-9908-4dad-ad5d-145392ee069d",objOut:"b57de6bd-4cef-4196-84b0-866a8f912d39"}]},{name:"width",value:1920},{name:"height",value:1080}],objName:"Ops.Gl.MainLoop"},{id:"07163efc-c97c-4fc8-b612-1f017e8e511a",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"URL",value:"assets/varrho.vs.monstro-b2b-anticore.ogg",display:"file"},{name:"Create Loading Task",value:1}],portsOut:[{name:"Audio Buffer",links:[{portIn:"Audio Buffer",portOut:"Audio Buffer",objIn:"d6fda95e-108f-4382-8c29-c2d767cbf6f4",objOut:"07163efc-c97c-4fc8-b612-1f017e8e511a"}]},{name:"Finished Loading",value:1},{name:"Sample Rate",value:48e3},{name:"Length",value:10602579},{name:"Duration",links:[{portIn:"number1",portOut:"Duration",objIn:"640d3813-6b75-4262-9bd3-453dad82126c",objOut:"07163efc-c97c-4fc8-b612-1f017e8e511a"}]},{name:"Number of Channels",value:2},{name:"isLoading",value:false}],objName:"Ops.WebAudio.AudioBuffer_v2"},{id:"d6fda95e-108f-4382-8c29-c2d767cbf6f4",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},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:"ab4a2bc5-36f2-4c34-94fa-e68ad29550a8",objOut:"d6fda95e-108f-4382-8c29-c2d767cbf6f4"},{portIn:"Audio In",portOut:"Audio Out",objIn:"4dfdd7a5-501c-4b77-8c57-68b7c80b6189",objOut:"d6fda95e-108f-4382-8c29-c2d767cbf6f4"}]},{name:"Is Playing",value:false},{name:"Loading",value:false}],objName:"Ops.WebAudio.AudioBufferPlayer_v2"},{id:"ab4a2bc5-36f2-4c34-94fa-e68ad29550a8",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"Volume",value:1},{name:"Show Audio Suspended Button",value:0}],portsOut:[{name:"Current Volume",value:1},{name:"Context State",value:"running"}],objName:"Ops.WebAudio.Output_v2"},{id:"2b4d6930-cc01-4f94-919f-f9dc02948537",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"PreRender Ops",value:0},{name:"Play Timeline",value:1}],portsOut:[{name:"Next",links:[{portIn:"exe",portOut:"Next",objIn:"98084cf5-89ff-427b-b4db-fcf67b48863c",objOut:"2b4d6930-cc01-4f94-919f-f9dc02948537"}]},{name:"Finished Initial Loading",links:[{portIn:"boolean",portOut:"Finished Initial Loading",objIn:"98084cf5-89ff-427b-b4db-fcf67b48863c",objOut:"2b4d6930-cc01-4f94-919f-f9dc02948537"},{portIn:"bool 1",portOut:"Finished Initial Loading",objIn:"03b731f0-ec08-47f5-9b16-8f17d40e870b",objOut:"2b4d6930-cc01-4f94-919f-f9dc02948537"}]},{name:"Loading",value:0},{name:"Progress",links:[{portIn:"number1",portOut:"Progress",objIn:"a9acf23e-f337-44bc-864f-0d1dc75f56b9",objOut:"2b4d6930-cc01-4f94-919f-f9dc02948537"}]},{name:"Trigger Loading Finished ",links:[{portIn:"exe 4",portOut:"Trigger Loading Finished ",objIn:"c3403809-c576-4d0c-ac64-3809b23b248c",objOut:"2b4d6930-cc01-4f94-919f-f9dc02948537"}]}],objName:"Ops.Cables.LoadingStatus_v2"},{id:"c3403809-c576-4d0c-ac64-3809b23b248c",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsOut:[{name:"trigger 0",links:[{portIn:"exe",portOut:"trigger 0",objIn:"1ce0bcd5-6599-42f7-a46d-afa4621bda08",objOut:"c3403809-c576-4d0c-ac64-3809b23b248c"}]},{name:"trigger 15",links:[{portIn:"render",portOut:"trigger 15",objIn:"1c1f7771-3cb0-4f48-b340-0e3b3693566c",objOut:"c3403809-c576-4d0c-ac64-3809b23b248c"}]}],objName:"Ops.Trigger.Sequence"},{id:"d29d7299-28ee-48ab-9976-0ef1dcb6f954",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"cursor index",value:16},{name:"cursor",value:"none"}],objName:"Ops.Html.Cursor"},{id:"a9acf23e-f337-44bc-864f-0d1dc75f56b9",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"8f84bdd9-008b-4126-8431-14fbc01e3935",objOut:"a9acf23e-f337-44bc-864f-0d1dc75f56b9"}]}],objName:"Ops.Math.Sum"},{id:"8f84bdd9-008b-4126-8431-14fbc01e3935",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"Value",portOut:"result",objIn:"845de1e6-4b7a-45e8-995a-42511e491fb1",objOut:"8f84bdd9-008b-4126-8431-14fbc01e3935"}]}],objName:"Ops.Math.Divide"},{id:"98084cf5-89ff-427b-b4db-fcf67b48863c",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsOut:[{name:"then",links:[{portIn:"exe",portOut:"then",objIn:"f2tp4tgfx",objOut:"98084cf5-89ff-427b-b4db-fcf67b48863c"}]},{name:"else",links:[{portIn:"exe",portOut:"else",objIn:"c3403809-c576-4d0c-ac64-3809b23b248c",objOut:"98084cf5-89ff-427b-b4db-fcf67b48863c"}]}],objName:"Ops.Boolean.IfTrueThen_v2"},{id:"99fba13a-1467-4b45-85dd-7a98e16ea127",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"Times",value:[0,20.55,20.866666666666667,21.016666666666666,21.133333333333333,21.266666666666666,21.4,21.533333333333335,21.666666666666668,21.8,21.933333333333334,22.066666666666666,22.183333333333334,22.316666666666666,22.45,22.583333333333332,22.716666666666665,22.85,22.983333333333334,23.116666666666667,23.25,23.383333333333333,23.516666666666666,23.65,23.783333333333335,23.916666666666668,24.05,24.183333333333334,24.316666666666666,24.45,24.583333333333332,24.716666666666665,24.85,24.983333333333334,25.116666666666667,25.25,25.366666666666667,25.5,25.516666666666666,.15,.2833333333333333,.4166666666666667,.55,.6833333333333333,.8166666666666667,.95,1.0833333333333333,1.2166666666666666,1.35,1.4833333333333334,1.6166666666666667,1.75,1.8833333333333333,2.0166666666666666,2.15,2.283333333333333,2.4166666666666665,2.55,2.683333333333333,2.816666666666667,2.95,3.0833333333333335,3.2,3.3333333333333335,3.466666666666667,3.6,3.7333333333333334,3.8666666666666667,4,4.133333333333334,4.266666666666667,4.4,4.533333333333333,4.666666666666667,4.8,4.933333333333334,5.066666666666666,5.2,5.333333333333333,5.466666666666667,5.6,5.733333333333333,5.866666666666666,6,6.133333333333334,6.266666666666667,6.383333333333334,6.516666666666667,6.65,6.783333333333333,6.933333333333334,7.066666666666666,7.2,7.316666666666666,7.45,7.583333333333333,7.716666666666667,7.85,7.983333333333333,8.116666666666667,8.25,8.383333333333333,8.516666666666667,8.65,8.783333333333333,8.916666666666666,9.05,9.183333333333334,9.316666666666666,9.45,9.566666666666666,9.7,9.833333333333334,9.983333333333333,10.116666666666667,10.25,10.383333333333333,10.516666666666667,10.65,10.783333333333333,10.916666666666666,11.05,11.183333333333334,11.316666666666666,11.45,11.583333333333334,11.716666666666667,11.85,11.983333333333333,12.116666666666667,12.25,12.383333333333333,12.516666666666667,12.65,12.766666666666667,12.9,13.033333333333333,13.166666666666666,13.3,13.433333333333334,13.566666666666666,13.7,13.833333333333334,13.966666666666667,14.1,14.233333333333333,14.366666666666667,14.5,14.633333333333333,14.766666666666667,14.9,15.033333333333333,15.166666666666666,15.3,15.433333333333334,15.566666666666666,15.7,15.816666666666666,15.95,16.083333333333332,16.216666666666665,16.35,16.483333333333334,16.616666666666667,16.75,16.883333333333333,17.016666666666666,17.15,17.283333333333335,17.416666666666668,17.55,17.683333333333334,17.816666666666666,17.95,18.083333333333332,18.216666666666665,18.35,18.483333333333334,18.616666666666667,18.75,18.883333333333333,19,19.133333333333333,19.266666666666666,19.4,19.533333333333335,19.666666666666668,19.8,19.933333333333334,20.066666666666666,20.2,20.333333333333332,20.466666666666665,20.6,20.733333333333334,21,42.5,42.516666666666666,59.5,71.18333333333334,76.48333333333333,93.48333333333333,93.71666666666667,93.75,93.88333333333334,94.01666666666667,94.15,94.28333333333333,94.41666666666667,94.55,94.68333333333334,94.81666666666666,94.93333333333334,95.06666666666666,95.2,95.33333333333333,95.46666666666667,95.6,95.73333333333333,95.86666666666666,96,96.13333333333334,96.26666666666667,96.4,96.53333333333333,96.66666666666667,96.8,96.93333333333334,97.06666666666666,97.2,97.33333333333333,97.46666666666667,97.6,97.73333333333333,97.86666666666666,98,98.11666666666666,98.25,98.38333333333334,98.51666666666667,98.65,98.78333333333333,98.91666666666667,99.05,99.18333333333334,99.31666666666666,99.45,99.58333333333333,99.71666666666667,99.85,99.98333333333333,100.11666666666666,100.25,100.38333333333334,100.51666666666667,100.65,100.78333333333333,100.91666666666667,101.05,101.18333333333334,101.3,101.43333333333334,101.56666666666666,101.7,101.83333333333333,101.96666666666667,102.1,102.23333333333333,102.36666666666666,102.5,102.63333333333334,102.76666666666667,102.9,103.03333333333333,103.16666666666667,103.3,103.43333333333334,103.56666666666666,103.7,103.83333333333333,103.96666666666667,104.1,104.23333333333333,104.36666666666666,104.48333333333333,104.61666666666666,104.75,104.88333333333334,105.01666666666667,105.15,105.28333333333333,105.41666666666667,105.55,105.68333333333334,105.81666666666666,105.95,106.08333333333333,106.21666666666667,106.35,106.48333333333333,106.61666666666666,106.75,106.88333333333334,107.01666666666667,107.15,107.28333333333333,107.41666666666667,107.55,107.66666666666667,107.8,107.93333333333334,108.08333333333333,108.2,108.33333333333333,108.46666666666667,108.6,108.73333333333333,108.86666666666666,109,109.13333333333334,109.26666666666667,109.4,109.53333333333333,109.66666666666667,109.8,109.93333333333334,110.06666666666666,110.2,110.33333333333333,110.46666666666667,110.48333333333333,127.45,127.76666666666667,127.85,127.98333333333333,128.11666666666667,128.25,128.38333333333333,128.51666666666668,128.65,128.78333333333333,128.91666666666666,129.05,129.18333333333334,129.31666666666666,129.45,129.58333333333334,129.7,129.83333333333334,129.96666666666667,130.1,130.23333333333332,130.36666666666667,130.5,130.63333333333333,130.76666666666668,130.9,131.03333333333333,131.16666666666666,131.31666666666666,131.45,131.58333333333334,131.71666666666667,131.85,131.98333333333332,132.11666666666667,132.25,132.38333333333333,132.51666666666668,132.65,132.78333333333333,132.9,133.03333333333333,133.16666666666666,133.3,133.43333333333334,133.56666666666666,133.7,133.83333333333334,133.96666666666667,134.1,134.23333333333332,134.36666666666667,134.5,134.63333333333333,134.76666666666668,134.9,135.03333333333333,135.16666666666666,135.3,135.43333333333334,135.56666666666666,135.7,135.83333333333334,135.96666666666667,136.08333333333334,136.21666666666667,136.35,136.48333333333332,136.61666666666667,136.75,136.88333333333333,137.01666666666668,137.15,137.28333333333333,137.41666666666666,137.55,137.68333333333334,137.81666666666666,137.95,138.08333333333334,138.21666666666667,138.35,138.48333333333332,138.61666666666667,138.75,138.88333333333333,139.01666666666668,139.15,139.26666666666668,139.4,139.53333333333333,139.66666666666666,139.8,139.93333333333334,140.06666666666666,140.2,140.33333333333334,140.46666666666667,140.6,140.73333333333332,140.86666666666667,141,141.13333333333333,141.26666666666668,141.4,141.53333333333333,141.66666666666666,141.8,141.93333333333334,142.06666666666666,142.2,142.33333333333334,142.45,142.58333333333334,142.71666666666667,142.85,142.98333333333332,143.11666666666667,143.25,143.38333333333333,143.51666666666668,143.65,143.78333333333333,143.91666666666666,144.05,144.18333333333334,144.31666666666666,144.45,144.58333333333334,144.71666666666667,144.85,144.98333333333332,145.11666666666667,145.25,145.38333333333333,145.51666666666668,145.63333333333333,145.76666666666668,145.9,146.03333333333333,146.16666666666666,146.3,146.43333333333334,146.56666666666666,146.7,146.83333333333334,146.96666666666667,147.1,147.23333333333332,147.36666666666667,147.5,147.63333333333333,147.76666666666668,147.9,148.03333333333333,148.16666666666666,148.3,148.43333333333334,148.56666666666666,148.68333333333334,148.7,161.43333333333334,161.45,178.43333333333334,202.85]},{name:"Manual Timestamps",value:0},{name:"Record Events",value:0},{name:"ReRender on Resize",value:1}],portsOut:[{name:"Next",links:[{portIn:"out0 Ops.Sequence exe",portOut:"Next",objIn:"e286b485-7fd3-4825-8724-01e7037d5fbe",objOut:"99fba13a-1467-4b45-85dd-7a98e16ea127"}]},{name:"Prerendered Frame",links:[{portIn:"exe 1",portOut:"Prerendered Frame",objIn:"c3403809-c576-4d0c-ac64-3809b23b248c",objOut:"99fba13a-1467-4b45-85dd-7a98e16ea127"}]},{name:"Progress",links:[{portIn:"number2",portOut:"Progress",objIn:"a9acf23e-f337-44bc-864f-0d1dc75f56b9",objOut:"99fba13a-1467-4b45-85dd-7a98e16ea127"},{portIn:"number1",portOut:"Progress",objIn:"3989a525-104e-40ff-8d21-c6309d1e16c6",objOut:"99fba13a-1467-4b45-85dd-7a98e16ea127"}]},{name:"Num Events",value:496}],objName:"Ops.TimeLine.DemoPrerender"},{id:"267fe88d-f043-4d42-9906-70ca8977442c",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsOut:[{name:"Play/Stop",links:[{portIn:"Start / Stop",portOut:"Play/Stop",objIn:"d6fda95e-108f-4382-8c29-c2d767cbf6f4",objOut:"267fe88d-f043-4d42-9906-70ca8977442c"}]},{name:"time",links:[{portIn:"Offset",portOut:"time",objIn:"d6fda95e-108f-4382-8c29-c2d767cbf6f4",objOut:"267fe88d-f043-4d42-9906-70ca8977442c"}]}],objName:"Ops.TimeLine.TimeLineControls"},{id:"63741d97-dc47-4bab-974b-5641c03afeaf",uiAttribs:{},portsIn:[{name:"Only if Audio Suspended",value:1},{name:"Style Outer",value:"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;"},{name:"Style Inner",value:"\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"},{name:"Active",value:1}],portsOut:[{name:"Next",links:[{portIn:"in0 Ops.Patch.PlayButton Next",portOut:"Next",objIn:"0a529251-72ad-4c63-984d-9331b78fd567",objOut:"63741d97-dc47-4bab-974b-5641c03afeaf"}]},{name:"Audiocontext State",value:"running"},{name:"Clicked",links:[{portIn:"in1 Ops.Patch.PlayButton Clicked",portOut:"Clicked",objIn:"0a529251-72ad-4c63-984d-9331b78fd567",objOut:"63741d97-dc47-4bab-974b-5641c03afeaf"}]}],objName:"Ops.Html.PlayButton"},{id:"23d1b3f3-514a-4178-8062-194e596f1a59",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsOut:[{name:"Result",links:[{portIn:"Value",portOut:"Result",objIn:"30e8be7e-e04b-40ee-8d0e-c6f50b533ae5",objOut:"23d1b3f3-514a-4178-8062-194e596f1a59"}]}],objName:"Ops.Boolean.Not"},{id:"03b731f0-ec08-47f5-9b16-8f17d40e870b",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsOut:[{name:"result",links:[{portIn:"bool 1",portOut:"result",objIn:"bacb2d11-a437-4bf7-ba1b-b29e769aae6b",objOut:"03b731f0-ec08-47f5-9b16-8f17d40e870b"}]}],objName:"Ops.Boolean.And"},{id:"3989a525-104e-40ff-8d21-c6309d1e16c6",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"number2",value:1}],portsOut:[{name:"result",links:[{portIn:"bool 2",portOut:"result",objIn:"bacb2d11-a437-4bf7-ba1b-b29e769aae6b",objOut:"3989a525-104e-40ff-8d21-c6309d1e16c6"}]}],objName:"Ops.Math.Compare.Equals"},{id:"bacb2d11-a437-4bf7-ba1b-b29e769aae6b",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsOut:[{name:"result",links:[{portIn:"Boolean",portOut:"result",objIn:"23d1b3f3-514a-4178-8062-194e596f1a59",objOut:"bacb2d11-a437-4bf7-ba1b-b29e769aae6b"}]}],objName:"Ops.Boolean.And"},{id:"1c1f7771-3cb0-4f48-b340-0e3b3693566c",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"posX",value:1.5},{name:"posY",value:0},{name:"posZ",value:0},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:180}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"25c6195c-f7d4-4321-bbcc-4ab64a1de425",objOut:"1c1f7771-3cb0-4f48-b340-0e3b3693566c"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"e9cdad1b-7316-43d7-b85b-b87e7653e997",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"Title",value:"LOADING BAR"}],objName:"Ops.Ui.Area"},{id:"9b880025-7fc4-4f61-9821-c2e99fbbb80b",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"Enable depth testing",value:0},{name:"Depth Test Method index",value:3},{name:"Depth Test Method",value:"less or equal"},{name:"Write to depth buffer",value:0}],portsOut:[{name:"Next",links:[{portIn:"render",portOut:"Next",objIn:"3ef1b270-69ce-4ad3-a4cf-8f4b4df97c4f",objOut:"9b880025-7fc4-4f61-9821-c2e99fbbb80b"}]}],objName:"Ops.Graphics.DepthTest"},{id:"25c6195c-f7d4-4321-bbcc-4ab64a1de425",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"a",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"9b880025-7fc4-4f61-9821-c2e99fbbb80b",objOut:"25c6195c-f7d4-4321-bbcc-4ab64a1de425"}]}],objName:"Ops.Gl.ClearColor"},{id:"3ef1b270-69ce-4ad3-a4cf-8f4b4df97c4f",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1},{name:"colorizeTexture",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:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"e19cef21-95fb-46d8-b251-8fd673b84eb7",objOut:"3ef1b270-69ce-4ad3-a4cf-8f4b4df97c4f"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v2"},{id:"5cef3cb6-1399-4023-a3c0-b06f1488e387",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"r",value:.12941176470588237},{name:"g",value:.11764705882352941},{name:"b",value:.12941176470588237},{name:"a",value:1},{name:"colorizeTexture",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:"billboard",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"79edd37c-9982-40b5-8d51-d9042660e286",objOut:"5cef3cb6-1399-4023-a3c0-b06f1488e387"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v2"},{id:"e19cef21-95fb-46d8-b251-8fd673b84eb7",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"width",value:3},{name:"height",value:.03},{name:"pivot x index",value:0},{name:"pivot x",value:"left"},{name:"pivot y index",value:1},{name:"pivot y",value:"center"},{name:"num columns",value:1},{name:"num rows",value:1},{name:"axis index",value:0},{name:"axis",value:"xy"},{name:"Active",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"5cef3cb6-1399-4023-a3c0-b06f1488e387",objOut:"e19cef21-95fb-46d8-b251-8fd673b84eb7"}]}],objName:"Ops.Gl.Meshes.Rectangle"},{id:"b5afdc82-e69b-48b5-9990-84e18c81dc5a",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"width",value:1},{name:"height",value:.0301},{name:"pivot x index",value:0},{name:"pivot x",value:"left"},{name:"pivot y index",value:1},{name:"pivot y",value:"center"},{name:"num columns",value:1},{name:"num rows",value:1},{name:"axis index",value:0},{name:"axis",value:"xy"},{name:"Active",value:1}],objName:"Ops.Gl.Meshes.Rectangle"},{id:"79edd37c-9982-40b5-8d51-d9042660e286",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"y",value:1},{name:"z",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"b5afdc82-e69b-48b5-9990-84e18c81dc5a",objOut:"79edd37c-9982-40b5-8d51-d9042660e286"}]}],objName:"Ops.Extension.Deprecated.ScaleXYZ"},{id:"845de1e6-4b7a-45e8-995a-42511e491fb1",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsOut:[{name:"Result",links:[{portIn:"x",portOut:"Result",objIn:"79edd37c-9982-40b5-8d51-d9042660e286",objOut:"845de1e6-4b7a-45e8-995a-42511e491fb1"}]}],objName:"Ops.Math.OneMinus"},{id:"1ce0bcd5-6599-42f7-a46d-afa4621bda08",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsOut:[{name:"then",links:[{portIn:"Set Cursor",portOut:"then",objIn:"d29d7299-28ee-48ab-9976-0ef1dcb6f954",objOut:"1ce0bcd5-6599-42f7-a46d-afa4621bda08"}]}],objName:"Ops.Boolean.IfTrueThen_v2"},{id:"78a1ca43-da7b-43db-acec-64f8b9004296",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsOut:[{name:"Result",links:[{portIn:"boolean",portOut:"Result",objIn:"1ce0bcd5-6599-42f7-a46d-afa4621bda08",objOut:"78a1ca43-da7b-43db-acec-64f8b9004296"}]}],objName:"Ops.Boolean.Not"},{id:"32cf662a-922f-490e-af11-9cbf1eb2a9b7",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsOut:[{name:"UI",links:[{portIn:"Boolean",portOut:"UI",objIn:"78a1ca43-da7b-43db-acec-64f8b9004296",objOut:"32cf662a-922f-490e-af11-9cbf1eb2a9b7"}]},{name:"Overlay Mode",value:0},{name:"Remote Viewer",value:0},{name:"Is Standalone",value:0},{name:"Canvas Mode",value:0},{name:"Patch Field Visible",value:0}],objName:"Ops.Cables.UIMode"},{id:"bf8205b7-1846-46fc-98bf-73cb3c91379d",uiAttribs:{},portsIn:[{name:"css code",value:".progressUI\n{\n    background-color: #444;\n}"},{name:"Active",value:1}],objName:"Ops.Html.CSS.CSS_v2"},{id:"0a9e824d-a55c-4b78-b74a-221fd174f2ea",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsIn:[{name:"Active",value:1},{name:"relative",value:0},{name:"normalize",value:0},{name:"flip y",value:1},{name:"Area index",value:0},{name:"Area",value:"Canvas"},{name:"right click prevent default",value:1},{name:"Touch support",value:1},{name:"smooth",value:0},{name:"smoothSpeed",value:20},{name:"multiply",value:1}],portsOut:[{name:"x",value:236},{name:"y",value:26},{name:"button down",value:0},{name:"click right",links:[{portIn:"trigger",portOut:"click right",objIn:"4e3b5940-0fd9-418a-8286-8524984c1bc3",objOut:"0a9e824d-a55c-4b78-b74a-221fd174f2ea"}]},{name:"mouseOver",value:0},{name:"button",value:0}],objName:"Ops.Devices.Mouse.Mouse_v2"},{id:"4e3b5940-0fd9-418a-8286-8524984c1bc3",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsIn:[{name:"Default",value:0}],portsOut:[{name:"result",links:[{portIn:"Value",portOut:"result",objIn:"c2c1dd6d-1188-4a64-80c1-ca6ad7ac82e5",objOut:"4e3b5940-0fd9-418a-8286-8524984c1bc3"}]}],objName:"Ops.Boolean.ToggleBool"},{id:"5bba1ef5-ce06-49ed-90e9-09d6cd20f456",uiAttribs:{},portsOut:[{name:"trigger 0",links:[{portIn:"Trigger",portOut:"trigger 0",objIn:"29f8a3cf-ec18-4ac3-809d-2bb70a1342b9",objOut:"5bba1ef5-ce06-49ed-90e9-09d6cd20f456"}]},{name:"trigger 8",links:[{portIn:"Trigger",portOut:"trigger 8",objIn:"63741d97-dc47-4bab-974b-5641c03afeaf",objOut:"5bba1ef5-ce06-49ed-90e9-09d6cd20f456"}]},{name:"trigger 15",links:[{portIn:"render",portOut:"trigger 15",objIn:"b4312ed6-352e-4566-bce7-8989182abfa6",objOut:"5bba1ef5-ce06-49ed-90e9-09d6cd20f456"}]}],objName:"Ops.Trigger.Sequence"},{id:"29f8a3cf-ec18-4ac3-809d-2bb70a1342b9",uiAttribs:{},portsIn:[{name:"Named Trigger",value:"preframe"}],objName:"Ops.Trigger.TriggerSend"},{id:"65d4ab90-a9de-43bd-8f90-56dda95ef2a1",uiAttribs:{},portsIn:[{name:"Named Trigger",value:"overlay"}],objName:"Ops.Trigger.TriggerSend"},{id:"b4312ed6-352e-4566-bce7-8989182abfa6",uiAttribs:{},portsOut:[{name:"trigger",links:[{portIn:"Trigger",portOut:"trigger",objIn:"65d4ab90-a9de-43bd-8f90-56dda95ef2a1",objOut:"b4312ed6-352e-4566-bce7-8989182abfa6"}]}],objName:"Ops.Gl.ClearDepth"},{id:"2e426d04-f639-4882-a575-d1c14f618eed",uiAttribs:{},portsOut:[{name:"trigger 0",links:[{portIn:"in0 Ops.Gl.ClearColor trigger",portOut:"trigger 0",objIn:"8365c441-1498-4cd7-8859-841bc27eb0b8",objOut:"2e426d04-f639-4882-a575-d1c14f618eed"}]},{name:"trigger 15",links:[{portIn:"in0 Ops.Sequence trigger 8",portOut:"trigger 15",objIn:"9a3cbd80-74fb-447b-9184-ce11bbfd2347",objOut:"2e426d04-f639-4882-a575-d1c14f618eed"}]}],objName:"Ops.Trigger.Sequence"},{id:"b88aaf0f-aca1-4f79-a1bc-655bec55867e",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsOut:[{name:"trigger 5",links:[{portIn:"Render",portOut:"trigger 5",objIn:"b2d45b11-0da8-44cc-8d18-07ee3a737147",objOut:"b88aaf0f-aca1-4f79-a1bc-655bec55867e"}]},{name:"trigger 15",links:[{portIn:"render",portOut:"trigger 15",objIn:"8c2ceec4-a523-4886-9c63-93b486bee179",objOut:"b88aaf0f-aca1-4f79-a1bc-655bec55867e"}]}],objName:"Ops.Trigger.Sequence"},{id:"b2d45b11-0da8-44cc-8d18-07ee3a737147",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},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:2},{name:"Wrap",value:"mirrored repeat"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{name:"R",value:0},{name:"G",value:0},{name:"B",value:0},{name:"A",value:1}],portsOut:[{name:"Next",links:[{portIn:"render",portOut:"Next",objIn:"f1aacd3c-f363-4339-a0fb-844b8cc9e253",objOut:"b2d45b11-0da8-44cc-8d18-07ee3a737147"}]},{name:"texture_out",links:[{portIn:"Texture",portOut:"texture_out",objIn:"8c2ceec4-a523-4886-9c63-93b486bee179",objOut:"b2d45b11-0da8-44cc-8d18-07ee3a737147"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"8c2ceec4-a523-4886-9c63-93b486bee179",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"Scale index",value:0},{name:"Scale",value:"Stretch"},{name:"Flip Y",value:0},{name:"Flip X",value:0}],objName:"Ops.Gl.Meshes.FullscreenRectangle"},{id:"0feaf3df-7239-47d6-ae03-802a35aefbb4",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsOut:[{name:"create port",value:0},{name:"in0 Ops.Sequence trigger 8",links:[{portIn:"exe",portOut:"in0 Ops.Sequence trigger 8",objIn:"b88aaf0f-aca1-4f79-a1bc-655bec55867e",objOut:"0feaf3df-7239-47d6-ae03-802a35aefbb4"}]},{name:"in1 Ops.Gl.Render2Texture texture",value:0}],objName:"Ops.Ui.PatchInput"},{id:"85e91606-60c8-4c2f-b03e-6109b8c4d62f",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"9a3cbd80-74fb-447b-9184-ce11bbfd2347",uiAttribs:{},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Ops.Sequence trigger 8","type":1},{"name":"in1 Ops.Gl.Render2Texture texture","type":2,"objType":"texture","value":null}],"portsOut":[]}'},{name:"patchId",value:"55667c89-cb99-4c3a-8424-21faf0e697be"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"8ce5c34a-1e00-4934-a768-789b3e089afd",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsOut:[{name:"create port",value:0}],objName:"Ops.Ui.PatchInput"},{id:"89e9c0bc-c6e5-4d57-8f13-65154f3ec4c6",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"93782ba9-32d9-4afc-8896-e74d72fab37d",uiAttribs:{},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:0},{name:"patchId",value:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"30e8be7e-e04b-40ee-8d0e-c6f50b533ae5",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"Variable",value:"mute"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"cd8e02e4-c10b-4c33-840a-31fb3d8c36b6",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"Variable",value:"mute"}],portsOut:[{name:"Value",links:[{portIn:"Mute",portOut:"Value",objIn:"ab4a2bc5-36f2-4c34-94fa-e68ad29550a8",objOut:"cd8e02e4-c10b-4c33-840a-31fb3d8c36b6"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"a6de4dd6-d746-403b-9ce2-0df524c1310b",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsOut:[{name:"create port",value:0},{name:"in0 Ops.Patch.PlayButton Next",links:[{portIn:"exe",portOut:"in0 Ops.Patch.PlayButton Next",objIn:"2b4d6930-cc01-4f94-919f-f9dc02948537",objOut:"a6de4dd6-d746-403b-9ce2-0df524c1310b"}]},{name:"in1 Ops.Patch.PlayButton Clicked",links:[{portIn:"bool 2",portOut:"in1 Ops.Patch.PlayButton Clicked",objIn:"03b731f0-ec08-47f5-9b16-8f17d40e870b",objOut:"a6de4dd6-d746-403b-9ce2-0df524c1310b"}]}],objName:"Ops.Ui.PatchInput"},{id:"e286b485-7fd3-4825-8724-01e7037d5fbe",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"0a529251-72ad-4c63-984d-9331b78fd567",uiAttribs:{},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Ops.Patch.PlayButton Next","type":1},{"name":"in1 Ops.Patch.PlayButton Clicked","type":0}],"portsOut":[{"name":"out0 Ops.Sequence exe","type":1}]}'},{name:"patchId",value:"13f105ab-1b41-4be0-801c-e06345ec5080"}],portsOut:[{name:"create port out",value:0},{name:"out0 Ops.Sequence exe",links:[{portIn:"exe",portOut:"out0 Ops.Sequence exe",objIn:"2e426d04-f639-4882-a575-d1c14f618eed",objOut:"0a529251-72ad-4c63-984d-9331b78fd567"}]}],objName:"Ops.Ui.SubPatch"},{id:"6d6e5199-9016-4738-bfdc-af5e8a1c11d8",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsOut:[{name:"create port",value:0}],objName:"Ops.Ui.PatchInput"},{id:"e37b6638-7e5d-4d6f-987f-151adcb332ee",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"b78977d7-edc9-4ecc-8fbe-32d39406ea55",uiAttribs:{},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:0},{name:"patchId",value:"abd4c25e-4960-42af-b4fc-d93c41038354"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"c2c1dd6d-1188-4a64-80c1-ca6ad7ac82e5",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsIn:[{name:"Variable",value:"overlay_show"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"b9a56530-8464-4fa3-9893-5524b9b03836",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsIn:[{name:"Variable",value:"dev"}],portsOut:[{name:"Value",links:[{portIn:"Visible",portOut:"Value",objIn:"592298c7-4769-447e-a561-db38762ee5f5",objOut:"b9a56530-8464-4fa3-9893-5524b9b03836"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"81e5e52e-5450-41a9-bbb3-ad46bf782a72",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"Named Trigger",value:"preframe"}],portsOut:[{name:"Triggered",links:[{portIn:"Trigger In",portOut:"Triggered",objIn:"4dfdd7a5-501c-4b77-8c57-68b7c80b6189",objOut:"81e5e52e-5450-41a9-bbb3-ad46bf782a72"}]}],objName:"Ops.Trigger.TriggerReceive"},{id:"681654eb-286f-4d77-a7ea-85be183b9aa9",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"X Position",value:.569},{name:"Y Position",value:.459},{name:"Width",value:.757},{name:"Height",value:.339},{name:"Create Texture",value:1},{name:"Texture Size index",value:0},{name:"Texture Size",value:"128"}],portsOut:[{name:"Texture Out",links:[{portIn:"Texture In",portOut:"Texture Out",objIn:"4b5fc3d4-d130-47a8-a176-48f4372738b4",objOut:"681654eb-286f-4d77-a7ea-85be183b9aa9"}]},{name:"Area Average Volume",links:[{portIn:"Number",portOut:"Area Average Volume",objIn:"9af6e129-0599-40ed-b3cd-1e96f48d3664",objOut:"681654eb-286f-4d77-a7ea-85be183b9aa9"},{portIn:"Value",portOut:"Area Average Volume",objIn:"30bc715c-4214-4df4-ba48-e2f14efceb9b",objOut:"681654eb-286f-4d77-a7ea-85be183b9aa9"}]}],objName:"Ops.WebAudio.FFTAreaAverage_v2"},{id:"4dfdd7a5-501c-4b77-8c57-68b7c80b6189",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},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:"Refresh",portOut:"Trigger Out",objIn:"681654eb-286f-4d77-a7ea-85be183b9aa9",objOut:"4dfdd7a5-501c-4b77-8c57-68b7c80b6189"}]},{name:"FFT Array",links:[{portIn:"FFT Array",portOut:"FFT Array",objIn:"681654eb-286f-4d77-a7ea-85be183b9aa9",objOut:"4dfdd7a5-501c-4b77-8c57-68b7c80b6189"}]},{name:"Array Length",value:128},{name:"Average Volume",value:0},{name:"Average Volume Time-Domain",value:.5},{name:"RMS Volume",value:.5}],objName:"Ops.WebAudio.AudioAnalyzer_v2"},{id:"9af6e129-0599-40ed-b3cd-1e96f48d3664",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},objName:"Ops.Ui.VizNumberBar"},{id:"4b5fc3d4-d130-47a8-a176-48f4372738b4",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"30bc715c-4214-4df4-ba48-e2f14efceb9b",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"Variable",value:"fftHighs"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"640d3813-6b75-4262-9bd3-453dad82126c",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"number2",value:1}],portsOut:[{name:"result",links:[{portIn:"number2",portOut:"result",objIn:"c4ac5031-cf5b-4ece-8f0e-745cbe5b4e6d",objOut:"640d3813-6b75-4262-9bd3-453dad82126c"},{portIn:"Value",portOut:"result",objIn:"878a6680-90aa-4150-b81f-150bf105fd74",objOut:"640d3813-6b75-4262-9bd3-453dad82126c"}]}],objName:"Ops.Math.Sum"},{id:"c4ac5031-cf5b-4ece-8f0e-745cbe5b4e6d",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsOut:[{name:"result",links:[{portIn:"Value",portOut:"result",objIn:"a52b5486-0e1f-4e10-8971-86b39b494277",objOut:"c4ac5031-cf5b-4ece-8f0e-745cbe5b4e6d"}]}],objName:"Ops.Math.Compare.GreaterThan"},{id:"a52b5486-0e1f-4e10-8971-86b39b494277",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},objName:"Ops.Boolean.TriggerChangedTrue"},{id:"878a6680-90aa-4150-b81f-150bf105fd74",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"Variable",value:"demo_length"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"47e725ca-4ba2-4ad7-8a61-850d87668ecd",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsOut:[{name:"time",links:[{portIn:"number1",portOut:"time",objIn:"c4ac5031-cf5b-4ece-8f0e-745cbe5b4e6d",objOut:"47e725ca-4ba2-4ad7-8a61-850d87668ecd"},{portIn:"A",portOut:"time",objIn:"72873054-8d8c-43a5-a4db-dd3da14012f6",objOut:"47e725ca-4ba2-4ad7-8a61-850d87668ecd"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"bb9f623b-f6c2-429d-9f32-257190ecf214",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsIn:[{name:"Variable",value:"demo_length"}],portsOut:[{name:"Value",links:[{portIn:"Length",portOut:"Value",objIn:"592298c7-4769-447e-a561-db38762ee5f5",objOut:"bb9f623b-f6c2-429d-9f32-257190ecf214"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"8f935488-a2e4-47ec-814f-fed263d9382b",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},portsOut:[{name:"create port",value:0},{name:"in0 Ops.Gl.ClearColor trigger",links:[{portIn:"Execute",portOut:"in0 Ops.Gl.ClearColor trigger",objIn:"299ac23a-27e6-49a6-96e7-115e36be1a40",objOut:"8f935488-a2e4-47ec-814f-fed263d9382b"}]}],objName:"Ops.Ui.PatchInput"},{id:"8365c441-1498-4cd7-8859-841bc27eb0b8",uiAttribs:{},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Ops.Gl.ClearColor trigger","type":1}],"portsOut":[]}'},{name:"patchId",value:"d2d6bd4c-4b4d-480f-b440-24967a683713"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"4b8ebfcb-c2a4-45e1-b538-cbdc56f42d2a",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsOut:[{name:"time",links:[{portIn:"Current",portOut:"time",objIn:"592298c7-4769-447e-a561-db38762ee5f5",objOut:"4b8ebfcb-c2a4-45e1-b538-cbdc56f42d2a"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"5bad60b7-98aa-4050-b49a-d1389c6d2447",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},objName:"Ops.TimeLine.TimeLinePlay"},{id:"e4cc8d1f-f22e-4f9a-a710-f4802a4bf543",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"Time",portOut:"result",objIn:"6d872c3b-f5a0-4cf0-b480-c8ce35a34a38",objOut:"e4cc8d1f-f22e-4f9a-a710-f4802a4bf543"}]}],objName:"Ops.Math.Subtract"},{id:"0a324160-3592-46d1-85bd-57833db2e0f7",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"Time",portOut:"result",objIn:"7190ca22-4af8-4b02-80c1-856a662f5a31",objOut:"0a324160-3592-46d1-85bd-57833db2e0f7"}]}],objName:"Ops.Math.Sum"},{id:"6d872c3b-f5a0-4cf0-b480-c8ce35a34a38",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},objName:"Ops.TimeLine.TimeLineSetTime"},{id:"7190ca22-4af8-4b02-80c1-856a662f5a31",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},objName:"Ops.TimeLine.TimeLineSetTime"},{id:"19b99a37-3c9f-4c5f-8087-c4ff420e827a",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},objName:"Ops.TimeLine.TimeLineRewind"},{id:"99e362e2-5d9a-4010-931a-79b333a51fdb",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsOut:[{name:"Next",links:[{portIn:"Play",portOut:"Next",objIn:"5bad60b7-98aa-4050-b49a-d1389c6d2447",objOut:"99e362e2-5d9a-4010-931a-79b333a51fdb"}]}],objName:"Ops.TimeLine.TimeLineSetTime"},{id:"a4aa7628-4187-4571-b496-21704f2f397b",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},objName:"Ops.TimeLine.TimeLineSetTime"},{id:"439111e3-3be2-4ca6-a4f2-3d1977649787",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsOut:[{name:"Play/Stop",links:[{portIn:"Is Playing",portOut:"Play/Stop",objIn:"592298c7-4769-447e-a561-db38762ee5f5",objOut:"439111e3-3be2-4ca6-a4f2-3d1977649787"}]},{name:"time",value:184.78539999999998}],objName:"Ops.TimeLine.TimeLineControls"},{id:"592298c7-4769-447e-a561-db38762ee5f5",uiAttribs:{subPatch:"9844bc5e-efd0-4206-bd7d-059aa51fb3ed"},portsIn:[{name:"Clamp",value:1},{name:"Show Time",value:1},{name:"Show Skip Buttons",value:1}],portsOut:[{name:"Play clicked",links:[{portIn:"Update",portOut:"Play clicked",objIn:"99e362e2-5d9a-4010-931a-79b333a51fdb",objOut:"592298c7-4769-447e-a561-db38762ee5f5"}]},{name:"Pause clicked",links:[{portIn:"Pause",portOut:"Pause clicked",objIn:"5bad60b7-98aa-4050-b49a-d1389c6d2447",objOut:"592298c7-4769-447e-a561-db38762ee5f5"}]},{name:"Rewind clicked",links:[{portIn:"exe",portOut:"Rewind clicked",objIn:"19b99a37-3c9f-4c5f-8087-c4ff420e827a",objOut:"592298c7-4769-447e-a561-db38762ee5f5"}]},{name:"Skip Back clicked",links:[{portIn:"Update",portOut:"Skip Back clicked",objIn:"6d872c3b-f5a0-4cf0-b480-c8ce35a34a38",objOut:"592298c7-4769-447e-a561-db38762ee5f5"}]},{name:"Skip Forward clicked",links:[{portIn:"Update",portOut:"Skip Forward clicked",objIn:"7190ca22-4af8-4b02-80c1-856a662f5a31",objOut:"592298c7-4769-447e-a561-db38762ee5f5"}]},{name:"Dragged",links:[{portIn:"Update",portOut:"Dragged",objIn:"a4aa7628-4187-4571-b496-21704f2f397b",objOut:"592298c7-4769-447e-a561-db38762ee5f5"}]},{name:"Current Value",links:[{portIn:"Time",portOut:"Current Value",objIn:"a4aa7628-4187-4571-b496-21704f2f397b",objOut:"592298c7-4769-447e-a561-db38762ee5f5"},{portIn:"Time",portOut:"Current Value",objIn:"99e362e2-5d9a-4010-931a-79b333a51fdb",objOut:"592298c7-4769-447e-a561-db38762ee5f5"},{portIn:"number1",portOut:"Current Value",objIn:"0a324160-3592-46d1-85bd-57833db2e0f7",objOut:"592298c7-4769-447e-a561-db38762ee5f5"},{portIn:"number1",portOut:"Current Value",objIn:"e4cc8d1f-f22e-4f9a-a710-f4802a4bf543",objOut:"592298c7-4769-447e-a561-db38762ee5f5"}]},{name:"Dragging",value:0}],objName:"Ops.Html.PlayerControlPanel_v2"},{id:"f1aacd3c-f363-4339-a0fb-844b8cc9e253",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},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:"51pos4tkk",objOut:"f1aacd3c-f363-4339-a0fb-844b8cc9e253"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"86bad370-6b67-4415-a82c-70adf05dcc61",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"Variable",value:"sceneTex"}],portsOut:[{name:"Value",links:[{portIn:"Image",portOut:"Value",objIn:"f1aacd3c-f363-4339-a0fb-844b8cc9e253",objOut:"86bad370-6b67-4415-a82c-70adf05dcc61"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"8e5b8501-efb6-4575-b3f5-f32bc2be7014",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},objName:"Ops.Html.WindowClose"},{id:"5e50cccc-b0a6-4fd3-8529-e9c386ef689b",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},portsIn:[{name:"sheet",value:"0 (0.)\n48 (1.)\n80 (2.)\n112 (3.)\n144 (4.)\n176 (5.)\n208 (6.)\n240 (7.)\n280 (8.)\n304 (9.)\n336 (10.)"}],portsOut:[{name:"analog 1",links:[{portIn:"Switch Value",portOut:"analog 1",objIn:"299ac23a-27e6-49a6-96e7-115e36be1a40",objOut:"5e50cccc-b0a6-4fd3-8529-e9c386ef689b"}]},{name:"analog 2",value:0},{name:"analog 3",value:0},{name:"analog 4",value:0},{name:"analog 5",value:0},{name:"analog 6",value:0},{name:"analog 7",value:0},{name:"analog 8",value:0}],objName:"Ops.User.anticore.DopeSheet"},{id:"9d85fb49-def6-4707-9e94-a7da0821550b",uiAttribs:{},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:0},{name:"patchId",value:"b0b5b4a6-7957-4a3e-a915-4a236331ad57"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"f67f3a4e-9908-4dad-ad5d-145392ee069d",uiAttribs:{},portsIn:[{name:"Active",value:1},{name:"Force index",value:0},{name:"Force",value:"Resolution"},{name:"Center In Parent",value:1},{name:"Scale to fit Parent",value:1},{name:"Set Width",value:1920},{name:"Set Height",value:1080},{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:"Update",portOut:"Next",objIn:"ab25048f-ec41-44a1-9d5a-3ff0384673f9",objOut:"f67f3a4e-9908-4dad-ad5d-145392ee069d"}]},{name:"Width",links:[{portIn:"Width",portOut:"Width",objIn:"ab25048f-ec41-44a1-9d5a-3ff0384673f9",objOut:"f67f3a4e-9908-4dad-ad5d-145392ee069d"}]},{name:"Height",links:[{portIn:"Height",portOut:"Height",objIn:"ab25048f-ec41-44a1-9d5a-3ff0384673f9",objOut:"f67f3a4e-9908-4dad-ad5d-145392ee069d"}]},{name:"Margin Left",value:-570},{name:"Margin Top",value:-329}],objName:"Ops.Gl.ForceCanvasSize"},{id:"72873054-8d8c-43a5-a4db-dd3da14012f6",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"C",value:60},{name:"D",value:3},{name:"Expression",value:"(a * b) / 60"}],portsOut:[{name:"Result",links:[{portIn:"Value",portOut:"Result",objIn:"24c0a629-cc98-4728-8ae9-d08c9d41be4d",objOut:"72873054-8d8c-43a5-a4db-dd3da14012f6"},{portIn:"Value",portOut:"Result",objIn:"xz077oh7e",objOut:"72873054-8d8c-43a5-a4db-dd3da14012f6"}]},{name:"Expression Valid",value:true}],objName:"Ops.Math.MathExpression"},{id:"24c0a629-cc98-4728-8ae9-d08c9d41be4d",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"Variable",value:"beat"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"xz077oh7e",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsOut:[{name:"Result",links:[{portIn:"Value",portOut:"Result",objIn:"06rxni48q",objOut:"xz077oh7e"}]}],objName:"Ops.Math.Fract"},{id:"06rxni48q",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsOut:[{name:"Result",links:[{portIn:"Value",portOut:"Result",objIn:"7c356a5b-0a8d-465e-bab3-b699e87e0bf8",objOut:"06rxni48q"},{portIn:"Number 1",portOut:"Result",objIn:"zqrh4lgfk",objOut:"06rxni48q"}]}],objName:"Ops.Math.OneMinus"},{id:"7c356a5b-0a8d-465e-bab3-b699e87e0bf8",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"Variable",value:"beatBang"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"9e12a193-43c7-4a04-adc1-30df0c05dbac",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"time",portOut:"Value",objIn:"5e50cccc-b0a6-4fd3-8529-e9c386ef689b",objOut:"9e12a193-43c7-4a04-adc1-30df0c05dbac"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"a90d06a6-d022-4186-b5f7-eecb73cae329",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsOut:[{name:"create port",value:0}],objName:"Ops.Ui.PatchInput"},{id:"9fede47c-448b-4ab1-ba4e-812f4a764bc2",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"8e66a9db-181e-4c97-b6c4-20327b1843c9",uiAttribs:{},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:0},{name:"patchId",value:"10b30ac0-012a-4a7c-8002-380eb93a93c0"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"f175b81c-1cf9-4908-96cf-4f3f9c4da54d",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"Variable",value:"dev"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"57aebcc3-050a-4254-9738-c1042ad5c597",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Pixel",value:2},{name:"Lens Distort",value:0},{name:"Smooth",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"6xwbekyxp",objOut:"57aebcc3-050a-4254-9738-c1042ad5c597"}]}],objName:"Ops.Gl.ImageCompose.ChromaticAberration_v2"},{id:"d537b0eb-e22f-4a25-976f-6c0d050ca09b",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"span index",value:0},{name:"span",value:8},{name:"reduceMin",value:128},{name:"reduceMul",value:8},{name:"use viewport size",value:1},{name:"width",value:0},{name:"height",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"57aebcc3-050a-4254-9738-c1042ad5c597",objOut:"d537b0eb-e22f-4a25-976f-6c0d050ca09b"}]}],objName:"Ops.Gl.ImageCompose.FXAA"},{id:"66fea0b7-f22b-4374-a5c4-c59a8781ddbf",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"Variable",value:"post"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"8a5586b9-add9-483a-a073-22e2d89ac50b",uiAttribs:{},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:0},{name:"patchId",value:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"2937afc0-bcbb-4f22-8393-9b89beec0ae3",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Title",value:"fonts"}],objName:"Ops.Ui.Area"},{id:"629aa2bc-4152-446c-895c-c7bfbc1db24e",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Title",value:"hdr's"}],objName:"Ops.Ui.Area"},{id:"c174128f-5e7c-42f6-a18b-8c86f6e15f3d",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Title",value:"materials"}],objName:"Ops.Ui.Area"},{id:"6d99169e-9aa1-4181-8f7b-203fc7f5630d",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Title",value:"textures"}],objName:"Ops.Ui.Area"},{id:"f91b4507-0b98-4dd7-b655-c934df511a3d",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Title",value:"models"}],objName:"Ops.Ui.Area"},{id:"a3c1643c-e465-43a8-909c-479956f8276d",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"value",value:113}],portsOut:[{name:"result",links:[{portIn:"B",portOut:"result",objIn:"72873054-8d8c-43a5-a4db-dd3da14012f6",objOut:"a3c1643c-e465-43a8-909c-479956f8276d"}]}],objName:"Ops.Number.Number"},{id:"299ac23a-27e6-49a6-96e7-115e36be1a40",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},portsOut:[{name:"Switched Value",value:10},{name:"Trigger 0",links:[{portIn:"in0 Sequence exe",portOut:"Trigger 0",objIn:"3e72isj2d",objOut:"299ac23a-27e6-49a6-96e7-115e36be1a40"}]},{name:"Trigger 1",links:[{portIn:"in0 Ops.Trigger.RouteTrigger Trigger 0",portOut:"Trigger 1",objIn:"brnqmdof0",objOut:"299ac23a-27e6-49a6-96e7-115e36be1a40"}]},{name:"Trigger 2",links:[{portIn:"in0 Sequence exe",portOut:"Trigger 2",objIn:"7fpyvjt0e",objOut:"299ac23a-27e6-49a6-96e7-115e36be1a40"}]},{name:"Trigger 3",links:[{portIn:"in0 Ops.Trigger.RouteTrigger Trigger 0",portOut:"Trigger 3",objIn:"xahkssrav",objOut:"299ac23a-27e6-49a6-96e7-115e36be1a40"}]},{name:"Trigger 4",links:[{portIn:"in0 Sequence exe",portOut:"Trigger 4",objIn:"gfjrak52f",objOut:"299ac23a-27e6-49a6-96e7-115e36be1a40"}]},{name:"Trigger 5",links:[{portIn:"in0 Sequence exe",portOut:"Trigger 5",objIn:"o0uhlestl",objOut:"299ac23a-27e6-49a6-96e7-115e36be1a40"}]},{name:"Trigger 6",links:[{portIn:"in0 Sequence exe",portOut:"Trigger 6",objIn:"eevfr8uys",objOut:"299ac23a-27e6-49a6-96e7-115e36be1a40"}]},{name:"Trigger 7",links:[{portIn:"in0 Sequence exe",portOut:"Trigger 7",objIn:"7k9k2elxv",objOut:"299ac23a-27e6-49a6-96e7-115e36be1a40"}]},{name:"Trigger 8",links:[{portIn:"in0 Sequence exe",portOut:"Trigger 8",objIn:"hn5dov7iv",objOut:"299ac23a-27e6-49a6-96e7-115e36be1a40"}]},{name:"Trigger 9",links:[{portIn:"in0 Sequence exe",portOut:"Trigger 9",objIn:"2chnkyrwc",objOut:"299ac23a-27e6-49a6-96e7-115e36be1a40"}]},{name:"Trigger 10",links:[{portIn:"in0 Sequence exe",portOut:"Trigger 10",objIn:"izpymzwvx",objOut:"299ac23a-27e6-49a6-96e7-115e36be1a40"}]},{name:"Highest Index",value:10}],objName:"Ops.Trigger.RouteTrigger"},{id:"4b9f99e2-5e17-4014-b178-ac16dcdaa3fc",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"value",value:1}],portsOut:[{name:"result",links:[{portIn:"Value",portOut:"result",objIn:"66fea0b7-f22b-4374-a5c4-c59a8781ddbf",objOut:"4b9f99e2-5e17-4014-b178-ac16dcdaa3fc"}]}],objName:"Ops.Boolean.Boolean"},{id:"w9mg6vfc1",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"value",value:0}],portsOut:[{name:"result",links:[{portIn:"Value",portOut:"result",objIn:"f175b81c-1cf9-4908-96cf-4f3f9c4da54d",objOut:"w9mg6vfc1"},{portIn:"Visible",portOut:"result",objIn:"bad867d3-4aeb-4095-87cf-92143c7ccdb5",objOut:"w9mg6vfc1"}]}],objName:"Ops.Boolean.Boolean"},{id:"bad867d3-4aeb-4095-87cf-92143c7ccdb5",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"Opacity",value:1},{name:"Default Minimized",value:0},{name:"Minimized Opacity",value:.5},{name:"Show undo button",value:0},{name:"Show Minimize",value:0},{name:"Title",value:""},{name:"Side",value:0},{name:"Default CSS",value:1}],portsOut:[{name:"childs",title:"Children",links:[{portIn:"link",portOut:"childs",objIn:"bc7ccd34-1a5c-419e-a4ee-f31f42d29b06",objOut:"bad867d3-4aeb-4095-87cf-92143c7ccdb5"}]},{name:"Opfened",value:false,title:"Opened"}],objName:"Ops.Sidebar.Sidebar"},{id:"bc7ccd34-1a5c-419e-a4ee-f31f42d29b06",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"Text",value:"open external"},{name:"Grey Out",value:0},{name:"Visible",value:1}],portsOut:[{name:"childs",links:[{portIn:"link",portOut:"childs",objIn:"bcc6a720-fe03-417f-b317-261b3233cd2f",objOut:"bc7ccd34-1a5c-419e-a4ee-f31f42d29b06"}]},{name:"Pressed Trigger",links:[{portIn:"Trigger",portOut:"Pressed Trigger",objIn:"af3ff653-38ec-4e02-a813-0bbfda34d29f",objOut:"bc7ccd34-1a5c-419e-a4ee-f31f42d29b06"}]}],objName:"Ops.Sidebar.Button_v2"},{id:"af3ff653-38ec-4e02-a813-0bbfda34d29f",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"Named Trigger",value:"openExternal"}],objName:"Ops.Trigger.TriggerSend"},{id:"ab25048f-ec41-44a1-9d5a-3ff0384673f9",uiAttribs:{},portsIn:[{name:"Pos X",value:0},{name:"Pos Y",value:0},{name:"Smoothing",value:1},{name:"Stretch",value:0},{name:"Title",value:"cables"}],portsOut:[{name:"Next",links:[{portIn:"exe 3",portOut:"Next",objIn:"5bba1ef5-ce06-49ed-90e9-09d6cd20f456",objOut:"ab25048f-ec41-44a1-9d5a-3ff0384673f9"}]}],objName:"Ops.Gl.ExternalCanvas"},{id:"67b5e2c6-6563-4646-970f-3314e26f1c6b",uiAttribs:{},portsIn:[{name:"Named Trigger",value:"openExternal"}],portsOut:[{name:"Triggered",links:[{portIn:"Open Window",portOut:"Triggered",objIn:"ab25048f-ec41-44a1-9d5a-3ff0384673f9",objOut:"67b5e2c6-6563-4646-970f-3314e26f1c6b"}]}],objName:"Ops.Trigger.TriggerReceive"},{id:"bcc6a720-fe03-417f-b317-261b3233cd2f",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"Text",value:"post"},{name:"Input",value:0},{name:"Default",value:1},{name:"Grey Out",value:0},{name:"Visible",value:1}],portsOut:[{name:"childs",links:[{portIn:"link",portOut:"childs",objIn:"o3pybmmbx",objOut:"bcc6a720-fe03-417f-b317-261b3233cd2f"}]},{name:"Value",links:[{portIn:"Value",portOut:"Value",objIn:"66fea0b7-f22b-4374-a5c4-c59a8781ddbf",objOut:"bcc6a720-fe03-417f-b317-261b3233cd2f"}]}],objName:"Ops.Sidebar.Toggle_v3"},{id:"iac5cdsvb",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsOut:[{name:"create port",value:0},{name:"in0 Ops.Trigger.RouteTrigger Trigger 0",links:[{portIn:"exe",portOut:"in0 Ops.Trigger.RouteTrigger Trigger 0",objIn:"12qjvei0o",objOut:"iac5cdsvb"}]}],objName:"Ops.Ui.PatchInput"},{id:"ewy4dwt9e",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"brnqmdof0",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Ops.Trigger.RouteTrigger Trigger 0","type":1}],"portsOut":[]}'},{name:"patchId",value:"97550752-dd1e-4d10-89a9-20099811ef1c"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"12qjvei0o",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsOut:[{name:"trigger 6",links:[{portIn:"exe",portOut:"trigger 6",objIn:"eiax5rmqh",objOut:"12qjvei0o"}]},{name:"trigger 9",links:[{portIn:"Render",portOut:"trigger 9",objIn:"e73bkicqg",objOut:"12qjvei0o"}]},{name:"trigger 11",links:[{portIn:"Render",portOut:"trigger 11",objIn:"ulrhh4580",objOut:"12qjvei0o"}]},{name:"trigger 12",links:[{portIn:"Render",portOut:"trigger 12",objIn:"jla88qvsv",objOut:"12qjvei0o"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"fgqh8ouje",objOut:"12qjvei0o"}]}],objName:"Ops.Trigger.Sequence"},{id:"fgqh8ouje",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},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:1},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{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:"h9x9dpnt9",objOut:"fgqh8ouje"}]},{name:"texture_out",links:[{portIn:"Value",portOut:"texture_out",objIn:"f3myngsiw",objOut:"fgqh8ouje"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"f3myngsiw",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Variable",value:"sceneTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"h9x9dpnt9",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Mask Invert",value:0},{name:"Blendmode 1 index",value:0},{name:"Blendmode 1",value:"normal"},{name:"Mask Source 1 index",value:0},{name:"Mask Source 1",value:"R"},{name:"Opacity 1 index",value:0},{name:"Opacity 1",value:"Normal"},{name:"Amount 1",value:1},{name:"Blendmode 2 index",value:0},{name:"Blendmode 2",value:"normal"},{name:"Mask Source 2 index",value:0},{name:"Mask Source 2",value:"R"},{name:"Opacity 2 index",value:0},{name:"Opacity 2",value:"Normal"},{name:"Amount 2",value:1},{name:"Blendmode 3 index",value:6},{name:"Blendmode 3",value:"add"},{name:"Mask Source 3 index",value:0},{name:"Mask Source 3",value:"R"},{name:"Opacity 3 index",value:0},{name:"Opacity 3",value:"Normal"},{name:"Amount 3",value:.88},{name:"Blendmode 4 index",value:3},{name:"Blendmode 4",value:"multiply"},{name:"Mask Source 4 index",value:0},{name:"Mask Source 4",value:"R"},{name:"Opacity 4 index",value:0},{name:"Opacity 4",value:"Normal"},{name:"Amount 4",value:1},{name:"Blendmode 5 index",value:3},{name:"Blendmode 5",value:"multiply"},{name:"Mask Source 5 index",value:0},{name:"Mask Source 5",value:"R"},{name:"Opacity 5 index",value:0},{name:"Opacity 5",value:"Normal"},{name:"Amount 5",value:1},{name:"Blendmode 6 index",value:0},{name:"Blendmode 6",value:"normal"},{name:"Mask Source 6 index",value:0},{name:"Mask Source 6",value:"R"},{name:"Opacity 6 index",value:0},{name:"Opacity 6",value:"Normal"},{name:"Amount 6",value:1},{name:"Blendmode 7 index",value:0},{name:"Blendmode 7",value:"normal"},{name:"Mask Source 7 index",value:0},{name:"Mask Source 7",value:"R"},{name:"Opacity 7 index",value:0},{name:"Opacity 7",value:"Normal"},{name:"Amount 7",value:1},{name:"Blendmode 8 index",value:0},{name:"Blendmode 8",value:"normal"},{name:"Mask Source 8 index",value:0},{name:"Mask Source 8",value:"R"},{name:"Opacity 8 index",value:0},{name:"Opacity 8",value:"Normal"},{name:"Amount 8",value:1}],objName:"Ops.Gl.ImageCompose.MultiDrawImage"},{id:"e73bkicqg",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},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:1},{name:"Wrap",value:"repeat"},{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:"texture_out",links:[{portIn:"Texture 2",portOut:"texture_out",objIn:"h9x9dpnt9",objOut:"e73bkicqg"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"eiax5rmqh",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"8ycj8dl3p",objOut:"eiax5rmqh"}]}],objName:"Ops.Trigger.Sequence"},{id:"8ycj8dl3p",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Canvas"},{name:"texture width",value:1920},{name:"texture height",value:1080},{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:0},{name:"MSAA",value:"none"},{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:"Trigger In",portOut:"trigger",objIn:"a8hobpbuh",objOut:"8ycj8dl3p"}]},{name:"texture",links:[{portIn:"Base Texture",portOut:"texture",objIn:"e73bkicqg",objOut:"8ycj8dl3p"}]}],objName:"Ops.Gl.RenderToTexture_v3"},{id:"30aslp2pi",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Named Trigger",value:"mdlFalling"}],portsOut:[{name:"Triggered",links:[{portIn:"Trigger In",portOut:"Triggered",objIn:"94lkb1z76",objOut:"30aslp2pi"}]}],objName:"Ops.Trigger.TriggerReceive"},{id:"2lvp6ff45",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Named Trigger",value:"mdlSocrates"}],objName:"Ops.Trigger.TriggerSend"},{id:"sjn8j5tn1",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Named Trigger",value:"mdlDrunk"}],portsOut:[{name:"Triggered",links:[{portIn:"Render",portOut:"Triggered",objIn:"zs8ujbtfy",objOut:"sjn8j5tn1"}]}],objName:"Ops.Trigger.TriggerReceive"},{id:"9as5c4pqf",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Named Trigger",value:"mdlDrunk"}],objName:"Ops.Trigger.TriggerSend"},{id:"zqrh4lgfk",uiAttribs:{subPatch:"abd4c25e-4960-42af-b4fc-d93c41038354"},portsIn:[{name:"Number 2",value:0},{name:"Number 3",value:0},{name:"Number 4",value:0},{name:"Number 5",value:0},{name:"Number 6",value:0},{name:"Number 7",value:0},{name:"Number 8",value:0},{name:"Fill Graph",value:1}],objName:"Ops.Ui.VizGraph"},{id:"gi71c87fu",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Url",value:"assets/station_XXX.png"},{name:"Left Pad",value:0},{name:"Num Digits",value:3},{name:"Index Start",value:1},{name:"Index End",value:8},{name:"filter index",value:1},{name:"filter",value:"linear"},{name:"wrap index",value:0},{name:"wrap",value:"repeat"},{name:"Flip",value:0},{name:"unpackPreMultipliedAlpha",value:0}],portsOut:[{name:"TextureArray",links:[{portIn:"array",portOut:"TextureArray",objIn:"qc12ih1ki",objOut:"gi71c87fu"},{portIn:"array",portOut:"TextureArray",objIn:"54zyeanqq",objOut:"gi71c87fu"}]},{name:"Width",value:1920},{name:"Height",value:1285},{name:"Loading",value:0},{name:"Aspect Ratio",value:1.4941634241245136}],objName:"Ops.Gl.TextureArrayLoader_v2"},{id:"qc12ih1ki",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"value",links:[{portIn:"Texture In",portOut:"value",objIn:"wblje4wst",objOut:"qc12ih1ki"},{portIn:"Value",portOut:"value",objIn:"wfzpur17u",objOut:"qc12ih1ki"}]}],objName:"Ops.Array.ArrayGetTexture"},{id:"wblje4wst",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"wj8hpt4du",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"number1",portOut:"Value",objIn:"xmreni9n9",objOut:"wj8hpt4du"},{portIn:"number1",portOut:"Value",objIn:"6y7itkv0t",objOut:"wj8hpt4du"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"xmreni9n9",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"number2",value:4}],portsOut:[{name:"result",links:[{portIn:"Number",portOut:"result",objIn:"3bome42sp",objOut:"xmreni9n9"}]}],objName:"Ops.Math.Multiply"},{id:"1742208tk",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"pingpong",value:0}],portsOut:[{name:"result",links:[{portIn:"index",portOut:"result",objIn:"qc12ih1ki",objOut:"1742208tk"}]}],objName:"Ops.Math.Modulo"},{id:"54zyeanqq",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"length",links:[{portIn:"number2",portOut:"length",objIn:"1742208tk",objOut:"54zyeanqq"}]}],objName:"Ops.Array.ArrayLength_v2"},{id:"3bome42sp",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"Result",links:[{portIn:"number1",portOut:"Result",objIn:"1742208tk",objOut:"3bome42sp"},{portIn:"Seed",portOut:"Result",objIn:"bhqbdfnp9",objOut:"3bome42sp"}]}],objName:"Ops.Math.Floor"},{id:"wfzpur17u",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"stationTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"zs8ujbtfy",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"data",value:""},{name:"glb File",value:"assets/drunk.glb",display:"file"},{name:"Draw",value:1},{name:"Camera index",value:0},{name:"Camera",value:"None"},{name:"Animation",value:""},{name:"Center index",value:1},{name:"Center",value:"XYZ"},{name:"Rescale",value:1},{name:"Rescale Size",value:2.5},{name:"Sync to timeline",value:0},{name:"Loop",value:1},{name:"Normals Format index",value:0},{name:"Normals Format",value:"XYZ"},{name:"Vertices Format index",value:0},{name:"Vertices Format",value:"XYZ"},{name:"Calc Normals index",value:0},{name:"Calc Normals",value:"Auto"},{name:"Hide Nodes",value:0},{name:"Use Material Properties",value:0},{name:"Active",value:1}],portsOut:[{name:"Generator",value:"FBX2glTF v0.9.7"},{name:"GLTF Version",value:2},{name:"Anim Length",value:3},{name:"Anim Time",value:1.1740740740740705},{name:"Loading",value:false}],objName:"Ops.Gl.GLTF.GltfScene_v4"},{id:"39pmkmaq9",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"data",value:""},{name:"glb File",value:"assets/fall.glb",display:"file"},{name:"Draw",value:1},{name:"Camera index",value:0},{name:"Camera",value:"None"},{name:"Animation",value:""},{name:"Center index",value:1},{name:"Center",value:"XYZ"},{name:"Rescale",value:1},{name:"Rescale Size",value:2.5},{name:"Sync to timeline",value:0},{name:"Loop",value:1},{name:"Normals Format index",value:0},{name:"Normals Format",value:"XYZ"},{name:"Vertices Format index",value:0},{name:"Vertices Format",value:"XYZ"},{name:"Calc Normals index",value:0},{name:"Calc Normals",value:"Auto"},{name:"Hide Nodes",value:0},{name:"Use Material Properties",value:0},{name:"Active",value:1}],portsOut:[{name:"Generator",value:"FBX2glTF v0.9.7"},{name:"GLTF Version",value:2},{name:"Anim Length",value:4.25},{name:"Anim Time",value:.01666666666666572},{name:"Loading",value:false}],objName:"Ops.Gl.GLTF.GltfScene_v4"},{id:"x31zrwqan",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Named Trigger",value:"mdlIdle"}],portsOut:[{name:"Triggered",links:[{portIn:"Trigger In",portOut:"Triggered",objIn:"4082k6hl5",objOut:"x31zrwqan"}]}],objName:"Ops.Trigger.TriggerReceive"},{id:"gbi1gehw6",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Material Name",value:"citizen_fbx"}],portsOut:[{name:"Material",links:[{portIn:"Materials",portOut:"Material",objIn:"zs8ujbtfy",objOut:"gbi1gehw6"}]}],objName:"Ops.Gl.GLTF.GltfSetMaterial"},{id:"gervos78q",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Named Trigger",value:"mdlFalling"}],portsOut:[{name:"Triggered",links:[{portIn:"Execute",portOut:"Triggered",objIn:"jk1eg1owl",objOut:"gervos78q"},{portIn:"Trigger In",portOut:"Triggered",objIn:"avfrbcnlg",objOut:"gervos78q"},{portIn:"Trigger In",portOut:"Triggered",objIn:"vovh32xm7",objOut:"gervos78q"},{portIn:"Trigger In",portOut:"Triggered",objIn:"4t8kpkxo4",objOut:"gervos78q"}]}],objName:"Ops.Trigger.TriggerReceive"},{id:"u7z3mnqvb",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Named Trigger",value:"mdlDrunk"}],portsOut:[{name:"Triggered",links:[{portIn:"Execute",portOut:"Triggered",objIn:"jk1eg1owl",objOut:"u7z3mnqvb"}]}],objName:"Ops.Trigger.TriggerReceive"},{id:"riw0vyppt",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Named Trigger",value:"mdlIdle"}],portsOut:[{name:"Triggered",links:[{portIn:"Execute",portOut:"Triggered",objIn:"jk1eg1owl",objOut:"riw0vyppt"}]}],objName:"Ops.Trigger.TriggerReceive"},{id:"jk1eg1owl",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"Next",links:[{portIn:"Trigger In",portOut:"Next",objIn:"5zrib6oau",objOut:"jk1eg1owl"},{portIn:"Trigger In",portOut:"Next",objIn:"cgebpktne",objOut:"jk1eg1owl"},{portIn:"Trigger In",portOut:"Next",objIn:"ktasw0uqn",objOut:"jk1eg1owl"}]}],objName:"Ops.Trigger.TriggerExtender"},{id:"4u94kzczb",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Material Name",value:"male_casualsuit05"}],portsOut:[{name:"Material",links:[{portIn:"Materials",portOut:"Material",objIn:"zs8ujbtfy",objOut:"4u94kzczb"}]}],objName:"Ops.Gl.GLTF.GltfSetMaterial"},{id:"cgebpktne",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"R",value:.9009375},{name:"G",value:.9009375},{name:"B",value:.9009375},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.6287891140871502},{name:"Emissive G",value:.6154530818129118},{name:"Emissive B",value:.02067747350707383},{name:"Shininess",value:.1},{name:"Specular Amount",value:.069},{name:"Specular Model index",value:0},{name:"Specular Model",value:"Blinn"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:1},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:1},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Shader",links:[{portIn:"Shader",portOut:"Shader",objIn:"gbi1gehw6",objOut:"cgebpktne"},{portIn:"Shader",portOut:"Shader",objIn:"azyn8cu70",objOut:"cgebpktne"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"0b4kx5fep",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"File",value:"assets/d_skin.png",display:"file"},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{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:"Diffuse Texture",portOut:"Texture",objIn:"cgebpktne",objOut:"0b4kx5fep"},{portIn:"Diffuse Texture",portOut:"Texture",objIn:"vovh32xm7",objOut:"0b4kx5fep"}]},{name:"Width",value:2048},{name:"Height",value:2048},{name:"Aspect Ratio",value:1},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"r6gx5djc8",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"mdlDrunkAnim"}],portsOut:[{name:"Value",links:[{portIn:"Time",portOut:"Value",objIn:"zs8ujbtfy",objOut:"r6gx5djc8"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"5zrib6oau",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"R",value:.3409375},{name:"G",value:.3409375},{name:"B",value:.3409375},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.6287891140871502},{name:"Emissive G",value:.6154530818129118},{name:"Emissive B",value:.02067747350707383},{name:"Shininess",value:.1},{name:"Specular Amount",value:0},{name:"Specular Model index",value:2},{name:"Specular Model",value:"Phong"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.104},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:1},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Shader",links:[{portIn:"Shader",portOut:"Shader",objIn:"4u94kzczb",objOut:"5zrib6oau"},{portIn:"Shader",portOut:"Shader",objIn:"flzv76h39",objOut:"5zrib6oau"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"pj0lfpbty",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"File",value:"assets/n_suit.png",display:"file"},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{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:"Normal Map",portOut:"Texture",objIn:"5zrib6oau",objOut:"pj0lfpbty"}]},{name:"Width",value:4096},{name:"Height",value:4096},{name:"Aspect Ratio",value:1},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"ktasw0uqn",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"R",value:.15427083333333336},{name:"G",value:.15427083333333336},{name:"B",value:.15427083333333336},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.6287891140871502},{name:"Emissive G",value:.6154530818129118},{name:"Emissive B",value:.02067747350707383},{name:"Shininess",value:3.61},{name:"Specular Amount",value:.023},{name:"Specular Model index",value:2},{name:"Specular Model",value:"Phong"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:1},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.104},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:1},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Shader",links:[{portIn:"Shader",portOut:"Shader",objIn:"gh6op6w3l",objOut:"ktasw0uqn"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"8hh801a0y",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"mdlFallAnim"}],portsOut:[{name:"Value",links:[{portIn:"Time",portOut:"Value",objIn:"39pmkmaq9",objOut:"8hh801a0y"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"vilbwf66l",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Material Name",value:"citizen_fbx"}],portsOut:[{name:"Material",links:[{portIn:"Materials",portOut:"Material",objIn:"39pmkmaq9",objOut:"vilbwf66l"}]}],objName:"Ops.Gl.GLTF.GltfSetMaterial"},{id:"h8ks2ojci",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Material Name",value:"male_casualsuit05"}],portsOut:[{name:"Material",links:[{portIn:"Materials",portOut:"Material",objIn:"39pmkmaq9",objOut:"h8ks2ojci"}]}],objName:"Ops.Gl.GLTF.GltfSetMaterial"},{id:"azyn8cu70",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Material Name",value:"citizen_fbx"}],objName:"Ops.Gl.GLTF.GltfSetMaterial"},{id:"flzv76h39",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Material Name",value:"male_casualsuit05"}],objName:"Ops.Gl.GLTF.GltfSetMaterial"},{id:"jla88qvsv",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Size index",value:2},{name:"Size",value:"Manual"},{name:"Width",value:1920},{name:"Height",value:1080},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"repeat"},{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:"98o5aq8y0",objOut:"jla88qvsv"}]},{name:"texture_out",links:[{portIn:"Texture 1",portOut:"texture_out",objIn:"h9x9dpnt9",objOut:"jla88qvsv"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"nqbqfxsx4",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Url",value:"assets/liqube-vignette_XXX.jpg"},{name:"Left Pad",value:0},{name:"Num Digits",value:3},{name:"Index Start",value:1},{name:"Index End",value:8},{name:"filter index",value:1},{name:"filter",value:"linear"},{name:"wrap index",value:0},{name:"wrap",value:"repeat"},{name:"Flip",value:0},{name:"unpackPreMultipliedAlpha",value:0}],portsOut:[{name:"TextureArray",links:[{portIn:"array",portOut:"TextureArray",objIn:"it7rer7ik",objOut:"nqbqfxsx4"},{portIn:"array",portOut:"TextureArray",objIn:"flkxuuvry",objOut:"nqbqfxsx4"},{portIn:"array",portOut:"TextureArray",objIn:"xcapltao7",objOut:"nqbqfxsx4"}]},{name:"Width",value:1920},{name:"Height",value:1080},{name:"Loading",value:0},{name:"Aspect Ratio",value:1.7777777777777777}],objName:"Ops.Gl.TextureArrayLoader_v2"},{id:"it7rer7ik",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"value",links:[{portIn:"Texture In",portOut:"value",objIn:"abnoq61mx",objOut:"it7rer7ik"},{portIn:"Value",portOut:"value",objIn:"drnm0pwcy",objOut:"it7rer7ik"}]}],objName:"Ops.Array.ArrayGetTexture"},{id:"abnoq61mx",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"drnm0pwcy",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"randomVignetteTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"bhqbdfnp9",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Min",value:0},{name:"Max",value:6.9}],portsOut:[{name:"X",links:[{portIn:"Number",portOut:"X",objIn:"okiyhy1af",objOut:"bhqbdfnp9"}]},{name:"Y",links:[{portIn:"Number",portOut:"Y",objIn:"9g4i695g4",objOut:"bhqbdfnp9"}]},{name:"Z",links:[{portIn:"Number",portOut:"Z",objIn:"lpzm11h28",objOut:"bhqbdfnp9"}]},{name:"W",links:[{portIn:"Number",portOut:"W",objIn:"pzjjubard",objOut:"bhqbdfnp9"}]}],objName:"Ops.Math.RandomNumbers_v3"},{id:"okiyhy1af",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"Result",links:[{portIn:"index",portOut:"Result",objIn:"it7rer7ik",objOut:"okiyhy1af"},{portIn:"Value",portOut:"Result",objIn:"ynlggiyqr",objOut:"okiyhy1af"}]}],objName:"Ops.Math.Floor"},{id:"w08otcbx7",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"randomBeat"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"9g4i695g4",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"Result",links:[{portIn:"Value",portOut:"Result",objIn:"w08otcbx7",objOut:"9g4i695g4"}]}],objName:"Ops.Math.Floor"},{id:"lpzm11h28",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"Result",links:[{portIn:"Value",portOut:"Result",objIn:"037hibf8p",objOut:"lpzm11h28"}]}],objName:"Ops.Math.Floor"},{id:"pzjjubard",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"Result",links:[{portIn:"Value",portOut:"Result",objIn:"43p73xsm3",objOut:"pzjjubard"}]}],objName:"Ops.Math.Floor"},{id:"ynlggiyqr",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"randomBeat2"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"43p73xsm3",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"randomBeat4"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"037hibf8p",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"randomBeat3"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"ityyww3tj",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"data",value:""},{name:"glb File",value:"assets/socrates-d0.glb",display:"file"},{name:"Draw",value:1},{name:"Camera index",value:0},{name:"Camera",value:"None"},{name:"Animation",value:""},{name:"Center index",value:1},{name:"Center",value:"XYZ"},{name:"Rescale",value:1},{name:"Rescale Size",value:2.5},{name:"Time",value:0},{name:"Sync to timeline",value:0},{name:"Loop",value:1},{name:"Normals Format index",value:0},{name:"Normals Format",value:"XYZ"},{name:"Vertices Format index",value:0},{name:"Vertices Format",value:"XYZ"},{name:"Calc Normals index",value:0},{name:"Calc Normals",value:"Auto"},{name:"Hide Nodes",value:0},{name:"Use Material Properties",value:0},{name:"Active",value:1}],portsOut:[{name:"Generator",value:"Khronos glTF Blender I/O v1.2.75"},{name:"GLTF Version",value:2},{name:"Anim Length",value:0},{name:"Anim Time",value:0},{name:"Loading",value:true}],objName:"Ops.Gl.GLTF.GltfScene_v4"},{id:"bmzz3vg43",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Named Trigger",value:"mdlSocrates"}],portsOut:[{name:"Triggered",links:[{portIn:"Render",portOut:"Triggered",objIn:"ityyww3tj",objOut:"bmzz3vg43"}]}],objName:"Ops.Trigger.TriggerReceive"},{id:"cig0yc7ld",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"data",value:""},{name:"glb File",value:"assets/Happy_Idle.glb",display:"file"},{name:"Draw",value:1},{name:"Camera index",value:0},{name:"Camera",value:"None"},{name:"Animation",value:""},{name:"Center index",value:1},{name:"Center",value:"XYZ"},{name:"Rescale",value:1},{name:"Rescale Size",value:2.5},{name:"Sync to timeline",value:0},{name:"Loop",value:1},{name:"Normals Format index",value:0},{name:"Normals Format",value:"XYZ"},{name:"Vertices Format index",value:0},{name:"Vertices Format",value:"XYZ"},{name:"Calc Normals index",value:0},{name:"Calc Normals",value:"Auto"},{name:"Hide Nodes",value:0},{name:"Use Material Properties",value:0},{name:"Active",value:1}],portsOut:[{name:"Generator",value:"FBX2glTF v0.9.7"},{name:"GLTF Version",value:2},{name:"Anim Length",value:3.9583332538604736},{name:"Anim Time",value:3.8916680177052854},{name:"Loading",value:false}],objName:"Ops.Gl.GLTF.GltfScene_v4"},{id:"4082k6hl5",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"R",value:.6142708333333333},{name:"G",value:.6142708333333333},{name:"B",value:.6142708333333333},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.936967151029976},{name:"Emissive G",value:.3813367697060084},{name:"Emissive B",value:.4940920994827973},{name:"Shininess",value:4},{name:"Specular Amount",value:.5},{name:"Specular Model index",value:0},{name:"Specular Model",value:"Blinn"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:1},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Trigger Out",links:[{portIn:"Render",portOut:"Trigger Out",objIn:"cig0yc7ld",objOut:"4082k6hl5"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"xahkssrav",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Ops.Trigger.RouteTrigger Trigger 0","type":1}],"portsOut":[]}'},{name:"patchId",value:"1b2ji7hqx"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"e58096kx8",uiAttribs:{subPatch:"1b2ji7hqx"},portsOut:[{name:"create port",value:0},{name:"in0 Ops.Trigger.RouteTrigger Trigger 0",links:[{portIn:"exe 5",portOut:"in0 Ops.Trigger.RouteTrigger Trigger 0",objIn:"onrx4wxeg",objOut:"e58096kx8"}]}],objName:"Ops.Ui.PatchInput"},{id:"onrx4wxeg",uiAttribs:{subPatch:"1b2ji7hqx"},portsOut:[{name:"trigger 6",links:[{portIn:"exe",portOut:"trigger 6",objIn:"thxbxgmoj",objOut:"onrx4wxeg"}]},{name:"trigger 9",links:[{portIn:"Render",portOut:"trigger 9",objIn:"ophr6oyny",objOut:"onrx4wxeg"}]},{name:"trigger 11",links:[{portIn:"Render",portOut:"trigger 11",objIn:"6zxdx8edm",objOut:"onrx4wxeg"}]},{name:"trigger 12",links:[{portIn:"Render",portOut:"trigger 12",objIn:"eczvvuyyv",objOut:"onrx4wxeg"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"4cja6jowt",objOut:"onrx4wxeg"}]}],objName:"Ops.Trigger.Sequence"},{id:"4cja6jowt",uiAttribs:{subPatch:"1b2ji7hqx"},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:2},{name:"Wrap",value:"mirrored repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{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:"397ql4esm",objOut:"4cja6jowt"}]},{name:"texture_out",links:[{portIn:"Value",portOut:"texture_out",objIn:"ad17gtxnc",objOut:"4cja6jowt"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"ad17gtxnc",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Variable",value:"sceneTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"397ql4esm",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Mask Invert",value:0},{name:"Blendmode 1 index",value:0},{name:"Blendmode 1",value:"normal"},{name:"Mask Source 1 index",value:0},{name:"Mask Source 1",value:"R"},{name:"Opacity 1 index",value:0},{name:"Opacity 1",value:"Normal"},{name:"Amount 1",value:1},{name:"Blendmode 2 index",value:0},{name:"Blendmode 2",value:"normal"},{name:"Mask Source 2 index",value:0},{name:"Mask Source 2",value:"R"},{name:"Opacity 2 index",value:0},{name:"Opacity 2",value:"Normal"},{name:"Amount 2",value:1},{name:"Blendmode 3 index",value:0},{name:"Blendmode 3",value:"normal"},{name:"Mask Source 3 index",value:0},{name:"Mask Source 3",value:"R"},{name:"Opacity 3 index",value:0},{name:"Opacity 3",value:"Normal"},{name:"Amount 3",value:.88},{name:"Blendmode 4 index",value:11},{name:"Blendmode 4",value:"overlay"},{name:"Mask Source 4 index",value:0},{name:"Mask Source 4",value:"R"},{name:"Opacity 4 index",value:0},{name:"Opacity 4",value:"Normal"},{name:"Amount 4",value:1},{name:"Blendmode 5 index",value:3},{name:"Blendmode 5",value:"multiply"},{name:"Mask Source 5 index",value:0},{name:"Mask Source 5",value:"R"},{name:"Opacity 5 index",value:0},{name:"Opacity 5",value:"Normal"},{name:"Amount 5",value:1},{name:"Blendmode 6 index",value:0},{name:"Blendmode 6",value:"normal"},{name:"Mask Source 6 index",value:0},{name:"Mask Source 6",value:"R"},{name:"Opacity 6 index",value:0},{name:"Opacity 6",value:"Normal"},{name:"Amount 6",value:1},{name:"Blendmode 7 index",value:0},{name:"Blendmode 7",value:"normal"},{name:"Mask Source 7 index",value:0},{name:"Mask Source 7",value:"R"},{name:"Opacity 7 index",value:0},{name:"Opacity 7",value:"Normal"},{name:"Amount 7",value:1},{name:"Blendmode 8 index",value:0},{name:"Blendmode 8",value:"normal"},{name:"Mask Source 8 index",value:0},{name:"Mask Source 8",value:"R"},{name:"Opacity 8 index",value:0},{name:"Opacity 8",value:"Normal"},{name:"Amount 8",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"58exs4ol0",objOut:"397ql4esm"}]}],objName:"Ops.Gl.ImageCompose.MultiDrawImage"},{id:"ophr6oyny",uiAttribs:{subPatch:"1b2ji7hqx"},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:1},{name:"Wrap",value:"repeat"},{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:"kh1aim033",objOut:"ophr6oyny"}]},{name:"texture_out",links:[{portIn:"Texture 2",portOut:"texture_out",objIn:"397ql4esm",objOut:"ophr6oyny"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"thxbxgmoj",uiAttribs:{subPatch:"1b2ji7hqx"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"79gu97dxy",objOut:"thxbxgmoj"}]}],objName:"Ops.Trigger.Sequence"},{id:"79gu97dxy",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Canvas"},{name:"texture width",value:1920},{name:"texture height",value:1080},{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:0},{name:"MSAA",value:"none"},{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:"ecb9g1yz0",objOut:"79gu97dxy"}]},{name:"texture",links:[{portIn:"Base Texture",portOut:"texture",objIn:"ophr6oyny",objOut:"79gu97dxy"}]}],objName:"Ops.Gl.RenderToTexture_v3"},{id:"8988u5f77",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Named Trigger",value:"mdlIdle"}],objName:"Ops.Trigger.TriggerSend"},{id:"qpphaosic",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"posX",value:0},{name:"scale",value:.34},{name:"rotX",value:0},{name:"rotY",value:180},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Trigger",portOut:"trigger",objIn:"8988u5f77",objOut:"qpphaosic"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"eczvvuyyv",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Size index",value:2},{name:"Size",value:"Manual"},{name:"Width",value:1920},{name:"Height",value:1080},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"repeat"},{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:"lu7qolm4h",objOut:"eczvvuyyv"}]},{name:"texture_out",links:[{portIn:"Texture 1",portOut:"texture_out",objIn:"397ql4esm",objOut:"eczvvuyyv"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"lu7qolm4h",uiAttribs:{subPatch:"1b2ji7hqx"},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:"9cky70m5w",objOut:"lu7qolm4h"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"v6fdpjh85",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Variable",value:"stationTex"}],portsOut:[{name:"Value",links:[{portIn:"Image",portOut:"Value",objIn:"lu7qolm4h",objOut:"v6fdpjh85"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"9cky70m5w",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Amount",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"dmpo8cjqg",objOut:"9cky70m5w"}]}],objName:"Ops.Gl.ImageCompose.LUTMap"},{id:"0vi2yum50",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"File",value:"assets/lib_lut_lut4.jpg",display:"file"},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Data Format index",value:3},{name:"Data Format",value:"RGBA"},{name:"Flip",value:1},{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:"LUT Image",portOut:"Texture",objIn:"9cky70m5w",objOut:"0vi2yum50"},{portIn:"LUT Image",portOut:"Texture",objIn:"kh1aim033",objOut:"0vi2yum50"}]},{name:"Width",value:512},{name:"Height",value:512},{name:"Aspect Ratio",value:1},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"nswibkbuf",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Cast Light",value:1},{name:"Radius",value:10},{name:"X",value:-9.22},{name:"Y",value:0},{name:"Z",value:1.54},{name:"Point At X",value:0},{name:"Point At Y",value:0},{name:"Point At Z",value:0},{name:"R",value:1},{name:"G",value:.6799999999999997},{name:"B",value:0},{name:"Specular R",value:1},{name:"Specular G",value:.72},{name:"Specular B",value:0},{name:"Cone Angle",value:120},{name:"Inner Cone Angle",value:60},{name:"Spot Exponent",value:.97},{name:"Falloff",value:1e-5},{name:"Cast Shadow",value:0},{name:"Rendering Active",value:1},{name:"Map Size index",value:1},{name:"Map Size",value:512},{name:"Shadow Strength",value:.99},{name:"Near",value:.1},{name:"Far",value:30},{name:"Bias",value:1e-4},{name:"Polygon Offset",value:0},{name:"Normal Offset",value:0},{name:"Blur Amount",value:0},{name:"Enable Advanced",value:0},{name:"MSAA index",value:0},{name:"MSAA",value:"none"},{name:"Texture Filter index",value:0},{name:"Texture Filter",value:"Linear"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"}],portsOut:[{name:"Trigger Out",links:[{portIn:"Trigger In",portOut:"Trigger Out",objIn:"hz20k9nem",objOut:"nswibkbuf"}]},{name:"World Position X",value:-9.220000267028809},{name:"World Position Y",value:0},{name:"World Position Z",value:1.5399999618530273}],objName:"Ops.Gl.Phong.SpotLight_v5"},{id:"hz20k9nem",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Cast Light",value:1},{name:"Radius",value:22.97},{name:"X",value:4.6},{name:"Y",value:3},{name:"Z",value:-.03},{name:"Point At X",value:0},{name:"Point At Y",value:0},{name:"Point At Z",value:0},{name:"R",value:.4957560221354167},{name:"G",value:.7058900390625003},{name:"B",value:.9733333333333334},{name:"Specular R",value:0},{name:"Specular G",value:.1599999999999997},{name:"Specular B",value:1},{name:"Cone Angle",value:120},{name:"Inner Cone Angle",value:60},{name:"Spot Exponent",value:.97},{name:"Falloff",value:1e-5},{name:"Cast Shadow",value:0},{name:"Rendering Active",value:1},{name:"Map Size index",value:1},{name:"Map Size",value:512},{name:"Shadow Strength",value:.99},{name:"Near",value:.1},{name:"Far",value:30},{name:"Bias",value:1e-4},{name:"Polygon Offset",value:0},{name:"Normal Offset",value:0},{name:"Blur Amount",value:0},{name:"Enable Advanced",value:0},{name:"MSAA index",value:0},{name:"MSAA",value:"none"},{name:"Texture Filter index",value:0},{name:"Texture Filter",value:"Linear"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"}],portsOut:[{name:"Trigger Out",links:[{portIn:"Trigger In",portOut:"Trigger Out",objIn:"l2t05quq8",objOut:"hz20k9nem"}]},{name:"World Position X",value:4.599999904632568},{name:"World Position Y",value:3},{name:"World Position Z",value:-.029999999329447746}],objName:"Ops.Gl.Phong.SpotLight_v5"},{id:"dmpo8cjqg",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Samples",value:40},{name:"X",value:0},{name:"Y",value:0},{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:"61pzw3bku",objOut:"dmpo8cjqg"}]}],objName:"Ops.Gl.ImageCompose.ZoomBlur_v2"},{id:"61pzw3bku",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"blendMode index",value:3},{name:"blendMode",value:"multiply"},{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:"r4ggxyno7",objOut:"61pzw3bku"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"mtzz7lonq",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Variable",value:"randomVignetteTex"}],portsOut:[{name:"Value",links:[{portIn:"Image",portOut:"Value",objIn:"61pzw3bku",objOut:"mtzz7lonq"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"ecb9g1yz0",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Axis index",value:0},{name:"Axis",value:"Vertical"},{name:"fov y",value:45.14,title:"FOV Degrees"},{name:"frustum near",value:.1},{name:"frustum far",value:22.11},{name:"Auto Aspect Ratio",value:1},{name:"Aspect Ratio",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Trigger In",portOut:"trigger",objIn:"nswibkbuf",objOut:"ecb9g1yz0"}]},{name:"Aspect",value:1.7777777777777777}],objName:"Ops.Gl.Perspective"},{id:"xj0q626f8",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"number2",value:4}],portsOut:[{name:"result",links:[{portIn:"Intensity",portOut:"result",objIn:"nswibkbuf",objOut:"xj0q626f8"}]}],objName:"Ops.Math.Multiply"},{id:"6traoynvd",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"number1",portOut:"Value",objIn:"zefb9ll4f",objOut:"6traoynvd"},{portIn:"number1",portOut:"Value",objIn:"qlaht7f62",objOut:"6traoynvd"},{portIn:"number1",portOut:"Value",objIn:"upybgo80r",objOut:"6traoynvd"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"s78vswbix",uiAttribs:{subPatch:"1b2ji7hqx"},portsOut:[{name:"Result",links:[{portIn:"number1",portOut:"Result",objIn:"xj0q626f8",objOut:"s78vswbix"}]}],objName:"Ops.Math.Fract"},{id:"zefb9ll4f",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"number2",value:1}],portsOut:[{name:"result",links:[{portIn:"Value",portOut:"result",objIn:"s78vswbix",objOut:"zefb9ll4f"}]}],objName:"Ops.Math.Multiply"},{id:"qlaht7f62",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"number2",value:.5}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"0fq38zpju",objOut:"qlaht7f62"}]}],objName:"Ops.Math.Sum"},{id:"75u1kp46q",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"number2",value:4}],portsOut:[{name:"result",links:[{portIn:"Intensity",portOut:"result",objIn:"hz20k9nem",objOut:"75u1kp46q"}]}],objName:"Ops.Math.Multiply"},{id:"dzlj3wild",uiAttribs:{subPatch:"1b2ji7hqx"},portsOut:[{name:"Result",links:[{portIn:"number1",portOut:"Result",objIn:"75u1kp46q",objOut:"dzlj3wild"}]}],objName:"Ops.Math.Fract"},{id:"0fq38zpju",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"number2",value:1}],portsOut:[{name:"result",links:[{portIn:"Value",portOut:"result",objIn:"dzlj3wild",objOut:"0fq38zpju"}]}],objName:"Ops.Math.Multiply"},{id:"l2t05quq8",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Cast Light",value:1},{name:"Radius",value:10},{name:"X",value:1},{name:"Y",value:5.68},{name:"Z",value:1.43},{name:"Point At X",value:0},{name:"Point At Y",value:0},{name:"Point At Z",value:0},{name:"R",value:1},{name:"G",value:1},{name:"B",value:1},{name:"Specular R",value:1},{name:"Specular G",value:1},{name:"Specular B",value:1},{name:"Cone Angle",value:120},{name:"Inner Cone Angle",value:60},{name:"Spot Exponent",value:.97},{name:"Falloff",value:1e-5},{name:"Cast Shadow",value:0},{name:"Rendering Active",value:1},{name:"Map Size index",value:1},{name:"Map Size",value:512},{name:"Shadow Strength",value:.99},{name:"Near",value:.1},{name:"Far",value:30},{name:"Bias",value:1e-4},{name:"Polygon Offset",value:0},{name:"Normal Offset",value:0},{name:"Blur Amount",value:0},{name:"Enable Advanced",value:0},{name:"MSAA index",value:0},{name:"MSAA",value:"none"},{name:"Texture Filter index",value:0},{name:"Texture Filter",value:"Linear"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"}],portsOut:[{name:"Trigger Out",links:[{portIn:"render",portOut:"Trigger Out",objIn:"qpphaosic",objOut:"l2t05quq8"}]},{name:"World Position X",value:1},{name:"World Position Y",value:5.679999828338623},{name:"World Position Z",value:1.4299999475479126}],objName:"Ops.Gl.Phong.SpotLight_v5"},{id:"upybgo80r",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"Value",portOut:"result",objIn:"6q4qt0qhv",objOut:"upybgo80r"}]}],objName:"Ops.Math.Multiply"},{id:"6q4qt0qhv",uiAttribs:{subPatch:"1b2ji7hqx"},portsOut:[{name:"Result",links:[{portIn:"number1",portOut:"Result",objIn:"19dl4l2vk",objOut:"6q4qt0qhv"}]}],objName:"Ops.Math.Fract"},{id:"19dl4l2vk",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"Intensity",portOut:"result",objIn:"l2t05quq8",objOut:"19dl4l2vk"}]}],objName:"Ops.Math.Multiply"},{id:"6zxdx8edm",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Size index",value:2},{name:"Size",value:"Manual"},{name:"Width",value:1920},{name:"Height",value:1080},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"repeat"},{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:"k23b030al",objOut:"6zxdx8edm"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"qkcz3idot",objOut:"6zxdx8edm"},{portIn:"Image",portOut:"texture_out",objIn:"r4ggxyno7",objOut:"6zxdx8edm"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"k23b030al",uiAttribs:{subPatch:"1b2ji7hqx"},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:"66tb0f8nk",objOut:"k23b030al"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"g3m3sqwz3",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Variable",value:"stationTex"}],portsOut:[{name:"Value",links:[{portIn:"Image",portOut:"Value",objIn:"k23b030al",objOut:"g3m3sqwz3"},{portIn:"Image",portOut:"Value",objIn:"u7235vhhp",objOut:"g3m3sqwz3"},{portIn:"Image",portOut:"Value",objIn:"d6d7h5999",objOut:"g3m3sqwz3"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"qkcz3idot",uiAttribs:{subPatch:"1b2ji7hqx"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"66tb0f8nk",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Invert",value:0},{name:"Black White",value:0},{name:"Remove Alpha",value:1},{name:"Remap",value:1},{name:"Threshold low ",value:.187},{name:"Threshold high",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"d6d7h5999",objOut:"66tb0f8nk"}]}],objName:"Ops.Gl.ImageCompose.LumaKey_v3"},{id:"2a2kuc1zp",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"contrast",value:.603},{name:"brightness",value:.984}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"u7235vhhp",objOut:"2a2kuc1zp"}]}],objName:"Ops.Gl.ImageCompose.BrightnessContrast"},{id:"y9kc32o7h",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Passes",value:7.11},{name:"Clamp",value:0},{name:"direction index",value:2},{name:"direction",value:"horizontal"},{name:"Mask Invert",value:0}],objName:"Ops.Gl.ImageCompose.FastBlur_v2"},{id:"r4ggxyno7",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"blendMode index",value:6},{name:"blendMode",value:"add"},{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}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"u7235vhhp",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"blendMode index",value:3},{name:"blendMode",value:"multiply"},{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:"y9kc32o7h",objOut:"u7235vhhp"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"kh1aim033",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Amount",value:.56}],objName:"Ops.Gl.ImageCompose.LUTMap"},{id:"8rdl4zsea",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"posX",value:0},{name:"posY",value:-.04},{name:"posZ",value:.78},{name:"scale",value:.34},{name:"rotX",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Trigger",portOut:"trigger",objIn:"9as5c4pqf",objOut:"8rdl4zsea"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"48hyk2qry",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"number1",portOut:"Value",objIn:"hadhf9mtb",objOut:"48hyk2qry"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"h8wz3vjaa",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsOut:[{name:"result",links:[{portIn:"Value",portOut:"result",objIn:"cvwxyma75",objOut:"h8wz3vjaa"}]}],objName:"Ops.Math.Sum"},{id:"t1yrupohy",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsOut:[{name:"time",links:[{portIn:"number1",portOut:"time",objIn:"6qswc6845",objOut:"t1yrupohy"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"ff098cbf-3934-4c81-819f-7c86b67491d1",uiAttribs:{subPatch:"bfc44afe-727f-4391-adce-79c291a4f319"},portsOut:[{name:"create port",value:0},{name:"in0 Sequence exe",links:[{portIn:"exe",portOut:"in0 Sequence exe",objIn:"4ecfbad4-7feb-4fa7-96c6-b395940d26ec",objOut:"ff098cbf-3934-4c81-819f-7c86b67491d1"}]}],objName:"Ops.Ui.PatchInput"},{id:"5f1779d8-e0a0-4c7e-99db-abf39789c666",uiAttribs:{subPatch:"bfc44afe-727f-4391-adce-79c291a4f319"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"4ecfbad4-7feb-4fa7-96c6-b395940d26ec",uiAttribs:{subPatch:"bfc44afe-727f-4391-adce-79c291a4f319"},portsOut:[{name:"trigger 6",links:[{portIn:"exe",portOut:"trigger 6",objIn:"1429c7a8-05d8-4d01-aba0-e70d61f1d75b",objOut:"4ecfbad4-7feb-4fa7-96c6-b395940d26ec"}]},{name:"trigger 9",links:[{portIn:"Render",portOut:"trigger 9",objIn:"9c36d9ba-8b45-44db-87ea-80e1db5d5e0a",objOut:"4ecfbad4-7feb-4fa7-96c6-b395940d26ec"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"c0e59e09-31f9-4d83-a0bc-4904572a89b7",objOut:"4ecfbad4-7feb-4fa7-96c6-b395940d26ec"}]}],objName:"Ops.Trigger.Sequence"},{id:"c0e59e09-31f9-4d83-a0bc-4904572a89b7",uiAttribs:{subPatch:"bfc44afe-727f-4391-adce-79c291a4f319"},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:1},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{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:"1c0fbd61-fad1-4c03-a0ea-b28d0d1928ab",objOut:"c0e59e09-31f9-4d83-a0bc-4904572a89b7"}]},{name:"texture_out",links:[{portIn:"Value",portOut:"texture_out",objIn:"6ef16feb-ba84-405f-930f-56c69298e3d3",objOut:"c0e59e09-31f9-4d83-a0bc-4904572a89b7"}]},{name:"Aspect Ratio",value:0},{name:"Texture Width",value:0},{name:"Texture Height",value:0}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"6ef16feb-ba84-405f-930f-56c69298e3d3",uiAttribs:{subPatch:"bfc44afe-727f-4391-adce-79c291a4f319"},portsIn:[{name:"Variable",value:"sceneTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"1c0fbd61-fad1-4c03-a0ea-b28d0d1928ab",uiAttribs:{subPatch:"bfc44afe-727f-4391-adce-79c291a4f319"},portsIn:[{name:"Mask Invert",value:0},{name:"Blendmode 1 index",value:0},{name:"Blendmode 1",value:"normal"},{name:"Mask Source 1 index",value:0},{name:"Mask Source 1",value:"R"},{name:"Opacity 1 index",value:0},{name:"Opacity 1",value:"Normal"},{name:"Amount 1",value:1},{name:"Blendmode 2 index",value:0},{name:"Blendmode 2",value:"normal"},{name:"Mask Source 2 index",value:0},{name:"Mask Source 2",value:"R"},{name:"Opacity 2 index",value:0},{name:"Opacity 2",value:"Normal"},{name:"Amount 2",value:1},{name:"Blendmode 3 index",value:0},{name:"Blendmode 3",value:"normal"},{name:"Mask Source 3 index",value:0},{name:"Mask Source 3",value:"R"},{name:"Opacity 3 index",value:0},{name:"Opacity 3",value:"Normal"},{name:"Amount 3",value:.88},{name:"Blendmode 4 index",value:11},{name:"Blendmode 4",value:"overlay"},{name:"Mask Source 4 index",value:0},{name:"Mask Source 4",value:"R"},{name:"Opacity 4 index",value:0},{name:"Opacity 4",value:"Normal"},{name:"Amount 4",value:1},{name:"Blendmode 5 index",value:3},{name:"Blendmode 5",value:"multiply"},{name:"Mask Source 5 index",value:0},{name:"Mask Source 5",value:"R"},{name:"Opacity 5 index",value:0},{name:"Opacity 5",value:"Normal"},{name:"Amount 5",value:1},{name:"Blendmode 6 index",value:0},{name:"Blendmode 6",value:"normal"},{name:"Mask Source 6 index",value:0},{name:"Mask Source 6",value:"R"},{name:"Opacity 6 index",value:0},{name:"Opacity 6",value:"Normal"},{name:"Amount 6",value:1},{name:"Blendmode 7 index",value:0},{name:"Blendmode 7",value:"normal"},{name:"Mask Source 7 index",value:0},{name:"Mask Source 7",value:"R"},{name:"Opacity 7 index",value:0},{name:"Opacity 7",value:"Normal"},{name:"Amount 7",value:1},{name:"Blendmode 8 index",value:0},{name:"Blendmode 8",value:"normal"},{name:"Mask Source 8 index",value:0},{name:"Mask Source 8",value:"R"},{name:"Opacity 8 index",value:0},{name:"Opacity 8",value:"Normal"},{name:"Amount 8",value:1}],objName:"Ops.Gl.ImageCompose.MultiDrawImage"},{id:"9c36d9ba-8b45-44db-87ea-80e1db5d5e0a",uiAttribs:{subPatch:"bfc44afe-727f-4391-adce-79c291a4f319"},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:1},{name:"Wrap",value:"repeat"},{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:"texture_out",links:[{portIn:"Texture 1",portOut:"texture_out",objIn:"1c0fbd61-fad1-4c03-a0ea-b28d0d1928ab",objOut:"9c36d9ba-8b45-44db-87ea-80e1db5d5e0a"}]},{name:"Aspect Ratio",value:0},{name:"Texture Width",value:0},{name:"Texture Height",value:0}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"1429c7a8-05d8-4d01-aba0-e70d61f1d75b",uiAttribs:{subPatch:"bfc44afe-727f-4391-adce-79c291a4f319"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"9baa6daa-6540-41ac-b0c5-1c57c97da7a7",objOut:"1429c7a8-05d8-4d01-aba0-e70d61f1d75b"}]}],objName:"Ops.Trigger.Sequence"},{id:"9baa6daa-6540-41ac-b0c5-1c57c97da7a7",uiAttribs:{subPatch:"bfc44afe-727f-4391-adce-79c291a4f319"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Canvas"},{name:"texture width",value:1920},{name:"texture height",value:1080},{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:0},{name:"MSAA",value:"none"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{name:"Depth",value:1},{name:"Clear",value:1}],portsOut:[{name:"texture",links:[{portIn:"Base Texture",portOut:"texture",objIn:"9c36d9ba-8b45-44db-87ea-80e1db5d5e0a",objOut:"9baa6daa-6540-41ac-b0c5-1c57c97da7a7"}]}],objName:"Ops.Gl.RenderToTexture_v3"},{id:"d39c876b-40b6-4bd1-8c9f-5305d8c5dea2",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Sequence exe","type":1}],"portsOut":[]}'},{name:"patchId",value:"bfc44afe-727f-4391-adce-79c291a4f319"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"lu6xkvrv0",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Url",value:"assets/trails_XXX.png"},{name:"Left Pad",value:0},{name:"Num Digits",value:3},{name:"Index Start",value:1},{name:"Index End",value:7},{name:"filter index",value:1},{name:"filter",value:"linear"},{name:"wrap index",value:0},{name:"wrap",value:"repeat"},{name:"Flip",value:0},{name:"unpackPreMultipliedAlpha",value:0}],portsOut:[{name:"TextureArray",links:[{portIn:"array",portOut:"TextureArray",objIn:"j6cq1mm9h",objOut:"lu6xkvrv0"},{portIn:"array",portOut:"TextureArray",objIn:"u7d30l0r5",objOut:"lu6xkvrv0"}]},{name:"Width",value:1920},{name:"Height",value:1280},{name:"Loading",value:0},{name:"Aspect Ratio",value:1.5}],objName:"Ops.Gl.TextureArrayLoader_v2"},{id:"j6cq1mm9h",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"value",links:[{portIn:"Texture In",portOut:"value",objIn:"n5pjeer9o",objOut:"j6cq1mm9h"},{portIn:"Value",portOut:"value",objIn:"kc0751zhj",objOut:"j6cq1mm9h"}]}],objName:"Ops.Array.ArrayGetTexture"},{id:"n5pjeer9o",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"kc0751zhj",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"lightsTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"6y7itkv0t",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"Number",portOut:"result",objIn:"dxly5wos7",objOut:"6y7itkv0t"}]}],objName:"Ops.Math.Multiply"},{id:"1eki1840i",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"pingpong",value:0}],portsOut:[{name:"result",links:[{portIn:"index",portOut:"result",objIn:"j6cq1mm9h",objOut:"1eki1840i"},{portIn:"index",portOut:"result",objIn:"flkxuuvry",objOut:"1eki1840i"}]}],objName:"Ops.Math.Modulo"},{id:"u7d30l0r5",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"length",links:[{portIn:"number2",portOut:"length",objIn:"1eki1840i",objOut:"u7d30l0r5"}]}],objName:"Ops.Array.ArrayLength_v2"},{id:"dxly5wos7",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"Result",links:[{portIn:"number1",portOut:"Result",objIn:"1eki1840i",objOut:"dxly5wos7"}]}],objName:"Ops.Math.Floor"},{id:"98o5aq8y0",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},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:"oeyox7s7m",objOut:"98o5aq8y0"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"h0s48bk5z",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Variable",value:"lightsTex"}],portsOut:[{name:"Value",links:[{portIn:"Image",portOut:"Value",objIn:"98o5aq8y0",objOut:"h0s48bk5z"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"oeyox7s7m",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Amount",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"r9jkn52jp",objOut:"oeyox7s7m"}]}],objName:"Ops.Gl.ImageCompose.LUTMap"},{id:"qy1n865an",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"File",value:"assets/lib_lut_lut5.jpg",display:"file"},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Data Format index",value:3},{name:"Data Format",value:"RGBA"},{name:"Flip",value:1},{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:"LUT Image",portOut:"Texture",objIn:"oeyox7s7m",objOut:"qy1n865an"}]},{name:"Width",value:512},{name:"Height",value:512},{name:"Aspect Ratio",value:1},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"cvwxyma75",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Variable",value:"mdlDrunkAnim"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"xhlqie3qq",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsOut:[{name:"Result",links:[{portIn:"Seed",portOut:"Result",objIn:"ziha1pmq9",objOut:"xhlqie3qq"}]}],objName:"Ops.Math.Floor"},{id:"ziha1pmq9",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Min",value:0},{name:"Max",value:360}],portsOut:[{name:"X",links:[{portIn:"number1",portOut:"X",objIn:"h8wz3vjaa",objOut:"ziha1pmq9"}]},{name:"Y",links:[{portIn:"rotY",portOut:"Y",objIn:"8rdl4zsea",objOut:"ziha1pmq9"}]},{name:"Z",value:179.50817933053145},{name:"W",value:1.651570557076254}],objName:"Ops.Math.RandomNumbers_v3"},{id:"hadhf9mtb",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"Number",portOut:"result",objIn:"xhlqie3qq",objOut:"hadhf9mtb"}]}],objName:"Ops.Math.Multiply"},{id:"9ymprs1n1",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"R",value:.30196078431372547},{name:"G",value:.05001225490196076},{name:"B",value:0},{name:"Intensity",value:1}],portsOut:[{name:"Trigger Out",links:[{portIn:"render",portOut:"Trigger Out",objIn:"8rdl4zsea",objOut:"9ymprs1n1"}]}],objName:"Ops.Gl.Phong.AmbientLight_v4"},{id:"a8hobpbuh",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Cast Light",value:1},{name:"Intensity",value:2.28},{name:"Radius",value:10},{name:"X",value:1},{name:"Y",value:.13},{name:"Z",value:.99},{name:"Point At X",value:0},{name:"Point At Y",value:0},{name:"Point At Z",value:0},{name:"R",value:1},{name:"G",value:.56793212890625},{name:"B",value:.56793212890625},{name:"Specular R",value:1},{name:"Specular G",value:1},{name:"Specular B",value:1},{name:"Cone Angle",value:120},{name:"Inner Cone Angle",value:60},{name:"Spot Exponent",value:.97},{name:"Falloff",value:1e-5},{name:"Cast Shadow",value:0},{name:"Rendering Active",value:1},{name:"Map Size index",value:1},{name:"Map Size",value:512},{name:"Shadow Strength",value:.99},{name:"Near",value:.1},{name:"Far",value:30},{name:"Bias",value:1e-4},{name:"Polygon Offset",value:0},{name:"Normal Offset",value:0},{name:"Blur Amount",value:0},{name:"Enable Advanced",value:0},{name:"MSAA index",value:0},{name:"MSAA",value:"none"},{name:"Texture Filter index",value:0},{name:"Texture Filter",value:"Linear"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"}],portsOut:[{name:"Trigger Out",links:[{portIn:"Trigger In",portOut:"Trigger Out",objIn:"9ymprs1n1",objOut:"a8hobpbuh"}]},{name:"World Position X",value:1},{name:"World Position Y",value:.12999999523162842},{name:"World Position Z",value:.9900000095367432}],objName:"Ops.Gl.Phong.SpotLight_v5"},{id:"6qswc6845",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"number2",portOut:"result",objIn:"h8wz3vjaa",objOut:"6qswc6845"}]}],objName:"Ops.Math.Divide"},{id:"d6d7h5999",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"blendMode index",value:3},{name:"blendMode",value:"multiply"},{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:"2a2kuc1zp",objOut:"d6d7h5999"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"ulrhh4580",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Size index",value:2},{name:"Size",value:"Manual"},{name:"Width",value:1920},{name:"Height",value:1080},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"repeat"},{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:"mv9enat55",objOut:"ulrhh4580"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"3vun4mlzo",objOut:"ulrhh4580"},{portIn:"Texture 3",portOut:"texture_out",objIn:"h9x9dpnt9",objOut:"ulrhh4580"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"mv9enat55",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},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:"9jp8xxjay",objOut:"mv9enat55"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"cl7ahi1q4",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Variable",value:"lightsTex"}],portsOut:[{name:"Value",links:[{portIn:"Image",portOut:"Value",objIn:"mv9enat55",objOut:"cl7ahi1q4"},{portIn:"Image",portOut:"Value",objIn:"iu6o6la2y",objOut:"cl7ahi1q4"},{portIn:"Image",portOut:"Value",objIn:"9tfpl1vxi",objOut:"cl7ahi1q4"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"9jp8xxjay",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Invert",value:0},{name:"Black White",value:0},{name:"Remove Alpha",value:1},{name:"Remap",value:1},{name:"Threshold low ",value:.225},{name:"Threshold high",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"9tfpl1vxi",objOut:"9jp8xxjay"}]}],objName:"Ops.Gl.ImageCompose.LumaKey_v3"},{id:"r1jm10xp3",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"contrast",value:.603},{name:"brightness",value:.984}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"iu6o6la2y",objOut:"r1jm10xp3"}]}],objName:"Ops.Gl.ImageCompose.BrightnessContrast"},{id:"173jb1e0k",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Passes",value:7.11},{name:"Clamp",value:0},{name:"direction index",value:2},{name:"direction",value:"horizontal"},{name:"Mask Invert",value:0}],objName:"Ops.Gl.ImageCompose.FastBlur_v2"},{id:"iu6o6la2y",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"blendMode index",value:3},{name:"blendMode",value:"multiply"},{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:"173jb1e0k",objOut:"iu6o6la2y"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"9tfpl1vxi",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"blendMode index",value:3},{name:"blendMode",value:"multiply"},{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:"r1jm10xp3",objOut:"9tfpl1vxi"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"3vun4mlzo",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"flkxuuvry",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsOut:[{name:"value",links:[{portIn:"Value",portOut:"value",objIn:"zk4emaktj",objOut:"flkxuuvry"},{portIn:"Texture In",portOut:"value",objIn:"y0q4igpoi",objOut:"flkxuuvry"}]}],objName:"Ops.Array.ArrayGetTexture"},{id:"zk4emaktj",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"randomVignetteTex2"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"y0q4igpoi",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"fdbpfwc95",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Variable",value:"randomVignetteTex2"}],portsOut:[{name:"Value",links:[{portIn:"Texture 4",portOut:"Value",objIn:"h9x9dpnt9",objOut:"fdbpfwc95"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"7k9k2elxv",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Sequence exe","type":1}],"portsOut":[]}'},{name:"patchId",value:"nfuzc9gb4"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"av9vkp2f0",uiAttribs:{subPatch:"nfuzc9gb4"},portsOut:[{name:"create port",value:0},{name:"in0 Sequence exe",links:[{portIn:"exe",portOut:"in0 Sequence exe",objIn:"n21xrxv10",objOut:"av9vkp2f0"}]}],objName:"Ops.Ui.PatchInput"},{id:"n21xrxv10",uiAttribs:{subPatch:"nfuzc9gb4"},portsOut:[{name:"trigger 6",links:[{portIn:"exe",portOut:"trigger 6",objIn:"curfks71n",objOut:"n21xrxv10"}]},{name:"trigger 7",links:[{portIn:"Render",portOut:"trigger 7",objIn:"mxitomv28",objOut:"n21xrxv10"}]},{name:"trigger 9",links:[{portIn:"Render",portOut:"trigger 9",objIn:"6tg9gc5k1",objOut:"n21xrxv10"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"fyyj1pwjf",objOut:"n21xrxv10"}]}],objName:"Ops.Trigger.Sequence"},{id:"fyyj1pwjf",uiAttribs:{subPatch:"nfuzc9gb4"},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:2},{name:"Wrap",value:"mirrored repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:5},{name:"Pixel Format",value:"SRGBA 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:"tm0yns0tu",objOut:"fyyj1pwjf"}]},{name:"texture_out",links:[{portIn:"Value",portOut:"texture_out",objIn:"qbzll1e1s",objOut:"fyyj1pwjf"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"qbzll1e1s",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Variable",value:"sceneTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"tm0yns0tu",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Mask Invert",value:0},{name:"Blendmode 1 index",value:0},{name:"Blendmode 1",value:"normal"},{name:"Mask Source 1 index",value:0},{name:"Mask Source 1",value:"R"},{name:"Opacity 1 index",value:0},{name:"Opacity 1",value:"Normal"},{name:"Amount 1",value:.297},{name:"Blendmode 2 index",value:2},{name:"Blendmode 2",value:"darken"},{name:"Mask Source 2 index",value:0},{name:"Mask Source 2",value:"R"},{name:"Opacity 2 index",value:0},{name:"Opacity 2",value:"Normal"},{name:"Amount 2",value:1},{name:"Blendmode 3 index",value:0},{name:"Blendmode 3",value:"normal"},{name:"Mask Source 3 index",value:0},{name:"Mask Source 3",value:"R"},{name:"Opacity 3 index",value:0},{name:"Opacity 3",value:"Normal"},{name:"Amount 3",value:1},{name:"Blendmode 4 index",value:11},{name:"Blendmode 4",value:"overlay"},{name:"Mask Source 4 index",value:0},{name:"Mask Source 4",value:"R"},{name:"Opacity 4 index",value:0},{name:"Opacity 4",value:"Normal"},{name:"Amount 4",value:1},{name:"Blendmode 5 index",value:3},{name:"Blendmode 5",value:"multiply"},{name:"Mask Source 5 index",value:0},{name:"Mask Source 5",value:"R"},{name:"Opacity 5 index",value:0},{name:"Opacity 5",value:"Normal"},{name:"Amount 5",value:1},{name:"Blendmode 6 index",value:0},{name:"Blendmode 6",value:"normal"},{name:"Mask Source 6 index",value:0},{name:"Mask Source 6",value:"R"},{name:"Opacity 6 index",value:0},{name:"Opacity 6",value:"Normal"},{name:"Amount 6",value:1},{name:"Blendmode 7 index",value:0},{name:"Blendmode 7",value:"normal"},{name:"Mask Source 7 index",value:0},{name:"Mask Source 7",value:"R"},{name:"Opacity 7 index",value:0},{name:"Opacity 7",value:"Normal"},{name:"Amount 7",value:1},{name:"Blendmode 8 index",value:0},{name:"Blendmode 8",value:"normal"},{name:"Mask Source 8 index",value:0},{name:"Mask Source 8",value:"R"},{name:"Opacity 8 index",value:0},{name:"Opacity 8",value:"Normal"},{name:"Amount 8",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"iri226zob",objOut:"tm0yns0tu"}]}],objName:"Ops.Gl.ImageCompose.MultiDrawImage"},{id:"6tg9gc5k1",uiAttribs:{subPatch:"nfuzc9gb4"},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:1},{name:"Wrap",value:"repeat"},{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:"texture_out",links:[{portIn:"Texture 3",portOut:"texture_out",objIn:"tm0yns0tu",objOut:"6tg9gc5k1"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"curfks71n",uiAttribs:{subPatch:"nfuzc9gb4"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"tkqqpjlhq",objOut:"curfks71n"}]}],objName:"Ops.Trigger.Sequence"},{id:"tkqqpjlhq",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Canvas"},{name:"texture width",value:1920},{name:"texture height",value:1080},{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:0},{name:"MSAA",value:"none"},{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:"exe",portOut:"trigger",objIn:"1o3wtowq7",objOut:"tkqqpjlhq"}]},{name:"texture",links:[{portIn:"Base Texture",portOut:"texture",objIn:"6tg9gc5k1",objOut:"tkqqpjlhq"}]}],objName:"Ops.Gl.RenderToTexture_v3"},{id:"1xlfgjmyt",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Draw",value:1,title:"Render mesh"},{name:"segments",value:4},{name:"stacks",value:300},{name:"length",value:23.3},{name:"outer radius",value:.64},{name:"inner radius",value:0},{name:"UV mode index",value:0},{name:"UV mode",value:"simple"},{name:"Flip Mapping",value:0},{name:"Caps",value:0},{name:"Flat Normals",value:1}],objName:"Ops.Gl.Meshes.Cylinder_v2"},{id:"42ohkjciz",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"posX",value:.03},{name:"scale",value:.91},{name:"rotX",value:0},{name:"rotY",value:90},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"xhmy50ugb",objOut:"42ohkjciz"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"ilw5inq1f",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"R",value:.6855098269143594},{name:"G",value:.6657297021080522},{name:"B",value:.6138437503033101},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.5718450123348118},{name:"Emissive G",value:.8471433928331629},{name:"Emissive B",value:.16685073079966117},{name:"Shininess",value:4},{name:"Specular Amount",value:.5},{name:"Specular Model index",value:0},{name:"Specular Model",value:"Blinn"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1.47},{name:"Diffuse Repeat Y",value:3.89},{name:"Texture Offset Y",value:.04},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:1},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Trigger Out",links:[{portIn:"render",portOut:"Trigger Out",objIn:"42ohkjciz",objOut:"ilw5inq1f"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"xhmy50ugb",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Height",value:1.54},{name:"Axis index",value:2},{name:"Axis",value:"Z"}],portsOut:[{name:"Trigger",links:[{portIn:"render",portOut:"Trigger",objIn:"nrfi71zta",objOut:"xhmy50ugb"}]}],objName:"Ops.Gl.ShaderEffects.Twist_v3"},{id:"nrfi71zta",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Amount",value:-.98},{name:"RotX",value:0},{name:"RotY",value:78.98},{name:"RotZ",value:0},{name:"Scale",value:.18},{name:"Offset",value:-1.03},{name:"Limited",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"1xlfgjmyt",objOut:"nrfi71zta"}]}],objName:"Ops.Gl.ShaderEffects.Bend_v2"},{id:"bx8hrydxe",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"File",value:"assets/gfx-scroller.png",display:"file"},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{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:"Diffuse Texture",portOut:"Texture",objIn:"ilw5inq1f",objOut:"bx8hrydxe"}]},{name:"Width",value:1920},{name:"Height",value:128},{name:"Aspect Ratio",value:15},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"4bzyao7f6",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Variable",value:"randomVignetteTex"}],portsOut:[{name:"Value",links:[{portIn:"Texture 1",portOut:"Value",objIn:"tm0yns0tu",objOut:"4bzyao7f6"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"q8zjgh51u",uiAttribs:{subPatch:"nfuzc9gb4"},portsOut:[{name:"time",links:[{portIn:"number1",portOut:"time",objIn:"y7io0htet",objOut:"q8zjgh51u"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"y7io0htet",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"number2",value:13.55}],portsOut:[{name:"result",links:[{portIn:"Texture Offset X",portOut:"result",objIn:"ilw5inq1f",objOut:"y7io0htet"}]}],objName:"Ops.Math.Divide"},{id:"iri226zob",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"amount",value:3.35},{name:"direction index",value:0},{name:"direction",value:"both"},{name:"Fast",value:1}],objName:"Ops.Gl.ImageCompose.Blur"},{id:"pvjw12gnm",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Named Trigger",value:"preframe"}],portsOut:[{name:"Triggered",links:[{portIn:"Render",portOut:"Triggered",objIn:"qruizibi6",objOut:"pvjw12gnm"}]}],objName:"Ops.Trigger.TriggerReceive"},{id:"qruizibi6",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},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:1},{name:"Wrap",value:"repeat"},{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:"ibgd33duz",objOut:"qruizibi6"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"1kij5i50r",objOut:"qruizibi6"},{portIn:"Value",portOut:"texture_out",objIn:"jwv26zl62",objOut:"qruizibi6"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"xcapltao7",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"index",value:6}],portsOut:[{name:"value",links:[{portIn:"Base Texture",portOut:"value",objIn:"qruizibi6",objOut:"xcapltao7"}]}],objName:"Ops.Array.ArrayGetTexture"},{id:"1kij5i50r",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"ibgd33duz",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Mask Invert",value:0},{name:"Invert R",value:1},{name:"Invert G",value:1},{name:"Invert B",value:1}],objName:"Ops.Gl.ImageCompose.Invert_v2"},{id:"muv08hdqy",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Variable",value:"invertedVignette"}],portsOut:[{name:"Value",links:[{portIn:"mask",portOut:"Value",objIn:"iri226zob",objOut:"muv08hdqy"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"jwv26zl62",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"invertedVignette"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"mxitomv28",uiAttribs:{subPatch:"nfuzc9gb4"},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:1},{name:"Wrap",value:"repeat"},{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:"339g6gcc2",objOut:"mxitomv28"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"cdvmc6o2k",objOut:"mxitomv28"},{portIn:"Texture 2",portOut:"texture_out",objIn:"tm0yns0tu",objOut:"mxitomv28"}]},{name:"Aspect Ratio",value:1.4941634241245136},{name:"Texture Width",value:1920},{name:"Texture Height",value:1285}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"mcbkkqyym",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Variable",value:"stationTex"}],portsOut:[{name:"Value",links:[{portIn:"Base Texture",portOut:"Value",objIn:"mxitomv28",objOut:"mcbkkqyym"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"cdvmc6o2k",uiAttribs:{subPatch:"nfuzc9gb4"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"339g6gcc2",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Amount",value:1}],objName:"Ops.Gl.ImageCompose.LUTMap"},{id:"67mw86ave",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"File",value:"assets/lib_lut_lut8.jpg",display:"file"},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Data Format index",value:3},{name:"Data Format",value:"RGBA"},{name:"Flip",value:1},{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:"LUT Image",portOut:"Texture",objIn:"339g6gcc2",objOut:"67mw86ave"}]},{name:"Width",value:512},{name:"Height",value:512},{name:"Aspect Ratio",value:1},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"7fpyvjt0e",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Sequence exe","type":1}],"portsOut":[]}'},{name:"patchId",value:"yhlhmvwcf"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"zegjgk95z",uiAttribs:{subPatch:"yhlhmvwcf"},portsOut:[{name:"create port",value:0},{name:"in0 Sequence exe",links:[{portIn:"exe",portOut:"in0 Sequence exe",objIn:"q9lhn1tq3",objOut:"zegjgk95z"}]}],objName:"Ops.Ui.PatchInput"},{id:"q9lhn1tq3",uiAttribs:{subPatch:"yhlhmvwcf"},portsOut:[{name:"trigger 6",links:[{portIn:"exe",portOut:"trigger 6",objIn:"baoluswkf",objOut:"q9lhn1tq3"}]},{name:"trigger 7",links:[{portIn:"Render",portOut:"trigger 7",objIn:"5saj5ze9z",objOut:"q9lhn1tq3"}]},{name:"trigger 9",links:[{portIn:"Render",portOut:"trigger 9",objIn:"glf6s2c0c",objOut:"q9lhn1tq3"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"xsg3xtp0v",objOut:"q9lhn1tq3"}]}],objName:"Ops.Trigger.Sequence"},{id:"xsg3xtp0v",uiAttribs:{subPatch:"yhlhmvwcf"},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:2},{name:"Wrap",value:"mirrored repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{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:"vdg8yh39d",objOut:"xsg3xtp0v"}]},{name:"texture_out",links:[{portIn:"Value",portOut:"texture_out",objIn:"5hkpabi56",objOut:"xsg3xtp0v"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"5hkpabi56",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Variable",value:"sceneTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"vdg8yh39d",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Mask Invert",value:0},{name:"Blendmode 1 index",value:0},{name:"Blendmode 1",value:"normal"},{name:"Mask Source 1 index",value:0},{name:"Mask Source 1",value:"R"},{name:"Opacity 1 index",value:0},{name:"Opacity 1",value:"Normal"},{name:"Amount 1",value:1},{name:"Blendmode 2 index",value:0},{name:"Blendmode 2",value:"normal"},{name:"Mask Source 2 index",value:0},{name:"Mask Source 2",value:"R"},{name:"Opacity 2 index",value:0},{name:"Opacity 2",value:"Normal"},{name:"Amount 2",value:1},{name:"Blendmode 3 index",value:0},{name:"Blendmode 3",value:"normal"},{name:"Mask Source 3 index",value:0},{name:"Mask Source 3",value:"R"},{name:"Opacity 3 index",value:0},{name:"Opacity 3",value:"Normal"},{name:"Amount 3",value:.88},{name:"Blendmode 4 index",value:3},{name:"Blendmode 4",value:"multiply"},{name:"Mask Source 4 index",value:0},{name:"Mask Source 4",value:"R"},{name:"Opacity 4 index",value:0},{name:"Opacity 4",value:"Normal"},{name:"Amount 4",value:1},{name:"Blendmode 5 index",value:3},{name:"Blendmode 5",value:"multiply"},{name:"Mask Source 5 index",value:0},{name:"Mask Source 5",value:"R"},{name:"Opacity 5 index",value:0},{name:"Opacity 5",value:"Normal"},{name:"Amount 5",value:1},{name:"Blendmode 6 index",value:0},{name:"Blendmode 6",value:"normal"},{name:"Mask Source 6 index",value:0},{name:"Mask Source 6",value:"R"},{name:"Opacity 6 index",value:0},{name:"Opacity 6",value:"Normal"},{name:"Amount 6",value:1},{name:"Blendmode 7 index",value:0},{name:"Blendmode 7",value:"normal"},{name:"Mask Source 7 index",value:0},{name:"Mask Source 7",value:"R"},{name:"Opacity 7 index",value:0},{name:"Opacity 7",value:"Normal"},{name:"Amount 7",value:1},{name:"Blendmode 8 index",value:0},{name:"Blendmode 8",value:"normal"},{name:"Mask Source 8 index",value:0},{name:"Mask Source 8",value:"R"},{name:"Opacity 8 index",value:0},{name:"Opacity 8",value:"Normal"},{name:"Amount 8",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"7e9sa01e4",objOut:"vdg8yh39d"}]}],objName:"Ops.Gl.ImageCompose.MultiDrawImage"},{id:"glf6s2c0c",uiAttribs:{subPatch:"yhlhmvwcf"},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:1},{name:"Wrap",value:"repeat"},{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:"texture_out",links:[{portIn:"Texture 3",portOut:"texture_out",objIn:"vdg8yh39d",objOut:"glf6s2c0c"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"baoluswkf",uiAttribs:{subPatch:"yhlhmvwcf"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"6zt5p2l5q",objOut:"baoluswkf"}]}],objName:"Ops.Trigger.Sequence"},{id:"6zt5p2l5q",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Canvas"},{name:"texture width",value:1920},{name:"texture height",value:1080},{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:0},{name:"MSAA",value:"none"},{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:"flmke194r",objOut:"6zt5p2l5q"}]},{name:"texture",links:[{portIn:"Base Texture",portOut:"texture",objIn:"glf6s2c0c",objOut:"6zt5p2l5q"}]}],objName:"Ops.Gl.RenderToTexture_v3"},{id:"3t04xpfq8",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Named Trigger",value:"mdlFalling"}],objName:"Ops.Trigger.TriggerSend"},{id:"4nh6rs2am",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"posX",value:0},{name:"scale",value:1},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Trigger In",portOut:"trigger",objIn:"5wo701n1c",objOut:"4nh6rs2am"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"flmke194r",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Axis index",value:0},{name:"Axis",value:"Vertical"},{name:"fov y",value:13.41,title:"FOV Degrees"},{name:"frustum near",value:.1},{name:"frustum far",value:20},{name:"Auto Aspect Ratio",value:1},{name:"Aspect Ratio",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"4nh6rs2am",objOut:"flmke194r"}]},{name:"Aspect",value:1.7777777777777777}],objName:"Ops.Gl.Perspective"},{id:"wzc88h234",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Variable",value:"mdlFallAnim"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"5ufwceamw",uiAttribs:{subPatch:"yhlhmvwcf"},portsOut:[{name:"time",links:[{portIn:"number1",portOut:"time",objIn:"8in7zpzy6",objOut:"5ufwceamw"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"8in7zpzy6",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"number2",value:1}],portsOut:[{name:"result",links:[{portIn:"Value",portOut:"result",objIn:"wzc88h234",objOut:"8in7zpzy6"}]}],objName:"Ops.Math.Divide"},{id:"3ufpw3xcf",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Material Name",value:"low-poly"}],portsOut:[{name:"Material",links:[{portIn:"Materials",portOut:"Material",objIn:"39pmkmaq9",objOut:"3ufpw3xcf"}]}],objName:"Ops.Gl.GLTF.GltfSetMaterial"},{id:"avfrbcnlg",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"R",value:.40739815427557957},{name:"G",value:.8265610889075303},{name:"B",value:.7575200173272809},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:1},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.299113675442489},{name:"Emissive G",value:.4805045083566244},{name:"Emissive B",value:.15740253024605066},{name:"Shininess",value:4},{name:"Specular Amount",value:0},{name:"Specular Model index",value:0},{name:"Specular Model",value:"Blinn"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:1},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Shader",links:[{portIn:"Shader",portOut:"Shader",objIn:"3ufpw3xcf",objOut:"avfrbcnlg"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"ophgm12w6",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"stationTex"}],portsOut:[{name:"Value",links:[{portIn:"Emissive Texture",portOut:"Value",objIn:"avfrbcnlg",objOut:"ophgm12w6"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"arziyfest",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"lightsTex"}],portsOut:[{name:"Value",links:[{portIn:"Environment Map",portOut:"Value",objIn:"vovh32xm7",objOut:"arziyfest"},{portIn:"Environment Map",portOut:"Value",objIn:"4t8kpkxo4",objOut:"arziyfest"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"vovh32xm7",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"R",value:.8142708333333333},{name:"G",value:.5649302101135253},{name:"B",value:.6034221688230832},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.299113675442489},{name:"Emissive G",value:.4805045083566244},{name:"Emissive B",value:.15740253024605066},{name:"Shininess",value:1.11},{name:"Specular Amount",value:0},{name:"Specular Model index",value:0},{name:"Specular Model",value:"Blinn"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:1},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Shader",links:[{portIn:"Shader",portOut:"Shader",objIn:"vilbwf66l",objOut:"vovh32xm7"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"4t8kpkxo4",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"R",value:.2209375},{name:"G",value:.2171482276916504},{name:"B",value:.2171482276916504},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.299113675442489},{name:"Emissive G",value:.4805045083566244},{name:"Emissive B",value:.15740253024605066},{name:"Shininess",value:3.93},{name:"Specular Amount",value:0},{name:"Specular Model index",value:0},{name:"Specular Model",value:"Blinn"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:.579},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Shader",links:[{portIn:"Shader",portOut:"Shader",objIn:"h8ks2ojci",objOut:"4t8kpkxo4"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"5saj5ze9z",uiAttribs:{subPatch:"yhlhmvwcf"},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:1},{name:"Wrap",value:"repeat"},{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:"oze5gv8px",objOut:"5saj5ze9z"}]},{name:"texture_out",links:[{portIn:"Texture 2",portOut:"texture_out",objIn:"vdg8yh39d",objOut:"5saj5ze9z"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"oze5gv8px",uiAttribs:{subPatch:"yhlhmvwcf"},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:1},{name:"Scale X",value:1},{name:"Scale Y",value:1},{name:"Position X",value:0},{name:"Rotation",value:0},{name:"Clip Repeat",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"l9efz6w1l",objOut:"oze5gv8px"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"zsk0zxcjo",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Variable",value:"lightsTex"}],portsOut:[{name:"Value",links:[{portIn:"Image",portOut:"Value",objIn:"oze5gv8px",objOut:"zsk0zxcjo"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"l9efz6w1l",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Samples",value:40},{name:"X",value:0},{name:"Source Strength Map index",value:0},{name:"Source Strength Map",value:"R"},{name:"Invert Strength Map",value:0}],objName:"Ops.Gl.ImageCompose.ZoomBlur_v2"},{id:"7e9sa01e4",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Amount",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"pthqxajyu",objOut:"7e9sa01e4"}]}],objName:"Ops.Gl.ImageCompose.LUTMap"},{id:"rjal8xdwd",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"File",value:"assets/lib_lut_lut11.jpg",display:"file"},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Data Format index",value:3},{name:"Data Format",value:"RGBA"},{name:"Flip",value:1},{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:"LUT Image",portOut:"Texture",objIn:"7e9sa01e4",objOut:"rjal8xdwd"}]},{name:"Width",value:512},{name:"Height",value:512},{name:"Aspect Ratio",value:1},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"5o267jl05",uiAttribs:{subPatch:"wbx4aydb0"},portsOut:[{name:"create port",value:0},{name:"in0 Sequence exe",links:[{portIn:"exe",portOut:"in0 Sequence exe",objIn:"goip71404",objOut:"5o267jl05"}]}],objName:"Ops.Ui.PatchInput"},{id:"mjynu4l79",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"goip71404",uiAttribs:{subPatch:"wbx4aydb0"},portsOut:[{name:"trigger 6",links:[{portIn:"exe",portOut:"trigger 6",objIn:"4y9z4wqre",objOut:"goip71404"}]},{name:"trigger 9",links:[{portIn:"Render",portOut:"trigger 9",objIn:"7ov358v0h",objOut:"goip71404"}]},{name:"trigger 13",links:[{portIn:"Render",portOut:"trigger 13",objIn:"rx5cna7dd",objOut:"goip71404"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"jzk82n0xc",objOut:"goip71404"}]}],objName:"Ops.Trigger.Sequence"},{id:"jzk82n0xc",uiAttribs:{subPatch:"wbx4aydb0"},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:1},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{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:"mu4wucxm9",objOut:"jzk82n0xc"}]},{name:"texture_out",links:[{portIn:"Value",portOut:"texture_out",objIn:"opnd3crge",objOut:"jzk82n0xc"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"opnd3crge",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Variable",value:"sceneTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"mu4wucxm9",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Mask Invert",value:0},{name:"Blendmode 1 index",value:0},{name:"Blendmode 1",value:"normal"},{name:"Mask Source 1 index",value:0},{name:"Mask Source 1",value:"R"},{name:"Opacity 1 index",value:0},{name:"Opacity 1",value:"Normal"},{name:"Amount 1",value:1},{name:"Blendmode 2 index",value:0},{name:"Blendmode 2",value:"normal"},{name:"Mask Source 2 index",value:0},{name:"Mask Source 2",value:"R"},{name:"Opacity 2 index",value:0},{name:"Opacity 2",value:"Normal"},{name:"Amount 2",value:1},{name:"Blendmode 3 index",value:3},{name:"Blendmode 3",value:"multiply"},{name:"Mask Source 3 index",value:0},{name:"Mask Source 3",value:"R"},{name:"Opacity 3 index",value:0},{name:"Opacity 3",value:"Normal"},{name:"Amount 3",value:.88},{name:"Blendmode 4 index",value:11},{name:"Blendmode 4",value:"overlay"},{name:"Mask Source 4 index",value:0},{name:"Mask Source 4",value:"R"},{name:"Opacity 4 index",value:0},{name:"Opacity 4",value:"Normal"},{name:"Amount 4",value:1},{name:"Blendmode 5 index",value:3},{name:"Blendmode 5",value:"multiply"},{name:"Mask Source 5 index",value:0},{name:"Mask Source 5",value:"R"},{name:"Opacity 5 index",value:0},{name:"Opacity 5",value:"Normal"},{name:"Amount 5",value:1},{name:"Blendmode 6 index",value:0},{name:"Blendmode 6",value:"normal"},{name:"Mask Source 6 index",value:0},{name:"Mask Source 6",value:"R"},{name:"Opacity 6 index",value:0},{name:"Opacity 6",value:"Normal"},{name:"Amount 6",value:1},{name:"Blendmode 7 index",value:0},{name:"Blendmode 7",value:"normal"},{name:"Mask Source 7 index",value:0},{name:"Mask Source 7",value:"R"},{name:"Opacity 7 index",value:0},{name:"Opacity 7",value:"Normal"},{name:"Amount 7",value:1},{name:"Blendmode 8 index",value:0},{name:"Blendmode 8",value:"normal"},{name:"Mask Source 8 index",value:0},{name:"Mask Source 8",value:"R"},{name:"Opacity 8 index",value:0},{name:"Opacity 8",value:"Normal"},{name:"Amount 8",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"7rxhdy1db",objOut:"mu4wucxm9"}]}],objName:"Ops.Gl.ImageCompose.MultiDrawImage"},{id:"7ov358v0h",uiAttribs:{subPatch:"wbx4aydb0"},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:1},{name:"Wrap",value:"repeat"},{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:"texture_out",links:[{portIn:"Texture 2",portOut:"texture_out",objIn:"mu4wucxm9",objOut:"7ov358v0h"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"4y9z4wqre",uiAttribs:{subPatch:"wbx4aydb0"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"ld0z7l4tz",objOut:"4y9z4wqre"}]}],objName:"Ops.Trigger.Sequence"},{id:"ld0z7l4tz",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Canvas"},{name:"texture width",value:1920},{name:"texture height",value:1080},{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:0},{name:"MSAA",value:"none"},{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:"exe",portOut:"trigger",objIn:"obd0y6opt",objOut:"ld0z7l4tz"}]},{name:"texture",links:[{portIn:"Base Texture",portOut:"texture",objIn:"7ov358v0h",objOut:"ld0z7l4tz"}]}],objName:"Ops.Gl.RenderToTexture_v3"},{id:"o0uhlestl",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Sequence exe","type":1}],"portsOut":[]}'},{name:"patchId",value:"wbx4aydb0"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"0vc1vhc6s",uiAttribs:{subPatch:"x8e2jwc2f"},portsOut:[{name:"create port",value:0},{name:"in0 Sequence exe",links:[{portIn:"exe",portOut:"in0 Sequence exe",objIn:"pdimxdmrt",objOut:"0vc1vhc6s"}]}],objName:"Ops.Ui.PatchInput"},{id:"qo688q5jr",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"pdimxdmrt",uiAttribs:{subPatch:"x8e2jwc2f"},portsOut:[{name:"trigger 0",links:[{portIn:"exe",portOut:"trigger 0",objIn:"r70f3gbon",objOut:"pdimxdmrt"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"hg039ehcf",objOut:"pdimxdmrt"}]}],objName:"Ops.Trigger.Sequence"},{id:"hg039ehcf",uiAttribs:{subPatch:"x8e2jwc2f"},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:1},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{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:"0lpiv0jlt",objOut:"hg039ehcf"}]},{name:"texture_out",links:[{portIn:"Value",portOut:"texture_out",objIn:"v19icphya",objOut:"hg039ehcf"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"v19icphya",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Variable",value:"sceneTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"0lpiv0jlt",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Mask Invert",value:0},{name:"Blendmode 1 index",value:0},{name:"Blendmode 1",value:"normal"},{name:"Mask Source 1 index",value:0},{name:"Mask Source 1",value:"R"},{name:"Opacity 1 index",value:0},{name:"Opacity 1",value:"Normal"},{name:"Amount 1",value:1},{name:"Blendmode 2 index",value:3},{name:"Blendmode 2",value:"multiply"},{name:"Mask Source 2 index",value:0},{name:"Mask Source 2",value:"R"},{name:"Opacity 2 index",value:0},{name:"Opacity 2",value:"Normal"},{name:"Amount 2",value:1},{name:"Blendmode 3 index",value:0},{name:"Blendmode 3",value:"normal"},{name:"Mask Source 3 index",value:0},{name:"Mask Source 3",value:"R"},{name:"Opacity 3 index",value:0},{name:"Opacity 3",value:"Normal"},{name:"Amount 3",value:.88},{name:"Blendmode 4 index",value:11},{name:"Blendmode 4",value:"overlay"},{name:"Mask Source 4 index",value:0},{name:"Mask Source 4",value:"R"},{name:"Opacity 4 index",value:0},{name:"Opacity 4",value:"Normal"},{name:"Amount 4",value:1},{name:"Blendmode 5 index",value:3},{name:"Blendmode 5",value:"multiply"},{name:"Mask Source 5 index",value:0},{name:"Mask Source 5",value:"R"},{name:"Opacity 5 index",value:0},{name:"Opacity 5",value:"Normal"},{name:"Amount 5",value:1},{name:"Blendmode 6 index",value:0},{name:"Blendmode 6",value:"normal"},{name:"Mask Source 6 index",value:0},{name:"Mask Source 6",value:"R"},{name:"Opacity 6 index",value:0},{name:"Opacity 6",value:"Normal"},{name:"Amount 6",value:1},{name:"Blendmode 7 index",value:0},{name:"Blendmode 7",value:"normal"},{name:"Mask Source 7 index",value:0},{name:"Mask Source 7",value:"R"},{name:"Opacity 7 index",value:0},{name:"Opacity 7",value:"Normal"},{name:"Amount 7",value:1},{name:"Blendmode 8 index",value:0},{name:"Blendmode 8",value:"normal"},{name:"Mask Source 8 index",value:0},{name:"Mask Source 8",value:"R"},{name:"Opacity 8 index",value:0},{name:"Opacity 8",value:"Normal"},{name:"Amount 8",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"zn5erzi53",objOut:"0lpiv0jlt"}]}],objName:"Ops.Gl.ImageCompose.MultiDrawImage"},{id:"gfjrak52f",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Sequence exe","type":1}],"portsOut":[]}'},{name:"patchId",value:"x8e2jwc2f"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"7juyoxwxr",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"create port",value:0},{name:"in0 Sequence exe",links:[{portIn:"exe",portOut:"in0 Sequence exe",objIn:"0t6erdha7",objOut:"7juyoxwxr"}]}],objName:"Ops.Ui.PatchInput"},{id:"qjjig2rht",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"0t6erdha7",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"trigger 6",links:[{portIn:"exe",portOut:"trigger 6",objIn:"js8t8ie3z",objOut:"0t6erdha7"}]},{name:"trigger 13",links:[{portIn:"Render",portOut:"trigger 13",objIn:"rtq7l2mua",objOut:"0t6erdha7"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"o1c43ohap",objOut:"0t6erdha7"}]}],objName:"Ops.Trigger.Sequence"},{id:"o1c43ohap",uiAttribs:{subPatch:"kb5v7uxi5"},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:1},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{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:"cbj6ahuk5",objOut:"o1c43ohap"}]},{name:"texture_out",links:[{portIn:"Value",portOut:"texture_out",objIn:"63ds6jes9",objOut:"o1c43ohap"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"63ds6jes9",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Variable",value:"sceneTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"cbj6ahuk5",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Mask Invert",value:0},{name:"Blendmode 1 index",value:0},{name:"Blendmode 1",value:"normal"},{name:"Mask Source 1 index",value:0},{name:"Mask Source 1",value:"R"},{name:"Opacity 1 index",value:0},{name:"Opacity 1",value:"Normal"},{name:"Amount 1",value:1},{name:"Blendmode 2 index",value:3},{name:"Blendmode 2",value:"multiply"},{name:"Mask Source 2 index",value:0},{name:"Mask Source 2",value:"R"},{name:"Opacity 2 index",value:0},{name:"Opacity 2",value:"Normal"},{name:"Amount 2",value:.71},{name:"Blendmode 3 index",value:0},{name:"Blendmode 3",value:"normal"},{name:"Mask Source 3 index",value:0},{name:"Mask Source 3",value:"R"},{name:"Opacity 3 index",value:0},{name:"Opacity 3",value:"Normal"},{name:"Amount 3",value:.88},{name:"Blendmode 4 index",value:11},{name:"Blendmode 4",value:"overlay"},{name:"Mask Source 4 index",value:0},{name:"Mask Source 4",value:"R"},{name:"Opacity 4 index",value:0},{name:"Opacity 4",value:"Normal"},{name:"Amount 4",value:1},{name:"Blendmode 5 index",value:3},{name:"Blendmode 5",value:"multiply"},{name:"Mask Source 5 index",value:0},{name:"Mask Source 5",value:"R"},{name:"Opacity 5 index",value:0},{name:"Opacity 5",value:"Normal"},{name:"Amount 5",value:1},{name:"Blendmode 6 index",value:0},{name:"Blendmode 6",value:"normal"},{name:"Mask Source 6 index",value:0},{name:"Mask Source 6",value:"R"},{name:"Opacity 6 index",value:0},{name:"Opacity 6",value:"Normal"},{name:"Amount 6",value:1},{name:"Blendmode 7 index",value:0},{name:"Blendmode 7",value:"normal"},{name:"Mask Source 7 index",value:0},{name:"Mask Source 7",value:"R"},{name:"Opacity 7 index",value:0},{name:"Opacity 7",value:"Normal"},{name:"Amount 7",value:1},{name:"Blendmode 8 index",value:0},{name:"Blendmode 8",value:"normal"},{name:"Mask Source 8 index",value:0},{name:"Mask Source 8",value:"R"},{name:"Opacity 8 index",value:0},{name:"Opacity 8",value:"Normal"},{name:"Amount 8",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"n6e626ojc",objOut:"cbj6ahuk5"}]}],objName:"Ops.Gl.ImageCompose.MultiDrawImage"},{id:"js8t8ie3z",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"trigger 0",links:[{portIn:"exe",portOut:"trigger 0",objIn:"pq0hdz9r8",objOut:"js8t8ie3z"}]}],objName:"Ops.Trigger.Sequence"},{id:"izpymzwvx",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Sequence exe","type":1}],"portsOut":[]}'},{name:"patchId",value:"kb5v7uxi5"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"3aw6tv4fz",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Text",value:"NO YOUTUBE É..."},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:0},{name:"vertical align",value:"Top"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:2.1857142262644587},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"yyni46vx6",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:-3.33},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"7aledp1xr",objOut:"yyni46vx6"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"7aledp1xr",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Text",value:"VER DEMOS"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:2},{name:"vertical align",value:"Bottom"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1}],portsOut:[{name:"Next",links:[{portIn:"Render",portOut:"Next",objIn:"3aw6tv4fz",objOut:"7aledp1xr"}]},{name:"Total Lines",value:1},{name:"Width",value:1.4949999722567475},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"prgz7uip6",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"file",value:"assets/xband-ro.ttf",display:"file"},{name:"family",value:"XBAND Rough"},{name:"Active",value:1}],portsOut:[{name:"Loaded",value:1}],objName:"Ops.Html.FontFile_v2"},{id:"hf70ssz00",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Variable",value:"mdlIdleAnim"}],portsOut:[{name:"Value",links:[{portIn:"Time",portOut:"Value",objIn:"cig0yc7ld",objOut:"hf70ssz00"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"pdwgyyxhu",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Value",value:0},{name:"Variable",value:"mdlIdleAnim"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"o3pybmmbx",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"Label",value:"Incrementor"},{name:"min",value:0},{name:"stepsize",value:1},{name:"Default",value:0},{name:"Values",value:0},{name:"Grey Out",value:0}],portsOut:[{name:"childs",links:[{portIn:"link",portOut:"childs",objIn:"a5on9gden",objOut:"o3pybmmbx"}]},{name:"value",links:[{portIn:"Value",portOut:"value",objIn:"4h4jarnup",objOut:"o3pybmmbx"}]}],objName:"Ops.Sidebar.Incrementor_v2"},{id:"9b2iebw9i",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},portsIn:[{name:"Value",value:9},{name:"Variable",value:"noOfScenes"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"8zp4f989h",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"Variable",value:"noOfScenes"}],portsOut:[{name:"Value",links:[{portIn:"number1",portOut:"Value",objIn:"ra4inw5x8",objOut:"8zp4f989h"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"ra4inw5x8",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"number2",value:1}],portsOut:[{name:"result",links:[{portIn:"max",portOut:"result",objIn:"o3pybmmbx",objOut:"ra4inw5x8"}]}],objName:"Ops.Math.Subtract"},{id:"4h4jarnup",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"Variable",value:"currentSceneDev"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"5cvg6cwgg",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},portsIn:[{name:"Variable",value:"currentSceneDev"}],portsOut:[{name:"Value",value:0}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"e7yikoq4a",uiAttribs:{subPatch:"qjbpb8llo"},portsOut:[{name:"create port",value:0},{name:"in0 Sequence exe",links:[{portIn:"exe",portOut:"in0 Sequence exe",objIn:"px2y73v7f",objOut:"e7yikoq4a"}]}],objName:"Ops.Ui.PatchInput"},{id:"4g2bdeksg",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"px2y73v7f",uiAttribs:{subPatch:"qjbpb8llo"},portsOut:[{name:"trigger 5",links:[{portIn:"exe",portOut:"trigger 5",objIn:"ufuwl6u2m",objOut:"px2y73v7f"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"oc16qu3q9",objOut:"px2y73v7f"}]}],objName:"Ops.Trigger.Sequence"},{id:"oc16qu3q9",uiAttribs:{subPatch:"qjbpb8llo"},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:1},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{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:"35b1nvdq0",objOut:"oc16qu3q9"}]},{name:"texture_out",links:[{portIn:"Value",portOut:"texture_out",objIn:"jafxepbxh",objOut:"oc16qu3q9"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"jafxepbxh",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Variable",value:"sceneTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"35b1nvdq0",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Mask Invert",value:0},{name:"Blendmode 1 index",value:0},{name:"Blendmode 1",value:"normal"},{name:"Mask Source 1 index",value:0},{name:"Mask Source 1",value:"R"},{name:"Opacity 1 index",value:0},{name:"Opacity 1",value:"Normal"},{name:"Amount 1",value:.139},{name:"Blendmode 2 index",value:1},{name:"Blendmode 2",value:"lighten"},{name:"Mask Source 2 index",value:0},{name:"Mask Source 2",value:"R"},{name:"Opacity 2 index",value:0},{name:"Opacity 2",value:"Normal"},{name:"Amount 2",value:1},{name:"Blendmode 3 index",value:3},{name:"Blendmode 3",value:"multiply"},{name:"Mask Source 3 index",value:0},{name:"Mask Source 3",value:"R"},{name:"Opacity 3 index",value:0},{name:"Opacity 3",value:"Normal"},{name:"Amount 3",value:1},{name:"Blendmode 4 index",value:11},{name:"Blendmode 4",value:"overlay"},{name:"Mask Source 4 index",value:0},{name:"Mask Source 4",value:"R"},{name:"Opacity 4 index",value:0},{name:"Opacity 4",value:"Normal"},{name:"Amount 4",value:1},{name:"Blendmode 5 index",value:3},{name:"Blendmode 5",value:"multiply"},{name:"Mask Source 5 index",value:0},{name:"Mask Source 5",value:"R"},{name:"Opacity 5 index",value:0},{name:"Opacity 5",value:"Normal"},{name:"Amount 5",value:1},{name:"Blendmode 6 index",value:0},{name:"Blendmode 6",value:"normal"},{name:"Mask Source 6 index",value:0},{name:"Mask Source 6",value:"R"},{name:"Opacity 6 index",value:0},{name:"Opacity 6",value:"Normal"},{name:"Amount 6",value:1},{name:"Blendmode 7 index",value:0},{name:"Blendmode 7",value:"normal"},{name:"Mask Source 7 index",value:0},{name:"Mask Source 7",value:"R"},{name:"Opacity 7 index",value:0},{name:"Opacity 7",value:"Normal"},{name:"Amount 7",value:1},{name:"Blendmode 8 index",value:0},{name:"Blendmode 8",value:"normal"},{name:"Mask Source 8 index",value:0},{name:"Mask Source 8",value:"R"},{name:"Opacity 8 index",value:0},{name:"Opacity 8",value:"Normal"},{name:"Amount 8",value:1}],objName:"Ops.Gl.ImageCompose.MultiDrawImage"},{id:"eevfr8uys",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Sequence exe","type":1}],"portsOut":[{"name":"out0 title in0 Sequence exe","type":1}]}'},{name:"patchId",value:"qjbpb8llo"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"s0c8dfjg6",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Cast Light",value:1},{name:"Intensity",value:.48},{name:"X",value:-4},{name:"Y",value:8.2},{name:"Z",value:4.11},{name:"R",value:1},{name:"G",value:1},{name:"B",value:1},{name:"Specular R",value:0},{name:"Specular G",value:0},{name:"Specular B",value:0},{name:"Cast Shadow",value:0},{name:"Rendering Active",value:1},{name:"Map Size index",value:1},{name:"Map Size",value:512},{name:"Shadow Strength",value:1},{name:"LR-BottomTop",value:8},{name:"Near",value:.1},{name:"Far",value:30},{name:"Bias",value:.004},{name:"Polygon Offset",value:0},{name:"Normal Offset",value:0},{name:"Blur Amount",value:0},{name:"Enable Advanced",value:0},{name:"MSAA index",value:0},{name:"MSAA",value:"none"},{name:"Texture Filter index",value:0},{name:"Texture Filter",value:"Linear"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"}],portsOut:[{name:"Trigger Out",links:[{portIn:"Trigger In",portOut:"Trigger Out",objIn:"wmw27m1tw",objOut:"s0c8dfjg6"}]}],objName:"Ops.Gl.Phong.DirectionalLight_v5"},{id:"vjw2ilbv4",uiAttribs:{subPatch:"x8e2jwc2f"},portsOut:[{name:"trigger 0",links:[{portIn:"Trigger In",portOut:"trigger 0",objIn:"2fdoid4b2",objOut:"vjw2ilbv4"}]}],objName:"Ops.Trigger.Sequence"},{id:"t8fijspzw",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"use viewport size",value:0},{name:"texture width",value:640},{name:"texture height",value:640},{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:2},{name:"MSAA",value:"4x"},{name:"HDR",value:0,title:"Pixelformat Float 32bit"},{name:"Depth",value:1},{name:"Clear",value:1}],portsOut:[{name:"trigger",links:[{portIn:"exe",portOut:"trigger",objIn:"vjw2ilbv4",objOut:"t8fijspzw"}]},{name:"texture",links:[{portIn:"Image",portOut:"texture",objIn:"jxt2xtb7u",objOut:"t8fijspzw"},{portIn:"Base Texture",portOut:"texture",objIn:"emguwjswi",objOut:"t8fijspzw"},{portIn:"Base Texture",portOut:"texture",objIn:"1bh8uz882",objOut:"t8fijspzw"},{portIn:"Mask",portOut:"texture",objIn:"5bsbwzc3e",objOut:"t8fijspzw"}]}],objName:"Ops.Gl.RenderToTexture"},{id:"vucd04g1x",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{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:"num columns",value:1},{name:"num rows",value:1},{name:"axis index",value:0},{name:"axis",value:"xy"},{name:"Active",value:1,title:"Render mesh"}],objName:"Ops.Gl.Meshes.Rectangle_v2"},{id:"e200hva55",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"posX",value:0},{name:"posY",value:.51},{name:"posZ",value:0},{name:"scale",value:1.77},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"vucd04g1x",objOut:"e200hva55"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"mjp5wr98p",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"r",value:.8922275391012302},{name:"g",value:.45188428780340617},{name:"b",value:.3308771565625803},{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:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"e200hva55",objOut:"mjp5wr98p"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"nt78h88mp",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"radius",value:1},{name:"stacks",value:50},{name:"slices",value:50},{name:"Filloffset",value:1},{name:"Render",value:1}],objName:"Ops.Gl.Meshes.Sphere_v2"},{id:"hjqfbd1k5",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"R",value:0},{name:"G",value:.6562499999999996},{name:"B",value:1},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:1},{name:"Emissive G",value:0},{name:"Emissive B",value:.9762499999999994},{name:"Shininess",value:20.58},{name:"Specular Amount",value:0},{name:"Specular Model index",value:1},{name:"Specular Model",value:"Schlick"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:.003},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Trigger Out",links:[{portIn:"Render",portOut:"Trigger Out",objIn:"skn6tlqjo",objOut:"hjqfbd1k5"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"skn6tlqjo",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Extrude",value:1.07},{name:"Mode index",value:0},{name:"Mode",value:"Norm"},{name:"Axis index",value:0},{name:"Axis",value:"XYZ"},{name:"Coordinates index",value:1},{name:"Coordinates",value:"Mesh XY"},{name:"Channel index",value:0},{name:"Channel",value:"Luminance"},{name:"Flip index",value:0},{name:"Flip",value:"None"},{name:"Range index",value:2},{name:"Range",value:"Normalized"},{name:"Offset X",value:0},{name:"Offset Y",value:0},{name:"Scale",value:.5},{name:"Calc Normals",value:1},{name:"Normal Axis index",value:2},{name:"Normal Axis",value:"Z"},{name:"Discard Zero Values",value:0},{name:"colorize",value:0},{name:"Colorize Min",value:0},{name:"Colorize Max",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"jao5bf4iv",objOut:"skn6tlqjo"}]}],objName:"Ops.Gl.ShaderEffects.VertexDisplacementMap_v4"},{id:"6k5f3voab",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Size index",value:1},{name:"Size",value:"Manual"},{name:"Width",value:50},{name:"Height",value:50},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:2},{name:"Wrap",value:"mirrored repeat"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{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:"mhijzjlfb",objOut:"6k5f3voab"},{portIn:"Trigger in",portOut:"Next",objIn:"qy3po9gmp",objOut:"6k5f3voab"}]},{name:"texture_out",links:[{portIn:"Texture",portOut:"texture_out",objIn:"skn6tlqjo",objOut:"6k5f3voab"}]},{name:"Aspect Ratio",value:1},{name:"Texture Width",value:50},{name:"Texture Height",value:50}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"mhijzjlfb",uiAttribs:{subPatch:"x8e2jwc2f"},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:1},{name:"Color index",value:1},{name:"Color",value:"RGB"},{name:"Scale",value:4.64},{name:"Multiply",value:1},{name:"Value index",value:0},{name:"Value",value:"0-1"},{name:"Harmonics index",value:0},{name:"Harmonics",value:"1"},{name:"X",value:0},{name:"Offset Multiply",value:1},{name:"Offset X index",value:0},{name:"Offset X",value:"None"},{name:"Offset Y index",value:0},{name:"Offset Y",value:"None"},{name:"Offset Z index",value:1},{name:"Offset Z",value:"R"}],objName:"Ops.Gl.ImageCompose.Noise.PerlinNoise_v2"},{id:"ezzfa56mg",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Speed",value:1},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",value:304.6432999999523}],objName:"Ops.Anim.Timer_v2"},{id:"jao5bf4iv",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"posX",value:0},{name:"posY",value:-.2},{name:"posZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"nt78h88mp",objOut:"jao5bf4iv"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"bnvjom26q",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"number2",value:23.65}],portsOut:[{name:"result",links:[{portIn:"rotX",portOut:"result",objIn:"jao5bf4iv",objOut:"bnvjom26q"},{portIn:"rotY",portOut:"result",objIn:"jao5bf4iv",objOut:"bnvjom26q"},{portIn:"rotZ",portOut:"result",objIn:"jao5bf4iv",objOut:"bnvjom26q"}]}],objName:"Ops.Math.Multiply"},{id:"wmw27m1tw",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Cast Light",value:1},{name:"Intensity",value:.56},{name:"X",value:1.34},{name:"Y",value:-8.13},{name:"Z",value:-5.14},{name:"R",value:1},{name:"G",value:1},{name:"B",value:1},{name:"Specular R",value:.2},{name:"Specular G",value:.2},{name:"Specular B",value:.2},{name:"Cast Shadow",value:0},{name:"Rendering Active",value:1},{name:"Map Size index",value:1},{name:"Map Size",value:512},{name:"Shadow Strength",value:1},{name:"LR-BottomTop",value:8},{name:"Near",value:.1},{name:"Far",value:30},{name:"Bias",value:.004},{name:"Polygon Offset",value:0},{name:"Normal Offset",value:0},{name:"Blur Amount",value:0},{name:"Enable Advanced",value:0},{name:"MSAA index",value:0},{name:"MSAA",value:"none"},{name:"Texture Filter index",value:0},{name:"Texture Filter",value:"Linear"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"}],portsOut:[{name:"Trigger Out",links:[{portIn:"Trigger In",portOut:"Trigger Out",objIn:"hjqfbd1k5",objOut:"wmw27m1tw"}]}],objName:"Ops.Gl.Phong.DirectionalLight_v5"},{id:"obwrrf3ce",uiAttribs:{subPatch:"x8e2jwc2f"},portsOut:[{name:"trigger 1",links:[{portIn:"render",portOut:"trigger 1",objIn:"t8fijspzw",objOut:"obwrrf3ce"}]},{name:"trigger 3",links:[{portIn:"exe",portOut:"trigger 3",objIn:"bffq9ibt2",objOut:"obwrrf3ce"}]},{name:"trigger 4",links:[{portIn:"render",portOut:"trigger 4",objIn:"boy572c3o",objOut:"obwrrf3ce"}]},{name:"trigger 5",links:[{portIn:"Trigger In",portOut:"trigger 5",objIn:"nvis4tyau",objOut:"obwrrf3ce"}]},{name:"trigger 6",links:[{portIn:"Trigger In",portOut:"trigger 6",objIn:"7tgr8s0fe",objOut:"obwrrf3ce"}]},{name:"trigger 15",links:[{portIn:"exe",portOut:"trigger 15",objIn:"hyo5lm2yx",objOut:"obwrrf3ce"}]}],objName:"Ops.Trigger.Sequence"},{id:"799me75z1",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Strength",value:66.42},{name:"Width",value:.237},{name:"Mul Color",value:.268}],portsOut:[{name:"Trigger",links:[{portIn:"render",portOut:"Trigger",objIn:"eqfv1v7gr",objOut:"799me75z1"}]}],objName:"Ops.Gl.ImageCompose.EdgeDetection_v4"},{id:"kxcym63yz",uiAttribs:{subPatch:"x8e2jwc2f"},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:1},{name:"Wrap",value:"repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"jxt2xtb7u",objOut:"kxcym63yz"}]},{name:"texture_out",links:[{portIn:"texture",portOut:"texture_out",objIn:"mjp5wr98p",objOut:"kxcym63yz"},{portIn:"Texture In",portOut:"texture_out",objIn:"zg9zpfoks",objOut:"kxcym63yz"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"emguwjswi",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Auto"},{name:"Width",value:640},{name:"Height",value:480},{name:"Filter index",value:0},{name:"Filter",value:"nearest"},{name:"Wrap index",value:0},{name:"Wrap",value:"clamp to edge"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"799me75z1",objOut:"emguwjswi"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"yaj2rmxef",objOut:"emguwjswi"},{portIn:"Image",portOut:"texture_out",objIn:"xj7rxnecy",objOut:"emguwjswi"}]},{name:"Aspect Ratio",value:1},{name:"Texture Width",value:640},{name:"Texture Height",value:640}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"jxt2xtb7u",uiAttribs:{subPatch:"x8e2jwc2f"},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:0},{name:"Mask Src",value:"alpha channel"},{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:"xj7rxnecy",objOut:"jxt2xtb7u"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"yaj2rmxef",uiAttribs:{subPatch:"x8e2jwc2f"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"xj7rxnecy",uiAttribs:{subPatch:"x8e2jwc2f"},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:0},{name:"Mask Src",value:"alpha channel"},{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:"j1x90073m",objOut:"xj7rxnecy"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"eqfv1v7gr",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Invert",value:0},{name:"Black White",value:0},{name:"Threshold low ",value:.173},{name:"Threshold high",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"gxp2ly83t",objOut:"eqfv1v7gr"}]}],objName:"Ops.Gl.ImageCompose.LumaKey_v2"},{id:"gxp2ly83t",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"amount",value:1},{name:"direction index",value:2},{name:"direction",value:"horizontal"},{name:"Fast",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"5f3iocx5z",objOut:"gxp2ly83t"}]}],objName:"Ops.Gl.ImageCompose.Blur"},{id:"8875708pc",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Blend Mode index",value:6},{name:"Blend Mode",value:"add"},{name:"Amount",value:1},{name:"Strength",value:2.9},{name:"Width",value:.838},{name:"Mul Color",value:0}],portsOut:[{name:"Trigger",links:[{portIn:"render",portOut:"Trigger",objIn:"boitoqoih",objOut:"8875708pc"}]}],objName:"Ops.Gl.ImageCompose.EdgeDetection_v4"},{id:"1bh8uz882",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Auto"},{name:"Width",value:640},{name:"Height",value:480},{name:"Filter index",value:0},{name:"Filter",value:"nearest"},{name:"Wrap index",value:0},{name:"Wrap",value:"clamp to edge"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"8875708pc",objOut:"1bh8uz882"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"040k0xi8h",objOut:"1bh8uz882"},{portIn:"Image",portOut:"texture_out",objIn:"j1x90073m",objOut:"1bh8uz882"}]},{name:"Aspect Ratio",value:1},{name:"Texture Width",value:640},{name:"Texture Height",value:640}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"040k0xi8h",uiAttribs:{subPatch:"x8e2jwc2f"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"boitoqoih",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Invert",value:0},{name:"Black White",value:1},{name:"Threshold low ",value:.884},{name:"Threshold high",value:1}],objName:"Ops.Gl.ImageCompose.LumaKey_v2"},{id:"j1x90073m",uiAttribs:{subPatch:"x8e2jwc2f"},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:0},{name:"Mask Src",value:"alpha channel"},{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:"0wyjm29dv",objOut:"j1x90073m"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"u4fnju4u2",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"amount",value:.5},{name:"Lumi Scale",value:.9},{name:"X or Y",value:0},{name:"Line Size",value:4},{name:"Displacement",value:0},{name:"Add",value:.02},{name:"scroll",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"ixdqm15qr",objOut:"u4fnju4u2"}]}],objName:"Ops.Gl.ImageCompose.Interlace"},{id:"zg9zpfoks",uiAttribs:{subPatch:"x8e2jwc2f"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"0wyjm29dv",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"contrast",value:.438},{name:"brightness",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"u4fnju4u2",objOut:"0wyjm29dv"}]}],objName:"Ops.Gl.ImageCompose.BrightnessContrast"},{id:"2fdoid4b2",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"R",value:.0006103515625},{name:"G",value:.7364109802246095},{name:"B",value:1},{name:"Intensity",value:.109}],portsOut:[{name:"Trigger Out",links:[{portIn:"Trigger In",portOut:"Trigger Out",objIn:"s0c8dfjg6",objOut:"2fdoid4b2"},{portIn:"Render",portOut:"Trigger Out",objIn:"6k5f3voab",objOut:"2fdoid4b2"}]}],objName:"Ops.Gl.Phong.AmbientLight_v4"},{id:"bffq9ibt2",uiAttribs:{subPatch:"x8e2jwc2f"},portsOut:[{name:"trigger 0",links:[{portIn:"Render",portOut:"trigger 0",objIn:"1bh8uz882",objOut:"bffq9ibt2"}]},{name:"trigger 1",links:[{portIn:"render",portOut:"trigger 1",objIn:"mjp5wr98p",objOut:"bffq9ibt2"}]},{name:"trigger 2",links:[{portIn:"Render",portOut:"trigger 2",objIn:"kxcym63yz",objOut:"bffq9ibt2"}]},{name:"trigger 3",links:[{portIn:"Render",portOut:"trigger 3",objIn:"3lgnty56z",objOut:"bffq9ibt2"}]},{name:"trigger 4",links:[{portIn:"Render",portOut:"trigger 4",objIn:"emguwjswi",objOut:"bffq9ibt2"}]}],objName:"Ops.Trigger.Sequence"},{id:"zwtrb6wjh",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"posY",value:-2.45},{name:"scale",value:1},{name:"rotX",value:-90},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"v3ju5zq52",objOut:"zwtrb6wjh"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"zey7hxe4f",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"num x",value:2},{name:"num y",value:2},{name:"mul",value:.15},{name:"center",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"gg7icqqi2",objOut:"zey7hxe4f"}]},{name:"x",links:[{portIn:"posX",portOut:"x",objIn:"zwtrb6wjh",objOut:"zey7hxe4f"}]},{name:"y",links:[{portIn:"posZ",portOut:"y",objIn:"zwtrb6wjh",objOut:"zey7hxe4f"}]},{name:"index",value:3},{name:"total iterations",value:4}],objName:"Ops.Trigger.Repeat2d"},{id:"xh4djkj9c",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"posX",value:0},{name:"posY",value:-.56},{name:"posZ",value:0},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"exe",portOut:"trigger",objIn:"zey7hxe4f",objOut:"xh4djkj9c"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"nvis4tyau",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Cast Light",value:1},{name:"Intensity",value:1},{name:"X",value:0},{name:"Y",value:3},{name:"Z",value:5},{name:"R",value:1},{name:"G",value:1},{name:"B",value:1},{name:"Specular R",value:.2},{name:"Specular G",value:.2},{name:"Specular B",value:.2},{name:"Cast Shadow",value:0},{name:"Rendering Active",value:1},{name:"Map Size index",value:1},{name:"Map Size",value:512},{name:"Shadow Strength",value:1},{name:"LR-BottomTop",value:8},{name:"Near",value:.1},{name:"Far",value:30},{name:"Bias",value:.004},{name:"Polygon Offset",value:0},{name:"Normal Offset",value:0},{name:"Blur Amount",value:0},{name:"Enable Advanced",value:0},{name:"MSAA index",value:0},{name:"MSAA",value:"none"},{name:"Texture Filter index",value:0},{name:"Texture Filter",value:"Linear"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"}],portsOut:[{name:"Trigger Out",links:[{portIn:"Trigger In",portOut:"Trigger Out",objIn:"cp1ew1ve4",objOut:"nvis4tyau"}]}],objName:"Ops.Gl.Phong.DirectionalLight_v5"},{id:"cp1ew1ve4",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"R",value:1},{name:"G",value:1},{name:"B",value:1},{name:"A",value:.722},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.585570631672061},{name:"Emissive G",value:.9884725420169509},{name:"Emissive B",value:.1014322159239136},{name:"Shininess",value:4},{name:"Specular Amount",value:.5},{name:"Specular Model index",value:0},{name:"Specular Model",value:"Blinn"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:.336},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Trigger Out",links:[{portIn:"render",portOut:"Trigger Out",objIn:"xh4djkj9c",objOut:"cp1ew1ve4"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"gg7icqqi2",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Area index",value:3},{name:"Area",value:"Axis Y"},{name:"Size",value:.84},{name:"Amount",value:1},{name:"Falloff",value:.066},{name:"Invert",value:0},{name:"Blend  index",value:2},{name:"Blend ",value:"Opacity"},{name:"r",value:0},{name:"g",value:.7597765363128492},{name:"b",value:1},{name:"x",value:0},{name:"y",value:-1.84},{name:"z",value:0},{name:"Change Size",value:0},{name:"Size X",value:1},{name:"Size Y",value:1},{name:"Size Z",value:1},{name:"WorldSpace",value:1},{name:"Priority",value:1}],portsOut:[{name:"Next",links:[{portIn:"render",portOut:"Next",objIn:"zwtrb6wjh",objOut:"gg7icqqi2"}]}],objName:"Ops.Gl.ShaderEffects.ColorArea_v4"},{id:"as6uazbm7",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Draw",value:1,title:"Render mesh"},{name:"segments",value:40},{name:"stacks",value:1},{name:"length",value:1.24},{name:"outer radius",value:.06},{name:"inner radius",value:.02},{name:"UV mode index",value:0},{name:"UV mode",value:"simple"},{name:"Flip Mapping",value:0},{name:"Caps",value:1},{name:"Flat Normals",value:0}],objName:"Ops.Gl.Meshes.Cylinder_v2"},{id:"boy572c3o",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"posX",value:0},{name:"posY",value:-1.61},{name:"posZ",value:0},{name:"scale",value:1},{name:"rotX",value:90},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"h6z82fjbf",objOut:"boy572c3o"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"vo3npugsi",uiAttribs:{subPatch:"x8e2jwc2f"},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:"as6uazbm7",objOut:"vo3npugsi"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"v3ju5zq52",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Render Mesh",value:1},{name:"Width",value:.09},{name:"Length",value:4.07},{name:"Height",value:.11},{name:"Center",value:1},{name:"Mapping index",value:0},{name:"Mapping",value:"Side"},{name:"Bias",value:0},{name:"Flip X",value:1},{name:"Top",value:1},{name:"Bottom",value:1},{name:"Left",value:1},{name:"Right",value:1},{name:"Front",value:1},{name:"Back",value:1}],objName:"Ops.Gl.Meshes.Cube_v2"},{id:"tzmo3vkil",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Speed",value:68.76},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"rotY",portOut:"Time",objIn:"xh4djkj9c",objOut:"tzmo3vkil"}]}],objName:"Ops.Anim.Timer_v2"},{id:"h6z82fjbf",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Scale",value:1},{name:"Size",value:4.25},{name:"Strength",value:23.01},{name:"Calc Normals",value:1},{name:"Flip Normals",value:0},{name:"Falloff",value:1},{name:"Output index",value:5},{name:"Output",value:"Add XYZ"},{name:"Source index",value:0},{name:"Source",value:"Pos"},{name:"x",value:0},{name:"y",value:0},{name:"z",value:0},{name:"Scroll X",value:0},{name:"Scroll Y",value:0},{name:"Scroll Z",value:0},{name:"WorldSpace",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"vo3npugsi",objOut:"h6z82fjbf"}]}],objName:"Ops.Gl.ShaderEffects.PerlinAreaDeform_v4"},{id:"05i2ktlxm",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Draw",value:1,title:"Render mesh"},{name:"segments",value:40},{name:"stacks",value:1},{name:"length",value:17.35},{name:"outer radius",value:18.09},{name:"inner radius",value:0},{name:"UV mode index",value:0},{name:"UV mode",value:"simple"},{name:"Flip Mapping",value:0},{name:"Caps",value:0},{name:"Flat Normals",value:0}],objName:"Ops.Gl.Meshes.Cylinder_v2"},{id:"sd8bpafwm",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:0},{name:"scale",value:1},{name:"rotX",value:90},{name:"rotY",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"05i2ktlxm",objOut:"sd8bpafwm"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"hyo5lm2yx",uiAttribs:{subPatch:"x8e2jwc2f"},portsOut:[{name:"trigger 0",links:[{portIn:"Render",portOut:"trigger 0",objIn:"h7rv3mtuu",objOut:"hyo5lm2yx"}]},{name:"trigger 8",links:[{portIn:"In Trigger",portOut:"trigger 8",objIn:"wp0j7kaaj",objOut:"hyo5lm2yx"}]}],objName:"Ops.Trigger.Sequence"},{id:"h7rv3mtuu",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Size index",value:1},{name:"Size",value:"Manual"},{name:"Width",value:1080},{name:"Height",value:1080},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"5k8ii5wra",objOut:"h7rv3mtuu"}]},{name:"texture_out",links:[{portIn:"Diffuse Texture",portOut:"texture_out",objIn:"5xw4apfyv",objOut:"h7rv3mtuu"},{portIn:"Environment Map",portOut:"texture_out",objIn:"hjqfbd1k5",objOut:"h7rv3mtuu"}]},{name:"Aspect Ratio",value:1},{name:"Texture Width",value:1080},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"euj40uj5u",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Num",value:7.19},{name:"Rotate",value:.042},{name:"Gradients",value:0},{name:"Circular",value:0},{name:"Invert",value:1},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"65h96ugvw",objOut:"euj40uj5u"}]}],objName:"Ops.Gl.ImageCompose.Stripes_v4"},{id:"5xw4apfyv",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Diffuse R",value:1},{name:"Diffuse G",value:1},{name:"Diffuse B",value:1},{name:"Diffuse A",value:1},{name:"Double Sided",value:1},{name:"Colorize Texture",value:0}],portsOut:[{name:"next",links:[{portIn:"render",portOut:"next",objIn:"sd8bpafwm",objOut:"5xw4apfyv"}]}],objName:"Ops.Gl.Phong.LambertMaterial_v2"},{id:"wp0j7kaaj",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Milliseconds",value:200}],portsOut:[{name:"Out Trigger",links:[{portIn:"Generate",portOut:"Out Trigger",objIn:"4rr7frxvg",objOut:"wp0j7kaaj"},{portIn:"Generate",portOut:"Out Trigger",objIn:"041692fg3",objOut:"wp0j7kaaj"}]},{name:"Progress",value:.004000000953674317}],objName:"Ops.Trigger.TriggerLimiter"},{id:"4rr7frxvg",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"min",value:0},{name:"max",value:20},{name:"Integer",value:0},{name:"No consecutive duplicates",value:0}],portsOut:[{name:"result",links:[{portIn:"Offset",portOut:"result",objIn:"euj40uj5u",objOut:"4rr7frxvg"}]}],objName:"Ops.Math.TriggerRandomNumber_v2"},{id:"041692fg3",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"min",value:.06},{name:"max",value:.51},{name:"Integer",value:0},{name:"No consecutive duplicates",value:0}],portsOut:[{name:"result",links:[{portIn:"Width",portOut:"result",objIn:"euj40uj5u",objOut:"041692fg3"},{portIn:"Slide X",portOut:"result",objIn:"65h96ugvw",objOut:"041692fg3"}]}],objName:"Ops.Math.TriggerRandomNumber_v2"},{id:"7tgr8s0fe",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Cast Light",value:1},{name:"Intensity",value:2},{name:"Radius",value:67.21},{name:"X",value:0},{name:"Y",value:0},{name:"Z",value:0},{name:"R",value:1},{name:"G",value:1},{name:"B",value:1},{name:"Specular R",value:1},{name:"Specular G",value:1},{name:"Specular B",value:1},{name:"Falloff",value:.602},{name:"Cast Shadow",value:0},{name:"Rendering Active",value:1},{name:"Map Size index",value:1},{name:"Map Size",value:512},{name:"Shadow Strength",value:1},{name:"Near",value:.1},{name:"Far",value:30},{name:"Bias",value:.004},{name:"Polygon Offset",value:0}],portsOut:[{name:"Trigger Out",links:[{portIn:"Execute",portOut:"Trigger Out",objIn:"5xw4apfyv",objOut:"7tgr8s0fe"}]},{name:"World Position X",value:0},{name:"World Position Y",value:0},{name:"World Position Z",value:0}],objName:"Ops.Gl.Phong.PointLight_v5"},{id:"5k8ii5wra",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Mask Invert",value:0},{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"A",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"euj40uj5u",objOut:"5k8ii5wra"}]}],objName:"Ops.Gl.ImageCompose.Color_v2"},{id:"6v9l27yhu",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Speed",value:-33.72},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"rotZ",portOut:"Time",objIn:"sd8bpafwm",objOut:"6v9l27yhu"}]}],objName:"Ops.Anim.Timer_v2"},{id:"65h96ugvw",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Sides",value:10},{name:"Angle",value:0},{name:"Slide Y",value:0},{name:"Center X",value:.5},{name:"Center Y",value:.5},{name:"Aspect Ratio",value:1}],portsOut:[{name:"Next",links:[{portIn:"Render",portOut:"Next",objIn:"5hayxcd7h",objOut:"65h96ugvw"}]}],objName:"Ops.Gl.ImageCompose.Kaleidoscope_v2"},{id:"29d5jjt9v",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"use viewport size",value:1},{name:"texture width",value:1920},{name:"texture height",value:1080},{name:"Auto Aspect",value:0},{name:"filter index",value:1},{name:"filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"Repeat"},{name:"MSAA index",value:0},{name:"MSAA",value:"none"},{name:"HDR",value:0,title:"Pixelformat Float 32bit"},{name:"Depth",value:1},{name:"Clear",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"qvh1qb3rg",objOut:"29d5jjt9v"}]},{name:"texture",links:[{portIn:"Texture In",portOut:"texture",objIn:"wzmxkds09",objOut:"29d5jjt9v"},{portIn:"Image",portOut:"texture",objIn:"3lro8bw1c",objOut:"29d5jjt9v"}]},{name:"textureDepth",links:[{portIn:"Depth Texture",portOut:"textureDepth",objIn:"nfsdyoskq",objOut:"29d5jjt9v"}]}],objName:"Ops.Gl.RenderToTexture"},{id:"wzmxkds09",uiAttribs:{subPatch:"x8e2jwc2f"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"r70f3gbon",uiAttribs:{subPatch:"x8e2jwc2f"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"29d5jjt9v",objOut:"r70f3gbon"}]},{name:"trigger 14",links:[{portIn:"Render",portOut:"trigger 14",objIn:"dq4abqhlg",objOut:"r70f3gbon"}]}],objName:"Ops.Trigger.Sequence"},{id:"dq4abqhlg",uiAttribs:{subPatch:"x8e2jwc2f"},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:1},{name:"Wrap",value:"repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"3lro8bw1c",objOut:"dq4abqhlg"}]},{name:"texture_out",links:[{portIn:"Texture 1",portOut:"texture_out",objIn:"0lpiv0jlt",objOut:"dq4abqhlg"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"3lro8bw1c",uiAttribs:{subPatch:"x8e2jwc2f"},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:0},{name:"Mask Src",value:"alpha channel"},{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:"nfsdyoskq",objOut:"3lro8bw1c"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"nfsdyoskq",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"blendMode index",value:0},{name:"blendMode",value:"normal"},{name:"Amount",value:1},{name:"Fog Start",value:1},{name:"Fog End",value:43.92},{name:"Fog Density",value:1},{name:"Ignore Infinity",value:0},{name:"nearplane",value:.1},{name:"farplane",value:20},{name:"Fog R",value:0},{name:"Fog G",value:0},{name:"Fog B",value:0},{name:"Fog A",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"jq5762vds",objOut:"nfsdyoskq"}]}],objName:"Ops.Gl.ImageCompose.Fog_v4"},{id:"5hayxcd7h",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Radius",value:.64},{name:"Center X",value:0},{name:"Center Y",value:0}],portsOut:[{name:"Next",links:[{portIn:"render",portOut:"Next",objIn:"ihnw389kd",objOut:"5hayxcd7h"}]}],objName:"Ops.Gl.ImageCompose.Twirl_v4"},{id:"z6loq2qbp",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Speed",value:1},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"value",portOut:"Time",objIn:"et2rjzpl6",objOut:"z6loq2qbp"}]}],objName:"Ops.Anim.Timer_v2"},{id:"et2rjzpl6",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"phase",value:0},{name:"frequency",value:1},{name:"amplitude",value:50},{name:"asine",value:0}],portsOut:[{name:"result",links:[{portIn:"Twist amount",portOut:"result",objIn:"5hayxcd7h",objOut:"et2rjzpl6"}]}],objName:"Ops.Math.Sine"},{id:"ixdqm15qr",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"amount X",value:.036},{name:"amount Y",value:.022},{name:"Wrap index",value:2},{name:"Wrap",value:"Repeat"},{name:"Input index",value:1},{name:"Input",value:"RedGreen"},{name:"Zero Displace index",value:1},{name:"Zero Displace",value:"Black"},{name:"Pixel Mapping index",value:0},{name:"Pixel Mapping",value:"Stretch"}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"5bsbwzc3e",objOut:"ixdqm15qr"}]}],objName:"Ops.Gl.ImageCompose.PixelDisplacement_v4"},{id:"3lgnty56z",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Size index",value:1},{name:"Size",value:"Manual"},{name:"Width",value:100},{name:"Height",value:100},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"2n3tqaglf",objOut:"3lgnty56z"},{portIn:"In Trigger",portOut:"Next",objIn:"1b38zoxb9",objOut:"3lgnty56z"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"95ucsrzre",objOut:"3lgnty56z"},{portIn:"displaceTex",portOut:"texture_out",objIn:"ixdqm15qr",objOut:"3lgnty56z"},{portIn:"Image",portOut:"texture_out",objIn:"5bsbwzc3e",objOut:"3lgnty56z"}]},{name:"Aspect Ratio",value:1},{name:"Texture Width",value:100},{name:"Texture Height",value:100}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"2n3tqaglf",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"frequency",value:1},{name:"strength",value:8},{name:"Block size small x",value:16.42},{name:"Block size small y",value:17.96},{name:"Block size large x",value:17.96},{name:"Block size large y",value:4},{name:"Scroll X",value:0},{name:"Scroll Y",value:0}],objName:"Ops.Gl.ImageCompose.Noise.GlitchNoise_v2"},{id:"95ucsrzre",uiAttribs:{subPatch:"x8e2jwc2f"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"if62xpazk",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Speed",value:1},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"value",portOut:"Time",objIn:"5zhizpvyl",objOut:"if62xpazk"}]}],objName:"Ops.Anim.Timer_v2"},{id:"1b38zoxb9",uiAttribs:{subPatch:"x8e2jwc2f"},portsOut:[{name:"Out Trigger",links:[{portIn:"Generate",portOut:"Out Trigger",objIn:"qo2q0fmsj",objOut:"1b38zoxb9"}]},{name:"Progress",value:.018630646304524552}],objName:"Ops.Trigger.TriggerLimiter"},{id:"qo2q0fmsj",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"min",value:0},{name:"max",value:1},{name:"Integer",value:0},{name:"No consecutive duplicates",value:0}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"gyrojd4g6",objOut:"qo2q0fmsj"}]}],objName:"Ops.Math.TriggerRandomNumber_v2"},{id:"gyrojd4g6",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"number2",value:.22}],portsOut:[{name:"result",links:[{portIn:"Amount",portOut:"result",objIn:"2n3tqaglf",objOut:"gyrojd4g6"}]}],objName:"Ops.Math.Compare.LessThan"},{id:"5bsbwzc3e",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"blendMode index",value:11},{name:"blendMode",value:"overlay"},{name:"amount",value:1},{name:"Premultiplied",value:0},{name:"Alpha Mask",value:0},{name:"removeAlphaSrc",value:0},{name:"Mask Src index",value:0},{name:"Mask Src",value:"alpha channel"},{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}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"5f3iocx5z",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Pixel",value:37.42},{name:"Lens Distort",value:1},{name:"Smooth",value:1}],objName:"Ops.Gl.ImageCompose.ChromaticAberration_v2"},{id:"qvh1qb3rg",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Axis index",value:0},{name:"Axis",value:"Vertical"},{name:"fov y",title:"FOV Degrees"},{name:"frustum near",value:.1},{name:"frustum far",value:21.28},{name:"Auto Aspect Ratio",value:1},{name:"Aspect Ratio",value:0}],portsOut:[{name:"trigger",links:[{portIn:"exe",portOut:"trigger",objIn:"obwrrf3ce",objOut:"qvh1qb3rg"}]},{name:"Aspect",value:1.7777777777777777}],objName:"Ops.Gl.Perspective"},{id:"uq5gaxwcm",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Blend Mode index",value:17},{name:"Blend Mode",value:"subtract one"},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Amount",value:.258},{name:"Threshold",value:0},{name:"Animated",value:1},{name:"RGB",value:0},{name:"Normalize",value:0}],objName:"Ops.Gl.ImageCompose.Noise.Noise_v2"},{id:"f0w8ufxxq",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Speed",value:1},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"value",portOut:"Time",objIn:"yvrx252tu",objOut:"f0w8ufxxq"}]}],objName:"Ops.Anim.Timer_v2"},{id:"yvrx252tu",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"phase",value:0},{name:"frequency",value:1},{name:"amplitude",value:2},{name:"asine",value:0}],portsOut:[{name:"result",links:[{portIn:"amount",portOut:"result",objIn:"jq5762vds",objOut:"yvrx252tu"}]}],objName:"Ops.Math.Sine"},{id:"tqlvdzslp",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"amount",value:.273}],portsOut:[{name:"Trigger",links:[{portIn:"Render",portOut:"Trigger",objIn:"uq5gaxwcm",objOut:"tqlvdzslp"}]}],objName:"Ops.Gl.ImageCompose.Clarity"},{id:"jq5762vds",uiAttribs:{subPatch:"x8e2jwc2f"},portsOut:[{name:"Trigger",links:[{portIn:"Render",portOut:"Trigger",objIn:"tqlvdzslp",objOut:"jq5762vds"}]}],objName:"Ops.Gl.ImageCompose.Vibrance"},{id:"zn5erzi53",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Amount",value:1}],objName:"Ops.Gl.ImageCompose.LUTMap"},{id:"cfx7m53if",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"File",value:"assets/lib_lut_lut5.jpg",display:"file"},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Data Format index",value:3},{name:"Data Format",value:"RGBA"},{name:"Flip",value:1},{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:"LUT Image",portOut:"Texture",objIn:"zn5erzi53",objOut:"cfx7m53if"}]},{name:"Width",value:512},{name:"Height",value:512},{name:"Aspect Ratio",value:1},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"ihnw389kd",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"blendMode index",value:4},{name:"blendMode",value:"multiply invert"},{name:"amount",value:.259},{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}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"qgwonjxvk",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Variable",value:"stationTex"}],portsOut:[{name:"Value",links:[{portIn:"Image",portOut:"Value",objIn:"ihnw389kd",objOut:"qgwonjxvk"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"omd1aijnq",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"value",value:113}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"lov5mgq3w",objOut:"omd1aijnq"}]}],objName:"Ops.Number.Number"},{id:"lov5mgq3w",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"number2",value:.38}],portsOut:[{name:"result",links:[{portIn:"Milliseconds",portOut:"result",objIn:"1b38zoxb9",objOut:"lov5mgq3w"}]}],objName:"Ops.Math.Multiply"},{id:"gu9e5gs95",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"trigger 0",links:[{portIn:"Render",portOut:"trigger 0",objIn:"pyvvt77zi",objOut:"gu9e5gs95"}]},{name:"trigger 1",links:[{portIn:"Render",portOut:"trigger 1",objIn:"t7xf1f93l",objOut:"gu9e5gs95"}]},{name:"trigger 15",links:[{portIn:"render",portOut:"trigger 15",objIn:"l2s0hlaom",objOut:"gu9e5gs95"}]}],objName:"Ops.Trigger.Sequence"},{id:"pyvvt77zi",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Size index",value:1},{name:"Size",value:"Manual"},{name:"Width",value:50},{name:"Height",value:50},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"zmt0iffay",objOut:"pyvvt77zi"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"aynidlfdl",objOut:"pyvvt77zi"},{portIn:"texture",portOut:"texture_out",objIn:"8tv3rebhz",objOut:"pyvvt77zi"},{portIn:"Base Texture",portOut:"texture_out",objIn:"t7xf1f93l",objOut:"pyvvt77zi"},{portIn:"texture",portOut:"texture_out",objIn:"fe2gevotr",objOut:"pyvvt77zi"}]},{name:"Aspect Ratio",value:1},{name:"Texture Width",links:[{portIn:"number1",portOut:"Texture Width",objIn:"sb9kg38yw",objOut:"pyvvt77zi"}]},{name:"Texture Height",links:[{portIn:"number2",portOut:"Texture Height",objIn:"sb9kg38yw",objOut:"pyvvt77zi"}]}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"aynidlfdl",uiAttribs:{subPatch:"kb5v7uxi5"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"dza7kxe77",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"contrast",value:.636},{name:"brightness",value:.36}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"5pszpnhda",objOut:"dza7kxe77"}]}],objName:"Ops.Gl.ImageCompose.BrightnessContrast"},{id:"bylqisyfe",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Scale",value:1},{name:"Limit Instances",value:0},{name:"Limit",value:100},{name:"Rotations",value:0},{name:"Rotation Type index",value:0},{name:"Rotation Type",value:"Euler"},{name:"Billboarding index",value:0},{name:"Billboarding",value:"Off"},{name:"Material blend mode index",value:1},{name:"Material blend mode",value:"Add"},{name:"TexCoords",value:0}],portsOut:[{name:"Num",value:2500}],objName:"Ops.Gl.MeshInstancer_v4"},{id:"klb84hlxn",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Render Mesh",value:0},{name:"Center",value:1},{name:"Mapping index",value:0},{name:"Mapping",value:"Side"},{name:"Bias",value:0},{name:"Flip X",value:1},{name:"Top",value:1},{name:"Bottom",value:1},{name:"Left",value:1},{name:"Right",value:1},{name:"Front",value:1},{name:"Back",value:1}],portsOut:[{name:"Next",links:[{portIn:"Render",portOut:"Next",objIn:"t3agdvi7f",objOut:"klb84hlxn"}]},{name:"geometry",links:[{portIn:"geom",portOut:"geometry",objIn:"bylqisyfe",objOut:"klb84hlxn"}]}],objName:"Ops.Gl.Meshes.Cube_v2"},{id:"wvfmw980s",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"value",value:.02}],portsOut:[{name:"result",links:[{portIn:"Width",portOut:"result",objIn:"klb84hlxn",objOut:"wvfmw980s"},{portIn:"Length",portOut:"result",objIn:"klb84hlxn",objOut:"wvfmw980s"},{portIn:"Height",portOut:"result",objIn:"klb84hlxn",objOut:"wvfmw980s"}]}],objName:"Ops.Number.Number"},{id:"fzgzlaick",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"R",value:1},{name:"G",value:1},{name:"B",value:1},{name:"A",value:1},{name:"Enable",value:1},{name:"Albedo",value:.425},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:0},{name:"Emissive G",value:0},{name:"Emissive B",value:0},{name:"Shininess",value:18.36},{name:"Specular Amount",value:0},{name:"Specular Model index",value:3},{name:"Specular Model",value:"Gauss"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:3},{name:"Falloff Mode",value:"D"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:1},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Trigger Out",links:[{portIn:"Render",portOut:"Trigger Out",objIn:"klb84hlxn",objOut:"fzgzlaick"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"8tv3rebhz",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Seed",value:1},{name:"Z Position index",value:0},{name:"Z Position",value:"None"},{name:"Z Multiply",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Trigger in",portOut:"trigger",objIn:"0n27ss2ek",objOut:"8tv3rebhz"}]},{name:"Points",links:[{portIn:"In",portOut:"Points",objIn:"5qbjqdnwf",objOut:"8tv3rebhz"}]},{name:"NumPoints",value:2500}],objName:"Ops.Gl.TextureToRandomPoints"},{id:"5pszpnhda",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Mask Invert",value:0},{name:"Invert R",value:1},{name:"Invert G",value:1},{name:"Invert B",value:1}],portsOut:[{name:"trigger",links:[{portIn:"update",portOut:"trigger",objIn:"fe2gevotr",objOut:"5pszpnhda"},{portIn:"update",portOut:"trigger",objIn:"8tv3rebhz",objOut:"5pszpnhda"}]}],objName:"Ops.Gl.ImageCompose.Invert_v2"},{id:"g5gnf2yfy",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"Array 1 out",links:[{portIn:"Array 1",portOut:"Array 1 out",objIn:"0n27ss2ek",objOut:"g5gnf2yfy"}]},{name:"Array 2 out",links:[{portIn:"Array 2",portOut:"Array 2 out",objIn:"0n27ss2ek",objOut:"g5gnf2yfy"}]},{name:"Array lengths",links:[{portIn:"Array length",portOut:"Array lengths",objIn:"0nc6se93i",objOut:"g5gnf2yfy"}]}],objName:"Ops.Array.ArrayUnpack3"},{id:"0nc6se93i",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Mode select index",value:0},{name:"Mode select",value:"Number"},{name:"Default Value",value:.22},{name:"Reverse",value:0}],portsOut:[{name:"Array length out",value:2500}],objName:"Ops.Array.Array_v3"},{id:"0n27ss2ek",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"Array out",links:[{portIn:"positions",portOut:"Array out",objIn:"bylqisyfe",objOut:"0n27ss2ek"}]},{name:"Num Points",value:2500},{name:"Array length",value:7500}],objName:"Ops.Array.ArrayPack3"},{id:"zmt0iffay",uiAttribs:{subPatch:"kb5v7uxi5"},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:1},{name:"Color index",value:0},{name:"Color",value:"Mono"},{name:"Scale",value:4.73},{name:"Multiply",value:4.13},{name:"Value index",value:0},{name:"Value",value:"0-1"},{name:"Harmonics index",value:0},{name:"Harmonics",value:"1"},{name:"X",value:0},{name:"Y",value:0},{name:"Z",value:0},{name:"Offset Multiply",value:1},{name:"Offset X index",value:0},{name:"Offset X",value:"None"},{name:"Offset Y index",value:0},{name:"Offset Y",value:"None"},{name:"Offset Z index",value:1},{name:"Offset Z",value:"R"}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"dza7kxe77",objOut:"zmt0iffay"}]}],objName:"Ops.Gl.ImageCompose.Noise.PerlinNoise_v2"},{id:"fe2gevotr",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Normalize index",value:1},{name:"Normalize",value:"0-1"}],portsOut:[{name:"trigger",links:[{portIn:"Trigger in",portOut:"trigger",objIn:"q44p70ird",objOut:"fe2gevotr"}]},{name:"Colors",links:[{portIn:"Array in xyzw",portOut:"Colors",objIn:"6xm8lktiy",objOut:"fe2gevotr"}]},{name:"Floating Point",value:0}],objName:"Ops.Gl.TextureToArray"},{id:"6xm8lktiy",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"Array 2 out",links:[{portIn:"In",portOut:"Array 2 out",objIn:"fzghcvrfb",objOut:"6xm8lktiy"}]},{name:"Array 3 out",links:[{portIn:"In",portOut:"Array 3 out",objIn:"oohurrxff",objOut:"6xm8lktiy"}]},{name:"Array lengths",links:[{portIn:"Array length",portOut:"Array lengths",objIn:"oqk3brk0j",objOut:"6xm8lktiy"}]}],objName:"Ops.Array.ArrayUnpack4"},{id:"q44p70ird",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"Array out",links:[{portIn:"Scale Array",portOut:"Array out",objIn:"bylqisyfe",objOut:"q44p70ird"}]},{name:"Num Points",value:2500},{name:"Array length",value:7500}],objName:"Ops.Array.ArrayPack3"},{id:"fzghcvrfb",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Value",value:3.8}],portsOut:[{name:"Result",links:[{portIn:"Array 2",portOut:"Result",objIn:"q44p70ird",objOut:"fzghcvrfb"},{portIn:"Array 1",portOut:"Result",objIn:"q44p70ird",objOut:"fzghcvrfb"}]}],objName:"Ops.Array.ArrayMultiply"},{id:"t7xf1f93l",uiAttribs:{subPatch:"kb5v7uxi5"},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:1},{name:"Wrap",value:"repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"61tcab031",objOut:"t7xf1f93l"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"6jmriqqe2",objOut:"t7xf1f93l"},{portIn:"texture",portOut:"texture_out",objIn:"h6w6t7bf8",objOut:"t7xf1f93l"}]},{name:"Aspect Ratio",value:1},{name:"Texture Width",value:50},{name:"Texture Height",value:50}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"cou8cqwkw",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"scale",value:1},{name:"rotY",value:3.82}],portsOut:[{name:"trigger",links:[{portIn:"Trigger In",portOut:"trigger",objIn:"fzgzlaick",objOut:"cou8cqwkw"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"5qbjqdnwf",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Value",value:2.65}],portsOut:[{name:"Result",links:[{portIn:"Array in xyz",portOut:"Result",objIn:"g5gnf2yfy",objOut:"5qbjqdnwf"}]}],objName:"Ops.Array.ArrayMultiply"},{id:"oqk3brk0j",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Mode select index",value:0},{name:"Mode select",value:"Number"},{name:"Default Value",value:20},{name:"Reverse",value:0}],portsOut:[{name:"Array",links:[{portIn:"Array 3",portOut:"Array",objIn:"q44p70ird",objOut:"oqk3brk0j"}]},{name:"Array length out",value:2500}],objName:"Ops.Array.Array_v3"},{id:"oohurrxff",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Value",value:.16}],portsOut:[{name:"Result",links:[{portIn:"Array 3",portOut:"Result",objIn:"0n27ss2ek",objOut:"oohurrxff"}]}],objName:"Ops.Array.ArrayMultiply"},{id:"sb9kg38yw",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"result",links:[{portIn:"Num Points",portOut:"result",objIn:"8tv3rebhz",objOut:"sb9kg38yw"}]}],objName:"Ops.Math.Multiply"},{id:"t3agdvi7f",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Strength",value:.025},{name:"Scroll X",value:18.02},{name:"Scale",value:2.74},{name:"Method index",value:0},{name:"Method",value:"Translate"},{name:"Mul X",value:1},{name:"Mul Y",value:1},{name:"Mul Z",value:1},{name:"Min Scale",value:15.98},{name:"WorldSpace",value:1}],portsOut:[{name:"Next",links:[{portIn:"exe",portOut:"Next",objIn:"bylqisyfe",objOut:"t3agdvi7f"}]}],objName:"Ops.Gl.ShaderEffects.InstancedPerlinPosition_v2"},{id:"kof622ydy",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Speed",value:1},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"Scroll Z",portOut:"Time",objIn:"t3agdvi7f",objOut:"kof622ydy"},{portIn:"Scroll Y",portOut:"Time",objIn:"t3agdvi7f",objOut:"kof622ydy"}]}],objName:"Ops.Anim.Timer_v2"},{id:"6jmriqqe2",uiAttribs:{subPatch:"kb5v7uxi5"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"h6w6t7bf8",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Normalize index",value:1},{name:"Normalize",value:"0-1"}],portsOut:[{name:"Colors",links:[{portIn:"Array in xyzw",portOut:"Colors",objIn:"7pfks0vqw",objOut:"h6w6t7bf8"}]},{name:"Floating Point",value:0}],objName:"Ops.Gl.TextureToArray"},{id:"61tcab031",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Method index",value:0},{name:"Method",value:"Luminance"},{name:"Min",value:0},{name:"Max",value:1},{name:"Position",value:.5}],portsOut:[{name:"trigger",links:[{portIn:"update",portOut:"trigger",objIn:"h6w6t7bf8",objOut:"61tcab031"}]}],objName:"Ops.Gl.ImageCompose.ColorMap_v2"},{id:"442vwugtd",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Gradient",value:'{"keys":[{"pos":0,"posy":null,"r":1,"g":1,"b":1},{"pos":0.226,"posy":null,"r":1,"g":1,"b":1},{"pos":0.352,"posy":null,"r":1,"g":0.4656250000000002,"b":0},{"pos":0.58,"posy":null,"r":0.3764705882352941,"g":0,"b":0.1277647058823531},{"pos":0.826,"posy":null,"r":0.15760416666666666,"g":0.15760416666666666,"b":0.15760416666666666},{"pos":0.976,"posy":null,"r":0,"g":0,"b":0},{"pos":1,"posy":null,"r":0,"g":0,"b":0}]}'},{name:"Direction index",value:0},{name:"Direction",value:"X"},{name:"Smoothstep",value:0},{name:"Step",value:0},{name:"Flip",value:0},{name:"sRGB",value:0},{name:"Oklab",value:0},{name:"Size",value:256},{name:"filter index",value:1},{name:"filter",value:"linear"},{name:"wrap index",value:0},{name:"wrap",value:"clamp to edge"},{name:"Dither",value:0},{name:"Gradient Array",value:0}],portsOut:[{name:"Texture",links:[{portIn:"Gradient",portOut:"Texture",objIn:"61tcab031",objOut:"442vwugtd"}]}],objName:"Ops.Gl.GradientTexture"},{id:"3czwowev8",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Speed",value:20},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"rotZ",portOut:"Time",objIn:"cou8cqwkw",objOut:"3czwowev8"}]}],objName:"Ops.Anim.Timer_v2"},{id:"7pfks0vqw",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"Array 1 out",links:[{portIn:"Array 1",portOut:"Array 1 out",objIn:"g2ferps42",objOut:"7pfks0vqw"}]},{name:"Array 2 out",links:[{portIn:"Array 2",portOut:"Array 2 out",objIn:"g2ferps42",objOut:"7pfks0vqw"}]},{name:"Array 3 out",links:[{portIn:"Array 3",portOut:"Array 3 out",objIn:"g2ferps42",objOut:"7pfks0vqw"}]},{name:"Array 4 out",links:[{portIn:"In",portOut:"Array 4 out",objIn:"5udvm0o1e",objOut:"7pfks0vqw"}]},{name:"Array lengths",value:2500}],objName:"Ops.Array.ArrayUnpack4"},{id:"g2ferps42",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"Array out",links:[{portIn:"Colors",portOut:"Array out",objIn:"bylqisyfe",objOut:"g2ferps42"}]},{name:"Num Points",value:2500},{name:"Array length",value:1e4}],objName:"Ops.Array.ArrayPack4Simple"},{id:"5udvm0o1e",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Value",value:-.28}],portsOut:[{name:"Result",links:[{portIn:"Array 4",portOut:"Result",objIn:"g2ferps42",objOut:"5udvm0o1e"}]}],objName:"Ops.Array.ArrayMultiply"},{id:"l2s0hlaom",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"use viewport size",value:1},{name:"texture width",value:1920},{name:"texture height",value:1080},{name:"Auto Aspect",value:0},{name:"filter index",value:1},{name:"filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"Repeat"},{name:"MSAA index",value:0},{name:"MSAA",value:"none"},{name:"HDR",value:0,title:"Pixelformat Float 32bit"},{name:"Depth",value:1},{name:"Clear",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Input_0",portOut:"trigger",objIn:"3yz67mvac",objOut:"l2s0hlaom"}]},{name:"texture",links:[{portIn:"Texture In",portOut:"texture",objIn:"d7txu3945",objOut:"l2s0hlaom"},{portIn:"Base Texture",portOut:"texture",objIn:"xs1f528cv",objOut:"l2s0hlaom"},{portIn:"Base Texture",portOut:"texture",objIn:"7t8nyuhds",objOut:"l2s0hlaom"}]},{name:"textureDepth",links:[{portIn:"Depth Texture",portOut:"textureDepth",objIn:"1peu3e8dk",objOut:"l2s0hlaom"},{portIn:"Depth Texture",portOut:"textureDepth",objIn:"85sxbat6m",objOut:"l2s0hlaom"}]}],objName:"Ops.Gl.RenderToTexture"},{id:"pq0hdz9r8",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"trigger 0",links:[{portIn:"exe",portOut:"trigger 0",objIn:"gu9e5gs95",objOut:"pq0hdz9r8"}]},{name:"trigger 10",links:[{portIn:"Render",portOut:"trigger 10",objIn:"7t8nyuhds",objOut:"pq0hdz9r8"}]},{name:"trigger 12",links:[{portIn:"Render",portOut:"trigger 12",objIn:"gl2fghv12",objOut:"pq0hdz9r8"}]},{name:"trigger 14",links:[{portIn:"Render",portOut:"trigger 14",objIn:"xs1f528cv",objOut:"pq0hdz9r8"}]}],objName:"Ops.Trigger.Sequence"},{id:"d7txu3945",uiAttribs:{subPatch:"kb5v7uxi5"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"xs1f528cv",uiAttribs:{subPatch:"kb5v7uxi5"},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:2},{name:"Wrap",value:"mirrored repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"fbcpmaqw8",objOut:"xs1f528cv"}]},{name:"texture_out",links:[{portIn:"Texture 1",portOut:"texture_out",objIn:"cbj6ahuk5",objOut:"xs1f528cv"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"1peu3e8dk",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"blendMode index",value:0},{name:"blendMode",value:"normal"},{name:"Amount",value:1},{name:"Fog Start",value:1},{name:"Fog End",value:1.99},{name:"Fog Density",value:1},{name:"Ignore Infinity",value:0},{name:"nearplane",value:.11},{name:"farplane",value:17.66},{name:"Fog R",value:0},{name:"Fog G",value:0},{name:"Fog B",value:0},{name:"Fog A",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"yx96ibfwx",objOut:"1peu3e8dk"}]}],objName:"Ops.Gl.ImageCompose.Fog_v4"},{id:"gl2fghv12",uiAttribs:{subPatch:"kb5v7uxi5"},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:1},{name:"Wrap",value:"repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"85sxbat6m",objOut:"gl2fghv12"}]},{name:"texture_out",links:[{portIn:"mask",portOut:"texture_out",objIn:"yx96ibfwx",objOut:"gl2fghv12"},{portIn:"Texture In",portOut:"texture_out",objIn:"4dyq2o7x2",objOut:"gl2fghv12"},{portIn:"Mask",portOut:"texture_out",objIn:"g46qzrt68",objOut:"gl2fghv12"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"85sxbat6m",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Focus",value:.95},{name:"Width",value:.64},{name:"Invert",value:1},{name:"nearplane",value:.1},{name:"farplane",value:100}],objName:"Ops.Gl.ImageCompose.DepthTextureFocus_v2"},{id:"yx96ibfwx",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"amount",value:.71},{name:"direction index",value:0},{name:"direction",value:"both"},{name:"Fast",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"g46qzrt68",objOut:"yx96ibfwx"}]}],objName:"Ops.Gl.ImageCompose.Blur"},{id:"4dyq2o7x2",uiAttribs:{subPatch:"kb5v7uxi5"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"g46qzrt68",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Pixel",value:8.82},{name:"Lens Distort",value:0},{name:"Smooth",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"do54z9xed",objOut:"g46qzrt68"}]}],objName:"Ops.Gl.ImageCompose.ChromaticAberration_v2"},{id:"7t8nyuhds",uiAttribs:{subPatch:"kb5v7uxi5"},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:2},{name:"Wrap",value:"mirrored repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"nqm8szb4k",objOut:"7t8nyuhds"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"5b9hbjurc",objOut:"7t8nyuhds"},{portIn:"Image",portOut:"texture_out",objIn:"fbcpmaqw8",objOut:"7t8nyuhds"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"nqm8szb4k",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Invert",value:0},{name:"Black White",value:1},{name:"Threshold low ",value:.931},{name:"Threshold high",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"el0oc25yv",objOut:"nqm8szb4k"}]}],objName:"Ops.Gl.ImageCompose.LumaKey_v2"},{id:"5b9hbjurc",uiAttribs:{subPatch:"kb5v7uxi5"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"el0oc25yv",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Blend Mode index",value:1},{name:"Blend Mode",value:"lighten"},{name:"Amount",value:1},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Mask Invert",value:0},{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"A",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"t4e0kcjbq",objOut:"el0oc25yv"}]}],objName:"Ops.Gl.ImageCompose.Color_v2"},{id:"hw5f7hyiu",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:.968},{name:"Pixel",value:54.88},{name:"Lens Distort",value:.442},{name:"Smooth",value:1}],objName:"Ops.Gl.ImageCompose.ChromaticAberration_v2"},{id:"fbcpmaqw8",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"blendMode index",value:6},{name:"blendMode",value:"add"},{name:"amount",value:.772},{name:"Premultiplied",value:0},{name:"Alpha Mask",value:0},{name:"removeAlphaSrc",value:0},{name:"Mask Src index",value:0},{name:"Mask Src",value:"alpha channel"},{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:"1peu3e8dk",objOut:"fbcpmaqw8"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"1skxmhv28",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Strength",value:0},{name:"Samples",value:40},{name:"X",value:0},{name:"Y",value:-1.42},{name:"Source Strength Map index",value:0},{name:"Source Strength Map",value:"R"},{name:"Invert Strength Map",value:0}],objName:"Ops.Gl.ImageCompose.ZoomBlur_v2"},{id:"do54z9xed",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"amount",value:-.16}],objName:"Ops.Gl.ImageCompose.Vibrance"},{id:"hqnji774m",uiAttribs:{subPatch:"qjbpb8llo"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"vdftswxis",objOut:"hqnji774m"}]},{name:"trigger 1",links:[{portIn:"render",portOut:"trigger 1",objIn:"pv7nfohd2",objOut:"hqnji774m"}]},{name:"trigger 2",links:[{portIn:"render",portOut:"trigger 2",objIn:"2dvpst4ic",objOut:"hqnji774m"}]},{name:"trigger 15",links:[{portIn:"render",portOut:"trigger 15",objIn:"kkdmtu5n3",objOut:"hqnji774m"}]}],objName:"Ops.Trigger.Sequence"},{id:"9npfg2jcg",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"data",value:""},{name:"glb File",value:"assets/630cdec28cdf9c86c82cba59_avatar_blendshapes2.glb",display:"file"},{name:"Draw",value:0},{name:"Camera index",value:0},{name:"Camera",value:"None"},{name:"Animation",value:""},{name:"Center index",value:1},{name:"Center",value:"XYZ"},{name:"Rescale",value:0},{name:"Rescale Size",value:2.5},{name:"Sync to timeline",value:0},{name:"Loop",value:1},{name:"Normals Format index",value:0},{name:"Normals Format",value:"XYZ"},{name:"Vertices Format index",value:0},{name:"Vertices Format",value:"XYZ"},{name:"Calc Normals",value:0},{name:"Hide Nodes",value:0},{name:"Use Material Properties",value:0},{name:"Active",value:1}],portsOut:[{name:"Next",links:[{portIn:"render",portOut:"Next",objIn:"zxblxqeip",objOut:"9npfg2jcg"}]},{name:"Generator",value:"Khronos glTF Blender I/O v1.8.19"},{name:"GLTF Version",value:2},{name:"Anim Length",value:14.666666984558105},{name:"Anim Time",value:.058599999904626277},{name:"Loading",value:false}],objName:"Ops.Gl.GLTF.GltfScene_v3"},{id:"rg5oevn16",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Node Name",value:"mesh_m_low_baseFace_001"},{name:"Transformation",value:1},{name:"Draw Mesh",value:1},{name:"Draw Childs",value:1},{name:"Ignore Material",value:1},{name:"Use Scene Time",value:1},{name:"Time",value:0}],portsOut:[{name:"Found",value:true}],objName:"Ops.Gl.GLTF.GltfNode_v2"},{id:"vdftswxis",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"posX",value:-.03},{name:"posY",value:-.82},{name:"posZ",value:0},{name:"scale",value:1.06},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"9npfg2jcg",objOut:"vdftswxis"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"22k4766oo",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Speed",value:1},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"number1",portOut:"Time",objIn:"ov8yvxumz",objOut:"22k4766oo"},{portIn:"number1",portOut:"Time",objIn:"9ri7ssu9z",objOut:"22k4766oo"},{portIn:"number1",portOut:"Time",objIn:"xj6rkf66m",objOut:"22k4766oo"}]}],objName:"Ops.Anim.Timer_v2"},{id:"ov8yvxumz",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"number2",value:1.09},{name:"pingpong",value:1}],portsOut:[{name:"result",links:[{portIn:"Time",portOut:"result",objIn:"9npfg2jcg",objOut:"ov8yvxumz"}]}],objName:"Ops.Math.Modulo"},{id:"zxblxqeip",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"PointSize",value:2},{name:"Size in Pixels",value:0},{name:"Random Size",value:3},{name:"Round",value:1},{name:"Round Antialias",value:0},{name:"Scale by Distance",value:0},{name:"r",value:1},{name:"g",value:0},{name:"b",value:0},{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:"Random Atlas",value:0},{name:"Atlas Repeat X",value:4}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"rg5oevn16",objOut:"zxblxqeip"}]}],objName:"Ops.Gl.Shader.PointMaterial_v4"},{id:"sn26mtese",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"data",value:""},{name:"glb File",value:"assets/630cdec28cdf9c86c82cba59_avatar_blendshapes2.glb",display:"file"},{name:"Draw",value:0},{name:"Camera index",value:0},{name:"Camera",value:"None"},{name:"Animation",value:""},{name:"Center index",value:1},{name:"Center",value:"XYZ"},{name:"Rescale",value:0},{name:"Rescale Size",value:2.5},{name:"Sync to timeline",value:0},{name:"Loop",value:1},{name:"Normals Format index",value:0},{name:"Normals Format",value:"XYZ"},{name:"Vertices Format index",value:0},{name:"Vertices Format",value:"XYZ"},{name:"Calc Normals",value:0},{name:"Hide Nodes",value:0},{name:"Use Material Properties",value:0},{name:"Active",value:1}],portsOut:[{name:"Next",links:[{portIn:"render",portOut:"Next",objIn:"1bfuqyzeu",objOut:"sn26mtese"}]},{name:"Generator",value:"Khronos glTF Blender I/O v1.8.19"},{name:"GLTF Version",value:2},{name:"Anim Length",value:14.666666984558105},{name:"Anim Time",value:.5585999999046263},{name:"Loading",value:false}],objName:"Ops.Gl.GLTF.GltfScene_v3"},{id:"8buzq7014",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Node Name",value:"mesh_m_low_baseFace_001"},{name:"Transformation",value:1},{name:"Draw Mesh",value:1},{name:"Draw Childs",value:1},{name:"Ignore Material",value:1},{name:"Use Scene Time",value:1},{name:"Time",value:0}],portsOut:[{name:"Found",value:true}],objName:"Ops.Gl.GLTF.GltfNode_v2"},{id:"pv7nfohd2",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"posX",value:-.03},{name:"posY",value:-.82},{name:"posZ",value:0},{name:"scale",value:1.06},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"sn26mtese",objOut:"pv7nfohd2"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"qei3tiwvr",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"number2",value:1.09},{name:"pingpong",value:1}],portsOut:[{name:"result",links:[{portIn:"Time",portOut:"result",objIn:"sn26mtese",objOut:"qei3tiwvr"}]}],objName:"Ops.Math.Modulo"},{id:"1bfuqyzeu",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"PointSize",value:2},{name:"Size in Pixels",value:0},{name:"Random Size",value:3},{name:"Round",value:1},{name:"Round Antialias",value:0},{name:"Scale by Distance",value:0},{name:"r",value:0},{name:"g",value:1},{name:"b",value:.005624999999999769},{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:"Random Atlas",value:0},{name:"Atlas Repeat X",value:4}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"8buzq7014",objOut:"1bfuqyzeu"}]}],objName:"Ops.Gl.Shader.PointMaterial_v4"},{id:"9ri7ssu9z",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"number2",value:.5}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"qei3tiwvr",objOut:"9ri7ssu9z"}]}],objName:"Ops.Math.Sum"},{id:"izfhcifqc",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"data",value:""},{name:"glb File",value:"assets/630cdec28cdf9c86c82cba59_avatar_blendshapes2.glb",display:"file"},{name:"Draw",value:0},{name:"Camera index",value:0},{name:"Camera",value:"None"},{name:"Animation",value:""},{name:"Center index",value:1},{name:"Center",value:"XYZ"},{name:"Rescale",value:0},{name:"Rescale Size",value:2.5},{name:"Sync to timeline",value:0},{name:"Loop",value:1},{name:"Normals Format index",value:0},{name:"Normals Format",value:"XYZ"},{name:"Vertices Format index",value:0},{name:"Vertices Format",value:"XYZ"},{name:"Calc Normals",value:0},{name:"Hide Nodes",value:0},{name:"Use Material Properties",value:0},{name:"Active",value:1}],portsOut:[{name:"Next",links:[{portIn:"render",portOut:"Next",objIn:"i717w6te1",objOut:"izfhcifqc"}]},{name:"Generator",value:"Khronos glTF Blender I/O v1.8.19"},{name:"GLTF Version",value:2},{name:"Anim Length",value:14.666666984558105},{name:"Anim Time",value:1.0585999999046263},{name:"Loading",value:false}],objName:"Ops.Gl.GLTF.GltfScene_v3"},{id:"rtk07gpe7",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Node Name",value:"mesh_m_low_baseFace_001"},{name:"Transformation",value:1},{name:"Draw Mesh",value:1},{name:"Draw Childs",value:1},{name:"Ignore Material",value:1},{name:"Use Scene Time",value:1},{name:"Time",value:0}],portsOut:[{name:"Found",value:true}],objName:"Ops.Gl.GLTF.GltfNode_v2"},{id:"2dvpst4ic",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"posX",value:-.03},{name:"posY",value:-.82},{name:"posZ",value:0},{name:"scale",value:1.06},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"izfhcifqc",objOut:"2dvpst4ic"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"i830hd5ih",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"number2",value:1.09},{name:"pingpong",value:1}],portsOut:[{name:"result",links:[{portIn:"Time",portOut:"result",objIn:"izfhcifqc",objOut:"i830hd5ih"}]}],objName:"Ops.Math.Modulo"},{id:"i717w6te1",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"PointSize",value:2},{name:"Size in Pixels",value:0},{name:"Random Size",value:3},{name:"Round",value:1},{name:"Round Antialias",value:0},{name:"Scale by Distance",value:0},{name:"r",value:0},{name:"g",value:.07437499999999941},{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:"Random Atlas",value:0},{name:"Atlas Repeat X",value:4}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"rtk07gpe7",objOut:"i717w6te1"}]}],objName:"Ops.Gl.Shader.PointMaterial_v4"},{id:"xj6rkf66m",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"number2",value:1}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"i830hd5ih",objOut:"xj6rkf66m"}]}],objName:"Ops.Math.Sum"},{id:"enzyzwdyx",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"posX",value:-.01},{name:"posY",value:-.21},{name:"posZ",value:-.25},{name:"scale",value:4.02},{name:"rotX",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"exe",portOut:"trigger",objIn:"hqnji774m",objOut:"enzyzwdyx"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"8klsgwf60",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Axis index",value:0},{name:"Axis",value:"Vertical"},{name:"fov y",value:35.34,title:"FOV Degrees"},{name:"frustum near",value:.1},{name:"frustum far",value:20},{name:"Auto Aspect Ratio",value:1},{name:"Aspect Ratio",value:-1.88}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"enzyzwdyx",objOut:"8klsgwf60"},{portIn:"render",portOut:"trigger",objIn:"vptq08uts",objOut:"8klsgwf60"},{portIn:"render",portOut:"trigger",objIn:"yqtit3oh3",objOut:"8klsgwf60"}]},{name:"Aspect",value:1.7777777777777777}],objName:"Ops.Gl.Perspective"},{id:"yp1t5dbrz",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"use viewport size",value:1},{name:"texture width",value:1920},{name:"texture height",value:1080},{name:"Auto Aspect",value:0},{name:"filter index",value:1},{name:"filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"Repeat"},{name:"MSAA index",value:0},{name:"MSAA",value:"none"},{name:"HDR",value:0,title:"Pixelformat Float 32bit"},{name:"Depth",value:1},{name:"Clear",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"8klsgwf60",objOut:"yp1t5dbrz"}]},{name:"texture",links:[{portIn:"Image",portOut:"texture",objIn:"ubgo9dzce",objOut:"yp1t5dbrz"},{portIn:"Image",portOut:"texture",objIn:"uh7on3zii",objOut:"yp1t5dbrz"}]},{name:"textureDepth",links:[{portIn:"Depth Texture",portOut:"textureDepth",objIn:"ofms6eju0",objOut:"yp1t5dbrz"}]}],objName:"Ops.Gl.RenderToTexture"},{id:"ufuwl6u2m",uiAttribs:{subPatch:"qjbpb8llo"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"yp1t5dbrz",objOut:"ufuwl6u2m"}]},{name:"trigger 11",links:[{portIn:"Render",portOut:"trigger 11",objIn:"q07ned5dl",objOut:"ufuwl6u2m"}]},{name:"trigger 13",links:[{portIn:"Render",portOut:"trigger 13",objIn:"6pvg5jrkn",objOut:"ufuwl6u2m"}]},{name:"trigger 14",links:[{portIn:"Render",portOut:"trigger 14",objIn:"bcgj5l40d",objOut:"ufuwl6u2m"}]}],objName:"Ops.Trigger.Sequence"},{id:"bcgj5l40d",uiAttribs:{subPatch:"qjbpb8llo"},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:2},{name:"Wrap",value:"mirrored repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"vwqrlgdx9",objOut:"bcgj5l40d"}]},{name:"texture_out",links:[{portIn:"Texture 2",portOut:"texture_out",objIn:"35b1nvdq0",objOut:"bcgj5l40d"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"x4ytveckr",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"smooth",value:0}],objName:"Ops.Gl.Meshes.Icosahedron"},{id:"1trk9wp7u",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"posX",value:0},{name:"posY",value:.13},{name:"posZ",value:.01}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"x4ytveckr",objOut:"1trk9wp7u"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"ubgo9dzce",uiAttribs:{subPatch:"qjbpb8llo"},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:0},{name:"Mask Src",value:"alpha channel"},{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:"q55jv5ukl",objOut:"ubgo9dzce"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"q07ned5dl",uiAttribs:{subPatch:"qjbpb8llo"},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:1},{name:"Wrap",value:"repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"ofms6eju0",objOut:"q07ned5dl"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"te23cj85g",objOut:"q07ned5dl"},{portIn:"mask",portOut:"texture_out",objIn:"q55jv5ukl",objOut:"q07ned5dl"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"ofms6eju0",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Focus",value:1.76},{name:"Width",value:1.45},{name:"Invert",value:1},{name:"nearplane",value:.1},{name:"farplane",value:100}],objName:"Ops.Gl.ImageCompose.DepthTextureFocus_v2"},{id:"te23cj85g",uiAttribs:{subPatch:"qjbpb8llo"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"q55jv5ukl",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"amount",value:1},{name:"direction index",value:0},{name:"direction",value:"both"},{name:"Fast",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"qlhgi154s",objOut:"q55jv5ukl"}]}],objName:"Ops.Gl.ImageCompose.Blur"},{id:"kkdmtu5n3",uiAttribs:{subPatch:"qjbpb8llo"},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:"1trk9wp7u",objOut:"kkdmtu5n3"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"qlhgi154s",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"blendMode index",value:6},{name:"blendMode",value:"add"},{name:"amount",value:.648},{name:"Premultiplied",value:0},{name:"Alpha Mask",value:0},{name:"removeAlphaSrc",value:0},{name:"Mask Src index",value:0},{name:"Mask Src",value:"alpha channel"},{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:"unm96uvui",objOut:"qlhgi154s"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"6pvg5jrkn",uiAttribs:{subPatch:"qjbpb8llo"},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:1},{name:"Wrap",value:"repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"uh7on3zii",objOut:"6pvg5jrkn"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"ailzsmo07",objOut:"6pvg5jrkn"},{portIn:"Image",portOut:"texture_out",objIn:"qlhgi154s",objOut:"6pvg5jrkn"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"ailzsmo07",uiAttribs:{subPatch:"qjbpb8llo"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"rja3pohhf",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Invert",value:0},{name:"Black White",value:0},{name:"Threshold low ",value:.76},{name:"Threshold high",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"1icv5plag",objOut:"rja3pohhf"}]}],objName:"Ops.Gl.ImageCompose.LumaKey_v2"},{id:"1icv5plag",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Blend Mode index",value:4},{name:"Blend Mode",value:"multiply invert"},{name:"Amount",value:1},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Mask Invert",value:0},{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"A",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"qnrisvneg",objOut:"1icv5plag"}]}],objName:"Ops.Gl.ImageCompose.Color_v2"},{id:"uh7on3zii",uiAttribs:{subPatch:"qjbpb8llo"},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:0},{name:"Mask Src",value:"alpha channel"},{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:"rja3pohhf",objOut:"uh7on3zii"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"qnrisvneg",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Lens Distort",value:0},{name:"Smooth",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"php1zgoja",objOut:"qnrisvneg"}]}],objName:"Ops.Gl.ImageCompose.ChromaticAberration_v2"},{id:"php1zgoja",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Strength",value:1},{name:"Samples",value:40},{name:"X",value:0},{name:"Y",value:.51},{name:"Source Strength Map index",value:0},{name:"Source Strength Map",value:"R"},{name:"Invert Strength Map",value:0}],objName:"Ops.Gl.ImageCompose.ZoomBlur_v2"},{id:"0sk8k6kz0",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Speed",value:100},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"rotY",portOut:"Time",objIn:"1trk9wp7u",objOut:"0sk8k6kz0"},{portIn:"rotZ",portOut:"Time",objIn:"1trk9wp7u",objOut:"0sk8k6kz0"},{portIn:"rotX",portOut:"Time",objIn:"1trk9wp7u",objOut:"0sk8k6kz0"}]}],objName:"Ops.Anim.Timer_v2"},{id:"0jucjma76",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"X",value:0},{name:"Y",value:0},{name:"Scale",value:1},{name:"Seed",value:1}],portsOut:[{name:"Result",links:[{portIn:"number1",portOut:"Result",objIn:"na048spq9",objOut:"0jucjma76"}]}],objName:"Ops.Math.PerlinNoise_v2"},{id:"5nlnuhdj4",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Speed",value:1},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"Z",portOut:"Time",objIn:"0jucjma76",objOut:"5nlnuhdj4"}]}],objName:"Ops.Anim.Timer_v2"},{id:"na048spq9",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"number2",value:.02}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"hkovt7bmk",objOut:"na048spq9"}]}],objName:"Ops.Math.Multiply"},{id:"hkovt7bmk",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"number2",value:.005}],portsOut:[{name:"result",links:[{portIn:"scale",portOut:"result",objIn:"1trk9wp7u",objOut:"hkovt7bmk"}]}],objName:"Ops.Math.Sum"},{id:"unm96uvui",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"width",value:640},{name:"height",value:480}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"fwxn623ws",objOut:"unm96uvui"}]}],objName:"Ops.Gl.ImageCompose.Pixelate_v2"},{id:"0dpy5g7ky",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Variable",value:"lightsTex"}],portsOut:[{name:"Value",links:[{portIn:"Texture 1",portOut:"Value",objIn:"35b1nvdq0",objOut:"0dpy5g7ky"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"vwqrlgdx9",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Mask Invert",value:0},{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"A",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"ubgo9dzce",objOut:"vwqrlgdx9"}]}],objName:"Ops.Gl.ImageCompose.Color_v2"},{id:"hdckn7cpf",uiAttribs:{subPatch:"8ufgvhf99"},portsOut:[{name:"create port",value:0},{name:"in0 Sequence exe",links:[{portIn:"exe",portOut:"in0 Sequence exe",objIn:"5nbni5wp8",objOut:"hdckn7cpf"}]}],objName:"Ops.Ui.PatchInput"},{id:"torxs1w9o",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"5nbni5wp8",uiAttribs:{subPatch:"8ufgvhf99"},portsOut:[{name:"trigger 6",links:[{portIn:"exe",portOut:"trigger 6",objIn:"oih5ayuhm",objOut:"5nbni5wp8"}]},{name:"trigger 8",links:[{portIn:"Render",portOut:"trigger 8",objIn:"1fezais1i",objOut:"5nbni5wp8"}]},{name:"trigger 9",links:[{portIn:"Render",portOut:"trigger 9",objIn:"rrb5efx96",objOut:"5nbni5wp8"}]},{name:"trigger 13",links:[{portIn:"Render",portOut:"trigger 13",objIn:"2a1ece6h6",objOut:"5nbni5wp8"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"qr8cmyk3l",objOut:"5nbni5wp8"}]}],objName:"Ops.Trigger.Sequence"},{id:"qr8cmyk3l",uiAttribs:{subPatch:"8ufgvhf99"},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:1},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{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:"q9ql10b7z",objOut:"qr8cmyk3l"}]},{name:"texture_out",links:[{portIn:"Value",portOut:"texture_out",objIn:"38y0ucnuq",objOut:"qr8cmyk3l"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"38y0ucnuq",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Variable",value:"sceneTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"q9ql10b7z",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Mask Invert",value:0},{name:"Blendmode 1 index",value:0},{name:"Blendmode 1",value:"normal"},{name:"Mask Source 1 index",value:0},{name:"Mask Source 1",value:"R"},{name:"Opacity 1 index",value:0},{name:"Opacity 1",value:"Normal"},{name:"Blendmode 2 index",value:0},{name:"Blendmode 2",value:"normal"},{name:"Mask Source 2 index",value:0},{name:"Mask Source 2",value:"R"},{name:"Opacity 2 index",value:0},{name:"Opacity 2",value:"Normal"},{name:"Amount 2",value:1},{name:"Blendmode 3 index",value:0},{name:"Blendmode 3",value:"normal"},{name:"Mask Source 3 index",value:0},{name:"Mask Source 3",value:"R"},{name:"Opacity 3 index",value:0},{name:"Opacity 3",value:"Normal"},{name:"Amount 3",value:.88},{name:"Blendmode 4 index",value:11},{name:"Blendmode 4",value:"overlay"},{name:"Mask Source 4 index",value:0},{name:"Mask Source 4",value:"R"},{name:"Opacity 4 index",value:0},{name:"Opacity 4",value:"Normal"},{name:"Amount 4",value:1},{name:"Blendmode 5 index",value:3},{name:"Blendmode 5",value:"multiply"},{name:"Mask Source 5 index",value:0},{name:"Mask Source 5",value:"R"},{name:"Opacity 5 index",value:0},{name:"Opacity 5",value:"Normal"},{name:"Amount 5",value:1},{name:"Blendmode 6 index",value:0},{name:"Blendmode 6",value:"normal"},{name:"Mask Source 6 index",value:0},{name:"Mask Source 6",value:"R"},{name:"Opacity 6 index",value:0},{name:"Opacity 6",value:"Normal"},{name:"Amount 6",value:1},{name:"Blendmode 7 index",value:0},{name:"Blendmode 7",value:"normal"},{name:"Mask Source 7 index",value:0},{name:"Mask Source 7",value:"R"},{name:"Opacity 7 index",value:0},{name:"Opacity 7",value:"Normal"},{name:"Amount 7",value:1},{name:"Blendmode 8 index",value:0},{name:"Blendmode 8",value:"normal"},{name:"Mask Source 8 index",value:0},{name:"Mask Source 8",value:"R"},{name:"Opacity 8 index",value:0},{name:"Opacity 8",value:"Normal"},{name:"Amount 8",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"omssa55sh",objOut:"q9ql10b7z"}]}],objName:"Ops.Gl.ImageCompose.MultiDrawImage"},{id:"rrb5efx96",uiAttribs:{subPatch:"8ufgvhf99"},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:1},{name:"Wrap",value:"repeat"},{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:"cbkrwqf7y",objOut:"rrb5efx96"}]},{name:"texture_out",links:[{portIn:"Texture 2",portOut:"texture_out",objIn:"q9ql10b7z",objOut:"rrb5efx96"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"oih5ayuhm",uiAttribs:{subPatch:"8ufgvhf99"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"77ofg5ioa",objOut:"oih5ayuhm"}]}],objName:"Ops.Trigger.Sequence"},{id:"77ofg5ioa",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Canvas"},{name:"texture width",value:1920},{name:"texture height",value:1080},{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:0},{name:"MSAA",value:"none"},{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:"Input_0",portOut:"trigger",objIn:"u7gxley0s",objOut:"77ofg5ioa"}]},{name:"texture",links:[{portIn:"Base Texture",portOut:"texture",objIn:"rrb5efx96",objOut:"77ofg5ioa"},{portIn:"Texture In",portOut:"texture",objIn:"t0l4llj2v",objOut:"77ofg5ioa"}]}],objName:"Ops.Gl.RenderToTexture_v3"},{id:"3e72isj2d",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Sequence exe","type":1}],"portsOut":[]}'},{name:"patchId",value:"8ufgvhf99"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"1cmwdwd93",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"File",value:"assets/FCPLOGO2.png",display:"file"},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{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:"nyhwopcf9",objOut:"1cmwdwd93"}]},{name:"Width",value:376},{name:"Height",value:500},{name:"Aspect Ratio",links:[{portIn:"width",portOut:"Aspect Ratio",objIn:"p85vrfr8l",objOut:"1cmwdwd93"}]},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"p85vrfr8l",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"render",title:"Trigger"},{name:"Render Mesh",value:1,title:"Render"},{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:"nyhwopcf9",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"r",value:.12086987858513587},{name:"g",value:.8428574071333648},{name:"b",value:.3961394635804625},{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:"p85vrfr8l",objOut:"nyhwopcf9"}]}],objName:"Ops.Gl.Shader.BasicMaterial_v3"},{id:"t0l4llj2v",uiAttribs:{subPatch:"8ufgvhf99"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"u7gxley0s",uiAttribs:{subPatch:"8ufgvhf99"},portsOut:[{name:"Output",multiPortNum:5},{name:"Output_0",links:[{portIn:"render",portOut:"Output_0",objIn:"2ijl1k0l4",objOut:"u7gxley0s"}]},{name:"Output_1",title:"add port",links:[{portIn:"render",portOut:"Output_1",objIn:"gm4xqc6zm",objOut:"u7gxley0s"}]},{name:"Output_2",links:[{portIn:"render",portOut:"Output_2",objIn:"htb28xniz",objOut:"u7gxley0s"}]},{name:"Output_3",links:[{portIn:"render",portOut:"Output_3",objIn:"bmblamb9l",objOut:"u7gxley0s"}]},{name:"Output_4",links:[{portIn:"render",portOut:"Output_4",objIn:"4d38ebyj1",objOut:"u7gxley0s"}]}],objName:"Ops.Trigger.SequenceMultiPort"},{id:"lj1do2tm2",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Text",value:"FAST cOMpo"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:1},{name:"vertical align",value:"Middle"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:1.63499995640346},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"gm4xqc6zm",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"x",value:.04},{name:"y",value:.87}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"lj1do2tm2",objOut:"gm4xqc6zm"}]}],objName:"Ops.Gl.Matrix.Translate"},{id:"2ijl1k0l4",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"posX",value:0},{name:"posY",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:"nyhwopcf9",objOut:"2ijl1k0l4"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"gc59n0m42",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Text",value:"ProdUCtions"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:1},{name:"vertical align",value:"Middle"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:1.8671428135463173},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"htb28xniz",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"x",value:0},{name:"y",value:-1.01}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"gc59n0m42",objOut:"htb28xniz"}]}],objName:"Ops.Gl.Matrix.Translate"},{id:"5zhizpvyl",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"phase",value:0},{name:"frequency",value:1},{name:"amplitude",value:1},{name:"asine",value:0}],portsOut:[{name:"result",links:[{portIn:"Seed",portOut:"result",objIn:"2n3tqaglf",objOut:"5zhizpvyl"}]}],objName:"Ops.Math.Sine"},{id:"1fezais1i",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Size index",value:1},{name:"Size",value:"Manual"},{name:"Width",value:100},{name:"Height",value:100},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"ysxgy5aae",objOut:"1fezais1i"},{portIn:"In Trigger",portOut:"Next",objIn:"f1d10nawr",objOut:"1fezais1i"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"rvpq05e1n",objOut:"1fezais1i"},{portIn:"displaceTex",portOut:"texture_out",objIn:"cbkrwqf7y",objOut:"1fezais1i"},{portIn:"Image",portOut:"texture_out",objIn:"ik3s3ljmj",objOut:"1fezais1i"}]},{name:"Aspect Ratio",value:1},{name:"Texture Width",value:100},{name:"Texture Height",value:100}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"ysxgy5aae",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"frequency",value:1},{name:"strength",value:8},{name:"Block size small x",value:16.42},{name:"Block size small y",value:17.96},{name:"Block size large x",value:17.96},{name:"Block size large y",value:4},{name:"Scroll X",value:0},{name:"Scroll Y",value:0}],objName:"Ops.Gl.ImageCompose.Noise.GlitchNoise_v2"},{id:"rvpq05e1n",uiAttribs:{subPatch:"8ufgvhf99"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"tw74osjeb",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Speed",value:1},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"value",portOut:"Time",objIn:"72o5cbvo6",objOut:"tw74osjeb"}]}],objName:"Ops.Anim.Timer_v2"},{id:"f1d10nawr",uiAttribs:{subPatch:"8ufgvhf99"},portsOut:[{name:"Out Trigger",links:[{portIn:"Generate",portOut:"Out Trigger",objIn:"nm5ubqxs8",objOut:"f1d10nawr"}]},{name:"Progress",value:.8887215222685693}],objName:"Ops.Trigger.TriggerLimiter"},{id:"nm5ubqxs8",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"min",value:0},{name:"max",value:1},{name:"Integer",value:0},{name:"No consecutive duplicates",value:0}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"dp2io32x0",objOut:"nm5ubqxs8"}]}],objName:"Ops.Math.TriggerRandomNumber_v2"},{id:"dp2io32x0",uiAttribs:{subPatch:"8ufgvhf99"},portsOut:[{name:"result",links:[{portIn:"Amount",portOut:"result",objIn:"ysxgy5aae",objOut:"dp2io32x0"}]}],objName:"Ops.Math.Compare.LessThan"},{id:"mobvqf4df",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"value",value:113}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"r9dn3zw7t",objOut:"mobvqf4df"}]}],objName:"Ops.Number.Number"},{id:"r9dn3zw7t",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"number2",value:.47}],portsOut:[{name:"result",links:[{portIn:"Milliseconds",portOut:"result",objIn:"f1d10nawr",objOut:"r9dn3zw7t"}]}],objName:"Ops.Math.Multiply"},{id:"72o5cbvo6",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"phase",value:0},{name:"frequency",value:1},{name:"amplitude",value:1},{name:"asine",value:0}],portsOut:[{name:"result",links:[{portIn:"Seed",portOut:"result",objIn:"ysxgy5aae",objOut:"72o5cbvo6"}]}],objName:"Ops.Math.Sine"},{id:"cbkrwqf7y",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"amount X",value:.036},{name:"amount Y",value:.022},{name:"Wrap index",value:2},{name:"Wrap",value:"Repeat"},{name:"Input index",value:0},{name:"Input",value:"Luminance"},{name:"Zero Displace index",value:1},{name:"Zero Displace",value:"Black"},{name:"Pixel Mapping index",value:0},{name:"Pixel Mapping",value:"Stretch"}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"ik3s3ljmj",objOut:"cbkrwqf7y"}]}],objName:"Ops.Gl.ImageCompose.PixelDisplacement_v4"},{id:"ik3s3ljmj",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"blendMode index",value:11},{name:"blendMode",value:"overlay"},{name:"amount",value:1},{name:"Premultiplied",value:0},{name:"Alpha Mask",value:1},{name:"removeAlphaSrc",value:1},{name:"Mask Src index",value:0},{name:"Mask Src",value:"alpha channel"},{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}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"1o3wtowq7",uiAttribs:{subPatch:"nfuzc9gb4"},portsOut:[{name:"trigger 0",links:[{portIn:"Trigger In",portOut:"trigger 0",objIn:"ilw5inq1f",objOut:"1o3wtowq7"}]},{name:"trigger 2",links:[{portIn:"Trigger In",portOut:"trigger 2",objIn:"6enlsxgbg",objOut:"1o3wtowq7"}]}],objName:"Ops.Trigger.Sequence"},{id:"rrnbj5rh1",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Draw",value:1,title:"Render mesh"},{name:"segments",value:4},{name:"stacks",value:300},{name:"length",value:23.3},{name:"outer radius",value:.59},{name:"inner radius",value:0},{name:"UV mode index",value:0},{name:"UV mode",value:"simple"},{name:"Flip Mapping",value:0},{name:"Caps",value:0},{name:"Flat Normals",value:1}],objName:"Ops.Gl.Meshes.Cylinder_v2"},{id:"ttl8wprv7",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"posX",value:-.12},{name:"scale",value:.91},{name:"rotX",value:-25.25},{name:"rotY",value:69.01},{name:"rotZ",value:4.03}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"ybfohchdc",objOut:"ttl8wprv7"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"6enlsxgbg",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"R",value:.6855098269143594},{name:"G",value:.6657297021080522},{name:"B",value:.6138437503033101},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.5718450123348118},{name:"Emissive G",value:.8471433928331629},{name:"Emissive B",value:.16685073079966117},{name:"Shininess",value:4},{name:"Specular Amount",value:.5},{name:"Specular Model index",value:0},{name:"Specular Model",value:"Blinn"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1.47},{name:"Diffuse Repeat Y",value:3.89},{name:"Texture Offset Y",value:.04},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:1},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Trigger Out",links:[{portIn:"render",portOut:"Trigger Out",objIn:"ttl8wprv7",objOut:"6enlsxgbg"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"ybfohchdc",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Height",value:2.33},{name:"Axis index",value:2},{name:"Axis",value:"Z"}],portsOut:[{name:"Trigger",links:[{portIn:"render",portOut:"Trigger",objIn:"m9i8n2yhs",objOut:"ybfohchdc"}]}],objName:"Ops.Gl.ShaderEffects.Twist_v3"},{id:"m9i8n2yhs",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Amount",value:2.22},{name:"RotX",value:0},{name:"RotY",value:78.98},{name:"RotZ",value:0},{name:"Scale",value:.18},{name:"Offset",value:-1.03},{name:"Limited",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"rrnbj5rh1",objOut:"m9i8n2yhs"}]}],objName:"Ops.Gl.ShaderEffects.Bend_v2"},{id:"ahn1rse3m",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"File",value:"assets/music-scroller.png",display:"file"},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{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:"Diffuse Texture",portOut:"Texture",objIn:"6enlsxgbg",objOut:"ahn1rse3m"}]},{name:"Width",value:1920},{name:"Height",value:128},{name:"Aspect Ratio",value:15},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"jpku5te27",uiAttribs:{subPatch:"nfuzc9gb4"},portsOut:[{name:"time",links:[{portIn:"number1",portOut:"time",objIn:"oe2nl81cd",objOut:"jpku5te27"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"oe2nl81cd",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"number2",value:13.36}],portsOut:[{name:"result",links:[{portIn:"Texture Offset X",portOut:"result",objIn:"6enlsxgbg",objOut:"oe2nl81cd"}]}],objName:"Ops.Math.Divide"},{id:"a5on9gden",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"Text",value:"beat"}],objName:"Ops.Sidebar.DisplayValue_v2"},{id:"ty9el051g",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"Number",portOut:"Value",objIn:"bk4f8tvgr",objOut:"ty9el051g"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"z7h0al4js",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsIn:[{name:"Decimal Places",value:4}],portsOut:[{name:"Result",links:[{portIn:"Value",portOut:"Result",objIn:"a5on9gden",objOut:"z7h0al4js"}]}],objName:"Ops.String.NumberToString_v2"},{id:"bk4f8tvgr",uiAttribs:{subPatch:"10b30ac0-012a-4a7c-8002-380eb93a93c0"},portsOut:[{name:"Result",links:[{portIn:"Number",portOut:"Result",objIn:"z7h0al4js",objOut:"bk4f8tvgr"}]}],objName:"Ops.Math.Floor"},{id:"fwvo8toiw",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"sheet",value:"#a1 - logo z\na1:\n0 (-15.qio)\n14 (0.)\n31. (0.qio)\n32. (15.)\n\n#a2 - text alpha\na2:\n0. (0.)\n14 (1.)\n31. (1.qio)\n32. (0.)\n\n#a3 a4 - top bottom pos z\na3:\n0. (-16.) (-16.)\n15 (-16.qio) (-)\n16 (-1.5li) (-16.qio)\n17 (-1.5li) (-1.5li)\n32. (-1.) (-1.)\n\n\n# a5 - glitch amt\na5:\n0. (0.)\n8 (0.li)\n16 (0.40)\n\n#a6 - crime\na6:\n0. (0.)\n47. (1.)\n\n#a7 bg amount\na7:\n0. (0.2l)\n12. (1.)\n\n#a8 crime red\na8:\n47. (0.qio)\n48. (1.)"}],portsOut:[{name:"analog 1",links:[{portIn:"posZ",portOut:"analog 1",objIn:"2ijl1k0l4",objOut:"fwvo8toiw"}]},{name:"analog 2",links:[{portIn:"a",portOut:"analog 2",objIn:"lj1do2tm2",objOut:"fwvo8toiw"},{portIn:"a",portOut:"analog 2",objIn:"gc59n0m42",objOut:"fwvo8toiw"}]},{name:"analog 3",links:[{portIn:"z",portOut:"analog 3",objIn:"gm4xqc6zm",objOut:"fwvo8toiw"}]},{name:"analog 4",links:[{portIn:"z",portOut:"analog 4",objIn:"htb28xniz",objOut:"fwvo8toiw"}]},{name:"analog 5",links:[{portIn:"number2",portOut:"analog 5",objIn:"dp2io32x0",objOut:"fwvo8toiw"}]},{name:"analog 6",links:[{portIn:"amount",portOut:"analog 6",objIn:"omssa55sh",objOut:"fwvo8toiw"}]},{name:"analog 7",links:[{portIn:"Amount 1",portOut:"analog 7",objIn:"q9ql10b7z",objOut:"fwvo8toiw"}]},{name:"analog 8",links:[{portIn:"Amount",portOut:"analog 8",objIn:"0ggxkqsne",objOut:"fwvo8toiw"}]}],objName:"Ops.User.anticore.DopeSheet"},{id:"qfew6olhv",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"time",portOut:"Value",objIn:"fwvo8toiw",objOut:"qfew6olhv"},{portIn:"time",portOut:"Value",objIn:"9c58w1gg0",objOut:"qfew6olhv"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"t4e0kcjbq",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"amount",value:5.48},{name:"direction index",value:2},{name:"direction",value:"horizontal"},{name:"Fast",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"hw5f7hyiu",objOut:"t4e0kcjbq"}]}],objName:"Ops.Gl.ImageCompose.Blur"},{id:"n6e626ojc",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"blendMode index",value:3},{name:"blendMode",value:"multiply"},{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:"0nwfqwfcd",objOut:"n6e626ojc"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"kyra1eihp",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"File",value:"assets/crime.png",display:"file"},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{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:"Image",portOut:"Texture",objIn:"n6e626ojc",objOut:"kyra1eihp"},{portIn:"Base Texture",portOut:"Texture",objIn:"rtq7l2mua",objOut:"kyra1eihp"}]},{name:"Width",value:1920},{name:"Height",value:1080},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"0nwfqwfcd",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"direction index",value:0},{name:"direction",value:"both"},{name:"Fast",value:1}],objName:"Ops.Gl.ImageCompose.Blur"},{id:"rtq7l2mua",uiAttribs:{subPatch:"kb5v7uxi5"},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:1},{name:"Wrap",value:"repeat"},{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:"5y7wefbbi",objOut:"rtq7l2mua"}]},{name:"texture_out",links:[{portIn:"mask",portOut:"texture_out",objIn:"0nwfqwfcd",objOut:"rtq7l2mua"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"5y7wefbbi",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Mask Invert",value:0},{name:"Invert R",value:1},{name:"Invert G",value:1},{name:"Invert B",value:1}],objName:"Ops.Gl.ImageCompose.Invert_v2"},{id:"r9jkn52jp",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Strength",value:.083},{name:"Samples",value:40},{name:"Y",value:0},{name:"Source Strength Map index",value:0},{name:"Source Strength Map",value:"R"},{name:"Invert Strength Map",value:0}],objName:"Ops.Gl.ImageCompose.ZoomBlur_v2"},{id:"5wo701n1c",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"R",value:.30196078431372547},{name:"G",value:.05001225490196076},{name:"B",value:0},{name:"Intensity",value:1}],portsOut:[{name:"Trigger Out",links:[{portIn:"Trigger In",portOut:"Trigger Out",objIn:"mkol139h6",objOut:"5wo701n1c"}]}],objName:"Ops.Gl.Phong.AmbientLight_v4"},{id:"mkol139h6",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Cast Light",value:1},{name:"Intensity",value:1},{name:"X",value:0},{name:"Y",value:-6.41},{name:"Z",value:5},{name:"R",value:1},{name:"G",value:1},{name:"B",value:1},{name:"Specular R",value:.2},{name:"Specular G",value:.2},{name:"Specular B",value:.2},{name:"Cast Shadow",value:0},{name:"Rendering Active",value:1},{name:"Map Size index",value:1},{name:"Map Size",value:512},{name:"Shadow Strength",value:1},{name:"LR-BottomTop",value:8},{name:"Near",value:.1},{name:"Far",value:30},{name:"Bias",value:.004},{name:"Polygon Offset",value:0},{name:"Normal Offset",value:0},{name:"Blur Amount",value:0},{name:"Enable Advanced",value:0},{name:"MSAA index",value:0},{name:"MSAA",value:"none"},{name:"Texture Filter index",value:0},{name:"Texture Filter",value:"Linear"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"}],portsOut:[{name:"Trigger Out",links:[{portIn:"Trigger",portOut:"Trigger Out",objIn:"3t04xpfq8",objOut:"mkol139h6"}]}],objName:"Ops.Gl.Phong.DirectionalLight_v5"},{id:"7ktwzmsh8",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"File",value:"assets/crime.png",display:"file"},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{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:"Image",portOut:"Texture",objIn:"omssa55sh",objOut:"7ktwzmsh8"}]},{name:"Width",value:1920},{name:"Height",value:1080},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"omssa55sh",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"blendMode index",value:0},{name:"blendMode",value:"normal"},{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:"0ggxkqsne",objOut:"omssa55sh"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"gwvdahjng",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Variable",value:"randomVignetteTex"}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"2a1ece6h6",uiAttribs:{subPatch:"8ufgvhf99"},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:1},{name:"Wrap",value:"repeat"},{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:"5xbcwtaoa",objOut:"2a1ece6h6"}]},{name:"texture_out",links:[{portIn:"Texture 1",portOut:"texture_out",objIn:"q9ql10b7z",objOut:"2a1ece6h6"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"pyu0mwnn6",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Variable",value:"stationTex"}],portsOut:[{name:"Value",links:[{portIn:"Base Texture",portOut:"Value",objIn:"2a1ece6h6",objOut:"pyu0mwnn6"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"5xbcwtaoa",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Amount",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"vp4676m6g",objOut:"5xbcwtaoa"}]}],objName:"Ops.Gl.ImageCompose.LUTMap"},{id:"hvmbl01ta",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"File",value:"assets/lib_lut_lut8.jpg",display:"file"},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Data Format index",value:3},{name:"Data Format",value:"RGBA"},{name:"Flip",value:1},{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:"LUT Image",portOut:"Texture",objIn:"5xbcwtaoa",objOut:"hvmbl01ta"}]},{name:"Width",value:512},{name:"Height",value:512},{name:"Aspect Ratio",value:1},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"vp4676m6g",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Blend Mode index",value:3},{name:"Blend Mode",value:"multiply"},{name:"Amount",value:1},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Mask Invert",value:0},{name:"r",value:.396078431372549},{name:"g",value:.015686274509803935},{name:"b",value:.015686274509803935},{name:"A",value:1}],objName:"Ops.Gl.ImageCompose.Color_v2"},{id:"ghg6lsywu",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Variable",value:"randomVignetteTex"}],portsOut:[{name:"Value",links:[{portIn:"Texture 4",portOut:"Value",objIn:"q9ql10b7z",objOut:"ghg6lsywu"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"ivqdb6rh2",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Text",value:"PubLIc ServICE"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:1},{name:"vertical align",value:"Middle"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:2.2467856799369255},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"bmblamb9l",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"x",value:.04},{name:"y",value:.39}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"ivqdb6rh2",objOut:"bmblamb9l"}]}],objName:"Ops.Gl.Matrix.Translate"},{id:"od129vbeq",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Text",value:"AnNOUnceMENT"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:1},{name:"vertical align",value:"Middle"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:2.1153571388938213},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"4d38ebyj1",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"x",value:0},{name:"y",value:-.39}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"od129vbeq",objOut:"4d38ebyj1"}]}],objName:"Ops.Gl.Matrix.Translate"},{id:"9c58w1gg0",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"sheet",value:"# psa text pos\n0. (-150.)\n31. (-15.qio) (-150.)\n32. (-1.4li) (-150.qio)\n33. (-1.4li) (-1.4li)\n48. (-1.) (-1.)\n"}],portsOut:[{name:"analog 1",links:[{portIn:"z",portOut:"analog 1",objIn:"bmblamb9l",objOut:"9c58w1gg0"}]},{name:"analog 2",links:[{portIn:"z",portOut:"analog 2",objIn:"4d38ebyj1",objOut:"9c58w1gg0"}]},{name:"analog 3",value:0},{name:"analog 4",value:0},{name:"analog 5",value:0},{name:"analog 6",value:0},{name:"analog 7",value:0},{name:"analog 8",value:0}],objName:"Ops.User.anticore.DopeSheet"},{id:"0ggxkqsne",uiAttribs:{subPatch:"8ufgvhf99"},portsIn:[{name:"Blend Mode index",value:3},{name:"Blend Mode",value:"multiply"},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Mask Invert",value:0},{name:"r",value:.7952083333333333},{name:"g",value:0},{name:"b",value:0},{name:"A",value:1}],objName:"Ops.Gl.ImageCompose.Color_v2"},{id:"lqvuxytd8",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"phase",value:0},{name:"frequency",value:1},{name:"amplitude",value:1.42},{name:"asine",value:0}],portsOut:[{name:"result",links:[{portIn:"X",portOut:"result",objIn:"r9jkn52jp",objOut:"lqvuxytd8"}]}],objName:"Ops.Math.Sine"},{id:"y8kpl26ks",uiAttribs:{subPatch:"97550752-dd1e-4d10-89a9-20099811ef1c"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"value",portOut:"Value",objIn:"lqvuxytd8",objOut:"y8kpl26ks"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"7lymuxycq",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"value",portOut:"Value",objIn:"9dytrdlt8",objOut:"7lymuxycq"},{portIn:"time",portOut:"Value",objIn:"qi6y1koj4",objOut:"7lymuxycq"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"9dytrdlt8",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"phase",value:0},{name:"frequency",value:1},{name:"amplitude",value:.1},{name:"asine",value:0}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"mk70njdzd",objOut:"9dytrdlt8"}]}],objName:"Ops.Math.Sine"},{id:"mk70njdzd",uiAttribs:{subPatch:"yhlhmvwcf"},portsOut:[{name:"result",links:[{portIn:"Strength",portOut:"result",objIn:"l9efz6w1l",objOut:"mk70njdzd"}]}],objName:"Ops.Math.Sum"},{id:"qi6y1koj4",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"sheet",value:"#a1 - fall amount\n80. (1.li)\n92. (10.qo)\n94. (11.)\n\n#a2 a3 man y z\na2:\n0. (-0.28) (-10.13)\n92. (-0.28qio) (-10.13qio)\n96. (-0.61) (-2.16li)\n112. (-) (0.)\n\n#a4 a5 rotx roty man\na4:\n0. (-10.46) (-61.43)\n92. (-10.46qio) (-61.43qio)\n96. (-65.17) (1.)\n\n#a6 - fall y\na6:\n92. (1.55qio)\n96. (0.)\n\na7:\n80. (0.46)\n92. (0.46li)\n98. (1.)"}],portsOut:[{name:"analog 1",links:[{portIn:"Position Y",portOut:"analog 1",objIn:"oze5gv8px",objOut:"qi6y1koj4"}]},{name:"analog 2",links:[{portIn:"posY",portOut:"analog 2",objIn:"4nh6rs2am",objOut:"qi6y1koj4"}]},{name:"analog 3",links:[{portIn:"posZ",portOut:"analog 3",objIn:"4nh6rs2am",objOut:"qi6y1koj4"}]},{name:"analog 4",links:[{portIn:"rotX",portOut:"analog 4",objIn:"4nh6rs2am",objOut:"qi6y1koj4"}]},{name:"analog 5",links:[{portIn:"rotY",portOut:"analog 5",objIn:"4nh6rs2am",objOut:"qi6y1koj4"}]},{name:"analog 6",links:[{portIn:"Y",portOut:"analog 6",objIn:"l9efz6w1l",objOut:"qi6y1koj4"}]},{name:"analog 7",links:[{portIn:"number2",portOut:"analog 7",objIn:"mk70njdzd",objOut:"qi6y1koj4"}]},{name:"analog 8",value:0}],objName:"Ops.User.anticore.DopeSheet"},{id:"0risiorau",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Variable",value:"randomVignetteTex2"}],portsOut:[{name:"Value",links:[{portIn:"Texture 4",portOut:"Value",objIn:"vdg8yh39d",objOut:"0risiorau"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"pthqxajyu",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"amount",value:4},{name:"direction index",value:0},{name:"direction",value:"both"},{name:"Fast",value:1}],objName:"Ops.Gl.ImageCompose.Blur"},{id:"qv70i6yey",uiAttribs:{subPatch:"yhlhmvwcf"},portsIn:[{name:"Variable",value:"invertedVignette"}],portsOut:[{name:"Value",links:[{portIn:"mask",portOut:"Value",objIn:"pthqxajyu",objOut:"qv70i6yey"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"y798vofn3",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"time",portOut:"Value",objIn:"ng7cee9si",objOut:"y798vofn3"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"ng7cee9si",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"sheet",value:"#a1 man y z\n112. (-0.27li) (0.78li)\n144. (-0.35) (1.49)\n\n#a3 zoomblur amount\na3:\n134. (0.li)\n144. (0.6)"}],portsOut:[{name:"analog 1",links:[{portIn:"posY",portOut:"analog 1",objIn:"qpphaosic",objOut:"ng7cee9si"}]},{name:"analog 2",links:[{portIn:"posZ",portOut:"analog 2",objIn:"qpphaosic",objOut:"ng7cee9si"}]},{name:"analog 3",links:[{portIn:"Strength",portOut:"analog 3",objIn:"dmpo8cjqg",objOut:"ng7cee9si"}]},{name:"analog 4",value:0},{name:"analog 5",value:0},{name:"analog 6",value:0},{name:"analog 7",value:0},{name:"analog 8",value:0}],objName:"Ops.User.anticore.DopeSheet"},{id:"syzlkfbz3",uiAttribs:{subPatch:"1b2ji7hqx"},portsOut:[{name:"time",links:[{portIn:"Value",portOut:"time",objIn:"l5bzjvk12",objOut:"syzlkfbz3"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"l5bzjvk12",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Variable",value:"mdlIdleAnim"}],objName:"Ops.Vars.VarSetNumber_v2"},{id:"58exs4ol0",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"amount",value:3.05},{name:"direction index",value:0},{name:"direction",value:"both"},{name:"Fast",value:1}],objName:"Ops.Gl.ImageCompose.Blur"},{id:"tw5n2jeus",uiAttribs:{subPatch:"1b2ji7hqx"},portsIn:[{name:"Variable",value:"invertedVignette"}],portsOut:[{name:"Value",links:[{portIn:"mask",portOut:"Value",objIn:"58exs4ol0",objOut:"tw5n2jeus"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"ji88zhl5e",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"time",portOut:"Value",objIn:"w8dr6ddmx",objOut:"ji88zhl5e"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"w8dr6ddmx",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"sheet",value:"#fov\n144. (99.)\n151. (99.qio)\n152. (75.)\n159. (75.qio)\n160. (99.)\n175. (99.qi)\n176 (0.)\n\n#blob scale\na2:\n170. (0.52qi)\n176. (0.)"}],portsOut:[{name:"analog 1",links:[{portIn:"fov y",portOut:"analog 1",objIn:"qvh1qb3rg",objOut:"w8dr6ddmx"}]},{name:"analog 2",links:[{portIn:"value",portOut:"analog 2",objIn:"r79gzz0jb",objOut:"w8dr6ddmx"}]},{name:"analog 3",value:0},{name:"analog 4",value:0},{name:"analog 5",value:0},{name:"analog 6",value:0},{name:"analog 7",value:0},{name:"analog 8",value:0}],objName:"Ops.User.anticore.DopeSheet"},{id:"r79gzz0jb",uiAttribs:{subPatch:"x8e2jwc2f"},portsOut:[{name:"result",links:[{portIn:"scale",portOut:"result",objIn:"jao5bf4iv",objOut:"r79gzz0jb"}]}],objName:"Ops.Number.Number"},{id:"6xwbekyxp",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"direction index",value:0},{name:"direction",value:"both"},{name:"Fast",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"uhdbk6dn2",objOut:"6xwbekyxp"}]}],objName:"Ops.Gl.ImageCompose.Blur"},{id:"9eulce2by",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"number2",value:10}],portsOut:[{name:"result",links:[{portIn:"amount",portOut:"result",objIn:"6xwbekyxp",objOut:"9eulce2by"}]}],objName:"Ops.Math.Multiply"},{id:"uo06uh75k",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"sheet",value:"0 (1.qio)\n6. (0.)\n47.8 (0.qio)\n48 (1.qio)\n48.5 (0.)\n79.5 (0.qio)\n80 (1.qio)\n80.5 (0.)\n111.5 (0.qio)\n112 (1.qio)\n112.5 (0.)\n143.5 (0.qio)\n144 (1.qio)\n144.5 (0.)\n175.5 (0.qio)\n176 (1.qio)\n176.3 (0.)\n207.7 (0.qio)\n208 (1.qio)\n208.5 (0.)\n239.5 (0.qio)\n240 (1.qio)\n240.5 (0.)\n279.5 (0.qio)\n280 (1.qio)\n280.5 (0.)\n287.5 (0.qio)\n288 (1.qio)\n288.5 (0.)\n303.5 (0.qio)\n304 (1.qio)\n304.5 (0.)\n335.5 (0.qio)\n336 (1.qio)\n336.5 (0.)\n390. (0.qio)\n410. (1.)\n\na2:\n0 (0.qio)\n3 (.5)\n410 (.5qio)\n415 (0.)"}],portsOut:[{name:"analog 1",links:[{portIn:"number1",portOut:"analog 1",objIn:"9eulce2by",objOut:"uo06uh75k"}]},{name:"analog 2",links:[{portIn:"brightness",portOut:"analog 2",objIn:"mw5zfn4tt",objOut:"uo06uh75k"}]},{name:"analog 3",value:0},{name:"analog 4",value:0},{name:"analog 5",value:0},{name:"analog 6",value:0},{name:"analog 7",value:0},{name:"analog 8",value:0}],objName:"Ops.User.anticore.DopeSheet"},{id:"inwabio1o",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"time",portOut:"Value",objIn:"uo06uh75k",objOut:"inwabio1o"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"zbdbk1264",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Variable",value:"randomVignetteTex"}],portsOut:[{name:"Value",links:[{portIn:"Texture 2",portOut:"Value",objIn:"0lpiv0jlt",objOut:"zbdbk1264"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"irc5mqr8d",uiAttribs:{subPatch:"x8e2jwc2f"},portsOut:[{name:"time",links:[{portIn:"Z",portOut:"time",objIn:"mhijzjlfb",objOut:"irc5mqr8d"},{portIn:"number1",portOut:"time",objIn:"bnvjom26q",objOut:"irc5mqr8d"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"zcy6925vk",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Variable",value:"fftHighs"}],portsOut:[{name:"Value",links:[{portIn:"Add to number",portOut:"Value",objIn:"qy3po9gmp",objOut:"zcy6925vk"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"qy3po9gmp",uiAttribs:{subPatch:"x8e2jwc2f"},portsIn:[{name:"Multiplier to add number",value:2},{name:"Default Value",value:1}],portsOut:[{name:"Current value",links:[{portIn:"Y",portOut:"Current value",objIn:"mhijzjlfb",objOut:"qy3po9gmp"}]}],objName:"Ops.Math.Accumulator"},{id:"rx5cna7dd",uiAttribs:{subPatch:"wbx4aydb0"},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:1},{name:"Wrap",value:"repeat"},{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:"hvvrmqnsy",objOut:"rx5cna7dd"}]},{name:"texture_out",links:[{portIn:"Texture 1",portOut:"texture_out",objIn:"mu4wucxm9",objOut:"rx5cna7dd"}]},{name:"Aspect Ratio",value:1.3333333333333333},{name:"Texture Width",value:1920},{name:"Texture Height",value:1440}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"z1iwaxh92",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Variable",value:"stationTex"}],portsOut:[{name:"Value",links:[{portIn:"Base Texture",portOut:"Value",objIn:"rx5cna7dd",objOut:"z1iwaxh92"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"hvvrmqnsy",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Amount",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"vh0ft00g6",objOut:"hvvrmqnsy"}]}],objName:"Ops.Gl.ImageCompose.LUTMap"},{id:"mgfqja4ne",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"File",value:"assets/lib_lut_lut8.jpg",display:"file"},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Data Format index",value:3},{name:"Data Format",value:"RGBA"},{name:"Flip",value:1},{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:"LUT Image",portOut:"Texture",objIn:"hvvrmqnsy",objOut:"mgfqja4ne"}]},{name:"Width",value:512},{name:"Height",value:512},{name:"Aspect Ratio",value:1},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"vh0ft00g6",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Blend Mode index",value:3},{name:"Blend Mode",value:"multiply"},{name:"Amount",value:1},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Mask Invert",value:0},{name:"r",value:.21520833333333333},{name:"g",value:.21520833333333333},{name:"b",value:.21520833333333333},{name:"A",value:1}],objName:"Ops.Gl.ImageCompose.Color_v2"},{id:"m45m789q7",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Variable",value:"randomVignetteTex2"}],portsOut:[{name:"Value",links:[{portIn:"Texture 3",portOut:"Value",objIn:"mu4wucxm9",objOut:"m45m789q7"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"obd0y6opt",uiAttribs:{subPatch:"wbx4aydb0"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"yyni46vx6",objOut:"obd0y6opt"}]},{name:"trigger 1",links:[{portIn:"render",portOut:"trigger 1",objIn:"cjs2ikb69",objOut:"obd0y6opt"}]},{name:"trigger 2",links:[{portIn:"render",portOut:"trigger 2",objIn:"dgpn9d6mz",objOut:"obd0y6opt"}]},{name:"trigger 4",links:[{portIn:"render",portOut:"trigger 4",objIn:"oygx6jy24",objOut:"obd0y6opt"}]}],objName:"Ops.Trigger.Sequence"},{id:"9cknpig2t",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Text",value:"UMA TELEBISÃo."},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:0},{name:"vertical align",value:"Top"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:2.2135713915804254},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"cjs2ikb69",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:-3.33},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"bcqsj60j1",objOut:"cjs2ikb69"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"bcqsj60j1",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Text",value:"NÃO SACARias"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:2},{name:"vertical align",value:"Bottom"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1}],portsOut:[{name:"Next",links:[{portIn:"Render",portOut:"Next",objIn:"9cknpig2t",objOut:"bcqsj60j1"}]},{name:"Total Lines",value:1},{name:"Width",value:1.9696428042985665},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"xpc1395ps",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Text",value:"UM BEÍCULO."},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:0},{name:"vertical align",value:"Top"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:1.7053571098294613},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"dgpn9d6mz",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:-3.33},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"hukq16gfb",objOut:"dgpn9d6mz"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"hukq16gfb",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Text",value:"NÃO SACARias"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:2},{name:"vertical align",value:"Bottom"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1}],portsOut:[{name:"Next",links:[{portIn:"Render",portOut:"Next",objIn:"xpc1395ps",objOut:"hukq16gfb"}]},{name:"Total Lines",value:1},{name:"Width",value:1.9696428042985665},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"rdwh4sw9i",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Text",value:"UMAS DEMOS PÁ..."},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:0},{name:"vertical align",value:"Top"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:2.420714242117746},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"oygx6jy24",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:-3.33},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"q2cysanok",objOut:"oygx6jy24"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"q2cysanok",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Text",value:"MAS PODIAS SACAR"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:2},{name:"vertical align",value:"Bottom"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1}],portsOut:[{name:"Next",links:[{portIn:"Render",portOut:"Next",objIn:"rdwh4sw9i",objOut:"q2cysanok"}]},{name:"Total Lines",value:1},{name:"Width",value:2.5678570900128532},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"ct57fprmg",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"time",portOut:"Value",objIn:"fq210ycn7",objOut:"ct57fprmg"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"fq210ycn7",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"sheet",value:"# nao sacarias um carro\n176. (0.qo)\n177. (1.li)\n183. (1.3qi)\n183.5 (0.)\n\n#nao sacarias uma telebisao\na2:\n184. (0.qo)\n185. (1.li)\n191. (1.3qi)\n191.5 (0.)\n\n#mas podias sacar umas demos\na3:\n192. (0.qo)\n193. (1.li)\n199. (1.3qi)\n199.5 (0.)\n\n#ver demos no youtube é um crime\na4:\n200. (0.qo)\n201. (1.li)\n205.9 (1.3)\n206. (0.)\n\n# crime\na5:\n0. (0.)\n206. (1.)\n"}],portsOut:[{name:"analog 1",links:[{portIn:"scale",portOut:"analog 1",objIn:"cjs2ikb69",objOut:"fq210ycn7"}]},{name:"analog 2",links:[{portIn:"scale",portOut:"analog 2",objIn:"dgpn9d6mz",objOut:"fq210ycn7"}]},{name:"analog 3",links:[{portIn:"scale",portOut:"analog 3",objIn:"oygx6jy24",objOut:"fq210ycn7"}]},{name:"analog 4",links:[{portIn:"scale",portOut:"analog 4",objIn:"yyni46vx6",objOut:"fq210ycn7"}]},{name:"analog 5",links:[{portIn:"amount",portOut:"analog 5",objIn:"7rxhdy1db",objOut:"fq210ycn7"}]},{name:"analog 6",value:0},{name:"analog 7",value:0},{name:"analog 8",value:0}],objName:"Ops.User.anticore.DopeSheet"},{id:"7rxhdy1db",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"blendMode index",value:9},{name:"blendMode",value:"negation"},{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}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"n3sitlvfj",uiAttribs:{subPatch:"wbx4aydb0"},portsIn:[{name:"File",value:"assets/crime.png",display:"file"},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{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:"Image",portOut:"Texture",objIn:"7rxhdy1db",objOut:"n3sitlvfj"}]},{name:"Width",value:1920},{name:"Height",value:1080},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"hnlfjei1d",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Variable",value:"randomVignetteTex"}],portsOut:[{name:"Value",links:[{portIn:"Texture 3",portOut:"Value",objIn:"35b1nvdq0",objOut:"hnlfjei1d"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"e3iw539wl",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Text",value:"COLORS"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:1},{name:"vertical align",value:"Middle"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:1.0603571309671775},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"vptq08uts",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"posX",value:1.9},{name:"posY",value:0},{name:"posZ",value:-2.22},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:-90.46}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"e3iw539wl",objOut:"vptq08uts"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"r68krm137",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Text",value:"CODER's"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:1},{name:"vertical align",value:"Middle"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1},{name:"a",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:1.165357119077212},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"yqtit3oh3",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"posX",value:-1.9},{name:"posY",value:0},{name:"posZ",value:-2.22},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:90}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"r68krm137",objOut:"yqtit3oh3"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"fwxn623ws",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Lens Distort",value:0},{name:"Smooth",value:0}],objName:"Ops.Gl.ImageCompose.ChromaticAberration_v2"},{id:"c37g3wfzq",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"number1",portOut:"Value",objIn:"af01vbb13",objOut:"c37g3wfzq"},{portIn:"time",portOut:"Value",objIn:"xg2crtrmb",objOut:"c37g3wfzq"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"af01vbb13",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"number2",value:8},{name:"pingpong",value:0}],portsOut:[{name:"result",links:[{portIn:"time",portOut:"result",objIn:"u11oye277",objOut:"af01vbb13"}]}],objName:"Ops.Math.Modulo"},{id:"u11oye277",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"sheet",value:"0. (0.)\n3. (0.qio)\n4. (1.)\n6. (1.qio)\n7. (0.)"}],portsOut:[{name:"analog 1",links:[{portIn:"number1",portOut:"analog 1",objIn:"pzbrsss59",objOut:"u11oye277"}]},{name:"analog 2",value:0},{name:"analog 3",value:0},{name:"analog 4",value:0},{name:"analog 5",value:0},{name:"analog 6",value:0},{name:"analog 7",value:0},{name:"analog 8",value:0}],objName:"Ops.User.anticore.DopeSheet"},{id:"pzbrsss59",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"number2",value:50}],portsOut:[{name:"result",links:[{portIn:"Pixel",portOut:"result",objIn:"qnrisvneg",objOut:"pzbrsss59"}]}],objName:"Ops.Math.Multiply"},{id:"fton5mbup",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"number2",value:70}],portsOut:[{name:"result",links:[{portIn:"Pixel",portOut:"result",objIn:"fwxn623ws",objOut:"fton5mbup"}]}],objName:"Ops.Math.Multiply"},{id:"xg2crtrmb",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"sheet",value:"228. (0.qio)\n236. (1.)"}],portsOut:[{name:"analog 1",links:[{portIn:"number1",portOut:"analog 1",objIn:"fton5mbup",objOut:"xg2crtrmb"}]},{name:"analog 2",value:0},{name:"analog 3",value:0},{name:"analog 4",value:0},{name:"analog 5",value:0},{name:"analog 6",value:0},{name:"analog 7",value:0},{name:"analog 8",value:0}],objName:"Ops.User.anticore.DopeSheet"},{id:"tgmifgjqw",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"time",portOut:"Value",objIn:"1s1o2qhu2",objOut:"tgmifgjqw"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"1s1o2qhu2",uiAttribs:{subPatch:"nfuzc9gb4"},portsIn:[{name:"sheet",value:"# anticore twist\n240. (55.qio)\n246. (-55.)\n250. (-55qio)\n260. (55.)\n\n# anticore pos\na2:\n256. (0.qio) (-2.37qio)\n258. (-1.57) (-6.62)\n\n# varrho pos\na4:\n256. (2.58qio) (3.qio)\n259. (0.72) (-2.25)\n\n# varrho twist\na6:\n256. (55.qio)\n264. (-55.)\n265. (-55qio)\n270. (85.)\n\n"}],portsOut:[{name:"analog 1",links:[{portIn:"Degree",portOut:"analog 1",objIn:"xhmy50ugb",objOut:"1s1o2qhu2"}]},{name:"analog 2",links:[{portIn:"posY",portOut:"analog 2",objIn:"42ohkjciz",objOut:"1s1o2qhu2"}]},{name:"analog 3",links:[{portIn:"posZ",portOut:"analog 3",objIn:"42ohkjciz",objOut:"1s1o2qhu2"}]},{name:"analog 4",links:[{portIn:"posY",portOut:"analog 4",objIn:"ttl8wprv7",objOut:"1s1o2qhu2"}]},{name:"analog 5",links:[{portIn:"posZ",portOut:"analog 5",objIn:"ttl8wprv7",objOut:"1s1o2qhu2"}]},{name:"analog 6",links:[{portIn:"Degree",portOut:"analog 6",objIn:"ybfohchdc",objOut:"1s1o2qhu2"}]},{name:"analog 7",value:0},{name:"analog 8",value:0}],objName:"Ops.User.anticore.DopeSheet"},{id:"2j1yd64fg",uiAttribs:{subPatch:"qjbpb8llo"},portsOut:[{name:"time",links:[{portIn:"number1",portOut:"time",objIn:"wwimp1p77",objOut:"2j1yd64fg"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"wwimp1p77",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"number2",value:60}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"xdb46nlvt",objOut:"wwimp1p77"}]}],objName:"Ops.Math.Multiply"},{id:"xdb46nlvt",uiAttribs:{subPatch:"qjbpb8llo"},portsIn:[{name:"number2",value:190.04}],portsOut:[{name:"result",links:[{portIn:"rotY",portOut:"result",objIn:"enzyzwdyx",objOut:"xdb46nlvt"}]}],objName:"Ops.Math.Sum"},{id:"69t0zyo8m",uiAttribs:{subPatch:"3da97ohdf"},portsOut:[{name:"create port",value:0},{name:"in0 Sequence exe",links:[{portIn:"exe",portOut:"in0 Sequence exe",objIn:"mnqwjqkmd",objOut:"69t0zyo8m"}]}],objName:"Ops.Ui.PatchInput"},{id:"7053gwvfm",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"mnqwjqkmd",uiAttribs:{subPatch:"3da97ohdf"},portsOut:[{name:"trigger 6",links:[{portIn:"exe",portOut:"trigger 6",objIn:"tmkjgcub7",objOut:"mnqwjqkmd"}]},{name:"trigger 8",links:[{portIn:"exe",portOut:"trigger 8",objIn:"xz48sz9sc",objOut:"mnqwjqkmd"}]},{name:"trigger 9",links:[{portIn:"Render",portOut:"trigger 9",objIn:"0id5ss92l",objOut:"mnqwjqkmd"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"o6enjm2m8",objOut:"mnqwjqkmd"}]}],objName:"Ops.Trigger.Sequence"},{id:"o6enjm2m8",uiAttribs:{subPatch:"3da97ohdf"},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:2},{name:"Wrap",value:"mirrored repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{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:"s3kkq7z2p",objOut:"o6enjm2m8"}]},{name:"texture_out",links:[{portIn:"Value",portOut:"texture_out",objIn:"06ioxs4ah",objOut:"o6enjm2m8"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"06ioxs4ah",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Variable",value:"sceneTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"s3kkq7z2p",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Mask Invert",value:0},{name:"Blendmode 1 index",value:0},{name:"Blendmode 1",value:"normal"},{name:"Mask Source 1 index",value:0},{name:"Mask Source 1",value:"R"},{name:"Opacity 1 index",value:0},{name:"Opacity 1",value:"Normal"},{name:"Amount 1",value:1},{name:"Blendmode 2 index",value:0},{name:"Blendmode 2",value:"normal"},{name:"Mask Source 2 index",value:0},{name:"Mask Source 2",value:"R"},{name:"Opacity 2 index",value:0},{name:"Opacity 2",value:"Normal"},{name:"Amount 2",value:1},{name:"Blendmode 3 index",value:0},{name:"Blendmode 3",value:"normal"},{name:"Mask Source 3 index",value:0},{name:"Mask Source 3",value:"R"},{name:"Opacity 3 index",value:0},{name:"Opacity 3",value:"Normal"},{name:"Amount 3",value:.88},{name:"Blendmode 4 index",value:11},{name:"Blendmode 4",value:"overlay"},{name:"Mask Source 4 index",value:0},{name:"Mask Source 4",value:"R"},{name:"Opacity 4 index",value:0},{name:"Opacity 4",value:"Normal"},{name:"Amount 4",value:1},{name:"Blendmode 5 index",value:3},{name:"Blendmode 5",value:"multiply"},{name:"Mask Source 5 index",value:0},{name:"Mask Source 5",value:"R"},{name:"Opacity 5 index",value:0},{name:"Opacity 5",value:"Normal"},{name:"Amount 5",value:1},{name:"Blendmode 6 index",value:0},{name:"Blendmode 6",value:"normal"},{name:"Mask Source 6 index",value:0},{name:"Mask Source 6",value:"R"},{name:"Opacity 6 index",value:0},{name:"Opacity 6",value:"Normal"},{name:"Amount 6",value:1},{name:"Blendmode 7 index",value:0},{name:"Blendmode 7",value:"normal"},{name:"Mask Source 7 index",value:0},{name:"Mask Source 7",value:"R"},{name:"Opacity 7 index",value:0},{name:"Opacity 7",value:"Normal"},{name:"Amount 7",value:1},{name:"Blendmode 8 index",value:0},{name:"Blendmode 8",value:"normal"},{name:"Mask Source 8 index",value:0},{name:"Mask Source 8",value:"R"},{name:"Opacity 8 index",value:0},{name:"Opacity 8",value:"Normal"},{name:"Amount 8",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"c4nhfnihb",objOut:"s3kkq7z2p"}]}],objName:"Ops.Gl.ImageCompose.MultiDrawImage"},{id:"0id5ss92l",uiAttribs:{subPatch:"3da97ohdf"},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:1},{name:"Wrap",value:"repeat"},{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:"texture_out",links:[{portIn:"Texture 1",portOut:"texture_out",objIn:"s3kkq7z2p",objOut:"0id5ss92l"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"tmkjgcub7",uiAttribs:{subPatch:"3da97ohdf"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"n68litaed",objOut:"tmkjgcub7"}]}],objName:"Ops.Trigger.Sequence"},{id:"n68litaed",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Canvas"},{name:"texture width",value:1920},{name:"texture height",value:1080},{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:0},{name:"MSAA",value:"none"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{name:"Depth",value:1},{name:"Clear",value:1}],portsOut:[{name:"texture",links:[{portIn:"Base Texture",portOut:"texture",objIn:"0id5ss92l",objOut:"n68litaed"}]}],objName:"Ops.Gl.RenderToTexture_v3"},{id:"2chnkyrwc",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Sequence exe","type":1}],"portsOut":[]}'},{name:"patchId",value:"3da97ohdf"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"o80jg1zjy",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"u6bxwbye4",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"data",value:""},{name:"glb File",value:"assets/64ac3bdb4bfdc7eab8130c83_arrow.glb",display:"file"},{name:"Draw",value:0},{name:"Camera index",value:0},{name:"Camera",value:"None"},{name:"Animation",value:""},{name:"Center index",value:1},{name:"Center",value:"XYZ"},{name:"Rescale",value:1},{name:"Rescale Size",value:2.5},{name:"Time",value:0},{name:"Sync to timeline",value:0},{name:"Loop",value:1},{name:"Normals Format index",value:0},{name:"Normals Format",value:"XYZ"},{name:"Vertices Format index",value:0},{name:"Vertices Format",value:"XYZ"},{name:"Calc Normals",value:0},{name:"Hide Nodes",value:0},{name:"Use Material Properties",value:0},{name:"Active",value:1}],portsOut:[{name:"Render Before",links:[{portIn:"render",portOut:"Render Before",objIn:"qmy57ielr",objOut:"u6bxwbye4"}]},{name:"Next",links:[{portIn:"Update",portOut:"Next",objIn:"r9eczrwoa",objOut:"u6bxwbye4"}]},{name:"Generator",value:"FBX2glTF v0.9.7"},{name:"GLTF Version",value:2},{name:"Anim Length",value:0},{name:"Anim Time",value:0},{name:"Loading",value:false}],objName:"Ops.Gl.GLTF.GltfScene_v3"},{id:"jleybbvsw",uiAttribs:{subPatch:"3da97ohdf"},portsOut:[{name:"trigger 0",links:[{portIn:"Trigger In",portOut:"trigger 0",objIn:"xoqm446e8",objOut:"jleybbvsw"}]},{name:"trigger 1",links:[{portIn:"Trigger In",portOut:"trigger 1",objIn:"94hnw1gcf",objOut:"jleybbvsw"}]},{name:"trigger 4",links:[{portIn:"Render",portOut:"trigger 4",objIn:"ys27xqdqm",objOut:"jleybbvsw"}]},{name:"trigger 9",links:[{portIn:"Render",portOut:"trigger 9",objIn:"4t9h2ny83",objOut:"jleybbvsw"}]},{name:"trigger 12",links:[{portIn:"Render",portOut:"trigger 12",objIn:"y0cnxszpc",objOut:"jleybbvsw"}]}],objName:"Ops.Trigger.Sequence"},{id:"sm5r4qlrd",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Canvas"},{name:"texture width",value:1920},{name:"texture height",value:1080},{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:0},{name:"MSAA",value:"none"},{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:"rikije2bc",objOut:"sm5r4qlrd"}]},{name:"texture",links:[{portIn:"Image",portOut:"texture",objIn:"8z14odb4y",objOut:"sm5r4qlrd"},{portIn:"Base Texture",portOut:"texture",objIn:"yd2rccnqy",objOut:"sm5r4qlrd"}]},{name:"textureDepth",links:[{portIn:"Depth Texture",portOut:"textureDepth",objIn:"910q3n1ha",objOut:"sm5r4qlrd"},{portIn:"Depth Texture",portOut:"textureDepth",objIn:"uyo3tdejz",objOut:"sm5r4qlrd"}]}],objName:"Ops.Gl.RenderToTexture_v3"},{id:"xz48sz9sc",uiAttribs:{subPatch:"3da97ohdf"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"sm5r4qlrd",objOut:"xz48sz9sc"}]},{name:"trigger 1",links:[{portIn:"Trigger in",portOut:"trigger 1",objIn:"i23ozkzr9",objOut:"xz48sz9sc"}]},{name:"trigger 8",links:[{portIn:"Render",portOut:"trigger 8",objIn:"yd2rccnqy",objOut:"xz48sz9sc"}]},{name:"trigger 10",links:[{portIn:"Render",portOut:"trigger 10",objIn:"bt4qunx9i",objOut:"xz48sz9sc"}]},{name:"trigger 12",links:[{portIn:"Render",portOut:"trigger 12",objIn:"7rl9lwsdw",objOut:"xz48sz9sc"}]},{name:"trigger 14",links:[{portIn:"Render",portOut:"trigger 14",objIn:"inucjjol3",objOut:"xz48sz9sc"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"pydliatj7",objOut:"xz48sz9sc"}]}],objName:"Ops.Trigger.Sequence"},{id:"pydliatj7",uiAttribs:{subPatch:"3da97ohdf"},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:1},{name:"Wrap",value:"repeat"},{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:"8z14odb4y",objOut:"pydliatj7"}]},{name:"texture_out",links:[{portIn:"Texture 2",portOut:"texture_out",objIn:"s3kkq7z2p",objOut:"pydliatj7"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"8z14odb4y",uiAttribs:{subPatch:"3da97ohdf"},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:"910q3n1ha",objOut:"8z14odb4y"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"r9eczrwoa",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Name",value:"arrow"},{name:"Submesh",value:0}],portsOut:[{name:"Geometry",links:[{portIn:"Geometry",portOut:"Geometry",objIn:"t00l9j9sg",objOut:"r9eczrwoa"}]},{name:"Found",value:1}],objName:"Ops.Gl.GLTF.GltfGeometry"},{id:"ye4572c1r",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Scale",value:1},{name:"Limit Instances",value:0},{name:"Limit",value:100},{name:"Rotation Type index",value:0},{name:"Rotation Type",value:"Euler"},{name:"Billboarding index",value:0},{name:"Billboarding",value:"Off"},{name:"Material blend mode index",value:0},{name:"Material blend mode",value:"Multiply"},{name:"Colors",value:0},{name:"TexCoords",value:0}],portsOut:[{name:"Num",value:160}],objName:"Ops.Gl.MeshInstancer_v4"},{id:"t00l9j9sg",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Scale",value:11.05}],portsOut:[{name:"Result",links:[{portIn:"geom",portOut:"Result",objIn:"ye4572c1r",objOut:"t00l9j9sg"}]}],objName:"Ops.Graphics.Geometry.ScaleGeometry"},{id:"rikije2bc",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"posX",value:-12.37},{name:"posY",value:0},{name:"posZ",value:-4.46},{name:"scale",value:1},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"exe",portOut:"trigger",objIn:"jleybbvsw",objOut:"rikije2bc"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"0xx0sbcq1",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"value",value:160}],portsOut:[{name:"result",links:[{portIn:"Num Values",portOut:"result",objIn:"a0tljpnoh",objOut:"0xx0sbcq1"},{portIn:"Num Values",portOut:"result",objIn:"q8tva8wot",objOut:"0xx0sbcq1"},{portIn:"Num Values",portOut:"result",objIn:"pd0ofye0q",objOut:"0xx0sbcq1"},{portIn:"Num Values",portOut:"result",objIn:"61ybl12k6",objOut:"0xx0sbcq1"},{portIn:"Num Values",portOut:"result",objIn:"rx5tro22n",objOut:"0xx0sbcq1"}]}],objName:"Ops.Number.Number"},{id:"56gzwfwxh",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"number2",value:10}],portsOut:[{name:"result",links:[{portIn:"rotX",portOut:"result",objIn:"rikije2bc",objOut:"56gzwfwxh"}]}],objName:"Ops.Math.Multiply"},{id:"zoapd8vv8",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"File",value:"assets/64ac3bdb4bfdc7eab8130c83_pink-2.png",display:"file"},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{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:"Base Texture",portOut:"Texture",objIn:"bt4qunx9i",objOut:"zoapd8vv8"}]},{name:"Width",value:64},{name:"Height",value:64},{name:"Aspect Ratio",value:1},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"a0tljpnoh",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"A"},{name:"Random Seed ",value:0},{name:"Integer",value:0},{name:"Last == First",value:0},{name:"Min A",value:0},{name:"Max A",value:6},{name:"Min B",value:-1},{name:"Max B",value:1},{name:"Min C",value:-1},{name:"Max C",value:1},{name:"Min D",value:-1},{name:"Max D",value:1}],portsOut:[{name:"Array Out",links:[{portIn:"A",portOut:"Array Out",objIn:"ovnlop7xk",objOut:"a0tljpnoh"}]},{name:"Chunks Amount",value:160},{name:"Array length",value:160}],objName:"Ops.Array.RandomNumbersArray_v4"},{id:"q8tva8wot",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"A"},{name:"Random Seed ",value:0},{name:"Integer",value:0},{name:"Last == First",value:0},{name:"Min A",value:-1},{name:"Max A",value:1},{name:"Min B",value:-1},{name:"Max B",value:1},{name:"Min C",value:-1},{name:"Max C",value:1},{name:"Min D",value:-1},{name:"Max D",value:1}],portsOut:[{name:"Array Out",links:[{portIn:"Array 2",portOut:"Array Out",objIn:"e7qewefqn",objOut:"q8tva8wot"}]},{name:"Chunks Amount",value:160},{name:"Array length",value:160}],objName:"Ops.Array.RandomNumbersArray_v4"},{id:"pd0ofye0q",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"A"},{name:"Random Seed ",value:0},{name:"Integer",value:0},{name:"Last == First",value:0},{name:"Min A",value:-1},{name:"Max A",value:1},{name:"Min B",value:-1},{name:"Max B",value:1},{name:"Min C",value:-1},{name:"Max C",value:1},{name:"Min D",value:-1},{name:"Max D",value:1}],portsOut:[{name:"Array Out",links:[{portIn:"Array 3",portOut:"Array Out",objIn:"e7qewefqn",objOut:"pd0ofye0q"}]},{name:"Chunks Amount",value:160},{name:"Array length",value:160}],objName:"Ops.Array.RandomNumbersArray_v4"},{id:"e7qewefqn",uiAttribs:{subPatch:"3da97ohdf"},portsOut:[{name:"Array out",links:[{portIn:"positions",portOut:"Array out",objIn:"ye4572c1r",objOut:"e7qewefqn"}]},{name:"Num Points",value:160},{name:"Array length",value:480}],objName:"Ops.Array.ArrayPack3Simple"},{id:"61ybl12k6",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"A"},{name:"Random Seed ",value:0},{name:"Integer",value:0},{name:"Last == First",value:0},{name:"Min A",value:2},{name:"Max A",value:4},{name:"Min B",value:-1},{name:"Max B",value:1},{name:"Min C",value:-1},{name:"Max C",value:1},{name:"Min D",value:-1},{name:"Max D",value:1}],portsOut:[{name:"Array Out",links:[{portIn:"Array1x",portOut:"Array Out",objIn:"zhp2l1n57",objOut:"61ybl12k6"}]},{name:"Chunks Amount",value:160},{name:"Array length",value:160}],objName:"Ops.Array.RandomNumbersArray_v4"},{id:"zhp2l1n57",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Format index",value:1},{name:"Format",value:"ABC"},{name:"A index",value:0},{name:"A",value:"Input"},{name:"B index",value:0},{name:"B",value:"Input"},{name:"C index",value:0},{name:"C",value:"Input"},{name:"D index",value:4},{name:"D",value:"0"}],portsOut:[{name:"Array3x",links:[{portIn:"Scale Array",portOut:"Array3x",objIn:"ye4572c1r",objOut:"zhp2l1n57"}]},{name:"Total points",value:160},{name:"Array length",value:480}],objName:"Ops.Array.Array1toX"},{id:"ovnlop7xk",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"B",value:0},{name:"C",value:0},{name:"Y",value:6},{name:"Z",value:1},{name:"Expression",value:"(a+x)%y"}],portsOut:[{name:"Result Array",links:[{portIn:"Array 1",portOut:"Result Array",objIn:"e7qewefqn",objOut:"ovnlop7xk"}]},{name:"Array Length",value:160},{name:"Expression Valid",value:1}],objName:"Ops.Array.ArrayMathExpression"},{id:"910q3n1ha",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"blendMode index",value:0},{name:"blendMode",value:"normal"},{name:"Amount",value:1},{name:"Fog Start",value:1},{name:"Fog End",value:7.18},{name:"Fog Density",value:1},{name:"Ignore Infinity",value:0},{name:"nearplane",value:.1},{name:"farplane",value:10},{name:"Fog R",value:1},{name:"Fog G",value:1},{name:"Fog B",value:1},{name:"Fog A",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"3f5vjjujm",objOut:"910q3n1ha"}]}],objName:"Ops.Gl.ImageCompose.Fog_v4"},{id:"inucjjol3",uiAttribs:{subPatch:"3da97ohdf"},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:1},{name:"Wrap",value:"repeat"},{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:"zsbzdwfrs",objOut:"inucjjol3"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"8edkzqswh",objOut:"inucjjol3"},{portIn:"Background Texture",portOut:"texture_out",objIn:"910q3n1ha",objOut:"inucjjol3"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"8edkzqswh",uiAttribs:{subPatch:"3da97ohdf"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"rx5tro22n",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"A"},{name:"Random Seed ",value:0},{name:"Integer",value:0},{name:"Last == First",value:0},{name:"Min A",value:0},{name:"Max A",value:360},{name:"Min B",value:-1},{name:"Max B",value:1},{name:"Min C",value:-1},{name:"Max C",value:1},{name:"Min D",value:-1},{name:"Max D",value:1}],portsOut:[{name:"Array Out",links:[{portIn:"In",portOut:"Array Out",objIn:"lr5wgc5ve",objOut:"rx5tro22n"}]},{name:"Chunks Amount",value:160},{name:"Array length",value:160}],objName:"Ops.Array.RandomNumbersArray_v4"},{id:"lr5wgc5ve",uiAttribs:{subPatch:"3da97ohdf"},portsOut:[{name:"Result",links:[{portIn:"Array1x",portOut:"Result",objIn:"5ibn6vr81",objOut:"lr5wgc5ve"}]}],objName:"Ops.Array.ArraySum"},{id:"5ibn6vr81",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Format index",value:1},{name:"Format",value:"ABC"},{name:"A index",value:0},{name:"A",value:"Input"},{name:"B index",value:5},{name:"B",value:"1"},{name:"C index",value:5},{name:"C",value:"1"},{name:"D index",value:5},{name:"D",value:"1"}],portsOut:[{name:"Array3x",links:[{portIn:"Rotations",portOut:"Array3x",objIn:"ye4572c1r",objOut:"5ibn6vr81"}]},{name:"Total points",value:160},{name:"Array length",value:480}],objName:"Ops.Array.Array1toX"},{id:"86qkj6qi3",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Scale",value:4},{name:"Size",value:1},{name:"Strength",value:.07},{name:"Calc Normals",value:0},{name:"Flip Normals",value:0},{name:"Falloff",value:1},{name:"Output index",value:5},{name:"Output",value:"Add XYZ"},{name:"Source index",value:1},{name:"Source",value:"Orig Pos"},{name:"x",value:0},{name:"y",value:0},{name:"z",value:0},{name:"Scroll Y",value:0},{name:"Scroll Z",value:0},{name:"WorldSpace",value:0}],portsOut:[{name:"trigger",links:[{portIn:"exe",portOut:"trigger",objIn:"ye4572c1r",objOut:"86qkj6qi3"}]}],objName:"Ops.Gl.ShaderEffects.PerlinAreaDeform_v4"},{id:"0z71v9qlx",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"data",value:""},{name:"glb File",value:"assets/64ac3bdb4bfdc7eab8130c83_arrow.glb",display:"file"},{name:"Draw",value:0},{name:"Camera index",value:0},{name:"Camera",value:"None"},{name:"Animation",value:""},{name:"Center index",value:1},{name:"Center",value:"XYZ"},{name:"Rescale",value:1},{name:"Rescale Size",value:2.5},{name:"Time",value:0},{name:"Sync to timeline",value:0},{name:"Loop",value:1},{name:"Normals Format index",value:0},{name:"Normals Format",value:"XYZ"},{name:"Vertices Format index",value:0},{name:"Vertices Format",value:"XYZ"},{name:"Calc Normals",value:0},{name:"Hide Nodes",value:0},{name:"Use Material Properties",value:0},{name:"Active",value:1}],portsOut:[{name:"Render Before",links:[{portIn:"render",portOut:"Render Before",objIn:"v64zdijjj",objOut:"0z71v9qlx"}]},{name:"Next",links:[{portIn:"Update",portOut:"Next",objIn:"tlrg1hj8r",objOut:"0z71v9qlx"}]},{name:"Generator",value:"FBX2glTF v0.9.7"},{name:"GLTF Version",value:2},{name:"Anim Length",value:0},{name:"Anim Time",value:0},{name:"Loading",value:false}],objName:"Ops.Gl.GLTF.GltfScene_v3"},{id:"tlrg1hj8r",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Name",value:"arrow"},{name:"Submesh",value:0}],portsOut:[{name:"Geometry",links:[{portIn:"Geometry",portOut:"Geometry",objIn:"27mq2agrz",objOut:"tlrg1hj8r"}]},{name:"Found",value:1}],objName:"Ops.Gl.GLTF.GltfGeometry"},{id:"k5gvb4w76",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Scale",value:1},{name:"Limit Instances",value:0},{name:"Limit",value:100},{name:"Rotation Type index",value:0},{name:"Rotation Type",value:"Euler"},{name:"Billboarding index",value:0},{name:"Billboarding",value:"Off"},{name:"Material blend mode index",value:0},{name:"Material blend mode",value:"Multiply"},{name:"Colors",value:0},{name:"TexCoords",value:0}],portsOut:[{name:"Num",value:250}],objName:"Ops.Gl.MeshInstancer_v4"},{id:"27mq2agrz",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Scale",value:11.05}],portsOut:[{name:"Result",links:[{portIn:"geom",portOut:"Result",objIn:"k5gvb4w76",objOut:"27mq2agrz"}]}],objName:"Ops.Graphics.Geometry.ScaleGeometry"},{id:"9il4bkduk",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"File",value:"assets/64ac3bdb4bfdc7eab8130c83_pink-2.png",display:"file"},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{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:"Base Texture",portOut:"Texture",objIn:"y0cnxszpc",objOut:"9il4bkduk"}]},{name:"Width",value:64},{name:"Height",value:64},{name:"Aspect Ratio",value:1},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"v64zdijjj",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Scale",value:5},{name:"Size",value:1},{name:"Strength",value:.05},{name:"Calc Normals",value:1},{name:"Flip Normals",value:0},{name:"Falloff",value:1},{name:"Output index",value:5},{name:"Output",value:"Add XYZ"},{name:"Source index",value:1},{name:"Source",value:"Orig Pos"},{name:"x",value:0},{name:"y",value:0},{name:"z",value:0},{name:"Scroll Y",value:0},{name:"Scroll Z",value:0},{name:"WorldSpace",value:0}],portsOut:[{name:"trigger",links:[{portIn:"exe",portOut:"trigger",objIn:"k5gvb4w76",objOut:"v64zdijjj"}]}],objName:"Ops.Gl.ShaderEffects.PerlinAreaDeform_v4"},{id:"76hszfcrm",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"value",value:250}],portsOut:[{name:"result",links:[{portIn:"Num Values",portOut:"result",objIn:"pq3wydbmz",objOut:"76hszfcrm"},{portIn:"Num Values",portOut:"result",objIn:"ftc7peiei",objOut:"76hszfcrm"},{portIn:"Num Values",portOut:"result",objIn:"xztbizj0c",objOut:"76hszfcrm"},{portIn:"Num Values",portOut:"result",objIn:"oypid806h",objOut:"76hszfcrm"},{portIn:"Num Values",portOut:"result",objIn:"vo4vpdhw9",objOut:"76hszfcrm"}]}],objName:"Ops.Number.Number"},{id:"pq3wydbmz",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"A"},{name:"Random Seed ",value:0},{name:"Integer",value:0},{name:"Last == First",value:0},{name:"Min A",value:0},{name:"Max A",value:6},{name:"Min B",value:-1},{name:"Max B",value:1},{name:"Min C",value:-1},{name:"Max C",value:1},{name:"Min D",value:-1},{name:"Max D",value:1}],portsOut:[{name:"Array Out",links:[{portIn:"A",portOut:"Array Out",objIn:"rrm6rljnr",objOut:"pq3wydbmz"}]},{name:"Chunks Amount",value:250},{name:"Array length",value:250}],objName:"Ops.Array.RandomNumbersArray_v4"},{id:"ftc7peiei",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"A"},{name:"Random Seed ",value:0},{name:"Integer",value:0},{name:"Last == First",value:0},{name:"Min A",value:-1},{name:"Max A",value:1},{name:"Min B",value:-1},{name:"Max B",value:1},{name:"Min C",value:-1},{name:"Max C",value:1},{name:"Min D",value:-1},{name:"Max D",value:1}],portsOut:[{name:"Array Out",links:[{portIn:"Array 2",portOut:"Array Out",objIn:"8v7qydpoq",objOut:"ftc7peiei"}]},{name:"Chunks Amount",value:250},{name:"Array length",value:250}],objName:"Ops.Array.RandomNumbersArray_v4"},{id:"xztbizj0c",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"A"},{name:"Random Seed ",value:0},{name:"Integer",value:0},{name:"Last == First",value:0},{name:"Min A",value:-1},{name:"Max A",value:1},{name:"Min B",value:-1},{name:"Max B",value:1},{name:"Min C",value:-1},{name:"Max C",value:1},{name:"Min D",value:-1},{name:"Max D",value:1}],portsOut:[{name:"Array Out",links:[{portIn:"Array 3",portOut:"Array Out",objIn:"8v7qydpoq",objOut:"xztbizj0c"}]},{name:"Chunks Amount",value:250},{name:"Array length",value:250}],objName:"Ops.Array.RandomNumbersArray_v4"},{id:"8v7qydpoq",uiAttribs:{subPatch:"3da97ohdf"},portsOut:[{name:"Array out",links:[{portIn:"positions",portOut:"Array out",objIn:"k5gvb4w76",objOut:"8v7qydpoq"}]},{name:"Num Points",value:250},{name:"Array length",value:750}],objName:"Ops.Array.ArrayPack3Simple"},{id:"oypid806h",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"A"},{name:"Random Seed ",value:0},{name:"Integer",value:0},{name:"Last == First",value:0},{name:"Min A",value:1},{name:"Max A",value:3},{name:"Min B",value:-1},{name:"Max B",value:1},{name:"Min C",value:-1},{name:"Max C",value:1},{name:"Min D",value:-1},{name:"Max D",value:1}],portsOut:[{name:"Array Out",links:[{portIn:"Array1x",portOut:"Array Out",objIn:"jfrj2i88x",objOut:"oypid806h"}]},{name:"Chunks Amount",value:250},{name:"Array length",value:250}],objName:"Ops.Array.RandomNumbersArray_v4"},{id:"jfrj2i88x",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Format index",value:1},{name:"Format",value:"ABC"},{name:"A index",value:0},{name:"A",value:"Input"},{name:"B index",value:0},{name:"B",value:"Input"},{name:"C index",value:0},{name:"C",value:"Input"},{name:"D index",value:4},{name:"D",value:"0"}],portsOut:[{name:"Array3x",links:[{portIn:"Scale Array",portOut:"Array3x",objIn:"k5gvb4w76",objOut:"jfrj2i88x"}]},{name:"Total points",value:250},{name:"Array length",value:750}],objName:"Ops.Array.Array1toX"},{id:"rrm6rljnr",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"B",value:0},{name:"C",value:0},{name:"Y",value:6},{name:"Z",value:1},{name:"Expression",value:"(a+x)%y"}],portsOut:[{name:"Result Array",links:[{portIn:"Array 1",portOut:"Result Array",objIn:"8v7qydpoq",objOut:"rrm6rljnr"}]},{name:"Array Length",value:250},{name:"Expression Valid",value:1}],objName:"Ops.Array.ArrayMathExpression"},{id:"vo4vpdhw9",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Mode index",value:0},{name:"Mode",value:"A"},{name:"Random Seed ",value:0},{name:"Integer",value:0},{name:"Last == First",value:0},{name:"Min A",value:0},{name:"Max A",value:360},{name:"Min B",value:-1},{name:"Max B",value:1},{name:"Min C",value:-1},{name:"Max C",value:1},{name:"Min D",value:-1},{name:"Max D",value:1}],portsOut:[{name:"Array Out",links:[{portIn:"In",portOut:"Array Out",objIn:"olbuthv3m",objOut:"vo4vpdhw9"}]},{name:"Chunks Amount",value:250},{name:"Array length",value:250}],objName:"Ops.Array.RandomNumbersArray_v4"},{id:"olbuthv3m",uiAttribs:{subPatch:"3da97ohdf"},portsOut:[{name:"Result",links:[{portIn:"Array1x",portOut:"Result",objIn:"12q99nvft",objOut:"olbuthv3m"}]}],objName:"Ops.Array.ArraySum"},{id:"12q99nvft",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Format index",value:1},{name:"Format",value:"ABC"},{name:"A index",value:0},{name:"A",value:"Input"},{name:"B index",value:5},{name:"B",value:"1"},{name:"C index",value:5},{name:"C",value:"1"},{name:"D index",value:5},{name:"D",value:"1"}],portsOut:[{name:"Array3x",links:[{portIn:"Rotations",portOut:"Array3x",objIn:"k5gvb4w76",objOut:"12q99nvft"}]},{name:"Total points",value:250},{name:"Array length",value:750}],objName:"Ops.Array.Array1toX"},{id:"y0cnxszpc",uiAttribs:{subPatch:"3da97ohdf"},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:1},{name:"Wrap",value:"repeat"},{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:"29mjhtufj",objOut:"y0cnxszpc"}]},{name:"texture_out",links:[{portIn:"Environment Map",portOut:"texture_out",objIn:"94hnw1gcf",objOut:"y0cnxszpc"}]},{name:"Aspect Ratio",value:1},{name:"Texture Width",value:64},{name:"Texture Height",value:64}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"29mjhtufj",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"hue",value:.065}],objName:"Ops.Gl.ImageCompose.Hue"},{id:"94hnw1gcf",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"R",value:0},{name:"G",value:0},{name:"B",value:0},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.6474170557940231},{name:"Emissive G",value:.9707351211112594},{name:"Emissive B",value:.13778167892179272},{name:"Shininess",value:4},{name:"Specular Amount",value:.5},{name:"Specular Model index",value:0},{name:"Specular Model",value:"Blinn"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:1},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Trigger Out",links:[{portIn:"render",portOut:"Trigger Out",objIn:"r2tfjztum",objOut:"94hnw1gcf"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"3s17vlmep",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Mask Invert",value:0},{name:"r",value:.18854166666666672},{name:"g",value:.18854166666666672},{name:"b",value:.18854166666666672},{name:"A",value:1}],objName:"Ops.Gl.ImageCompose.Color_v2"},{id:"oue6bxvdc",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"number2",value:-.4}],portsOut:[{name:"result",value:-45.05044}],objName:"Ops.Math.Multiply"},{id:"7rl9lwsdw",uiAttribs:{subPatch:"3da97ohdf"},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:1},{name:"Wrap",value:"repeat"},{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:"uyo3tdejz",objOut:"7rl9lwsdw"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"01b5gfeu4",objOut:"7rl9lwsdw"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"uyo3tdejz",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Focus",value:3.46},{name:"Width",value:4.79},{name:"Invert",value:1},{name:"nearplane",value:.1},{name:"farplane",value:100}],objName:"Ops.Gl.ImageCompose.DepthTextureFocus_v2"},{id:"01b5gfeu4",uiAttribs:{subPatch:"3da97ohdf"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"xoqm446e8",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"R",value:0},{name:"G",value:0},{name:"B",value:0},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.7599581892979923},{name:"Emissive G",value:.1719505088347546},{name:"Emissive B",value:.8011584447533793},{name:"Shininess",value:4},{name:"Specular Amount",value:.5},{name:"Specular Model index",value:0},{name:"Specular Model",value:"Blinn"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:1},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Trigger Out",links:[{portIn:"Render",portOut:"Trigger Out",objIn:"u6bxwbye4",objOut:"xoqm446e8"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"r2tfjztum",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"blendMode index",value:0},{name:"blendMode",value:"normal"},{name:"Amount",value:1},{name:"Target index",value:2},{name:"Target",value:"Alpha"},{name:"Scale",value:1},{name:"Use Texture Alpha",value:0},{name:"Pos X",value:0},{name:"Pos Y",value:0},{name:"Rot X",value:0},{name:"Rot Y",value:0},{name:"Rot Z",value:0},{name:"Mapping index",value:4},{name:"Mapping",value:"Screen"},{name:"Discard",value:0},{name:"WorldSpace",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"0z71v9qlx",objOut:"r2tfjztum"}]}],objName:"Ops.Gl.ShaderEffects.TextureProjection_v2"},{id:"4t9h2ny83",uiAttribs:{subPatch:"3da97ohdf"},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:1},{name:"Wrap",value:"repeat"},{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:"y0uzmn22c",objOut:"4t9h2ny83"}]},{name:"texture_out",links:[{portIn:"Texture",portOut:"texture_out",objIn:"r2tfjztum",objOut:"4t9h2ny83"},{portIn:"Texture",portOut:"texture_out",objIn:"qmy57ielr",objOut:"4t9h2ny83"},{portIn:"Image",portOut:"texture_out",objIn:"oybtcc232",objOut:"4t9h2ny83"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"y0uzmn22c",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Num",value:28.49},{name:"Width",value:.9},{name:"Rotate",value:.187},{name:"Gradients",value:0},{name:"Circular",value:0},{name:"Invert",value:0},{name:"r",value:.9996875},{name:"g",value:.9996875},{name:"b",value:.9996875}],objName:"Ops.Gl.ImageCompose.Stripes_v4"},{id:"qmy57ielr",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"blendMode index",value:0},{name:"blendMode",value:"normal"},{name:"Amount",value:1},{name:"Target index",value:0},{name:"Target",value:"Color"},{name:"Scale",value:1},{name:"Use Texture Alpha",value:0},{name:"Pos X",value:0},{name:"Pos Y",value:0},{name:"Rot X",value:0},{name:"Rot Y",value:0},{name:"Rot Z",value:0},{name:"Mapping index",value:4},{name:"Mapping",value:"Screen"},{name:"Discard",value:0},{name:"WorldSpace",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"86qkj6qi3",objOut:"qmy57ielr"}]}],objName:"Ops.Gl.ShaderEffects.TextureProjection_v2"},{id:"bt4qunx9i",uiAttribs:{subPatch:"3da97ohdf"},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:1},{name:"Wrap",value:"repeat"},{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:"33bmbitxu",objOut:"bt4qunx9i"}]},{name:"texture_out",links:[{portIn:"Environment Map",portOut:"texture_out",objIn:"xoqm446e8",objOut:"bt4qunx9i"}]},{name:"Aspect Ratio",value:1},{name:"Texture Width",value:64},{name:"Texture Height",value:64}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"33bmbitxu",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"hue",value:.19}],objName:"Ops.Gl.ImageCompose.Hue"},{id:"71x01q8on",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"number2",value:.1}],portsOut:[{name:"result",links:[{portIn:"Offset",portOut:"result",objIn:"y0uzmn22c",objOut:"71x01q8on"}]}],objName:"Ops.Math.Multiply"},{id:"ys27xqdqm",uiAttribs:{subPatch:"3da97ohdf"},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:1},{name:"Wrap",value:"repeat"},{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:"or3bmk850",objOut:"ys27xqdqm"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"or3bmk850",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Num",value:28.49},{name:"Width",value:.9},{name:"Rotate",value:.293},{name:"Gradients",value:0},{name:"Circular",value:0},{name:"Invert",value:0},{name:"r",value:.9996875},{name:"g",value:.9996875},{name:"b",value:.9996875}],objName:"Ops.Gl.ImageCompose.Stripes_v4"},{id:"5cx49tao2",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"number1",value:1},{name:"number2",value:.1}],portsOut:[{name:"result",links:[{portIn:"Offset",portOut:"result",objIn:"or3bmk850",objOut:"5cx49tao2"}]}],objName:"Ops.Math.Multiply"},{id:"oybtcc232",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"blendMode index",value:4},{name:"blendMode",value:"multiply invert"},{name:"amount",value:.129},{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}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"3f5vjjujm",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Blend Mode index",value:17},{name:"Blend Mode",value:"subtract one"},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Amount",value:.191},{name:"Animated",value:1},{name:"RGB",value:0},{name:"Normalize",value:0}],portsOut:[{name:"Next",links:[{portIn:"render",portOut:"Next",objIn:"f6i7gejnt",objOut:"3f5vjjujm"}]}],objName:"Ops.Team.Mdlviz_a0rO0B.CustomNoise"},{id:"yd2rccnqy",uiAttribs:{subPatch:"3da97ohdf"},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:1},{name:"Wrap",value:"repeat"},{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:"h2atsvvlp",objOut:"yd2rccnqy"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"riylcph8d",objOut:"yd2rccnqy"},{portIn:"Image",portOut:"texture_out",objIn:"f6i7gejnt",objOut:"yd2rccnqy"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"riylcph8d",uiAttribs:{subPatch:"3da97ohdf"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"h2atsvvlp",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Blend Mode index",value:1},{name:"Blend Mode",value:"lighten"},{name:"Amount",value:1},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Mask Invert",value:0},{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"A",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"5elcyqko2",objOut:"h2atsvvlp"}]}],objName:"Ops.Gl.ImageCompose.Color_v2"},{id:"5elcyqko2",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Invert",value:0},{name:"Black White",value:0},{name:"Threshold low ",value:1},{name:"Threshold high",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"r5pzvyey6",objOut:"5elcyqko2"}]}],objName:"Ops.Gl.ImageCompose.LumaKey_v2"},{id:"r5pzvyey6",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Blend Mode index",value:1},{name:"Blend Mode",value:"lighten"},{name:"Amount",value:1},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Mask Invert",value:0},{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"A",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"xcsg1c658",objOut:"r5pzvyey6"}]}],objName:"Ops.Gl.ImageCompose.Color_v2"},{id:"xcsg1c658",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Pixel",value:5},{name:"Lens Distort",value:0},{name:"Smooth",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"l8d61hdno",objOut:"xcsg1c658"}]}],objName:"Ops.Gl.ImageCompose.ChromaticAberration_v2"},{id:"l8d61hdno",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Blend Mode index",value:3},{name:"Blend Mode",value:"multiply"},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Amount",value:.631},{name:"Animated",value:1},{name:"RGB",value:0},{name:"Normalize",value:0}],portsOut:[{name:"Next",links:[{portIn:"render",portOut:"Next",objIn:"48eyrn1vd",objOut:"l8d61hdno"}]}],objName:"Ops.Team.Mdlviz_a0rO0B.CustomNoise"},{id:"f6i7gejnt",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"blendMode index",value:6},{name:"blendMode",value:"add"},{name:"amount",value:.617},{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:"gad5409qw",objOut:"f6i7gejnt"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"48eyrn1vd",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"amount",value:.988},{name:"Lumi Scale",value:.9},{name:"X or Y",value:0},{name:"Line Size",value:4},{name:"Displacement",value:0},{name:"Add",value:.02},{name:"scroll",value:0}],objName:"Ops.Gl.ImageCompose.Interlace"},{id:"gad5409qw",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"contrast",value:.557},{name:"brightness",value:.745}],objName:"Ops.Gl.ImageCompose.BrightnessContrast"},{id:"12zrr5t25",uiAttribs:{subPatch:"3da97ohdf"},portsOut:[{name:"time",links:[{portIn:"number1",portOut:"time",objIn:"mrmjxwjgq",objOut:"12zrr5t25"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"zsbzdwfrs",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"blendMode index",value:1},{name:"blendMode",value:"lighten"},{name:"amount",value:.783},{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:"725a64u0e",objOut:"zsbzdwfrs"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"ossc7mqtg",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Variable",value:"stationTex"}],portsOut:[{name:"Value",links:[{portIn:"Image",portOut:"Value",objIn:"zsbzdwfrs",objOut:"ossc7mqtg"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"0cgpevmj3",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"amount",value:1},{name:"Invert Mask",value:0}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"ic2plnbpi",objOut:"0cgpevmj3"}]}],objName:"Ops.Gl.ImageCompose.Desaturate"},{id:"725a64u0e",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Strength",value:.354},{name:"Samples",value:40},{name:"X",value:0},{name:"Y",value:0},{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:"0cgpevmj3",objOut:"725a64u0e"}]}],objName:"Ops.Gl.ImageCompose.ZoomBlur_v2"},{id:"ic2plnbpi",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"blendMode index",value:3},{name:"blendMode",value:"multiply"},{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:"oybtcc232",objOut:"ic2plnbpi"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"0cnr1m3ga",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Variable",value:"randomVignetteTex2"}],portsOut:[{name:"Value",links:[{portIn:"Image",portOut:"Value",objIn:"ic2plnbpi",objOut:"0cnr1m3ga"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"c4nhfnihb",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"amount",value:2.14},{name:"direction index",value:0},{name:"direction",value:"both"},{name:"Fast",value:1}],objName:"Ops.Gl.ImageCompose.Blur"},{id:"k3x7cc7rz",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Variable",value:"invertedVignette"}],portsOut:[{name:"Value",links:[{portIn:"mask",portOut:"Value",objIn:"c4nhfnihb",objOut:"k3x7cc7rz"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"m6jatb7el",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Variable",value:"fftHighs"}],portsOut:[{name:"Value",links:[{portIn:"Add to number",portOut:"Value",objIn:"i23ozkzr9",objOut:"m6jatb7el"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"i23ozkzr9",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"Multiplier to add number",value:.2},{name:"Default Value",value:1}],portsOut:[{name:"Current value",value:59.22929174617011}],objName:"Ops.Math.Accumulator"},{id:"cf4c0tnvd",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"number1",value:0}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"56gzwfwxh",objOut:"cf4c0tnvd"},{portIn:"X",portOut:"result",objIn:"ovnlop7xk",objOut:"cf4c0tnvd"},{portIn:"Value",portOut:"result",objIn:"lr5wgc5ve",objOut:"cf4c0tnvd"},{portIn:"Scroll X",portOut:"result",objIn:"86qkj6qi3",objOut:"cf4c0tnvd"},{portIn:"number1",portOut:"result",objIn:"oue6bxvdc",objOut:"cf4c0tnvd"},{portIn:"X",portOut:"result",objIn:"rrm6rljnr",objOut:"cf4c0tnvd"},{portIn:"Value",portOut:"result",objIn:"olbuthv3m",objOut:"cf4c0tnvd"},{portIn:"Scroll X",portOut:"result",objIn:"v64zdijjj",objOut:"cf4c0tnvd"},{portIn:"number1",portOut:"result",objIn:"71x01q8on",objOut:"cf4c0tnvd"}]}],objName:"Ops.Math.Sum"},{id:"51pos4tkk",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"Amount",value:.461}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"d537b0eb-e22f-4a25-976f-6c0d050ca09b",objOut:"51pos4tkk"}]}],objName:"Ops.Gl.ImageCompose.LUTMap"},{id:"ed7u16q0q",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"File",value:"assets/lib_lut_lut9.jpg",display:"file"},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Data Format index",value:3},{name:"Data Format",value:"RGBA"},{name:"Flip",value:1},{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:"LUT Image",portOut:"Texture",objIn:"51pos4tkk",objOut:"ed7u16q0q"}]},{name:"Width",value:512},{name:"Height",value:512},{name:"Aspect Ratio",value:1},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"uhdbk6dn2",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"Blend Mode index",value:3},{name:"Blend Mode",value:"multiply"},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Amount",value:.144},{name:"Threshold",value:0},{name:"Animated",value:0},{name:"RGB",value:1},{name:"Normalize",value:0}],portsOut:[{name:"Next",links:[{portIn:"render",portOut:"Next",objIn:"mw5zfn4tt",objOut:"uhdbk6dn2"}]}],objName:"Ops.Gl.ImageCompose.Noise.Noise_v2"},{id:"y7z6vjdft",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"File",value:"assets/liqube-vignette_4.jpg",display:"file"},{name:"Filter index",value:2},{name:"Filter",value:"mipmap"},{name:"Wrap index",value:0},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{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 2",portOut:"Texture",objIn:"cbj6ahuk5",objOut:"y7z6vjdft"}]},{name:"Width",value:1920},{name:"Height",value:1080},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Loaded",value:1},{name:"Loading",value:0}],objName:"Ops.Gl.Texture_v2"},{id:"d6oh8mfl1",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Variable",value:"beat"}],portsOut:[{name:"Value",links:[{portIn:"time",portOut:"Value",objIn:"1fcsfrl1h",objOut:"d6oh8mfl1"}]}],objName:"Ops.Vars.VarGetNumber_v2"},{id:"1fcsfrl1h",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"sheet",value:"368. (120.qio) (0.57qio)\n380 (180.) (0.8)\n\na3:\n382 (0.qio)\n383 (.8)\n\na4:\n336. (0.qio)\n344 (1.)\n360. (1.qio)\n368 (0.)"}],portsOut:[{name:"analog 1",links:[{portIn:"rotX",portOut:"analog 1",objIn:"cou8cqwkw",objOut:"1fcsfrl1h"}]},{name:"analog 2",links:[{portIn:"posZ",portOut:"analog 2",objIn:"cou8cqwkw",objOut:"1fcsfrl1h"}]},{name:"analog 3",links:[{portIn:"amount",portOut:"analog 3",objIn:"n6e626ojc",objOut:"1fcsfrl1h"},{portIn:"number1",portOut:"analog 3",objIn:"o6ri0hpdu",objOut:"1fcsfrl1h"}]},{name:"analog 4",links:[{portIn:"a",portOut:"analog 4",objIn:"spjlltkrw",objOut:"1fcsfrl1h"}]},{name:"analog 5",value:0},{name:"analog 6",value:0},{name:"analog 7",value:0},{name:"analog 8",value:0}],objName:"Ops.User.anticore.DopeSheet"},{id:"o6ri0hpdu",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"number2",value:2.93}],portsOut:[{name:"result",links:[{portIn:"amount",portOut:"result",objIn:"0nwfqwfcd",objOut:"o6ri0hpdu"}]}],objName:"Ops.Math.Multiply"},{id:"mrmjxwjgq",uiAttribs:{subPatch:"3da97ohdf"},portsIn:[{name:"number2",value:2}],portsOut:[{name:"result",links:[{portIn:"number2",portOut:"result",objIn:"cf4c0tnvd",objOut:"mrmjxwjgq"}]}],objName:"Ops.Math.Divide"},{id:"3yz67mvac",uiAttribs:{subPatch:"kb5v7uxi5"},portsOut:[{name:"Output",multiPortNum:2},{name:"Output_0",links:[{portIn:"render",portOut:"Output_0",objIn:"cou8cqwkw",objOut:"3yz67mvac"}]},{name:"Output_1",title:"add port",links:[{portIn:"render",portOut:"Output_1",objIn:"kzdh1koer",objOut:"3yz67mvac"}]}],objName:"Ops.Trigger.SequenceMultiPort"},{id:"spjlltkrw",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"Text",value:"INERCIA 2024 * ANTICORE * VAR.RHO * MONSTRO"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:1},{name:"vertical align",value:"Middle"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:1},{name:"g",value:1},{name:"b",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:6.572856952617698},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"kzdh1koer",uiAttribs:{subPatch:"kb5v7uxi5"},portsIn:[{name:"posX",value:0},{name:"posY",value:.24},{name:"posZ",value:1.47},{name:"scale",value:.07},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"spjlltkrw",objOut:"kzdh1koer"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"gh6op6w3l",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"Material Name",value:"shoes03"}],portsOut:[{name:"Material",links:[{portIn:"Materials",portOut:"Material",objIn:"zs8ujbtfy",objOut:"gh6op6w3l"}]}],objName:"Ops.Gl.GLTF.GltfSetMaterial"},{id:"94lkb1z76",uiAttribs:{subPatch:"0eb4f2f9-5676-4adf-a58b-f1a423817be6"},portsIn:[{name:"R",value:.0809375},{name:"G",value:.0809375},{name:"B",value:.0809375},{name:"A",value:1},{name:"Enable",value:0},{name:"Albedo",value:.707},{name:"Roughness",value:.835},{name:"Active",value:0},{name:"Fresnel Intensity",value:.7},{name:"Fresnel Width",value:1},{name:"Fresnel Exponent",value:6},{name:"Fresnel R",value:1},{name:"Fresnel G",value:1},{name:"Fresnel B",value:1},{name:"Emissive Active",value:0},{name:"Color Intensity",value:.3},{name:"Emissive R",value:.4846925819613257},{name:"Emissive G",value:.009356416823264713},{name:"Emissive B",value:.8573214584187876},{name:"Shininess",value:4},{name:"Specular Amount",value:.5},{name:"Specular Model index",value:0},{name:"Specular Model",value:"Blinn"},{name:"Energy Conservation",value:0},{name:"Double Sided Material",value:0},{name:"Falloff Mode index",value:0},{name:"Falloff Mode",value:"A"},{name:"Colorize Texture",value:0},{name:"Diffuse Repeat X",value:1},{name:"Diffuse Repeat Y",value:1},{name:"Texture Offset X",value:0},{name:"Texture Offset Y",value:0},{name:"Specular Intensity",value:1},{name:"Normal Map Intensity",value:.5},{name:"AO Intensity",value:1},{name:"AO UV Channel index",value:0},{name:"AO UV Channel",value:1},{name:"Emissive Intensity",value:1},{name:"Emissive Mask Intensity",value:1},{name:"Env Map Intensity",value:1},{name:"Env Map Blend index",value:0},{name:"Env Map Blend",value:"Add"},{name:"Env Mask Intensity",value:1},{name:"Alpha Mask Source index",value:0},{name:"Alpha Mask Source",value:"Luminance"},{name:"Discard Transparent Pixels",value:0}],portsOut:[{name:"Trigger Out",links:[{portIn:"Render",portOut:"Trigger Out",objIn:"39pmkmaq9",objOut:"94lkb1z76"}]}],objName:"Ops.Gl.Phong.PhongMaterial_v6"},{id:"je2tg233t",uiAttribs:{subPatch:"wgd0fkctg"},portsOut:[{name:"create port",value:0},{name:"in0 Sequence exe",links:[{portIn:"exe",portOut:"in0 Sequence exe",objIn:"at36jeuna",objOut:"je2tg233t"}]}],objName:"Ops.Ui.PatchInput"},{id:"7wfs4ua5h",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"create port",value:0}],objName:"Ops.Ui.PatchOutput"},{id:"at36jeuna",uiAttribs:{subPatch:"wgd0fkctg"},portsOut:[{name:"trigger 6",links:[{portIn:"exe",portOut:"trigger 6",objIn:"qylo80vp6",objOut:"at36jeuna"}]},{name:"trigger 7",links:[{portIn:"Render",portOut:"trigger 7",objIn:"es8j16pke",objOut:"at36jeuna"}]},{name:"trigger 9",links:[{portIn:"Render",portOut:"trigger 9",objIn:"zxx71ndyq",objOut:"at36jeuna"}]},{name:"trigger 12",links:[{portIn:"Render",portOut:"trigger 12",objIn:"7kqgtxoxy",objOut:"at36jeuna"}]},{name:"trigger 13",links:[{portIn:"Render",portOut:"trigger 13",objIn:"4tvggxych",objOut:"at36jeuna"}]},{name:"trigger 15",links:[{portIn:"Render",portOut:"trigger 15",objIn:"mdosa5fvv",objOut:"at36jeuna"}]}],objName:"Ops.Trigger.Sequence"},{id:"mdosa5fvv",uiAttribs:{subPatch:"wgd0fkctg"},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:1},{name:"Wrap",value:"repeat"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:"0"},{name:"Pixel Format index",value:11},{name:"Pixel Format",value:"RGBA 32bit float"},{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:"2xn2truox",objOut:"mdosa5fvv"}]},{name:"texture_out",links:[{portIn:"Value",portOut:"texture_out",objIn:"i5s749be5",objOut:"mdosa5fvv"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"i5s749be5",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Variable",value:"sceneTex"}],objName:"Ops.Vars.VarSetTexture_v2"},{id:"2xn2truox",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Mask Invert",value:0},{name:"Blendmode 1 index",value:0},{name:"Blendmode 1",value:"normal"},{name:"Mask Source 1 index",value:0},{name:"Mask Source 1",value:"R"},{name:"Opacity 1 index",value:0},{name:"Opacity 1",value:"Normal"},{name:"Amount 1",value:1},{name:"Blendmode 2 index",value:0},{name:"Blendmode 2",value:"normal"},{name:"Mask Source 2 index",value:0},{name:"Mask Source 2",value:"R"},{name:"Opacity 2 index",value:0},{name:"Opacity 2",value:"Normal"},{name:"Amount 2",value:1},{name:"Blendmode 3 index",value:0},{name:"Blendmode 3",value:"normal"},{name:"Mask Source 3 index",value:0},{name:"Mask Source 3",value:"R"},{name:"Opacity 3 index",value:0},{name:"Opacity 3",value:"Normal"},{name:"Amount 3",value:.88},{name:"Blendmode 4 index",value:11},{name:"Blendmode 4",value:"overlay"},{name:"Mask Source 4 index",value:0},{name:"Mask Source 4",value:"R"},{name:"Opacity 4 index",value:0},{name:"Opacity 4",value:"Normal"},{name:"Amount 4",value:1},{name:"Blendmode 5 index",value:3},{name:"Blendmode 5",value:"multiply"},{name:"Mask Source 5 index",value:0},{name:"Mask Source 5",value:"R"},{name:"Opacity 5 index",value:0},{name:"Opacity 5",value:"Normal"},{name:"Amount 5",value:.679},{name:"Blendmode 6 index",value:0},{name:"Blendmode 6",value:"normal"},{name:"Mask Source 6 index",value:0},{name:"Mask Source 6",value:"R"},{name:"Opacity 6 index",value:0},{name:"Opacity 6",value:"Normal"},{name:"Amount 6",value:1},{name:"Blendmode 7 index",value:0},{name:"Blendmode 7",value:"normal"},{name:"Mask Source 7 index",value:0},{name:"Mask Source 7",value:"R"},{name:"Opacity 7 index",value:0},{name:"Opacity 7",value:"Normal"},{name:"Amount 7",value:1},{name:"Blendmode 8 index",value:0},{name:"Blendmode 8",value:"normal"},{name:"Mask Source 8 index",value:0},{name:"Mask Source 8",value:"R"},{name:"Opacity 8 index",value:0},{name:"Opacity 8",value:"Normal"},{name:"Amount 8",value:1}],portsOut:[{name:"trigger",links:[{portIn:"render",portOut:"trigger",objIn:"e64dpdb50",objOut:"2xn2truox"}]}],objName:"Ops.Gl.ImageCompose.MultiDrawImage"},{id:"zxx71ndyq",uiAttribs:{subPatch:"wgd0fkctg"},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:1},{name:"Wrap",value:"repeat"},{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:"texture_out",links:[{portIn:"Texture 2",portOut:"texture_out",objIn:"2xn2truox",objOut:"zxx71ndyq"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"qylo80vp6",uiAttribs:{subPatch:"wgd0fkctg"},portsOut:[{name:"trigger 0",links:[{portIn:"render",portOut:"trigger 0",objIn:"m5ccved2m",objOut:"qylo80vp6"}]},{name:"trigger 5",links:[{portIn:"render",portOut:"trigger 5",objIn:"uti9ifcpv",objOut:"qylo80vp6"}]}],objName:"Ops.Trigger.Sequence"},{id:"m5ccved2m",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Canvas"},{name:"texture width",value:1920},{name:"texture height",value:1080},{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:0},{name:"MSAA",value:"none"},{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:"uklxhyr1a",objOut:"m5ccved2m"},{portIn:"render",portOut:"trigger",objIn:"vreta0yen",objOut:"m5ccved2m"}]},{name:"texture",links:[{portIn:"Base Texture",portOut:"texture",objIn:"zxx71ndyq",objOut:"m5ccved2m"}]}],objName:"Ops.Gl.RenderToTexture_v3"},{id:"hn5dov7iv",uiAttribs:{subPatch:"d2d6bd4c-4b4d-480f-b440-24967a683713"},storage:{subPatchVer:1},portsIn:[{name:"create port",value:0},{name:"dataStr",value:'{"ports":[{"name":"in0 Sequence exe","type":1}],"portsOut":[]}'},{name:"patchId",value:"wgd0fkctg"}],portsOut:[{name:"create port out",value:0}],objName:"Ops.Ui.SubPatch"},{id:"es8j16pke",uiAttribs:{subPatch:"wgd0fkctg"},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:1},{name:"Wrap",value:"repeat"},{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:"065bwo0oe",objOut:"es8j16pke"}]},{name:"texture_out",links:[{portIn:"Texture 1",portOut:"texture_out",objIn:"2xn2truox",objOut:"es8j16pke"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"2fd3p0rdt",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Blend Mode index",value:5},{name:"Blend Mode",value:"average"},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"Amount",value:1},{name:"Threshold",value:0},{name:"Animated",value:1},{name:"RGB",value:0},{name:"Normalize",value:0}],objName:"Ops.Gl.ImageCompose.Noise.Noise_v2"},{id:"065bwo0oe",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Scale",value:400},{name:"X",value:0},{name:"Y",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"2fd3p0rdt",objOut:"065bwo0oe"}]}],objName:"Ops.Gl.ImageCompose.Noise.ValueNoise_v2"},{id:"l32h67ro7",uiAttribs:{subPatch:"wgd0fkctg"},portsOut:[{name:"time",links:[{portIn:"number1",portOut:"time",objIn:"17bv1t0vp",objOut:"l32h67ro7"}]}],objName:"Ops.TimeLine.TimeLineTime"},{id:"17bv1t0vp",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"number2",value:1e3}],portsOut:[{name:"result",links:[{portIn:"Z",portOut:"result",objIn:"065bwo0oe",objOut:"17bv1t0vp"}]}],objName:"Ops.Math.Multiply"},{id:"2rikxss3i",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Variable",value:"randomVignetteTex2"}],portsOut:[{name:"Value",links:[{portIn:"Texture 5",portOut:"Value",objIn:"2xn2truox",objOut:"2rikxss3i"}]}],objName:"Ops.Vars.VarGetTexture_v2"},{id:"1427n8tv1",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Text",value:"FUCK YOUR"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:1},{name:"vertical align",value:"Middle"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"a",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:1.4549999484768164},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"g92vut3gr",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"scale",value:.65},{name:"x",value:1.3},{name:"y",value:1.13},{name:"z",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"1427n8tv1",objOut:"g92vut3gr"}]}],objName:"Ops.Gl.Matrix.Scale"},{id:"uklxhyr1a",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"posX",value:0},{name:"posY",value:.62},{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:"g92vut3gr",objOut:"uklxhyr1a"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"8rup4otp5",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Text",value:"ENCODER"},{name:"Scale Text",value:1},{name:"Scale",value:1,title:"Line Scale"},{name:"Font",value:"XBAND Rough"},{name:"align index",value:1},{name:"align",value:"center"},{name:"vertical align index",value:1},{name:"vertical align",value:"Middle"},{name:"Line Height",value:1},{name:"Letter Spacing",value:0},{name:"filter index",value:2},{name:"filter",value:"mipmap"},{name:"Anisotropic index",value:0},{name:"Anisotropic",value:0},{name:"r",value:0},{name:"g",value:0},{name:"b",value:0},{name:"a",value:1}],portsOut:[{name:"Total Lines",value:1},{name:"Width",value:1.2500000000000002},{name:"Font Available",value:1}],objName:"Ops.Gl.Meshes.TextMesh_v2"},{id:"9li0abcv4",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"scale",value:.65},{name:"x",value:1.3},{name:"y",value:1.13},{name:"z",value:1}],portsOut:[{name:"trigger",links:[{portIn:"Render",portOut:"trigger",objIn:"8rup4otp5",objOut:"9li0abcv4"}]}],objName:"Ops.Gl.Matrix.Scale"},{id:"vreta0yen",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"posX",value:0},{name:"posY",value:-.73},{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:"9li0abcv4",objOut:"vreta0yen"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"uti9ifcpv",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Size index",value:0},{name:"Size",value:"Canvas"},{name:"texture width",value:1920},{name:"texture height",value:1080},{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:0},{name:"MSAA",value:"none"},{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:"sqqyak4re",objOut:"uti9ifcpv"}]},{name:"texture",links:[{portIn:"Image",portOut:"texture",objIn:"9ey873ad5",objOut:"uti9ifcpv"}]}],objName:"Ops.Gl.RenderToTexture_v3"},{id:"d93euxov4",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Named Trigger",value:"mdlDrunk"}],objName:"Ops.Trigger.TriggerSend"},{id:"iem01rc2f",uiAttribs:{subPatch:"wgd0fkctg"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"7kqgtxoxy",uiAttribs:{subPatch:"wgd0fkctg"},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:1},{name:"Wrap",value:"repeat"},{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:"9ey873ad5",objOut:"7kqgtxoxy"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"iem01rc2f",objOut:"7kqgtxoxy"},{portIn:"Texture 3",portOut:"texture_out",objIn:"2xn2truox",objOut:"7kqgtxoxy"}]},{name:"Aspect Ratio",value:1.7777777777777777},{name:"Texture Width",value:1920},{name:"Texture Height",value:1080}],objName:"Ops.Gl.ImageCompose.ImageCompose_v4"},{id:"d09jzyn7e",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Amount",value:1},{name:"Alpha Mask index",value:1},{name:"Alpha Mask",value:"On"},{name:"Mask Invert",value:0},{name:"r",value:1},{name:"g",value:0},{name:"b",value:0},{name:"A",value:1}],objName:"Ops.Gl.ImageCompose.Color_v2"},{id:"9ey873ad5",uiAttribs:{subPatch:"wgd0fkctg"},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:"d09jzyn7e",objOut:"9ey873ad5"}]}],objName:"Ops.Gl.ImageCompose.DrawImage_v3"},{id:"sqqyak4re",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"posX",value:0},{name:"posY",value:0},{name:"posZ",value:-.91},{name:"scale",value:1},{name:"rotX",value:0},{name:"rotY",value:0},{name:"rotZ",value:0}],portsOut:[{name:"trigger",links:[{portIn:"Trigger",portOut:"trigger",objIn:"d93euxov4",objOut:"sqqyak4re"}]}],objName:"Ops.Gl.Matrix.Transform"},{id:"4tvggxych",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Size index",value:1},{name:"Size",value:"Manual"},{name:"Width",value:100},{name:"Height",value:100},{name:"Filter index",value:1},{name:"Filter",value:"linear"},{name:"Wrap index",value:1},{name:"Wrap",value:"repeat"},{name:"Pixel Format index",value:4},{name:"Pixel Format",value:"RGBA 8bit ubyte"},{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:"mfeo9wvgd",objOut:"4tvggxych"},{portIn:"In Trigger",portOut:"Next",objIn:"yas2c2hbe",objOut:"4tvggxych"}]},{name:"texture_out",links:[{portIn:"Texture In",portOut:"texture_out",objIn:"xidqv8m4o",objOut:"4tvggxych"},{portIn:"displaceTex",portOut:"texture_out",objIn:"e64dpdb50",objOut:"4tvggxych"}]},{name:"Aspect Ratio",value:1},{name:"Texture Width",value:100},{name:"Texture Height",value:100}],objName:"Ops.Gl.ImageCompose.ImageCompose_v3"},{id:"mfeo9wvgd",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Blend Mode index",value:0},{name:"Blend Mode",value:"normal"},{name:"Alpha Mask index",value:0},{name:"Alpha Mask",value:"Off"},{name:"frequency",value:1},{name:"strength",value:8},{name:"Block size small x",value:8.02},{name:"Block size small y",value:17.96},{name:"Block size large x",value:17.96},{name:"Block size large y",value:4},{name:"Scroll X",value:0},{name:"Scroll Y",value:0}],objName:"Ops.Gl.ImageCompose.Noise.GlitchNoise_v2"},{id:"xidqv8m4o",uiAttribs:{subPatch:"wgd0fkctg"},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:""}],objName:"Ops.Ui.VizTexture"},{id:"04ia2t6fk",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Speed",value:1},{name:"Play",value:1},{name:"Sync to timeline",value:0}],portsOut:[{name:"Time",links:[{portIn:"value",portOut:"Time",objIn:"clklce7dv",objOut:"04ia2t6fk"}]}],objName:"Ops.Anim.Timer_v2"},{id:"yas2c2hbe",uiAttribs:{subPatch:"wgd0fkctg"},portsOut:[{name:"Out Trigger",links:[{portIn:"Generate",portOut:"Out Trigger",objIn:"kvww6a6q9",objOut:"yas2c2hbe"}]},{name:"Progress",value:.08661268884640498}],objName:"Ops.Trigger.TriggerLimiter"},{id:"kvww6a6q9",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"min",value:0},{name:"max",value:1},{name:"Integer",value:0},{name:"No consecutive duplicates",value:0}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"9uo5giazw",objOut:"kvww6a6q9"}]}],objName:"Ops.Math.TriggerRandomNumber_v2"},{id:"9uo5giazw",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"number2",value:1}],portsOut:[{name:"result",links:[{portIn:"Amount",portOut:"result",objIn:"mfeo9wvgd",objOut:"9uo5giazw"}]}],objName:"Ops.Math.Compare.LessThan"},{id:"35ebpl7zr",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"value",value:113}],portsOut:[{name:"result",links:[{portIn:"number1",portOut:"result",objIn:"ym6ci1j9f",objOut:"35ebpl7zr"}]}],objName:"Ops.Number.Number"},{id:"ym6ci1j9f",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"number2",value:.47}],portsOut:[{name:"result",links:[{portIn:"Milliseconds",portOut:"result",objIn:"yas2c2hbe",objOut:"ym6ci1j9f"}]}],objName:"Ops.Math.Multiply"},{id:"clklce7dv",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"phase",value:0},{name:"frequency",value:1},{name:"amplitude",value:1},{name:"asine",value:0}],portsOut:[{name:"result",links:[{portIn:"Seed",portOut:"result",objIn:"mfeo9wvgd",objOut:"clklce7dv"}]}],objName:"Ops.Math.Sine"},{id:"e64dpdb50",uiAttribs:{subPatch:"wgd0fkctg"},portsIn:[{name:"Blend Mode index",value:11},{name:"Blend Mode",value:"overlay"},{name:"Amount",value:1},{name:"amount X",value:.027},{name:"amount Y",value:.063},{name:"Wrap index",value:2},{name:"Wrap",value:"Repeat"},{name:"Input index",value:0},{name:"Input",value:"Luminance"},{name:"Zero Displace index",value:1},{name:"Zero Displace",value:"Black"},{name:"Pixel Mapping index",value:0},{name:"Pixel Mapping",value:"Stretch"}],objName:"Ops.Gl.ImageCompose.PixelDisplacement_v4"},{id:"mw5zfn4tt",uiAttribs:{subPatch:"55667c89-cb99-4c3a-8424-21faf0e697be"},portsIn:[{name:"contrast",value:.5}],objName:"Ops.Gl.ImageCompose.BrightnessContrast"},{id:"f2tp4tgfx",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsOut:[{name:"then",links:[{portIn:"out0 Ops.Sequence exe",portOut:"then",objIn:"e286b485-7fd3-4825-8724-01e7037d5fbe",objOut:"f2tp4tgfx"}]},{name:"else",links:[{portIn:"Render",portOut:"else",objIn:"99fba13a-1467-4b45-85dd-7a98e16ea127",objOut:"f2tp4tgfx"}]}],objName:"Ops.Boolean.IfTrueThen_v2"},{id:"37o0pwbh9",uiAttribs:{subPatch:"13f105ab-1b41-4be0-801c-e06345ec5080"},portsIn:[{name:"Variable",value:"dev"}],portsOut:[{name:"Value",links:[{portIn:"boolean",portOut:"Value",objIn:"f2tp4tgfx",objOut:"37o0pwbh9"}]}],objName:"Ops.Vars.VarGetNumber_v2"}],export:{time:"2024-12-05 10:36",service:"exe",exportNumber:3}};if(!CABLES.exportedPatch){CABLES.exportedPatch=CABLES.exportedPatches["SG56Nv"]}"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.Math=Ops.Math||{};Ops.Team=Ops.Team||{};Ops.User=Ops.User||{};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.Devices=Ops.Devices||{};Ops.Gl.GLTF=Ops.Gl.GLTF||{};Ops.Sidebar=Ops.Sidebar||{};Ops.Trigger=Ops.Trigger||{};Ops.Gl.Phong=Ops.Gl.Phong||{};Ops.Graphics=Ops.Graphics||{};Ops.Html.CSS=Ops.Html.CSS||{};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.Math.Compare=Ops.Math.Compare||{};Ops.Devices.Mouse=Ops.Devices.Mouse||{};Ops.User.anticore=Ops.User.anticore||{};Ops.Gl.ImageCompose=Ops.Gl.ImageCompose||{};Ops.Gl.ShaderEffects=Ops.Gl.ShaderEffects||{};Ops.Graphics.Geometry=Ops.Graphics.Geometry||{};Ops.Team.Mdlviz_a0rO0B=Ops.Team.Mdlviz_a0rO0B||{};Ops.Extension.Deprecated=Ops.Extension.Deprecated||{};Ops.Gl.ImageCompose.Noise=Ops.Gl.ImageCompose.Noise||{};Ops.Gl.MainLoop=function(){CABLES.Op.apply(this,arguments);const a=this;const e=a.attachments={};const t=a.inValue("FPS Limit",0),n=a.outTrigger("trigger"),i=a.outNumber("width"),r=a.outNumber("height"),o=a.inValueBool("Reduce FPS not focussed",false),s=a.inValueBool("Reduce FPS loading"),l=a.inValueBool("Clear",true),u=a.inValueBool("ClearAlpha",true),m=a.inValueBool("Fullscreen Button",false),c=a.inValueBool("Active",true),d=a.inValueBool("Hires Displays",false),h=a.inSwitch("Pixel Unit",["Display","CSS"],"Display");a.onAnimFrame=C;d.onChange=function(){if(d.get())a.patch.cgl.pixelDensity=window.devicePixelRatio;else a.patch.cgl.pixelDensity=1;a.patch.cgl.updateSize();if(CABLES.UI)gui.setLayout()};c.onChange=function(){a.patch.removeOnAnimFrame(a);if(c.get()){a.setUiAttrib({extendTitle:""});a.onAnimFrame=C;a.patch.addOnAnimFrame(a);a.log("adding again!")}else{a.setUiAttrib({extendTitle:"Inactive"})}};const f=a.patch.cgl;let p=0;let g=0;let v=null;let b=false;if(!a.patch.cgl)a.uiAttr({error:"No webgl cgl context"});const x=vec3.create();vec3.set(x,0,0,0);const _=vec3.create();vec3.set(_,0,0,-2);m.onChange=S;setTimeout(S,100);let O=null;let A=true;let I=true;window.addEventListener("blur",()=>{A=false});window.addEventListener("focus",()=>{A=true});document.addEventListener("visibilitychange",()=>{I=!document.hidden});y();f.mainloopOp=this;h.onChange=()=>{i.set(0);r.set(0)};function T(){if(s.get()&&a.patch.loading.getProgress()<1)return 5;if(o.get()){if(!I)return 10;if(!A)return 30}return t.get()}function S(){function e(){if(O)O.style.display="block"}function t(){if(O)O.style.display="none"}a.patch.cgl.canvas.addEventListener("mouseleave",t);a.patch.cgl.canvas.addEventListener("mouseenter",e);if(m.get()){if(!O){O=document.createElement("div");const n=a.patch.cgl.canvas.parentElement;if(n)n.appendChild(O);O.addEventListener("mouseenter",e);O.addEventListener("click",function(e){if(CABLES.UI&&!e.shiftKey)gui.cycleFullscreen();else f.fullScreen()})}O.style.padding="10px";O.style.position="absolute";O.style.right="5px";O.style.top="5px";O.style.width="20px";O.style.height="20px";O.style.cursor="pointer";O.style["border-radius"]="40px";O.style.background="#444";O.style["z-index"]="9999";O.style.display="none";O.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 490 490" style="width:20px;height:20px;" xml:space="preserve" width="512px" height="512px"><g><path d="M173.792,301.792L21.333,454.251v-80.917c0-5.891-4.776-10.667-10.667-10.667C4.776,362.667,0,367.442,0,373.333V480     c0,5.891,4.776,10.667,10.667,10.667h106.667c5.891,0,10.667-4.776,10.667-10.667s-4.776-10.667-10.667-10.667H36.416     l152.459-152.459c4.093-4.237,3.975-10.99-0.262-15.083C184.479,297.799,177.926,297.799,173.792,301.792z" fill="#FFFFFF"/><path d="M480,0H373.333c-5.891,0-10.667,4.776-10.667,10.667c0,5.891,4.776,10.667,10.667,10.667h80.917L301.792,173.792     c-4.237,4.093-4.354,10.845-0.262,15.083c4.093,4.237,10.845,4.354,15.083,0.262c0.089-0.086,0.176-0.173,0.262-0.262     L469.333,36.416v80.917c0,5.891,4.776,10.667,10.667,10.667s10.667-4.776,10.667-10.667V10.667C490.667,4.776,485.891,0,480,0z" fill="#FFFFFF"/><path d="M36.416,21.333h80.917c5.891,0,10.667-4.776,10.667-10.667C128,4.776,123.224,0,117.333,0H10.667     C4.776,0,0,4.776,0,10.667v106.667C0,123.224,4.776,128,10.667,128c5.891,0,10.667-4.776,10.667-10.667V36.416l152.459,152.459     c4.237,4.093,10.99,3.975,15.083-0.262c3.992-4.134,3.992-10.687,0-14.82L36.416,21.333z" fill="#FFFFFF"/><path d="M480,362.667c-5.891,0-10.667,4.776-10.667,10.667v80.917L316.875,301.792c-4.237-4.093-10.99-3.976-15.083,0.261     c-3.993,4.134-3.993,10.688,0,14.821l152.459,152.459h-80.917c-5.891,0-10.667,4.776-10.667,10.667s4.776,10.667,10.667,10.667     H480c5.891,0,10.667-4.776,10.667-10.667V373.333C490.667,367.442,485.891,362.667,480,362.667z" fill="#FFFFFF"/></g></svg>'}else{if(O){O.style.display="none";O.remove();O=null}}}a.onDelete=function(){f.gl.clearColor(0,0,0,0);f.gl.clear(f.gl.COLOR_BUFFER_BIT|f.gl.DEPTH_BUFFER_BIT)};function C(e){if(!c.get())return;if(f.aborted||f.canvas.clientWidth===0||f.canvas.clientHeight===0)return;a.patch.cg=f;if(d.get())a.patch.cgl.pixelDensity=window.devicePixelRatio;const t=performance.now();a.patch.config.fpsLimit=T();if(f.canvasWidth==-1){f.setCanvas(a.patch.config.glCanvasId);return}if(f.canvasWidth!=i.get()||f.canvasHeight!=r.get()){let e=1;if(h.get()=="CSS")e=a.patch.cgl.pixelDensity;i.set(f.canvasWidth/e);r.set(f.canvasHeight/e)}if(CABLES.now()-g>1e3){CGL.fpsReport=CGL.fpsReport||[];if(a.patch.loading.getProgress()>=1&&g!==0)CGL.fpsReport.push(p);p=0;g=CABLES.now()}CGL.MESH.lastShader=null;CGL.MESH.lastMesh=null;f.renderStart(f,x,_);if(l.get()){f.gl.clearColor(0,0,0,1);f.gl.clear(f.gl.COLOR_BUFFER_BIT|f.gl.DEPTH_BUFFER_BIT)}n.trigger();if(CGL.MESH.lastMesh)CGL.MESH.lastMesh.unBind();if(CGL.Texture.previewTexture){if(!CGL.Texture.texturePreviewer)CGL.Texture.texturePreviewer=new CGL.Texture.texturePreview(f);CGL.Texture.texturePreviewer.render(CGL.Texture.previewTexture)}f.renderEnd(f);a.patch.cg=null;if(u.get()){f.gl.clearColor(1,1,1,1);f.gl.colorMask(false,false,false,true);f.gl.clear(f.gl.COLOR_BUFFER_BIT);f.gl.colorMask(true,true,true,true)}if(!f.frameStore.phong)f.frameStore.phong={};p++;a.patch.cgl.profileData.profileMainloopMs=performance.now()-t}function y(){clearTimeout(v);v=setTimeout(()=>{if(a.patch.getOpsByObjName(a.name).length>1){a.setUiError("multimainloop","there should only be one mainloop op!");if(!b)b=a.patch.addEventListener("onOpDelete",y)}else a.setUiError("multimainloop",null,1)},500)}};Ops.Gl.MainLoop.prototype=new CABLES.Op;CABLES.OPS["b0472a1d-db16-4ba6-8787-f300fbdc77bb"]={f:Ops.Gl.MainLoop,objName:"Ops.Gl.MainLoop"};Ops.WebAudio.AudioBuffer_v2=function(){CABLES.Op.apply(this,arguments);const a=this;const e=a.attachments={};const i=a.patch.cgl;const t=CABLES.WEBAUDIO.createAudioContext(a),n=a.inUrl("URL","audio"),r=a.inBool("Create Loading Task",true),o=a.outObject("Audio Buffer",null,"audioBuffer"),s=a.outBoolNum("Finished Loading",false),l=a.outNumber("Sample Rate",0),u=a.outNumber("Length",0),m=a.outNumber("Duration",0),c=a.outNumber("Number of Channels",0),d=a.outBool("isLoading",0);let h=null;let f=false;let p=null;let g=null;let v=false;let b=false;let x=false;let _=new FileReader;let O=null;let A=0;if(!o.isLinked()){a.setUiError("notConnected","To play back sound, connect this op to a playback operator such as SamplePlayer or AudioBufferPlayer.",0)}else{a.setUiError("notConnected",null)}o.onLinkChanged=()=>{if(o.isLinked()){a.setUiError("notConnected",null)}else{a.setUiError("notConnected","To play back sound, connect this op to a playback operator such as SamplePlayer or AudioBufferPlayer.",0)}};function I(t,e){p=t;f=true;d.set(f);if(!e){const n=t.substr(t.lastIndexOf(".")+1);if(n==="wav"){a.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{a.setUiError("wavFormat",null)}CABLES.WEBAUDIO.loadAudioFile(a.patch,t,C,y,r.get())}else{let e=T(t);if(e.type==="audio/wav"){a.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{a.setUiError("wavFormat",null)}if(r.get()){A=i.patch.loading.start("audiobuffer from data-url "+a.id,t,a);if(i.patch.isEditorMode())gui.jobs().start({id:"loadaudio"+A,title:" loading audio data url ("+a.id+")"})}_.readAsArrayBuffer(e)}}function T(e){let t=atob(e.split(",")[1]);let n=e.split(",")[0].split(":")[1].split(";")[0];let a=new ArrayBuffer(t.length);let i=new Uint8Array(a);for(let e=0;e<t.length;e++){i[e]=t.charCodeAt(e)}let r=new Blob([a],{type:n});return r}n.onChange=function(){if(n.get()){b=String(n.get()).indexOf("data:")==0;if(f){x=String(n.get()).indexOf("data:")==0;const t=x?n.get():a.patch.getFilePath(n.get());if(t!==p){g=t}else{g=null}v=false;return}E();const e=b?n.get():a.patch.getFilePath(n.get());I(e,b)}else{if(f){v=true;return}E();a.setUiError("wavFormat",null);a.setUiError("failedLoading",null)}};_.onloadend=()=>{O=_.result;i.patch.loading.finished(A);if(i.patch.isEditorMode())gui.jobs().finish("loadaudio"+A);S()};function S(){if(O)t.decodeAudioData(O,C,y)}function C(e){f=false;d.set(f);if(v){E();v=false;return}if(g){I(g,x);g=null}else{h=e;u.set(e.length);m.set(e.duration);c.set(e.numberOfChannels);l.set(e.sampleRate);o.set(e);a.setUiError("failedLoading",null);s.set(true);b=false;x=false}}function y(e){a.setUiError("failedLoading","The audio file could not be loaded. Make sure the right file URL is used.",2);f=false;E();d.set(f);h=null;if(g){I(g,x);g=null}}function E(){u.set(0);m.set(0);c.set(0);l.set(0);o.set(null);s.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 n=this;const e=n.attachments={};const a=n.inObject("Audio Buffer",null,"audioBuffer");const i=n.inBool("Start / Stop",false);const r=n.inBool("Loop",false);const t=n.inTriggerButton("Restart");const o=n.inFloat("Offset",0);const s=n.inFloat("Playback Rate",1);const l=n.inFloat("Detune",0);n.setPortGroup("Playback Controls",[i,r,t]);n.setPortGroup("Time Controls",[o]);n.setPortGroup("Miscellaneous",[s,l]);const u=n.outObject("Audio Out",null,"audioNode");const m=n.outBool("Is Playing",false);const c=n.outBool("Loading",false);let d=null;let h=false;let f=false;let p=null;let g=null;let v=false;const b=CABLES.WEBAUDIO.createAudioContext(n);const x=b.createGain();if(!a.isLinked()){n.setUiError("inputNotConnected","To be able to play back sound, you need to connect an AudioBuffer to this op.",0)}else{n.setUiError("inputNotConnected",null)}a.onLinkChanged=()=>{if(!a.isLinked()){n.setUiError("inputNotConnected","To be able to play back sound, you need to connect an AudioBuffer to this op.",0)}else{n.setUiError("inputNotConnected",null)}};if(!u.isLinked()){n.setUiError("outputNotConnected","To be able to hear sound playing, you need to connect this op to an Output op.",0)}else{n.setUiError("outputNotConnected",null)}u.onLinkChanged=()=>{if(!u.isLinked()){n.setUiError("outputNotConnected","To be able to hear sound playing, you need to connect this op to an Output op.",0)}else{n.setUiError("outputNotConnected",null)}};a.onChange=function(){if(a.get())I();else{if(v){v=false;c.set(v)}if(h){E(0);d.buffer=null;d=null}}};i.onChange=function(){if(!a.get())return;if(!d){if(!v)I()}if(i.get()){const e=0;C(e)}else{const t=0;E(t)}};r.onChange=function(){if(d){d.loop=!!r.get()}};l.onChange=_;function _(){if(!d)return;const e=l.get()||0;if(d.detune){d.detune.setValueAtTime(e,b.currentTime)}}s.onChange=O;function O(){if(!d)return;const e=s.get()||0;if(e>=d.playbackRate.minValue&&e<=d.playbackRate.maxValue){d.playbackRate.setValueAtTime(e,b.currentTime)}}let A=false;t.onTriggered=function(){if(!d)return;if(!a.get())return;else{if(!(a.get()instanceof AudioBuffer))return}if(i.get()){if(h){A=true;E(0)}else{C(0)}}};function I(e=false){if(v)return;if(!(a.get()instanceof AudioBuffer))return;v=true;c.set(v);if(d){d.onended=null;if(d.buffer){E(0);d.disconnect(x);d.buffer=null}d=null}d=b.createBufferSource();const t=a.get();if(!t){v=false;c.set(v);return}d.buffer=t;d.onended=M;d.loop=r.get();d.connect(x);O();_();u.set(x);v=false;c.set(v);if(A){C(0);A=false;return}if(i.get()&&!e){C(0)}}let T=false;let S=null;o.onChange=()=>{if(o.get()>=0)n.setUiError("offsetNegative",null);else{n.setUiError("offsetNegative","Offset cannot be negative. Setting to 0.",1)}if(d){if(d.buffer){if(o.get()>d.buffer.duration){n.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{n.setUiError("offsetTooLong",null)}}}};function C(t){try{if(d){let e=Math.max(0,o.get());d.start(t,e);h=true;f=false;m.set(true)}else{n.log("start() but no src...")}}catch(e){n.log("Error on start: ",e.message);m.set(false);h=false}}function y(){let e=!r.get();I(e)}function E(e){try{if(d){d.stop();if(!A)y()}h=false;m.set(false)}catch(e){n.setUiError(e);m.set(false)}}function M(){if(r.get()){h=true;f=false}else{h=false;f=true}m.set(h);y()}};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.WebAudio.Output_v2=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={};const t=i.inObject("Audio In",null,"audioNode"),r=i.inFloatSlider("Volume",1),o=i.inBool("Mute",false),n=i.inBool("Show Audio Suspended Button",true),s=i.outNumber("Current Volume",0),a=i.outString("Context State","unknown");i.setPortGroup("Volume Settings",[o,r]);let l=false;let u=CABLES.WEBAUDIO.createAudioContext(i);let m=u.createGain();const c=u.destination;let d=null;let h=false;o.onChange=()=>{v(o.get());b()};r.onChange=g;i.onMasterVolumeChanged=g;let f=i.patch.on("pause",g);let p=i.patch.on("resume",g);u.addEventListener("statechange",b);n.onChange=x;b();x();i.onDelete=()=>{if(m)m.disconnect();m=null;if(CABLES.interActionNeededButton)CABLES.interActionNeededButton.remove("audiosuspended");if(f)i.patch.off(f);if(p)i.patch.off(p)};t.onChange=function(){if(!t.get()){if(d){try{if(d.disconnect){d.disconnect(m)}}catch(e){i.logError(e)}}i.setUiError("multipleInputs",null);if(h){if(m)m.disconnect(c);h=false}}else{if(t.links.length>1)i.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 i.setUiError("multipleInputs",null);if(t.get().connect)t.get().connect(m)}d=t.get();if(!h){if(m)m.connect(c);h=true}g()};function g(e){const t=i.patch.config.masterVolume||0;let n=r.get()*t;if(i.patch._paused||o.get())n=0;let a=.05;if(e)a=.2;n=CABLES.clamp(n,0,1);if(!m)i.logError("gainNode undefined");if(m)m.gain.linearRampToValueAtTime(n,u.currentTime+a);s.set(n)}function v(e){if(e){if(u.state==="suspended"){if(m){m.gain.cancelScheduledValues(u.currentTime);m.gain.value=0;m.gain.setValueAtTime(0,u.currentTime)}s.set(0);return}}g(true)}function b(){a.set(u.state);i.logVerbose("audioCtx.state change",u.state);i.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(o.get())e=0;i.setUiError("ctxSusp",t,e)}x()}function x(){if(u.state=="suspended"){v(true);if(n.get()){l=true;if(CABLES.interActionNeededButton){CABLES.interActionNeededButton.add(i.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){i.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.Cables.LoadingStatus_v2=function(){CABLES.Op.apply(this,arguments);const a=this;const e=a.attachments={};const t=a.inTrigger("exe"),i=a.inValueBool("PreRender Ops"),r=a.inBool("Play Timeline",true),n=a.outTrigger("Next"),o=a.outBoolNum("Finished Initial Loading",false),s=a.outBoolNum("Loading"),l=a.outNumber("Progress"),u=a.outArray("Jobs"),m=a.outTrigger("Trigger Loading Finished ");const c=a.patch.cgl;const d=a.patch;let h=false;const f=[];let p=true;let g=0;document.body.classList.add("cables-loading");let v=c.patch.loading.start("loadingStatusInit","loadingStatusInit",a);a.patch.loading.on("finishedTask",b.bind(this));a.patch.loading.on("startTask",b.bind(this));function b(){const e=a.patch.loading.getListJobs();l.set(d.loading.getProgress());let t=e.length===0;const n=!t;if(n){u.set(a.patch.loading.getListJobs())}if(n){if(p){if(i.get())a.patch.preRenderOps();a.patch.timer.setTime(0);if(r.get()){a.patch.timer.play()}else{a.patch.timer.pause()}}p=false;document.body.classList.remove("cables-loading");document.body.classList.add("cables-loaded")}else{h=true;u.set(a.patch.loading.getListJobs());if(d.loading.getProgress()<1){a.patch.timer.setTime(0);a.patch.timer.pause()}}o.set(h);if(s.get()&&t)m.trigger();s.set(n);a.setUiAttribs({loading:n})}t.onTriggered=()=>{b();n.trigger();if(v){c.patch.loading.finished(v);v=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.Trigger.Sequence=function(){CABLES.Op.apply(this,arguments);const r=this;const e=r.attachments={};const t=r.inTrigger("exe"),n=r.inTriggerButton("Clean up connections");r.setUiAttrib({resizable:true,resizableY:false,stretchPorts:true});const a=[],o=[],i=16;let s=null,l=[];t.onTriggered=c;n.onTriggered=d;n.setUiAttribs({hideParam:true,hidePort:true});for(let t=0;t<i;t++){const h=r.outTrigger("trigger "+t);o.push(h);h.onLinkChanged=m;if(t<i-1){let e=r.inTrigger("exe "+t);e.onTriggered=c;a.push(e)}}u();function u(){l.length=0;for(let e=0;e<o.length;e++)if(o[e].links.length>0)l.push(o[e])}function m(){u();clearTimeout(s);s=setTimeout(()=>{let t=false;for(let e=0;e<o.length;e++)if(o[e].links.length>1)t=true;n.setUiAttribs({hideParam:!t});if(r.isCurrentUiOp())r.refreshParams()},60)}function c(){for(let e=0;e<l.length;e++)l[e].trigger()}function d(){let a=0;for(let n=0;n<o.length;n++){let t=[];if(o[n].links.length>1)for(let e=1;e<o[n].links.length;e++){while(o[a].links.length>0)a++;t.push(o[n].links[e]);const i=o[n].links[e].getOtherPort(o[n]);r.patch.link(r,"trigger "+a,i.op,i.name);a++}for(let e=0;e<t.length;e++)t[e].remove()}m();u()}};Ops.Trigger.Sequence.prototype=new CABLES.Op;CABLES.OPS["a466bc1f-06e9-4595-8849-bffb9fe22f99"]={f:Ops.Trigger.Sequence,objName:"Ops.Trigger.Sequence"};Ops.Html.Cursor=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValueSelect("cursor",["auto","crosshair","pointer","hand","move","n-resize","ne-resize","e-resize","se-resize","s-resize","sw-resize","w-resize","nw-resize","text","wait","help","none"]),a=e.inTriggerButton("Set Cursor"),i=e.patch.cgl;n.onChange=a.onTriggered=r;function r(){var e=n.get();i.canvas.style.cursor=e}};Ops.Html.Cursor.prototype=new CABLES.Op;CABLES.OPS["409f94da-6264-435c-8e73-03e8d2275e04"]={f:Ops.Html.Cursor,objName:"Ops.Html.Cursor"};Ops.Math.Sum=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValueFloat("number1",0),a=e.inValueFloat("number2",0),i=e.outNumber("result");e.setUiAttribs({mathTitle:true});n.onChange=a.onChange=r;r();function r(){const e=n.get()+a.get();if(!isNaN(e))i.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.Math.Divide=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValueFloat("number1",1),a=e.inValueFloat("number2",2),i=e.outNumber("result");e.setUiAttribs({mathTitle:true});n.onChange=a.onChange=r;r();function r(){i.set(n.get()/a.get())}};Ops.Math.Divide.prototype=new CABLES.Op;CABLES.OPS["86fcfd8c-038d-4b91-9820-a08114f6b7eb"]={f:Ops.Math.Divide,objName:"Ops.Math.Divide"};Ops.Boolean.IfTrueThen_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTrigger("exe"),a=e.inValueBool("boolean",false),i=e.outTrigger("then"),r=e.outTrigger("else");n.onTriggered=o;function o(){if(a.get())i.trigger();else r.trigger()}};Ops.Boolean.IfTrueThen_v2.prototype=new CABLES.Op;CABLES.OPS["9549e2ed-a544-4d33-a672-05c7854ccf5d"]={f:Ops.Boolean.IfTrueThen_v2,objName:"Ops.Boolean.IfTrueThen_v2"};Ops.TimeLine.DemoPrerender=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={};const t=i.inTrigger("Render"),n=i.inArray("Times"),a=i.inArray("Manual Timestamps"),r=i.inBool("Record Events",false),o=i.inTriggerButton("Reset"),s=i.inTriggerButton("Clear"),l=i.inBool("ReRender on Resize",true),u=i.outTrigger("Next"),m=i.outTrigger("Prerendered Frame"),c=i.outNumber("Progress",0),d=i.outNumber("Num Events");t.onTriggered=A;n.setUiAttribs({hidePort:true,hideParam:true});let h=true;let f=0;let p=false;let g=0;let v=0;let b=[0];i.patch.cgl.on("resize",()=>{if(l.get()){if(!h&&c.get()==1){g=i.patch.timer.getTime();v=i.patch.freeTimer.getTime();h=true;f=0}}});a.onChange=n.onChange=()=>{d.set(O().length);b=n.get()||[0]};i.patch.cgl.on("heavyEvent",e=>{if(r.get()&&!h&&CABLES.uniqueArray){b.push(Math.round(i.patch.timer.getTime()*60)/60);b=CABLES.uniqueArray(b);n.set(b)}});let x=0;o.onTriggered=()=>{h=true};s.onTriggered=()=>{b=[0];n.set(b)};function _(){return x*1e3}function O(){let e=[];e=e.concat(n.get()||[0]);if(a.get())e=e.concat(a.get());return e}function A(){if(r.get()){h=false;c.set(1);u.trigger();return}if(h){let e=O();if(f<e.length){const n=CABLES.internalNow;CABLES.internalNow=_;x=e[f];i.patch._frameNum=f+22;CABLES.overwriteTime=x;i.patch.timer.setTime(x);i.patch.freeTimer.setTime(x);CABLES.overwriteTime=undefined;CABLES.internalNow=n}const t=30;if(f>=e.length){const a=(t-(f-e.length))/t;i.patch.timer.setTime(a);i.patch.freeTimer.setTime(a)}u.trigger();u.trigger();c.set(Math.min(1,f/(e.length+t)));m.trigger();if(f>=e.length+t){i.patch.timer.setTime(g);i.patch.freeTimer.setTime(v);h=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.TimeLine.TimeLineControls=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.outBoolNum("Play/Stop");const a=e.outNumber("time");e.patch.timer.on("playPause",i);e.patch.timer.on("timeChange",i);function i(){n.set(false);setTimeout(function(){a.set(e.patch.timer.getTime());n.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.Html.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 n=e.inTrigger("Trigger"),a=e.inValueBool("Only if Audio Suspended"),i=e.inTriggerButton("Reset"),r=e.inStringEditor("Style Outer",t.outer_css),o=e.inStringEditor("Style Inner",t.inner_css),s=e.inBool("Active",true),l=e.outTrigger("Next"),u=e.outTrigger("Not Clicked"),m=e.outString("Audiocontext State","unknown"),c=e.outObject("Element"),d=e.outBoolNum("Clicked",false),h=e.outTrigger("Clicked Trigger");e.toWorkPortsNeedToBeLinked(n);let f=CABLES.WEBAUDIO.createAudioContext(e);const p=e.patch.cgl.canvas.parentElement;let g=false;let v=null;let b=null;x();r.onChange=o.onChange=x;f.addEventListener("statechange",_);_();s.onChange=()=>{if(!s.get())v.style.display="none";else v.style.display="block"};function x(){_();if(b)b.remove();if(v)v.remove();v=document.createElement("div");v.style=r.get();c.set(v);p.appendChild(v);b=document.createElement("div");b.style=o.get();v.appendChild(b);v.classList.add("playButton");v.addEventListener("mouseenter",T);v.addEventListener("mouseleave",I);v.addEventListener("click",O);v.addEventListener("touchStart",O);e.onDelete=A}i.onTriggered=function(){x();g=false;d.set(g)};function _(){m.set(f.state);if(a.get()&&f.state=="running")O()}n.onTriggered=function(){if(g)l.trigger();else u.trigger()};function O(){A();if(f&&f.state=="suspended")f.resume();g=true;d.set(g);h.trigger()}function A(){if(b)b.remove();if(v)v.remove()}function I(){if(v)v.style.opacity=.7}function T(){if(v)v.style.opacity=1}};Ops.Html.PlayButton.prototype=new CABLES.Op;CABLES.OPS["32e53fa2-4545-4c53-a94d-2204aa079246"]={f:Ops.Html.PlayButton,objName:"Ops.Html.PlayButton"};Ops.Boolean.Not=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValueBool("Boolean"),a=e.outBoolNum("Result");n.changeAlways=true;n.onChange=function(){a.set(!n.get())}};Ops.Boolean.Not.prototype=new CABLES.Op;CABLES.OPS["6d123c9f-7485-4fd9-a5c2-76e59dcbeb34"]={f:Ops.Boolean.Not,objName:"Ops.Boolean.Not"};Ops.Boolean.And=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValueBool("bool 1"),a=e.inValueBool("bool 2"),i=e.outBoolNum("result");n.onChange=a.onChange=r;function r(){i.set(a.get()&&n.get())}};Ops.Boolean.And.prototype=new CABLES.Op;CABLES.OPS["c26e6ce0-8047-44bb-9bc8-5a4f911ed8ad"]={f:Ops.Boolean.And,objName:"Ops.Boolean.And"};Ops.Math.Compare.Equals=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValue("number1",1),a=e.inValue("number2",1),i=e.outBoolNum("result");n.onChange=a.onChange=r;r();function r(){i.set(n.get()==a.get())}};Ops.Math.Compare.Equals.prototype=new CABLES.Op;CABLES.OPS["4dd3cc55-eebc-4187-9d4e-2e053a956fab"]={f:Ops.Math.Compare.Equals,objName:"Ops.Math.Compare.Equals"};Ops.Gl.Matrix.Transform=function(){CABLES.Op.apply(this,arguments);const n=this;const e=n.attachments={};const t=n.inTrigger("render"),a=n.inValue("posX",0),i=n.inValue("posY",0),r=n.inValue("posZ",0),o=n.inValue("scale",1),s=n.inValue("rotX",0),l=n.inValue("rotY",0),u=n.inValue("rotZ",0),m=n.outTrigger("trigger");n.setPortGroup("Rotation",[s,l,u]);n.setPortGroup("Position",[a,i,r]);n.setPortGroup("Scale",[o]);n.setUiAxisPorts(a,i,r);n.toWorkPortsNeedToBeLinked(t,m);const c=vec3.create();const d=vec3.create();const h=mat4.create();mat4.identity(h);let f=false,p=false,g=true,v=true,b=true;s.onChange=l.onChange=u.onChange=T;a.onChange=i.onChange=r.onChange=A;o.onChange=I;t.onTriggered=function(){let e=false;if(g){_();e=true}if(v){O();e=true}if(b)e=true;if(e)x();const t=n.patch.cg||n.patch.cgl;t.pushModelMatrix();mat4.multiply(t.mMatrix,t.mMatrix,h);m.trigger();t.popModelMatrix();if(CABLES.UI){if(!a.isLinked()&&!i.isLinked()&&!r.isLinked()){gui.setTransform(n.id,a.get(),i.get(),r.get());if(n.isCurrentUiOp())gui.setTransformGizmo({posX:a,posY:i,posZ:r})}}};function x(){mat4.identity(h);if(p)mat4.translate(h,h,c);if(s.get()!==0)mat4.rotateX(h,h,s.get()*CGL.DEG2RAD);if(l.get()!==0)mat4.rotateY(h,h,l.get()*CGL.DEG2RAD);if(u.get()!==0)mat4.rotateZ(h,h,u.get()*CGL.DEG2RAD);if(f)mat4.scale(h,h,d);b=false}function _(){p=false;if(a.get()!==0||i.get()!==0||r.get()!==0)p=true;vec3.set(c,a.get(),i.get(),r.get());g=false}function O(){f=true;vec3.set(d,o.get(),o.get(),o.get());v=false}function A(){g=true}function I(){v=true}function T(){b=true}x()};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.Ui.Area=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inString("Title",""),a=e.inTriggerButton("Delete");n.setUiAttribs({hidePort:true});e.setUiAttrib({hasArea:true});e.init=n.onChange=e.onLoaded=i;i();function i(){if(CABLES.UI){gui.savedState.setUnSaved("areaOp",e.getSubPatch());e.uiAttr({comment_title:n.get()||" "});e.name=n.get()}}a.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.Graphics.DepthTest=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=t.inTrigger("Render"),a=t.inValueBool("Enable depth testing",true),i=t.inValueSelect("Depth Test Method",["never","always","less","less or equal","greater","greater or equal","equal","not equal"],"less or equal"),r=t.inValueBool("Write to depth buffer",true),o=t.outTrigger("Next");const s=t.patch.cgl;let l=CABLES.CG.DEPTH_COMPARE_LESSEQUAL;i.onChange=u;function u(){const e=i.get();if(e=="never")l=CABLES.CG.DEPTH_COMPARE_NEVER;else if(e=="always")l=CABLES.CG.DEPTH_COMPARE_ALWAYS;else if(e=="less")l=CABLES.CG.DEPTH_COMPARE_LESS;else if(e=="less or equal")l=CABLES.CG.DEPTH_COMPARE_LESSEQUAL;else if(e=="greater")l=CABLES.CG.DEPTH_COMPARE_GREATER;else if(e=="greater or equal")l=CABLES.CG.DEPTH_COMPARE_GREATEREQUAL;else if(e=="equal")l=CABLES.CG.DEPTH_COMPARE_EQUAL;else if(e=="not equal")l=CABLES.CG.DEPTH_COMPARE_NOTEQUAL}n.onTriggered=function(){const e=t.patch.cg;if(!e)return;t.patch.cg.pushDepthTest(a.get());t.patch.cg.pushDepthWrite(r.get());t.patch.cg.pushDepthFunc(e.DEPTH_FUNCS[l]);o.trigger();t.patch.cg.popDepthTest();t.patch.cg.popDepthWrite();t.patch.cg.popDepthFunc()}};Ops.Graphics.DepthTest.prototype=new CABLES.Op;CABLES.OPS["3996ed5d-8143-4bec-9cfd-c1b193a295af"]={f:Ops.Graphics.DepthTest,objName:"Ops.Graphics.DepthTest"};Ops.Gl.ClearColor=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTrigger("render"),a=e.outTrigger("trigger"),i=e.inFloatSlider("r",.1),r=e.inFloatSlider("g",.1),o=e.inFloatSlider("b",.1),s=e.inFloatSlider("a",1);i.setUiAttribs({colorPick:true});const l=e.patch.cgl;n.onTriggered=function(){l.gl.clearColor(i.get(),r.get(),o.get(),s.get());l.gl.clear(l.gl.COLOR_BUFFER_BIT|l.gl.DEPTH_BUFFER_BIT);a.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.Shader.BasicMaterial_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={basicmaterial_frag:"{{MODULES_HEAD}}\n\nIN vec2 texCoord;\nUNI vec4 color;\n// UNI float r;\n// UNI float g;\n// UNI float b;\n// UNI float a;\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\nvoid main()\n{\n    {{MODULE_BEGIN_FRAG}}\n    vec4 col=color;\n\n    #ifdef HAS_TEXTURES\n        // vec2 uv=vec2(texCoord.s,1.0-texCoord.t);\n        vec2 uv=texCoord;\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=vec2(texCoordOrig.s,1.0-texCoordOrig.t);\n                uv=texCoordOrig;\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    outColor = col;\n}\n",basicmaterial_vert:"IN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\nIN float attrVertIndex;\n\n{{MODULES_HEAD}}\n\nOUT vec3 norm;\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\nvoid main()\n{\n    mat4 mMatrix=modelMatrix;\n    mat4 mvMatrix;\n\n    norm=attrVertNormal;\n    texCoordOrig=vec2(attrTexCoord.x,1.0-attrTexCoord.y);\n    texCoord=vec2(attrTexCoord.x,1.0-attrTexCoord.y);\n    #ifdef HAS_TEXTURES\n        texCoord.x=texCoord.x*diffuseRepeatX+texOffsetX;\n        texCoord.y=texCoord.y*diffuseRepeatY+texOffsetY;\n    #endif\n\n    vec4 pos = vec4(vPosition, 1.0);\n\n    #ifdef BILLBOARD\n       vec3 position=vPosition;\n       mvMatrix=viewMatrix*modelMatrix;\n\n       gl_Position = projMatrix * mvMatrix * vec4((\n           position.x * vec3(\n               mvMatrix[0][0],\n               mvMatrix[1][0],\n               mvMatrix[2][0] ) +\n           position.y * vec3(\n               mvMatrix[0][1],\n               mvMatrix[1][1],\n               mvMatrix[2][1]) ), 1.0);\n    #endif\n\n    {{MODULE_VERTEX_POSITION}}\n\n    #ifndef BILLBOARD\n        mvMatrix=viewMatrix * mMatrix;\n    #endif\n\n\n    #ifndef BILLBOARD\n        // gl_Position = projMatrix * viewMatrix * modelMatrix * pos;\n        gl_Position = projMatrix * mvMatrix * pos;\n    #endif\n}\n"};const n=e.inTrigger("render");const a=e.outTrigger("trigger");const i=e.outObject("shader");i.ignoreValueSerialize=true;const r=e.patch.cgl;e.toWorkPortsNeedToBeLinked(n);const o=new CGL.Shader(r,"basicmaterialnew");o.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"]);o.setSource(t.basicmaterial_vert,t.basicmaterial_frag);i.set(o);n.onTriggered=s;e.preRender=function(){o.bind();s()};function s(){if(!o)return;r.pushShader(o);o.popTextures();if(f&&h.get())o.pushTexture(f,h.get().tex);if(b&&v.get())o.pushTexture(b,v.get().tex);a.trigger();r.popShader()}const l=e.inValueSlider("r",Math.random());const u=e.inValueSlider("g",Math.random());const m=e.inValueSlider("b",Math.random());const c=e.inValueSlider("a",1);l.setUiAttribs({colorPick:true});const d=new CGL.Uniform(o,"4f","color",l,u,m,c);e.setPortGroup("Color",[l,u,m,c]);var h=e.inTexture("texture");var f=null;h.onChange=p;function p(){if(h.get()){if(!o.hasDefine("HAS_TEXTURE_DIFFUSE"))o.define("HAS_TEXTURE_DIFFUSE");if(!f)f=new CGL.Uniform(o,"t","texDiffuse",0);I.setUiAttribs({greyout:false});T.setUiAttribs({greyout:false});S.setUiAttribs({greyout:false});C.setUiAttribs({greyout:false});g.setUiAttribs({greyout:false})}else{o.removeUniform("texDiffuse");o.removeDefine("HAS_TEXTURE_DIFFUSE");f=null;I.setUiAttribs({greyout:true});T.setUiAttribs({greyout:true});S.setUiAttribs({greyout:true});C.setUiAttribs({greyout:true});g.setUiAttribs({greyout:true})}}const g=e.inValueBool("colorizeTexture",false);e.setPortGroup("Color Texture",[h,g]);var v=e.inTexture("textureOpacity");var b=null;e.alphaMaskSource=e.inSwitch("Alpha Mask Source",["Luminance","R","G","B","A"],"Luminance");e.alphaMaskSource.onChange=x;e.alphaMaskSource.setUiAttribs({greyout:true});function x(){if(e.alphaMaskSource.get()=="A")o.define("ALPHA_MASK_ALPHA");else o.removeDefine("ALPHA_MASK_ALPHA");if(e.alphaMaskSource.get()=="Luminance")o.define("ALPHA_MASK_LUMI");else o.removeDefine("ALPHA_MASK_LUMI");if(e.alphaMaskSource.get()=="R")o.define("ALPHA_MASK_R");else o.removeDefine("ALPHA_MASK_R");if(e.alphaMaskSource.get()=="G")o.define("ALPHA_MASK_G");else o.removeDefine("ALPHA_MASK_G");if(e.alphaMaskSource.get()=="B")o.define("ALPHA_MASK_B");else o.removeDefine("ALPHA_MASK_B")}v.onChange=_;function _(){if(v.get()){if(b!==null)return;o.removeUniform("texOpacity");o.define("HAS_TEXTURE_OPACITY");if(!b)b=new CGL.Uniform(o,"t","texOpacity",1);e.alphaMaskSource.setUiAttribs({greyout:false});A.setUiAttribs({greyout:false});O.setUiAttribs({greyout:false})}else{o.removeUniform("texOpacity");o.removeDefine("HAS_TEXTURE_OPACITY");b=null;e.alphaMaskSource.setUiAttribs({greyout:true});A.setUiAttribs({greyout:true});O.setUiAttribs({greyout:true})}x()}var O=e.inValueBool("Opacity TexCoords Transform",false);const A=e.inValueBool("Discard Transparent Pixels");A.onChange=function(){if(A.get())o.define("DISCARDTRANS");else o.removeDefine("DISCARDTRANS")};O.onChange=function(){if(O.get())o.define("TRANSFORMALPHATEXCOORDS");else o.removeDefine("TRANSFORMALPHATEXCOORDS")};e.setPortGroup("Opacity",[v,e.alphaMaskSource,A,O]);g.onChange=function(){if(g.get())o.define("COLORIZE_TEXTURE");else o.removeDefine("COLORIZE_TEXTURE")};const I=e.inValue("diffuseRepeatX",1);const T=e.inValue("diffuseRepeatY",1);const S=e.inValue("Tex Offset X",0);const C=e.inValue("Tex Offset Y",0);const y=new CGL.Uniform(o,"f","diffuseRepeatX",I);const E=new CGL.Uniform(o,"f","diffuseRepeatY",T);const M=new CGL.Uniform(o,"f","texOffsetX",S);const P=new CGL.Uniform(o,"f","texOffsetY",C);e.setPortGroup("Texture Transform",[I,T,S,C]);const N=e.inValueBool("billboard",false);N.onChange=function(){if(N.get())o.define("BILLBOARD");else o.removeDefine("BILLBOARD")};_();p()};Ops.Gl.Shader.BasicMaterial_v2.prototype=new CABLES.Op;CABLES.OPS["51f2207b-daaa-447f-bdbe-87fdd72f0c40"]={f:Ops.Gl.Shader.BasicMaterial_v2,objName:"Ops.Gl.Shader.BasicMaterial_v2"};Ops.Gl.Meshes.Rectangle=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};var n=e.inTrigger("render");var a=e.outTrigger("trigger");var A=e.inValue("width",1);var I=e.inValue("height",1);var T=e.inSwitch("pivot x",["left","center","right"]);var S=e.inSwitch("pivot y",["top","center","bottom"]);var C=e.inValueInt("num columns",1);var y=e.inValueInt("num rows",1);var E=e.inSwitch("axis",["xy","xz"],"xy");var i=e.inValueBool("Active",true);var M=e.outObject("geometry");M.ignoreValueSerialize=true;var P=e.patch.cgl;E.set("xy");T.set("center");S.set("center");e.setPortGroup("Pivot",[T,S]);e.setPortGroup("Size",[A,I]);e.setPortGroup("Structure",[C,y]);var N=new CGL.Geometry("rectangle");var j=null;var L=false;E.onChange=T.onChange=S.onChange=A.onChange=I.onChange=y.onChange=C.onChange=r;o();function r(){o()}e.preRender=n.onTriggered=function(){if(!CGL.TextureEffect.checkOpNotInTextureEffect(e))return;if(L)o();if(i.get()&&j)j.render(P.getShader());a.trigger()};function o(){var e=A.get();var t=parseFloat(I.get());var n=0;var a=0;if(typeof e=="string")e=parseFloat(e);if(typeof t=="string")t=parseFloat(t);if(T.get()=="center")n=0;else if(T.get()=="right")n=-e/2;else if(T.get()=="left")n=+e/2;if(S.get()=="center")a=0;else if(S.get()=="top")a=-t/2;else if(S.get()=="bottom")a=+t/2;var i=[];var r=[];var o=[];var s=[];var l=[];var u=[];var m=Math.round(y.get());var c=Math.round(C.get());var d=e/c;var h=t/m;var f,p,g;g=E.get();for(p=0;p<=m;p++){for(f=0;f<=c;f++){i.push(f*d-A.get()/2+n);if(g=="xz")i.push(0);i.push(p*h-I.get()/2+a);if(g=="xy")i.push(0);r.push(f/c);r.push(1-p/m);if(g=="xz"){o.push(0,1,0);s.push(1,0,0);l.push(0,0,1)}else if(g=="xy"){o.push(0,0,1);s.push(-1,0,0);l.push(0,-1,0)}}}for(f=0;f<c;f++){for(p=0;p<m;p++){var v=f+(c+1)*p;var b=v;var x=v+1;var _=v+c+1;var O=v+1+c+1;u.push(b);u.push(_);u.push(x);u.push(x);u.push(_);u.push(O)}}N.clear();N.vertices=i;N.texCoords=r;N.verticesIndices=u;N.vertexNormals=o;N.tangents=s;N.biTangents=l;if(c*m>64e3)N.unIndex();if(!j)j=new CGL.Mesh(P,N);else j.setGeom(N);M.set(null);M.set(N);L=false}e.onDelete=function(){if(j)j.dispose()}};Ops.Gl.Meshes.Rectangle.prototype=new CABLES.Op;CABLES.OPS["20f3c4e7-04d1-44e0-b868-05756d1c66c6"]={f:Ops.Gl.Meshes.Rectangle,objName:"Ops.Gl.Meshes.Rectangle"};Ops.Extension.Deprecated.ScaleXYZ=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=t.inTrigger("render"),a=t.inValueFloat("x",1),i=t.inValueFloat("y",1),r=t.inValueFloat("z",1),o=t.outTrigger("trigger");const s=vec3.create();let l=true;a.onChange=i.onChange=r.onChange=m;m();n.onTriggered=u;function u(){const e=t.patch.cg||t.patch.cgl;if(l){vec3.set(s,a.get(),i.get(),r.get());l=false}e.pushModelMatrix();mat4.scale(e.mMatrix,e.mMatrix,s);o.trigger();e.popModelMatrix()}function m(){l=true}};Ops.Extension.Deprecated.ScaleXYZ.prototype=new CABLES.Op;CABLES.OPS["9ba52457-5f0d-4b20-a97c-4ec4856b8e29"]={f:Ops.Extension.Deprecated.ScaleXYZ,objName:"Ops.Extension.Deprecated.ScaleXYZ"};Ops.Math.OneMinus=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValue("Value"),a=e.outNumber("Result");n.onChange=i;i();function i(){a.set(1-n.get())}};Ops.Math.OneMinus.prototype=new CABLES.Op;CABLES.OPS["f34d019d-59ae-40d6-a55d-a7691bbc40e0"]={f:Ops.Math.OneMinus,objName:"Ops.Math.OneMinus"};Ops.Cables.UIMode=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.outBoolNum("UI",e.patch.isEditorMode()),a=e.outBoolNum("Overlay Mode",false),i=e.outBoolNum("Remote Viewer",window.gui?window.gui.isRemoteClient:false),r=e.outBoolNum("Is Standalone",CABLES.platform&&CABLES.platform.frontendOptions.isStandalone),o=e.outNumber("Canvas Mode"),s=e.outBoolNum("Patch Field Visible");if(CABLES.UI){a.set(gui.shouldDrawOverlay);gui.on("overlaysChanged",e=>{a.set(e)});gui.on("canvasModeChange",()=>{o.set(gui.canvasManager.mode);s.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.Html.CSS.CSS_v2=function(){CABLES.Op.apply(this,arguments);const n=this;const e=n.attachments={};const a=n.inStringEditor("css code"),t=n.inBool("Active",true);a.setUiAttribs({editorSyntax:"css",ignoreBigPort:true});let i=null;const r="css_"+CABLES.uuid();a.onChange=s;s();t.onChange=()=>{if(!t.get())i.remove();else l()};function o(){let t=a.get();if(t){let e=null;if(n.storage&&n.storage.blueprint&&n.storage.blueprint.patchId){e=n.storage.blueprint.patchId}t=t.replace(new RegExp("{{ASSETPATH}}","g"),n.patch.getAssetPath(e))}return t}function s(){i=n.patch.getDocument().getElementById(r);if(i){i.textContent=o()}else{i=n.patch.getDocument().createElement("style");i.type="text/css";i.id=r;i.textContent=e.css_spinner;i.classList.add("cablesEle");l()}}function l(){const e=n.patch.getDocument().getElementsByTagName("body")[0];e.appendChild(i)}n.onDelete=function(){i=n.patch.getDocument().getElementById(r);if(i)i.remove()}};Ops.Html.CSS.CSS_v2.prototype=new CABLES.Op;CABLES.OPS["a56d3edd-06ad-44ed-9810-dbf714600c67"]={f:Ops.Html.CSS.CSS_v2,objName:"Ops.Html.CSS.CSS_v2"};Ops.Devices.Mouse.Mouse_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const k=e.attachments={};const t=e.inValueBool("Active",true),n=e.inValueBool("relative"),i=e.inValueBool("normalize"),a=e.inValueBool("flip y",true),r=e.inValueSelect("Area",["Canvas","Document","Parent Element"],"Canvas"),o=e.inBool("right click prevent default",true),s=e.inValueBool("Touch support",true),l=e.inValueBool("smooth"),u=e.inValueFloat("smoothSpeed",20),m=e.inValueFloat("multiply",1),c=e.outNumber("x",0),d=e.outNumber("y",0),h=e.outBoolNum("button down"),B=e.outTrigger("click"),D=e.outTrigger("Button Up"),G=e.outTrigger("click right"),f=e.outBoolNum("mouseOver"),p=e.outNumber("button");e.setPortGroup("Behavior",[n,i,a,r,o,s]);e.setPortGroup("Smoothing",[l,u,m]);let g=0;const v=e.patch.cgl;let b=null;function x(n,a){if(i.get()){let e=v.canvas.width/v.pixelDensity;let t=v.canvas.height/v.pixelDensity;if(b==document.body){e=b.clientWidth/v.pixelDensity;t=b.clientHeight/v.pixelDensity}c.set(((n||0)/e*2-1)*m.get());d.set(((a||0)/t*2-1)*m.get())}else{c.set((n||0)*m.get());d.set((a||0)*m.get())}}l.onChange=function(){if(l.get())g=setInterval(V,5);else if(g)clearTimeout(g)};let U,F;let _=0,O=0;i.onChange=function(){A=0;I=0;x(A,I)};let A=v.canvas.width/2;let I=v.canvas.height/2;_=A;O=I;c.set(A);d.set(I);let T=0;let S=0;let C=0;let y=0;R();r.onChange=R;let E=0;function V(){E=u.get();if(E<=0)E=.01;const e=Math.abs(A-_);const t=Math.round(e/E,0);_=_<A?_+t:_-t;const n=Math.abs(I-O);const a=Math.round(n/E,0);O=O<I?O+a:O-a;x(_,O)}function M(e){h.set(false);f.set(true);E=u.get()}function P(e){p.set(e.which);h.set(true)}function N(e){p.set(0);h.set(false);D.trigger()}function j(e){G.trigger();if(o.get())e.preventDefault()}function L(e){B.trigger()}function z(e){T=0;S=0;E=100;f.set(false);h.set(false)}n.onChange=function(){C=0;y=0};function X(e){if(!n.get()){if(r.get()!="Document"){C=e.offsetX;y=e.offsetY}else{C=e.clientX;y=e.clientY}if(l.get()){A=C;if(a.get())I=b.clientHeight-y;else I=y}else{if(a.get())x(C,b.clientHeight-y);else x(C,y)}}else{if(T!=0&&S!=0){C=e.offsetX-T;y=e.offsetY-S}else{}T=e.offsetX;S=e.offsetY;A+=C;I+=y;if(I>460)I=460}}function q(e){f.set(true);X(e)}function H(e){if(event.touches&&event.touches.length>0)X(e.touches[0])}function W(e){h.set(true);if(e.touches&&e.touches.length>0)P(e.touches[0])}function Y(e){h.set(false);N()}s.onChange=function(){w();R()};function w(){if(!b)return;b.removeEventListener("touchend",Y);b.removeEventListener("touchstart",W);b.removeEventListener("touchmove",H);b.removeEventListener("click",L);b.removeEventListener("mousemove",q);b.removeEventListener("mouseleave",z);b.removeEventListener("mousedown",P);b.removeEventListener("mouseup",N);b.removeEventListener("mouseenter",M);b.removeEventListener("contextmenu",j);b=null}function R(){if(b||!t.get())w();if(!t.get())return;b=v.canvas;if(r.get()=="Document")b=document.body;if(r.get()=="Parent Element")b=v.canvas.parentElement;if(s.get()){b.addEventListener("touchend",Y);b.addEventListener("touchstart",W);b.addEventListener("touchmove",H)}b.addEventListener("mousemove",q);b.addEventListener("mouseleave",z);b.addEventListener("mousedown",P);b.addEventListener("mouseup",N);b.addEventListener("mouseenter",M);b.addEventListener("contextmenu",j);b.addEventListener("click",L)}t.onChange=function(){if(b)w();if(t.get())R()};e.onDelete=function(){w()};R()};Ops.Devices.Mouse.Mouse_v2.prototype=new CABLES.Op;CABLES.OPS["9fa3fc46-3147-4e3a-8ee8-a93ea9e8786e"]={f:Ops.Devices.Mouse.Mouse_v2,objName:"Ops.Devices.Mouse.Mouse_v2"};Ops.Boolean.ToggleBool=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTriggerButton("trigger"),a=e.inTriggerButton("reset"),i=e.outBool("result"),r=e.inBool("Default",false);let o=false;i.set(o);i.ignoreValueSerialize=true;n.onTriggered=function(){o=!o;i.set(o)};a.onTriggered=function(){o=r.get();i.set(o)}};Ops.Boolean.ToggleBool.prototype=new CABLES.Op;CABLES.OPS["712a25f4-3a93-4042-b8c5-2f56169186cc"]={f:Ops.Boolean.ToggleBool,objName:"Ops.Boolean.ToggleBool"};Ops.Trigger.TriggerSend=function(){CABLES.Op.apply(this,arguments);const a=this;const e=a.attachments={};const t=a.inTriggerButton("Trigger");a.varName=a.inValueSelect("Named Trigger",[],"",true);a.varName.onChange=i;t.onTriggered=r;a.patch.addEventListener("namedTriggersChanged",n);n();function n(){if(CABLES.UI){let e=[];const t=a.patch.namedTriggers;e.push("+ create new one");for(const n in t)e.push(n);e=e.sort();a.varName.uiAttribs.values=e}}function i(){if(CABLES.UI){if(a.varName.get()=="+ create new one"){new CABLES.UI.ModalDialog({prompt:true,title:"New Trigger",text:"Enter a name for the new trigger",promptValue:"",promptOk:e=>{a.varName.set(e);a.patch.namedTriggers[e]=a.patch.namedTriggers[e]||[];n()}});return}a.refreshParams()}if(!a.patch.namedTriggers[a.varName.get()]){a.patch.namedTriggers[a.varName.get()]=a.patch.namedTriggers[a.varName.get()]||[];a.patch.emitEvent("namedTriggersChanged")}a.setTitle(">"+a.varName.get());a.refreshParams();a.patch.emitEvent("opTriggerNameChanged",a,a.varName.get())}function r(){const t=a.patch.namedTriggers[a.varName.get()];a.patch.emitEvent("namedTriggerSent",a.varName.get());if(!t){a.setUiError("unknowntrigger","unknown trigger");return}else a.setUiError("unknowntrigger",null);for(let e=0;e<t.length;e++){t[e]()}}};Ops.Trigger.TriggerSend.prototype=new CABLES.Op;CABLES.OPS["ce1eaf2b-943b-4dc0-ab5e-ee11b63c9ed0"]={f:Ops.Trigger.TriggerSend,objName:"Ops.Trigger.TriggerSend"};Ops.Gl.ClearDepth=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTrigger("render"),a=e.outTrigger("trigger"),i=e.patch.cgl;n.onTriggered=function(){i.gl.clear(i.gl.DEPTH_BUFFER_BIT);a.trigger()}};Ops.Gl.ClearDepth.prototype=new CABLES.Op;CABLES.OPS["9e8a4b73-4ba7-4c4f-b266-81c5f9db9b7a"]={f:Ops.Gl.ClearDepth,objName:"Ops.Gl.ClearDepth"};Ops.Gl.ImageCompose.ImageCompose_v3=function(){CABLES.Op.apply(this,arguments);const n=this;const e=n.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 a=n.patch.cgl,t=n.inTrigger("Render"),i=n.inTexture("Base Texture"),r=n.inTexture("UV Texture"),o=n.inSwitch("Size",["Auto","Manual"],"Auto"),s=n.inValueInt("Width",640),l=n.inValueInt("Height",480),u=n.inSwitch("Filter",["nearest","linear","mipmap"],"linear"),m=n.inValueSelect("Wrap",["clamp to edge","repeat","mirrored repeat"],"repeat"),c=n.inDropDown("Pixel Format",CGL.Texture.PIXELFORMATS,CGL.Texture.PFORMATSTR_RGBA8UB),d=n.inValueSlider("R",0),h=n.inValueSlider("G",0),f=n.inValueSlider("B",0),p=n.inValueSlider("A",0),g=n.outTrigger("Next"),v=n.outTexture("texture_out",CGL.Texture.getEmptyTexture(a)),b=n.outNumber("Aspect Ratio"),x=n.outNumber("Texture Width"),R=n.outNumber("Texture Height");n.setPortGroup("Texture Size",[o,s,l]);n.setPortGroup("Texture Parameters",[m,u,c]);d.setUiAttribs({colorPick:true});n.setPortGroup("Color",[d,h,f,p]);n.toWorkPortsNeedToBeLinked(t);const _=[0,0,0,0];let O=null;let A=null;let I=true;let k=false;let T=null;let B=null;let D=null;let G=null;m.onChange=u.onChange=c.onChange=U;i.onLinkChanged=o.onChange=r.onChange=j;t.onTriggered=n.preRender=w;j();function S(){if(O)O.delete();if(A)A.delete();O=new CGL.TextureEffect(a,{isFloatingPointTexture:CGL.Texture.isPixelFormatFloat(c.get())});A=new CGL.Texture(a,{name:"image_compose_v2_"+n.id,isFloatingPointTexture:CGL.Texture.isPixelFormatFloat(c.get()),pixelFormat:c.get(),filter:C(),wrap:y(),width:E(),height:M()});O.setSourceTexture(A);x.set(E());R.set(M());b.set(E()/M());v.set(CGL.Texture.getEmptyTexture(a));I=false;j()}function C(){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 y(){if(m.get()=="repeat")return CGL.Texture.WRAP_REPEAT;else if(m.get()=="mirrored repeat")return CGL.Texture.WRAP_MIRRORED_REPEAT;else if(m.get()=="clamp to edge")return CGL.Texture.WRAP_CLAMP_TO_EDGE}function E(){if(i.get()&&o.get()=="Auto")return i.get().width;if(o.get()=="Auto")return a.getViewPort()[2];return Math.ceil(s.get())}function M(){if(i.get()&&o.get()=="Auto")return i.get().height;else if(o.get()=="Auto")return a.getViewPort()[3];else return Math.ceil(l.get())}function U(){I=true}function F(){if((E()!=A.width||M()!=A.height||A.pixelFormat!=c.get()||A.filter!=C()||A.wrap!=y())&&(E()!==0&&M()!==0)){S();O.setSourceTexture(A);v.set(CGL.Texture.getEmptyTexture(a));v.set(A);P();L()}}function P(){let e=null;if(o.get()=="Manual"){e=null}else if(o.get()=="Auto"){if(i.get())e="Input Texture";else e="Canvas Size";e+=": "+E()+" x "+M()}let t=false;t=o.uiAttribs.info!=e;o.setUiAttribs({info:e});if(t)n.refreshParams()}function N(){if(T)T.toggleDefine("USE_TEX",i.isLinked());if(T)T.toggleDefine("USE_UVTEX",r.isLinked())}function j(){d.setUiAttribs({greyout:i.isLinked()});f.setUiAttribs({greyout:i.isLinked()});h.setUiAttribs({greyout:i.isLinked()});p.setUiAttribs({greyout:i.isLinked()});s.setUiAttribs({greyout:o.get()=="Auto"});l.setUiAttribs({greyout:o.get()=="Auto"});s.setUiAttribs({hideParam:o.get()!="Manual"});l.setUiAttribs({hideParam:o.get()!="Manual"});if(A)if(CGL.Texture.isPixelFormatFloat(c.get())&&C()==CGL.Texture.FILTER_MIPMAP)n.setUiError("fpmipmap","Don't use mipmap and 32bit at the same time, many systems do not support this.");else n.setUiError("fpmipmap",null);P();N();L()}function L(){if(A)if(i.isLinked()&&i.get()&&A.textureType!=i.get().textureType&&(A.textureType!=CGL.Texture.TYPE_FLOAT||i.get().textureType==CGL.Texture.TYPE_FLOAT))n.setUiError("textypediff","Drawing 32bit texture into an 8 bit can result in data/precision loss",1);else n.setUiError("textypediff",null)}n.preRender=()=>{w()};function V(){if(!T){T=new CGL.Shader(a,"copytextureshader");T.setSource(T.getDefaultVertexShader(),e.imgcomp_frag);B=new CGL.Uniform(T,"t","tex",0);D=new CGL.Uniform(T,"t","UVTex",1);G=new CGL.Uniform(T,"4f","bgColor",d,h,f,p);N()}a.pushShader(T);a.currentTextureEffect.bind();if(i.get())a.setTexture(0,i.get().tex);if(r.get())a.setTexture(1,r.get().tex);a.currentTextureEffect.finish();a.popShader()}function w(){if(!O||I)S();const e=a.getViewPort();_[0]=e[0];_[1]=e[1];_[2]=e[2];_[3]=e[3];a.pushBlend(false);F();const t=a.currentTextureEffect;a.currentTextureEffect=O;a.currentTextureEffect.imgCompVer=3;a.currentTextureEffect.width=s.get();a.currentTextureEffect.height=l.get();O.setSourceTexture(A);O.startEffect(i.get()||CGL.Texture.getEmptyTexture(a,k),true);V();g.trigger();v.setRef(O.getCurrentSourceTexture());O.endEffect();a.setViewPort(_[0],_[1],_[2],_[3]);a.popBlend(false);a.currentTextureEffect=t}};Ops.Gl.ImageCompose.ImageCompose_v3.prototype=new CABLES.Op;CABLES.OPS["e890a050-11b7-456e-b09b-d08cd9c1ee41"]={f:Ops.Gl.ImageCompose.ImageCompose_v3,objName:"Ops.Gl.ImageCompose.ImageCompose_v3"};Ops.Gl.Meshes.FullscreenRectangle=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 n=e.inTrigger("render"),a=e.inSwitch("Scale",["Stretch","Fit"],"Fit"),i=e.inValueBool("Flip Y"),r=e.inValueBool("Flip X"),o=e.inTexture("Texture"),s=e.outTrigger("trigger");const l=e.patch.cgl;let u=null;let m=new CGL.Geometry("fullscreen rectangle");let c=0,d=0,h=0,f=0,p=0;e.toWorkShouldNotBeChild("Ops.Gl.TextureEffects.ImageCompose",CABLES.OP_PORT_TYPE_FUNCTION);e.toWorkPortsNeedToBeLinked(n);r.onChange=S;i.onChange=S;n.onTriggered=T;o.onLinkChanged=O;a.onChange=I;const g=new CGL.Shader(l,"fullscreenrectangle",this);g.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"]);g.setSource(t.shader_vert,t.shader_frag);g.fullscreenRectUniform=new CGL.Uniform(g,"t","tex",0);g.aspectUni=new CGL.Uniform(g,"f","aspectTex",0);let v=false;let b=true;let x=false;let _=[];O();I();o.onChange=function(){b=true};function O(){if(!CABLES.UI)return;i.setUiAttribs({greyout:!o.isLinked()});r.setUiAttribs({greyout:!o.isLinked()});a.setUiAttribs({greyout:!o.isLinked()})}function A(){let e=o.get();if(e)v=true;else v=false}e.preRender=function(){A();g.bind();if(u)u.render(g);T()};function I(){x=a.get()=="Fit"}function T(){if(l.getViewPort()[2]!=f||l.getViewPort()[3]!=p||!u)C();if(b)A();l.pushPMatrix();mat4.identity(l.pMatrix);mat4.ortho(l.pMatrix,0,f,p,0,-10,1e3);l.pushModelMatrix();mat4.identity(l.mMatrix);l.pushViewMatrix();mat4.identity(l.vMatrix);if(x&&o.get()){const n=o.get().width/o.get().height;let e=p;let t=p*n;if(t>f){e=f*1/n;t=f}_[0]=l.getViewPort()[0];_[1]=l.getViewPort()[1];_[2]=l.getViewPort()[2];_[3]=l.getViewPort()[3];l.setViewPort((f-t)/2,(p-e)/2,t,e)}if(v){if(o.get())l.setTexture(0,o.get().tex);u.render(g)}else{u.render(l.getShader())}l.gl.clear(l.gl.DEPTH_BUFFER_BIT);l.popPMatrix();l.popModelMatrix();l.popViewMatrix();if(x&&o.get())l.setViewPort(_[0],_[1],_[2],_[3]);s.trigger()}function S(){u=null}function C(){const e=l.getViewPort();if(e[2]==f&&e[3]==p&&u)return;let t=0,n=0;f=e[2];p=e[3];m.vertices=new Float32Array([t+f,n+p,0,t,n+p,0,t+f,n,0,t,n,0]);let a=null;if(i.get())a=new Float32Array([1,0,0,0,1,1,0,1]);else a=new Float32Array([1,1,0,1,1,0,0,0]);if(r.get()){a[0]=0;a[2]=1;a[4]=0;a[6]=1}m.setTexCoords(a);m.verticesIndices=new Uint16Array([2,1,0,3,1,2]);m.vertexNormals=new Float32Array([0,0,1,0,0,1,0,0,1,0,0,1]);m.tangents=new Float32Array([-1,0,0,-1,0,0,-1,0,0,-1,0,0]);m.biTangents==new Float32Array([0,-1,0,0,-1,0,0,-1,0,0,-1,0]);if(!u)u=new CGL.Mesh(l,m);else u.setGeom(m)}};Ops.Gl.Meshes.FullscreenRectangle.prototype=new CABLES.Op;CABLES.OPS["255bd15b-cc91-4a12-9b4e-53c710cbb282"]={f:Ops.Gl.Meshes.FullscreenRectangle,objName:"Ops.Gl.Meshes.FullscreenRectangle"};Ops.Ui.PatchInput=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={};const r=i.addOutPort(new CABLES.Port(i,"create port",CABLES.OP_PORT_TYPE_DYNAMIC));function o(){for(let e in i.patch.ops){if(i.patch.ops[e].patchId){if(i.patch.ops[e].patchId.get()==i.uiAttribs.subPatch){return i.patch.ops[e]}}}}r.onLinkChanged=()=>{const e=o();if(!r.links.length||!e||!e.addNewInPort)return;const t=r.links[0].getOtherPort(r);r.removeLinks();const n=e.addNewInPort(t);const a=gui.scene().link(t.parent,t.getName(),i,n);e.saveData()}};Ops.Ui.PatchInput.prototype=new CABLES.Op;CABLES.OPS["e3f68bc3-892a-4c78-9974-aca25c27025d"]={f:Ops.Ui.PatchInput,objName:"Ops.Ui.PatchInput"};Ops.Ui.PatchOutput=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={};const r=i.addInPort(new CABLES.Port(i,"create port",CABLES.OP_PORT_TYPE_DYNAMIC));function o(){for(let e in i.patch.ops){if(i.patch.ops[e].patchId){if(i.patch.ops[e].patchId.get()==i.uiAttribs.subPatch){return i.patch.ops[e]}}}}r.onLinkChanged=()=>{const e=o();if(!r.links.length)return;const t=r.links[0].getOtherPort(r);r.removeLinks();const n=e.addNewOutPort(t);const a=gui.scene().link(t.parent,t.getName(),i,n);e.saveData()}};Ops.Ui.PatchOutput.prototype=new CABLES.Op;CABLES.OPS["851b44cb-5667-4140-9800-5aeb7031f1d7"]={f:Ops.Ui.PatchOutput,objName:"Ops.Ui.PatchOutput"};Ops.Ui.SubPatch=function(){CABLES.Op.apply(this,arguments);const u=this;const e=u.attachments={};u.dyn=u.addInPort(new CABLES.Port(u,"create port",CABLES.OP_PORT_TYPE_DYNAMIC));u.dynOut=u.addOutPort(new CABLES.Port(u,"create port out",CABLES.OP_PORT_TYPE_DYNAMIC));const t=u.addInPort(new CABLES.Port(u,"dataStr",CABLES.OP_PORT_TYPE_VALUE,{display:"readonly"}));u.patchId=u.addInPort(new CABLES.Port(u,"patchId",CABLES.OP_PORT_TYPE_VALUE,{display:"readonly"}));t.setUiAttribs({hideParam:true});u.patchId.setUiAttribs({hidePort:true});let m={ports:[],portsOut:[]};let n=CABLES.generateUUID();u.patchId.set(n);f();h();let c=false;u.saveData=o;u.init=()=>{u.setStorage({subPatchVer:1})};u.patchId.onChange=function(){if(!u.patch.isEditorMode())return;const t=u.patch.getSubPatchOps(n);if(t.length===2){if(u.patch.isEditorMode()&&CABLES.UI.DEFAULTOPS.isInBlueprint(u))CABLES.UI.undo.pause();for(let e=0;e<t.length;e++){u.patch.deleteOp(t[e].id)}if(u.patch.isEditorMode()&&CABLES.UI.DEFAULTOPS.isInBlueprint(u))CABLES.UI.undo.resume()}};u.onLoaded=function(){};u.onLoadedValueSet=function(){m=JSON.parse(t.get());if(!m){m={ports:[],portsOut:[]}}r()};function a(){}t.onChange=function(){if(c)return;if(!t.get())return;try{a()}catch(e){u.logError("cannot load subpatch data...");u.logError(e)}};function o(){try{t.set(JSON.stringify(m))}catch(e){u.log(e)}}u.addPortListener=d;function d(n,e){if(!n.hasSubpatchLstener){n.hasSubpatchLstener=true;n.addEventListener("onUiAttrChange",function(t){if(t.title){let e=0;for(e=0;e<m.portsOut.length;e++)if(m.portsOut[e].name==n.name)m.portsOut[e].title=t.title;for(e=0;e<m.ports.length;e++)if(m.ports[e].name==n.name)m.ports[e].title=t.title;o()}})}if(n.direction==CABLES.PORT_DIR_IN){if(n.type==CABLES.OP_PORT_TYPE_FUNCTION){n.onTriggered=function(){if(e.isLinked())e.trigger()}}else{n.onChange=function(){e.set(n.get());if(!n.isLinked()){for(let e=0;e<m.ports.length;e++){if(m.ports[e].name===n.name){m.ports[e].value=n.get()}}o()}}}}}u.setupPorts=r;function r(){if(!u.patchId.get())return;const e=m.ports||[];const t=m.portsOut||[];let n=0;for(n=0;n<e.length;n++){if(!u.getPortByName(e[n].name)){const a=u.addInPort(new CABLES.Port(u,e[n].name,e[n].type));const i=f();const r=i.addOutPort(new CABLES.Port(i,e[n].name,e[n].type));a.ignoreValueSerialize=true;a.setUiAttribs({editableTitle:true});if(e[n].title){a.setUiAttribs({title:e[n].title});r.setUiAttribs({title:e[n].title})}if(e[n].objType){a.setUiAttribs({objType:e[n].objType});r.setUiAttribs({objType:e[n].objType})}if(e[n].value){a.set(e[n].value);r.set(e[n].value)}d(a,r)}}for(n=0;n<t.length;n++){if(!u.getPortByName(t[n].name)){const o=u.addOutPort(new CABLES.Port(u,t[n].name,t[n].type));const s=h();const l=s.addInPort(new CABLES.Port(s,t[n].name,t[n].type));o.ignoreValueSerialize=true;o.setUiAttribs({editableTitle:true});if(t[n].title){o.setUiAttribs({title:t[n].title});l.setUiAttribs({title:t[n].title})}if(t[n].objType){o.setUiAttribs({objType:t[n].objType});l.setUiAttribs({objType:t[n].objType})}d(l,o)}}c=true}u.addNewInPort=function(e,t,n){const a="in"+m.ports.length+" "+e.op.name+" "+e.name;const i={name:a,type:e.type};if(e.uiAttribs.objType)i.objType=e.uiAttribs.objType;m.ports.push(i);r();return a};u.dyn.onLinkChanged=function(){if(u.dyn.isLinked()){const e=u.dyn.links[0].getOtherPort(u.dyn);u.dyn.removeLinks();e.removeLinkTo(u.dyn);u.log("dyn link changed!!!");const t=u.addNewInPort(e);const n=gui.scene().link(e.op,e.getName(),u,t);c=true;o()}else{setTimeout(function(){u.dyn.removeLinks()},100)}};u.addNewOutPort=function(e,t,n){const a="out"+m.portsOut.length+" "+e.op.name+" "+e.name;const i={name:a,type:e.type};if(e.uiAttribs.objType)i.objType=e.uiAttribs.objType;m.portsOut.push(i);r();return a};u.dynOut.onLinkChanged=function(){if(u.dynOut.isLinked()){const e=u.dynOut.links[0].getOtherPort(u.dynOut);u.dynOut.removeLinks();if(e){e.removeLinkTo(u.dynOut);const t=u.addNewOutPort(e);gui.scene().link(e.op,e.getName(),u,t)}c=true;o()}else{setTimeout(function(){u.dynOut.removeLinks()},100);u.log("dynOut unlinked...")}};function h(){let e=u.patch.getSubPatchOp(u.patchId.get(),"Ops.Ui.PatchOutput");if(!e){u.patch.addOp("Ops.Ui.PatchOutput",{subPatch:u.patchId.get(),translate:{x:0,y:0}});e=u.patch.getSubPatchOp(u.patchId.get(),"Ops.Ui.PatchOutput");if(!e)u.warn("no patchoutput!")}return e}function f(){let e=u.patch.getSubPatchOp(u.patchId.get(),"Ops.Ui.PatchInput");if(!e){u.patch.addOp("Ops.Ui.PatchInput",{subPatch:u.patchId.get(),translate:{x:0,y:0}});e=u.patch.getSubPatchOp(u.patchId.get(),"Ops.Ui.PatchInput");if(!e)u.warn("no patchinput2!")}return e}u.addSubLink=function(e,t){const n=m.ports.length;const a="in"+(n-1)+" "+t.op.name+" "+t.name;if(e.direction==CABLES.PORT_DIR_IN){gui.scene().link(e.op,e.getName(),f(),a)}else{const r=m.portsOut.length;gui.scene().link(e.op,e.getName(),h(),"out"+(r-1)+" "+t.op.name+" "+t.name)}const i=gui.patchView.getSubPatchBounds(u.patchId.get());f().uiAttr({translate:{x:i.minx,y:i.miny-100}});h().uiAttr({translate:{x:i.minx,y:i.maxy+100}});o();return a};u.onDelete=function(){for(let e=u.patch.ops.length-1;e>=0;e--)if(u.patch.ops[e]&&u.patch.ops[e].uiAttribs&&u.patch.ops[e].uiAttribs.subPatch==u.patchId.get())u.patch.deleteOp(u.patch.ops[e].id)};u.rebuildListeners=()=>{u.log("rebuild listeners...");const t=h();for(let e=0;e<t.portsIn.length;e++){if(t.portsIn[e].isLinked()){d(t.portsIn[e],this.portsOut[e])}}}};Ops.Ui.SubPatch.prototype=new CABLES.Op;CABLES.OPS["84d9a6f0-ed7a-466d-b386-225ed9e89c60"]={f:Ops.Ui.SubPatch,objName:"Ops.Ui.SubPatch"};Ops.Vars.VarSetNumber_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValueFloat("Value",0);e.varName=e.inDropDown("Variable",[],"",true);new CABLES.VarSetOpWrapper(e,"number",n,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 n=e.outNumber("Value");e.varName=e.inValueSelect("Variable",[],"",true);new CABLES.VarGetOpWrapper(e,"number",e.varName,n)};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.Trigger.TriggerReceive=function(){CABLES.Op.apply(this,arguments);const a=this;const e=a.attachments={};const t=a.outTrigger("Triggered");a.varName=a.inValueSelect("Named Trigger",[],"",true);r();a.patch.addEventListener("namedTriggersChanged",r);let n=null;function i(){t.trigger()}function r(){if(CABLES.UI){let t=[];let n=a.patch.namedTriggers;for(let e in n)t.push(e);t=t.sort();a.varName.uiAttribs.values=t}}a.varName.onChange=function(){if(n){let e=a.patch.namedTriggers[n];let t=e.indexOf(i);if(t!=-1)e.splice(t,1)}a.setTitle(">"+a.varName.get());a.patch.namedTriggers[a.varName.get()]=a.patch.namedTriggers[a.varName.get()]||[];let e=a.patch.namedTriggers[a.varName.get()];e.push(i);n=a.varName.get();o();a.patch.emitEvent("opTriggerNameChanged",a,a.varName.get())};a.on("uiParamPanel",o);function o(){if(!a.varName.get()){a.setUiError("unknowntrigger","unknown trigger")}else a.setUiError("unknowntrigger",null)}};Ops.Trigger.TriggerReceive.prototype=new CABLES.Op;CABLES.OPS["0816c999-f2db-466b-9777-2814573574c5"]={f:Ops.Trigger.TriggerReceive,objName:"Ops.Trigger.TriggerReceive"};Ops.WebAudio.FFTAreaAverage_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const o=e.patch.cgl;const s=["128","256","512","1024","2048"];const n=e.inTriggerButton("Refresh"),l=e.inArray("FFT Array"),u=e.inValueSlider("X Position"),m=e.inValueSlider("Y Position"),c=e.inValueSlider("Width",.2),d=e.inValueSlider("Height",.2),h=e.inValueBool("Create Texture",true),f=e.inSwitch("Texture Size",s,"128"),p=e.outTexture("Texture Out",null,"texture"),g=e.outNumber("Area Average Volume");e.setPortGroup("Area Settings",[u,m,c,d]);e.setPortGroup("Texture Settings",[h,f]);let v=false;f.onChange=()=>{v=true};const a=[];const i=0;let b=Number(f.get());const x=document.createElement("canvas");x.id="fft_"+CABLES.uuid();x.width=x.height=b;x.style.display="none";const r=document.getElementsByTagName("body")[0];r.appendChild(x);const _=x.getContext("2d");const O=[.5,1,2,4,8];let A=1;let I=0;let T=0;let S=20;let C=20;let y=0;n.onTriggered=function(){const n=l.get();if(!n){return}const e=n.length;const t=h.get();if(v){b=Number(f.get());x.width=x.height=b;const r=s.indexOf(String(f.get()));A=O[r];v=false}if(t){_.beginPath();_.fillStyle="#000";_.strokeStyle="#ff0";_.fillRect(0,0,x.width,x.height);_.fillStyle="#888";for(let e=0;e<n.length;e++){_.fillRect(e,b-n[e]*A,1,n[e]*A)}}I=u.get()*x.width;T=m.get()*x.height;S=c.get()*b/2;C=d.get()*b/2;if(t)_.rect(I,T,S,C);if(t){_.lineWidth=2*A;_.stroke()}const a=0;let i=0;for(let t=I;t<I+S;t++)for(let e=T;e<T+C;e++)if(n[Math.round(t)]*A>b-e)i++;if(y!=y)y=0;y+=i/(S*C);y/=2;g.set(y);if(t){_.fillStyle="#ff0";_.fillRect(0,0,y*x.width,6*A);if(p.get())p.get().initTexture(x,CGL.Texture.FILTER_NEAREST);else{p.set(new CGL.Texture.createFromImage(o,x,{filter:CGL.Texture.FILTER_NEAREST}))}}}};Ops.WebAudio.FFTAreaAverage_v2.prototype=new CABLES.Op;CABLES.OPS["8dd14fde-57d1-408c-a3ef-441a65bfe53a"]={f:Ops.WebAudio.FFTAreaAverage_v2,objName:"Ops.WebAudio.FFTAreaAverage_v2"};Ops.WebAudio.AudioAnalyzer_v2=function(){CABLES.Op.apply(this,arguments);const a=this;const e=a.attachments={};const i=(e,t,n)=>{return Math.min(Math.max(e,t),n)};const r=-144;const t=-96;let n=CABLES.WEBAUDIO.createAudioContext(a);const o=a.inTrigger("Trigger In");const s=n.createAnalyser();s.smoothingTimeConstant=.3;s.fftSize=256;const l=[32,64,128,256,512,1024,2048,4096,8192,16384,32768];const u=a.inObject("Audio In",null,"audioNode");const m=a.inDropDown("FFT size",l,256);const c=a.inFloatSlider("Smoothing",.3);const d=a.inFloat("Min",-90);const h=a.inFloat("Max",0);a.setPortGroup("Inputs",[o,u]);a.setPortGroup("FFT Options",[m,c]);a.setPortGroup("Range (in dBFS)",[d,h]);const f=a.outTrigger("Trigger Out");const p=a.outObject("Audio Out",null,"audioNode");const g=a.outArray("FFT Array");const v=a.outArray("Waveform Array");const b=a.outArray("Frequencies by Index Array");const x=a.outNumber("Array Length");const _=a.outNumber("Average Volume");const O=a.outNumber("Average Volume Time-Domain");const A=a.outNumber("RMS Volume");let I=false;let T=s.frequencyBinCount;let S=new Uint8Array(T);let C=new Uint8Array(T);let y=[];y.length=T;let E=null;u.onChange=()=>{if(u.get()){const e=u.get();if(e.connect){e.connect(s);p.set(s)}}else{if(E){if(E.disconnect)E.disconnect(s);p.set(null)}}E=u.get()};function M(){try{const e=Number(m.get());s.smoothingTimeConstant=i(c.get(),0,1);s.fftSize=e;const t=i(d.get(),r,-1e-4);const n=Math.max(h.get(),s.minDecibels+1e-4);s.minDecibels=t;s.maxDecibels=n;if(t<r){a.setUiError("maxDbRangeMin","Your minimum is below the lowest possible dBFS value: "+r+"dBFS. To make sure your analyser data is correct, try increasing the minimum.",1)}else{a.setUiError("maxDbRangeMin",null)}if(n>0){a.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{a.setUiError("maxDbRangeMax",null)}if(l.indexOf(e)>=6){a.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{a.setUiError("highFftSize",null)}}catch(e){a.log(e)}}m.onChange=c.onChange=d.onChange=h.onChange=()=>{if(o.isLinked())I=true;else M()};o.onTriggered=function(){if(I){M();I=false}if(T!=s.frequencyBinCount){T=s.frequencyBinCount;S=new Uint8Array(T);C=new Uint8Array(T);y=[];y.length=T;for(let e=0;e<T;e+=1){y[e]=Math.round(e*n.sampleRate/(s.fftSize*2))}b.set(null);b.set(y)}if(!S)return;if(!C)return;const e=Number(m.get());try{s.getByteFrequencyData(S);s.getByteTimeDomainData(C);let t=0;let n=0;let a=0;for(let e=0;e<s.frequencyBinCount;e++){t+=C[e]*C[e];n+=S[e];a+=C[e]}const i=n/s.frequencyBinCount;const r=a/s.frequencyBinCount;_.set(i/128);O.set(r/256);let e=Math.sqrt(t/s.frequencyBinCount);e=Math.max(e,e*c.get());A.set(e/256)}catch(e){a.log(e)}g.setRef(S);v.setRef(C);x.set(S.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.Ui.VizNumberBar=function(){CABLES.Op.apply(this,arguments);const o=this;const e=o.attachments={};const s=o.inFloat("Number",0);o.setUiAttrib({height:100,width:200,resizable:true});let l=-Number.MAX_VALUE;let u=Number.MAX_VALUE;s.onLinkChanged=()=>{l=-Number.MAX_VALUE;u=Number.MAX_VALUE};o.renderVizLayer=(i,r)=>{i.fillStyle="#222";i.fillRect(r.x,r.y,r.width,r.height);{l=Math.max(l,s.get());u=Math.min(u,s.get());if(o.uiAttribs.color)i.fillStyle=o.uiAttribs.color;else i.fillStyle="#555";let e=CABLES.map(0,u,l,0,r.width);let t=CABLES.map(s.get(),u,l,0,r.width);let n=Math.min(e,t);let a=Math.max(e,t);i.fillRect(n+r.x,r.y,a-n,r.height)}{const e=10;if(o.uiAttribs.color)i.fillStyle="#fff";else i.fillStyle="#ccc";const t=r.height*.7;i.font="normal "+t+"px sourceCodePro";i.fillText(Math.round(s.get()*1e4)/1e4,r.x+e,r.y+t)}}};Ops.Ui.VizNumberBar.prototype=new CABLES.Op;CABLES.OPS["37575d2e-4ba6-4d2b-b00c-c503666867c5"]={f:Ops.Ui.VizNumberBar,objName:"Ops.Ui.VizNumberBar"};Ops.Ui.VizTexture=function(){CABLES.Op.apply(this,arguments);const k=this;const n=k.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 B=k.inTexture("Texture In"),D=k.inBool("Show Info",false),e=k.inSwitch("Visualize outside 0-1",["Off","Anim","Modulo"],"Anim"),t=k.inSwitch("Alpha",["A","1","1-A"],"A"),G=k.inBool("Show Color",false),U=k.inFloatSlider("X",.5),F=k.inFloatSlider("Y",.5),a=k.outTexture("Texture Out"),V=k.outString("Info");k.setUiAttrib({height:150,resizable:true});const z=new CABLES.Timer;let i=null;let X=null;let q=null;let H="";let r=true;t.onChange=e.onChange=s;G.onChange=o;o();if(CABLES.UI){z.play()}function o(){U.setUiAttribs({greyout:!G.get()});F.setUiAttribs({greyout:!G.get()})}B.onChange=()=>{const e=B.get();a.setRef(e);let t="";if(B.get()&&B.isLinked())t=B.links[0].getOtherPort(B).name;k.setUiAttrib({extendTitle:t})};function s(){if(!i)return;i.toggleDefine("MOD_RANGE",e.get()=="Modulo");i.toggleDefine("ANIM_RANGE",e.get()=="Anim");i.toggleDefine("ALPHA_INV",t.get()=="1-A");i.toggleDefine("ALPHA_ONE",t.get()=="1")}k.renderVizLayerGl=(m,c)=>{if(!B.isLinked())return;if(!c.useGl)return;const d=B;const h=5;const f=h+1;const e=CABLES.UI.uiProfiler.start("previewlayer texture");const p=d.op.patch.cgl;if(!this._emptyCubemap)this._emptyCubemap=CGL.Texture.getEmptyCubemapTexture(p);d.op.patch.cgl.profileData.profileTexPreviews++;const g=d.get()||CGL.Texture.getEmptyTexture(p);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(p,t)}if(!this._shader){this._shader=new CGL.Shader(p,"glpreviewtex");this._shader.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"]);this._shader.setSource(n.viztex_vert,n.viztex_frag);this._shaderTexUniform=new CGL.Uniform(this._shader,"t","tex",h);this._shaderTexCubemapUniform=new CGL.Uniform(this._shader,"tc","cubeMap",f);i=this._shader;s();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)}p.pushPMatrix();const v=[g.width,g.height];const b=d.op.patch.cgl.canvasWidth>v[0]&&d.op.patch.cgl.canvasHeight>v[1];if(b){mat4.ortho(p.pMatrix,0,d.op.patch.cgl.canvasWidth,d.op.patch.cgl.canvasHeight,0,.001,11)}else mat4.ortho(p.pMatrix,-1,1,1,-1,.001,11);const x=p.getTexture(h);const _=p.getTexture(f);let O=0;if(g){if(g.cubemap)O=1;if(g.textureType==CGL.Texture.TYPE_DEPTH)O=2;if(O==0||O==2){p.setTexture(h,g.tex);p.setTexture(f,this._emptyCubemap.cubemap,p.gl.TEXTURE_CUBE_MAP)}else if(O==1){p.setTexture(f,g.cubemap,p.gl.TEXTURE_CUBE_MAP)}z.update();this._shaderTimeUniform.setValue(z.get());this._shaderTypeUniform.setValue(O);let t=[d.op.patch.cgl.canvasWidth,d.op.patch.cgl.canvasHeight];p.gl.clearColor(0,0,0,0);p.gl.clear(p.gl.COLOR_BUFFER_BIT|p.gl.DEPTH_BUFFER_BIT);p.pushModelMatrix();if(b){t=v;mat4.translate(p.mMatrix,p.mMatrix,[v[0]/2,v[1]/2,0]);mat4.scale(p.mMatrix,p.mMatrix,[v[0]/2,v[1]/2,0])}this._mesh.render(this._shader);p.popModelMatrix();if(O==0)p.setTexture(h,x);if(O==1)p.setTexture(f,_);p.popPMatrix();p.resetViewPort();const A=[c.width,c.height];const I=false;if(g.width>g.height)A[1]=c.width*v[1]/v[0];else{A[1]=c.width*(v[1]/v[0]);if(A[1]>c.height){const y=c.height/A[1];A[0]*=y;A[1]*=y}}const T=A[0]>v[0]&&A[1]>v[1];m.imageSmoothingEnabled=true;m.fillStyle="#ffffff";m.fillRect(c.x,c.y-10,10,10);m.fillStyle="#000000";m.fillRect(c.x,c.y-10,5,5);m.fillRect(c.x+5,c.y-10+5,5,5);let e=c.height;let n=10*c.width/e;let a=e/10;let i=c.width/n;for(let t=0;t<n;t++)for(let e=0;e<10;e++){if((t+e)%2==0)m.fillStyle="#333333";else m.fillStyle="#393939";m.fillRect(c.x+i*t,c.y+a*e,i,a)}m.fillStyle="#222";const S=(c.width-A[0])/2;const C=(e-A[1])/2;let r=c.x+(c.width-A[0])/2;let o=c.y+(e-A[1])/2;let s=A[0];let l=A[1];if(e-A[1]<0){r=c.x+(c.width-A[0]*e/A[1])/2;o=c.y;s=A[0]*e/A[1];l=e}m.fillRect(c.x,c.y,r-c.x,e);m.fillRect(c.x+s+r-c.x,c.y,s,e);m.fillRect(c.x,c.y,c.width,C);m.fillRect(c.x,c.y+A[1]+C,c.width,C);if(p.canvas&&p.canvasWidth>0&&p.canvasHeight>0&&p.canvas.width>0&&p.canvas.height>0){try{const E=s/t[0]>3||l/t[1]>3;const M=s/t[0]>10||l/t[1]>10;if(v[1]==1){m.imageSmoothingEnabled=false;m.drawImage(p.canvas,0,0,t[0],t[1],c.x,c.y,c.width,e);m.imageSmoothingEnabled=true}else if(v[0]==1){m.imageSmoothingEnabled=false;m.drawImage(p.canvas,0,0,t[0],t[1],c.x,c.y,c.width,e);m.imageSmoothingEnabled=true}else if(A[0]!=0&&A[1]!=0&&c.width!=0&&e!=0&&s!=0&&l!=0){m.imageSmoothingEnabled=!E;m.drawImage(p.canvas,0,0,t[0],t[1],r,o,s,l)}if(M){const P=s/t[0];const N=l/t[1];m.imageSmoothingEnabled=true;m.lineWidth=1;m.globalAlpha=.5;m.beginPath();for(let e=0;e<=t[0];e++){m.moveTo(r+e*P,o);m.lineTo(r+e*P,o+l)}for(let e=0;e<=t[1];e++){m.moveTo(r,o+e*N);m.lineTo(r+s,o+e*N)}m.strokeStyle="#555";m.stroke();m.globalAlpha=1}}catch(e){console.error("canvas drawimage exception...",e)}}let u="";if(D.get()){if(d.get()&&d.get().getInfoOneLine)u+=d.get().getInfoOneLine()+"\n"}if(G.get()){u+=H+"\n";const j=r+s*U.get();const L=o+l*F.get();m.fillStyle="#000";m.fillRect(j-1,L-10,3,20);m.fillRect(j,L-1,20,3);m.fillStyle="#fff";m.fillRect(j-1,L-10,1,20);m.fillRect(j-10,L-1,20,1)}k.setUiAttrib({comment:u});V.set(u);if(G.get()){const w=p.gl;const R=B.get();if(!R){H="";return}if(!X)X=w.createFramebuffer();if(!q)q=new CGL.PixelReader;w.bindFramebuffer(w.FRAMEBUFFER,X);w.framebufferTexture2D(w.FRAMEBUFFER,w.COLOR_ATTACHMENT0,w.TEXTURE_2D,R.tex,0);w.bindFramebuffer(w.FRAMEBUFFER,null);q.read(p,X,R.pixelFormat,U.get()*R.width,R.height-F.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"}})}}p.gl.clearColor(0,0,0,0);p.gl.clear(p.gl.COLOR_BUFFER_BIT|p.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.Math.Compare.GreaterThan=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValueFloat("number1"),a=e.inValueFloat("number2"),i=e.outBoolNum("result");e.setUiAttribs({mathTitle:true});n.onChange=a.onChange=r;function r(){i.set(n.get()>a.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 n=e.inValueBool("Value",false);let a=e.outTrigger("Next");let i=0;n.onChange=function(){let e=n.get();if(!i&&e){i=true;a.trigger()}else{i=false}}};Ops.Boolean.TriggerChangedTrue.prototype=new CABLES.Op;CABLES.OPS["385197e1-8b34-4d1c-897f-d1386d99e3b3"]={f:Ops.Boolean.TriggerChangedTrue,objName:"Ops.Boolean.TriggerChangedTrue"};Ops.TimeLine.TimeLineTime=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.outNumber("time");e.onAnimFrame=function(e){n.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.TimeLine.TimeLinePlay=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTriggerButton("Play"),a=e.inTriggerButton("Pause"),i=e.outTrigger("Next");n.onTriggered=function(){e.patch.timer.play();i.trigger()};a.onTriggered=function(){e.patch.timer.pause();i.trigger()}};Ops.TimeLine.TimeLinePlay.prototype=new CABLES.Op;CABLES.OPS["fc75b841-a55f-4474-8746-61218588598d"]={f:Ops.TimeLine.TimeLinePlay,objName:"Ops.TimeLine.TimeLinePlay"};Ops.Math.Subtract=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValue("number1",1),a=e.inValue("number2",1),i=e.outNumber("result");e.setUiAttribs({mathTitle:true});n.onChange=a.onChange=r;r();function r(){let e=n.get()-a.get();if(!isNaN(e))i.set(e)}};Ops.Math.Subtract.prototype=new CABLES.Op;CABLES.OPS["a4ffe852-d200-4b96-9347-68feb01122ca"]={f:Ops.Math.Subtract,objName:"Ops.Math.Subtract"};Ops.TimeLine.TimeLineSetTime=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTriggerButton("Update"),a=e.inFloat("Time",0),i=e.outTrigger("Next");n.onTriggered=function(){e.patch.timer.setTime(parseFloat(a.get()));i.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.TimeLineRewind=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTriggerButton("exe"),a=e.outTrigger("Next");n.onTriggered=function(){e.patch.timer.setTime(0);a.trigger()}};Ops.TimeLine.TimeLineRewind.prototype=new CABLES.Op;CABLES.OPS["d3408604-858c-4226-8d4c-1ef669956f35"]={f:Ops.TimeLine.TimeLineRewind,objName:"Ops.TimeLine.TimeLineRewind"};Ops.Html.PlayerControlPanel_v2=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.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=i.inFloat("Length",30),a=i.inFloat("Current",0),n=i.inBool("Clamp",false),r=i.inBool("Is Playing",false),o=i.inBool("Visible",true),s=i.inBool("Show Time"),l=i.inBool("Show Skip Buttons"),u=i.outTrigger("Play clicked"),m=i.outTrigger("Pause clicked"),c=i.outTrigger("Rewind clicked"),d=i.outTrigger("Skip Back clicked"),h=i.outTrigger("Skip Forward clicked"),f=i.outTrigger("Dragged"),p=i.outNumber("Current Value"),g=i.outBoolNum("Dragging",false),v=i.outObject("DOM Element",null,"element");let b=i.patch.getDocument().createElement("div");b.id="progressUI_"+i.id;b.classList.add("progressUI");v.set(b);const R=i.patch.cgl;let k=i.patch.cgl.canvas.parentElement;k.appendChild(b);let x=i.patch.getDocument().createElement("div");if(!o.get()){b.style.display="none"}let _=i.patch.getDocument().createElement("input");let O=i.patch.getDocument().createElement("div");const A=i.patch.getDocument().createElement("div");x.classList.add("progressContainer");x.appendChild(_);_.setAttribute("type","range");_.setAttribute("step",.01);_.setAttribute("min",0);_.setAttribute("max",t.get());_.setAttribute("value",a.get());_.classList.add("progressbar");_.addEventListener("input",U);let I=false;let T=false;b.appendChild(A);b.appendChild(x);b.appendChild(O);let B="css_progressui_"+CABLES.uuid();const S=i.patch.getDocument().createElement("style");S.type="text/css";S.id=B;S.classList.add("cablesEle");let D=i.patch.getDocument().getElementsByTagName("body")[0];D.appendChild(S);A.classList.add("buttonContainer");let C=P("","progressUI_icon-skip-back");A.appendChild(C);let y=P("","progressUI_icon-rewind","skip");if(!l.get()){y.style.display="none"}A.appendChild(y);y.addEventListener("pointerdown",()=>{d.trigger()});let E=P("","progressUI_icon-play");A.appendChild(E);let M=P("","progressUI_icon-fast-forward","skip");if(!l.get()){M.style.display="none"}A.appendChild(M);M.addEventListener("pointerdown",()=>{h.trigger()});O.classList.add("progress");O.innerHTML="00:00:000";function P(e,t,n){let a=i.patch.getDocument().createElement("div");a.classList.add("button");a.classList.add(n);a.innerHTML=e;if(t){let e=i.patch.getDocument().createElement("div");e.classList.add("progressUIIcon");e.classList.add(t);a.appendChild(e)}return a}t.onChange=()=>{_.setAttribute("max",t.get())};o.onChange=()=>{if(o.get()){b.style.removeProperty("display")}else{b.style.display="none"}};s.onChange=()=>{if(s.get()){b.classList.add("showValue");O.style.display="block"}else{b.classList.remove("showValue");O.style.display="none"}};l.onChange=()=>{if(l.get()){b.querySelectorAll(".button.skip").forEach(e=>{e.style.display="block"})}else{b.querySelectorAll(".button.skip").forEach(e=>{e.style.display="none"})}};if(!s.get()){O.style.display="none"}_.addEventListener("pointerdown",()=>{T=true;if(r.get()){I=true;m.trigger();N()}});_.addEventListener("pointermove",()=>{const e=_.value;if(T){g.set(T);w(e);p.set(e);f.trigger()}});_.addEventListener("pointerup",()=>{const e=_.value;w(e);p.set(e);if(T){f.trigger()}T=false;g.set(T);if(I){I=false;u.trigger();N()}});function G(){S.textContent=e.css_progressui_css}function N(){E.querySelector(".progressUIIcon").classList.remove("progressUI_icon-play");E.querySelector(".progressUIIcon").classList.remove("progressUI_icon-pause");if(r.get()){E.querySelector(".progressUIIcon").classList.add("progressUI_icon-pause")}else{E.querySelector(".progressUIIcon").classList.add("progressUI_icon-play")}}E.addEventListener("pointerdown",function(){if(r.get()){m.trigger()}else{u.trigger()}N()});C.addEventListener("pointerdown",()=>{p.set(0);c.trigger()});i.onDelete=function(){if(b)b.remove();if(S)S.remove()};function U(e){a.onChange=null;const t=e.target.value;p.set(t);a.onChange=j}function j(){let e=a.get();if(n.get()&&e>t.get()){e=t.get()}_.value=e;p.set(e);w()}let L=0;function w(e=null){let t=e||a.get();let n=t;if(n!=L){O.innerHTML=F(n);L=n}}function F(e){const t=String(new Date(e*1e3).getUTCMinutes()).padStart(2,"0");const n=String(new Date(e*1e3).getUTCSeconds()).padStart(2,"0");const a=String(new Date(e*1e3).getUTCMilliseconds()).padStart(2,"0").padEnd(3,"0");const i=t+":"+n+":"+a;return i}G();N();a.onChange=j;r.onChange=N};Ops.Html.PlayerControlPanel_v2.prototype=new CABLES.Op;CABLES.OPS["12ac1d94-f043-454d-92a8-60733d2908b2"]={f:Ops.Html.PlayerControlPanel_v2,objName:"Ops.Html.PlayerControlPanel_v2"};Ops.Gl.ImageCompose.DrawImage_v3=function(){CABLES.Op.apply(this,arguments);const a=this;const e=a.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=a.inTrigger("render"),n=CGL.TextureEffect.AddBlendSelect(a,"blendMode"),i=a.inValueSlider("amount",1),r=a.inTexture("Image"),o=a.inValueBool("Premultiplied",false),s=a.inValueBool("Alpha Mask",false),l=a.inValueBool("removeAlphaSrc",false),u=a.inTexture("Mask"),m=a.inValueSelect("Mask Src",["alpha channel","luminance","luminance inv"],"luminance"),c=a.inValueBool("Invert alpha channel"),d=a.inValueBool("Aspect Ratio",false),h=a.inValueSelect("Stretch Axis",["X","Y"],"X"),f=a.inValueSlider("Position",0),p=a.inValueBool("Crop",false),g=a.outTrigger("trigger");n.set("normal");const v=a.patch.cgl;const b=new CGL.Shader(v,"drawimage");u.onLinkChanged=x;a.setPortGroup("Mask",[u,m,c]);a.setPortGroup("Aspect Ratio",[d,f,p,h]);function x(){if(u.isLinked()){l.setUiAttribs({greyout:true});m.setUiAttribs({greyout:false});c.setUiAttribs({greyout:false})}else{l.setUiAttribs({greyout:false});m.setUiAttribs({greyout:true});c.setUiAttribs({greyout:true})}}a.toWorkPortsNeedToBeLinked(r);b.setSource(e.drawimage_vert,e.drawimage_frag);const _=new CGL.Uniform(b,"t","tex",0),R=new CGL.Uniform(b,"t","image",1),k=new CGL.Uniform(b,"t","imageAlpha",2),O=new CGL.Uniform(b,"f","aspectTex",1),B=new CGL.Uniform(b,"f","aspectPos",f);d.onChange=p.onChange=h.onChange=A;function A(){b.removeDefine("ASPECT_AXIS_X");b.removeDefine("ASPECT_AXIS_Y");b.removeDefine("ASPECT_CROP");f.setUiAttribs({greyout:!d.get()});p.setUiAttribs({greyout:!d.get()});h.setUiAttribs({greyout:!d.get()});if(d.get()){b.define("ASPECT_RATIO");if(p.get())b.define("ASPECT_CROP");if(h.get()=="X")b.define("ASPECT_AXIS_X");if(h.get()=="Y")b.define("ASPECT_AXIS_Y")}else{b.removeDefine("ASPECT_RATIO");if(p.get())b.define("ASPECT_CROP");if(h.get()=="X")b.define("ASPECT_AXIS_X");if(h.get()=="Y")b.define("ASPECT_AXIS_Y")}}const I=a.inValueBool("flip x");const T=a.inValueBool("flip y");let S=a.inValueBool("Transform");let C=a.inValueSlider("Scale X",1);let y=a.inValueSlider("Scale Y",1);let E=a.inValue("Position X",0);let M=a.inValue("Position Y",0);let P=a.inValue("Rotation",0);const N=a.inValueBool("Clip Repeat",false);const D=new CGL.Uniform(b,"f","scaleX",C);const G=new CGL.Uniform(b,"f","scaleY",y);const U=new CGL.Uniform(b,"f","posX",E);const F=new CGL.Uniform(b,"f","posY",M);const V=new CGL.Uniform(b,"f","rotate",P);S.onChange=j;function j(){b.toggleDefine("TEX_TRANSFORM",S.get());C.setUiAttribs({greyout:!S.get()});y.setUiAttribs({greyout:!S.get()});E.setUiAttribs({greyout:!S.get()});M.setUiAttribs({greyout:!S.get()});P.setUiAttribs({greyout:!S.get()})}CGL.TextureEffect.setupBlending(a,b,n,i);const z=new CGL.Uniform(b,"f","amount",i);t.onTriggered=w;N.onChange=u.onChange=o.onChange=s.onChange=c.onChange=T.onChange=I.onChange=l.onChange=m.onChange=L;j();x();A();L();function L(){b.toggleDefine("REMOVE_ALPHA_SRC",l.get());b.toggleDefine("ALPHA_MASK",s.get());b.toggleDefine("CLIP_REPEAT",N.get());b.toggleDefine("HAS_TEXTUREALPHA",u.get()&&u.get().tex);b.toggleDefine("TEX_FLIP_X",I.get());b.toggleDefine("TEX_FLIP_Y",T.get());b.toggleDefine("INVERT_ALPHA",c.get());b.toggleDefine("ALPHA_FROM_LUMINANCE",m.get()=="luminance");b.toggleDefine("ALPHA_FROM_INV_UMINANCE",m.get()=="luminance_inv");b.toggleDefine("PREMUL",o.get())}function w(){if(!CGL.TextureEffect.checkOpInEffect(a))return;const e=r.get();if(e&&e.tex&&i.get()>0){v.pushShader(b);v.currentTextureEffect.bind();const t=v.currentTextureEffect.getCurrentSourceTexture();v.setTexture(0,t.tex);const n=1/(v.currentTextureEffect.getWidth()/v.currentTextureEffect.getHeight())*(e.width/e.height);O.setValue(n);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.Vars.VarGetTexture_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.outTexture("Value");e.varName=e.inValueSelect("Variable",[],"",true);new CABLES.VarGetOpWrapper(e,"object",e.varName,n)};Ops.Vars.VarGetTexture_v2.prototype=new CABLES.Op;CABLES.OPS["5f8ce5fc-9787-45c9-9a83-0eebd2c6de15"]={f:Ops.Vars.VarGetTexture_v2,objName:"Ops.Vars.VarGetTexture_v2"};Ops.Html.WindowClose=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTriggerButton("Close");n.onTriggered=function(){window.close()}};Ops.Html.WindowClose.prototype=new CABLES.Op;CABLES.OPS["4f5d56b9-28a0-47fe-86f7-7b765268d694"]={f:Ops.Html.WindowClose,objName:"Ops.Html.WindowClose"};Ops.User.anticore.DopeSheet=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const a=8;const o=4;const n=t.inFloat("time",0);const i=t.inStringEditor("sheet","");const u=[];const r=[];for(let e=1;e<=a;e++)u.push(t.outValue("analog "+e));for(let e=1;e<=o;e++)r.push(t.outTrigger("digital "+e));function m(e,t,n,a,i){return(e-t)/(n-t)*(i-a)+a}function c(e,r,o,s){const t={xx:()=>o+((r-1)*(r-1)*(2.70158*(r-1)+1.70158)+1)*(s-o),c:()=>o,li:()=>o+r*(s-o),l:()=>o+r*(s-o),et:()=>o+Math.pow(r,.25)*(s-o),ex:()=>o+Math.pow(2,10*(r-1))*(s-o),xi:()=>o+Math.pow(2,10*(r-1))*(s-o),xo:()=>o+(1-Math.pow(2,-10*r))*(s-o),xio:()=>{let e=2*r-1;return o+(e<0?Math.pow(2,10*e):1-Math.pow(2,-10*e)*.5)+(s-o)},ci:()=>o+(1-Math.sqrt(1-Math.pow(r,2)))*(s-o),s:()=>o+r*(2*r*r-3*r+2)*(s-o),ss:()=>o+r*(3*r*r-4.5*r+2.5)*(s-o),sss:()=>o+r*(4*r*r-6*r+3)*(s-o),st:()=>o+((r-1)*(r-1)*(2.70158*(r-1)+1.70158)+1)*(s-o),sf:()=>o+r*r*(2.70158*r-1.70158)*(s-o),ef:()=>o+Math.pow(r,4)*(s-o),eft:()=>{if(r*2<1){return o+.5*Math.pow(r,4)*(s-o)}r-=2;return o+-.5*(r*Math.pow(r,3)-2)*(s-o)},qi:()=>o+Math.pow(r,3)*(s-o),qo:()=>o+(1+Math.pow(r-1,3))*(s-o),qio:()=>{return o+(r<.5?4*Math.pow(r,3):1+4*Math.pow(r-1,3))*(s-o)},bxx:()=>{let e=6;const t=3-Math.pow(2,2-e);let n=-1;let a=0;let i=0;while(n/t<r){a=Math.pow(2,1-i++);n+=a}if(n-a>0){r-=(n-a+a*.5)/t}return o+(t*t*Math.pow(r,2)+(1-Math.pow(.25,i-1)))*(s-o)}};if(!t[e])return o;return t[e]()}let d=[];let h=0;let s=0;t.onLoaded=()=>p();i.onChange=()=>p();n.onChange=()=>v();let l=1;function f(e){if(e.trim().match(/\w\d\d?\:/)){l=parseInt(e.substring(1,e.length-1));console.log(l);return}let t=e.split(/\s+/);if(t.length<2)return;let n=parseFloat(t[0]);let i={time:n,analog:Array(a).fill(null),digital:Array(o).fill([false,false])};let r=l-1;for(let e=1;e<t.length;e++){let a=t[e].trim();console.log(a);if(a.length===0)continue;if(!["-","(","["].includes(a[0]))continue;if(["(","["].includes(a[0])&&a.length<2)continue;if(["(","["].includes(a[0])&&![")","]"].includes(a[a.length-1]))continue;if(a[0]==="-"){r++;continue}else if(a[0]=="("){if(a=="()"){r++;continue}let e=a.substring(1,a.length-1);let t="c";let n=0;if(e[e.length-1].match(/[a-z]/i)){if(e.length>3&&e[e.length-3].match(/[a-z]/i)){t=e[e.length-3]+e[e.length-2]+e[e.length-1];n=parseFloat(e.substring(0,e.length-3))}else if(e.length>2&&e[e.length-2].match(/[a-z]/i)){t=e[e.length-2]+e[e.length-1];n=parseFloat(e.substring(0,e.length-2))}else if(e.length>1){t=e[e.length-1];n=parseFloat(e.substring(0,e.length-1))}else{continue}}else{n=parseFloat(e)}i.analog[r]=[n,t];r++}else if(a[0]=="["){if(a=="[]"){i.digital[0]=[true,false]}else{let e=a.substring(1,a.length-1);let t=parseInt(e);if(typeof t=="number"&&t<=o&&t)i.digital[t-1]=[true,false];if(t-1>s)s=t-1}}}if(r>h)h=r;return i}function p(){d=[];l=1;let e=i.get();let t=e.split("\n");if(t.length<1)return;d=t.map(e=>f(e)).filter(e=>!!e).sort((e,t)=>e.time-t.time);console.log(d);v()}function g(n,a){let i=null,r=null,o=null,s=null,l=null;for(let t=0;t<d.length;t++){let e=d[t];if(e.time<=a&&e.analog[n]){i=e.time;r=e.analog[n][0];o=e.analog[n][1]}if(e.time>=a&&e.analog[n]&&s==null){s=e.time;l=e.analog[n][0];break}}return[i,r,o,s,l]}function v(){let l=n.get();for(let s=0;s<Math.min(h,a);s++){let[n,a,i,r,o]=g(s,l);if(n===null&&r===null){u[s].set(0)}else if(n===null&&o){u[s].set(o)}else if(a&&r===null){u[s].set(a)}else{let e=m(l,n,r,0,1);let t=c(i,e,a,o);u[s].set(t)}}for(let n=0;n<o;n++){for(let t=0;t<d.length;t++){let e=d[t];if(e.time<l){if(e.digital[n][0]===true&&e.digital[n][1]===false){r[n].trigger();e.digital[n][1]=true}}else{e.digital[n][1]=false}}}}};Ops.User.anticore.DopeSheet.prototype=new CABLES.Op;CABLES.OPS["9e9392aa-3b41-453e-919c-aacf33f2aabe"]={f:Ops.User.anticore.DopeSheet,objName:"Ops.User.anticore.DopeSheet"};Ops.Gl.ForceCanvasSize=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTrigger("Trigger"),l=e.inBool("Active",true),a=e.inSwitch("Force",["Resolution","Aspect Ratio"],"Resolution"),u=e.inBool("Center In Parent",true),m=e.inBool("Scale to fit Parent",true),c=e.inInt("Set Width",300),d=e.inInt("Set Height",200),i=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"),h=e.inFloat("Ratio",0),r=e.inDropDown("Fill Parent",["Auto","Width","Height","Both"],"Auto"),f=e.outTrigger("Next"),p=e.outNumber("Width"),g=e.outNumber("Height"),v=e.outNumber("Margin Left"),b=e.outNumber("Margin Top");e.setPortGroup("Size",[c,d]);e.setPortGroup("Proportions",[h,r,i]);let x=0;const o=0;const _=1;const O=2;const A=3;const I=4;r.onChange=C;a.onChange=s;u.onChange=n.onLinkChanged=y;i.onChange=S;const T=e.patch.cgl;C();function s(){if(a.get()=="Aspect Ratio"){h.set(100);S()}C()}function S(){const e=i.get();if(e=="Custom")return;else if(e=="16:9")h.set(16/9);else if(e=="4:3")h.set(4/3);else if(e=="16:10")h.set(16/10);else if(e=="21:9")h.set(21/9);else if(e=="2:1")h.set(2);else if(e=="1:1")h.set(1);else if(e=="9:16")h.set(9/16);else if(e=="1:2")h.set(.5);else if(e=="iPhoneXr Vert")h.set(9/19.5)}e.on("delete",()=>{y()});h.onChange=()=>{y()};l.onChange=function(){if(!l.get())y()};function C(){const e=a.get()=="Resolution";c.setUiAttribs({greyout:!e});d.setUiAttribs({greyout:!e});i.setUiAttribs({greyout:e});r.setUiAttribs({greyout:e});h.setUiAttribs({greyout:e});x=0;if(!e){const t=r.get();if(t=="Width")x=_;else if(t=="Height")x=O;else if(t=="Both")x=A;else if(t=="Auto")x=I}}function y(){T.canvas.style["margin-top"]="";T.canvas.style["margin-left"]="";T.canvas.styleMarginLeft=0;T.canvas.styleMarginTop=0;v.set(0);b.set(0);const e=T.canvas.parentNode.getBoundingClientRect();T.setSize(e.width,e.height);T.canvas.style.transform="scale(1)";T.canvas.style.position="absolute";T.updateSize()}n.onTriggered=function(){if(!l.get())return f.trigger();let e=c.get();let t=d.get();let n=T.canvas.parentNode.getBoundingClientRect();if(n.height==0){T.canvas.parentNode.style.height="100%";n=T.canvas.parentNode.getBoundingClientRect()}if(n.width==0){T.canvas.parentNode.style.width="100%";n=T.canvas.parentNode.getBoundingClientRect()}if(x==_){e=n.width;t=e*1/h.get()}else if(x==O){t=n.height;e=t*h.get()}else if(x==I){const a=n;t=a.height;e=t*h.get();if(e>a.width){e=a.width;t=e*1/h.get()}}else if(x==A){const a=n;t=a.height;e=t*h.get();if(e<a.width){e=a.width;t=e*1/h.get()}}e=Math.ceil(e);t=Math.ceil(t);if(u.get()){const a=n;const i=(a.height-t)/2;const r=(a.width-e)/2;v.set(r);b.set(i);T.canvas.style["margin-top"]=i+"px";T.canvas.style["margin-left"]=r+"px";T.canvas.styleMarginTop=i;T.canvas.styleMarginLeft=r}else{T.canvas.style["margin-top"]="0";T.canvas.style["margin-left"]="0";T.canvas.styleMarginTop=0;T.canvas.styleMarginLeft=0;v.set(0);b.set(0)}if(m.get()){const a=n;const o=a.width/c.get();const s=a.height/d.get();T.canvas.style.transform="scale("+Math.min(o,s)+")"}else{T.canvas.style.transform="scale(1)"}if(T.canvas.width/T.pixelDensity!=e||T.canvas.height/T.pixelDensity!=t){p.set(e);g.set(t);T.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.Math.MathExpression=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inFloat("A",0);const a=e.inFloat("B",1);const i=e.inFloat("C",2);const r=e.inFloat("D",3);e.setPortGroup("Parameters",[n,a,i,r]);const o=e.inString("Expression","a*(b+c+d)");e.setPortGroup("Expression",[o]);const s=e.outNumber("Result");const l=e.outBool("Expression Valid");let u=o.get();let m=false;const c=()=>{try{u=new Function("m","a","b","c","d",`with(m) { return ${o.get()} }`);m=true;d();l.set(m)}catch(e){m=false;l.set(m);if(e instanceof ReferenceError||e instanceof SyntaxError)return}};const d=()=>{if(m){s.set(u(Math,n.get(),a.get(),i.get(),r.get()));if(!o.get())s.set(0)}l.set(m)};n.onChange=a.onChange=i.onChange=r.onChange=d;o.onChange=c;c()};Ops.Math.MathExpression.prototype=new CABLES.Op;CABLES.OPS["d2343a1e-64ea-45b2-99ed-46e167bbdcd3"]={f:Ops.Math.MathExpression,objName:"Ops.Math.MathExpression"};Ops.Math.Fract=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValue("Value"),a=e.outNumber("Result");n.onChange=function(){const e=n.get();a.set(e-Math.floor(e))}};Ops.Math.Fract.prototype=new CABLES.Op;CABLES.OPS["12573ba7-866d-40c4-9ddd-14d9331ffe6f"]={f:Ops.Math.Fract,objName:"Ops.Math.Fract"};Ops.Gl.ImageCompose.ChromaticAberration_v2=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={chromatic_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float pixel;\nUNI float onePixel;\nUNI float amount;\nUNI float lensDistort;\n\n#ifdef MASK\nUNI sampler2D texMask;\n#endif\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n   vec4 base=texture(tex,texCoord);\n   vec4 col=texture(tex,texCoord);\n\n   vec2 tc=texCoord;;\n   float pix = pixel;\n   if(lensDistort>0.0)\n   {\n       float dist = distance(texCoord, vec2(0.5,0.5));\n       tc-=0.5;\n       tc *=smoothstep(-0.9,1.0*lensDistort,1.0-dist);\n       tc+=0.5;\n   }\n\n    #ifdef MASK\n        vec4 m=texture(texMask,texCoord);\n        pix*=m.r*m.a;\n    #endif\n\n    #ifdef SMOOTH\n    #ifdef WEBGL2\n        float numSamples=round(pix/onePixel/4.0+1.0);\n        col.r=0.0;\n        col.b=0.0;\n\n        for(float off=0.0;off<numSamples;off++)\n        {\n            float diff=(pix/numSamples)*off;\n            col.r+=texture(tex,vec2(tc.x+diff,tc.y)).r/numSamples;\n            col.b+=texture(tex,vec2(tc.x-diff,tc.y)).b/numSamples;\n        }\n    #endif\n    #endif\n\n    #ifndef SMOOTH\n        col.r=texture(tex,vec2(tc.x+pix,tc.y)).r;\n        col.b=texture(tex,vec2(tc.x-pix,tc.y)).b;\n    #endif\n\n   outColor= cgl_blendPixel(base,col,amount);\n\n}\n"};const n=t.inTrigger("render"),a=CGL.TextureEffect.AddBlendSelect(t,"Blend Mode","normal"),i=t.inValueSlider("Amount",1),r=t.inValue("Pixel",5),o=t.inValueSlider("Lens Distort",0),s=t.inValueBool("Smooth",false),l=t.inTexture("Mask"),u=t.outTrigger("trigger");const m=t.patch.cgl;const c=new CGL.Shader(m,"chromatic");CGL.TextureEffect.setupBlending(t,c,a,i);c.setSource(c.getDefaultVertexShader(),e.chromatic_frag);const d=new CGL.Uniform(c,"t","tex",0),h=new CGL.Uniform(c,"f","pixel",0),f=new CGL.Uniform(c,"f","onePixel",0),p=new CGL.Uniform(c,"t","texMask",1),g=new CGL.Uniform(c,"f","amount",i),v=new CGL.Uniform(c,"f","lensDistort",o);s.onChange=function(){if(s.get())c.define("SMOOTH");else c.removeDefine("SMOOTH")};l.onChange=function(){if(l.get())c.define("MASK");else c.removeDefine("MASK")};n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(t,3))return;let e=m.currentTextureEffect.getCurrentSourceTexture();h.setValue(r.get()*(1/e.width));f.setValue(1/e.width);m.pushShader(c);m.currentTextureEffect.bind();m.setTexture(0,e.tex);if(l.get())m.setTexture(1,l.get().tex);m.currentTextureEffect.finish();m.popShader();u.trigger()}};Ops.Gl.ImageCompose.ChromaticAberration_v2.prototype=new CABLES.Op;CABLES.OPS["07701f81-1a98-44c0-b1ef-592db3cbb5d3"]={f:Ops.Gl.ImageCompose.ChromaticAberration_v2,objName:"Ops.Gl.ImageCompose.ChromaticAberration_v2"};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 n=e.inTrigger("render");let a=e.outTrigger("trigger");let i=e.inValueSelect("span",[0,2,4,8,16,32,64]);let r=e.inValueFloat("reduceMin");let o=e.inValueFloat("reduceMul");let s=e.inValueBool("use viewport size",true);let l=e.inValueInt("width");let u=e.inValueInt("height");let m=e.patch.cgl;let c=new CGL.Shader(m,e.name,e);c.setSource(c.getDefaultVertexShader(),t.fxaa_frag);let d=new CGL.Uniform(c,"t","tex",0);n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;m.pushShader(c);if(m.getViewPort()[2]!=l.get()||m.getViewPort()[3]!=u.get()){b()}m.currentTextureEffect.bind();m.setTexture(0,m.currentTextureEffect.getCurrentSourceTexture().tex);m.currentTextureEffect.finish();m.popShader();a.trigger()};let h=new CGL.Uniform(c,"f","FXAA_SPAN_MAX",0);let f=new CGL.Uniform(c,"f","FXAA_REDUCE_MUL",0);let p=new CGL.Uniform(c,"f","FXAA_REDUCE_MIN",0);i.onChange=function(){h.setValue(parseInt(i.get(),10))};let g=new CGL.Uniform(c,"f","width",0);let v=new CGL.Uniform(c,"f","height",0);function b(){if(s.get()){let e=m.getViewPort()[2];let t=m.getViewPort()[3];g.setValue(e);v.setValue(t)}else{g.setValue(l.get());v.setValue(u.get())}}l.onChange=b;u.onChange=b;s.onChange=b;e.onResize=b;i.set(8);o.onChange=function(){f.setValue(1/o.get())};r.onChange=function(){p.setValue(1/r.get())};o.set(8);r.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.Number.Number=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValueFloat("value"),a=e.outNumber("result");n.onChange=i;function i(){a.set(Number(n.get()))}};Ops.Number.Number.prototype=new CABLES.Op;CABLES.OPS["8fb2bb5d-665a-4d0a-8079-12710ae453be"]={f:Ops.Number.Number,objName:"Ops.Number.Number"};Ops.Trigger.RouteTrigger=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=24;const a=t.inTriggerButton("Execute"),i=t.inValueInt("Switch Value"),r=t.outTrigger("Next Trigger"),o=t.outNumber("Switched Value");const s=[];a.onTriggered=m;for(let e=0;e<n;e++){s[e]=t.outTrigger("Trigger "+e);s[e].onLinkChanged=c}const l=t.outTrigger("Default Trigger"),u=t.outNumber("Highest Index");function m(){const e=Math.round(i.get());if(e>=0&&e<n){o.set(e);s[e].trigger()}else{o.set(-1);l.trigger()}r.trigger()}function c(){let t=0;for(let e=0;e<s.length;e++)if(s[e]&&s[e].isLinked())t=e;u.set(t)}};Ops.Trigger.RouteTrigger.prototype=new CABLES.Op;CABLES.OPS["44ceb5d8-b040-4722-b189-a6fb8172517d"]={f:Ops.Trigger.RouteTrigger,objName:"Ops.Trigger.RouteTrigger"};Ops.Boolean.Boolean=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inBool("value",false),a=e.outBoolNum("result");a.set(false);n.onChange=i;function i(){if(a.get()!=n.get())a.set(n.get())}};Ops.Boolean.Boolean.prototype=new CABLES.Op;CABLES.OPS["83e2d74c-9741-41aa-a4d7-1bda4ef55fb3"]={f:Ops.Boolean.Boolean,objName:"Ops.Boolean.Boolean"};Ops.Sidebar.Sidebar=function(){CABLES.Op.apply(this,arguments);const o=this;const n=o.attachments={style_css:" /*\n * SIDEBAR\n  http://danielstern.ca/range.css/#/\n  https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-progress-value\n */\n\n.sidebar-icon-undo\n{\n    width:10px;\n    height:10px;\n    background-image: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='grey' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 7v6h6'/%3E%3Cpath d='M21 17a9 9 0 00-9-9 9 9 0 00-6 2.3L3 13'/%3E%3C/svg%3E\");\n    background-size: 19px;\n    background-repeat: no-repeat;\n    top: -19px;\n    margin-top: -7px;\n}\n\n.icon-chevron-down {\n    top: 2px;\n    right: 9px;\n}\n\n.iconsidebar-chevron-up,.sidebar__close-button {\n\tbackground-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM4ODg4ODgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLWNoZXZyb24tdXAiPjxwb2x5bGluZSBwb2ludHM9IjE4IDE1IDEyIDkgNiAxNSI+PC9wb2x5bGluZT48L3N2Zz4=);\n}\n\n.iconsidebar-minimizebutton {\n    background-position: 98% center;\n    background-repeat: no-repeat;\n}\n\n.sidebar-cables-right\n{\n    right: 15px;\n    left: initial !important;\n}\n\n.sidebar-cables *\n{\n    color: #BBBBBB !important;\n    font-family: Arial;\n}\n\n.sidebar-cables {\n    --sidebar-color: #07f78c;\n    --sidebar-width: 220px;\n    --sidebar-border-radius: 10px;\n    --sidebar-monospace-font-stack: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n    --sidebar-hover-transition-time: .2s;\n\n    position: absolute;\n    top: 15px;\n    left: 15px;\n    border-radius: var(--sidebar-border-radius);\n    z-index: 100000;\n    width: var(--sidebar-width);\n    max-height: 100%;\n    box-sizing: border-box;\n    overflow-y: auto;\n    overflow-x: hidden;\n    font-size: 13px;\n    line-height: 1em; /* prevent emojis from breaking height of the title */\n}\n\n.sidebar-cables::selection {\n    background-color: var(--sidebar-color);\n    color: #EEEEEE;\n}\n\n.sidebar-cables::-webkit-scrollbar {\n    background-color: transparent;\n    --cables-scrollbar-width: 8px;\n    width: var(--cables-scrollbar-width);\n}\n\n.sidebar-cables::-webkit-scrollbar-track {\n    background-color: transparent;\n    width: var(--cables-scrollbar-width);\n}\n\n.sidebar-cables::-webkit-scrollbar-thumb {\n    background-color: #333333;\n    border-radius: 4px;\n    width: var(--cables-scrollbar-width);\n}\n\n.sidebar-cables--closed {\n    width: auto;\n}\n\n.sidebar__close-button {\n    background-color: #222;\n    /*-webkit-user-select: none;  */\n    /*-moz-user-select: none;     */\n    /*-ms-user-select: none;      */\n    /*user-select: none;          */\n    /*transition: background-color var(--sidebar-hover-transition-time);*/\n    /*color: #CCCCCC;*/\n    height: 2px;\n    /*border-bottom:20px solid #222;*/\n\n    /*box-sizing: border-box;*/\n    /*padding-top: 2px;*/\n    /*text-align: center;*/\n    /*cursor: pointer;*/\n    /*border-radius: 0 0 var(--sidebar-border-radius) var(--sidebar-border-radius);*/\n    /*opacity: 1.0;*/\n    /*transition: opacity 0.3s;*/\n    /*overflow: hidden;*/\n}\n\n.sidebar__close-button-icon {\n    display: inline-block;\n    /*opacity: 0;*/\n    width: 20px;\n    height: 20px;\n    /*position: relative;*/\n    /*top: -1px;*/\n\n\n}\n\n.sidebar--closed {\n    width: auto;\n    margin-right: 20px;\n}\n\n.sidebar--closed .sidebar__close-button {\n    margin-top: 8px;\n    margin-left: 8px;\n    padding:10px;\n\n    height: 25px;\n    width:25px;\n    border-radius: 50%;\n    cursor: pointer;\n    opacity: 0.3;\n    background-repeat: no-repeat;\n    background-position: center center;\n    transform:rotate(180deg);\n}\n\n.sidebar--closed .sidebar__group\n{\n    display:none;\n\n}\n.sidebar--closed .sidebar__close-button-icon {\n    background-position: 0px 0px;\n}\n\n.sidebar__close-button:hover {\n    background-color: #111111;\n    opacity: 1.0 !important;\n}\n\n/*\n * SIDEBAR ITEMS\n */\n\n.sidebar__items {\n    /* max-height: 1000px; */\n    /* transition: max-height 0.5;*/\n    background-color: #222;\n    padding-bottom: 20px;\n}\n\n.sidebar--closed .sidebar__items {\n    /* max-height: 0; */\n    height: 0;\n    display: none;\n    pointer-interactions: none;\n}\n\n.sidebar__item__right {\n    float: right;\n}\n\n/*\n * SIDEBAR GROUP\n */\n\n.sidebar__group {\n    /*background-color: #1A1A1A;*/\n    overflow: hidden;\n    box-sizing: border-box;\n    animate: height;\n    /*background-color: #151515;*/\n    /* max-height: 1000px; */\n    /* transition: max-height 0.5s; */\n--sidebar-group-header-height: 33px;\n}\n\n.sidebar__group-items\n{\n    padding-top: 15px;\n    padding-bottom: 15px;\n}\n\n.sidebar__group--closed {\n    /* max-height: 13px; */\n    height: var(--sidebar-group-header-height);\n}\n\n.sidebar__group-header {\n    box-sizing: border-box;\n    color: #EEEEEE;\n    background-color: #151515;\n    -webkit-user-select: none;  /* Chrome all / Safari all */\n    -moz-user-select: none;     /* Firefox all */\n    -ms-user-select: none;      /* IE 10+ */\n    user-select: none;          /* Likely future */\n\n    /*height: 100%;//var(--sidebar-group-header-height);*/\n\n    padding-top: 7px;\n    text-transform: uppercase;\n    letter-spacing: 0.08em;\n    cursor: pointer;\n    /*transition: background-color var(--sidebar-hover-transition-time);*/\n    position: relative;\n}\n\n.sidebar__group-header:hover {\n  background-color: #111111;\n}\n\n.sidebar__group-header-title {\n  /*float: left;*/\n  overflow: hidden;\n  padding: 0 15px;\n  padding-top:5px;\n  padding-bottom:10px;\n  font-weight:bold;\n}\n\n.sidebar__group-header-undo {\n    float: right;\n    overflow: hidden;\n    padding-right: 15px;\n    padding-top:5px;\n    font-weight:bold;\n  }\n\n.sidebar__group-header-icon {\n    width: 17px;\n    height: 14px;\n    background-repeat: no-repeat;\n    display: inline-block;\n    position: absolute;\n    background-size: cover;\n\n    /* icon open */\n    /* feather icon: chevron up */\n    background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM4ODg4ODgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLWNoZXZyb24tdXAiPjxwb2x5bGluZSBwb2ludHM9IjE4IDE1IDEyIDkgNiAxNSI+PC9wb2x5bGluZT48L3N2Zz4=);\n    top: 4px;\n    right: 5px;\n    opacity: 0.0;\n    transition: opacity 0.3;\n}\n\n.sidebar__group-header:hover .sidebar__group-header-icon {\n    opacity: 1.0;\n}\n\n/* icon closed */\n.sidebar__group--closed .sidebar__group-header-icon {\n    /* feather icon: chevron down */\n    background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM4ODg4ODgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLWNoZXZyb24tZG93biI+PHBvbHlsaW5lIHBvaW50cz0iNiA5IDEyIDE1IDE4IDkiPjwvcG9seWxpbmU+PC9zdmc+);\n    top: 4px;\n    right: 5px;\n}\n\n/*\n * SIDEBAR ITEM\n */\n\n.sidebar__item\n{\n    box-sizing: border-box;\n    padding: 7px;\n    padding-left:15px;\n    padding-right:15px;\n\n    overflow: hidden;\n    position: relative;\n}\n\n.sidebar__item-label {\n    display: inline-block;\n    -webkit-user-select: none;  /* Chrome all / Safari all */\n    -moz-user-select: none;     /* Firefox all */\n    -ms-user-select: none;      /* IE 10+ */\n    user-select: none;          /* Likely future */\n    width: calc(50% - 7px);\n    margin-right: 7px;\n    margin-top: 2px;\n    text-overflow: ellipsis;\n    /* overflow: hidden; */\n}\n\n.sidebar__item-value-label {\n    font-family: var(--sidebar-monospace-font-stack);\n    display: inline-block;\n    text-overflow: ellipsis;\n    overflow: hidden;\n    white-space: nowrap;\n    max-width: 60%;\n}\n\n.sidebar__item-value-label::selection {\n    background-color: var(--sidebar-color);\n    color: #EEEEEE;\n}\n\n.sidebar__item + .sidebar__item,\n.sidebar__item + .sidebar__group,\n.sidebar__group + .sidebar__item,\n.sidebar__group + .sidebar__group {\n    /*border-top: 1px solid #272727;*/\n}\n\n/*\n * SIDEBAR ITEM TOGGLE\n */\n\n/*.sidebar__toggle */\n.icon_toggle{\n    cursor: pointer;\n}\n\n.sidebar__toggle-input {\n    --sidebar-toggle-input-color: #CCCCCC;\n    --sidebar-toggle-input-color-hover: #EEEEEE;\n    --sidebar-toggle-input-border-size: 2px;\n    display: inline;\n    float: right;\n    box-sizing: border-box;\n    border-radius: 50%;\n    cursor: pointer;\n    --toggle-size: 11px;\n    margin-top: 2px;\n    background-color: transparent !important;\n    border: var(--sidebar-toggle-input-border-size) solid var(--sidebar-toggle-input-color);\n    width: var(--toggle-size);\n    height: var(--toggle-size);\n    transition: background-color var(--sidebar-hover-transition-time);\n    transition: border-color var(--sidebar-hover-transition-time);\n}\n.sidebar__toggle:hover .sidebar__toggle-input {\n    border-color: var(--sidebar-toggle-input-color-hover);\n}\n\n.sidebar__toggle .sidebar__item-value-label {\n    -webkit-user-select: none;  /* Chrome all / Safari all */\n    -moz-user-select: none;     /* Firefox all */\n    -ms-user-select: none;      /* IE 10+ */\n    user-select: none;          /* Likely future */\n    max-width: calc(50% - 12px);\n}\n.sidebar__toggle-input::after { clear: both; }\n\n.sidebar__toggle--active .icon_toggle\n{\n\n    background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE1cHgiIHdpZHRoPSIzMHB4IiBmaWxsPSIjMDZmNzhiIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTAwIDEwMCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PGcgZGlzcGxheT0ibm9uZSI+PGcgZGlzcGxheT0iaW5saW5lIj48Zz48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZmlsbD0iIzA2Zjc4YiIgZD0iTTMwLDI3QzE3LjM1LDI3LDcsMzcuMzUsNyw1MGwwLDBjMCwxMi42NSwxMC4zNSwyMywyMywyM2g0MCBjMTIuNjUsMCwyMy0xMC4zNSwyMy0yM2wwLDBjMC0xMi42NS0xMC4zNS0yMy0yMy0yM0gzMHogTTcwLDY3Yy05LjM4OSwwLTE3LTcuNjEtMTctMTdzNy42MTEtMTcsMTctMTdzMTcsNy42MSwxNywxNyAgICAgUzc5LjM4OSw2Nyw3MCw2N3oiPjwvcGF0aD48L2c+PC9nPjwvZz48Zz48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTMwLDI3QzE3LjM1LDI3LDcsMzcuMzUsNyw1MGwwLDBjMCwxMi42NSwxMC4zNSwyMywyMywyM2g0MCAgIGMxMi42NSwwLDIzLTEwLjM1LDIzLTIzbDAsMGMwLTEyLjY1LTEwLjM1LTIzLTIzLTIzSDMweiBNNzAsNjdjLTkuMzg5LDAtMTctNy42MS0xNy0xN3M3LjYxMS0xNywxNy0xN3MxNyw3LjYxLDE3LDE3ICAgUzc5LjM4OSw2Nyw3MCw2N3oiPjwvcGF0aD48L2c+PGcgZGlzcGxheT0ibm9uZSI+PGcgZGlzcGxheT0iaW5saW5lIj48cGF0aCBmaWxsPSIjMDZmNzhiIiBzdHJva2U9IiMwNmY3OGIiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBkPSJNNyw1MGMwLDEyLjY1LDEwLjM1LDIzLDIzLDIzaDQwICAgIGMxMi42NSwwLDIzLTEwLjM1LDIzLTIzbDAsMGMwLTEyLjY1LTEwLjM1LTIzLTIzLTIzSDMwQzE3LjM1LDI3LDcsMzcuMzUsNyw1MEw3LDUweiI+PC9wYXRoPjwvZz48Y2lyY2xlIGRpc3BsYXk9ImlubGluZSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiMwNmY3OGIiIHN0cm9rZT0iIzA2Zjc4YiIgc3Ryb2tlLXdpZHRoPSI0IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGN4PSI3MCIgY3k9IjUwIiByPSIxNyI+PC9jaXJjbGU+PC9nPjxnIGRpc3BsYXk9Im5vbmUiPjxwYXRoIGRpc3BsYXk9ImlubGluZSIgZD0iTTcwLDI1SDMwQzE2LjIxNSwyNSw1LDM2LjIxNSw1LDUwczExLjIxNSwyNSwyNSwyNWg0MGMxMy43ODUsMCwyNS0xMS4yMTUsMjUtMjVTODMuNzg1LDI1LDcwLDI1eiBNNzAsNzEgICBIMzBDMTguNDIxLDcxLDksNjEuNTc5LDksNTBzOS40MjEtMjEsMjEtMjFoNDBjMTEuNTc5LDAsMjEsOS40MjEsMjEsMjFTODEuNTc5LDcxLDcwLDcxeiBNNzAsMzFjLTEwLjQ3NywwLTE5LDguNTIzLTE5LDE5ICAgczguNTIzLDE5LDE5LDE5czE5LTguNTIzLDE5LTE5UzgwLjQ3NywzMSw3MCwzMXogTTcwLDY1Yy04LjI3MSwwLTE1LTYuNzI5LTE1LTE1czYuNzI5LTE1LDE1LTE1czE1LDYuNzI5LDE1LDE1Uzc4LjI3MSw2NSw3MCw2NXoiPjwvcGF0aD48L2c+PC9zdmc+);\n    opacity: 1;\n    transform: rotate(0deg);\n}\n\n\n.icon_toggle\n{\n    float: right;\n    width:40px;\n    height:18px;\n    background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE1cHgiIHdpZHRoPSIzMHB4IiBmaWxsPSIjYWFhYWFhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTAwIDEwMCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PGcgZGlzcGxheT0ibm9uZSI+PGcgZGlzcGxheT0iaW5saW5lIj48Zz48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZmlsbD0iI2FhYWFhYSIgZD0iTTMwLDI3QzE3LjM1LDI3LDcsMzcuMzUsNyw1MGwwLDBjMCwxMi42NSwxMC4zNSwyMywyMywyM2g0MCBjMTIuNjUsMCwyMy0xMC4zNSwyMy0yM2wwLDBjMC0xMi42NS0xMC4zNS0yMy0yMy0yM0gzMHogTTcwLDY3Yy05LjM4OSwwLTE3LTcuNjEtMTctMTdzNy42MTEtMTcsMTctMTdzMTcsNy42MSwxNywxNyAgICAgUzc5LjM4OSw2Nyw3MCw2N3oiPjwvcGF0aD48L2c+PC9nPjwvZz48Zz48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTMwLDI3QzE3LjM1LDI3LDcsMzcuMzUsNyw1MGwwLDBjMCwxMi42NSwxMC4zNSwyMywyMywyM2g0MCAgIGMxMi42NSwwLDIzLTEwLjM1LDIzLTIzbDAsMGMwLTEyLjY1LTEwLjM1LTIzLTIzLTIzSDMweiBNNzAsNjdjLTkuMzg5LDAtMTctNy42MS0xNy0xN3M3LjYxMS0xNywxNy0xN3MxNyw3LjYxLDE3LDE3ICAgUzc5LjM4OSw2Nyw3MCw2N3oiPjwvcGF0aD48L2c+PGcgZGlzcGxheT0ibm9uZSI+PGcgZGlzcGxheT0iaW5saW5lIj48cGF0aCBmaWxsPSIjYWFhYWFhIiBzdHJva2U9IiNhYWFhYWEiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBkPSJNNyw1MGMwLDEyLjY1LDEwLjM1LDIzLDIzLDIzaDQwICAgIGMxMi42NSwwLDIzLTEwLjM1LDIzLTIzbDAsMGMwLTEyLjY1LTEwLjM1LTIzLTIzLTIzSDMwQzE3LjM1LDI3LDcsMzcuMzUsNyw1MEw3LDUweiI+PC9wYXRoPjwvZz48Y2lyY2xlIGRpc3BsYXk9ImlubGluZSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiNhYWFhYWEiIHN0cm9rZT0iI2FhYWFhYSIgc3Ryb2tlLXdpZHRoPSI0IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGN4PSI3MCIgY3k9IjUwIiByPSIxNyI+PC9jaXJjbGU+PC9nPjxnIGRpc3BsYXk9Im5vbmUiPjxwYXRoIGRpc3BsYXk9ImlubGluZSIgZD0iTTcwLDI1SDMwQzE2LjIxNSwyNSw1LDM2LjIxNSw1LDUwczExLjIxNSwyNSwyNSwyNWg0MGMxMy43ODUsMCwyNS0xMS4yMTUsMjUtMjVTODMuNzg1LDI1LDcwLDI1eiBNNzAsNzEgICBIMzBDMTguNDIxLDcxLDksNjEuNTc5LDksNTBzOS40MjEtMjEsMjEtMjFoNDBjMTEuNTc5LDAsMjEsOS40MjEsMjEsMjFTODEuNTc5LDcxLDcwLDcxeiBNNzAsMzFjLTEwLjQ3NywwLTE5LDguNTIzLTE5LDE5ICAgczguNTIzLDE5LDE5LDE5czE5LTguNTIzLDE5LTE5UzgwLjQ3NywzMSw3MCwzMXogTTcwLDY1Yy04LjI3MSwwLTE1LTYuNzI5LTE1LTE1czYuNzI5LTE1LDE1LTE1czE1LDYuNzI5LDE1LDE1Uzc4LjI3MSw2NSw3MCw2NXoiPjwvcGF0aD48L2c+PC9zdmc+);\n    background-size: 50px 37px;\n    background-position: -6px -10px;\n    transform: rotate(180deg);\n    opacity: 0.4;\n}\n\n\n\n/*.sidebar__toggle--active .sidebar__toggle-input {*/\n/*    transition: background-color var(--sidebar-hover-transition-time);*/\n/*    background-color: var(--sidebar-toggle-input-color);*/\n/*}*/\n/*.sidebar__toggle--active .sidebar__toggle-input:hover*/\n/*{*/\n/*    background-color: var(--sidebar-toggle-input-color-hover);*/\n/*    border-color: var(--sidebar-toggle-input-color-hover);*/\n/*    transition: background-color var(--sidebar-hover-transition-time);*/\n/*    transition: border-color var(--sidebar-hover-transition-time);*/\n/*}*/\n\n/*\n * SIDEBAR ITEM BUTTON\n */\n\n.sidebar__button {}\n\n.sidebar__button-input:active\n{\n    background-color: #555 !important;\n}\n\n.sidebar__button-input {\n    -webkit-user-select: none;  /* Chrome all / Safari all */\n    -moz-user-select: none;     /* Firefox all */\n    -ms-user-select: none;      /* IE 10+ */\n    user-select: none;          /* Likely future */\n    min-height: 24px;\n    background-color: transparent;\n    color: #CCCCCC;\n    box-sizing: border-box;\n    padding-top: 3px;\n    text-align: center;\n    border-radius: 125px;\n    border:2px solid #555;\n    cursor: pointer;\n    padding-bottom: 3px;\n}\n\n.sidebar__button-input.plus, .sidebar__button-input.minus {\n    display: inline-block;\n    min-width: 20px;\n}\n\n.sidebar__button-input:hover {\n  background-color: #333;\n  border:2px solid var(--sidebar-color);\n}\n\n/*\n * VALUE DISPLAY (shows a value)\n */\n\n.sidebar__value-display {}\n\n/*\n * SLIDER\n */\n\n.sidebar__slider {\n    --sidebar-slider-input-height: 3px;\n}\n\n.sidebar__slider-input-wrapper {\n    width: 100%;\n\n    margin-top: 8px;\n    position: relative;\n}\n\n.sidebar__slider-input {\n    -webkit-appearance: none;\n    appearance: none;\n    margin: 0;\n    width: 100%;\n    height: var(--sidebar-slider-input-height);\n    background: #555;\n    cursor: pointer;\n    outline: 0;\n\n    -webkit-transition: .2s;\n    transition: background-color .2s;\n    border: none;\n}\n\n.sidebar__slider-input:focus, .sidebar__slider-input:hover {\n    border: none;\n}\n\n.sidebar__slider-input-active-track {\n    user-select: none;\n    position: absolute;\n    z-index: 11;\n    top: 0;\n    left: 0;\n    background-color: var(--sidebar-color);\n    pointer-events: none;\n    height: var(--sidebar-slider-input-height);\n    max-width: 100%;\n}\n\n/* Mouse-over effects */\n.sidebar__slider-input:hover {\n    /*background-color: #444444;*/\n}\n\n/*.sidebar__slider-input::-webkit-progress-value {*/\n/*    background-color: green;*/\n/*    color:green;*/\n\n/*    }*/\n\n/* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */\n\n.sidebar__slider-input::-moz-range-thumb\n{\n    position: absolute;\n    height: 15px;\n    width: 15px;\n    z-index: 900 !important;\n    border-radius: 20px !important;\n    cursor: pointer;\n    background: var(--sidebar-color) !important;\n    user-select: none;\n\n}\n\n.sidebar__slider-input::-webkit-slider-thumb\n{\n    position: relative;\n    appearance: none;\n    -webkit-appearance: none;\n    user-select: none;\n    height: 15px;\n    width: 15px;\n    display: block;\n    z-index: 900 !important;\n    border: 0;\n    border-radius: 20px !important;\n    cursor: pointer;\n    background: #777 !important;\n}\n\n.sidebar__slider-input:hover ::-webkit-slider-thumb {\n    background-color: #EEEEEE !important;\n}\n\n/*.sidebar__slider-input::-moz-range-thumb {*/\n\n/*    width: 0 !important;*/\n/*    height: var(--sidebar-slider-input-height);*/\n/*    background: #EEEEEE;*/\n/*    cursor: pointer;*/\n/*    border-radius: 0 !important;*/\n/*    border: none;*/\n/*    outline: 0;*/\n/*    z-index: 100 !important;*/\n/*}*/\n\n.sidebar__slider-input::-moz-range-track {\n    background-color: transparent;\n    z-index: 11;\n}\n\n/*.sidebar__slider-input::-moz-range-thumb:hover {*/\n  /* background-color: #EEEEEE; */\n/*}*/\n\n\n/*.sidebar__slider-input-wrapper:hover .sidebar__slider-input-active-track {*/\n/*    background-color: #EEEEEE;*/\n/*}*/\n\n/*.sidebar__slider-input-wrapper:hover .sidebar__slider-input::-moz-range-thumb {*/\n/*    background-color: #fff !important;*/\n/*}*/\n\n/*.sidebar__slider-input-wrapper:hover .sidebar__slider-input::-webkit-slider-thumb {*/\n/*    background-color: #EEEEEE;*/\n/*}*/\n\n.sidebar__slider input[type=text],\n.sidebar__slider input[type=paddword]\n{\n    box-sizing: border-box;\n    /*background-color: #333333;*/\n    text-align: right;\n    color: #BBBBBB;\n    display: inline-block;\n    background-color: transparent !important;\n\n    width: 40%;\n    height: 18px;\n    outline: none;\n    border: none;\n    border-radius: 0;\n    padding: 0 0 0 4px !important;\n    margin: 0;\n}\n\n.sidebar__slider input[type=text]:active,\n.sidebar__slider input[type=text]:focus,\n.sidebar__slider input[type=text]:hover\n.sidebar__slider input[type=password]:active,\n.sidebar__slider input[type=password]:focus,\n.sidebar__slider input[type=password]:hover\n{\n\n    color: #EEEEEE;\n}\n\n/*\n * TEXT / DESCRIPTION\n */\n\n.sidebar__text .sidebar__item-label {\n    width: auto;\n    display: block;\n    max-height: none;\n    margin-right: 0;\n    line-height: 1.1em;\n}\n\n/*\n * SIDEBAR INPUT\n */\n.sidebar__text-input textarea,\n.sidebar__text-input input[type=date],\n.sidebar__text-input input[type=datetime-local],\n.sidebar__text-input input[type=text],\n.sidebar__text-input input[type=password] {\n    box-sizing: border-box;\n    background-color: #333333;\n    color: #BBBBBB;\n    display: inline-block;\n    width: 50%;\n    height: 18px;\n    outline: none;\n    border: none;\n    border-radius: 0;\n    border:1px solid #666;\n    padding: 0 0 0 4px !important;\n    margin: 0;\n    color-scheme: dark;\n}\n\n.sidebar__text-input textarea:focus::placeholder {\n  color: transparent;\n}\n\n.sidebar__color-picker .sidebar__item-label\n{\n    width:45%;\n}\n\n.sidebar__text-input textarea,\n.sidebar__text-input input[type=text]:active,\n.sidebar__text-input input[type=text]:focus,\n.sidebar__text-input input[type=text]:hover,\n.sidebar__text-input input[type=password]:active,\n.sidebar__text-input input[type=password]:focus,\n.sidebar__text-input input[type=password]:hover {\n    background-color: transparent;\n    color: #EEEEEE;\n}\n\n.sidebar__text-input textarea\n{\n    margin-top:10px;\n    height:60px;\n    width:100%;\n}\n\n/*\n * SIDEBAR SELECT\n */\n\n\n\n .sidebar__select {}\n .sidebar__select-select {\n    color: #BBBBBB;\n    /*-webkit-appearance: none;*/\n    /*-moz-appearance: none;*/\n    appearance: none;\n    /*box-sizing: border-box;*/\n    width: 50%;\n    /*height: 20px;*/\n    background-color: #333333;\n    /*background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM4ODg4ODgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLWNoZXZyb24tZG93biI+PHBvbHlsaW5lIHBvaW50cz0iNiA5IDEyIDE1IDE4IDkiPjwvcG9seWxpbmU+PC9zdmc+);*/\n    background-repeat: no-repeat;\n    background-position: right center;\n    background-size: 16px 16px;\n    margin: 0;\n    /*padding: 0 2 2 6px;*/\n    border-radius: 5px;\n    border: 1px solid #777;\n    background-color: #444;\n    cursor: pointer;\n    outline: none;\n    padding-left: 5px;\n\n }\n\n.sidebar__select-select:hover,\n.sidebar__select-select:active,\n.sidebar__select-select:inactive {\n    background-color: #444444;\n    color: #EEEEEE;\n}\n\n/*.sidebar__select-select option*/\n/*{*/\n/*    background-color: #444444;*/\n/*    color: #bbb;*/\n/*}*/\n\n.sidebar__select-select option:checked\n{\n    background-color: #000;\n    color: #FFF;\n}\n\n\n/*\n * COLOR PICKER\n */\n\n\n .sidebar__color-picker input[type=text] {\n    box-sizing: border-box;\n    background-color: #333333;\n    color: #BBBBBB;\n    display: inline-block;\n    width: calc(50% - 21px); /* 50% minus space of picker circle */\n    height: 18px;\n    outline: none;\n    border: none;\n    border-radius: 0;\n    padding: 0 0 0 4px !important;\n    margin: 0;\n    margin-right: 7px;\n}\n\n.sidebar__color-picker input[type=text]:active,\n.sidebar__color-picker input[type=text]:focus,\n.sidebar__color-picker input[type=text]:hover {\n    background-color: #444444;\n    color: #EEEEEE;\n}\n\ndiv.sidebar__color-picker-color-input,\n.sidebar__color-picker input[type=color],\n.sidebar__palette-picker input[type=color] {\n    display: inline-block;\n    border-radius: 100%;\n    height: 14px;\n    width: 14px;\n\n    padding: 0;\n    border: none;\n    /*border:2px solid red;*/\n    border-color: transparent;\n    outline: none;\n    background: none;\n    appearance: none;\n    -moz-appearance: none;\n    -webkit-appearance: none;\n    cursor: pointer;\n    position: relative;\n    top: 3px;\n}\n.sidebar__color-picker input[type=color]:focus,\n.sidebar__palette-picker input[type=color]:focus {\n    outline: none;\n}\n.sidebar__color-picker input[type=color]::-moz-color-swatch,\n.sidebar__palette-picker input[type=color]::-moz-color-swatch {\n    border: none;\n}\n.sidebar__color-picker input[type=color]::-webkit-color-swatch-wrapper,\n.sidebar__palette-picker input[type=color]::-webkit-color-swatch-wrapper {\n    padding: 0;\n}\n.sidebar__color-picker input[type=color]::-webkit-color-swatch,\n.sidebar__palette-picker input[type=color]::-webkit-color-swatch {\n    border: none;\n    border-radius: 100%;\n}\n\n/*\n * Palette Picker\n */\n.sidebar__palette-picker .sidebar__palette-picker-color-input.first {\n    margin-left: 0;\n}\n.sidebar__palette-picker .sidebar__palette-picker-color-input.last {\n    margin-right: 0;\n}\n.sidebar__palette-picker .sidebar__palette-picker-color-input {\n    margin: 0 4px;\n}\n\n.sidebar__palette-picker .circlebutton {\n    width: 14px;\n    height: 14px;\n    border-radius: 1em;\n    display: inline-block;\n    top: 3px;\n    position: relative;\n}\n\n/*\n * Preset\n */\n.sidebar__item-presets-preset\n{\n    padding:4px;\n    cursor:pointer;\n    padding-left:8px;\n    padding-right:8px;\n    margin-right:4px;\n    background-color:#444;\n}\n\n.sidebar__item-presets-preset:hover\n{\n    background-color:#666;\n}\n\n.sidebar__greyout\n{\n    background: #222;\n    opacity: 0.8;\n    width: 100%;\n    height: 100%;\n    position: absolute;\n    z-index: 1000;\n    right: 0;\n    top: 0;\n}\n\n.sidebar_tabs\n{\n    background-color: #151515;\n    padding-bottom: 0px;\n}\n\n.sidebar_switchs\n{\n    float: right;\n}\n\n.sidebar_tab\n{\n    float:left;\n    background-color: #151515;\n    border-bottom:1px solid transparent;\n    padding-right:7px;\n    padding-left:7px;\n    padding-bottom: 5px;\n    padding-top: 5px;\n    cursor:pointer;\n}\n\n.sidebar_tab_active\n{\n    background-color: #272727;\n    color:white;\n}\n\n.sidebar_tab:hover\n{\n    border-bottom:1px solid #777;\n    color:white;\n}\n\n\n.sidebar_switch\n{\n    float:left;\n    background-color: #444;\n    padding-right:7px;\n    padding-left:7px;\n    padding-bottom: 5px;\n    padding-top: 5px;\n    cursor:pointer;\n}\n\n.sidebar_switch:last-child\n{\n    border-top-right-radius: 7px;\n    border-bottom-right-radius: 7px;\n}\n\n.sidebar_switch:first-child\n{\n    border-top-left-radius: 7px;\n    border-bottom-left-radius: 7px;\n}\n\n\n.sidebar_switch_active\n{\n    background-color: #999;\n    color:white;\n}\n\n.sidebar_switch:hover\n{\n    color:white;\n}\n\n"};const a="cables-sidebar-style";const i="cables-sidebar-dynamic-style";const s="sidebar-cables";const l="sidebar"+CABLES.uuid();const u="sidebar__items";const m="sidebar__close-button";const r="";const c="";let d=null;let R=null;let h=null;const e=o.inValueBool("Visible",true);const t=o.inValueSlider("Opacity",1);const f=o.inValueBool("Default Minimized");const p=o.inValueSlider("Minimized Opacity",.5);const g=o.inValueBool("Show undo button",false);const v=o.inValueBool("Show Minimize",false);const b=o.inString("Title","");const x=o.inValueBool("Side");const _=o.inValueBool("Default CSS",true);let O=o.patch.cgl.canvas.ownerDocument;const A=o.outObject("childs");A.setUiAttribs({title:"Children"});const I=o.outBool("Opfened");I.setUiAttribs({title:"Opened"});let T=O.querySelector("."+l);if(!T)T=B();const S=T.querySelector("."+u);A.set({parentElement:S,parentOp:o});P();w();j();_.onChange=()=>{w();j()};e.onChange=k;t.onChange=N;f.onChange=P;p.onChange=C;g.onChange=E;o.onDelete=G;function C(){j()}v.onChange=y;function y(e){if(!e||e.uiAttribs)e=O.querySelector(".sidebar-cables .sidebar__group-header");if(!e)return;const t=O.querySelector(".sidebar-cables .sidebar__group-header .sidebar__group-header-undo");if(v.get()){e.classList.add("iconsidebar-chevron-up");e.classList.add("iconsidebar-minimizebutton");if(t)t.style.marginRight="20px"}else{e.classList.remove("iconsidebar-chevron-up");e.classList.remove("iconsidebar-minimizebutton");if(t)t.style.marginRight="initial"}}x.onChange=function(){if(!T)return;if(x.get())T.classList.add("sidebar-cables-right");else T.classList.remove("sidebar-cables-right")};function E(){const e=O.querySelector(".sidebar-cables .sidebar__group-header");if(e){M(e)}}function M(e){if(e){const t=O.querySelector(".sidebar-cables .sidebar__group-header .sidebar__group-header-undo");if(t){if(!g.get()){t.remove()}}else{if(g.get()){const n=O.createElement("span");n.classList.add("sidebar__group-header-undo");n.classList.add("sidebar-icon-undo");n.addEventListener("click",function(e){e.stopPropagation();const t=O.querySelectorAll(".sidebar-cables .sidebar__reloadable");const n=O.createEvent("MouseEvents");n.initEvent("dblclick",true,true);t.forEach(e=>{e.dispatchEvent(n)})});e.appendChild(n)}}}y(e)}function P(){if(!d){return}if(f.get()){T.classList.add("sidebar--closed");if(e.get())I.set(false)}else{T.classList.remove("sidebar--closed");if(e.get())I.set(true)}}function N(){const e=t.get();T.style.opacity=e}function k(){if(!T)return;if(e.get()){T.style.display="block";if(!T.classList.contains("sidebar--closed"))I.set(true)}else{T.style.display="none";I.set(false)}}x.onChanged=function(){};function j(){const e=O.querySelectorAll("."+i);if(e){e.forEach(function(e){e.parentNode.removeChild(e)})}if(!_.get())return;const t=O.createElement("style");t.classList.add("cablesEle");t.classList.add(i);let n=".sidebar--closed .sidebar__close-button { ";n+="opacity: "+p.get();n+="}";const a=O.createTextNode(n);t.appendChild(a);O.body.appendChild(t)}function B(){const e=O.createElement("div");e.classList.add(s);e.classList.add(l);const t=o.patch.cgl.canvas.parentElement;const n=O.createElement("div");n.classList.add("sidebar__group");e.appendChild(n);const a=O.createElement("div");a.classList.add("sidebar__group-header");e.appendChild(a);const i=O.createElement("span");i.classList.add("sidebar__group-header-title");h=O.createElement("span");h.classList.add("sidebar__group-header-title-text");h.innerHTML=b.get();i.appendChild(h);a.appendChild(i);M(a);y(a);n.appendChild(a);e.appendChild(n);n.addEventListener("click",L);if(!t){o.warn("[sidebar] no canvas parentelement found...");return}t.appendChild(e);const r=O.createElement("div");r.classList.add(u);e.appendChild(r);d=O.createElement("div");d.classList.add(m);d.addEventListener("click",L);e.appendChild(d);return e}b.onChange=function(){if(h)h.innerHTML=b.get()};function D(e){}function L(e){e.stopPropagation();if(!T){o.logError("Sidebar could not be closed...");return}T.classList.toggle("sidebar--closed");const t=e.target;let n=r;if(T.classList.contains("sidebar--closed")){n=c;I.set(false)}else{I.set(true)}}function w(){const e=O.querySelectorAll("."+a);if(e){e.forEach(e=>{e.parentNode.removeChild(e)})}if(!_.get())return;const t=O.createElement("style");t.innerHTML=n.style_css;t.classList.add(a);t.classList.add("cablesEle");O.body.appendChild(t)}function G(){U(T)}function U(e){if(e&&e.parentNode&&e.parentNode.removeChild)e.parentNode.removeChild(e)}};Ops.Sidebar.Sidebar.prototype=new CABLES.Op;CABLES.OPS["5a681c35-78ce-4cb3-9858-bc79c34c6819"]={f:Ops.Sidebar.Sidebar,objName:"Ops.Sidebar.Sidebar"};Ops.Sidebar.Button_v2=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=t.inObject("link");const a=t.inString("Text","Button");const i=t.outObject("childs");const r=t.outTrigger("Pressed Trigger");const o=t.inBool("Grey Out",false);const s=t.inBool("Visible",true);const l=document.createElement("div");l.dataset.op=t.id;l.classList.add("cablesEle");l.classList.add("sidebar__item");l.classList.add("sidebar--button");const u=document.createElement("div");u.classList.add("sidebar__button-input");l.appendChild(u);u.addEventListener("click",d);const m=document.createTextNode(a.get());u.appendChild(m);t.toWorkNeedsParent("Ops.Sidebar.Sidebar");n.onChange=f;a.onChange=h;t.onDelete=v;const c=document.createElement("div");c.classList.add("sidebar__greyout");l.appendChild(c);c.style.display="none";o.onChange=function(){c.style.display=o.get()?"block":"none"};s.onChange=function(){l.style.display=s.get()?"block":"none"};function d(){r.trigger()}function h(){const e=a.get();u.textContent=e;if(CABLES.UI){t.setUiAttrib({extendTitle:e})}}function f(){i.set(null);const e=n.get();if(e&&e.parentElement){e.parentElement.appendChild(l);i.set(e)}else{if(l.parentElement){l.parentElement.removeChild(l)}}}function p(e){if(e){e.style.display="block"}}function g(e){if(e){e.style.display="none"}}function v(){b(l)}function b(e){if(e&&e.parentNode&&e.parentNode.removeChild){e.parentNode.removeChild(e)}}};Ops.Sidebar.Button_v2.prototype=new CABLES.Op;CABLES.OPS["5e9c6933-0605-4bf7-8671-a016d917f327"]={f:Ops.Sidebar.Button_v2,objName:"Ops.Sidebar.Button_v2"};Ops.Gl.ExternalCanvas=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=t.inTrigger("Update"),a=t.outTrigger("Next"),i=t.inInt("Pos X",0),r=t.inInt("Pos Y",0),o=t.inInt("Width",800),s=t.inInt("Height",480),l=t.inBool("Smoothing",true),u=t.inBool("Stretch",false),m=t.inString("Title","cables"),c=t.inTriggerButton("Open Window"),d=t.outObject("Element",null,"element"),h=t.inTriggerButton("Close");let f=null;let p=null;let g=400,v=400;let b,x;let _=null;let O=0;let A=0;t.toWorkPortsNeedToBeLinked(n,a);t.setPortGroup("Size",[o,s]);t.setPortGroup("Position",[r,i]);h.onTriggered=S;t.onDelete=S;window.addEventListener("beforeunload",S,false);if(CABLES.UI)gui.on("resizecanvas",()=>{C();setTimeout(C,150)});u.onChange=C;r.onChange=i.onChange=T;s.onChange=o.onChange=I;function I(){if(_)_.resizeTo(o.get(),s.get());C()}function T(){if(!_)return;_.moveTo(i.get(),r.get())}m.onChange=()=>{if(_)_.document.title=m.get()};n.onTriggered=()=>{a.trigger();if(f&&p){f.style.top=A+"px";f.style.left=O+"px";p.clearRect(0,0,f.width,f.height);p.imageSmoothingEnabled=l.get();if(t.patch.cgCanvas)p.drawImage(t.patch.cgCanvas.canvasEle,0,0,f.width,f.height);else p.drawImage(t.patch.cgl.canvas,0,0,f.width,f.height)}};function S(){if(_)_.close();_=null;f=null;p=null}function C(e){if(!_)return;b=t.patch.cgl.canvasWidth;x=t.patch.cgl.canvasHeight;g=_.innerWidth;v=_.innerHeight;O=0;A=0;if(u.get()){f.width=g;f.height=v}else{if(g/v<b/x){f.width=g;f.height=f.width*(x/b);A=Math.abs(v-f.height)/2}else{f.height=v;f.width=f.height/(x/b);O=Math.abs(g-f.width)/2}}}function y(){if(!_)return;const e=_.document.body;if(e.requestFullScreen)e.requestFullScreen();else if(e.mozRequestFullScreen)e.mozRequestFullScreen();else if(e.webkitRequestFullScreen)e.webkitRequestFullScreen();else if(e.msRequestFullScreen)e.msRequestFullScreen();C()}c.onTriggered=()=>{if(_)S();let e=CABLES.uuid();_=window.open("","view#"+e,"width="+o.get()+",height="+s.get()+",directories=0,titlebar=0,toolbar=0,location=0,status=0,menubar=0,scrollbars=no,resizable=yes,popup=true");if(!_)return;let t=_.document;t.title=m.get();let n=t.body;n.style="padding:0px;margin:0px;background-color:#000;overflow:hidden;";f=t.createElement("canvas");f.style.position="absolute";f.width=g;f.height=v;n.appendChild(f);p=f.getContext("2d");d.setRef(n);C();T();_.addEventListener("resize",()=>{C()});_.addEventListener("beforeunload",S,false);f.addEventListener("dblclick",e=>{y()})}};Ops.Gl.ExternalCanvas.prototype=new CABLES.Op;CABLES.OPS["7fdeec7a-43df-4e0c-bde5-d398b2151930"]={f:Ops.Gl.ExternalCanvas,objName:"Ops.Gl.ExternalCanvas"};Ops.Sidebar.Toggle_v3=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=true;const a=t.inObject("link");const i=t.inString("Text","Toggle");const r=t.inValueBool("Input",n);const o=t.inTriggerButton("Set Default");const s=t.inValueBool("Default",n);s.setUiAttribs({hidePort:true,greyout:true});const l=t.inBool("Grey Out",false);const u=t.inBool("Visible",true);const m=t.outObject("childs");const c=t.outBoolNum("Value",s.get());const d=t.outTrigger("Toggled");const h=document.createElement("div");h.dataset.op=t.id;h.classList.add("cablesEle");h.classList.add("sidebar__item");h.classList.add("sidebar__toggle");h.classList.add("sidebar__reloadable");if(n)h.classList.add("sidebar__toggle--active");h.addEventListener("dblclick",function(){c.set(s.get());r.set(s.get());d.trigger()});const f=document.createElement("div");f.classList.add("sidebar__item-label");const p=document.createTextNode(i.get());f.appendChild(p);h.appendChild(f);const g=document.createElement("div");g.classList.add("icon_toggle");g.addEventListener("click",x);h.appendChild(g);const v=document.createElement("div");v.classList.add("sidebar__greyout");h.appendChild(v);v.style.display="none";a.onChange=A;i.onChange=O;r.onChange=_;t.onDelete=S;o.onTriggered=b;function b(){const e=r.get();s.set(e);c.set(e);d.trigger();t.refreshParams()}function x(){h.classList.toggle("sidebar__toggle--active");if(h.classList.contains("sidebar__toggle--active")){c.set(true);r.set(true);g.classList.add("icon_toggle_true");g.classList.remove("icon_toggle_false");d.trigger()}else{g.classList.remove("icon_toggle_true");g.classList.add("icon_toggle_false");c.set(false);r.set(false);d.trigger()}t.refreshParams()}function _(){const e=r.get();if(e){h.classList.add("sidebar__toggle--active");c.set(true)}else{h.classList.remove("sidebar__toggle--active");c.set(false)}d.trigger()}function O(){const e=i.get();f.textContent=e;if(CABLES.UI)t.setUiAttrib({extendTitle:e})}function A(){m.set(null);const e=a.get();if(e&&e.parentElement){e.parentElement.appendChild(h);m.set(e)}else if(h.parentElement)h.parentElement.removeChild(h)}function I(e){if(e)e.style.display="block"}function T(e){if(e)e.style.display="none"}function S(){C(h)}function C(e){if(e&&e.parentNode&&e.parentNode.removeChild)e.parentNode.removeChild(h)}l.onChange=function(){v.style.display=l.get()?"block":"none"};u.onChange=function(){h.style.display=u.get()?"block":"none"}};Ops.Sidebar.Toggle_v3.prototype=new CABLES.Op;CABLES.OPS["fb60ab7d-f2f2-4fc5-bcd0-88c6ed481908"]={f:Ops.Sidebar.Toggle_v3,objName:"Ops.Sidebar.Toggle_v3"};Ops.Gl.ImageCompose.ImageCompose_v4=function(){CABLES.Op.apply(this,arguments);const n=this;const e=n.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=n.patch.cgl,a=n.inTrigger("Render"),i=n.inTexture("Base Texture"),r=n.inTexture("UV Texture"),o=n.inSwitch("Size",["Auto","Canvas","Manual"],"Auto"),s=n.inValueInt("Width",640),l=n.inValueInt("Height",480),u=n.inSwitch("Filter",["nearest","linear","mipmap"],"linear"),m=n.inValueSelect("Wrap",["clamp to edge","repeat","mirrored repeat"],"repeat"),c=n.inSwitch("Anisotropic",["0","1","2","4","8","16"],"0"),d=n.inDropDown("Pixel Format",CGL.Texture.PIXELFORMATS,CGL.Texture.PFORMATSTR_RGBA8UB),h=n.inBool("Clear",true),f=n.inValueSlider("R",0),p=n.inValueSlider("G",0),g=n.inValueSlider("B",0),v=n.inValueSlider("A",0),b=n.outTrigger("Next"),x=n.outTexture("texture_out",CGL.Texture.getEmptyTexture(t)),_=n.outNumber("Aspect Ratio"),R=n.outNumber("Texture Width"),k=n.outNumber("Texture Height");n.setPortGroup("Texture Size",[o,s,l]);n.setPortGroup("Texture Parameters",[m,c,u,d]);f.setUiAttribs({colorPick:true});n.setPortGroup("Color",[f,p,g,v,h]);n.toWorkPortsNeedToBeLinked(a);const B=[0,0,0,0];let O=null;let A=null;let I=true;let D=false;let T=null;let G=null;let U=null;let F=null;m.onChange=u.onChange=c.onChange=d.onChange=V;i.onLinkChanged=h.onChange=o.onChange=r.onChange=j;a.onTriggered=n.preRender=w;j();function S(){if(O)O.delete();if(A)A.delete();A=null;O=new CGL.TextureEffect(t,{isFloatingPointTexture:CGL.Texture.isPixelFormatFloat(d.get()),name:n.name});const e=Math.min(t.maxAnisotropic,parseFloat(c.get()));A=new CGL.Texture(t,{anisotropic:e,name:"image_compose_v2_"+n.id,pixelFormat:d.get(),filter:C(),wrap:y(),width:E(),height:M()});O.setSourceTexture(A);R.set(E());k.set(M());_.set(E()/M());x.set(CGL.Texture.getEmptyTexture(t));I=false;j()}function C(){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 y(){if(m.get()=="repeat")return CGL.Texture.WRAP_REPEAT;else if(m.get()=="mirrored repeat")return CGL.Texture.WRAP_MIRRORED_REPEAT;else if(m.get()=="clamp to edge")return CGL.Texture.WRAP_CLAMP_TO_EDGE}function E(){let e=0;if(i.get()&&o.get()=="Auto")e=i.get().width;else if(o.get()=="Auto"||o.get()=="Canvas")e=t.canvasWidth;else if(o.get()=="ViewPort")e=t.getViewPort()[2];else e=Math.ceil(s.get());return n.patch.cgl.checkTextureSize(e)}function M(){let e=0;if(i.get()&&o.get()=="Auto")e=i.get().height;else if(o.get()=="Auto"||o.get()=="Canvas")e=t.canvasHeight;else if(o.get()=="ViewPort")e=t.getViewPort()[3];else e=Math.ceil(l.get());return n.patch.cgl.checkTextureSize(e)}function V(){I=true}function z(){if((E()!=A.width||M()!=A.height||A.pixelFormat!=d.get()||A.filter!=C()||A.wrap!=y())&&(E()!==0&&M()!==0)){S();O.setSourceTexture(A);x.set(CGL.Texture.getEmptyTexture(t));x.set(A);P();L()}}function P(){let e=null;if(o.get()=="Manual"){e=null}else if(o.get()=="Auto"){if(i.get())e="Input Texture";else e="Canvas Size";e+=": "+E()+" x "+M()}let t=false;t=o.uiAttribs.info!=e;o.setUiAttribs({info:e});if(t)n.refreshParams()}function N(){if(T)T.toggleDefine("USE_TEX",i.isLinked()||!h.get());if(T)T.toggleDefine("USE_UVTEX",r.isLinked())}function j(){c.setUiAttribs({greyout:C()!=CGL.Texture.FILTER_MIPMAP});f.setUiAttribs({greyout:i.isLinked()});g.setUiAttribs({greyout:i.isLinked()});p.setUiAttribs({greyout:i.isLinked()});v.setUiAttribs({greyout:i.isLinked()});h.setUiAttribs({greyout:i.isLinked()});s.setUiAttribs({greyout:o.get()!="Manual"});l.setUiAttribs({greyout:o.get()!="Manual"});if(A)if(CGL.Texture.isPixelFormatFloat(d.get())&&C()==CGL.Texture.FILTER_MIPMAP)n.setUiError("fpmipmap","Don't use mipmap and 32bit at the same time, many systems do not support this.");else n.setUiError("fpmipmap",null);P();N();L()}function L(){if(A)if(i.isLinked()&&i.get()&&A.isFloatingPoint()!=i.get().isFloatingPoint())n.setUiError("textypediff","Warning: Mixing floating point and non floating point texture can result in data/precision loss",1);else n.setUiError("textypediff",null)}n.preRender=()=>{w()};function X(){if(!T){T=new CGL.Shader(t,"copytextureshader");T.setSource(T.getDefaultVertexShader(),e.imgcomp_frag);G=new CGL.Uniform(T,"t","tex",0);U=new CGL.Uniform(T,"t","UVTex",1);F=new CGL.Uniform(T,"4f","bgColor",f,p,g,v);N()}t.pushShader(T);t.currentTextureEffect.bind();if(i.get())t.setTexture(0,i.get().tex);else if(!h.get()&&x.get())t.setTexture(0,x.get().tex);if(r.get())t.setTexture(1,r.get().tex);t.currentTextureEffect.finish();t.popShader()}function w(){if(!O||I)S();t.pushBlend(false);z();const e=t.currentTextureEffect;t.currentTextureEffect=O;t.currentTextureEffect.imgCompVer=3;t.currentTextureEffect.width=s.get();t.currentTextureEffect.height=l.get();O.setSourceTexture(A);O.startEffect(i.get()||CGL.Texture.getEmptyTexture(t,D),true);X();b.trigger();t.pushViewPort(0,0,s.get(),l.get());O.endEffect();x.setRef(O.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.Vars.VarSetTexture_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTexture("Value",null);e.varName=e.inDropDown("Variable",[],"",true);new CABLES.VarSetOpWrapper(e,"object",n,e.varName)};Ops.Vars.VarSetTexture_v2.prototype=new CABLES.Op;CABLES.OPS["4fbfc71e-1429-439f-8591-ad35961252ed"]={f:Ops.Vars.VarSetTexture_v2,objName:"Ops.Vars.VarSetTexture_v2"};Ops.Gl.ImageCompose.MultiDrawImage=function(){CABLES.Op.apply(this,arguments);const n=this;const t=n.attachments={invert_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D tex1;\nUNI sampler2D tex2;\nUNI sampler2D tex3;\nUNI sampler2D tex4;\nUNI sampler2D tex5;\nUNI sampler2D tex6;\nUNI sampler2D tex7;\nUNI sampler2D tex8;\n\n\nUNI sampler2D texMask1;\nUNI sampler2D texMask2;\nUNI sampler2D texMask3;\nUNI sampler2D texMask4;\nUNI sampler2D texMask5;\nUNI sampler2D texMask6;\nUNI sampler2D texMask7;\nUNI sampler2D texMask8;\n\nUNI float amount1;\nUNI float amount2;\nUNI float amount3;\nUNI float amount4;\nUNI float amount5;\nUNI float amount6;\nUNI float amount7;\nUNI float amount8;\n\n{{BLENDCODE}}\n\nvoid main()\n{\n    vec4 col=texture(tex,texCoord);\n\n\n    #ifdef USE_TEX_1\n        vec4 col1=texture(tex1,texCoord);\n        col=cgl_blend1(col,col1,amount1);\n    #endif\n    #ifdef USE_TEX_2\n        vec4 col2=texture(tex2,texCoord);\n        col=cgl_blend2(col,col2,amount2);\n    #endif\n    #ifdef USE_TEX_3\n        vec4 col3=texture(tex3,texCoord);\n        col=cgl_blend3(col,col3,amount3);\n    #endif\n    #ifdef USE_TEX_4\n        vec4 col4=texture(tex4,texCoord);\n        col=cgl_blend4(col,col4,amount4);\n    #endif\n    #ifdef USE_TEX_5\n        vec4 col5=texture(tex5,texCoord);\n        col=cgl_blend5(col,col5,amount5);\n    #endif\n    #ifdef USE_TEX_6\n        vec4 col6=texture(tex6,texCoord);\n        col=cgl_blend6(col,col6,amount6);\n    #endif\n    #ifdef USE_TEX_7\n        vec4 col7=texture(tex7,texCoord);\n        col=cgl_blend7(col,col7,amount7);\n    #endif\n    #ifdef USE_TEX_8\n        vec4 col8=texture(tex8,texCoord);\n        col=cgl_blend8(col,col8,amount8);\n    #endif\n\n    outColor=col;\n\n}\n"};const a=["normal","lighten","darken","multiply","multiply invert","average","add","substract","difference","negation","exclusion","overlay","screen","color dodge","color burn","softlight","hardlight"];const e=n.inTrigger("render"),i=n.inBool("Mask Invert",false),r=n.outTrigger("trigger");const o=8,s=n.patch.cgl,l=new CGL.Shader(s,n.name),u=[],m=[],c=[],d=[],h=[],f=[];let p=true;for(let e=0;e<o;e++){const x=n.inTexture("Texture "+(e+1));const _=n.inDropDown("Blendmode "+(e+1),a,"normal");const O=n.inTexture("Mask "+(e+1));const A=n.inSwitch("Mask Source "+(e+1),["R","R inv","A","A inv"],"R");const I=n.inSwitch("Opacity "+(e+1),["Normal","Prev A","Prev R"],"Normal");const T=n.inValueSlider("Amount "+(e+1),1);_.onChange=I.onChange=A.onChange=O.onLinkChanged=x.onLinkChanged=()=>{p=true};f.push(x);d.push(O);c.push(I);m.push(_);u.push(T);h.push(A);n.setPortGroup("Image "+(e+1),[x,_,T,I,O,A]);new CGL.Uniform(l,"t","tex"+(e+1),e*2+1);new CGL.Uniform(l,"t","texMask"+(e+1),e*2+2);new CGL.Uniform(l,"f","amount"+(e+1),T)}const g=new CGL.Uniform(l,"t","tex",0);function v(){let n="";let a="";for(let t=0;t<o;t++){let e=f[t].isLinked();u[t].setUiAttribs({greyout:!e});m[t].setUiAttribs({greyout:!e});c[t].setUiAttribs({greyout:!e});if(e){n+="#define USE_TEX_"+(t+1)+"".endl();a+=b(t+1,m[t].get(),c[t].get(),d[t].get(),h[t].get())}}let e=n.endl()+t.invert_frag;e=e.replace("{{BLENDCODE}}",a);l.setSource(l.getDefaultVertexShader(),e);p=false}function b(e,t,n,a,i){let r=""+"vec3 _blend"+e+"(vec3 base,vec3 blend)".endl()+"{".endl()+"   vec3 colNew=blend;".endl();if(t=="multiply")r+="       colNew=base*blend;".endl();else if(t=="multiply invert")r+="       colNew=base* vec3(1.0)-blend;".endl();else if(t=="average")r+="       colNew=((base + blend) / 2.0);".endl();else if(t=="add")r+="       colNew=min(base + blend, vec3(1.0));".endl();else if(t=="substract")r+="       colNew=max(base + blend - vec3(1.0), vec3(0.0));".endl();else if(t=="difference")r+="       colNew=abs(base - blend);".endl();else if(t=="negation")r+="       colNew=(vec3(1.0) - abs(vec3(1.0) - base - blend));".endl();else if(t=="exclusion")r+="       colNew=(base + blend - 2.0 * base * blend);".endl();else if(t=="lighten")r+="       colNew=max(blend, base);".endl();else if(t=="darken")r+="       colNew=min(blend, base);".endl();else if(t=="overlay"){r+=""+"      #define BlendOverlayf(base, blend)  (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))".endl()+"      colNew=vec3(BlendOverlayf(base.r, blend.r),BlendOverlayf(base.g, blend.g),BlendOverlayf(base.b, blend.b));".endl()}else if(t=="screen"){r+=""+"      #define BlendScreenf(base, blend)       (1.0 - ((1.0 - base) * (1.0 - blend)))".endl()+"      colNew=vec3(BlendScreenf(base.r, blend.r),BlendScreenf(base.g, blend.g),BlendScreenf(base.b, blend.b));".endl()}else if(t=="softlight"){r+=""+"      #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()+"      colNew=vec3(BlendSoftLightf(base.r, blend.r),BlendSoftLightf(base.g, blend.g),BlendSoftLightf(base.b, blend.b));".endl()}else if(t=="hardlight"){r+=""+"      #define BlendOverlayf(base, blend)  (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))".endl()+"      colNew=vec3(BlendOverlayf(base.r, blend.r),BlendOverlayf(base.g, blend.g),BlendOverlayf(base.b, blend.b));".endl()}else if(t=="color dodge"){r+=""+"      #define BlendColorDodgef(base, blend)   ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0))".endl()+"      colNew=vec3(BlendColorDodgef(base.r, blend.r),BlendColorDodgef(base.g, blend.g),BlendColorDodgef(base.b, blend.b));".endl()}else if(t=="color burn"){r+=""+"      #define BlendColorBurnf(base, blend)    ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0))".endl()+"      colNew=vec3(BlendColorBurnf(base.r, blend.r),BlendColorBurnf(base.g, blend.g),BlendColorBurnf(base.b, blend.b));".endl()}r+=""+"   return colNew;".endl()+"}".endl()+"vec4 cgl_blend"+e+"(vec4 oldColor,vec4 newColor,float amount)".endl()+"{".endl()+"float a=(amount*newColor.a);".endl();if(n==="Prev A")r+="a*=oldColor.a;";if(n==="Prev R")r+="a*=oldColor.r;";r=r+"vec4 col = vec4( _blend"+e+"(oldColor.rgb, newColor.rgb), 1.0);".endl()+"col = vec4( mix( col.rgb,oldColor.rgb, col.a * 1.0-amount), 1.0);".endl();if(a)if(i==="R")r=r+"newColor.a *= texture(texMask"+e+",texCoord).r;".endl();else if(i==="R inv")r=r+"newColor.a *= 1.0-texture(texMask"+e+",texCoord).r;".endl();else if(i==="A")r=r+"newColor.a *= texture(texMask"+e+",texCoord).a;".endl();else if(i==="A inv")r=r+"newColor.a *= 1.0-texture(texMask"+e+",texCoord).a;".endl();r=r+"col = vec4( mix( oldColor,col, newColor.a));".endl()+"return col;".endl()+"}".endl().endl();return r}e.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(n))return;if(p)v();s.pushShader(l);s.currentTextureEffect.bind();s.setTexture(0,s.currentTextureEffect.getCurrentSourceTexture().tex);let t=1;for(let e=0;e<f.length;e++){if(f[e].get()){s.setTexture(e*2+1,f[e].get().tex);t++}if(d[e].get()){s.setTexture(e*2+2,d[e].get().tex);t++}}if(t>s.maxTextureUnits)n.setUiError("manytex","Too many textures bound");else n.setUiError("manytex",null);s.pushBlendMode(CGL.BLEND_NONE,true);s.currentTextureEffect.finish();s.popBlendMode();s.popShader();r.trigger()}};Ops.Gl.ImageCompose.MultiDrawImage.prototype=new CABLES.Op;CABLES.OPS["4df51ead-c46c-471d-ac5e-1872219a3174"]={f:Ops.Gl.ImageCompose.MultiDrawImage,objName:"Ops.Gl.ImageCompose.MultiDrawImage"};Ops.Gl.RenderToTexture_v3=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={};const t=i.inTrigger("render"),n=i.inSwitch("Size",["Canvas","Manual"],"Canvas"),a=i.inValueInt("texture width",512),r=i.inValueInt("texture height",512),o=i.inBool("Auto Aspect",true),s=i.inSwitch("filter",["nearest","linear","mipmap"],"linear"),l=i.inSwitch("Wrap",["Clamp","Repeat","Mirror"],"Repeat"),u=i.inSwitch("MSAA",["none","2x","4x","8x"],"none"),m=i.outTrigger("trigger"),c=i.outTexture("texture"),d=i.outTexture("textureDepth"),h=i.inDropDown("Pixel Format",CGL.Texture.PIXELFORMATS,CGL.Texture.PFORMATSTR_RGBA8UB),f=i.inValueBool("Depth",true),p=i.inValueBool("Clear",true);const g=i.patch.cgl;let v=null;let b=true;i.setPortGroup("Size",[n,a,r,o]);h.onChange=f.onChange=p.onChange=s.onChange=l.onChange=u.onChange=_;n.onChange=x;t.onTriggered=i.preRender=O;x();function x(){a.setUiAttribs({greyout:n.get()!="Manual"});r.setUiAttribs({greyout:n.get()!="Manual"});o.setUiAttribs({greyout:n.get()!="Manual"})}function _(){b=true}function O(){CGL.TextureEffect.checkOpNotInTextureEffect(i);if(!v||b){if(v)v.delete();let n=CGL.Texture.WRAP_REPEAT;if(l.get()=="Clamp")n=CGL.Texture.WRAP_CLAMP_TO_EDGE;else if(l.get()=="Mirror")n=CGL.Texture.WRAP_MIRRORED_REPEAT;let a=CGL.Texture.FILTER_NEAREST;if(s.get()=="nearest")a=CGL.Texture.FILTER_NEAREST;else if(s.get()=="linear")a=CGL.Texture.FILTER_LINEAR;else if(s.get()=="mipmap")a=CGL.Texture.FILTER_MIPMAP;if(h.get().indexOf("loat")&&s.get()=="mipmap")i.setUiError("fpmipmap","Can't use mipmap and float texture at the same time");else i.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 "+i.id,pixelFormat:h.get(),multisampling:e,multisamplingSamples:t,wrap:n,filter:a,depth:f.get(),clear:p.get()})}else{v=new CGL.Framebuffer(g,8,8,{isFloatingPointTexture:false,clear:p.get()})}if(v&&v.valid){d.set(v.getTextureDepth());b=false}else{v=null;b=true}}let e=o.get();if(n.get()=="Canvas"){e=true;a.set(i.patch.cgl.checkTextureSize(g.canvasWidth));r.set(i.patch.cgl.checkTextureSize(g.canvasHeight))}if(v.getWidth()!=i.patch.cgl.checkTextureSize(a.get())||v.getHeight()!=i.patch.cgl.checkTextureSize(r.get())){v.setSize(i.patch.cgl.checkTextureSize(a.get()),i.patch.cgl.checkTextureSize(r.get()))}v.renderStart(g);g.pushViewPort(0,0,a.get(),r.get());if(e)mat4.perspective(g.pMatrix,45,a.get()/r.get(),.1,1e3);m.trigger();v.renderEnd(g);g.popViewPort();d.setRef(v.getTextureDepth());c.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.Ui.VizGraph=function(){CABLES.Op.apply(this,arguments);const m=this;const e=m.attachments={};const t=m.inFloat("Number 1"),n=m.inFloat("Number 2"),a=m.inFloat("Number 3"),i=m.inFloat("Number 4"),r=m.inFloat("Number 5"),o=m.inFloat("Number 6"),s=m.inFloat("Number 7"),l=m.inFloat("Number 8"),c=m.inBool("Fill Graph",true),u=m.inTriggerButton("Reset");m.setUiAttrib({height:150,resizable:true,vizLayerMaxZoom:2500});let d=[];let h=-Number.MAX_VALUE;let f=Number.MAX_VALUE;t.onLinkChanged=n.onLinkChanged=a.onLinkChanged=i.onLinkChanged=r.onLinkChanged=o.onLinkChanged=s.onLinkChanged=l.onLinkChanged=u.onTriggered=()=>{h=-Number.MAX_VALUE;f=Number.MAX_VALUE;d=[]};m.renderVizLayer=(a,i)=>{const e=CABLES.UI.uiProfiler.start("previewlayer graph");const r=c.get();const o=["#7AC4E0","#D183BF","#9091D6","#FFC395","#F0D165","#63A8E8","#CF5D9D","#66C984","#D66AA6","#515151"];let t=10*i.pixelDensity;a.font="bold "+t+"px sourceCodePro";a.fillStyle="#222";a.fillRect(i.x,i.y,i.width,i.height);for(let n=0;n<m.portsIn.length;n++){if(!m.portsIn[n].isLinked())continue;const s=m.portsIn[n].get();h=Math.max(m.portsIn[n].get(),h);f=Math.min(m.portsIn[n].get(),f);if(!d[n])d[n]=[];d[n].push(s);if(d[n].length>60)d[n].shift();const l=6;const u=i.width/60;a.lineWidth=3;a.strokeStyle="#555555";a.beginPath();a.moveTo(i.x,CABLES.map(0,f,h,i.height,0)+i.y);a.lineTo(i.x+i.width,CABLES.map(0,f,h,i.height,0)+i.y);a.stroke();a.beginPath();let t;for(let e=0;e<d[n].length;e++){t=d[n][e];t=CABLES.map(t,f,h,i.height-3,3);t+=i.y;if(e===0)a.moveTo(i.x,t);else a.lineTo(i.x+e*u,t)}if(r){a.lineTo(i.x+d[n].length*u,i.y+i.height);a.lineTo(i.x,i.y+i.height);a.fillStyle=o[n];a.fill()}else{a.strokeStyle=o[n];a.stroke()}}a.fillStyle="#fff";a.fillText("max:"+Math.round(h*100)/100,i.x+10,i.y+i.height-10);a.fillText("min:"+Math.round(f*100)/100,i.x+10,i.y+i.height-30);e.finish()}};Ops.Ui.VizGraph.prototype=new CABLES.Op;CABLES.OPS["13c54eb4-60ef-4b9c-8425-d52a431f5c87"]={f:Ops.Ui.VizGraph,objName:"Ops.Ui.VizGraph"};Ops.Gl.TextureArrayLoader_v2=function(){CABLES.Op.apply(this,arguments);const l=this;const e=l.attachments={};const t=false;const u=l.inString("Url");const m=l.inBool("Left Pad",t);const c=l.inInt("Num Digits",3);c.setUiAttribs({hidePort:!t,greyout:!t});const d=l.inInt("Index Start");const n=l.inInt("Index End");const a=l.inValueSelect("filter",["nearest","linear","mipmap"]);const i=l.inValueSelect("wrap",["repeat","mirrored repeat","clamp to edge"],"clamp to edge");const h=l.inBool("Flip",false);const f=l.inBool("unpackPreMultipliedAlpha",false);const p=l.outArray("TextureArray");const g=l.outNumber("Width");const v=l.outNumber("Height");const b=l.outBool("Loading");const x=l.outNumber("Aspect Ratio");n.set(10);h.set(false);f.set(false);const _=l.patch.cgl;let O=0;let A=0;const I=[];p.set(I);h.onChange=function(){s()};u.onChange=s;a.onChange=M;i.onChange=P;f.onChange=function(){s()};m.onChange=o;let r=0;function o(){const e=m.get();c.setUiAttribs({hidePort:!e,greyout:!e})}const T=function(){const e=CGL.Texture.getTempTexture(_)};function s(e){clearTimeout(r);r=setTimeout(function(){E(e)},30)}const S="X";function C(e,t){return e.toString().length<t?C("0"+e,t):e}function y(t,e){let n=u.get();if(!n)return;const a=n.indexOf(S);const i=n.lastIndexOf(S);if(a===-1){return}const r=n.substring(a,i+1);let o=t;if(m.get()){o=C(t,c.get())}n=n.replace(r,o);n=l.patch.getFilePath(n);if(e)n+="?rnd="+CABLES.generateUUID();if(u.get()&&u.get().length>1){b.set(1);var s=CGL.Texture.load(_,n,function(e){if(e){console.warn("error loading texture",n,e);T();return}g.set(s.width);v.set(s.height);x.set(s.width/s.height);I[t-parseInt(d.get())]=s;p.setRef(I)},{wrap:A,flip:h.get(),unpackAlpha:f.get(),filter:O});b.set(0)}else{T()}}function E(e){for(var t=0;t<I.length;t++){if(I[t]){I[t].delete()}}I.length=0;for(var t=Math.floor(d.get());t<=Math.floor(n.get());t++){y(t,e)}}function M(){if(a.get()=="nearest")O=CGL.Texture.FILTER_NEAREST;if(a.get()=="linear")O=CGL.Texture.FILTER_LINEAR;if(a.get()=="mipmap")O=CGL.Texture.FILTER_MIPMAP;s()}function P(){if(i.get()=="repeat")A=CGL.Texture.WRAP_REPEAT;if(i.get()=="mirrored repeat")A=CGL.Texture.WRAP_MIRRORED_REPEAT;if(i.get()=="clamp to edge")A=CGL.Texture.WRAP_CLAMP_TO_EDGE;s()}l.onFileChanged=function(e){};a.set("linear");i.set("repeat")};Ops.Gl.TextureArrayLoader_v2.prototype=new CABLES.Op;CABLES.OPS["4bbb57ce-3c7b-49c1-84fd-2b6a27ff3afa"]={f:Ops.Gl.TextureArrayLoader_v2,objName:"Ops.Gl.TextureArrayLoader_v2"};Ops.Array.ArrayGetTexture=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inArray("array"),a=e.inValueInt("index"),i=e.outTexture("value");let r=null;n.ignoreValueSerialize=true;i.ignoreValueSerialize=true;a.onChange=n.onChange=s;e.toWorkPortsNeedToBeLinked(n,i);const o=CGL.Texture.getEmptyTexture(e.patch.cgl);function s(){const e=n.get();let t=a.get();if(t<0||!e||t>=e.length){i.set(o);return}if(e[t]){i.set(e[t]||o);r=e[t]}else i.set(o)}};Ops.Array.ArrayGetTexture.prototype=new CABLES.Op;CABLES.OPS["afea522b-ab72-4574-b721-5d37f5abaf77"]={f:Ops.Array.ArrayGetTexture,objName:"Ops.Array.ArrayGetTexture"};Ops.Math.Multiply=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValueFloat("number1",1),a=e.inValueFloat("number2",1),i=e.outNumber("result");e.setUiAttribs({mathTitle:true});n.onChange=a.onChange=r;r();function r(){const e=n.get();const t=a.get();i.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.Math.Modulo=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValueFloat("number1",1),a=e.inValueFloat("number2",2),i=e.inValueBool("pingpong"),r=e.outNumber("result");let o=l;n.onChange=a.onChange=s;i.onChange=m;s();function s(){let e=a.get();let t=n.get();r.set(o(t,e))}function l(e,t){let n=(e%t+t)%t;if(n!=n)n=0;return n}function u(e,t){let n=2*t;e%=n;if(e>=t)return n-e;else return e}function m(){if(i.get())o=u;else o=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.ArrayLength_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inArray("array"),a=e.outNumber("length");a.ignoreValueSerialize=true;function i(){let e=0;if(n.get())e=n.get().length;a.set(e)}n.onChange=i};Ops.Array.ArrayLength_v2.prototype=new CABLES.Op;CABLES.OPS["6f665caa-96ed-45d8-8620-e34f0f8e062c"]={f:Ops.Array.ArrayLength_v2,objName:"Ops.Array.ArrayLength_v2"};Ops.Math.Floor=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValue("Number");const a=e.outNumber("Result");n.onChange=i;function i(){a.set(Math.floor(n.get()))}};Ops.Math.Floor.prototype=new CABLES.Op;CABLES.OPS["0c77617c-b688-4b55-addf-2cbcaabf98af"]={f:Ops.Math.Floor,objName:"Ops.Math.Floor"};Ops.Gl.GLTF.GltfScene_v4=function(){CABLES.Op.apply(this,arguments);const O=this;const l=O.attachments={inc_camera_js:"const gltfCamera = class\n{\n    constructor(gltf, node)\n    {\n        this.node = node;\n        this.name = node.name;\n        // console.log(gltf);\n        this.config = gltf.json.cameras[node.camera];\n\n        this.pos = vec3.create();\n        this.quat = quat.create();\n        this.vCenter = vec3.create();\n        this.vUp = vec3.create();\n        this.vMat = mat4.create();\n    }\n\n    updateAnim(time)\n    {\n        if (this.node && this.node._animTrans)\n        {\n            vec3.set(this.pos,\n                this.node._animTrans[0].getValue(time),\n                this.node._animTrans[1].getValue(time),\n                this.node._animTrans[2].getValue(time));\n\n            quat.set(this.quat,\n                this.node._animRot[0].getValue(time),\n                this.node._animRot[1].getValue(time),\n                this.node._animRot[2].getValue(time),\n                this.node._animRot[3].getValue(time));\n        }\n    }\n\n    start(time)\n    {\n        if (cgl.frameStore.shadowPass) return;\n\n        this.updateAnim(time);\n        const asp = cgl.getViewPort()[2] / cgl.getViewPort()[3];\n\n        cgl.pushPMatrix();\n        // mat4.perspective(\n        //     cgl.pMatrix,\n        //     this.config.perspective.yfov*0.5,\n        //     asp,\n        //     this.config.perspective.znear,\n        //     this.config.perspective.zfar);\n\n        cgl.pushViewMatrix();\n        // mat4.identity(cgl.vMatrix);\n\n        // if(this.node && this.node.parent)\n        // {\n        //     console.log(this.node.parent)\n        // vec3.add(this.pos,this.pos,this.node.parent._node.translation);\n        // vec3.sub(this.vCenter,this.vCenter,this.node.parent._node.translation);\n        // mat4.translate(cgl.vMatrix,cgl.vMatrix,\n        // [\n        //     -this.node.parent._node.translation[0],\n        //     -this.node.parent._node.translation[1],\n        //     -this.node.parent._node.translation[2]\n        // ])\n        // }\n\n        // vec3.set(this.vUp, 0, 1, 0);\n        // vec3.set(this.vCenter, 0, -1, 0);\n        // // vec3.set(this.vCenter, 0, 1, 0);\n        // vec3.transformQuat(this.vCenter, this.vCenter, this.quat);\n        // vec3.normalize(this.vCenter, this.vCenter);\n        // vec3.add(this.vCenter, this.vCenter, this.pos);\n\n        // mat4.lookAt(cgl.vMatrix, this.pos, this.vCenter, this.vUp);\n\n        let mv = mat4.create();\n        mat4.invert(mv, this.node.modelMatAbs());\n\n        // console.log(this.node.modelMatAbs());\n\n        this.vMat = mv;\n\n        mat4.identity(cgl.vMatrix);\n        // console.log(mv);\n        mat4.mul(cgl.vMatrix, cgl.vMatrix, mv);\n    }\n\n    end()\n    {\n        if (cgl.frameStore.shadowPass) return;\n        cgl.popPMatrix();\n        cgl.popViewMatrix();\n    }\n};\n",inc_gltf_js:'const le = true; // little endian\n\nconst Gltf = class\n{\n    constructor()\n    {\n        this.json = {};\n        this.accBuffers = [];\n        this.meshes = [];\n        this.nodes = [];\n        this.shaders = [];\n        this.timing = [];\n        this.cams = [];\n        this.startTime = performance.now();\n        this.bounds = new CABLES.CG.BoundingBox();\n        this.loaded = Date.now();\n        this.accBuffersDelete = [];\n    }\n\n    getNode(n)\n    {\n        for (let i = 0; i < this.nodes.length; i++)\n        {\n            if (this.nodes[i].name == n) return this.nodes[i];\n        }\n    }\n\n    unHideAll()\n    {\n        for (let i = 0; i < this.nodes.length; i++)\n        {\n            this.nodes[i].unHide();\n        }\n    }\n};\n\nfunction Utf8ArrayToStr(array)\n{\n    if (window.TextDecoder) return new TextDecoder("utf-8").decode(array);\n\n    let out, i, len, c;\n    let char2, char3;\n\n    out = "";\n    len = array.length;\n    i = 0;\n    while (i < len)\n    {\n        c = array[i++];\n        switch (c >> 4)\n        {\n        case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:\n            // 0xxxxxxx\n            out += String.fromCharCode(c);\n            break;\n        case 12: case 13:\n            // 110x xxxx   10xx xxxx\n            char2 = array[i++];\n            out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));\n            break;\n        case 14:\n            // 1110 xxxx  10xx xxxx  10xx xxxx\n            char2 = array[i++];\n            char3 = array[i++];\n            out += String.fromCharCode(((c & 0x0F) << 12) |\n                    ((char2 & 0x3F) << 6) |\n                    ((char3 & 0x3F) << 0));\n            break;\n        }\n    }\n\n    return out;\n}\n\nfunction readChunk(dv, bArr, arrayBuffer, offset)\n{\n    const chunk = {};\n\n    if (offset >= dv.byteLength)\n    {\n        // op.log("could not read chunk...");\n        return;\n    }\n    chunk.size = dv.getUint32(offset + 0, le);\n\n    // chunk.type = new TextDecoder("utf-8").decode(bArr.subarray(offset+4, offset+4+4));\n    chunk.type = Utf8ArrayToStr(bArr.subarray(offset + 4, offset + 4 + 4));\n\n    if (chunk.type == "BIN\\0")\n    {\n        // console.log(chunk.size,arrayBuffer.length,offset);\n        // try\n        // {\n        chunk.dataView = new DataView(arrayBuffer, offset + 8, chunk.size);\n        // }\n        // catch(e)\n        // {\n        //     chunk.dataView = null;\n        //     console.log(e);\n        // }\n    }\n    else\n    if (chunk.type == "JSON")\n    {\n        const json = Utf8ArrayToStr(bArr.subarray(offset + 8, offset + 8 + chunk.size));\n\n        try\n        {\n            const obj = JSON.parse(json);\n            chunk.data = obj;\n            outGenerator.set(obj.asset.generator);\n        }\n        catch (e)\n        {\n        }\n    }\n    else\n    {\n        op.warn("unknown type", chunk.type);\n    }\n\n    return chunk;\n}\n\nfunction loadAnims(gltf)\n{\n    const uniqueAnimNames = {};\n\n    for (let i = 0; i < gltf.json.animations.length; i++)\n    {\n        const an = gltf.json.animations[i];\n\n        an.name = an.name || "unknown";\n\n        for (let ia = 0; ia < an.channels.length; ia++)\n        {\n            const chan = an.channels[ia];\n\n            const node = gltf.nodes[chan.target.node];\n            const sampler = an.samplers[chan.sampler];\n\n            const acc = gltf.json.accessors[sampler.input];\n            const bufferIn = gltf.accBuffers[sampler.input];\n\n            const accOut = gltf.json.accessors[sampler.output];\n            const bufferOut = gltf.accBuffers[sampler.output];\n\n            gltf.accBuffersDelete.push(sampler.output, sampler.input);\n\n            if (bufferIn && bufferOut)\n            {\n                let numComps = 1;\n                if (accOut.type === "VEC2")numComps = 2;\n                else if (accOut.type === "VEC3")numComps = 3;\n                else if (accOut.type === "VEC4")numComps = 4;\n                else if (accOut.type === "SCALAR")\n                {\n                    numComps = bufferOut.length / bufferIn.length; // is this really the way to find out ? cant find any other way,except number of morph targets, but not really connected...\n                }\n                else op.log("[] UNKNOWN accOut.type", accOut.type);\n\n                const anims = [];\n\n                uniqueAnimNames[an.name] = true;\n\n                for (let k = 0; k < numComps; k++)\n                {\n                    const newAnim = new CABLES.Anim();\n                    // newAnim.name=an.name;\n                    anims.push(newAnim);\n                }\n\n                if (sampler.interpolation === "LINEAR") {}\n                else if (sampler.interpolation === "STEP") for (let k = 0; k < numComps; k++) anims[k].defaultEasing = CABLES.EASING_ABSOLUTE;\n                else if (sampler.interpolation === "CUBICSPLINE") for (let k = 0; k < numComps; k++) anims[k].defaultEasing = CABLES.EASING_CUBICSPLINE;\n                else op.warn("unknown interpolation", sampler.interpolation);\n\n                // console.log(bufferOut)\n\n                // if there is no keyframe for time 0 copy value of first keyframe at time 0\n                if (bufferIn[0] !== 0.0)\n                    for (let k = 0; k < numComps; k++)\n                        anims[k].setValue(0, bufferOut[0 * numComps + k]);\n\n                for (let j = 0; j < bufferIn.length; j++)\n                {\n                    maxTime = Math.max(bufferIn[j], maxTime);\n\n                    for (let k = 0; k < numComps; k++)\n                    {\n                        if (anims[k].defaultEasing === CABLES.EASING_CUBICSPLINE)\n                        {\n                            const idx = ((j * numComps) * 3 + k);\n\n                            const key = anims[k].setValue(bufferIn[j], bufferOut[idx + numComps]);\n                            key.bezTangIn = bufferOut[idx];\n                            key.bezTangOut = bufferOut[idx + (numComps * 2)];\n\n                            // console.log(an.name,k,bufferOut[idx+1]);\n                        }\n                        else\n                        {\n                            // console.log(an.name,k,bufferOut[j * numComps + k]);\n                            anims[k].setValue(bufferIn[j], bufferOut[j * numComps + k]);\n                        }\n                    }\n                }\n\n                node.setAnim(chan.target.path, an.name, anims);\n            }\n            else\n            {\n                op.warn("loadAmins bufferIn undefined ", bufferIn === undefined);\n                op.warn("loadAmins bufferOut undefined ", bufferOut === undefined);\n                op.warn("loadAmins ", sampler, accOut);\n                op.warn("loadAmins num accBuffers", gltf.accBuffers.length);\n                op.warn("loadAmins num accessors", gltf.json.accessors.length);\n            }\n        }\n    }\n\n    gltf.uniqueAnimNames = uniqueAnimNames;\n\n    outAnims.setRef(Object.keys(uniqueAnimNames));\n}\n\nfunction loadCams(gltf)\n{\n    if (!gltf || !gltf.json.cameras) return;\n\n    gltf.cameras = gltf.cameras || [];\n\n    for (let i = 0; i < gltf.nodes.length; i++)\n    {\n        if (gltf.nodes[i].hasOwnProperty("camera"))\n        {\n            const cam = new gltfCamera(gltf, gltf.nodes[i]);\n            gltf.cameras.push(cam);\n        }\n    }\n}\n\nfunction loadAfterDraco()\n{\n    if (!window.DracoDecoder)\n    {\n        setTimeout(() =>\n        {\n            loadAfterDraco();\n        }, 100);\n    }\n\n    reloadSoon();\n}\n\nfunction parseGltf(arrayBuffer)\n{\n    const CHUNK_HEADER_SIZE = 8;\n\n    let j = 0, i = 0;\n\n    const gltf = new Gltf();\n    gltf.timing.push(["Start parsing", Math.round((performance.now() - gltf.startTime))]);\n\n    if (!arrayBuffer) return;\n    const byteArray = new Uint8Array(arrayBuffer);\n    let pos = 0;\n\n    // var string = new TextDecoder("utf-8").decode(byteArray.subarray(pos, 4));\n    const string = Utf8ArrayToStr(byteArray.subarray(pos, 4));\n    pos += 4;\n    if (string != "glTF") return;\n\n    gltf.timing.push(["dataview", Math.round((performance.now() - gltf.startTime))]);\n\n    const dv = new DataView(arrayBuffer);\n    const version = dv.getUint32(pos, le);\n    pos += 4;\n    const size = dv.getUint32(pos, le);\n    pos += 4;\n\n    outVersion.set(version);\n\n    const chunks = [];\n    gltf.chunks = chunks;\n\n    chunks.push(readChunk(dv, byteArray, arrayBuffer, pos));\n    pos += chunks[0].size + CHUNK_HEADER_SIZE;\n    gltf.json = chunks[0].data;\n\n    gltf.cables = {\n        "fileUrl": inFile.get(),\n        "shortFileName": CABLES.basename(inFile.get())\n    };\n\n    outJson.setRef(gltf.json);\n    outExtensions.setRef(gltf.json.extensionsUsed || []);\n\n    let ch = readChunk(dv, byteArray, arrayBuffer, pos);\n    while (ch)\n    {\n        chunks.push(ch);\n        pos += ch.size + CHUNK_HEADER_SIZE;\n        ch = readChunk(dv, byteArray, arrayBuffer, pos);\n    }\n\n    gltf.chunks = chunks;\n\n    const views = chunks[0].data.bufferViews;\n    const accessors = chunks[0].data.accessors;\n\n    gltf.timing.push(["Parse buffers", Math.round((performance.now() - gltf.startTime))]);\n\n    if (gltf.json.extensionsUsed && gltf.json.extensionsUsed.indexOf("KHR_draco_mesh_compression") > -1)\n    {\n        if (!window.DracoDecoder)\n        {\n            op.setUiError("gltfdraco", "GLTF draco compression lib not found / add draco op to your patch!");\n\n            loadAfterDraco();\n            return gltf;\n        }\n        else\n        {\n            gltf.useDraco = true;\n        }\n    }\n\n    op.setUiError("gltfdraco", null);\n    // let accPos = (view.byteOffset || 0) + (acc.byteOffset || 0);\n\n    if (views)\n    {\n        for (i = 0; i < accessors.length; i++)\n        {\n            const acc = accessors[i];\n            const view = views[acc.bufferView];\n\n            let numComps = 0;\n            if (acc.type == "SCALAR")numComps = 1;\n            else if (acc.type == "VEC2")numComps = 2;\n            else if (acc.type == "VEC3")numComps = 3;\n            else if (acc.type == "VEC4")numComps = 4;\n            else if (acc.type == "MAT4")numComps = 16;\n            else console.error("unknown accessor type", acc.type);\n\n            //   const decoder = new decoderModule.Decoder();\n            //   const decodedGeometry = decodeDracoData(data, decoder);\n            //   // Encode mesh\n            //   encodeMeshToFile(decodedGeometry, decoder);\n\n            //   decoderModule.destroy(decoder);\n            //   decoderModule.destroy(decodedGeometry);\n\n            // 5120 (BYTE)\t1\n            // 5121 (UNSIGNED_BYTE)\t1\n            // 5122 (SHORT)\t2\n\n            if (chunks[1].dataView)\n            {\n                if (view)\n                {\n                    const num = acc.count * numComps;\n                    let accPos = (view.byteOffset || 0) + (acc.byteOffset || 0);\n                    let stride = view.byteStride || 0;\n                    let dataBuff = null;\n\n                    if (acc.componentType == 5126 || acc.componentType == 5125) // 4byte FLOAT or INT\n                    {\n                        stride = stride || 4;\n\n                        const isInt = acc.componentType == 5125;\n                        if (isInt)dataBuff = new Uint32Array(num);\n                        else dataBuff = new Float32Array(num);\n\n                        dataBuff.cblStride = numComps;\n\n                        for (j = 0; j < num; j++)\n                        {\n                            if (isInt) dataBuff[j] = chunks[1].dataView.getUint32(accPos, le);\n                            else dataBuff[j] = chunks[1].dataView.getFloat32(accPos, le);\n\n                            if (stride != 4 && (j + 1) % numComps === 0)accPos += stride - (numComps * 4);\n                            accPos += 4;\n                        }\n                    }\n                    else if (acc.componentType == 5123) // UNSIGNED_SHORT\n                    {\n                        stride = stride || 2;\n\n                        dataBuff = new Uint16Array(num);\n                        dataBuff.cblStride = stride;\n\n                        for (j = 0; j < num; j++)\n                        {\n                            dataBuff[j] = chunks[1].dataView.getUint16(accPos, le);\n\n                            if (stride != 2 && (j + 1) % numComps === 0) accPos += stride - (numComps * 2);\n\n                            accPos += 2;\n                        }\n                    }\n                    else if (acc.componentType == 5121) // UNSIGNED_BYTE\n                    {\n                        stride = stride || 1;\n\n                        dataBuff = new Uint8Array(num);\n                        dataBuff.cblStride = stride;\n\n                        for (j = 0; j < num; j++)\n                        {\n                            dataBuff[j] = chunks[1].dataView.getUint8(accPos, le);\n\n                            if (stride != 1 && (j + 1) % numComps === 0) accPos += stride - (numComps * 1);\n\n                            accPos += 1;\n                        }\n                    }\n\n                    else\n                    {\n                        console.error("unknown component type", acc.componentType);\n                    }\n\n                    gltf.accBuffers.push(dataBuff);\n                }\n                else\n                {\n                    // console.log("has no dataview");\n                }\n            }\n        }\n    }\n\n    gltf.timing.push(["Parse mesh groups", Math.round((performance.now() - gltf.startTime))]);\n\n    gltf.json.meshes = gltf.json.meshes || [];\n\n    if (gltf.json.meshes)\n    {\n        for (i = 0; i < gltf.json.meshes.length; i++)\n        {\n            const mesh = new gltfMeshGroup(gltf, gltf.json.meshes[i]);\n            gltf.meshes.push(mesh);\n        }\n    }\n\n    gltf.timing.push(["Parse nodes", Math.round((performance.now() - gltf.startTime))]);\n\n    for (i = 0; i < gltf.json.nodes.length; i++)\n    {\n        if (gltf.json.nodes[i].children)\n            for (j = 0; j < gltf.json.nodes[i].children.length; j++)\n            {\n                gltf.json.nodes[gltf.json.nodes[i].children[j]].isChild = true;\n            }\n    }\n\n    for (i = 0; i < gltf.json.nodes.length; i++)\n    {\n        const node = new gltfNode(gltf.json.nodes[i], gltf);\n        gltf.nodes.push(node);\n    }\n\n    for (i = 0; i < gltf.nodes.length; i++)\n    {\n        const node = gltf.nodes[i];\n\n        if (!node.children) continue;\n        for (let j = 0; j < node.children.length; j++)\n        {\n            gltf.nodes[node.children[j]].parent = node;\n        }\n    }\n\n    for (i = 0; i < gltf.nodes.length; i++)\n    {\n        gltf.nodes[i].initSkin();\n    }\n\n    needsMatUpdate = true;\n\n    gltf.timing.push(["load anims", Math.round((performance.now() - gltf.startTime))]);\n\n    if (gltf.json.animations) loadAnims(gltf);\n\n    gltf.timing.push(["load cameras", Math.round((performance.now() - gltf.startTime))]);\n\n    if (gltf.json.cameras) loadCams(gltf);\n\n    gltf.timing.push(["finished", Math.round((performance.now() - gltf.startTime))]);\n    return gltf;\n}\n',inc_mesh_js:'let gltfMesh = class\n{\n    constructor(name, prim, gltf, finished)\n    {\n        this.POINTS = 0;\n        this.LINES = 1;\n        this.LINE_LOOP = 2;\n        this.LINE_STRIP = 3;\n        this.TRIANGLES = 4;\n        this.TRIANGLE_STRIP = 5;\n        this.TRIANGLE_FAN = 6;\n\n        this.test = 0;\n        this.name = name;\n        this.submeshIndex = 0;\n        this.material = prim.material;\n        // console.log(prim);\n        this.mesh = null;\n        this.geom = new CGL.Geometry("gltf_" + this.name);\n        this.geom.verticesIndices = [];\n        this.bounds = null;\n        this.primitive = 4;\n        this.morphTargetsRenderMod = null;\n        this.weights = prim.weights;\n\n        if (prim.hasOwnProperty("mode")) this.primitive = prim.mode;\n\n        if (prim.hasOwnProperty("indices")) this.geom.verticesIndices = gltf.accBuffers[prim.indices];\n\n        gltf.loadingMeshes = gltf.loadingMeshes || 0;\n        gltf.loadingMeshes++;\n\n        this.materialJson =\n            this._matPbrMetalness =\n            this._matPbrRoughness =\n            this._matDiffuseColor = null;\n\n        if (gltf.json.materials)\n        {\n            if (this.material != -1) this.materialJson = gltf.json.materials[this.material];\n\n            if (this.materialJson && this.materialJson.pbrMetallicRoughness)\n            {\n                if (!this.materialJson.pbrMetallicRoughness.hasOwnProperty("baseColorFactor"))\n                {\n                    this._matDiffuseColor = [1, 1, 1, 1];\n                }\n                else\n                {\n                    this._matDiffuseColor = this.materialJson.pbrMetallicRoughness.baseColorFactor;\n                }\n\n                this._matDiffuseColor = this.materialJson.pbrMetallicRoughness.baseColorFactor;\n\n                if (!this.materialJson.pbrMetallicRoughness.hasOwnProperty("metallicFactor"))\n                {\n                    this._matPbrMetalness = 1.0;\n                }\n                else\n                {\n                    this._matPbrMetalness = this.materialJson.pbrMetallicRoughness.metallicFactor || null;\n                }\n\n                if (!this.materialJson.pbrMetallicRoughness.hasOwnProperty("roughnessFactor"))\n                {\n                    this._matPbrRoughness = 1.0;\n                }\n                else\n                {\n                    this._matPbrRoughness = this.materialJson.pbrMetallicRoughness.roughnessFactor || null;\n                }\n            }\n        }\n\n        if (gltf.useDraco && prim.extensions.KHR_draco_mesh_compression)\n        {\n            const view = gltf.chunks[0].data.bufferViews[prim.extensions.KHR_draco_mesh_compression.bufferView];\n            const num = view.byteLength;\n            const dataBuff = new Int8Array(num);\n            let accPos = (view.byteOffset || 0);// + (acc.byteOffset || 0);\n            for (let j = 0; j < num; j++)\n            {\n                dataBuff[j] = gltf.chunks[1].dataView.getInt8(accPos, le);\n                accPos++;\n            }\n\n            const dracoDecoder = window.DracoDecoder;\n            dracoDecoder.decodeGeometry(dataBuff.buffer, (geometry) =>\n            {\n                const geom = new CGL.Geometry("draco mesh " + name);\n\n                for (let i = 0; i < geometry.attributes.length; i++)\n                {\n                    const attr = geometry.attributes[i];\n\n                    if (attr.name === "position") geom.vertices = attr.array;\n                    else if (attr.name === "normal") geom.vertexNormals = attr.array;\n                    else if (attr.name === "uv") geom.texCoords = attr.array;\n                    else if (attr.name === "color") geom.vertexColors = this.calcVertexColors(attr.array);\n                    else if (attr.name === "joints") geom.setAttribute("attrJoints", Array.from(attr.array), 4);\n                    else if (attr.name === "weights")\n                    {\n                        const arr4 = new Float32Array(attr.array.length / attr.itemSize * 4);\n\n                        for (let k = 0; k < attr.array.length / attr.itemSize; k++)\n                        {\n                            arr4[k * 4] = arr4[k * 4 + 1] = arr4[k * 4 + 2] = arr4[k * 4 + 3] = 0;\n                            for (let j = 0; j < attr.itemSize; j++)\n                                arr4[k * 4 + j] = attr.array[k * attr.itemSize + j];\n                        }\n                        geom.setAttribute("attrWeights", arr4, 4);\n                    }\n                    else op.logWarn("unknown draco attrib", attr);\n                }\n\n                geometry.attributes = null;\n                geom.verticesIndices = geometry.index.array;\n\n                this.setGeom(geom);\n\n                this.mesh = null;\n                gltf.loadingMeshes--;\n                gltf.timing.push(["draco decode", Math.round((performance.now() - gltf.startTime))]);\n\n                if (finished)finished(this);\n            }, (error) => { op.logError(error); });\n        }\n        else\n        {\n            gltf.loadingMeshes--;\n            this.fillGeomAttribs(gltf, this.geom, prim.attributes);\n\n            if (prim.targets)\n            {\n                for (let j = 0; j < prim.targets.length; j++)\n                {\n                    const tgeom = new CGL.Geometry("gltf_target_" + j);\n\n                    // if (prim.hasOwnProperty("indices")) tgeom.verticesIndices = gltf.accBuffers[prim.indices];\n\n                    this.fillGeomAttribs(gltf, tgeom, prim.targets[j], false);\n\n                    // { // calculate normals for final position of morphtarget for later...\n                    //     for (let i = 0; i < tgeom.vertices.length; i++) tgeom.vertices[i] += this.geom.vertices[i];\n                    //     tgeom.calculateNormals();\n                    //     for (let i = 0; i < tgeom.vertices.length; i++) tgeom.vertices[i] -= this.geom.vertices[i];\n                    // }\n\n                    this.geom.morphTargets.push(tgeom);\n                }\n            }\n            if (finished)finished(this);\n        }\n    }\n\n    _linearToSrgb(x)\n    {\n        if (x <= 0)\n            return 0;\n        else if (x >= 1)\n            return 1;\n        else if (x < 0.0031308)\n            return x * 12.92;\n        else\n            return x ** (1 / 2.2) * 1.055 - 0.055;\n    }\n\n    calcVertexColors(arr, type)\n    {\n        let vertexColors = null;\n        if (arr instanceof Float32Array)\n        {\n            let div = false;\n            for (let i = 0; i < arr.length; i++)\n            {\n                if (arr[i] > 1)\n                {\n                    div = true;\n                    continue;\n                }\n            }\n\n            if (div)\n                for (let i = 0; i < arr.length; i++) arr[i] /= 65535;\n\n            vertexColors = arr;\n        }\n\n        else if (arr instanceof Uint16Array)\n        {\n            const fb = new Float32Array(arr.length);\n            for (let i = 0; i < arr.length; i++) fb[i] = arr[i] / 65535;\n\n            vertexColors = fb;\n        }\n        else vertexColors = arr;\n\n        for (let i = 0; i < vertexColors.length; i++)\n        {\n            vertexColors[i] = this._linearToSrgb(vertexColors[i]);\n        }\n\n        console.log("arr.cblStride", arr.cblStride);\n        if (arr.cblStride == 3)\n        {\n            const nc = new Float32Array(vertexColors.length / 3 * 4);\n            for (let i = 0; i < vertexColors.length / 3; i++)\n            {\n                nc[i * 4 + 0] = vertexColors[i * 3 + 0];\n                nc[i * 4 + 1] = vertexColors[i * 3 + 1];\n                nc[i * 4 + 2] = vertexColors[i * 3 + 2];\n                nc[i * 4 + 3] = 1;\n            }\n            vertexColors = nc;\n        }\n\n        return vertexColors;\n    }\n\n    fillGeomAttribs(gltf, tgeom, attribs, setGeom)\n    {\n        if (attribs.hasOwnProperty("POSITION")) tgeom.vertices = gltf.accBuffers[attribs.POSITION];\n        if (attribs.hasOwnProperty("NORMAL")) tgeom.vertexNormals = gltf.accBuffers[attribs.NORMAL];\n        if (attribs.hasOwnProperty("TANGENT")) tgeom.tangents = gltf.accBuffers[attribs.TANGENT];\n\n        // // console.log(gltf.accBuffers[attribs.COLOR_0])\n        // console.log(gltf);\n\n        if (attribs.hasOwnProperty("COLOR_0")) tgeom.vertexColors = this.calcVertexColors(gltf.accBuffers[attribs.COLOR_0], gltf.accBuffers[attribs.COLOR_0].type);\n        if (attribs.hasOwnProperty("COLOR_1")) tgeom.setAttribute("attrVertColor1", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_1]), gltf.accBuffers[attribs.COLOR_1].type);\n        if (attribs.hasOwnProperty("COLOR_2")) tgeom.setAttribute("attrVertColor2", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_2]), gltf.accBuffers[attribs.COLOR_2].type);\n        if (attribs.hasOwnProperty("COLOR_3")) tgeom.setAttribute("attrVertColor3", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_3]), gltf.accBuffers[attribs.COLOR_3].type);\n        if (attribs.hasOwnProperty("COLOR_4")) tgeom.setAttribute("attrVertColor4", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_4]), gltf.accBuffers[attribs.COLOR_4].type);\n\n        if (attribs.hasOwnProperty("TEXCOORD_0")) tgeom.texCoords = gltf.accBuffers[attribs.TEXCOORD_0];\n        if (attribs.hasOwnProperty("TEXCOORD_1")) tgeom.setAttribute("attrTexCoord1", gltf.accBuffers[attribs.TEXCOORD_1], 2);\n        if (attribs.hasOwnProperty("TEXCOORD_2")) tgeom.setAttribute("attrTexCoord2", gltf.accBuffers[attribs.TEXCOORD_2], 2);\n        if (attribs.hasOwnProperty("TEXCOORD_3")) tgeom.setAttribute("attrTexCoord3", gltf.accBuffers[attribs.TEXCOORD_3], 2);\n        if (attribs.hasOwnProperty("TEXCOORD_4")) tgeom.setAttribute("attrTexCoord4", gltf.accBuffers[attribs.TEXCOORD_4], 2);\n\n        if (attribs.hasOwnProperty("WEIGHTS_0"))\n        {\n            tgeom.setAttribute("attrWeights", gltf.accBuffers[attribs.WEIGHTS_0], 4);\n        }\n        if (attribs.hasOwnProperty("JOINTS_0"))\n        {\n            if (!gltf.accBuffers[attribs.JOINTS_0])console.log("no !gltf.accBuffers[attribs.JOINTS_0]");\n            tgeom.setAttribute("attrJoints", gltf.accBuffers[attribs.JOINTS_0], 4);\n        }\n\n        if (attribs.hasOwnProperty("POSITION")) gltf.accBuffersDelete.push(attribs.POSITION);\n        if (attribs.hasOwnProperty("NORMAL")) gltf.accBuffersDelete.push(attribs.NORMAL);\n        if (attribs.hasOwnProperty("TEXCOORD_0")) gltf.accBuffersDelete.push(attribs.TEXCOORD_0);\n        if (attribs.hasOwnProperty("TANGENT")) gltf.accBuffersDelete.push(attribs.TANGENT);\n        if (attribs.hasOwnProperty("COLOR_0"))gltf.accBuffersDelete.push(attribs.COLOR_0);\n        if (attribs.hasOwnProperty("COLOR_0"))gltf.accBuffersDelete.push(attribs.COLOR_0);\n        if (attribs.hasOwnProperty("COLOR_1"))gltf.accBuffersDelete.push(attribs.COLOR_1);\n        if (attribs.hasOwnProperty("COLOR_2"))gltf.accBuffersDelete.push(attribs.COLOR_2);\n        if (attribs.hasOwnProperty("COLOR_3"))gltf.accBuffersDelete.push(attribs.COLOR_3);\n\n        if (attribs.hasOwnProperty("TEXCOORD_1")) gltf.accBuffersDelete.push(attribs.TEXCOORD_1);\n        if (attribs.hasOwnProperty("TEXCOORD_2")) gltf.accBuffersDelete.push(attribs.TEXCOORD_2);\n        if (attribs.hasOwnProperty("TEXCOORD_3")) gltf.accBuffersDelete.push(attribs.TEXCOORD_3);\n        if (attribs.hasOwnProperty("TEXCOORD_4")) gltf.accBuffersDelete.push(attribs.TEXCOORD_4);\n\n        if (setGeom !== false) if (tgeom && tgeom.verticesIndices) this.setGeom(tgeom);\n    }\n\n    setGeom(geom)\n    {\n        if (inNormFormat.get() == "X-ZY")\n        {\n            for (let i = 0; i < geom.vertexNormals.length; i += 3)\n            {\n                let t = geom.vertexNormals[i + 2];\n                geom.vertexNormals[i + 2] = geom.vertexNormals[i + 1];\n                geom.vertexNormals[i + 1] = -t;\n            }\n        }\n\n        if (inVertFormat.get() == "XZ-Y")\n        {\n            for (let i = 0; i < geom.vertices.length; i += 3)\n            {\n                let t = geom.vertices[i + 2];\n                geom.vertices[i + 2] = -geom.vertices[i + 1];\n                geom.vertices[i + 1] = t;\n            }\n        }\n\n        if (this.primitive == this.TRIANGLES)\n        {\n            if (inCalcNormals.get() == "Force Smooth" || inCalcNormals.get() == false) geom.calculateNormals();\n            else if (!geom.vertexNormals.length && inCalcNormals.get() == "Auto") geom.calculateNormals({ "smooth": false });\n\n            if ((!geom.biTangents || geom.biTangents.length == 0) && geom.tangents)\n            {\n                const bitan = vec3.create();\n                const tan = vec3.create();\n\n                const tangents = geom.tangents;\n                geom.tangents = new Float32Array(tangents.length / 4 * 3);\n                geom.biTangents = new Float32Array(tangents.length / 4 * 3);\n\n                for (let i = 0; i < tangents.length; i += 4)\n                {\n                    const idx = i / 4 * 3;\n\n                    vec3.cross(\n                        bitan,\n                        [geom.vertexNormals[idx], geom.vertexNormals[idx + 1], geom.vertexNormals[idx + 2]],\n                        [tangents[i], tangents[i + 1], tangents[i + 2]]\n                    );\n\n                    vec3.div(bitan, bitan, [tangents[i + 3], tangents[i + 3], tangents[i + 3]]);\n                    vec3.normalize(bitan, bitan);\n\n                    geom.biTangents[idx + 0] = bitan[0];\n                    geom.biTangents[idx + 1] = bitan[1];\n                    geom.biTangents[idx + 2] = bitan[2];\n\n                    geom.tangents[idx + 0] = tangents[i + 0];\n                    geom.tangents[idx + 1] = tangents[i + 1];\n                    geom.tangents[idx + 2] = tangents[i + 2];\n                }\n            }\n\n            if (geom.tangents.length === 0 || inCalcNormals.get() != "Never")\n            {\n                // console.log("[gltf ]no tangents... calculating tangents...");\n                geom.calcTangentsBitangents();\n            }\n        }\n\n        this.geom = geom;\n\n        this.bounds = geom.getBounds();\n    }\n\n    render(cgl, ignoreMaterial, skinRenderer)\n    {\n        if (!this.mesh && this.geom && this.geom.verticesIndices)\n        {\n            let g = this.geom;\n            if (this.geom.vertices.length / 3 > 64000)\n            {\n                g = this.geom.copy();\n                g.unIndex(false, true);\n            }\n\n            let glprim;\n\n            if (cgl.gl)\n            {\n                if (this.primitive == this.TRIANGLES)glprim = cgl.gl.TRIANGLES;\n                else if (this.primitive == this.LINES)glprim = cgl.gl.LINES;\n                else if (this.primitive == this.LINE_STRIP)glprim = cgl.gl.LINE_STRIP;\n                else if (this.primitive == this.POINTS)glprim = cgl.gl.POINTS;\n                else\n                {\n                    op.logWarn("unknown primitive type", this);\n                }\n            }\n\n            this.mesh = op.patch.cg.createMesh(g, { "glPrimitive": glprim });\n        }\n\n        if (this.mesh)\n        {\n            // update morphTargets\n            if (this.geom && this.geom.morphTargets.length && !this.morphTargetsRenderMod)\n            {\n                this.mesh.addVertexNumbers = true;\n                this.morphTargetsRenderMod = new GltfTargetsRenderer(this);\n            }\n\n            let useMat = !ignoreMaterial && this.material != -1 && gltf.shaders[this.material];\n            if (skinRenderer)useMat = false;\n\n            if (useMat) cgl.pushShader(gltf.shaders[this.material]);\n\n            const currentShader = cgl.getShader() || {};\n            const uniDiff = currentShader.uniformColorDiffuse;\n\n            const uniPbrMetalness = currentShader.uniformPbrMetalness;\n            const uniPbrRoughness = currentShader.uniformPbrRoughness;\n\n            // if (gltf.shaders[this.material] && !inUseMatProps.get())\n            // {\n            //     gltf.shaders[this.material]=null;\n            // }\n\n            if (!gltf.shaders[this.material] && inUseMatProps.get())\n            {\n                if (uniDiff && this._matDiffuseColor)\n                {\n                    this._matDiffuseColorOrig = [uniDiff.getValue()[0], uniDiff.getValue()[1], uniDiff.getValue()[2], uniDiff.getValue()[3]];\n                    uniDiff.setValue(this._matDiffuseColor);\n                }\n\n                if (uniPbrMetalness)\n                    if (this._matPbrMetalness != null)\n                    {\n                        this._matPbrMetalnessOrig = uniPbrMetalness.getValue();\n                        uniPbrMetalness.setValue(this._matPbrMetalness);\n                    }\n                    else\n                        uniPbrMetalness.setValue(0);\n\n                if (uniPbrRoughness)\n                    if (this._matPbrRoughness != null)\n                    {\n                        this._matPbrRoughnessOrig = uniPbrRoughness.getValue();\n                        uniPbrRoughness.setValue(this._matPbrRoughness);\n                    }\n                    else\n                    {\n                        uniPbrRoughness.setValue(0);\n                    }\n            }\n\n            if (this.morphTargetsRenderMod) this.morphTargetsRenderMod.renderStart(cgl, 0);\n            if (this.mesh)\n            {\n                // console.log(this.mesh)\n                // this.mesh.lastMaterial=0;\n                this.mesh.render(cgl.getShader(), ignoreMaterial);\n            }\n            if (this.morphTargetsRenderMod) this.morphTargetsRenderMod.renderFinish(cgl);\n\n            if (inUseMatProps.get())\n            {\n                if (uniDiff && this._matDiffuseColor) uniDiff.setValue(this._matDiffuseColorOrig);\n                if (uniPbrMetalness && this._matPbrMetalnessOrig != undefined) uniPbrMetalness.setValue(this._matPbrMetalnessOrig);\n                if (uniPbrRoughness && this._matPbrRoughnessOrig != undefined) uniPbrRoughness.setValue(this._matPbrRoughnessOrig);\n            }\n\n            if (useMat) cgl.popShader();\n        }\n    }\n};\n',inc_meshGroup_js:"const gltfMeshGroup = class\n{\n    constructor(gltf, m)\n    {\n        this.bounds = new CABLES.CG.BoundingBox();\n        this.meshes = [];\n        this.name = m.name;\n        const prims = m.primitives;\n\n        for (let i = 0; i < prims.length; i++)\n        {\n            const mesh = new gltfMesh(this.name, prims[i], gltf,\n                (mesh) =>\n                {\n                    mesh.extras = m.extras;\n                    this.bounds.apply(mesh.bounds);\n                });\n\n            mesh.submeshIndex = i;\n            this.meshes.push(mesh);\n        }\n    }\n\n    render(cgl, ignoreMat, skinRenderer, _time, weights)\n    {\n        for (let i = 0; i < this.meshes.length; i++)\n        {\n            const useMat = gltf.shaders[this.meshes[i].material];\n\n            if (!ignoreMat && useMat) cgl.pushShader(gltf.shaders[this.meshes[i].material]);\n            // console.log(gltf.shaders[this.meshes[i].material],this.meshes[i].material)\n            if (skinRenderer)skinRenderer.renderStart(cgl, _time);\n            if (weights) this.meshes[i].weights = weights;\n            this.meshes[i].render(cgl, ignoreMat, skinRenderer, _time);\n            if (skinRenderer)skinRenderer.renderFinish(cgl);\n            if (!ignoreMat && useMat) cgl.popShader();\n        }\n    }\n};\n",inc_node_js:'const gltfNode = class\n{\n    constructor(node, gltf)\n    {\n        this.isChild = node.isChild || false;\n        this.name = node.name;\n        if (node.hasOwnProperty("camera")) this.camera = node.camera;\n        this.hidden = false;\n        this.mat = mat4.create();\n        this._animActions = {};\n        this.animWeights = [];\n        this._animMat = mat4.create();\n        this._tempMat = mat4.create();\n        this._tempQuat = quat.create();\n        this._tempRotmat = mat4.create();\n        this.mesh = null;\n        this.children = [];\n        this._node = node;\n        this._gltf = gltf;\n        this.absMat = mat4.create();\n        this.addTranslate = null;\n        this._tempAnimScale = null;\n        this.addMulMat = null;\n        this.updateMatrix();\n        this.skinRenderer = null;\n        this.copies = [];\n    }\n\n    get skin()\n    {\n        if (this._node.hasOwnProperty("skin")) return this._node.skin;\n        else return -1;\n    }\n\n    copy()\n    {\n        this.isCopy = true;\n        const n = new gltfNode(this._node, this._gltf);\n        n.copyOf = this;\n\n        n._animActions = this._animActions;\n        n.children = this.children;\n        if (this.skin) n.skinRenderer = new GltfSkin(this);\n\n        this.updateMatrix();\n        return n;\n    }\n\n    hasSkin()\n    {\n        if (this._node.hasOwnProperty("skin")) return this._gltf.json.skins[this._node.skin].name || "unknown";\n        return false;\n    }\n\n    initSkin()\n    {\n        if (this.skin > -1)\n        {\n            this.skinRenderer = new GltfSkin(this);\n        }\n    }\n\n    updateMatrix()\n    {\n        mat4.identity(this.mat);\n        if (this._node.translation) mat4.translate(this.mat, this.mat, this._node.translation);\n\n        if (this._node.rotation)\n        {\n            const rotmat = mat4.create();\n            this._rot = this._node.rotation;\n\n            mat4.fromQuat(rotmat, this._node.rotation);\n            mat4.mul(this.mat, this.mat, rotmat);\n        }\n\n        if (this._node.scale)\n        {\n            this._scale = this._node.scale;\n            mat4.scale(this.mat, this.mat, this._scale);\n        }\n\n        if (this._node.hasOwnProperty("mesh"))\n        {\n            this.mesh = this._gltf.meshes[this._node.mesh];\n            if (this.isCopy)\n            {\n                // console.log(this.mesh);\n            }\n        }\n\n        if (this._node.children)\n        {\n            for (let i = 0; i < this._node.children.length; i++)\n            {\n                this._gltf.json.nodes[i].isChild = true;\n                if (this._gltf.nodes[this._node.children[i]]) this._gltf.nodes[this._node.children[i]].isChild = true;\n                this.children.push(this._node.children[i]);\n            }\n        }\n    }\n\n    unHide()\n    {\n        this.hidden = false;\n        for (let i = 0; i < this.children.length; i++)\n            if (this.children[i].unHide) this.children[i].unHide();\n    }\n\n    calcBounds(gltf, mat, bounds)\n    {\n        const localMat = mat4.create();\n\n        if (mat) mat4.copy(localMat, mat);\n        if (this.mat) mat4.mul(localMat, localMat, this.mat);\n\n        if (this.mesh)\n        {\n            const bb = this.mesh.bounds.copy();\n            bb.mulMat4(localMat);\n            bounds.apply(bb);\n\n            if (bounds.changed)\n            {\n                boundingPoints.push(\n                    bb._min[0] || 0, bb._min[1] || 0, bb._min[2] || 0,\n                    bb._max[0] || 0, bb._max[1] || 0, bb._max[2] || 0);\n            }\n        }\n\n        for (let i = 0; i < this.children.length; i++)\n        {\n            if (gltf.nodes[this.children[i]] && gltf.nodes[this.children[i]].calcBounds)\n            {\n                const b = gltf.nodes[this.children[i]].calcBounds(gltf, localMat, bounds);\n\n                bounds.apply(b);\n            }\n        }\n\n        if (bounds.changed) return bounds;\n        else return null;\n    }\n\n    setAnimAction(name)\n    {\n        // console.log("setAnimAction:", name);\n        if (!name) return;\n\n        this._currentAnimaction = name;\n\n        if (name && !this._animActions[name])\n        {\n            // console.log("no action found:", name,this._animActions);\n            return null;\n        }\n\n        // else console.log("YES action found:", name);\n        // console.log(this._animActions);\n\n        for (let path in this._animActions[name])\n        {\n            if (path == "translation") this._animTrans = this._animActions[name][path];\n            else if (path == "rotation") this._animRot = this._animActions[name][path];\n            else if (path == "scale") this._animScale = this._animActions[name][path];\n            else if (path == "weights") this.animWeights = this._animActions[name][path];\n            else console.log("[gltfNode] unknown anim path", path, this._animActions[name][path]);\n        }\n    }\n\n    setAnim(path, name, anims)\n    {\n        if (!path || !name || !anims) return;\n\n        // console.log("setanim", this._node.name, path, name, anims);\n\n        this._animActions[name] = this._animActions[name] || {};\n\n        // console.log(this._animActions);\n        // debugger;\n\n        // for (let i = 0; i < this.copies.length; i++) this.copies[i]._animActions = this._animActions;\n\n        if (this._animActions[name][path]) op.log("[gltfNode] animation action path already exists", name, path, this._animActions[name][path]);\n\n        this._animActions[name][path] = anims;\n\n        if (path == "translation") this._animTrans = anims;\n        else if (path == "rotation") this._animRot = anims;\n        else if (path == "scale") this._animScale = anims;\n        else if (path == "weights")\n        {\n            // console.log("weights",name,path,anims)\n            this.animWeights = this._animActions[name][path];\n            // console.log(this.animWeights);\n        }\n        else console.warn("unknown anim path", path, anims);\n    }\n\n    modelMatLocal()\n    {\n        return this._animMat || this.mat;\n    }\n\n    modelMatAbs()\n    {\n        return this.absMat;\n    }\n\n    transform(cgl, _time)\n    {\n        if (!_time && _time != 0)_time = time;\n\n        this._lastTimeTrans = _time;\n\n        // console.log(this._rot)\n\n        gltfTransforms++;\n\n        if (!this._animTrans && !this._animRot && !this._animScale)\n        {\n            mat4.mul(cgl.mMatrix, cgl.mMatrix, this.mat);\n            this._animMat = null;\n        }\n        else\n        {\n            this._animMat = this._animMat || mat4.create();\n            mat4.identity(this._animMat);\n\n            const playAnims = true;\n\n            if (playAnims && this._animTrans)\n            {\n                mat4.translate(this._animMat, this._animMat, [\n                    this._animTrans[0].getValue(_time),\n                    this._animTrans[1].getValue(_time),\n                    this._animTrans[2].getValue(_time)]);\n            }\n            else\n            if (this._node.translation) mat4.translate(this._animMat, this._animMat, this._node.translation);\n\n            if (playAnims && this._animRot)\n            {\n                if (this._animRot[0].defaultEasing == CABLES.EASING_LINEAR) CABLES.Anim.slerpQuaternion(_time, this._tempQuat, this._animRot[0], this._animRot[1], this._animRot[2], this._animRot[3]);\n                else if (this._animRot[0].defaultEasing == CABLES.EASING_ABSOLUTE)\n                {\n                    this._tempQuat[0] = this._animRot[0].getValue(_time);\n                    this._tempQuat[1] = this._animRot[1].getValue(_time);\n                    this._tempQuat[2] = this._animRot[2].getValue(_time);\n                    this._tempQuat[3] = this._animRot[3].getValue(_time);\n                }\n                else if (this._animRot[0].defaultEasing == CABLES.EASING_CUBICSPLINE)\n                {\n                    CABLES.Anim.slerpQuaternion(_time, this._tempQuat, this._animRot[0], this._animRot[1], this._animRot[2], this._animRot[3]);\n                }\n\n                mat4.fromQuat(this._tempMat, this._tempQuat);\n                mat4.mul(this._animMat, this._animMat, this._tempMat);\n            }\n            else if (this._rot)\n            {\n                mat4.fromQuat(this._tempRotmat, this._rot);\n                mat4.mul(this._animMat, this._animMat, this._tempRotmat);\n            }\n\n            if (playAnims && this._animScale)\n            {\n                if (!this._tempAnimScale) this._tempAnimScale = [1, 1, 1];\n                this._tempAnimScale[0] = this._animScale[0].getValue(_time);\n                this._tempAnimScale[1] = this._animScale[1].getValue(_time);\n                this._tempAnimScale[2] = this._animScale[2].getValue(_time);\n                mat4.scale(this._animMat, this._animMat, this._tempAnimScale);\n            }\n            else if (this._scale) mat4.scale(this._animMat, this._animMat, this._scale);\n\n            mat4.mul(cgl.mMatrix, cgl.mMatrix, this._animMat);\n        }\n\n        if (this.animWeights)\n        {\n            this.weights = this.weights || [];\n\n            let str = "";\n            for (let i = 0; i < this.animWeights.length; i++)\n            {\n                this.weights[i] = this.animWeights[i].getValue(_time);\n                str += this.weights[i] + "/";\n            }\n\n            // console.log(str);\n            // this.mesh.weights=this.animWeights.get(_time);\n            // console.log(this.animWeights);\n        }\n\n        if (this.addTranslate) mat4.translate(cgl.mMatrix, cgl.mMatrix, this.addTranslate);\n\n        if (this.addMulMat) mat4.mul(cgl.mMatrix, cgl.mMatrix, this.addMulMat);\n\n        mat4.copy(this.absMat, cgl.mMatrix);\n    }\n\n    render(cgl, dontTransform, dontDrawMesh, ignoreMaterial, ignoreChilds, drawHidden, _time)\n    {\n        if (!dontTransform) cgl.pushModelMatrix();\n\n        if (_time === undefined) _time = gltf.time;\n\n        if (!dontTransform || this.skinRenderer) this.transform(cgl, _time);\n\n        if (this.hidden && !drawHidden)\n        {\n        }\n        else\n        {\n            if (this.skinRenderer)\n            {\n                this.skinRenderer.time = _time;\n                if (!dontDrawMesh)\n                    this.mesh.render(cgl, ignoreMaterial, this.skinRenderer, _time, this.weights);\n            }\n            else\n            {\n                if (this.mesh && !dontDrawMesh)\n                    this.mesh.render(cgl, ignoreMaterial, null, _time, this.weights);\n            }\n        }\n\n        if (!ignoreChilds && !this.hidden)\n            for (let i = 0; i < this.children.length; i++)\n                if (gltf.nodes[this.children[i]])\n                    gltf.nodes[this.children[i]].render(cgl, dontTransform, dontDrawMesh, ignoreMaterial, ignoreChilds, drawHidden, _time);\n\n        if (!dontTransform)cgl.popModelMatrix();\n    }\n};\n',inc_print_js:'let tab = null;\n\nfunction closeTab()\n{\n    if (tab)gui.mainTabs.closeTab(tab.id);\n    tab = null;\n}\n\nfunction formatVec(arr)\n{\n    const nums = [];\n    for (let i = 0; i < arr.length; i++)\n    {\n        nums.push(Math.round(arr[i] * 1000) / 1000);\n    }\n\n    return nums.join(",");\n}\n\nfunction printNode(html, node, level)\n{\n    if (!gltf) return;\n\n    html += "<tr class=\\"row\\">";\n\n    let ident = "";\n    let identSpace = "";\n\n    for (let i = 1; i < level; i++)\n    {\n        identSpace += "&nbsp;&nbsp;&nbsp;";\n        let identClass = "identBg";\n        if (i == 1)identClass = "identBgLevel0";\n        ident += "<td class=\\"ident " + identClass + "\\" ><div style=\\"\\"></div></td>";\n    }\n    let id = CABLES.uuid();\n    html += ident;\n    html += "<td colspan=\\"" + (21 - level) + "\\">";\n\n    if (node.mesh && node.mesh.meshes.length)html += "<span class=\\"icon icon-cube\\"></span>&nbsp;";\n    else html += "<span class=\\"icon icon-box-select\\"></span> &nbsp;";\n\n    html += node.name + "</td><td></td>";\n\n    if (node.mesh)\n    {\n        html += "<td>";\n        for (let i = 0; i < node.mesh.meshes.length; i++)\n        {\n            if (i > 0)html += ", ";\n            html += node.mesh.meshes[i].name;\n        }\n\n        html += "</td>";\n\n        html += "<td>";\n        html += node.hasSkin() || "-";\n        html += "</td>";\n\n        html += "<td>";\n        let countMats = 0;\n        for (let i = 0; i < node.mesh.meshes.length; i++)\n        {\n            if (countMats > 0)html += ", ";\n            if (gltf.json.materials && node.mesh.meshes[i].hasOwnProperty("material"))\n            {\n                if (gltf.json.materials[node.mesh.meshes[i].material])\n                {\n                    html += gltf.json.materials[node.mesh.meshes[i].material].name;\n                    countMats++;\n                }\n            }\n        }\n        if (countMats == 0)html += "none";\n        html += "</td>";\n    }\n    else\n    {\n        html += "<td>-</td><td>-</td><td>-</td>";\n    }\n\n    html += "<td>";\n\n    if (node._node.translation || node._node.rotation || node._node.scale)\n    {\n        let info = "";\n\n        if (node._node.translation)info += "Translate: `" + formatVec(node._node.translation) + "` || ";\n        if (node._node.rotation)info += "Rotation: `" + formatVec(node._node.rotation) + "` || ";\n        if (node._node.scale)info += "Scale: `" + formatVec(node._node.scale) + "` || ";\n\n        html += "<span class=\\"icon icon-gizmo info\\" data-info=\\"" + info + "\\"></span> &nbsp;";\n    }\n\n    if (node._animRot || node._animScale || node._animTrans)\n    {\n        let info = "Animated: ";\n        if (node._animRot) info += "Rot ";\n        if (node._animScale) info += "Scale ";\n        if (node._animTrans) info += "Trans ";\n\n        html += "<span class=\\"icon icon-clock info\\" data-info=\\"" + info + "\\"></span>&nbsp;";\n    }\n\n    if (!node._node.translation && !node._node.rotation && !node._node.scale && !node._animRot && !node._animScale && !node._animTrans) html += "-";\n\n    html += "</td>";\n\n    html += "<td>";\n    let hideclass = "";\n    if (node.hidden)hideclass = "node-hidden";\n\n    // html+=\'\';\n    html += "<a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').exposeNode(\'" + node.name + "\',\'transform\')\\" class=\\"treebutton\\">Transform</a>";\n    html += " <a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').exposeNode(\'" + node.name + "\',\'hierarchy\')\\" class=\\"treebutton\\">Hierarchy</a>";\n    html += " <a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').exposeNode(\'" + node.name + "\')\\" class=\\"treebutton\\">Node</a>";\n\n    if (node.hasSkin())\n        html += " <a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').exposeNode(\'" + node.name + "\',false,{skin:true});\\" class=\\"treebutton\\">Skin</a>";\n\n    html += "</td><td>";\n    html += "&nbsp;<span class=\\"icon iconhover icon-eye " + hideclass + "\\" onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').toggleNodeVisibility(\'" + node.name + "\');this.classList.toggle(\'node-hidden\');\\"></span>";\n    html += "</td>";\n\n    html += "</tr>";\n\n    if (node.children)\n    {\n        for (let i = 0; i < node.children.length; i++)\n            html = printNode(html, gltf.nodes[node.children[i]], level + 1);\n    }\n\n    return html;\n}\n\nfunction printMaterial(mat, idx)\n{\n    let html = "<tr>";\n    html += " <td>" + idx + "</td>";\n    html += " <td>" + mat.name + "</td>";\n\n    html += " <td>";\n\n    const info = JSON.stringify(mat, null, 4).replaceAll("\\"", "").replaceAll("\\n", "<br/>");\n\n    html += "<span class=\\"icon icon-info\\" onclick=\\"new CABLES.UI.ModalDialog({ \'html\': \'<pre>" + info + "</pre>\', \'title\': \'" + mat.name + "\' });\\"></span>&nbsp;";\n\n    if (mat.pbrMetallicRoughness && mat.pbrMetallicRoughness.baseColorFactor)\n    {\n        let rgb = "";\n        rgb += "" + Math.round(mat.pbrMetallicRoughness.baseColorFactor[0] * 255);\n        rgb += "," + Math.round(mat.pbrMetallicRoughness.baseColorFactor[1] * 255);\n        rgb += "," + Math.round(mat.pbrMetallicRoughness.baseColorFactor[2] * 255);\n\n        html += "<div style=\\"width:15px;height:15px;background-color:rgb(" + rgb + ");display:inline-block\\">&nbsp;</a>";\n    }\n    html += " <td style=\\"\\">" + (gltf.shaders[idx] ? "-" : "<a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').assignMaterial(\'" + mat.name + "\')\\" class=\\"treebutton\\">Assign</a>") + "<td>";\n    html += "<td>";\n\n    html += "</tr>";\n    return html;\n}\n\nfunction printInfo()\n{\n    if (!gltf) return;\n\n    const startTime = performance.now();\n    const sizes = {};\n    let html = "<div style=\\"overflow:scroll;width:100%;height:100%\\">";\n\n    html += "File: <a href=\\"" + CABLES.platform.getCablesUrl() + "/asset/patches/?filename=" + inFile.get() + "\\" target=\\"_blank\\">" + CABLES.basename(inFile.get()) + "</a><br/>";\n\n    html += "Generator:" + gltf.json.asset.generator;\n\n    let numNodes = 0;\n    if (gltf.json.nodes)numNodes = gltf.json.nodes.length;\n    html += "<div id=\\"groupNodes\\">Nodes (" + numNodes + ")</div>";\n\n    html += "<table id=\\"sectionNodes\\" class=\\"table treetable\\">";\n\n    html += "<tr>";\n    html += " <th colspan=\\"21\\">Name</th>";\n    html += " <th>Mesh</th>";\n    html += " <th>Skin</th>";\n    html += " <th>Material</th>";\n    html += " <th>Transform</th>";\n    html += " <th>Expose</th>";\n    html += " <th></th>";\n    html += "</tr>";\n\n    for (let i = 0; i < gltf.nodes.length; i++)\n    {\n        if (!gltf.nodes[i].isChild)\n            html = printNode(html, gltf.nodes[i], 1);\n    }\n    html += "</table>";\n\n    // / //////////////////\n\n    let numMaterials = 0;\n    if (gltf.json.materials)numMaterials = gltf.json.materials.length;\n    html += "<div id=\\"groupMaterials\\">Materials (" + numMaterials + ")</div>";\n\n    if (!gltf.json.materials || gltf.json.materials.length == 0)\n    {\n    }\n    else\n    {\n        html += "<table id=\\"materialtable\\"  class=\\"table treetable\\">";\n        html += "<tr>";\n        html += " <th>Index</th>";\n        html += " <th>Name</th>";\n        html += " <th>Color</th>";\n        html += " <th>Function</th>";\n        html += " <th></th>";\n        html += "</tr>";\n        for (let i = 0; i < gltf.json.materials.length; i++)\n        {\n            html += printMaterial(gltf.json.materials[i], i);\n        }\n        html += "</table>";\n    }\n\n    // / ///////////////////////\n\n    html += "<div id=\\"groupMeshes\\">Meshes (" + gltf.json.meshes.length + ")</div>";\n\n    html += "<table id=\\"meshestable\\"  class=\\"table treetable\\">";\n    html += "<tr>";\n    html += " <th>Name</th>";\n    html += " <th>Node</th>";\n    html += " <th>Material</th>";\n    html += " <th>Vertices</th>";\n    html += " <th>Attributes</th>";\n    html += "</tr>";\n\n    let sizeBufferViews = [];\n    sizes.meshes = 0;\n    sizes.meshTargets = 0;\n\n    for (let i = 0; i < gltf.json.meshes.length; i++)\n    {\n        html += "<tr>";\n        html += "<td>" + gltf.json.meshes[i].name + "</td>";\n\n        html += "<td>";\n        let count = 0;\n        let nodename = "";\n        for (let j = 0; j < gltf.json.nodes.length; j++)\n        {\n            if (gltf.json.nodes[j].mesh == i)\n            {\n                count++;\n                if (count == 1)\n                {\n                    nodename = gltf.json.nodes[j].name;\n                }\n            }\n        }\n        if (count > 1) html += (count) + " nodes (" + nodename + " ...)";\n        else html += nodename;\n        html += "</td>";\n\n        // -------\n\n        html += "<td>";\n        for (let j = 0; j < gltf.json.meshes[i].primitives.length; j++)\n        {\n            if (gltf.json.meshes[i].primitives[j].hasOwnProperty("material"))\n            {\n                if (gltf.json.materials[gltf.json.meshes[i]])\n                {\n                    html += gltf.json.materials[gltf.json.meshes[i].primitives[j].material].name + " ";\n                }\n            }\n            else html += "None";\n        }\n        html += "</td>";\n\n        html += "<td>";\n        let numVerts = 0;\n        for (let j = 0; j < gltf.json.meshes[i].primitives.length; j++)\n        {\n            if (gltf.json.meshes[i].primitives[j].attributes.POSITION != undefined)\n            {\n                let v = parseInt(gltf.json.accessors[gltf.json.meshes[i].primitives[j].attributes.POSITION].count);\n                numVerts += v;\n                html += "" + v + "<br/>";\n            }\n            else html += "-<br/>";\n        }\n\n        if (gltf.json.meshes[i].primitives.length > 1)\n            html += "=" + numVerts;\n        html += "</td>";\n\n        html += "<td>";\n        for (let j = 0; j < gltf.json.meshes[i].primitives.length; j++)\n        {\n            html += Object.keys(gltf.json.meshes[i].primitives[j].attributes);\n            html += " <a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').exposeGeom(\'" + gltf.json.meshes[i].name + "\'," + j + ")\\" class=\\"treebutton\\">Geometry</a>";\n            html += "<br/>";\n\n            if (gltf.json.meshes[i].primitives[j].targets)\n            {\n                html += gltf.json.meshes[i].primitives[j].targets.length + " targets<br/>";\n\n                if (gltf.json.meshes[i].extras && gltf.json.meshes[i].extras.targetNames)\n                    html += "Targetnames:<br/>" + gltf.json.meshes[i].extras.targetNames.join("<br/>");\n\n                html += "<br/>";\n            }\n        }\n\n        html += "</td>";\n        html += "</tr>";\n\n        for (let j = 0; j < gltf.json.meshes[i].primitives.length; j++)\n        {\n            const accessor = gltf.json.accessors[gltf.json.meshes[i].primitives[j].indices];\n            if (accessor)\n            {\n                let bufView = accessor.bufferView;\n\n                if (sizeBufferViews.indexOf(bufView) == -1)\n                {\n                    sizeBufferViews.push(bufView);\n                    if (gltf.json.bufferViews[bufView])sizes.meshes += gltf.json.bufferViews[bufView].byteLength;\n                }\n            }\n\n            for (let k in gltf.json.meshes[i].primitives[j].attributes)\n            {\n                const attr = gltf.json.meshes[i].primitives[j].attributes[k];\n                const bufView2 = gltf.json.accessors[attr].bufferView;\n\n                if (sizeBufferViews.indexOf(bufView2) == -1)\n                {\n                    sizeBufferViews.push(bufView2);\n                    if (gltf.json.bufferViews[bufView2])sizes.meshes += gltf.json.bufferViews[bufView2].byteLength;\n                }\n            }\n\n            if (gltf.json.meshes[i].primitives[j].targets)\n                for (let k = 0; k < gltf.json.meshes[i].primitives[j].targets.length; k++)\n                {\n                    for (let l in gltf.json.meshes[i].primitives[j].targets[k])\n                    {\n                        const accessorIdx = gltf.json.meshes[i].primitives[j].targets[k][l];\n                        const accessor = gltf.json.accessors[accessorIdx];\n                        const bufView2 = accessor.bufferView;\n                        console.log("accessor", accessor);\n                        if (sizeBufferViews.indexOf(bufView2) == -1)\n                            if (gltf.json.bufferViews[bufView2])\n                            {\n                                sizeBufferViews.push(bufView2);\n                                sizes.meshTargets += gltf.json.bufferViews[bufView2].byteLength;\n                            }\n                    }\n                }\n        }\n    }\n    html += "</table>";\n\n    // / //////////////////////////////////\n\n    let numSamplers = 0;\n    let numAnims = 0;\n    let numKeyframes = 0;\n\n    if (gltf.json.animations)\n    {\n        numAnims = gltf.json.animations.length;\n        for (let i = 0; i < gltf.json.animations.length; i++)\n        {\n            numSamplers += gltf.json.animations[i].samplers.length;\n        }\n    }\n\n    html += "<div id=\\"groupAnims\\">Animations (" + numAnims + "/" + numSamplers + ")</div>";\n\n    if (gltf.json.animations)\n    {\n        html += "<table id=\\"sectionAnim\\" class=\\"table treetable\\">";\n        html += "<tr>";\n        html += "  <th>Name</th>";\n        html += "  <th>Target node</th>";\n        html += "  <th>Path</th>";\n        html += "  <th>Interpolation</th>";\n        html += "  <th>Keys</th>";\n        html += "</tr>";\n\n\n        sizes.animations = 0;\n\n        for (let i = 0; i < gltf.json.animations.length; i++)\n        {\n            for (let j = 0; j < gltf.json.animations[i].samplers.length; j++)\n            {\n                let bufView = gltf.json.accessors[gltf.json.animations[i].samplers[j].input].bufferView;\n                if (sizeBufferViews.indexOf(bufView) == -1)\n                {\n                    sizeBufferViews.push(bufView);\n                    sizes.animations += gltf.json.bufferViews[bufView].byteLength;\n                }\n\n                bufView = gltf.json.accessors[gltf.json.animations[i].samplers[j].output].bufferView;\n                if (sizeBufferViews.indexOf(bufView) == -1)\n                {\n                    sizeBufferViews.push(bufView);\n                    sizes.animations += gltf.json.bufferViews[bufView].byteLength;\n                }\n            }\n\n            for (let j = 0; j < gltf.json.animations[i].channels.length; j++)\n            {\n                html += "<tr>";\n                html += "  <td> Anim " + i + ": " + gltf.json.animations[i].name + "</td>";\n\n                html += "  <td>" + gltf.nodes[gltf.json.animations[i].channels[j].target.node].name + "</td>";\n                html += "  <td>";\n                html += gltf.json.animations[i].channels[j].target.path + " ";\n                html += "  </td>";\n\n                const smplidx = gltf.json.animations[i].channels[j].sampler;\n                const smplr = gltf.json.animations[i].samplers[smplidx];\n\n                html += "  <td>" + smplr.interpolation + "</td>";\n\n                html += "  <td>" + gltf.json.accessors[smplr.output].count;\n                numKeyframes += gltf.json.accessors[smplr.output].count;\n\n                // html += "&nbsp;&nbsp;<a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').showAnim(\'" + i + "\',\'" + j + "\')\\" class=\\"icon icon-search\\"></a>";\n\n                html += "</td>";\n\n                html += "</tr>";\n            }\n        }\n\n        html += "<tr>";\n        html += "  <td></td>";\n        html += "  <td></td>";\n        html += "  <td></td>";\n        html += "  <td></td>";\n        html += "  <td>" + numKeyframes + " total</td>";\n        html += "</tr>";\n        html += "</table>";\n    }\n    else\n    {\n\n    }\n\n    // / ///////////////////\n\n    let numImages = 0;\n    if (gltf.json.images)numImages = gltf.json.images.length;\n    html += "<div id=\\"groupImages\\">Images (" + numImages + ")</div>";\n\n    if (gltf.json.images)\n    {\n        html += "<table id=\\"sectionImages\\" class=\\"table treetable\\">";\n\n        html += "<tr>";\n        html += "  <th>name</th>";\n        html += "  <th>type</th>";\n        html += "  <th>func</th>";\n        html += "</tr>";\n\n        sizes.images = 0;\n\n        for (let i = 0; i < gltf.json.images.length; i++)\n        {\n            if (gltf.json.images[i].hasOwnProperty("bufferView"))\n            {\n                // if (sizeBufferViews.indexOf(gltf.json.images[i].hasOwnProperty("bufferView")) == -1)console.log("image bufferview already there?!");\n                // else\n                sizes.images += gltf.json.bufferViews[gltf.json.images[i].bufferView].byteLength;\n            }\n            else console.log("image has no bufferview?!");\n\n            html += "<tr>";\n            html += "<td>" + gltf.json.images[i].name + "</td>";\n            html += "<td>" + gltf.json.images[i].mimeType + "</td>";\n            html += "<td>";\n\n            let name = gltf.json.images[i].name;\n            if (name === undefined)name = gltf.json.images[i].bufferView;\n\n            html += "<a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').exposeTexture(\'" + name + "\')\\" class=\\"treebutton\\">Expose</a>";\n            html += "</td>";\n\n            html += "<tr>";\n        }\n        html += "</table>";\n    }\n\n    // / ///////////////////////\n\n    let numCameras = 0;\n    if (gltf.json.cameras)numCameras = gltf.json.cameras.length;\n    html += "<div id=\\"groupCameras\\">Cameras (" + numCameras + ")</div>";\n\n    if (gltf.json.cameras)\n    {\n        html += "<table id=\\"sectionCameras\\" class=\\"table treetable\\">";\n\n        html += "<tr>";\n        html += "  <th>name</th>";\n        html += "  <th>type</th>";\n        html += "  <th>info</th>";\n        html += "</tr>";\n\n        for (let i = 0; i < gltf.json.cameras.length; i++)\n        {\n            html += "<tr>";\n            html += "<td>" + gltf.json.cameras[i].name + "</td>";\n            html += "<td>" + gltf.json.cameras[i].type + "</td>";\n            html += "<td>";\n\n            if (gltf.json.cameras[i].perspective)\n            {\n                html += "yfov: " + Math.round(gltf.json.cameras[i].perspective.yfov * 100) / 100;\n                html += ", ";\n                html += "zfar: " + Math.round(gltf.json.cameras[i].perspective.zfar * 100) / 100;\n                html += ", ";\n                html += "znear: " + Math.round(gltf.json.cameras[i].perspective.znear * 100) / 100;\n            }\n            html += "</td>";\n\n            html += "<tr>";\n        }\n        html += "</table>";\n    }\n\n    // / ////////////////////////////////////\n\n    let numSkins = 0;\n    if (gltf.json.skins)numSkins = gltf.json.skins.length;\n    html += "<div id=\\"groupSkins\\">Skins (" + numSkins + ")</div>";\n\n    if (gltf.json.skins)\n    {\n        // html += "<h3>Skins (" + gltf.json.skins.length + ")</h3>";\n        html += "<table id=\\"sectionSkins\\" class=\\"table treetable\\">";\n\n        html += "<tr>";\n        html += "  <th>name</th>";\n        html += "  <th></th>";\n        html += "  <th>total joints</th>";\n        html += "</tr>";\n\n        for (let i = 0; i < gltf.json.skins.length; i++)\n        {\n            html += "<tr>";\n            html += "<td>" + gltf.json.skins[i].name + "</td>";\n            html += "<td>" + "</td>";\n            html += "<td>" + gltf.json.skins[i].joints.length + "</td>";\n            html += "<td>";\n            html += "</td>";\n            html += "<tr>";\n        }\n        html += "</table>";\n    }\n\n    // / ////////////////////////////////////\n\n    if (gltf.timing)\n    {\n        html += "<div id=\\"groupTiming\\">Debug Loading Timing </div>";\n\n        html += "<table id=\\"sectionTiming\\" class=\\"table treetable\\">";\n\n        html += "<tr>";\n        html += "  <th>task</th>";\n        html += "  <th>time used</th>";\n        html += "</tr>";\n\n        let lt = 0;\n        for (let i = 0; i < gltf.timing.length - 1; i++)\n        {\n            html += "<tr>";\n            html += "  <td>" + gltf.timing[i][0] + "</td>";\n            html += "  <td>" + (gltf.timing[i + 1][1] - gltf.timing[i][1]) + " ms</td>";\n            html += "</tr>";\n            // lt = gltf.timing[i][1];\n        }\n        html += "</table>";\n    }\n\n    // / //////////////////////////\n\n    let sizeBin = 0;\n    if (gltf.json.buffers)\n        sizeBin = gltf.json.buffers[0].byteLength;\n\n    html += "<div id=\\"groupBinary\\">File Size Allocation (" + Math.round(sizeBin / 1024) + "k )</div>";\n\n    html += "<table id=\\"sectionBinary\\" class=\\"table treetable\\">";\n    html += "<tr>";\n    html += "  <th>name</th>";\n    html += "  <th>size</th>";\n    html += "  <th>%</th>";\n    html += "</tr>";\n    let sizeUnknown = sizeBin;\n    for (let i in sizes)\n    {\n        // html+=i+\':\'+Math.round(sizes[i]/1024);\n        html += "<tr>";\n        html += "<td>" + i + "</td>";\n        html += "<td>" + readableSize(sizes[i]) + " </td>";\n        html += "<td>" + Math.round(sizes[i] / sizeBin * 100) + "% </td>";\n        html += "<tr>";\n        sizeUnknown -= sizes[i];\n    }\n\n    if (sizeUnknown != 0)\n    {\n        html += "<tr>";\n        html += "<td>unknown</td>";\n        html += "<td>" + readableSize(sizeUnknown) + " </td>";\n        html += "<td>" + Math.round(sizeUnknown / sizeBin * 100) + "% </td>";\n        html += "<tr>";\n    }\n\n    html += "</table>";\n    html += "</div>";\n\n    tab = new CABLES.UI.Tab("GLTF " + CABLES.basename(inFile.get()), { "icon": "cube", "infotext": "tab_gltf", "padding": true, "singleton": true });\n    gui.mainTabs.addTab(tab, true);\n\n    tab.addEventListener("close", closeTab);\n    tab.html(html);\n\n    CABLES.UI.Collapsable.setup(ele.byId("groupNodes"), ele.byId("sectionNodes"), false);\n    CABLES.UI.Collapsable.setup(ele.byId("groupMaterials"), ele.byId("materialtable"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupAnims"), ele.byId("sectionAnim"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupMeshes"), ele.byId("meshestable"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupCameras"), ele.byId("sectionCameras"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupImages"), ele.byId("sectionImages"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupSkins"), ele.byId("sectionSkins"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupBinary"), ele.byId("sectionBinary"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupTiming"), ele.byId("sectionTiming"), true);\n\n    gui.maintabPanel.show(true);\n}\n\nfunction readableSize(n)\n{\n    if (n > 1024) return Math.round(n / 1024) + " kb";\n    if (n > 1024 * 500) return Math.round(n / 1024) + " mb";\n    else return n + " bytes";\n}\n',inc_skin_js:'const GltfSkin = class\n{\n    constructor(node)\n    {\n        this._mod = null;\n        this._node = node;\n        this._lastTime = 0;\n        this._matArr = [];\n        this._m = mat4.create();\n        this._invBindMatrix = mat4.create();\n        this.identity = true;\n    }\n\n    renderFinish(cgl)\n    {\n        cgl.popModelMatrix();\n        this._mod.unbind();\n    }\n\n    renderStart(cgl, time)\n    {\n        if (!this._mod)\n        {\n            this._mod = new CGL.ShaderModifier(cgl, op.name + this._node.name);\n\n            this._mod.addModule({\n                "priority": -2,\n                "name": "MODULE_VERTEX_POSITION",\n                "srcHeadVert": attachments.skin_head_vert || "",\n                "srcBodyVert": attachments.skin_vert || ""\n            });\n\n            this._mod.addUniformVert("m4[]", "MOD_boneMats", []);// bohnenmatze\n            const tr = vec3.create();\n        }\n\n        const skinIdx = this._node.skin;\n        const arrLength = gltf.json.skins[skinIdx].joints.length * 16;\n\n        // if (this._lastTime != time || !time)\n        {\n            // this._lastTime=inTime.get();\n            if (this._matArr.length != arrLength) this._matArr.length = arrLength;\n\n            for (let i = 0; i < gltf.json.skins[skinIdx].joints.length; i++)\n            {\n                const i16 = i * 16;\n                const jointIdx = gltf.json.skins[skinIdx].joints[i];\n                const nodeJoint = gltf.nodes[jointIdx];\n\n                for (let j = 0; j < 16; j++)\n                    this._invBindMatrix[j] = gltf.accBuffers[gltf.json.skins[skinIdx].inverseBindMatrices][i16 + j];\n\n                mat4.mul(this._m, nodeJoint.modelMatAbs(), this._invBindMatrix);\n\n                for (let j = 0; j < this._m.length; j++) this._matArr[i16 + j] = this._m[j];\n            }\n\n            this._mod.setUniformValue("MOD_boneMats", this._matArr);\n            this._lastTime = time;\n        }\n\n        this._mod.define("SKIN_NUM_BONES", gltf.json.skins[skinIdx].joints.length);\n        this._mod.bind();\n\n        // draw mesh...\n        cgl.pushModelMatrix();\n        if (this.identity)mat4.identity(cgl.mMatrix);\n    }\n};\n',inc_targets_js:'const GltfTargetsRenderer = class\n{\n    constructor(mesh)\n    {\n        this.mesh = mesh;\n        this.tex = null;\n        this.numRowsPerTarget = 0;\n\n        this.makeTex(mesh.geom);\n    }\n\n    renderFinish(cgl)\n    {\n        cgl.popModelMatrix();\n        this._mod.unbind();\n    }\n\n    renderStart(cgl, time)\n    {\n        if (!this._mod)\n        {\n            this._mod = new CGL.ShaderModifier(cgl, "gltftarget");\n\n            this._mod.addModule({\n                "priority": -2,\n                "name": "MODULE_VERTEX_POSITION",\n                "srcHeadVert": attachments.targets_head_vert || "",\n                "srcBodyVert": attachments.targets_vert || ""\n            });\n\n            this._mod.addUniformVert("4f", "MOD_targetTexInfo", [0, 0, 0, 0]);\n            this._mod.addUniformVert("t", "MOD_targetTex", 1);\n            this._mod.addUniformVert("f[]", "MOD_weights", []);\n\n            const tr = vec3.create();\n        }\n\n        this._mod.pushTexture("MOD_targetTex", this.tex);\n        if (this.tex && this.mesh.weights)\n        {\n            this._mod.setUniformValue("MOD_weights", this.mesh.weights);\n            this._mod.setUniformValue("MOD_targetTexInfo", [this.tex.width, this.tex.height, this.numRowsPerTarget, this.mesh.weights.length]);\n\n            this._mod.define("MOD_NUM_WEIGHTS", Math.max(1, this.mesh.weights.length));\n        }\n        else\n        {\n            this._mod.define("MOD_NUM_WEIGHTS", 1);\n        }\n        this._mod.bind();\n\n        // draw mesh...\n        cgl.pushModelMatrix();\n        if (this.identity)mat4.identity(cgl.mMatrix);\n    }\n\n    makeTex(geom)\n    {\n        if (!geom.morphTargets || !geom.morphTargets.length) return;\n\n        let w = geom.morphTargets[0].vertices.length / 3;\n        let h = 0;\n        this.numRowsPerTarget = 0;\n\n        if (geom.morphTargets[0].vertices && geom.morphTargets[0].vertices.length) this.numRowsPerTarget++;\n        if (geom.morphTargets[0].vertexNormals && geom.morphTargets[0].vertexNormals.length) this.numRowsPerTarget++;\n        if (geom.morphTargets[0].tangents && geom.morphTargets[0].tangents.length) this.numRowsPerTarget++;\n        if (geom.morphTargets[0].bitangents && geom.morphTargets[0].bitangents.length) this.numRowsPerTarget++;\n\n        h = geom.morphTargets.length * this.numRowsPerTarget;\n\n        // console.log("this.numRowsPerTarget", this.numRowsPerTarget);\n\n        const pixels = new Float32Array(w * h * 4);\n        let row = 0;\n\n        for (let i = 0; i < geom.morphTargets.length; i++)\n        {\n            if (geom.morphTargets[i].vertices && geom.morphTargets[i].vertices.length)\n            {\n                for (let j = 0; j < geom.morphTargets[i].vertices.length; j += 3)\n                {\n                    pixels[((row * w) + (j / 3)) * 4 + 0] = geom.morphTargets[i].vertices[j + 0];\n                    pixels[((row * w) + (j / 3)) * 4 + 1] = geom.morphTargets[i].vertices[j + 1];\n                    pixels[((row * w) + (j / 3)) * 4 + 2] = geom.morphTargets[i].vertices[j + 2];\n                    pixels[((row * w) + (j / 3)) * 4 + 3] = 1;\n                }\n                row++;\n            }\n\n            if (geom.morphTargets[i].vertexNormals && geom.morphTargets[i].vertexNormals.length)\n            {\n                for (let j = 0; j < geom.morphTargets[i].vertexNormals.length; j += 3)\n                {\n                    pixels[(row * w + j / 3) * 4 + 0] = geom.morphTargets[i].vertexNormals[j + 0];\n                    pixels[(row * w + j / 3) * 4 + 1] = geom.morphTargets[i].vertexNormals[j + 1];\n                    pixels[(row * w + j / 3) * 4 + 2] = geom.morphTargets[i].vertexNormals[j + 2];\n                    pixels[(row * w + j / 3) * 4 + 3] = 1;\n                }\n\n                row++;\n            }\n\n            if (geom.morphTargets[i].tangents && geom.morphTargets[i].tangents.length)\n            {\n                for (let j = 0; j < geom.morphTargets[i].tangents.length; j += 3)\n                {\n                    pixels[(row * w + j / 3) * 4 + 0] = geom.morphTargets[i].tangents[j + 0];\n                    pixels[(row * w + j / 3) * 4 + 1] = geom.morphTargets[i].tangents[j + 1];\n                    pixels[(row * w + j / 3) * 4 + 2] = geom.morphTargets[i].tangents[j + 2];\n                    pixels[(row * w + j / 3) * 4 + 3] = 1;\n                }\n                row++;\n            }\n\n            if (geom.morphTargets[i].bitangents && geom.morphTargets[i].bitangents.length)\n            {\n                for (let j = 0; j < geom.morphTargets[i].bitangents.length; j += 3)\n                {\n                    pixels[(row * w + j / 3) * 4 + 0] = geom.morphTargets[i].bitangents[j + 0];\n                    pixels[(row * w + j / 3) * 4 + 1] = geom.morphTargets[i].bitangents[j + 1];\n                    pixels[(row * w + j / 3) * 4 + 2] = geom.morphTargets[i].bitangents[j + 2];\n                    pixels[(row * w + j / 3) * 4 + 3] = 1;\n                }\n                row++;\n            }\n        }\n\n        this.tex = new CGL.Texture(cgl, { "isFloatingPointTexture": true, "name": "targetsTexture" });\n\n        this.tex.initFromData(pixels, w, h, CGL.Texture.FILTER_LINEAR, CGL.Texture.WRAP_REPEAT);\n\n        // console.log("morphTargets generated texture", w, h);\n    }\n};\n',skin_vert:"int index=int(attrJoints.x);\nvec4 newPos = (MOD_boneMats[index] * pos) * attrWeights.x;\nvec3 newNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.x).xyz);\n\nindex=int(attrJoints.y);\nnewPos += (MOD_boneMats[index] * pos) * attrWeights.y;\nnewNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.y).xyz)+newNorm;\n\nindex=int(attrJoints.z);\nnewPos += (MOD_boneMats[index] * pos) * attrWeights.z;\nnewNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.z).xyz)+newNorm;\n\nindex=int(attrJoints.w);\nnewPos += (MOD_boneMats[index] * pos) * attrWeights.w ;\nnewNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.w).xyz)+newNorm;\n\npos=newPos;\n\nnorm=normalize(newNorm.xyz);\n\n\n",skin_head_vert:"\nIN vec4 attrWeights;\nIN vec4 attrJoints;\nUNI mat4 MOD_boneMats[SKIN_NUM_BONES];\n",targets_vert:"\n\nfloat MOD_width=MOD_targetTexInfo.x;\nfloat MOD_height=MOD_targetTexInfo.y;\nfloat MOD_numTargets=MOD_targetTexInfo.w;\nfloat MOD_numLinesPerTarget=MOD_height/MOD_numTargets;\n\nfloat halfpix=(1.0/MOD_width)*0.5;\nfloat halfpixy=(1.0/MOD_height)*0.5;\n\nfloat x=(attrVertIndex)/MOD_width+halfpix;\n\nvec3 off=vec3(0.0);\n\nfor(float i=0.0;i<MOD_numTargets;i+=1.0)\n{\n    float y=1.0-((MOD_numLinesPerTarget*i)/MOD_height+halfpixy);\n    vec2 coord=vec2(x,y);\n    vec3 targetXYZ = texture(MOD_targetTex,coord).xyz;\n\n    off+=(targetXYZ*MOD_weights[int(i)]);\n\n\n\n    coord.y+=1.0/MOD_height; // normals are in next row\n    vec3 targetNormal = texture(MOD_targetTex,coord).xyz;\n    norm+=targetNormal*MOD_weights[int(i)];\n\n\n}\n\n// norm=normalize(norm);\npos.xyz+=off;\n",targets_head_vert:"\nUNI float MOD_weights[MOD_NUM_WEIGHTS];\n"};const k=class{constructor(e,t){this.node=t;this.name=t.name;this.config=e.json.cameras[t.camera];this.pos=vec3.create();this.quat=quat.create();this.vCenter=vec3.create();this.vUp=vec3.create();this.vMat=mat4.create()}updateAnim(e){if(this.node&&this.node._animTrans){vec3.set(this.pos,this.node._animTrans[0].getValue(e),this.node._animTrans[1].getValue(e),this.node._animTrans[2].getValue(e));quat.set(this.quat,this.node._animRot[0].getValue(e),this.node._animRot[1].getValue(e),this.node._animRot[2].getValue(e),this.node._animRot[3].getValue(e))}}start(e){if(f.frameStore.shadowPass)return;this.updateAnim(e);const t=f.getViewPort()[2]/f.getViewPort()[3];f.pushPMatrix();f.pushViewMatrix();let n=mat4.create();mat4.invert(n,this.node.modelMatAbs());this.vMat=n;mat4.identity(f.vMatrix);mat4.mul(f.vMatrix,f.vMatrix,n)}end(){if(f.frameStore.shadowPass)return;f.popPMatrix();f.popViewMatrix()}};const A=true;const B=class{constructor(){this.json={};this.accBuffers=[];this.meshes=[];this.nodes=[];this.shaders=[];this.timing=[];this.cams=[];this.startTime=performance.now();this.bounds=new CABLES.CG.BoundingBox;this.loaded=Date.now();this.accBuffersDelete=[]}getNode(t){for(let e=0;e<this.nodes.length;e++){if(this.nodes[e].name==t)return this.nodes[e]}}unHideAll(){for(let e=0;e<this.nodes.length;e++){this.nodes[e].unHide()}}};function I(e){if(window.TextDecoder)return new TextDecoder("utf-8").decode(e);let t,n,a,i;let r,o;t="";a=e.length;n=0;while(n<a){i=e[n++];switch(i>>4){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:t+=String.fromCharCode(i);break;case 12:case 13:r=e[n++];t+=String.fromCharCode((i&31)<<6|r&63);break;case 14:r=e[n++];o=e[n++];t+=String.fromCharCode((i&15)<<12|(r&63)<<6|(o&63)<<0);break}}return t}function T(e,t,n,a){const i={};if(a>=e.byteLength){return}i.size=e.getUint32(a+0,A);i.type=I(t.subarray(a+4,a+4+4));if(i.type=="BIN\0"){i.dataView=new DataView(n,a+8,i.size)}else if(i.type=="JSON"){const r=I(t.subarray(a+8,a+8+i.size));try{const o=JSON.parse(r);i.data=o;oe.set(o.asset.generator)}catch(e){}}else{O.warn("unknown type",i.type)}return i}function D(t){const a={};for(let e=0;e<t.json.animations.length;e++){const i=t.json.animations[e];i.name=i.name||"unknown";for(let e=0;e<i.channels.length;e++){const r=i.channels[e];const o=t.nodes[r.target.node];const s=i.samplers[r.sampler];const n=t.json.accessors[s.input];const l=t.accBuffers[s.input];const u=t.json.accessors[s.output];const m=t.accBuffers[s.output];t.accBuffersDelete.push(s.output,s.input);if(l&&m){let n=1;if(u.type==="VEC2")n=2;else if(u.type==="VEC3")n=3;else if(u.type==="VEC4")n=4;else if(u.type==="SCALAR"){n=m.length/l.length}else O.log("[] UNKNOWN accOut.type",u.type);const c=[];a[i.name]=true;for(let e=0;e<n;e++){const d=new CABLES.Anim;c.push(d)}if(s.interpolation==="LINEAR"){}else if(s.interpolation==="STEP")for(let e=0;e<n;e++)c[e].defaultEasing=CABLES.EASING_ABSOLUTE;else if(s.interpolation==="CUBICSPLINE")for(let e=0;e<n;e++)c[e].defaultEasing=CABLES.EASING_CUBICSPLINE;else O.warn("unknown interpolation",s.interpolation);if(l[0]!==0)for(let e=0;e<n;e++)c[e].setValue(0,m[0*n+e]);for(let t=0;t<l.length;t++){x=Math.max(l[t],x);for(let e=0;e<n;e++){if(c[e].defaultEasing===CABLES.EASING_CUBICSPLINE){const h=t*n*3+e;const f=c[e].setValue(l[t],m[h+n]);f.bezTangIn=m[h];f.bezTangOut=m[h+n*2]}else{c[e].setValue(l[t],m[t*n+e])}}}o.setAnim(r.target.path,i.name,c)}else{O.warn("loadAmins bufferIn undefined ",l===undefined);O.warn("loadAmins bufferOut undefined ",m===undefined);O.warn("loadAmins ",s,u);O.warn("loadAmins num accBuffers",t.accBuffers.length);O.warn("loadAmins num accessors",t.json.accessors.length)}}}t.uniqueAnimNames=a;de.setRef(Object.keys(a))}function G(n){if(!n||!n.json.cameras)return;n.cameras=n.cameras||[];for(let t=0;t<n.nodes.length;t++){if(n.nodes[t].hasOwnProperty("camera")){const e=new k(n,n.nodes[t]);n.cameras.push(e)}}}function U(){if(!window.DracoDecoder){setTimeout(()=>{U()},100)}w()}function F(e){const t=8;let i=0,n=0;const r=new B;r.timing.push(["Start parsing",Math.round(performance.now()-r.startTime)]);if(!e)return;const a=new Uint8Array(e);let o=0;const s=I(a.subarray(o,4));o+=4;if(s!="glTF")return;r.timing.push(["dataview",Math.round(performance.now()-r.startTime)]);const l=new DataView(e);const u=l.getUint32(o,A);o+=4;const m=l.getUint32(o,A);o+=4;se.set(u);const c=[];r.chunks=c;c.push(T(l,a,e,o));o+=c[0].size+t;r.json=c[0].data;r.cables={fileUrl:C.get(),shortFileName:CABLES.basename(C.get())};ce.setRef(r.json);le.setRef(r.json.extensionsUsed||[]);let d=T(l,a,e,o);while(d){c.push(d);o+=d.size+t;d=T(l,a,e,o)}r.chunks=c;const h=c[0].data.bufferViews;const f=c[0].data.accessors;r.timing.push(["Parse buffers",Math.round(performance.now()-r.startTime)]);if(r.json.extensionsUsed&&r.json.extensionsUsed.indexOf("KHR_draco_mesh_compression")>-1){if(!window.DracoDecoder){O.setUiError("gltfdraco","GLTF draco compression lib not found / add draco op to your patch!");U();return r}else{r.useDraco=true}}O.setUiError("gltfdraco",null);if(h){for(n=0;n<f.length;n++){const p=f[n];const g=h[p.bufferView];let a=0;if(p.type=="SCALAR")a=1;else if(p.type=="VEC2")a=2;else if(p.type=="VEC3")a=3;else if(p.type=="VEC4")a=4;else if(p.type=="MAT4")a=16;else console.error("unknown accessor type",p.type);if(c[1].dataView){if(g){const v=p.count*a;let e=(g.byteOffset||0)+(p.byteOffset||0);let t=g.byteStride||0;let n=null;if(p.componentType==5126||p.componentType==5125){t=t||4;const b=p.componentType==5125;if(b)n=new Uint32Array(v);else n=new Float32Array(v);n.cblStride=a;for(i=0;i<v;i++){if(b)n[i]=c[1].dataView.getUint32(e,A);else n[i]=c[1].dataView.getFloat32(e,A);if(t!=4&&(i+1)%a===0)e+=t-a*4;e+=4}}else if(p.componentType==5123){t=t||2;n=new Uint16Array(v);n.cblStride=t;for(i=0;i<v;i++){n[i]=c[1].dataView.getUint16(e,A);if(t!=2&&(i+1)%a===0)e+=t-a*2;e+=2}}else if(p.componentType==5121){t=t||1;n=new Uint8Array(v);n.cblStride=t;for(i=0;i<v;i++){n[i]=c[1].dataView.getUint8(e,A);if(t!=1&&(i+1)%a===0)e+=t-a*1;e+=1}}else{console.error("unknown component type",p.componentType)}r.accBuffers.push(n)}else{}}}}r.timing.push(["Parse mesh groups",Math.round(performance.now()-r.startTime)]);r.json.meshes=r.json.meshes||[];if(r.json.meshes){for(n=0;n<r.json.meshes.length;n++){const x=new z(r,r.json.meshes[n]);r.meshes.push(x)}}r.timing.push(["Parse nodes",Math.round(performance.now()-r.startTime)]);for(n=0;n<r.json.nodes.length;n++){if(r.json.nodes[n].children)for(i=0;i<r.json.nodes[n].children.length;i++){r.json.nodes[r.json.nodes[n].children[i]].isChild=true}}for(n=0;n<r.json.nodes.length;n++){const _=new X(r.json.nodes[n],r);r.nodes.push(_)}for(n=0;n<r.nodes.length;n++){const _=r.nodes[n];if(!_.children)continue;for(let e=0;e<_.children.length;e++){r.nodes[_.children[e]].parent=_}}for(n=0;n<r.nodes.length;n++){r.nodes[n].initSkin()}M=true;r.timing.push(["load anims",Math.round(performance.now()-r.startTime)]);if(r.json.animations)D(r);r.timing.push(["load cameras",Math.round(performance.now()-r.startTime)]);if(r.json.cameras)G(r);r.timing.push(["finished",Math.round(performance.now()-r.startTime)]);return r}let V=class{constructor(e,n,r,o){this.POINTS=0;this.LINES=1;this.LINE_LOOP=2;this.LINE_STRIP=3;this.TRIANGLES=4;this.TRIANGLE_STRIP=5;this.TRIANGLE_FAN=6;this.test=0;this.name=e;this.submeshIndex=0;this.material=n.material;this.mesh=null;this.geom=new CGL.Geometry("gltf_"+this.name);this.geom.verticesIndices=[];this.bounds=null;this.primitive=4;this.morphTargetsRenderMod=null;this.weights=n.weights;if(n.hasOwnProperty("mode"))this.primitive=n.mode;if(n.hasOwnProperty("indices"))this.geom.verticesIndices=r.accBuffers[n.indices];r.loadingMeshes=r.loadingMeshes||0;r.loadingMeshes++;this.materialJson=this._matPbrMetalness=this._matPbrRoughness=this._matDiffuseColor=null;if(r.json.materials){if(this.material!=-1)this.materialJson=r.json.materials[this.material];if(this.materialJson&&this.materialJson.pbrMetallicRoughness){if(!this.materialJson.pbrMetallicRoughness.hasOwnProperty("baseColorFactor")){this._matDiffuseColor=[1,1,1,1]}else{this._matDiffuseColor=this.materialJson.pbrMetallicRoughness.baseColorFactor}this._matDiffuseColor=this.materialJson.pbrMetallicRoughness.baseColorFactor;if(!this.materialJson.pbrMetallicRoughness.hasOwnProperty("metallicFactor")){this._matPbrMetalness=1}else{this._matPbrMetalness=this.materialJson.pbrMetallicRoughness.metallicFactor||null}if(!this.materialJson.pbrMetallicRoughness.hasOwnProperty("roughnessFactor")){this._matPbrRoughness=1}else{this._matPbrRoughness=this.materialJson.pbrMetallicRoughness.roughnessFactor||null}}}if(r.useDraco&&n.extensions.KHR_draco_mesh_compression){const a=r.chunks[0].data.bufferViews[n.extensions.KHR_draco_mesh_compression.bufferView];const i=a.byteLength;const s=new Int8Array(i);let t=a.byteOffset||0;for(let e=0;e<i;e++){s[e]=r.chunks[1].dataView.getInt8(t,A);t++}const l=window.DracoDecoder;l.decodeGeometry(s.buffer,t=>{const n=new CGL.Geometry("draco mesh "+e);for(let e=0;e<t.attributes.length;e++){const a=t.attributes[e];if(a.name==="position")n.vertices=a.array;else if(a.name==="normal")n.vertexNormals=a.array;else if(a.name==="uv")n.texCoords=a.array;else if(a.name==="color")n.vertexColors=this.calcVertexColors(a.array);else if(a.name==="joints")n.setAttribute("attrJoints",Array.from(a.array),4);else if(a.name==="weights"){const i=new Float32Array(a.array.length/a.itemSize*4);for(let t=0;t<a.array.length/a.itemSize;t++){i[t*4]=i[t*4+1]=i[t*4+2]=i[t*4+3]=0;for(let e=0;e<a.itemSize;e++)i[t*4+e]=a.array[t*a.itemSize+e]}n.setAttribute("attrWeights",i,4)}else O.logWarn("unknown draco attrib",a)}t.attributes=null;n.verticesIndices=t.index.array;this.setGeom(n);this.mesh=null;r.loadingMeshes--;r.timing.push(["draco decode",Math.round(performance.now()-r.startTime)]);if(o)o(this)},e=>{O.logError(e)})}else{r.loadingMeshes--;this.fillGeomAttribs(r,this.geom,n.attributes);if(n.targets){for(let e=0;e<n.targets.length;e++){const t=new CGL.Geometry("gltf_target_"+e);this.fillGeomAttribs(r,t,n.targets[e],false);this.geom.morphTargets.push(t)}}if(o)o(this)}}_linearToSrgb(e){if(e<=0)return 0;else if(e>=1)return 1;else if(e<.0031308)return e*12.92;else return e**(1/2.2)*1.055-.055}calcVertexColors(n,e){let a=null;if(n instanceof Float32Array){let t=false;for(let e=0;e<n.length;e++){if(n[e]>1){t=true;continue}}if(t)for(let e=0;e<n.length;e++)n[e]/=65535;a=n}else if(n instanceof Uint16Array){const t=new Float32Array(n.length);for(let e=0;e<n.length;e++)t[e]=n[e]/65535;a=t}else a=n;for(let e=0;e<a.length;e++){a[e]=this._linearToSrgb(a[e])}console.log("arr.cblStride",n.cblStride);if(n.cblStride==3){const i=new Float32Array(a.length/3*4);for(let e=0;e<a.length/3;e++){i[e*4+0]=a[e*3+0];i[e*4+1]=a[e*3+1];i[e*4+2]=a[e*3+2];i[e*4+3]=1}a=i}return a}fillGeomAttribs(e,t,n,a){if(n.hasOwnProperty("POSITION"))t.vertices=e.accBuffers[n.POSITION];if(n.hasOwnProperty("NORMAL"))t.vertexNormals=e.accBuffers[n.NORMAL];if(n.hasOwnProperty("TANGENT"))t.tangents=e.accBuffers[n.TANGENT];if(n.hasOwnProperty("COLOR_0"))t.vertexColors=this.calcVertexColors(e.accBuffers[n.COLOR_0],e.accBuffers[n.COLOR_0].type);if(n.hasOwnProperty("COLOR_1"))t.setAttribute("attrVertColor1",this.calcVertexColors(e.accBuffers[n.COLOR_1]),e.accBuffers[n.COLOR_1].type);if(n.hasOwnProperty("COLOR_2"))t.setAttribute("attrVertColor2",this.calcVertexColors(e.accBuffers[n.COLOR_2]),e.accBuffers[n.COLOR_2].type);if(n.hasOwnProperty("COLOR_3"))t.setAttribute("attrVertColor3",this.calcVertexColors(e.accBuffers[n.COLOR_3]),e.accBuffers[n.COLOR_3].type);if(n.hasOwnProperty("COLOR_4"))t.setAttribute("attrVertColor4",this.calcVertexColors(e.accBuffers[n.COLOR_4]),e.accBuffers[n.COLOR_4].type);if(n.hasOwnProperty("TEXCOORD_0"))t.texCoords=e.accBuffers[n.TEXCOORD_0];if(n.hasOwnProperty("TEXCOORD_1"))t.setAttribute("attrTexCoord1",e.accBuffers[n.TEXCOORD_1],2);if(n.hasOwnProperty("TEXCOORD_2"))t.setAttribute("attrTexCoord2",e.accBuffers[n.TEXCOORD_2],2);if(n.hasOwnProperty("TEXCOORD_3"))t.setAttribute("attrTexCoord3",e.accBuffers[n.TEXCOORD_3],2);if(n.hasOwnProperty("TEXCOORD_4"))t.setAttribute("attrTexCoord4",e.accBuffers[n.TEXCOORD_4],2);if(n.hasOwnProperty("WEIGHTS_0")){t.setAttribute("attrWeights",e.accBuffers[n.WEIGHTS_0],4)}if(n.hasOwnProperty("JOINTS_0")){if(!e.accBuffers[n.JOINTS_0])console.log("no !gltf.accBuffers[attribs.JOINTS_0]");t.setAttribute("attrJoints",e.accBuffers[n.JOINTS_0],4)}if(n.hasOwnProperty("POSITION"))e.accBuffersDelete.push(n.POSITION);if(n.hasOwnProperty("NORMAL"))e.accBuffersDelete.push(n.NORMAL);if(n.hasOwnProperty("TEXCOORD_0"))e.accBuffersDelete.push(n.TEXCOORD_0);if(n.hasOwnProperty("TANGENT"))e.accBuffersDelete.push(n.TANGENT);if(n.hasOwnProperty("COLOR_0"))e.accBuffersDelete.push(n.COLOR_0);if(n.hasOwnProperty("COLOR_0"))e.accBuffersDelete.push(n.COLOR_0);if(n.hasOwnProperty("COLOR_1"))e.accBuffersDelete.push(n.COLOR_1);if(n.hasOwnProperty("COLOR_2"))e.accBuffersDelete.push(n.COLOR_2);if(n.hasOwnProperty("COLOR_3"))e.accBuffersDelete.push(n.COLOR_3);if(n.hasOwnProperty("TEXCOORD_1"))e.accBuffersDelete.push(n.TEXCOORD_1);if(n.hasOwnProperty("TEXCOORD_2"))e.accBuffersDelete.push(n.TEXCOORD_2);if(n.hasOwnProperty("TEXCOORD_3"))e.accBuffersDelete.push(n.TEXCOORD_3);if(n.hasOwnProperty("TEXCOORD_4"))e.accBuffersDelete.push(n.TEXCOORD_4);if(a!==false)if(t&&t.verticesIndices)this.setGeom(t)}setGeom(n){if(te.get()=="X-ZY"){for(let t=0;t<n.vertexNormals.length;t+=3){let e=n.vertexNormals[t+2];n.vertexNormals[t+2]=n.vertexNormals[t+1];n.vertexNormals[t+1]=-e}}if(ne.get()=="XZ-Y"){for(let t=0;t<n.vertices.length;t+=3){let e=n.vertices[t+2];n.vertices[t+2]=-n.vertices[t+1];n.vertices[t+1]=e}}if(this.primitive==this.TRIANGLES){if(m.get()=="Force Smooth"||m.get()==false)n.calculateNormals();else if(!n.vertexNormals.length&&m.get()=="Auto")n.calculateNormals({smooth:false});if((!n.biTangents||n.biTangents.length==0)&&n.tangents){const t=vec3.create();const e=vec3.create();const a=n.tangents;n.tangents=new Float32Array(a.length/4*3);n.biTangents=new Float32Array(a.length/4*3);for(let e=0;e<a.length;e+=4){const i=e/4*3;vec3.cross(t,[n.vertexNormals[i],n.vertexNormals[i+1],n.vertexNormals[i+2]],[a[e],a[e+1],a[e+2]]);vec3.div(t,t,[a[e+3],a[e+3],a[e+3]]);vec3.normalize(t,t);n.biTangents[i+0]=t[0];n.biTangents[i+1]=t[1];n.biTangents[i+2]=t[2];n.tangents[i+0]=a[e+0];n.tangents[i+1]=a[e+1];n.tangents[i+2]=a[e+2]}}if(n.tangents.length===0||m.get()!="Never"){n.calcTangentsBitangents()}}this.geom=n;this.bounds=n.getBounds()}render(n,t,a){if(!this.mesh&&this.geom&&this.geom.verticesIndices){let e=this.geom;if(this.geom.vertices.length/3>64e3){e=this.geom.copy();e.unIndex(false,true)}let t;if(n.gl){if(this.primitive==this.TRIANGLES)t=n.gl.TRIANGLES;else if(this.primitive==this.LINES)t=n.gl.LINES;else if(this.primitive==this.LINE_STRIP)t=n.gl.LINE_STRIP;else if(this.primitive==this.POINTS)t=n.gl.POINTS;else{O.logWarn("unknown primitive type",this)}}this.mesh=O.patch.cg.createMesh(e,{glPrimitive:t})}if(this.mesh){if(this.geom&&this.geom.morphTargets.length&&!this.morphTargetsRenderMod){this.mesh.addVertexNumbers=true;this.morphTargetsRenderMod=new Z(this)}let e=!t&&this.material!=-1&&y.shaders[this.material];if(a)e=false;if(e)n.pushShader(y.shaders[this.material]);const i=n.getShader()||{};const r=i.uniformColorDiffuse;const o=i.uniformPbrMetalness;const s=i.uniformPbrRoughness;if(!y.shaders[this.material]&&ie.get()){if(r&&this._matDiffuseColor){this._matDiffuseColorOrig=[r.getValue()[0],r.getValue()[1],r.getValue()[2],r.getValue()[3]];r.setValue(this._matDiffuseColor)}if(o)if(this._matPbrMetalness!=null){this._matPbrMetalnessOrig=o.getValue();o.setValue(this._matPbrMetalness)}else o.setValue(0);if(s)if(this._matPbrRoughness!=null){this._matPbrRoughnessOrig=s.getValue();s.setValue(this._matPbrRoughness)}else{s.setValue(0)}}if(this.morphTargetsRenderMod)this.morphTargetsRenderMod.renderStart(n,0);if(this.mesh){this.mesh.render(n.getShader(),t)}if(this.morphTargetsRenderMod)this.morphTargetsRenderMod.renderFinish(n);if(ie.get()){if(r&&this._matDiffuseColor)r.setValue(this._matDiffuseColorOrig);if(o&&this._matPbrMetalnessOrig!=undefined)o.setValue(this._matPbrMetalnessOrig);if(s&&this._matPbrRoughnessOrig!=undefined)s.setValue(this._matPbrRoughnessOrig)}if(e)n.popShader()}}};const z=class{constructor(t,n){this.bounds=new CABLES.CG.BoundingBox;this.meshes=[];this.name=n.name;const a=n.primitives;for(let e=0;e<a.length;e++){const i=new V(this.name,a[e],t,e=>{e.extras=n.extras;this.bounds.apply(e.bounds)});i.submeshIndex=e;this.meshes.push(i)}}render(t,n,a,i,r){for(let e=0;e<this.meshes.length;e++){const o=y.shaders[this.meshes[e].material];if(!n&&o)t.pushShader(y.shaders[this.meshes[e].material]);if(a)a.renderStart(t,i);if(r)this.meshes[e].weights=r;this.meshes[e].render(t,n,a,i);if(a)a.renderFinish(t);if(!n&&o)t.popShader()}}};const X=class{constructor(e,t){this.isChild=e.isChild||false;this.name=e.name;if(e.hasOwnProperty("camera"))this.camera=e.camera;this.hidden=false;this.mat=mat4.create();this._animActions={};this.animWeights=[];this._animMat=mat4.create();this._tempMat=mat4.create();this._tempQuat=quat.create();this._tempRotmat=mat4.create();this.mesh=null;this.children=[];this._node=e;this._gltf=t;this.absMat=mat4.create();this.addTranslate=null;this._tempAnimScale=null;this.addMulMat=null;this.updateMatrix();this.skinRenderer=null;this.copies=[]}get skin(){if(this._node.hasOwnProperty("skin"))return this._node.skin;else return-1}copy(){this.isCopy=true;const e=new X(this._node,this._gltf);e.copyOf=this;e._animActions=this._animActions;e.children=this.children;if(this.skin)e.skinRenderer=new Y(this);this.updateMatrix();return e}hasSkin(){if(this._node.hasOwnProperty("skin"))return this._gltf.json.skins[this._node.skin].name||"unknown";return false}initSkin(){if(this.skin>-1){this.skinRenderer=new Y(this)}}updateMatrix(){mat4.identity(this.mat);if(this._node.translation)mat4.translate(this.mat,this.mat,this._node.translation);if(this._node.rotation){const e=mat4.create();this._rot=this._node.rotation;mat4.fromQuat(e,this._node.rotation);mat4.mul(this.mat,this.mat,e)}if(this._node.scale){this._scale=this._node.scale;mat4.scale(this.mat,this.mat,this._scale)}if(this._node.hasOwnProperty("mesh")){this.mesh=this._gltf.meshes[this._node.mesh];if(this.isCopy){}}if(this._node.children){for(let e=0;e<this._node.children.length;e++){this._gltf.json.nodes[e].isChild=true;if(this._gltf.nodes[this._node.children[e]])this._gltf.nodes[this._node.children[e]].isChild=true;this.children.push(this._node.children[e])}}}unHide(){this.hidden=false;for(let e=0;e<this.children.length;e++)if(this.children[e].unHide)this.children[e].unHide()}calcBounds(t,e,n){const a=mat4.create();if(e)mat4.copy(a,e);if(this.mat)mat4.mul(a,a,this.mat);if(this.mesh){const i=this.mesh.bounds.copy();i.mulMat4(a);n.apply(i);if(n.changed){b.push(i._min[0]||0,i._min[1]||0,i._min[2]||0,i._max[0]||0,i._max[1]||0,i._max[2]||0)}}for(let e=0;e<this.children.length;e++){if(t.nodes[this.children[e]]&&t.nodes[this.children[e]].calcBounds){const r=t.nodes[this.children[e]].calcBounds(t,a,n);n.apply(r)}}if(n.changed)return n;else return null}setAnimAction(t){if(!t)return;this._currentAnimaction=t;if(t&&!this._animActions[t]){return null}for(let e in this._animActions[t]){if(e=="translation")this._animTrans=this._animActions[t][e];else if(e=="rotation")this._animRot=this._animActions[t][e];else if(e=="scale")this._animScale=this._animActions[t][e];else if(e=="weights")this.animWeights=this._animActions[t][e];else console.log("[gltfNode] unknown anim path",e,this._animActions[t][e])}}setAnim(e,t,n){if(!e||!t||!n)return;this._animActions[t]=this._animActions[t]||{};if(this._animActions[t][e])O.log("[gltfNode] animation action path already exists",t,e,this._animActions[t][e]);this._animActions[t][e]=n;if(e=="translation")this._animTrans=n;else if(e=="rotation")this._animRot=n;else if(e=="scale")this._animScale=n;else if(e=="weights"){this.animWeights=this._animActions[t][e]}else console.warn("unknown anim path",e,n)}modelMatLocal(){return this._animMat||this.mat}modelMatAbs(){return this.absMat}transform(e,n){if(!n&&n!=0)n=E;this._lastTimeTrans=n;be++;if(!this._animTrans&&!this._animRot&&!this._animScale){mat4.mul(e.mMatrix,e.mMatrix,this.mat);this._animMat=null}else{this._animMat=this._animMat||mat4.create();mat4.identity(this._animMat);const t=true;if(t&&this._animTrans){mat4.translate(this._animMat,this._animMat,[this._animTrans[0].getValue(n),this._animTrans[1].getValue(n),this._animTrans[2].getValue(n)])}else if(this._node.translation)mat4.translate(this._animMat,this._animMat,this._node.translation);if(t&&this._animRot){if(this._animRot[0].defaultEasing==CABLES.EASING_LINEAR)CABLES.Anim.slerpQuaternion(n,this._tempQuat,this._animRot[0],this._animRot[1],this._animRot[2],this._animRot[3]);else if(this._animRot[0].defaultEasing==CABLES.EASING_ABSOLUTE){this._tempQuat[0]=this._animRot[0].getValue(n);this._tempQuat[1]=this._animRot[1].getValue(n);this._tempQuat[2]=this._animRot[2].getValue(n);this._tempQuat[3]=this._animRot[3].getValue(n)}else if(this._animRot[0].defaultEasing==CABLES.EASING_CUBICSPLINE){CABLES.Anim.slerpQuaternion(n,this._tempQuat,this._animRot[0],this._animRot[1],this._animRot[2],this._animRot[3])}mat4.fromQuat(this._tempMat,this._tempQuat);mat4.mul(this._animMat,this._animMat,this._tempMat)}else if(this._rot){mat4.fromQuat(this._tempRotmat,this._rot);mat4.mul(this._animMat,this._animMat,this._tempRotmat)}if(t&&this._animScale){if(!this._tempAnimScale)this._tempAnimScale=[1,1,1];this._tempAnimScale[0]=this._animScale[0].getValue(n);this._tempAnimScale[1]=this._animScale[1].getValue(n);this._tempAnimScale[2]=this._animScale[2].getValue(n);mat4.scale(this._animMat,this._animMat,this._tempAnimScale)}else if(this._scale)mat4.scale(this._animMat,this._animMat,this._scale);mat4.mul(e.mMatrix,e.mMatrix,this._animMat)}if(this.animWeights){this.weights=this.weights||[];let t="";for(let e=0;e<this.animWeights.length;e++){this.weights[e]=this.animWeights[e].getValue(n);t+=this.weights[e]+"/"}}if(this.addTranslate)mat4.translate(e.mMatrix,e.mMatrix,this.addTranslate);if(this.addMulMat)mat4.mul(e.mMatrix,e.mMatrix,this.addMulMat);mat4.copy(this.absMat,e.mMatrix)}render(t,n,a,i,r,o,s){if(!n)t.pushModelMatrix();if(s===undefined)s=y.time;if(!n||this.skinRenderer)this.transform(t,s);if(this.hidden&&!o){}else{if(this.skinRenderer){this.skinRenderer.time=s;if(!a)this.mesh.render(t,i,this.skinRenderer,s,this.weights)}else{if(this.mesh&&!a)this.mesh.render(t,i,null,s,this.weights)}}if(!r&&!this.hidden)for(let e=0;e<this.children.length;e++)if(y.nodes[this.children[e]])y.nodes[this.children[e]].render(t,n,a,i,r,o,s);if(!n)t.popModelMatrix()}};let _=null;function S(){if(_)gui.mainTabs.closeTab(_.id);_=null}function s(t){const n=[];for(let e=0;e<t.length;e++){n.push(Math.round(t[e]*1e3)/1e3)}return n.join(",")}function q(n,a,i){if(!y)return;n+='<tr class="row">';let r="";let o="";for(let t=1;t<i;t++){o+="&nbsp;&nbsp;&nbsp;";let e="identBg";if(t==1)e="identBgLevel0";r+='<td class="ident '+e+'" ><div style=""></div></td>'}let e=CABLES.uuid();n+=r;n+='<td colspan="'+(21-i)+'">';if(a.mesh&&a.mesh.meshes.length)n+='<span class="icon icon-cube"></span>&nbsp;';else n+='<span class="icon icon-box-select"></span> &nbsp;';n+=a.name+"</td><td></td>";if(a.mesh){n+="<td>";for(let e=0;e<a.mesh.meshes.length;e++){if(e>0)n+=", ";n+=a.mesh.meshes[e].name}n+="</td>";n+="<td>";n+=a.hasSkin()||"-";n+="</td>";n+="<td>";let t=0;for(let e=0;e<a.mesh.meshes.length;e++){if(t>0)n+=", ";if(y.json.materials&&a.mesh.meshes[e].hasOwnProperty("material")){if(y.json.materials[a.mesh.meshes[e].material]){n+=y.json.materials[a.mesh.meshes[e].material].name;t++}}}if(t==0)n+="none";n+="</td>"}else{n+="<td>-</td><td>-</td><td>-</td>"}n+="<td>";if(a._node.translation||a._node.rotation||a._node.scale){let e="";if(a._node.translation)e+="Translate: `"+s(a._node.translation)+"` || ";if(a._node.rotation)e+="Rotation: `"+s(a._node.rotation)+"` || ";if(a._node.scale)e+="Scale: `"+s(a._node.scale)+"` || ";n+='<span class="icon icon-gizmo info" data-info="'+e+'"></span> &nbsp;'}if(a._animRot||a._animScale||a._animTrans){let e="Animated: ";if(a._animRot)e+="Rot ";if(a._animScale)e+="Scale ";if(a._animTrans)e+="Trans ";n+='<span class="icon icon-clock info" data-info="'+e+'"></span>&nbsp;'}if(!a._node.translation&&!a._node.rotation&&!a._node.scale&&!a._animRot&&!a._animScale&&!a._animTrans)n+="-";n+="</td>";n+="<td>";let t="";if(a.hidden)t="node-hidden";n+="<a onclick=\"gui.corePatch().getOpById('"+O.id+"').exposeNode('"+a.name+"','transform')\" class=\"treebutton\">Transform</a>";n+=" <a onclick=\"gui.corePatch().getOpById('"+O.id+"').exposeNode('"+a.name+"','hierarchy')\" class=\"treebutton\">Hierarchy</a>";n+=" <a onclick=\"gui.corePatch().getOpById('"+O.id+"').exposeNode('"+a.name+'\')" class="treebutton">Node</a>';if(a.hasSkin())n+=" <a onclick=\"gui.corePatch().getOpById('"+O.id+"').exposeNode('"+a.name+'\',false,{skin:true});" class="treebutton">Skin</a>';n+="</td><td>";n+='&nbsp;<span class="icon iconhover icon-eye '+t+'" onclick="gui.corePatch().getOpById(\''+O.id+"').toggleNodeVisibility('"+a.name+"');this.classList.toggle('node-hidden');\"></span>";n+="</td>";n+="</tr>";if(a.children){for(let e=0;e<a.children.length;e++)n=q(n,y.nodes[a.children[e]],i+1)}return n}function H(t,e){let n="<tr>";n+=" <td>"+e+"</td>";n+=" <td>"+t.name+"</td>";n+=" <td>";const a=JSON.stringify(t,null,4).replaceAll('"',"").replaceAll("\n","<br/>");n+="<span class=\"icon icon-info\" onclick=\"new CABLES.UI.ModalDialog({ 'html': '<pre>"+a+"</pre>', 'title': '"+t.name+"' });\"></span>&nbsp;";if(t.pbrMetallicRoughness&&t.pbrMetallicRoughness.baseColorFactor){let e="";e+=""+Math.round(t.pbrMetallicRoughness.baseColorFactor[0]*255);e+=","+Math.round(t.pbrMetallicRoughness.baseColorFactor[1]*255);e+=","+Math.round(t.pbrMetallicRoughness.baseColorFactor[2]*255);n+='<div style="width:15px;height:15px;background-color:rgb('+e+');display:inline-block">&nbsp;</a>'}n+=' <td style="">'+(y.shaders[e]?"-":"<a onclick=\"gui.corePatch().getOpById('"+O.id+"').assignMaterial('"+t.name+'\')" class="treebutton">Assign</a>')+"<td>";n+="<td>";n+="</tr>";return n}function e(){if(!y)return;const e=performance.now();const r={};let o='<div style="overflow:scroll;width:100%;height:100%">';o+='File: <a href="'+CABLES.platform.getCablesUrl()+"/asset/patches/?filename="+C.get()+'" target="_blank">'+CABLES.basename(C.get())+"</a><br/>";o+="Generator:"+y.json.asset.generator;let t=0;if(y.json.nodes)t=y.json.nodes.length;o+='<div id="groupNodes">Nodes ('+t+")</div>";o+='<table id="sectionNodes" class="table treetable">';o+="<tr>";o+=' <th colspan="21">Name</th>';o+=" <th>Mesh</th>";o+=" <th>Skin</th>";o+=" <th>Material</th>";o+=" <th>Transform</th>";o+=" <th>Expose</th>";o+=" <th></th>";o+="</tr>";for(let e=0;e<y.nodes.length;e++){if(!y.nodes[e].isChild)o=q(o,y.nodes[e],1)}o+="</table>";let n=0;if(y.json.materials)n=y.json.materials.length;o+='<div id="groupMaterials">Materials ('+n+")</div>";if(!y.json.materials||y.json.materials.length==0){}else{o+='<table id="materialtable"  class="table treetable">';o+="<tr>";o+=" <th>Index</th>";o+=" <th>Name</th>";o+=" <th>Color</th>";o+=" <th>Function</th>";o+=" <th></th>";o+="</tr>";for(let e=0;e<y.json.materials.length;e++){o+=H(y.json.materials[e],e)}o+="</table>"}o+='<div id="groupMeshes">Meshes ('+y.json.meshes.length+")</div>";o+='<table id="meshestable"  class="table treetable">';o+="<tr>";o+=" <th>Name</th>";o+=" <th>Node</th>";o+=" <th>Material</th>";o+=" <th>Vertices</th>";o+=" <th>Attributes</th>";o+="</tr>";let s=[];r.meshes=0;r.meshTargets=0;for(let i=0;i<y.json.meshes.length;i++){o+="<tr>";o+="<td>"+y.json.meshes[i].name+"</td>";o+="<td>";let t=0;let n="";for(let e=0;e<y.json.nodes.length;e++){if(y.json.nodes[e].mesh==i){t++;if(t==1){n=y.json.nodes[e].name}}}if(t>1)o+=t+" nodes ("+n+" ...)";else o+=n;o+="</td>";o+="<td>";for(let e=0;e<y.json.meshes[i].primitives.length;e++){if(y.json.meshes[i].primitives[e].hasOwnProperty("material")){if(y.json.materials[y.json.meshes[i]]){o+=y.json.materials[y.json.meshes[i].primitives[e].material].name+" "}}else o+="None"}o+="</td>";o+="<td>";let a=0;for(let t=0;t<y.json.meshes[i].primitives.length;t++){if(y.json.meshes[i].primitives[t].attributes.POSITION!=undefined){let e=parseInt(y.json.accessors[y.json.meshes[i].primitives[t].attributes.POSITION].count);a+=e;o+=""+e+"<br/>"}else o+="-<br/>"}if(y.json.meshes[i].primitives.length>1)o+="="+a;o+="</td>";o+="<td>";for(let e=0;e<y.json.meshes[i].primitives.length;e++){o+=Object.keys(y.json.meshes[i].primitives[e].attributes);o+=" <a onclick=\"gui.corePatch().getOpById('"+O.id+"').exposeGeom('"+y.json.meshes[i].name+"',"+e+')" class="treebutton">Geometry</a>';o+="<br/>";if(y.json.meshes[i].primitives[e].targets){o+=y.json.meshes[i].primitives[e].targets.length+" targets<br/>";if(y.json.meshes[i].extras&&y.json.meshes[i].extras.targetNames)o+="Targetnames:<br/>"+y.json.meshes[i].extras.targetNames.join("<br/>");o+="<br/>"}}o+="</td>";o+="</tr>";for(let n=0;n<y.json.meshes[i].primitives.length;n++){const f=y.json.accessors[y.json.meshes[i].primitives[n].indices];if(f){let e=f.bufferView;if(s.indexOf(e)==-1){s.push(e);if(y.json.bufferViews[e])r.meshes+=y.json.bufferViews[e].byteLength}}for(let e in y.json.meshes[i].primitives[n].attributes){const p=y.json.meshes[i].primitives[n].attributes[e];const g=y.json.accessors[p].bufferView;if(s.indexOf(g)==-1){s.push(g);if(y.json.bufferViews[g])r.meshes+=y.json.bufferViews[g].byteLength}}if(y.json.meshes[i].primitives[n].targets)for(let t=0;t<y.json.meshes[i].primitives[n].targets.length;t++){for(let e in y.json.meshes[i].primitives[n].targets[t]){const v=y.json.meshes[i].primitives[n].targets[t][e];const f=y.json.accessors[v];const g=f.bufferView;console.log("accessor",f);if(s.indexOf(g)==-1)if(y.json.bufferViews[g]){s.push(g);r.meshTargets+=y.json.bufferViews[g].byteLength}}}}}o+="</table>";let a=0;let i=0;let l=0;if(y.json.animations){i=y.json.animations.length;for(let e=0;e<y.json.animations.length;e++){a+=y.json.animations[e].samplers.length}}o+='<div id="groupAnims">Animations ('+i+"/"+a+")</div>";if(y.json.animations){o+='<table id="sectionAnim" class="table treetable">';o+="<tr>";o+="  <th>Name</th>";o+="  <th>Target node</th>";o+="  <th>Path</th>";o+="  <th>Interpolation</th>";o+="  <th>Keys</th>";o+="</tr>";r.animations=0;for(let n=0;n<y.json.animations.length;n++){for(let t=0;t<y.json.animations[n].samplers.length;t++){let e=y.json.accessors[y.json.animations[n].samplers[t].input].bufferView;if(s.indexOf(e)==-1){s.push(e);r.animations+=y.json.bufferViews[e].byteLength}e=y.json.accessors[y.json.animations[n].samplers[t].output].bufferView;if(s.indexOf(e)==-1){s.push(e);r.animations+=y.json.bufferViews[e].byteLength}}for(let e=0;e<y.json.animations[n].channels.length;e++){o+="<tr>";o+="  <td> Anim "+n+": "+y.json.animations[n].name+"</td>";o+="  <td>"+y.nodes[y.json.animations[n].channels[e].target.node].name+"</td>";o+="  <td>";o+=y.json.animations[n].channels[e].target.path+" ";o+="  </td>";const b=y.json.animations[n].channels[e].sampler;const x=y.json.animations[n].samplers[b];o+="  <td>"+x.interpolation+"</td>";o+="  <td>"+y.json.accessors[x.output].count;l+=y.json.accessors[x.output].count;o+="</td>";o+="</tr>"}}o+="<tr>";o+="  <td></td>";o+="  <td></td>";o+="  <td></td>";o+="  <td></td>";o+="  <td>"+l+" total</td>";o+="</tr>";o+="</table>"}else{}let u=0;if(y.json.images)u=y.json.images.length;o+='<div id="groupImages">Images ('+u+")</div>";if(y.json.images){o+='<table id="sectionImages" class="table treetable">';o+="<tr>";o+="  <th>name</th>";o+="  <th>type</th>";o+="  <th>func</th>";o+="</tr>";r.images=0;for(let t=0;t<y.json.images.length;t++){if(y.json.images[t].hasOwnProperty("bufferView")){r.images+=y.json.bufferViews[y.json.images[t].bufferView].byteLength}else console.log("image has no bufferview?!");o+="<tr>";o+="<td>"+y.json.images[t].name+"</td>";o+="<td>"+y.json.images[t].mimeType+"</td>";o+="<td>";let e=y.json.images[t].name;if(e===undefined)e=y.json.images[t].bufferView;o+="<a onclick=\"gui.corePatch().getOpById('"+O.id+"').exposeTexture('"+e+'\')" class="treebutton">Expose</a>';o+="</td>";o+="<tr>"}o+="</table>"}let m=0;if(y.json.cameras)m=y.json.cameras.length;o+='<div id="groupCameras">Cameras ('+m+")</div>";if(y.json.cameras){o+='<table id="sectionCameras" class="table treetable">';o+="<tr>";o+="  <th>name</th>";o+="  <th>type</th>";o+="  <th>info</th>";o+="</tr>";for(let e=0;e<y.json.cameras.length;e++){o+="<tr>";o+="<td>"+y.json.cameras[e].name+"</td>";o+="<td>"+y.json.cameras[e].type+"</td>";o+="<td>";if(y.json.cameras[e].perspective){o+="yfov: "+Math.round(y.json.cameras[e].perspective.yfov*100)/100;o+=", ";o+="zfar: "+Math.round(y.json.cameras[e].perspective.zfar*100)/100;o+=", ";o+="znear: "+Math.round(y.json.cameras[e].perspective.znear*100)/100}o+="</td>";o+="<tr>"}o+="</table>"}let c=0;if(y.json.skins)c=y.json.skins.length;o+='<div id="groupSkins">Skins ('+c+")</div>";if(y.json.skins){o+='<table id="sectionSkins" class="table treetable">';o+="<tr>";o+="  <th>name</th>";o+="  <th></th>";o+="  <th>total joints</th>";o+="</tr>";for(let e=0;e<y.json.skins.length;e++){o+="<tr>";o+="<td>"+y.json.skins[e].name+"</td>";o+="<td>"+"</td>";o+="<td>"+y.json.skins[e].joints.length+"</td>";o+="<td>";o+="</td>";o+="<tr>"}o+="</table>"}if(y.timing){o+='<div id="groupTiming">Debug Loading Timing </div>';o+='<table id="sectionTiming" class="table treetable">';o+="<tr>";o+="  <th>task</th>";o+="  <th>time used</th>";o+="</tr>";let e=0;for(let e=0;e<y.timing.length-1;e++){o+="<tr>";o+="  <td>"+y.timing[e][0]+"</td>";o+="  <td>"+(y.timing[e+1][1]-y.timing[e][1])+" ms</td>";o+="</tr>"}o+="</table>"}let d=0;if(y.json.buffers)d=y.json.buffers[0].byteLength;o+='<div id="groupBinary">File Size Allocation ('+Math.round(d/1024)+"k )</div>";o+='<table id="sectionBinary" class="table treetable">';o+="<tr>";o+="  <th>name</th>";o+="  <th>size</th>";o+="  <th>%</th>";o+="</tr>";let h=d;for(let e in r){o+="<tr>";o+="<td>"+e+"</td>";o+="<td>"+W(r[e])+" </td>";o+="<td>"+Math.round(r[e]/d*100)+"% </td>";o+="<tr>";h-=r[e]}if(h!=0){o+="<tr>";o+="<td>unknown</td>";o+="<td>"+W(h)+" </td>";o+="<td>"+Math.round(h/d*100)+"% </td>";o+="<tr>"}o+="</table>";o+="</div>";_=new CABLES.UI.Tab("GLTF "+CABLES.basename(C.get()),{icon:"cube",infotext:"tab_gltf",padding:true,singleton:true});gui.mainTabs.addTab(_,true);_.addEventListener("close",S);_.html(o);CABLES.UI.Collapsable.setup(ele.byId("groupNodes"),ele.byId("sectionNodes"),false);CABLES.UI.Collapsable.setup(ele.byId("groupMaterials"),ele.byId("materialtable"),true);CABLES.UI.Collapsable.setup(ele.byId("groupAnims"),ele.byId("sectionAnim"),true);CABLES.UI.Collapsable.setup(ele.byId("groupMeshes"),ele.byId("meshestable"),true);CABLES.UI.Collapsable.setup(ele.byId("groupCameras"),ele.byId("sectionCameras"),true);CABLES.UI.Collapsable.setup(ele.byId("groupImages"),ele.byId("sectionImages"),true);CABLES.UI.Collapsable.setup(ele.byId("groupSkins"),ele.byId("sectionSkins"),true);CABLES.UI.Collapsable.setup(ele.byId("groupBinary"),ele.byId("sectionBinary"),true);CABLES.UI.Collapsable.setup(ele.byId("groupTiming"),ele.byId("sectionTiming"),true);gui.maintabPanel.show(true)}function W(e){if(e>1024)return Math.round(e/1024)+" kb";if(e>1024*500)return Math.round(e/1024)+" mb";else return e+" bytes"}const Y=class{constructor(e){this._mod=null;this._node=e;this._lastTime=0;this._matArr=[];this._m=mat4.create();this._invBindMatrix=mat4.create();this.identity=true}renderFinish(e){e.popModelMatrix();this._mod.unbind()}renderStart(e,t){if(!this._mod){this._mod=new CGL.ShaderModifier(e,O.name+this._node.name);this._mod.addModule({priority:-2,name:"MODULE_VERTEX_POSITION",srcHeadVert:l.skin_head_vert||"",srcBodyVert:l.skin_vert||""});this._mod.addUniformVert("m4[]","MOD_boneMats",[]);const i=vec3.create()}const n=this._node.skin;const a=y.json.skins[n].joints.length*16;{if(this._matArr.length!=a)this._matArr.length=a;for(let e=0;e<y.json.skins[n].joints.length;e++){const r=e*16;const o=y.json.skins[n].joints[e];const s=y.nodes[o];for(let e=0;e<16;e++)this._invBindMatrix[e]=y.accBuffers[y.json.skins[n].inverseBindMatrices][r+e];mat4.mul(this._m,s.modelMatAbs(),this._invBindMatrix);for(let e=0;e<this._m.length;e++)this._matArr[r+e]=this._m[e]}this._mod.setUniformValue("MOD_boneMats",this._matArr);this._lastTime=t}this._mod.define("SKIN_NUM_BONES",y.json.skins[n].joints.length);this._mod.bind();e.pushModelMatrix();if(this.identity)mat4.identity(e.mMatrix)}};const Z=class{constructor(e){this.mesh=e;this.tex=null;this.numRowsPerTarget=0;this.makeTex(e.geom)}renderFinish(e){e.popModelMatrix();this._mod.unbind()}renderStart(e,t){if(!this._mod){this._mod=new CGL.ShaderModifier(e,"gltftarget");this._mod.addModule({priority:-2,name:"MODULE_VERTEX_POSITION",srcHeadVert:l.targets_head_vert||"",srcBodyVert:l.targets_vert||""});this._mod.addUniformVert("4f","MOD_targetTexInfo",[0,0,0,0]);this._mod.addUniformVert("t","MOD_targetTex",1);this._mod.addUniformVert("f[]","MOD_weights",[]);const n=vec3.create()}this._mod.pushTexture("MOD_targetTex",this.tex);if(this.tex&&this.mesh.weights){this._mod.setUniformValue("MOD_weights",this.mesh.weights);this._mod.setUniformValue("MOD_targetTexInfo",[this.tex.width,this.tex.height,this.numRowsPerTarget,this.mesh.weights.length]);this._mod.define("MOD_NUM_WEIGHTS",Math.max(1,this.mesh.weights.length))}else{this._mod.define("MOD_NUM_WEIGHTS",1)}this._mod.bind();e.pushModelMatrix();if(this.identity)mat4.identity(e.mMatrix)}makeTex(n){if(!n.morphTargets||!n.morphTargets.length)return;let a=n.morphTargets[0].vertices.length/3;let e=0;this.numRowsPerTarget=0;if(n.morphTargets[0].vertices&&n.morphTargets[0].vertices.length)this.numRowsPerTarget++;if(n.morphTargets[0].vertexNormals&&n.morphTargets[0].vertexNormals.length)this.numRowsPerTarget++;if(n.morphTargets[0].tangents&&n.morphTargets[0].tangents.length)this.numRowsPerTarget++;if(n.morphTargets[0].bitangents&&n.morphTargets[0].bitangents.length)this.numRowsPerTarget++;e=n.morphTargets.length*this.numRowsPerTarget;const i=new Float32Array(a*e*4);let r=0;for(let t=0;t<n.morphTargets.length;t++){if(n.morphTargets[t].vertices&&n.morphTargets[t].vertices.length){for(let e=0;e<n.morphTargets[t].vertices.length;e+=3){i[(r*a+e/3)*4+0]=n.morphTargets[t].vertices[e+0];i[(r*a+e/3)*4+1]=n.morphTargets[t].vertices[e+1];i[(r*a+e/3)*4+2]=n.morphTargets[t].vertices[e+2];i[(r*a+e/3)*4+3]=1}r++}if(n.morphTargets[t].vertexNormals&&n.morphTargets[t].vertexNormals.length){for(let e=0;e<n.morphTargets[t].vertexNormals.length;e+=3){i[(r*a+e/3)*4+0]=n.morphTargets[t].vertexNormals[e+0];i[(r*a+e/3)*4+1]=n.morphTargets[t].vertexNormals[e+1];i[(r*a+e/3)*4+2]=n.morphTargets[t].vertexNormals[e+2];i[(r*a+e/3)*4+3]=1}r++}if(n.morphTargets[t].tangents&&n.morphTargets[t].tangents.length){for(let e=0;e<n.morphTargets[t].tangents.length;e+=3){i[(r*a+e/3)*4+0]=n.morphTargets[t].tangents[e+0];i[(r*a+e/3)*4+1]=n.morphTargets[t].tangents[e+1];i[(r*a+e/3)*4+2]=n.morphTargets[t].tangents[e+2];i[(r*a+e/3)*4+3]=1}r++}if(n.morphTargets[t].bitangents&&n.morphTargets[t].bitangents.length){for(let e=0;e<n.morphTargets[t].bitangents.length;e+=3){i[(r*a+e/3)*4+0]=n.morphTargets[t].bitangents[e+0];i[(r*a+e/3)*4+1]=n.morphTargets[t].bitangents[e+1];i[(r*a+e/3)*4+2]=n.morphTargets[t].bitangents[e+2];i[(r*a+e/3)*4+3]=1}r++}}this.tex=new CGL.Texture(f,{isFloatingPointTexture:true,name:"targetsTexture"});this.tex.initFromData(i,a,e,CGL.Texture.FILTER_LINEAR,CGL.Texture.WRAP_REPEAT)}};const K=O.inTrigger("Render"),t=O.inString("data"),C=O.inUrl("glb File",[".glb"]),Q=O.inBool("Draw",true),n=O.inDropDown("Camera",["None"],"None"),J=O.inString("Animation",""),$=O.inTriggerButton("Show Structure"),a=O.inSwitch("Center",["None","XYZ","XZ"],"XYZ"),i=O.inBool("Rescale",true),r=O.inFloat("Rescale Size",2.5),o=O.inFloat("Time"),u=O.inBool("Sync to timeline",false),ee=O.inBool("Loop",true),te=O.inSwitch("Normals Format",["XYZ","X-ZY"],"XYZ"),ne=O.inSwitch("Vertices Format",["XYZ","XZ-Y"],"XYZ"),m=O.inSwitch("Calc Normals",["Auto","Force Smooth","Never"],"Auto"),c=O.inObject("Materials"),ae=O.inArray("Hide Nodes"),ie=O.inBool("Use Material Properties",false),d=O.inBool("Active",true),re=O.outTrigger("Render Before"),h=O.outTrigger("Next"),oe=O.outString("Generator"),se=O.outNumber("GLTF Version"),le=O.outArray("GLTF Extensions Used"),ue=O.outNumber("Anim Length",0),me=O.outNumber("Anim Time",0),ce=O.outObject("Json"),de=O.outArray("Anims"),he=O.outArray("BoundingPoints"),fe=O.outObject("Bounds"),pe=O.outTrigger("Finished"),ge=O.outBool("Loading");O.setPortGroup("Timing",[o,u,ee]);let f=O.patch.cg||O.patch.cgl;let p=null;let ve=false;let be=0;let g=false;let v=null;let b=[];let y=null;let x=0;let E=0;let M=true;let xe=null;let P=null;let N=null;const _e=vec3.create();let Oe=0;let Ae=false;const j=vec3.create();C.onChange=ne.onChange=m.onChange=te.onChange=w;$.onTriggered=e;t.onChange=Pe;ae.onChange=Me;J.onChange=je;a.onChange=Te;O.toWorkPortsNeedToBeLinked(K);t.setUiAttribs({hideParam:true,hidePort:true});O.setPortGroup("Transform",[i,r,a]);function Ie(){const t=["None"];if(y){for(let e=0;e<y.nodes.length;e++){if(y.nodes[e].camera>=0){t.push(y.nodes[e].name)}}}n.uiAttribs.values=t}function Te(){Ae=a.get()!="None";if(y&&y.bounds){j.set(y.bounds.center);j[0]=-j[0];j[1]=-j[1];j[2]=-j[2];if(a.get()=="XZ")j[1]=-y.bounds.minY}}i.onChange=function(){r.setUiAttribs({greyout:!i.get()})};c.onChange=function(){M=true};O.onDelete=function(){S()};u.onChange=function(){o.setUiAttribs({greyout:u.get()})};n.onChange=Se;function Se(){v=null;if(!y)return;for(let e=0;e<y.nodes.length;e++){if(y.nodes[e].name==n.get())v=new k(y,y.nodes[e])}}K.onTriggered=function(){f=O.patch.cg||O.patch.cgl;if(!g)return;if(!d.get())return;if(ve){if(!p)p=CGL.MESHES.getSimpleCube(f,"ErrorCube");p.render(f.getShader())}be=0;if(u.get())E=O.patch.timer.getTime();else E=Math.max(0,o.get());if(ee.get()){E%=x;if(E<Oe)pe.trigger()}else{if(x>0&&E>=x)pe.trigger()}Oe=E;f.pushModelMatrix();me.set(E||0);if(g&&y&&y.bounds){if(i.get()){let e=r.get()/y.bounds.maxAxis;y.scale=e;vec3.set(_e,e,e,e);mat4.scale(f.mMatrix,f.mMatrix,_e)}if(Ae){mat4.translate(f.mMatrix,f.mMatrix,j)}}let e=f.frameStore.currentScene||null;f.frameStore.currentScene=y;re.trigger();if(g){if(M)ye();if(v)v.start(E);if(y){y.time=E;if(y.bounds&&f.shouldDrawHelpers(O)){if(O.isCurrentUiOp())f.pushShader(CABLES.GL_MARKER.getSelectedShader(f));else f.pushShader(CABLES.GL_MARKER.getDefaultShader(f));y.bounds.render(f,null,O);f.popShader()}if(Q.get()){for(let e=0;e<y.nodes.length;e++)if(!y.nodes[e].isChild)y.nodes[e].render(f)}else{for(let e=0;e<y.nodes.length;e++)if(!y.nodes[e].isChild)y.nodes[e].render(f,false,true)}}}h.trigger();f.frameStore.currentScene=e;f.popModelMatrix();if(v)v.end()};function L(){if(!y){g=true;ve=true;f.patch.loading.finished(P);O.setUiError("nogltf","GLTF File not found");return}O.setUiError("nogltf",null);if(y.loadingMeshes>0){setTimeout(L,100);return}y.timing.push(["finishLoading()",Math.round(performance.now()-y.startTime)]);M=true;ue.set(x);y.bounds=new CABLES.CG.BoundingBox;y.timing.push(["start calc bounds",Math.round(performance.now()-y.startTime)]);for(let e=0;e<y.nodes.length;e++){const t=y.nodes[e];t.updateMatrix();if(!t.isChild)t.calcBounds(y,null,y.bounds)}if(y.bounds)fe.set(y.bounds);y.timing.push(["calced bounds",Math.round(performance.now()-y.startTime)]);Me();y.timing.push(["hideNodesFromData",Math.round(performance.now()-y.startTime)]);if(_)e();y.timing.push(["printinfo",Math.round(performance.now()-y.startTime)]);Ie();Se();he.set(b);if(y){if(C.get()&&!C.get().startsWith("data:")){O.setUiAttrib({extendTitle:CABLES.basename(C.get())})}y.loaded=Date.now()}if(y){for(let e=0;e<y.nodes.length;e++){if(!y.nodes[e].isChild){y.nodes[e].render(f,false,true,true,false,true,0)}}for(let e=0;e<y.nodes.length;e++){const t=y.nodes[e];t.children=we(t.children)}}Te();je();ge.set(false);f.patch.loading.finished(P);P=null;if(y.accBuffersDelete){for(let e=0;e<y.accBuffersDelete.length;e++){y.accBuffers[y.accBuffersDelete[e]]=null}}if(!(y.json.images&&y.json.images.length))y.chunks=null;g=true}function Ce(e){if(!d.get())return;if(!P)P=f.patch.loading.start("gltfScene",C.get(),O);let t=C.get();if(!t||t=="null")return;let n=O.patch.getFilePath(String(C.get()));if(!n)return;if(C.get()&&!C.get().startsWith("data:")){if(e===true)n+="?rnd="+CABLES.generateUUID()}M=true;ge.set(true);fetch(n).then(e=>{return e.arrayBuffer()}).then(e=>{if(C.get()!=t){f.patch.loading.finished(P);P=null;return}b=[];x=0;y=F(e);e=null;L()}).catch(e=>{if(P)f.patch.loading.finished(P);P=null;L();O.logError("gltf fetch error",e)});S();const a=new XMLHttpRequest;a.open("GET",n,true);a.responseType="arraybuffer";f.patch.loading.addAssetLoadingTask(()=>{})}O.onFileChanged=function(e){if(C.get()&&C.get().indexOf(e)>-1){w(true)}};d.onChange=()=>{if(d.get())w();if(!d.get()){y=null}};function w(e){clearTimeout(xe);xe=setTimeout(function(){Ce(e)},30)}function ye(){if(!y)return;y.shaders={};if(c.links.length==1&&c.get()){M=true;const n=c.links[0].portOut.op;const a=n.getPort("Shader");const i=n.getPort("Material Name");if(!a&&!i){const r=c.get();for(let t in r){if(r[t]&&y.json.materials)for(let e=0;e<y.json.materials.length;e++){if(y.json.materials[e].name==t){if(y.shaders[e]){n.warn("double material assignment:",name)}y.shaders[e]=r[t]}}}}}if(c.get()){for(let e=0;e<c.links.length;e++){const t=c.links[e].portOut.op;const a=t.getPort("Shader");const i=t.getPort("Material Name");if(a&&i&&a.get()){const name=i.get();if(y.json.materials)for(let e=0;e<y.json.materials.length;e++)if(y.json.materials[e].name==name){if(y.shaders[e]){t.warn("double material assignment:",name)}y.shaders[e]=a.get()}}}}M=false;if(_)e()}function Ee(){const t=ae.get();if(!y||!N||!N.hiddenNodes)return;if(!t){return}for(let e=0;e<t.length;e++){const n=y.getNode(t[e]);if(n)n.hidden=true}}function Me(){if(!N)Pe();if(!y)return;y.unHideAll();if(N&&N.hiddenNodes){for(const e in N.hiddenNodes){const t=y.getNode(e);if(t)t.hidden=true;else O.verbose("node to be hidden not found",e,t)}}Ee()}function Pe(){N=t.get();if(!N||N==="")N={};else N=JSON.parse(N);if(y)Me();return N}function Ne(){t.set(JSON.stringify(N))}function je(){if(y&&y.nodes){for(let e=0;e<y.nodes.length;e++){y.nodes[e].setAnimAction(J.get())}}}function Le(t,n){for(let e=0;e<y.nodes.length;e++){if(y.nodes[e].children.indexOf(n)>=0){t.push(y.nodes[e]);if(y.nodes[e].isChild)Le(t,e)}}}O.exposeTexture=function(e){const t=gui.corePatch().addOp("Ops.Gl.GLTF.GltfTexture");t.getPort("Name").set(e);R(t,1);O.patch.link(O,h.name,t,"Render");gui.patchView.testCollision(t);gui.patchView.centerSelectOp(t.id,true)};O.exposeGeom=function(e,t){const n=gui.corePatch().addOp("Ops.Gl.GLTF.GltfGeometry");n.getPort("Name").set(e);n.getPort("Submesh").set(t);R(n,1);O.patch.link(O,h.name,n,"Update");gui.patchView.testCollision(n);gui.patchView.centerSelectOp(n.id,true)};function R(e,t){t=t||1;e.setUiAttrib({subPatch:O.uiAttribs.subPatch,translate:{x:O.uiAttribs.translate.x,y:O.uiAttribs.translate.y+t*CABLES.GLUI.glUiConfig.newOpDistanceY}})}O.exposeNode=function(n,e,a){let t=e=="hierarchy";if(t){let i=[];for(let e=0;e<y.nodes.length;e++){if(y.nodes[e].name==n){let t=[];const r=y.nodes[e];Le(t,e);t=t.reverse();t.push(r,r);let n=h.name;let a=O;for(let e=0;e<t.length;e++){const o=gui.corePatch().addOp("Ops.Gl.GLTF.GltfNode_v2");o.getPort("Node Name").set(t[e].name);O.patch.link(a,n,o,"Render");R(o,e);if(e==t.length-1){o.getPort("Transformation").set(false)}else{o.getPort("Draw Mesh").set(false);o.getPort("Draw Childs").set(false)}n="Next";a=o;i.push(o);gui.patchView.testCollision(o)}}}for(let e=0;e<i.length;e++){i[e].selectChilds()}}else{let t="Ops.Gl.GLTF.GltfNode_v2";if(a&&a.skin)t="Ops.Gl.GLTF.GltfSkin";if(e=="transform")t="Ops.Gl.GLTF.GltfNodeTransform_v2";gui.serverOps.loadOpLibs(t,()=>{let e=gui.corePatch().addOp(t);e.getPort("Node Name").set(n);R(e);O.patch.link(O,h.name,e,"Render");gui.patchView.testCollision(e);gui.patchView.centerSelectOp(e.id,true)})}gui.closeModal()};O.assignMaterial=function(e){const t=gui.corePatch().addOp("Ops.Gl.GLTF.GltfSetMaterial");t.getPort("Material Name").set(e);O.patch.link(O,c.name,t,"Material");R(t);gui.patchView.testCollision(t);gui.patchView.centerSelectOp(t.id,true);gui.closeModal()};O.toggleNodeVisibility=function(e){const t=y.getNode(e);t.hidden=!t.hidden;N.hiddenNodes=N.hiddenNodes||{};if(t)if(t.hidden)N.hiddenNodes[e]=true;else delete N.hiddenNodes[e];Ne()};function we(n){const a={},i=[];for(let e=0,t=n.length;e<t;++e){if(!a.hasOwnProperty(n[e])){i.push(n[e]);a[n[e]]=1}}return i}};Ops.Gl.GLTF.GltfScene_v4.prototype=new CABLES.Op;CABLES.OPS["c9cbb226-46f7-4ca6-8dab-a9d0bdca4331"]={f:Ops.Gl.GLTF.GltfScene_v4,objName:"Ops.Gl.GLTF.GltfScene_v4"};Ops.Gl.GLTF.GltfSetMaterial=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inObject("Shader",null,"shader"),a=e.inString("Material Name","none"),i=e.outObject("Material");a.onChange=n.onChange=function(){e.setUiAttrib({extendTitle:a.get()});i.setRef(n.get()||e.patch.cgl.getDefaultShader())}};Ops.Gl.GLTF.GltfSetMaterial.prototype=new CABLES.Op;CABLES.OPS["baf968ea-e4df-4fca-9cda-e6ddd38a4200"]={f:Ops.Gl.GLTF.GltfSetMaterial,objName:"Ops.Gl.GLTF.GltfSetMaterial"};Ops.Trigger.TriggerExtender=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTriggerButton("Execute"),a=e.outTrigger("Next");n.onTriggered=function(){a.trigger()}};Ops.Trigger.TriggerExtender.prototype=new CABLES.Op;CABLES.OPS["7ef594f3-4907-47b0-a2d3-9854eda1679d"]={f:Ops.Trigger.TriggerExtender,objName:"Ops.Trigger.TriggerExtender"};Ops.Gl.Phong.PhongMaterial_v6=function(){CABLES.Op.apply(this,arguments);const e=this;const s=e.attachments={phong_frag:'IN vec3 viewDirection;\nIN vec3 normInterpolated;\nIN vec2 texCoord;\n\n#ifdef AO_CHAN_1\n    #ifndef ATTRIB_texCoord1\n        #define ATTRIB_texCoord1\n\n        IN vec2 texCoord1;\n    #endif\n#endif\n\n#ifdef HAS_TEXTURE_AO\nvec2 tcAo;\n#endif\n\n\n\n#ifdef ENABLE_FRESNEL\n    IN vec4 cameraSpace_pos;\n#endif\n\n// IN mat3 normalMatrix; // when instancing...\n\n#ifdef HAS_TEXTURE_NORMAL\n    IN mat3 TBN_Matrix; // tangent bitangent normal space transform matrix\n#endif\n\nIN vec3 fragPos;\nIN vec3 v_viewDirection;\n\nUNI vec4 inDiffuseColor;\nUNI vec4 inMaterialProperties;\n\n#ifdef ADD_EMISSIVE_COLOR\n    UNI vec4 inEmissiveColor; // .w = intensity\n#endif\n\n#ifdef ENABLE_FRESNEL\n    UNI mat4 viewMatrix;\n    UNI vec4 inFresnel;\n    UNI vec2 inFresnelWidthExponent;\n#endif\n\n#ifdef ENVMAP_MATCAP\n    IN vec3 viewSpaceNormal;\n    IN vec3 viewSpacePosition;\n#endif\n\nstruct Light {\n    vec3 color;\n    vec3 position;\n    vec3 specular;\n\n\n    // * SPOT LIGHT * //\n    #ifdef HAS_SPOT\n        vec3 conePointAt;\n        #define COSCONEANGLE x\n        #define COSCONEANGLEINNER y\n        #define SPOTEXPONENT z\n        vec3 spotProperties;\n    #endif\n\n    #define INTENSITY x\n    #define ATTENUATION y\n    #define FALLOFF z\n    #define RADIUS w\n    vec4 lightProperties;\n\n    int castLight;\n};\n\n/* CONSTANTS */\n#define NONE -1\n#define ALBEDO x\n#define ROUGHNESS y\n#define SHININESS z\n#define SPECULAR_AMT w\n#define NORMAL x\n#define AO y\n#define SPECULAR z\n#define EMISSIVE w\nconst float PI = 3.1415926535897932384626433832795;\nconst float TWO_PI = (2. * PI);\nconst float EIGHT_PI = (8. * PI);\n\n#define RECIPROCAL_PI 1./PI\n#define RECIPROCAL_PI2 RECIPROCAL_PI/2.\n\n// TEXTURES\n// #ifdef HAS_TEXTURES\n    UNI vec4 inTextureIntensities;\n\n    #ifdef HAS_TEXTURE_ENV\n        #ifdef TEX_FORMAT_CUBEMAP\n            UNI samplerCube texEnv;\n            #ifndef WEBGL1\n                #define SAMPLETEX textureLod\n            #endif\n            #ifdef WEBGL1\n                #define SAMPLETEX textureCubeLodEXT\n            #endif\n        #endif\n\n        #ifdef TEX_FORMAT_EQUIRECT\n            UNI sampler2D texEnv;\n            #ifdef WEBGL1\n                // #extension GL_EXT_shader_texture_lod : enable\n                #ifdef GL_EXT_shader_texture_lod\n                    #define textureLod texture2DLodEXT\n                #endif\n                // #define textureLod texture2D\n            #endif\n\n            #define SAMPLETEX sampleEquirect\n\n            const vec2 invAtan = vec2(0.1591, 0.3183);\n            vec4 sampleEquirect(sampler2D tex,vec3 direction,float lod)\n            {\n                #ifndef WEBGL1\n                    vec3 newDirection = normalize(direction);\n            \t\tvec2 sampleUV;\n            \t\tsampleUV.x = -1. * (atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.75);\n            \t\tsampleUV.y = asin( clamp(direction.y, -1., 1.) ) * RECIPROCAL_PI + 0.5;\n                #endif\n\n                #ifdef WEBGL1\n                    vec3 newDirection = normalize(direction);\n                \t\tvec2 sampleUV = vec2(atan(newDirection.z, newDirection.x), asin(newDirection.y+1e-6));\n                        sampleUV *= vec2(0.1591, 0.3183);\n                        sampleUV += 0.5;\n                #endif\n                return textureLod(tex, sampleUV, lod);\n            }\n        #endif\n        #ifdef ENVMAP_MATCAP\n            UNI sampler2D texEnv;\n            #ifdef WEBGL1\n                // #extension GL_EXT_shader_texture_lod : enable\n                #ifdef GL_EXT_shader_texture_lod\n                    #define textureLod texture2DLodEXT\n                #endif\n                // #define textureLod texture2D\n            #endif\n\n\n            // * taken & modified from https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderLib/meshmatcap_frag.glsl.js\n            vec2 getMatCapUV(vec3 viewSpacePosition, vec3 viewSpaceNormal) {\n                vec3 viewDir = normalize(-viewSpacePosition);\n            \tvec3 x = normalize(vec3(viewDir.z, 0.0, - viewDir.x));\n            \tvec3 y = normalize(cross(viewDir, x));\n            \tvec2 uv = vec2(dot(x, viewSpaceNormal), dot(y, viewSpaceNormal)) * 0.495 + 0.5; // 0.495 to remove artifacts caused by undersized matcap disks\n            \treturn uv;\n            }\n        #endif\n\n        UNI float inEnvMapIntensity;\n        UNI float inEnvMapWidth;\n    #endif\n\n    #ifdef HAS_TEXTURE_LUMINANCE_MASK\n        UNI sampler2D texLuminance;\n        UNI float inLuminanceMaskIntensity;\n    #endif\n\n    #ifdef HAS_TEXTURE_DIFFUSE\n        UNI sampler2D texDiffuse;\n    #endif\n\n    #ifdef HAS_TEXTURE_SPECULAR\n        UNI sampler2D texSpecular;\n    #endif\n\n    #ifdef HAS_TEXTURE_NORMAL\n        UNI sampler2D texNormal;\n    #endif\n\n    #ifdef HAS_TEXTURE_AO\n        UNI sampler2D texAO;\n    #endif\n\n    #ifdef HAS_TEXTURE_EMISSIVE\n        UNI sampler2D texEmissive;\n    #endif\n\n    #ifdef HAS_TEXTURE_EMISSIVE_MASK\n        UNI sampler2D texMaskEmissive;\n        UNI float inEmissiveMaskIntensity;\n    #endif\n    #ifdef HAS_TEXTURE_ALPHA\n        UNI sampler2D texAlpha;\n    #endif\n// #endif\n\n{{MODULES_HEAD}}\n\nfloat when_gt(float x, float y) { return max(sign(x - y), 0.0); } // comparator function\nfloat when_lt(float x, float y) { return max(sign(y - x), 0.0); }\nfloat when_eq(float x, float y) { return 1. - abs(sign(x - y)); } // comparator function\nfloat when_neq(float x, float y) { return abs(sign(x - y)); } // comparator function\nfloat when_ge(float x, float y) { return 1.0 - when_lt(x, y); }\nfloat when_le(float x, float y) { return 1.0 - when_gt(x, y); }\n\n#ifdef FALLOFF_MODE_A\n    float CalculateFalloff(float distance, vec3 lightDirection, float falloff, float radius) {\n        // * original falloff\n        float denom = distance / radius + 1.0;\n        float attenuation = 1.0 / (denom*denom);\n        float t = (attenuation - falloff) / (1.0 - falloff);\n        return max(t, 0.0);\n    }\n#endif\n\n#ifdef FALLOFF_MODE_B\n    float CalculateFalloff(float distance, vec3 lightDirection, float falloff, float radius) {\n        float distanceSquared = dot(lightDirection, lightDirection);\n        float factor = distanceSquared * falloff;\n        float smoothFactor = clamp(1. - factor * factor, 0., 1.);\n        float attenuation = smoothFactor * smoothFactor;\n\n        return attenuation * 1. / max(distanceSquared, 0.00001);\n    }\n#endif\n\n#ifdef FALLOFF_MODE_C\n    float CalculateFalloff(float distance, vec3 lightDirection, float falloff, float radius) {\n        // https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf\n        float falloffNumerator = 1. - pow(distance/radius, 4.);\n        falloffNumerator = clamp(falloffNumerator, 0., 1.);\n        falloffNumerator *= falloffNumerator;\n\n        float denominator = distance*distance + falloff;\n\n        return falloffNumerator/denominator;\n    }\n#endif\n\n#ifdef FALLOFF_MODE_D\n    float CalculateFalloff(float distance, vec3 lightDirection, float falloff, float radius) {\n        // inverse square falloff, "physically correct"\n        return 1.0 / max(distance * distance, 0.0001);\n    }\n#endif\n\n#ifdef ENABLE_FRESNEL\n    float CalculateFresnel(vec3 direction, vec3 normal)\n    {\n        vec3 nDirection = normalize( direction );\n        vec3 nNormal = normalize( mat3(viewMatrix) * normal );\n        vec3 halfDirection = normalize( nNormal + nDirection );\n\n        float cosine = dot( halfDirection, nDirection );\n        float product = max( cosine, 0.0 );\n        float factor = pow(product, inFresnelWidthExponent.y);\n\n        return 5. * factor;\n    }\n#endif\n\n#ifdef CONSERVE_ENERGY\n    // http://www.rorydriscoll.com/2009/01/25/energy-conservation-in-games/\n    // http://www.farbrausch.de/~fg/articles/phong.pdf\n    float EnergyConservation(float shininess) {\n        #ifdef SPECULAR_PHONG\n            return (shininess + 2.)/TWO_PI;\n        #endif\n        #ifdef SPECULAR_BLINN\n            return (shininess + 8.)/EIGHT_PI;\n        #endif\n\n        #ifdef SPECULAR_SCHLICK\n            return (shininess + 8.)/EIGHT_PI;\n        #endif\n\n        #ifdef SPECULAR_GAUSS\n            return (shininess + 8.)/EIGHT_PI;\n        #endif\n    }\n#endif\n\n#ifdef ENABLE_OREN_NAYAR_DIFFUSE\n    float CalculateOrenNayar(vec3 lightDirection, vec3 viewDirection, vec3 normal) {\n        float LdotV = dot(lightDirection, viewDirection);\n        float NdotL = dot(lightDirection, normal);\n        float NdotV = dot(normal, viewDirection);\n\n        float albedo = inMaterialProperties.ALBEDO;\n        albedo *= 1.8;\n        float s = LdotV - NdotL * NdotV;\n        float t = mix(1., max(NdotL, NdotV), step(0., s));\n\n        float roughness = inMaterialProperties.ROUGHNESS;\n        float sigma2 = roughness * roughness;\n        float A = 1. + sigma2 * (albedo / (sigma2 + 0.13) + 0.5 / (sigma2 + 0.33));\n        float B = 0.45 * sigma2 / (sigma2 + 0.09);\n\n        float factor = albedo * max(0., NdotL) * (A + B * s / t) / PI;\n\n        return factor;\n\n    }\n#endif\n\nvec3 CalculateDiffuseColor(\n    vec3 lightDirection,\n    vec3 viewDirection,\n    vec3 normal,\n    vec3 lightColor,\n    vec3 materialColor,\n    inout float lambert\n) {\n    #ifndef ENABLE_OREN_NAYAR_DIFFUSE\n        lambert = clamp(dot(lightDirection, normal), 0., 1.);\n    #endif\n\n    #ifdef ENABLE_OREN_NAYAR_DIFFUSE\n        lambert = CalculateOrenNayar(lightDirection, viewDirection, normal);\n    #endif\n\n    vec3 diffuseColor = lambert * lightColor * materialColor;\n    return diffuseColor;\n}\n\nvec3 CalculateSpecularColor(\n    vec3 specularColor,\n    float specularCoefficient,\n    float shininess,\n    vec3 lightDirection,\n    vec3 viewDirection,\n    vec3 normal,\n    float lambertian\n) {\n    vec3 resultColor = vec3(0.);\n\n    #ifdef SPECULAR_PHONG\n        vec3 reflectDirection = reflect(-lightDirection, normal);\n        float specularAngle = max(dot(reflectDirection, viewDirection), 0.);\n        float specularFactor = pow(specularAngle, max(0., shininess));\n    resultColor = lambertian * specularFactor * specularCoefficient * specularColor;\n    #endif\n\n    #ifdef SPECULAR_BLINN\n        vec3 halfDirection = normalize(lightDirection + viewDirection);\n        float specularAngle = max(dot(halfDirection, normal), 0.);\n        float specularFactor = pow(specularAngle, max(0., shininess));\n        resultColor = lambertian * specularFactor * specularCoefficient * specularColor;\n    #endif\n\n    #ifdef SPECULAR_SCHLICK\n        vec3 halfDirection = normalize(lightDirection + viewDirection);\n        float specularAngle = dot(halfDirection, normal);\n        float schlickShininess = max(0., shininess);\n        float specularFactor = specularAngle / (schlickShininess - schlickShininess*specularAngle + specularAngle);\n        resultColor = lambertian * specularFactor * specularCoefficient * specularColor;\n    #endif\n\n    #ifdef SPECULAR_GAUSS\n        vec3 halfDirection = normalize(lightDirection + viewDirection);\n        float specularAngle = acos(max(dot(halfDirection, normal), 0.));\n        float exponent = specularAngle * shininess * 0.17;\n        exponent = -(exponent*exponent);\n        float specularFactor = exp(exponent);\n\n        resultColor = lambertian * specularFactor * specularCoefficient * specularColor;\n    #endif\n\n    #ifdef CONSERVE_ENERGY\n        float conserveEnergyFactor = EnergyConservation(shininess);\n        resultColor = conserveEnergyFactor * resultColor;\n    #endif\n\n    return resultColor;\n}\n\n#ifdef HAS_SPOT\n    float CalculateSpotLightEffect(vec3 lightPosition, vec3 conePointAt, float cosConeAngle, float cosConeAngleInner, float spotExponent, vec3 lightDirection) {\n        vec3 spotLightDirection = normalize(lightPosition-conePointAt);\n        float spotAngle = dot(-lightDirection, spotLightDirection);\n        float epsilon = cosConeAngle - cosConeAngleInner;\n\n        float spotIntensity = clamp((spotAngle - cosConeAngle)/epsilon, 0.0, 1.0);\n        spotIntensity = pow(spotIntensity, max(0.01, spotExponent));\n\n        return max(0., spotIntensity);\n    }\n#endif\n\n\n\n{{PHONG_FRAGMENT_HEAD}}\n\n\nvoid main()\n{\n    {{MODULE_BEGIN_FRAG}}\n\n    vec4 col=vec4(0., 0., 0., inDiffuseColor.a);\n    vec3 calculatedColor = vec3(0.);\n    vec3 normal = normalize(normInterpolated);\n    vec3 baseColor = inDiffuseColor.rgb;\n\n    {{MODULE_BASE_COLOR}}\n\n\n\n    #ifdef AO_CHAN_0\n        vec2 tcAo=texCoord;\n    #endif\n    #ifdef AO_CHAN_1\n        vec2 tcAo=texCoord1;\n    #endif\n\n\n    vec3 viewDirection = normalize(v_viewDirection);\n\n    #ifdef DOUBLE_SIDED\n        if(!gl_FrontFacing) normal = normal * -1.0;\n    #endif\n\n    #ifdef HAS_TEXTURES\n        #ifdef HAS_TEXTURE_DIFFUSE\n            baseColor = texture(texDiffuse, texCoord).rgb;\n\n            #ifdef COLORIZE_TEXTURE\n                baseColor *= inDiffuseColor.rgb;\n            #endif\n        #endif\n\n        #ifdef HAS_TEXTURE_NORMAL\n            normal = texture(texNormal, texCoord).rgb;\n            normal = normalize(normal * 2. - 1.);\n            float normalIntensity = inTextureIntensities.NORMAL;\n            normal = normalize(mix(vec3(0., 0., 1.), normal, 2. * normalIntensity));\n            normal = normalize(TBN_Matrix * normal);\n        #endif\n    #endif\n\n    {{PHONG_FRAGMENT_BODY}}\n\n\n\n\n\n\n    #ifdef ENABLE_FRESNEL\n        calculatedColor += inFresnel.rgb * (CalculateFresnel(vec3(cameraSpace_pos), normal) * inFresnel.w * inFresnelWidthExponent.x);\n    #endif\n\n     #ifdef HAS_TEXTURE_ALPHA\n        #ifdef ALPHA_MASK_ALPHA\n            col.a*=texture(texAlpha,texCoord).a;\n        #endif\n        #ifdef ALPHA_MASK_LUMI\n            col.a*= dot(vec3(0.2126,0.7152,0.0722), texture(texAlpha,texCoord).rgb);\n        #endif\n        #ifdef ALPHA_MASK_R\n            col.a*=texture(texAlpha,texCoord).r;\n        #endif\n        #ifdef ALPHA_MASK_G\n            col.a*=texture(texAlpha,texCoord).g;\n        #endif\n        #ifdef ALPHA_MASK_B\n            col.a*=texture(texAlpha,texCoord).b;\n        #endif\n    #endif\n\n    #ifdef DISCARDTRANS\n        if(col.a<0.2) discard;\n    #endif\n\n\n    #ifdef HAS_TEXTURE_ENV\n        vec3 luminanceColor = vec3(0.);\n\n        #ifndef ENVMAP_MATCAP\n            float environmentMapWidth = inEnvMapWidth;\n            float glossyExponent = inMaterialProperties.SHININESS;\n            float glossyCoefficient = inMaterialProperties.SPECULAR_AMT;\n\n            vec3 envMapNormal =  normal;\n            vec3 reflectDirection = reflect(normalize(-viewDirection), normal);\n\n            float lambertianCoefficient = dot(viewDirection, reflectDirection); //0.44; // TODO: need prefiltered map for this\n            // lambertianCoefficient = 1.;\n            float specularAngle = max(dot(reflectDirection, viewDirection), 0.);\n            float specularFactor = pow(specularAngle, max(0., inMaterialProperties.SHININESS));\n\n            glossyExponent = specularFactor;\n\n            float maxMIPLevel = 10.;\n            float MIPlevel = log2(environmentMapWidth / 1024. * sqrt(3.)) - 0.5 * log2(glossyExponent + 1.);\n\n            luminanceColor = inEnvMapIntensity * (\n                inDiffuseColor.rgb *\n                SAMPLETEX(texEnv, envMapNormal, maxMIPLevel).rgb\n                +\n                glossyCoefficient * SAMPLETEX(texEnv, reflectDirection, MIPlevel).rgb\n            );\n        #endif\n        #ifdef ENVMAP_MATCAP\n            luminanceColor = inEnvMapIntensity * (\n                texture(texEnv, getMatCapUV(viewSpacePosition, viewSpaceNormal)).rgb\n                //inDiffuseColor.rgb\n                //* textureLod(texEnv, getMatCapUV(envMapNormal), maxMIPLevel).rgb\n                //+\n                //glossyCoefficient * textureLod(texEnv, getMatCapUV(reflectDirection), MIPlevel).rgb\n            );\n        #endif\n\n\n\n        #ifdef HAS_TEXTURE_LUMINANCE_MASK\n            luminanceColor *= texture(texLuminance, texCoord).r * inLuminanceMaskIntensity;\n        #endif\n\n        #ifdef HAS_TEXTURE_AO\n            luminanceColor *= texture(texAO, tcAo).r*inTextureIntensities.AO;\n        #endif\n\n        #ifdef ENV_BLEND_ADD\n            calculatedColor.rgb += luminanceColor;\n        #endif\n        #ifdef ENV_BLEND_MUL\n            calculatedColor.rgb *= luminanceColor;\n        #endif\n\n        #ifdef ENV_BLEND_MIX\n            calculatedColor.rgb=mix(luminanceColor,calculatedColor.rgb,luminanceColor);\n        #endif\n\n\n    #endif\n\n    #ifdef ADD_EMISSIVE_COLOR\n        vec3 emissiveRadiance = mix(calculatedColor, inEmissiveColor.rgb, inEmissiveColor.w); // .w = intensity of color;\n\n        #ifdef HAS_TEXTURE_EMISSIVE\n            float emissiveIntensity = inTextureIntensities.EMISSIVE;\n            emissiveRadiance = mix(calculatedColor, texture(texEmissive, texCoord).rgb, emissiveIntensity);\n        #endif\n\n        #ifdef HAS_TEXTURE_EMISSIVE_MASK\n           float emissiveMixValue = mix(1., texture(texMaskEmissive, texCoord).r, inEmissiveMaskIntensity);\n           calculatedColor = mix(calculatedColor, emissiveRadiance, emissiveMixValue);\n        #endif\n\n        #ifndef HAS_TEXTURE_EMISSIVE_MASK\n            calculatedColor = emissiveRadiance;\n        #endif\n    #endif\n\n    col.rgb = clamp(calculatedColor, 0., 1.);\n\n\n    {{MODULE_COLOR}}\n\n    outColor = col;\n\n}\n',phong_vert:"\n{{MODULES_HEAD}}\n\n#define NONE -1\n#define AMBIENT 0\n#define POINT 1\n#define DIRECTIONAL 2\n#define SPOT 3\n\n#define TEX_REPEAT_X x;\n#define TEX_REPEAT_Y y;\n#define TEX_OFFSET_X z;\n#define TEX_OFFSET_Y w;\n\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\nIN float attrVertIndex;\nIN vec3 attrTangent;\nIN vec3 attrBiTangent;\n\nOUT vec2 texCoord;\nOUT vec3 normInterpolated;\nOUT vec3 fragPos;\n\n#ifdef AO_CHAN_1\n    #ifndef ATTRIB_attrTexCoord1\n        IN vec2 attrTexCoord1;\n        OUT vec2 texCoord1;\n        #define ATTRIB_attrTexCoord1\n        #define ATTRIB_texCoord1\n    #endif\n#endif\n\n#ifdef HAS_TEXTURE_NORMAL\n    OUT mat3 TBN_Matrix; // tangent bitangent normal space transform matrix\n#endif\n\n#ifdef ENABLE_FRESNEL\n    OUT vec4 cameraSpace_pos;\n#endif\n\nOUT vec3 v_viewDirection;\nOUT mat3 normalMatrix;\nOUT mat4 mvMatrix;\n\n#ifdef HAS_TEXTURES\n    UNI vec4 inTextureRepeatOffset;\n#endif\n\nUNI vec3 camPos;\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\n#ifdef ENVMAP_MATCAP\n    OUT vec3 viewSpaceNormal;\n    OUT vec3 viewSpacePosition;\n#endif\n\n\nmat3 transposeMat3(mat3 m)\n{\n    return mat3(m[0][0], m[1][0], m[2][0],\n        m[0][1], m[1][1], m[2][1],\n        m[0][2], m[1][2], m[2][2]);\n}\n\nmat3 inverseMat3(mat3 m)\n{\n    float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\n    float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\n    float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\n\n    float b01 = a22 * a11 - a12 * a21;\n    float b11 = -a22 * a10 + a12 * a20;\n    float b21 = a21 * a10 - a11 * a20;\n\n    float det = a00 * b01 + a01 * b11 + a02 * b21;\n\n    return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\n        b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\n        b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\n}\n\nvoid main()\n{\n    mat4 mMatrix=modelMatrix;\n    vec4 pos=vec4(vPosition,  1.0);\n\n    texCoord=attrTexCoord;\n    texCoord.y = 1. - texCoord.y;\n\n    #ifdef ATTRIB_texCoord1\n        texCoord1=attrTexCoord1;\n    #endif\n\n    vec3 norm=attrVertNormal;\n    vec3 tangent = attrTangent;\n    vec3 bitangent = attrBiTangent;\n\n    {{MODULE_VERTEX_POSITION}}\n\n    normalMatrix = transposeMat3(inverseMat3(mat3(mMatrix)));\n    mvMatrix = (viewMatrix * mMatrix);\n\n\n\n    #ifdef ENABLE_FRESNEL\n        cameraSpace_pos = mvMatrix * pos;\n    #endif\n\n    #ifdef HAS_TEXTURES\n        float repeatX = inTextureRepeatOffset.TEX_REPEAT_X;\n        float offsetX = inTextureRepeatOffset.TEX_OFFSET_X;\n        float repeatY = inTextureRepeatOffset.TEX_REPEAT_Y;\n        float offsetY = inTextureRepeatOffset.TEX_OFFSET_Y;\n\n        texCoord.x *= repeatX;\n        texCoord.x += offsetX;\n        texCoord.y *= repeatY;\n        texCoord.y += offsetY;\n    #endif\n\n   normInterpolated = vec3(normalMatrix*norm);\n\n    #ifdef HAS_TEXTURE_NORMAL\n        vec3 normCameraSpace = normalize((vec4(normInterpolated, 0.0)).xyz);\n        vec3 tangCameraSpace = normalize((mMatrix * vec4(tangent, 0.0)).xyz);\n        vec3 bitangCameraSpace = normalize((mMatrix * vec4(bitangent, 0.0)).xyz);\n\n        // re orthogonalization for smoother normals\n        tangCameraSpace = normalize(tangCameraSpace - dot(tangCameraSpace, normCameraSpace) * normCameraSpace);\n        bitangCameraSpace = cross(normCameraSpace, tangCameraSpace);\n\n        TBN_Matrix = mat3(tangCameraSpace, bitangCameraSpace, normCameraSpace);\n    #endif\n\n    fragPos = vec3((mMatrix) * pos);\n    v_viewDirection = normalize(camPos - fragPos);\n    // modelPos=mMatrix*pos;\n\n    #ifdef ENVMAP_MATCAP\n        mat3 viewSpaceNormalMatrix = normalMatrix = transposeMat3(inverseMat3(mat3(mvMatrix)));\n        viewSpaceNormal = normalize(viewSpaceNormalMatrix * norm);\n        viewSpacePosition = vec3(mvMatrix * pos);\n    #endif\n\n    mat4 modelViewMatrix=mvMatrix;\n    {{MODULE_VERTEX_MODELVIEW}}\n\n\n    gl_Position = projMatrix * modelViewMatrix * pos;\n}\n",snippet_body_ambient_frag:"    // * AMBIENT LIGHT {{LIGHT_INDEX}} *\n    vec3 diffuseColor{{LIGHT_INDEX}} = phongLight{{LIGHT_INDEX}}.lightProperties.INTENSITY*phongLight{{LIGHT_INDEX}}.color;\n    calculatedColor += diffuseColor{{LIGHT_INDEX}};\n",snippet_body_directional_frag:"    // * DIRECTIONAL LIGHT {{LIGHT_INDEX}} *\n\n    if (phongLight{{LIGHT_INDEX}}.castLight == 1) {\n        vec3 phongLightDirection{{LIGHT_INDEX}} = normalize(phongLight{{LIGHT_INDEX}}.position);\n\n        float phongLambert{{LIGHT_INDEX}} = 1.; // inout variable\n\n        vec3 lightColor{{LIGHT_INDEX}} = phongLight{{LIGHT_INDEX}}.color;\n        vec3 lightSpecular{{LIGHT_INDEX}} = phongLight{{LIGHT_INDEX}}.specular;\n\n        #ifdef HAS_TEXTURES\n            #ifdef HAS_TEXTURE_AO\n                // lightColor{{LIGHT_INDEX}} *= mix(vec3(1.), texture(texAO, texCoord).rgb, inTextureIntensities.AO);\n                lightColor{{LIGHT_INDEX}} *= texture(texAO, tcAo).g, inTextureIntensities.AO;\n\n            #endif\n\n            #ifdef HAS_TEXTURE_SPECULAR\n                lightSpecular{{LIGHT_INDEX}} *= mix(1., texture(texSpecular, texCoord).r, inTextureIntensities.SPECULAR);\n            #endif\n        #endif\n\n        vec3 diffuseColor{{LIGHT_INDEX}} = CalculateDiffuseColor(phongLightDirection{{LIGHT_INDEX}}, viewDirection, normal, lightColor{{LIGHT_INDEX}}, baseColor, phongLambert{{LIGHT_INDEX}});\n        vec3 specularColor{{LIGHT_INDEX}} = CalculateSpecularColor(\n            lightSpecular{{LIGHT_INDEX}},\n            inMaterialProperties.SPECULAR_AMT,\n            inMaterialProperties.SHININESS,\n            phongLightDirection{{LIGHT_INDEX}},\n            viewDirection,\n            normal,\n            phongLambert{{LIGHT_INDEX}}\n        );\n\n        vec3 combinedColor{{LIGHT_INDEX}} = (diffuseColor{{LIGHT_INDEX}} + specularColor{{LIGHT_INDEX}});\n\n        vec3 lightModelDiff{{LIGHT_INDEX}} = phongLight{{LIGHT_INDEX}}.position - fragPos.xyz;\n\n        combinedColor{{LIGHT_INDEX}} *= phongLight{{LIGHT_INDEX}}.lightProperties.INTENSITY;\n        calculatedColor += combinedColor{{LIGHT_INDEX}};\n    }",snippet_body_point_frag:"// * POINT LIGHT {{LIGHT_INDEX}} *\n    if (phongLight{{LIGHT_INDEX}}.castLight == 1) {\n        vec3 phongLightDirection{{LIGHT_INDEX}} = phongLight{{LIGHT_INDEX}}.position - fragPos.xyz;\n        // * get length before normalization for falloff calculation\n        phongLightDirection{{LIGHT_INDEX}} = normalize(phongLightDirection{{LIGHT_INDEX}});\n        float phongLightDistance{{LIGHT_INDEX}} = length(phongLightDirection{{LIGHT_INDEX}});\n\n        float phongLambert{{LIGHT_INDEX}} = 1.; // inout variable\n\n        vec3 lightColor{{LIGHT_INDEX}} = phongLight{{LIGHT_INDEX}}.color;\n        vec3 lightSpecular{{LIGHT_INDEX}} = phongLight{{LIGHT_INDEX}}.specular;\n\n        #ifdef HAS_TEXTURES\n            #ifdef HAS_TEXTURE_AO\n                lightColor{{LIGHT_INDEX}} -= (1.0-texture(texAO, tcAo).g)* (inTextureIntensities.AO);\n            #endif\n\n            #ifdef HAS_TEXTURE_SPECULAR\n                lightSpecular{{LIGHT_INDEX}} *= mix(1., texture(texSpecular, texCoord).r, inTextureIntensities.SPECULAR);\n            #endif\n        #endif\n\n        vec3 diffuseColor{{LIGHT_INDEX}} = CalculateDiffuseColor(phongLightDirection{{LIGHT_INDEX}}, viewDirection, normal, lightColor{{LIGHT_INDEX}}, baseColor, phongLambert{{LIGHT_INDEX}});\n        vec3 specularColor{{LIGHT_INDEX}} = CalculateSpecularColor(\n            lightSpecular{{LIGHT_INDEX}},\n            inMaterialProperties.SPECULAR_AMT,\n            inMaterialProperties.SHININESS,\n            phongLightDirection{{LIGHT_INDEX}},\n            viewDirection,\n            normal,\n            phongLambert{{LIGHT_INDEX}}\n        );\n\n        vec3 combinedColor{{LIGHT_INDEX}} = (diffuseColor{{LIGHT_INDEX}} + specularColor{{LIGHT_INDEX}});\n\n        combinedColor{{LIGHT_INDEX}} *= phongLight{{LIGHT_INDEX}}.lightProperties.INTENSITY;\n\n        float attenuation{{LIGHT_INDEX}} = CalculateFalloff(\n            phongLightDistance{{LIGHT_INDEX}},\n            phongLightDirection{{LIGHT_INDEX}},\n            phongLight{{LIGHT_INDEX}}.lightProperties.FALLOFF,\n            phongLight{{LIGHT_INDEX}}.lightProperties.RADIUS\n        );\n\n        attenuation{{LIGHT_INDEX}} *= when_gt(phongLambert{{LIGHT_INDEX}}, 0.);\n        combinedColor{{LIGHT_INDEX}} *= attenuation{{LIGHT_INDEX}};\n\n        calculatedColor += combinedColor{{LIGHT_INDEX}};\n    }\n",snippet_body_spot_frag:"    // * SPOT LIGHT {{LIGHT_INDEX}} *\n    if (phongLight{{LIGHT_INDEX}}.castLight == 1) {\n        vec3 phongLightDirection{{LIGHT_INDEX}} = phongLight{{LIGHT_INDEX}}.position - fragPos.xyz;\n        phongLightDirection{{LIGHT_INDEX}} = normalize( phongLightDirection{{LIGHT_INDEX}});\n        float phongLightDistance{{LIGHT_INDEX}} = length(phongLightDirection{{LIGHT_INDEX}});\n\n        float phongLambert{{LIGHT_INDEX}} = 1.; // inout variable\n\n        vec3 lightColor{{LIGHT_INDEX}} = phongLight{{LIGHT_INDEX}}.color;\n        vec3 lightSpecular{{LIGHT_INDEX}} = phongLight{{LIGHT_INDEX}}.specular;\n\n        #ifdef HAS_TEXTURES\n            #ifdef HAS_TEXTURE_AO\n                // lightColor{{LIGHT_INDEX}} *= mix(vec3(1.), texture(texAO, texCoord).rgb, inTextureIntensities.AO);\n                lightColor{{LIGHT_INDEX}} *= texture(texAO, texCoord).g, inTextureIntensities.AO;\n\n            #endif\n\n            #ifdef HAS_TEXTURE_SPECULAR\n                lightSpecular{{LIGHT_INDEX}} *= mix(1., texture(texSpecular, texCoord).r, inTextureIntensities.SPECULAR);\n            #endif\n        #endif\n\n        vec3 diffuseColor{{LIGHT_INDEX}} = CalculateDiffuseColor(phongLightDirection{{LIGHT_INDEX}}, viewDirection, normal, lightColor{{LIGHT_INDEX}}, baseColor, phongLambert{{LIGHT_INDEX}});\n        vec3 specularColor{{LIGHT_INDEX}} = CalculateSpecularColor(\n            lightSpecular{{LIGHT_INDEX}},\n            inMaterialProperties.SPECULAR_AMT,\n            inMaterialProperties.SHININESS,\n            phongLightDirection{{LIGHT_INDEX}},\n            viewDirection,\n            normal,\n            phongLambert{{LIGHT_INDEX}}\n        );\n\n        vec3 combinedColor{{LIGHT_INDEX}} = (diffuseColor{{LIGHT_INDEX}} + specularColor{{LIGHT_INDEX}});\n\n        float spotIntensity{{LIGHT_INDEX}} = CalculateSpotLightEffect(\n            phongLight{{LIGHT_INDEX}}.position, phongLight{{LIGHT_INDEX}}.conePointAt, phongLight{{LIGHT_INDEX}}.spotProperties.COSCONEANGLE,\n            phongLight{{LIGHT_INDEX}}.spotProperties.COSCONEANGLEINNER, phongLight{{LIGHT_INDEX}}.spotProperties.SPOTEXPONENT,\n            phongLightDirection{{LIGHT_INDEX}}\n        );\n\n        combinedColor{{LIGHT_INDEX}} *= spotIntensity{{LIGHT_INDEX}};\n\n        vec3 lightModelDiff{{LIGHT_INDEX}} = phongLight{{LIGHT_INDEX}}.position - fragPos.xyz;\n\n        float attenuation{{LIGHT_INDEX}} = CalculateFalloff(\n            phongLightDistance{{LIGHT_INDEX}},\n            phongLightDirection{{LIGHT_INDEX}},\n            phongLight{{LIGHT_INDEX}}.lightProperties.FALLOFF,\n            phongLight{{LIGHT_INDEX}}.lightProperties.RADIUS\n        );\n\n        attenuation{{LIGHT_INDEX}} *= when_gt(phongLambert{{LIGHT_INDEX}}, 0.);\n\n        combinedColor{{LIGHT_INDEX}} *= attenuation{{LIGHT_INDEX}};\n\n        combinedColor{{LIGHT_INDEX}} *= phongLight{{LIGHT_INDEX}}.lightProperties.INTENSITY;\n        calculatedColor += combinedColor{{LIGHT_INDEX}};\n    }",snippet_head_frag:"UNI Light phongLight{{LIGHT_INDEX}};\n"};const t=e.patch.cgl;const k=s.snippet_head_frag;const B={point:s.snippet_body_point_frag,spot:s.snippet_body_spot_frag,ambient:s.snippet_body_ambient_frag,directional:s.snippet_body_directional_frag,area:s.snippet_body_area_frag};const D=new RegExp("{{LIGHT_INDEX}}","g");const G=e=>{return k.replace("{{LIGHT_INDEX}}",e)};const U=(e,t)=>{return B[t].replace(D,e)};function F(){const e=s.phong_vert;let t=s.phong_frag;let n=G(0);let a=U(0,it[0].type);t=t.replace(Ae,n);t=t.replace(Ie,a);M.setSource(e,t);M.define("HAS_POINT");M.removeDefine("HAS_SPOT");M.removeDefine("HAS_DIRECTIONAL");M.removeDefine("HAS_AMBIENT")}const V=e.inTrigger("Trigger In");const z=e.inFloat("R",Math.random());const X=e.inFloat("G",Math.random());const q=e.inFloat("B",Math.random());const H=e.inFloatSlider("A",1);const W=[z,X,q,H];e.setPortGroup("Diffuse Color",W);const n=e.inBool("Enable",false);const a=e.inFloatSlider("Albedo",.707);const i=e.inFloatSlider("Roughness",.835);n.setUiAttribs({hidePort:true});a.setUiAttribs({greyout:true});i.setUiAttribs({greyout:true});z.setUiAttribs({colorPick:true});e.setPortGroup("Oren-Nayar Diffuse",[n,a,i]);e.toWorkShouldNotBeChild("Ops.Gl.TextureEffects.ImageCompose",CABLES.OP_PORT_TYPE_FUNCTION);n.onChange=function(){M.toggleDefine("ENABLE_OREN_NAYAR_DIFFUSE",n);a.setUiAttribs({greyout:!n.get()});i.setUiAttribs({greyout:!n.get()})};const r=e.inValueBool("Active",false);r.setUiAttribs({hidePort:true});const Y=e.inValueSlider("Fresnel Intensity",.7);const Z=e.inFloat("Fresnel Width",1);const K=e.inFloat("Fresnel Exponent",6);const Q=e.inFloat("Fresnel R",1);const J=e.inFloat("Fresnel G",1);const $=e.inFloat("Fresnel B",1);Q.setUiAttribs({colorPick:true});const ee=[Y,Z,K,Q,J,$];ee.forEach(function(e){e.setUiAttribs({greyout:true})});e.setPortGroup("Fresnel",ee.concat([r]));let o=null;let te=null;r.onChange=function(){M.toggleDefine("ENABLE_FRESNEL",r);if(r.get()){if(!o)o=new CGL.Uniform(M,"4f","inFresnel",Q,J,$,Y);if(!te)te=new CGL.Uniform(M,"2f","inFresnelWidthExponent",Z,K)}else{if(o){M.removeUniform("inFresnel");o=null}if(te){M.removeUniform("inFresnelWidthExponent");te=null}}ee.forEach(function(e){e.setUiAttribs({greyout:!r.get()})})};const l=e.inBool("Emissive Active",false);const u=e.inFloatSlider("Color Intensity",.3);const m=e.inFloatSlider("Emissive R",Math.random());const c=e.inFloatSlider("Emissive G",Math.random());const d=e.inFloatSlider("Emissive B",Math.random());m.setUiAttribs({colorPick:true});e.setPortGroup("Emissive Color",[l,u,m,c,d]);u.setUiAttribs({greyout:!l.get()});m.setUiAttribs({greyout:!l.get()});c.setUiAttribs({greyout:!l.get()});d.setUiAttribs({greyout:!l.get()});let ne=null;l.onChange=()=>{M.toggleDefine("ADD_EMISSIVE_COLOR",l);if(l.get()){ne=new CGL.Uniform(M,"4f","inEmissiveColor",m,c,d,u);x.setUiAttribs({greyout:false});_.setUiAttribs({greyout:false});if(x.get())T.setUiAttribs({greyout:false});if(_.get())S.setUiAttribs({greyout:false})}else{e.log("ayayay");x.setUiAttribs({greyout:true});_.setUiAttribs({greyout:true});T.setUiAttribs({greyout:true});S.setUiAttribs({greyout:true});M.removeUniform("inEmissiveColor");ne=null}if(x.get()){u.setUiAttribs({greyout:true});m.setUiAttribs({greyout:true});c.setUiAttribs({greyout:true});d.setUiAttribs({greyout:true})}else{if(l.get()){u.setUiAttribs({greyout:false});m.setUiAttribs({greyout:false});c.setUiAttribs({greyout:false});d.setUiAttribs({greyout:false})}else{u.setUiAttribs({greyout:true});m.setUiAttribs({greyout:true});c.setUiAttribs({greyout:true});d.setUiAttribs({greyout:true})}}};const ae=e.inFloat("Shininess",4);const ie=e.inFloatSlider("Specular Amount",.5);const h=e.inSwitch("Specular Model",["Blinn","Schlick","Phong","Gauss"],"Blinn");h.setUiAttribs({hidePort:true});const re=[ae,ie,h];e.setPortGroup("Specular",re);const oe=e.inValueBool("Energy Conservation",false);const se=e.inBool("Double Sided Material",false);const f=e.inSwitch("Falloff Mode",["A","B","C","D"],"A");oe.setUiAttribs({hidePort:true});se.setUiAttribs({hidePort:true});f.setUiAttribs({hidePort:true});f.onChange=()=>{const e=["A","B","C","D"];M.define("FALLOFF_MODE_"+f.get());e.filter(e=>{return e!==f.get()}).forEach(e=>{return M.removeDefine("FALLOFF_MODE_"+e)})};const le=[oe,se,f];e.setPortGroup("Light Options",le);const p=e.inTexture("Diffuse Texture");const g=e.inTexture("Specular Texture");const v=e.inTexture("Normal Map");const b=e.inTexture("AO Texture");const x=e.inTexture("Emissive Texture");const _=e.inTexture("Emissive Mask");const O=e.inTexture("Opacity Texture");const A=e.inTexture("Environment Map");const I=e.inTexture("Env Map Mask");e.setPortGroup("Textures",[p,g,v,b,x,_,O,A,I]);const ue=e.inBool("Colorize Texture",false);const me=e.inFloat("Diffuse Repeat X",1);const ce=e.inFloat("Diffuse Repeat Y",1);const de=e.inFloat("Texture Offset X",0);const he=e.inFloat("Texture Offset Y",0);const fe=e.inFloatSlider("Specular Intensity",1);const pe=e.inFloatSlider("Normal Map Intensity",.5);const ge=e.inFloatSlider("AO Intensity",1);const ve=e.inSwitch("AO UV Channel",["1","2"],1);const T=e.inFloatSlider("Emissive Intensity",1);const S=e.inFloatSlider("Emissive Mask Intensity",1);const be=e.inFloatSlider("Env Map Intensity",1);const C=e.inSwitch("Env Map Blend",["Add","Multiply","Mix"],"Add");const xe=e.inFloatSlider("Env Mask Intensity",1);ue.setUiAttribs({hidePort:true});e.setPortGroup("Texture Transforms",[ue,ce,me,he,de]);e.setPortGroup("Texture Intensities",[pe,ge,fe,T,C,S,be,xe]);const y=e.inSwitch("Alpha Mask Source",["Luminance","R","G","B","A"],"Luminance");y.setUiAttribs({greyout:true});const E=e.inValueBool("Discard Transparent Pixels");E.setUiAttribs({hidePort:true});e.setPortGroup("Opacity Texture",[y,E]);ve.onChange=C.onChange=y.onChange=Xe;const _e=e.outTrigger("Trigger Out");const Oe=e.outObject("Shader",null,"shader");Oe.ignoreValueSerialize=true;const M=new CGL.Shader(t,"phongmaterial_"+e.id,this);M.op=this;M.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG","MODULE_BASE_COLOR","MODULE_VERTEX_MODELVIEW"]);M.setSource(s.simosphong_vert,s.simosphong_frag);M.define("FALLOFF_MODE_A");if(t.glVersion<2){M.enableExtension("GL_OES_standard_derivatives");if(t.enableExtension("OES_texture_float"))M.enableExtension("GL_OES_texture_float");else e.log("error loading extension OES_texture_float");if(t.enableExtension("OES_texture_float_linear"))M.enableExtension("GL_OES_texture_float_linear");else e.log("error loading extention OES_texture_float_linear");if(t.enableExtension("GL_OES_texture_half_float"))M.enableExtension("GL_OES_texture_half_float");else e.log("error loading extention GL_OES_texture_half_float");if(t.enableExtension("GL_OES_texture_half_float_linear"))M.enableExtension("GL_OES_texture_half_float_linear");else e.log("error loading extention GL_OES_texture_half_float_linear")}const Ae=new RegExp("{{PHONG_FRAGMENT_HEAD}}","g");const Ie=new RegExp("{{PHONG_FRAGMENT_BODY}}","g");const P={directional:false,spot:false,ambient:false,point:false};function Te(t){let e=s.phong_frag;let n="";let a="";P.directional=false;P.spot=false;P.ambient=false;P.point=false;for(let e=0;e<t.length;e+=1){const i=t[e];const r=i.type;if(!P[r]){P[r]=true}n=n.concat(G(e));a=a.concat(U(e,i.type))}e=e.replace(Ae,n);e=e.replace(Ie,a);M.setSource(s.phong_vert,e);for(let e=0,t=Object.keys(P);e<t.length;e+=1){const o=t[e];if(P[o]){if(!M.hasDefine("HAS_"+o.toUpperCase())){M.define("HAS_"+o.toUpperCase())}}else{if(M.hasDefine("HAS_"+o.toUpperCase())){M.removeDefine("HAS_"+o.toUpperCase())}}}}Oe.set(M);let Se=null;let Ce=null;let ye=null;let Ee=null;let Me=null;let Pe=null;let Ne=null;let N=null;let j=null;let L=null;let je=null;let Le=null;let we=null;ue.onChange=function(){M.toggleDefine("COLORIZE_TEXTURE",ue.get())};function Re(){if(p.get()){if(!M.hasDefine("HAS_TEXTURE_DIFFUSE")){M.define("HAS_TEXTURE_DIFFUSE");if(!Se)Se=new CGL.Uniform(M,"t","texDiffuse",0)}}else{M.removeUniform("texDiffuse");M.removeDefine("HAS_TEXTURE_DIFFUSE");Se=null}}function ke(){if(g.get()){fe.setUiAttribs({greyout:false});if(!M.hasDefine("HAS_TEXTURE_SPECULAR")){M.define("HAS_TEXTURE_SPECULAR");if(!Ce)Ce=new CGL.Uniform(M,"t","texSpecular",0)}}else{fe.setUiAttribs({greyout:true});M.removeUniform("texSpecular");M.removeDefine("HAS_TEXTURE_SPECULAR");Ce=null}}function Be(){if(v.get()){pe.setUiAttribs({greyout:false});if(!M.hasDefine("HAS_TEXTURE_NORMAL")){M.define("HAS_TEXTURE_NORMAL");if(!ye)ye=new CGL.Uniform(M,"t","texNormal",0)}}else{pe.setUiAttribs({greyout:true});M.removeUniform("texNormal");M.removeDefine("HAS_TEXTURE_NORMAL");ye=null}}Ee=new CGL.Uniform(M,"t","texAO");function De(){M.toggleDefine("HAS_TEXTURE_AO",b.get());ge.setUiAttribs({greyout:!b.get()})}function Ge(){if(x.get()){m.setUiAttribs({greyout:true});c.setUiAttribs({greyout:true});d.setUiAttribs({greyout:true});u.setUiAttribs({greyout:true});if(l.get()){T.setUiAttribs({greyout:false})}if(!M.hasDefine("HAS_TEXTURE_EMISSIVE")){M.define("HAS_TEXTURE_EMISSIVE");if(!Me)Me=new CGL.Uniform(M,"t","texEmissive",0)}}else{T.setUiAttribs({greyout:true});if(l.get()){m.setUiAttribs({greyout:false});c.setUiAttribs({greyout:false});d.setUiAttribs({greyout:false});u.setUiAttribs({greyout:false})}else{x.setUiAttribs({greyout:true})}M.removeUniform("texEmissive");M.removeDefine("HAS_TEXTURE_EMISSIVE");Me=null}}function Ue(){if(_.get()){if(l.get()){S.setUiAttribs({greyout:false})}if(!M.hasDefine("HAS_TEXTURE_EMISSIVE_MASK")){M.define("HAS_TEXTURE_EMISSIVE_MASK");if(!Pe)Pe=new CGL.Uniform(M,"t","texMaskEmissive",0);if(!Ne)Ne=new CGL.Uniform(M,"f","inEmissiveMaskIntensity",S)}}else{if(!l.get()){_.setUiAttribs({greyout:true})}S.setUiAttribs({greyout:true});M.removeUniform("texMaskEmissive");M.removeUniform("inEmissiveMaskIntensity");M.removeDefine("HAS_TEXTURE_EMISSIVE_MASK");Pe=null;Ne=null}}let Fe=false;function Ve(){M.toggleDefine("HAS_TEXTURE_ENV",A.get());be.setUiAttribs({greyout:!A.get()});if(A.get()){if(!j)j=new CGL.Uniform(M,"t","texEnv",0);M.toggleDefine("TEX_FORMAT_CUBEMAP",A.get().cubemap);if(A.get().cubemap){M.removeDefine("TEX_FORMAT_EQUIRECT");M.removeDefine("ENVMAP_MATCAP");if(!L)L=new CGL.Uniform(M,"f","inEnvMapIntensity",be);if(!je)je=new CGL.Uniform(M,"f","inEnvMapWidth",A.get().cubemap.width)}else{const e=A.get().width===A.get().height;M.toggleDefine("TEX_FORMAT_EQUIRECT",!e);M.toggleDefine("ENVMAP_MATCAP",e);if(!L)L=new CGL.Uniform(M,"f","inEnvMapIntensity",be);if(!je)je=new CGL.Uniform(M,"f","inEnvMapWidth",A.get().width)}}else{M.removeUniform("inEnvMapIntensity");M.removeUniform("inEnvMapWidth");M.removeUniform("texEnv");M.removeDefine("HAS_TEXTURE_ENV");M.removeDefine("ENVMAP_MATCAP");j=null;L=null}Fe=false}function ze(){if(I.get()){xe.setUiAttribs({greyout:false});if(!Le){M.define("HAS_TEXTURE_LUMINANCE_MASK");Le=new CGL.Uniform(M,"t","texLuminance",0);we=new CGL.Uniform(M,"f","inLuminanceMaskIntensity",xe)}}else{xe.setUiAttribs({greyout:true});M.removeDefine("HAS_TEXTURE_LUMINANCE_MASK");M.removeUniform("inLuminanceMaskIntensity");M.removeUniform("texLuminance");Le=null;we=null}}function Xe(){M.toggleDefine("ENV_BLEND_ADD",C.get()=="Add");M.toggleDefine("ENV_BLEND_MUL",C.get()=="Multiply");M.toggleDefine("ENV_BLEND_MIX",C.get()=="Mix");M.toggleDefine("ALPHA_MASK_ALPHA",y.get()=="A"||y.get()=="Alpha");M.toggleDefine("ALPHA_MASK_LUMI",y.get()=="Luminance");M.toggleDefine("ALPHA_MASK_R",y.get()=="R");M.toggleDefine("ALPHA_MASK_G",y.get()=="G");M.toggleDefine("ALPHA_MASK_B",y.get()=="B");M.toggleDefine("AO_CHAN_0",ve.get()=="1");M.toggleDefine("AO_CHAN_1",ve.get()=="2")}function qe(){if(O.get()){if(N!==null)return;M.removeUniform("texAlpha");M.define("HAS_TEXTURE_ALPHA");if(!N)N=new CGL.Uniform(M,"t","texAlpha",0);y.setUiAttribs({greyout:false});E.setUiAttribs({greyout:false})}else{M.removeUniform("texAlpha");M.removeDefine("HAS_TEXTURE_ALPHA");N=null;y.setUiAttribs({greyout:true});E.setUiAttribs({greyout:true})}Xe()}E.onChange=function(){M.toggleDefine("DISCARDTRANS",E.get())};p.onChange=Re;g.onChange=ke;v.onChange=Be;b.onChange=De;x.onChange=Ge;_.onChange=Ue;O.onChange=qe;A.onChange=()=>{Fe=true};I.onChange=ze;const He=t.maxUniformsFrag;const We=He===64?6:16;M.define("MAX_LIGHTS",We.toString());M.define("SPECULAR_PHONG");h.onChange=function(){if(h.get()==="Phong"){M.define("SPECULAR_PHONG");M.removeDefine("SPECULAR_BLINN");M.removeDefine("SPECULAR_GAUSS");M.removeDefine("SPECULAR_SCHLICK")}else if(h.get()==="Blinn"){M.define("SPECULAR_BLINN");M.removeDefine("SPECULAR_PHONG");M.removeDefine("SPECULAR_GAUSS");M.removeDefine("SPECULAR_SCHLICK")}else if(h.get()==="Gauss"){M.define("SPECULAR_GAUSS");M.removeDefine("SPECULAR_BLINN");M.removeDefine("SPECULAR_PHONG");M.removeDefine("SPECULAR_SCHLICK")}else if(h.get()==="Schlick"){M.define("SPECULAR_SCHLICK");M.removeDefine("SPECULAR_BLINN");M.removeDefine("SPECULAR_PHONG");M.removeDefine("SPECULAR_GAUSS")}};oe.onChange=function(){M.toggleDefine("CONSERVE_ENERGY",oe.get())};se.onChange=function(){M.toggleDefine("DOUBLE_SIDED",se.get())};const Ye=new CGL.Uniform(M,"4f","inMaterialProperties",a,i,ae,ie);const Ze=new CGL.Uniform(M,"4f","inDiffuseColor",z,X,q,H);const Ke=new CGL.Uniform(M,"4f","inTextureIntensities",pe,ge,fe,T);const Qe=new CGL.Uniform(M,"4f","inTextureRepeatOffset",me,ce,de,he);M.uniformColorDiffuse=Ze;const w=[];let Je=0;function $e(t){for(let e=0;e<w.length;e+=1){w[e]=null}for(let e=0;e<t;e+=1){w[e]=null;if(!w[e]){w[e]={color:new CGL.Uniform(M,"3f","phongLight"+e+".color",[1,1,1]),position:new CGL.Uniform(M,"3f","phongLight"+e+".position",[0,11,0]),specular:new CGL.Uniform(M,"3f","phongLight"+e+".specular",[1,1,1]),lightProperties:new CGL.Uniform(M,"4f","phongLight"+e+".lightProperties",[1,1,1,1]),conePointAt:new CGL.Uniform(M,"3f","phongLight"+e+".conePointAt",vec3.create()),spotProperties:new CGL.Uniform(M,"3f","phongLight"+e+".spotProperties",[0,0,0,0]),castLight:new CGL.Uniform(M,"i","phongLight"+e+".castLight",1)}}}}function et(e){R.position.setValue(e.position);R.color.setValue(e.color);R.specular.setValue(e.specular);R.lightProperties.setValue([e.intensity,e.attenuation,e.falloff,e.radius]);R.conePointAt.setValue(e.conePointAt);R.spotProperties.setValue([e.cosConeAngle,e.cosConeAngleInner,e.spotExponent])}function tt(t){for(let e=0;e<t.length;e+=1){const n=t[e];n.isUsed=true;w[e].position.setValue(n.position);w[e].color.setValue(n.color);w[e].specular.setValue(n.specular);w[e].lightProperties.setValue([n.intensity,n.attenuation,n.falloff,n.radius]);w[e].conePointAt.setValue(n.conePointAt);w[e].spotProperties.setValue([n.cosConeAngle,n.cosConeAngleInner,n.spotExponent]);w[e].castLight.setValue(n.castLight)}}function nt(e){if(e.length!==Je){Te(e);$e(e.length);Je=e.length;tt(e)}else{tt(e)}}let R=null;function at(){R={color:new CGL.Uniform(M,"3f","phongLight"+0+".color",[1,1,1]),specular:new CGL.Uniform(M,"3f","phongLight"+0+".specular",[1,1,1]),position:new CGL.Uniform(M,"3f","phongLight"+0+".position",[0,11,0]),lightProperties:new CGL.Uniform(M,"4f","phongLight"+0+".lightProperties",[1,1,1,1]),conePointAt:new CGL.Uniform(M,"3f","phongLight"+0+".conePointAt",vec3.create()),spotProperties:new CGL.Uniform(M,"3f","phongLight"+0+".spotProperties",[0,0,0,0]),castLight:new CGL.Uniform(M,"i","phongLight"+0+".castLight",1)}}const it=[{type:"point",position:[5,5,5],color:[1,1,1],specular:[1,1,1],intensity:1,attenuation:0,falloff:.5,radius:80,castLight:1}];const rt=mat4.create();function ot(){if(t.frameStore.lightStack){if(t.frameStore.lightStack.length===0){e.setUiError("deflight","Default light is enabled. Please add lights to your patch to make this warning disappear.",1)}else e.setUiError("deflight",null)}if(!t.frameStore.lightStack||!t.frameStore.lightStack.length){if(!R){F();at()}mat4.invert(rt,t.vMatrix);it[0].position=[rt[12],rt[13],rt[14]];et(it[0]);Je=-1}else{if(M){if(t.frameStore.lightStack){if(t.frameStore.lightStack.length){R=null;nt(t.frameStore.lightStack)}}}}}const st=function(){if(!M){e.log("NO SHADER");return}t.pushShader(M);M.popTextures();_e.trigger();t.popShader()};e.preRender=function(){M.bind();st()};const lt=mat4.create();const ut=vec3.create();const mt=vec3.create();V.onTriggered=function(){if(!M){e.log("phong has no shader...");return}if(Fe)Ve();t.pushShader(M);M.popTextures();if(p.get())M.pushTexture(Se,p.get());if(g.get())M.pushTexture(Ce,g.get());if(v.get())M.pushTexture(ye,v.get());if(b.get())M.pushTexture(Ee,b.get());if(x.get())M.pushTexture(Me,x.get());if(_.get())M.pushTexture(Pe,_.get());if(O.get())M.pushTexture(N,O.get());if(A.get()){if(A.get().cubemap)M.pushTexture(j,A.get().cubemap,t.gl.TEXTURE_CUBE_MAP);else M.pushTexture(j,A.get())}if(I.get()){M.pushTexture(Le,I.get())}ot();_e.trigger();t.popShader()};if(t.glVersion==1){if(!t.enableExtension("EXT_shader_texture_lod")){e.log("no EXT_shader_texture_lod texture extension")}else{M.enableExtension("GL_EXT_shader_texture_lod");t.enableExtension("OES_texture_float");t.enableExtension("OES_texture_float_linear");t.enableExtension("OES_texture_half_float");t.enableExtension("OES_texture_half_float_linear");M.enableExtension("GL_OES_standard_derivatives");M.enableExtension("GL_OES_texture_float");M.enableExtension("GL_OES_texture_float_linear");M.enableExtension("GL_OES_texture_half_float");M.enableExtension("GL_OES_texture_half_float_linear")}}Re();ke();Be();De();qe();Ge();Ue();Ve();ze()};Ops.Gl.Phong.PhongMaterial_v6.prototype=new CABLES.Op;CABLES.OPS["0d83ed06-cdbe-4fe0-87bb-0ccece7fb6e1"]={f:Ops.Gl.Phong.PhongMaterial_v6,objName:"Ops.Gl.Phong.PhongMaterial_v6"};Ops.Gl.Texture_v2=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={};const r=i.inUrl("File",[".jpg",".png",".webp",".jpeg",".avif"]),t=i.inSwitch("Filter",["nearest","linear","mipmap"]),n=i.inValueSelect("Wrap",["repeat","mirrored repeat","clamp to edge"],"clamp to edge"),a=i.inSwitch("Anisotropic",["0","1","2","4","8","16"],"0"),o=i.inSwitch("Data Format",["R","RG","RGB","RGBA","SRGBA"],"RGBA"),s=i.inValueBool("Flip",false),l=i.inValueBool("Pre Multiplied Alpha",false),u=i.inValueBool("Active",true),m=i.inBool("Save Memory",true),c=i.outTexture("Texture"),d=i.inBool("Add Cachebuster",false),h=i.inTriggerButton("Reload"),f=i.outNumber("Width"),p=i.outNumber("Height"),g=i.outNumber("Aspect Ratio"),v=i.outBoolNum("Loaded",0),b=i.outBoolNum("Loading",0);const x=i.patch.cgl;i.toWorkPortsNeedToBeLinked(c);i.setPortGroup("Size",[f,p]);let _=null;let O=null;let A=null;let I=CGL.Texture.FILTER_MIPMAP;let T=CGL.Texture.WRAP_REPEAT;let S=0;let C=0;l.setUiAttribs({hidePort:true});l.onChange=r.onChange=o.onChange=d.onChange=s.onChange=E;a.onChange=t.onChange=N;n.onChange=j;t.set("mipmap");n.set("repeat");c.set(CGL.Texture.getEmptyTexture(x));h.onTriggered=E;u.onChange=function(){if(u.get()){if(_!=r.get()||!A)E();else c.set(A)}else{c.set(CGL.Texture.getEmptyTexture(x));f.set(CGL.Texture.getEmptyTexture(x).width);p.set(CGL.Texture.getEmptyTexture(x).height);if(A)A.delete();i.setUiAttrib({extendTitle:""});A=null}};const y=function(){const e=CGL.Texture.getTempTexture(x);c.set(e)};function E(e){clearTimeout(C);C=setTimeout(function(){P(e)},1)}function M(){if(o.get()=="R")return CGL.Texture.PFORMATSTR_R8UB;if(o.get()=="RG")return CGL.Texture.PFORMATSTR_RG8UB;if(o.get()=="RGB")return CGL.Texture.PFORMATSTR_RGB8UB;if(o.get()=="SRGBA")return CGL.Texture.PFORMATSTR_SRGBA8;return CGL.Texture.PFORMATSTR_RGBA8UB}function P(e){i.checkMainloopExists();if(!u.get())return;if(O)O=x.patch.loading.finished(O);O=x.patch.loading.start(i.objName,r.get(),i);let t=i.patch.getFilePath(String(r.get()));if(d.get()||e===true)t=CABLES.cacheBust(t);if(String(r.get()).indexOf("data:")==0)t=r.get();let n=false;_=r.get();if(r.get()&&r.get().length>1){v.set(false);b.set(true);const a=r.get();i.setUiAttrib({extendTitle:CABLES.basename(t)});if(n)i.refreshParams();x.patch.loading.addAssetLoadingTask(()=>{i.setUiError("urlerror",null);CGL.Texture.load(x,t,function(e,t){x.checkFrameStarted("texture inittexture");if(r.get()!=a){O=x.patch.loading.finished(O);return}if(A)A.delete();if(e){const n=CGL.Texture.getErrorTexture(x);c.setRef(n);i.setUiError("urlerror",'could not load texture: "'+r.get()+'"',2);O=x.patch.loading.finished(O);return}f.set(t.width);p.set(t.height);g.set(t.width/t.height);A=t;c.setRef(A);b.set(false);v.set(true);if(m.get())A.image=null;if(O){O=x.patch.loading.finished(O)}i.checkMainloopExists()},{anisotropic:S,wrap:T,flip:s.get(),unpackAlpha:l.get(),pixelFormat:M(),filter:I});i.checkMainloopExists()})}else{y();O=x.patch.loading.finished(O)}}function N(){if(t.get()=="nearest")I=CGL.Texture.FILTER_NEAREST;else if(t.get()=="linear")I=CGL.Texture.FILTER_LINEAR;else if(t.get()=="mipmap")I=CGL.Texture.FILTER_MIPMAP;else if(t.get()=="Anisotropic")I=CGL.Texture.FILTER_ANISOTROPIC;a.setUiAttribs({greyout:I!=CGL.Texture.FILTER_MIPMAP});S=parseFloat(a.get());E()}function j(){if(n.get()=="repeat")T=CGL.Texture.WRAP_REPEAT;if(n.get()=="mirrored repeat")T=CGL.Texture.WRAP_MIRRORED_REPEAT;if(n.get()=="clamp to edge")T=CGL.Texture.WRAP_CLAMP_TO_EDGE;E()}i.onFileChanged=function(e){if(r.get()&&r.get().indexOf(e)>-1){c.set(CGL.Texture.getEmptyTexture(i.patch.cgl));c.set(CGL.Texture.getTempTexture(x));P(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.Math.RandomNumbers_v3=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValueFloat("Seed",1),a=e.inValueFloat("Min",0),i=e.inValueFloat("Max",1),r=e.outNumber("X"),o=e.outNumber("Y"),s=e.outNumber("Z"),l=e.outNumber("W");n.onChange=a.onChange=i.onChange=u;u();function u(){const e=a.get();const t=i.get();Math.randomSeed=Math.abs(n.get()||0)*571.1+1;r.set(Math.seededRandom()*(t-e)+e);o.set(Math.seededRandom()*(t-e)+e);s.set(Math.seededRandom()*(t-e)+e);l.set(Math.seededRandom()*(t-e)+e)}};Ops.Math.RandomNumbers_v3.prototype=new CABLES.Op;CABLES.OPS["d2b970e1-9406-4459-995c-5a594acd88e3"]={f:Ops.Math.RandomNumbers_v3,objName:"Ops.Math.RandomNumbers_v3"};Ops.Gl.ImageCompose.LUTMap=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={lut_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D texLut;\nUNI float amount;\n\nvoid main()\n{\n    vec4 textureColor = texture(tex, texCoord);\n    float blueColor = textureColor.b * 63.0;\n    \n    vec2 quad1;\n    quad1.y = floor(floor(blueColor) / 8.0);\n    quad1.x = floor(blueColor) - (quad1.y * 8.0);\n    \n    vec2 quad2;\n    quad2.y = floor(ceil(blueColor) / 8.0);\n    quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n    \n    highp vec2 texPos1;\n    texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n    texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);\n    \n    highp vec2 texPos2;\n    texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n    texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);\n    \n    vec4 newColor1 = texture(texLut, texPos1);\n    vec4 newColor2 = texture(texLut, texPos2);\n    \n    vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n    outColor= mix(textureColor,vec4(newColor.rgb, textureColor.w),amount);\n}\n"};let n=e.inTrigger("render");let a=e.outTrigger("trigger");let i=e.inTexture("LUT Image");let r=e.inValueSlider("Amount",1);let o=e.patch.cgl;let s=new CGL.Shader(o,e.name,e);s.setSource(s.getDefaultVertexShader(),t.lut_frag);let l=new CGL.Uniform(s,"t","tex",0);let u=new CGL.Uniform(s,"t","texLut",1);let m=new CGL.Uniform(s,"f","amount",r);n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;if(!i.get())return;o.pushShader(s);o.currentTextureEffect.bind();o.setTexture(0,o.currentTextureEffect.getCurrentSourceTexture().tex);o.setTexture(1,i.get().tex);o.currentTextureEffect.finish();o.popShader();a.trigger()}};Ops.Gl.ImageCompose.LUTMap.prototype=new CABLES.Op;CABLES.OPS["baba13d7-1cc2-4ba8-b66d-05425b0e5a75"]={f:Ops.Gl.ImageCompose.LUTMap,objName:"Ops.Gl.ImageCompose.LUTMap"};Ops.Gl.Phong.SpotLight_v5=function(){CABLES.Op.apply(this,arguments);const t=this;const k=t.attachments={};const n=t.patch.cgl;const B=t.inTrigger("Trigger In");const a=t.inBool("Cast Light",true);const i=t.inFloat("Intensity",2);const r=t.inFloat("Radius",10);const o=t.inFloat("X",1);const s=t.inFloat("Y",3);const l=t.inFloat("Z",1);const u=[o,s,l];t.setPortGroup("Position",u);const m=t.inFloat("Point At X",0);const c=t.inFloat("Point At Y",0);const d=t.inFloat("Point At Z",0);const h=[m,c,d];t.setPortGroup("Point At",h);const e=t.inFloatSlider("R",1);const D=t.inFloatSlider("G",1);const G=t.inFloatSlider("B",1);e.setUiAttribs({colorPick:true});const f=[e,D,G];t.setPortGroup("Color",f);const p=t.inFloatSlider("Specular R",1);const U=t.inFloatSlider("Specular G",1);const F=t.inFloatSlider("Specular B",1);p.setUiAttribs({colorPick:true});const V=[p,U,F];t.setPortGroup("Specular Color",V);const g=t.inFloat("Cone Angle",120);const v=t.inFloat("Inner Cone Angle",60);const b=t.inFloat("Spot Exponent",.97);const z=[g,v,b];t.setPortGroup("Cone Attributes",z);const X=t.inFloatSlider("Falloff",1e-5);const q=[a,i,r];t.setPortGroup("Light Attributes",q);const x=t.inBool("Cast Shadow",false);const _=t.inBool("Rendering Active",true);const O=t.inSwitch("Map Size",[256,512,1024,2048],512);const A=t.inFloatSlider("Shadow Strength",.99);const I=t.inFloat("Near",.1);const T=t.inFloat("Far",30);const S=t.inFloatSlider("Bias",1e-4);const C=t.inInt("Polygon Offset",0);const y=t.inFloatSlider("Normal Offset",0);const E=t.inFloatSlider("Blur Amount",0);t.setPortGroup("",[x]);t.setPortGroup("Shadow Map Settings",[O,_,A,I,T,S,C,y,E]);O.setUiAttribs({greyout:true,hidePort:true});_.setUiAttribs({greyout:true});A.setUiAttribs({greyout:true});I.setUiAttribs({greyout:true,hidePort:true});T.setUiAttribs({greyout:true,hidePort:true});E.setUiAttribs({greyout:true,hidePort:true});C.setUiAttribs({greyout:true,hidePort:true});y.setUiAttribs({greyout:true,hidePort:true});S.setUiAttribs({greyout:true,hidePort:true});const M=t.inBool("Enable Advanced",false);const P=t.inSwitch("MSAA",["none","2x","4x","8x"],"none");const N=t.inSwitch("Texture Filter",["Linear","Nearest","Mip Map"],"Linear");const j=t.inSwitch("Anisotropic",[0,1,2,4,8,16],"0");P.setUiAttribs({greyout:true,hidePort:true});N.setUiAttribs({greyout:true,hidePort:true});j.setUiAttribs({greyout:true,hidePort:true});t.setPortGroup("Advanced Options",[M,P,N,j]);let L=false;M.setUiAttribs({hidePort:true});M.onChange=function(){P.setUiAttribs({greyout:!M.get()});N.setUiAttribs({greyout:!M.get()});j.setUiAttribs({greyout:!M.get()})};const H=t.outTrigger("Trigger Out");const W=t.outTexture("Shadow Map");const Y=t.outNumber("World Position X");const Z=t.outNumber("World Position Y");const K=t.outNumber("World Position Z");const w=new CGL.Light(n,{type:"spot",position:[0,1,2].map(function(e){return u[e].get()}),color:[0,1,2].map(function(e){return f[e].get()}),specular:[0,1,2].map(function(e){return V[e].get()}),conePointAt:[0,1,2].map(function(e){return h[e].get()}),intensity:i.get(),radius:r.get(),falloff:X.get(),cosConeAngleInner:Math.cos(CGL.DEG2RAD*v.get()),cosConeAngle:Math.cos(CGL.DEG2RAD*g.get()),spotExponent:b.get(),castShadow:false,shadowStrength:A.get(),shadowBias:S.get(),normalOffset:y.get()});w.castLight=a.get();let Q=false;e.onChange=D.onChange=G.onChange=p.onChange=U.onChange=F.onChange=m.onChange=c.onChange=d.onChange=o.onChange=s.onChange=l.onChange;a.onChange=i.onChange=r.onChange=X.onChange=g.onChange=v.onChange=b.onChange=A.onChange=I.onChange=T.onChange=J;function J(){Q=true}x.onChange=function(){L=true;const e=x.get();O.setUiAttribs({greyout:!e});_.setUiAttribs({greyout:!e});A.setUiAttribs({greyout:!e});I.setUiAttribs({greyout:!e});T.setUiAttribs({greyout:!e});y.setUiAttribs({greyout:!e});E.setUiAttribs({greyout:!e});S.setUiAttribs({greyout:!e});C.setUiAttribs({greyout:!e});Q=true};let $=1/Number(O.get());function ee(){const e=Number(P.get().charAt(0));let t=null;const n=Number(j.get());if(N.get()=="Linear"){t=CGL.Texture.FILTER_LINEAR}else if(N.get()=="Nearest"){t=CGL.Texture.FILTER_NEAREST}else if(N.get()=="Mip Map"){t=CGL.Texture.FILTER_MIPMAP}const a=Number(O.get());const i={isFloatingPointTexture:true,filter:t};if(e)Object.assign(i,{multisampling:true,multisamplingSamples:e});Object.assign(i,{anisotropic:n});w.createFramebuffer(a,a,i);w.createBlurEffect(i)}P.onChange=j.onChange=N.onChange=O.onChange=function(){L=true};function te(){const e=Number(O.get());$=1/e;if(x.get()){w.createFramebuffer(Number(O.get()),Number(O.get()),{});w.createShadowMapShader();w.createBlurEffect({});w.createBlurShader();w.updateProjectionMatrix(null,I.get(),T.get(),g.get())}if(M.get())ee();L=false}const ne=vec3.create();const ae=vec3.create();const ie=vec3.create();const re=vec3.create();function oe(){if(n.frameStore.shadowPass)return;if(n.shouldDrawHelpers(t)){gui.setTransformGizmo({posX:o,posY:s,posZ:l});CABLES.GL_MARKER.drawLineSourceDest(t,w.position[0],w.position[1],w.position[2],w.conePointAt[0],w.conePointAt[1],w.conePointAt[2])}}let R=false;B.onTriggered=se;t.preRender=()=>{te();se()};function se(){if(L){if(n.frameStore.shadowPass)return;te()}if(!n.frameStore.shadowPass){if(!w.isUsed&&!R){t.setUiError("lightUsed","No operator is using this light. Make sure this op is positioned before an operator that uses lights. Also make sure there is an operator that uses lights after this.",1);R=true}else if(!w.isUsed&&R){}else if(w.isUsed&&R){t.setUiError("lightUsed",null);R=false}else if(w.isUsed&&!R){}w.isUsed=false}if(Q){w.position=[0,1,2].map(function(e){return u[e].get()});w.color=[0,1,2].map(function(e){return f[e].get()});w.specular=[0,1,2].map(function(e){return V[e].get()});w.conePointAt=[0,1,2].map(function(e){return h[e].get()});w.intensity=i.get();w.castLight=a.get();w.radius=r.get();w.falloff=X.get();w.cosConeAngleInner=Math.cos(CGL.DEG2RAD*v.get());w.cosConeAngle=Math.cos(CGL.DEG2RAD*g.get());w.spotExponent=b.get();w.castShadow=x.get();w.updateProjectionMatrix(null,I.get(),T.get(),g.get())}if(!n.frameStore.lightStack)n.frameStore.lightStack=[];vec3.set(ne,o.get(),s.get(),l.get());vec3.set(ae,m.get(),c.get(),d.get());vec3.transformMat4(ie,ne,n.mMatrix);vec3.transformMat4(re,ae,n.mMatrix);w.position=ie;w.conePointAt=re;Y.set(w.position[0]);Z.set(w.position[1]);K.set(w.position[2]);if(!n.frameStore.shadowPass)oe();n.frameStore.lightStack.push(w);if(x.get()){const e=1.5*E.get()*$;if(_.get())w.renderPasses(C.get(),e,function(){H.trigger()});W.setRef(w.getShadowMapDepth());n.frameStore.lightStack.pop();w.castShadow=x.get();w.blurAmount=E.get();w.normalOffset=y.get();w.shadowBias=S.get();w.shadowStrength=A.get();n.frameStore.lightStack.push(w)}H.trigger();n.frameStore.lightStack.pop()}};Ops.Gl.Phong.SpotLight_v5.prototype=new CABLES.Op;CABLES.OPS["76418c17-abd5-401b-82e2-688db6f966ee"]={f:Ops.Gl.Phong.SpotLight_v5,objName:"Ops.Gl.Phong.SpotLight_v5"};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 n=e.inTrigger("render"),a=e.inValueSlider("Strength",.5),i=e.inInt("Samples",40),r=e.inValue("X",0),o=e.inValue("Y",0),s=e.inTexture("Strength Map"),l=e.inSwitch("Source Strength Map",["R","G","B","A","Lum"],"R"),u=e.inBool("Invert Strength Map",false),m=e.outTrigger("trigger");e.setPortGroup("Strengh Map",[s,l,u]);const c=e.patch.cgl;const d=new CGL.Shader(c,"zoomblur");d.setSource(d.getDefaultVertexShader(),t.zoomblur_frag);const h=new CGL.Uniform(d,"t","tex",0),f=new CGL.Uniform(d,"t","texMask",1),p=new CGL.Uniform(d,"f","x",r),g=new CGL.Uniform(d,"f","y",o),v=new CGL.Uniform(d,"f","strength",a);i.onChange=l.onChange=u.onChange=s.onChange=b;b();function b(){d.toggleDefine("HAS_MASK",s.isLinked());d.toggleDefine("MASK_SRC_R",l.get()=="R");d.toggleDefine("MASK_SRC_G",l.get()=="G");d.toggleDefine("MASK_SRC_B",l.get()=="B");d.toggleDefine("MASK_SRC_A",l.get()=="A");d.toggleDefine("MASK_SRC_LUM",l.get()=="Lum");d.toggleDefine("MASK_INV",u.get());d.define("NUM_SAMPLES",i.get()+".0");l.setUiAttribs({greyout:!s.isLinked()});u.setUiAttribs({greyout:!s.isLinked()})}n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;if(a.get()>0){c.pushShader(d);c.currentTextureEffect.bind();c.setTexture(0,c.currentTextureEffect.getCurrentSourceTexture().tex);if(s.get()&&s.get().tex)c.setTexture(1,s.get().tex);c.currentTextureEffect.finish();c.popShader()}m.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.Gl.Perspective=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=t.inTrigger("render"),a=t.inSwitch("Axis",["Vertical","Horizontal"],"Vertical"),i=t.inValueFloat("fov y",45),r=t.inValueFloat("frustum near",.1),o=t.inValueFloat("frustum far",20),s=t.inValueBool("Auto Aspect Ratio",true),l=t.inValue("Aspect Ratio"),u=t.outTrigger("trigger"),m=t.outNumber("Aspect");i.onChange=o.onChange=r.onChange=h;i.setUiAttribs({title:"FOV Degrees"});t.setPortGroup("Field of View",[i]);t.setPortGroup("Frustrum",[r,o]);let c=0;let d=0;h();a.onChange=()=>{d=0;if(a.get()=="Horizontal")d=1};n.onTriggered=function(){const e=t.patch.cg;if(!e)return;c=e.getViewPort()[2]/e.getViewPort()[3];if(!s.get())c=l.get();m.set(c);e.pushPMatrix();if(d==0)mat4.perspective(e.pMatrix,i.get()*.0174533,c,r.get(),o.get());else f(e.pMatrix,i.get()*.0174533,c,r.get(),o.get());u.trigger();e.popPMatrix()};function h(){t.patch.cgl.frameStore.perspective={fovy:i.get(),zFar:o.get(),zNear:r.get()}}function f(e,t,n,a,i){let r;let o=1/t*2;e[0]=o;e[1]=0;e[2]=0;e[3]=0;e[4]=0;e[5]=o/(1/n);e[6]=0;e[7]=0;e[8]=0;e[9]=0;e[11]=-1;e[12]=0;e[13]=0;e[15]=0;if(i!=null&&i!==Infinity){r=1/(a-i);e[10]=(i+a)*r;e[14]=2*i*a*r}else{e[10]=-1;e[14]=-2*a}return e}};Ops.Gl.Perspective.prototype=new CABLES.Op;CABLES.OPS["7a78e163-d28c-4f70-a6d0-6d952da79f50"]={f:Ops.Gl.Perspective,objName:"Ops.Gl.Perspective"};Ops.Gl.ImageCompose.LumaKey_v3=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={lumakeyV2_frag:"IN vec2 texCoord;\nUNI float threshholdLow;\nUNI float threshholdHigh;\nUNI sampler2D text;\n\n\nfloat invLerp(float from, float to, float value) {\n  return (value - from) / (to - from);\n}\n\n\n\n\nfloat remap(float origFrom, float origTo, float targetFrom, float targetTo, float value){\n  float rel = invLerp(origFrom, origTo, value);\n  return mix(targetFrom, targetTo, rel);\n}\n\nvoid main()\n{\n   vec4 col = texture(text, texCoord );\n\n   float gray = dot(vec3(0.2126,0.7152,0.0722), col.rgb );\n\n    #ifdef INVERT\n        gray=1.0-gray;\n    #endif\n\n\n    if(gray < threshholdLow || gray > threshholdHigh) col.r=col.g=col.b=col.a=0.0;\n        #ifdef BLACKWHITE\n        else col.r=col.g=col.b=col.a=1.0;\n        #endif\n\n    #ifdef REMAP\n        col.rgb=vec3(remap(threshholdLow,threshholdHigh,0.0,1.0,gray));\n    #endif\n\n\n    #ifdef REMOVEALPHA\n        col.a=1.0;\n    #endif\n\n\n\n\n   outColor= col;\n}"};const n=e.inTrigger("render"),a=e.outTrigger("trigger"),i=e.inValueBool("Invert"),r=e.inValueBool("Black White"),o=e.inBool("Remove Alpha",true),s=e.inBool("Remap",true),l=e.inValueSlider("Threshold low ",.5),u=e.inValueSlider("Threshold high",1);const m=e.patch.cgl;const c=new CGL.Shader(m,"lumakey");c.setSource(c.getDefaultVertexShader(),t.lumakeyV2_frag);const d=new CGL.Uniform(c,"t","tex",0);const h=new CGL.Uniform(c,"f","threshholdLow",l);const f=new CGL.Uniform(c,"f","threshholdHigh",u);s.onChange=i.onChange=r.onChange=o.onChange=p;p();function p(){c.toggleDefine("BLACKWHITE",r.get());c.toggleDefine("INVERT",i.get());c.toggleDefine("REMOVEALPHA",o.get());c.toggleDefine("REMAP",s.get())}n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;m.pushShader(c);m.currentTextureEffect.bind();m.setTexture(0,m.currentTextureEffect.getCurrentSourceTexture().tex);m.currentTextureEffect.finish();m.popShader();a.trigger()}};Ops.Gl.ImageCompose.LumaKey_v3.prototype=new CABLES.Op;CABLES.OPS["3305b74b-d48a-4671-b456-fd9a64e8d0f3"]={f:Ops.Gl.ImageCompose.LumaKey_v3,objName:"Ops.Gl.ImageCompose.LumaKey_v3"};Ops.Gl.ImageCompose.BrightnessContrast=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={brightness_contrast_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float amountbright;\n\nvoid main()\n{\n    vec4 col=vec4(1.0,0.0,0.0,1.0);\n    col=texture(tex,texCoord);\n\n    // apply contrast\n    col.rgb = ((col.rgb - 0.5) * max(amount*2.0, 0.0))+0.5;\n\n    // apply brightness\n    col.rgb *= amountbright*2.0;\n\n    outColor = col;\n}"};const n=e.inTrigger("render"),a=e.inValueSlider("contrast",.5),i=e.inValueSlider("brightness",.5),r=e.outTrigger("trigger");const o=e.patch.cgl;const s=new CGL.Shader(o,"brightnesscontrast");s.setSource(s.getDefaultVertexShader(),t.brightness_contrast_frag);const l=new CGL.Uniform(s,"t","tex",0);const u=new CGL.Uniform(s,"f","amount",a);const m=new CGL.Uniform(s,"f","amountbright",i);n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;if(!o.currentTextureEffect.getCurrentSourceTexture())return;if(!CGL.TextureEffect.checkOpInEffect(e))return;o.pushShader(s);o.currentTextureEffect.bind();o.setTexture(0,o.currentTextureEffect.getCurrentSourceTexture().tex);o.currentTextureEffect.finish();o.popShader();r.trigger()}};Ops.Gl.ImageCompose.BrightnessContrast.prototype=new CABLES.Op;CABLES.OPS["54b89199-c594-4dff-bc48-82d6c7a55e8a"]={f:Ops.Gl.ImageCompose.BrightnessContrast,objName:"Ops.Gl.ImageCompose.BrightnessContrast"};Ops.Gl.ImageCompose.FastBlur_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={blur_frag:"\nUNI sampler2D tex;\n#ifdef USE_MASK\n    UNI sampler2D texMask;\n#endif\nUNI float amount;\nUNI float pass;\n\nIN vec2 texCoord;\n\nUNI float dirX;\nUNI float dirY;\nUNI float width;\nUNI float height;\n\nIN vec2 coord0;\nIN vec2 coord1;\nIN vec2 coord2;\nIN vec2 coord3;\nIN vec2 coord4;\nIN vec2 coord5;\nIN vec2 coord6;\n\n#ifdef HAS_MASK\n    UNI sampler2D imageMask;\n#endif\n\nvoid main()\n{\n    vec4 color = vec4(0.0);\n\n    #ifdef USE_MASK\n        #ifdef MASK_INVERT\n            if(texture(texMask,texCoord).r<0.5)\n            {\n                outColor= texture(tex, texCoord);\n                return;\n            }\n        #endif\n\n        #ifndef MASK_INVERT\n            if(texture(texMask,texCoord).r>0.5)\n            {\n                outColor= texture(tex, texCoord);\n                return;\n            }\n        #endif\n    #endif\n\n    color += texture(tex, coord0) * 0.06927096443792478;\n    color += texture(tex, coord1) * 0.1383328848652136;\n    color += texture(tex, coord2) * 0.21920904690397863;\n    color += texture(tex, coord3) * 0.14637421;\n    color += texture(tex, coord4) * 0.21920904690397863;\n    color += texture(tex, coord5) * 0.1383328848652136;\n    color += texture(tex, coord6) * 0.06927096443795711;\n\n    outColor= color;\n}",blur_vert:"\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\nOUT vec2 texCoord;\nOUT vec3 norm;\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\nUNI mat4 modelMatrix;\n\nUNI float pass;\nUNI float dirX;\nUNI float dirY;\nUNI float width;\nUNI float height;\n\nOUT vec2 coord0;\nOUT vec2 coord1;\nOUT vec2 coord2;\nOUT vec2 coord3;\nOUT vec2 coord4;\nOUT vec2 coord5;\nOUT vec2 coord6;\n\nvoid main()\n{\n    texCoord=attrTexCoord;\n    norm=attrVertNormal;\n    vec4 pos=vec4(vPosition,  1.0);\n    {{MODULE_VERTEX_POSITION}}\n\n    vec2 dir=vec2(dirX,dirY);\n    vec2 res=vec2( (1.) / width , (1.) / height )*dir;\n\n    coord3= attrTexCoord;\n\n    coord0= attrTexCoord + (-3.0368997744118595 * res);\n    coord1= attrTexCoord + (-2.089778445362373 * res);\n    coord2= attrTexCoord + (-1.2004366090034069 * res);\n    coord4= attrTexCoord + (1.2004366090034069 * res);\n    coord5= attrTexCoord + (2.089778445362373* res);\n    coord6= attrTexCoord + (3.0368997744118595 * res);\n\n    #ifdef CLAMP\n        coord0=clamp(coord0,0.0,1.0);\n        coord1=clamp(coord1,0.0,1.0);\n        coord2=clamp(coord2,0.0,1.0);\n        coord3=clamp(coord3,0.0,1.0);\n        coord4=clamp(coord4,0.0,1.0);\n        coord5=clamp(coord5,0.0,1.0);\n        coord6=clamp(coord6,0.0,1.0);\n    #endif\n\n    gl_Position = projMatrix * mvMatrix * pos;\n}\n"};const n=e.inTrigger("render"),a=e.outTrigger("trigger"),i=e.inFloat("Passes",3),r=e.inBool("Clamp",false),o=e.inDropDown("direction",["both","vertical","horizontal"],"both"),s=e.inTexture("Mask"),l=e.inBool("Mask Invert",false);const u=e.patch.cgl;const m=new CGL.Shader(u,"fastblur");e.setPortGroup("Mask",[s,l]);m.setSource(t.blur_vert,t.blur_frag);const c=new CGL.Uniform(m,"t","tex",0),d=new CGL.Uniform(m,"f","dirX",0),h=new CGL.Uniform(m,"f","dirY",0),f=new CGL.Uniform(m,"f","width",0),p=new CGL.Uniform(m,"f","height",0),g=new CGL.Uniform(m,"f","pass",0),v=new CGL.Uniform(m,"f","amount",i.get()),b=new CGL.Uniform(m,"t","texMask",1);i.onChange=()=>{v.setValue(i.get())};let x=0;o.onChange=()=>{if(o.get()=="both")x=0;if(o.get()=="horizontal")x=1;if(o.get()=="vertical")x=2};r.onChange=()=>{m.toggleDefine("CLAMP",r.get())};l.onChange=s.onChange=_;_();function _(){m.toggleDefine("USE_MASK",s.isLinked());m.toggleDefine("MASK_INVERT",l.get());l.setUiAttribs({greyout:!s.isLinked()})}n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;f.setValue(u.currentTextureEffect.getCurrentSourceTexture().width);p.setValue(u.currentTextureEffect.getCurrentSourceTexture().height);const t=i.get();if(s.get())u.setTexture(1,s.get().tex);for(let e=0;e<t;e++){u.pushShader(m);g.setValue(e/t);if(x===0||x==2){u.currentTextureEffect.bind();u.setTexture(0,u.currentTextureEffect.getCurrentSourceTexture().tex);d.setValue(0);h.setValue(1+e*e);u.currentTextureEffect.finish()}if(x===0||x==1){u.currentTextureEffect.bind();u.setTexture(0,u.currentTextureEffect.getCurrentSourceTexture().tex);d.setValue(1+e*e);h.setValue(0);u.currentTextureEffect.finish()}u.popShader()}a.trigger()}};Ops.Gl.ImageCompose.FastBlur_v2.prototype=new CABLES.Op;CABLES.OPS["61ed277f-d096-43b2-9de8-dc87fb3a9169"]={f:Ops.Gl.ImageCompose.FastBlur_v2,objName:"Ops.Gl.ImageCompose.FastBlur_v2"};Ops.Gl.Phong.AmbientLight_v4=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTrigger("Trigger In");const a=e.inValueSlider("R",.1);a.setUiAttribs({colorPick:true});const i=e.inValueSlider("G",.125);const r=e.inValueSlider("B",.15);const o=e.inValueSlider("Intensity",1);const s=[a,i,r];e.setPortGroup("Color",s);const l=e.outTrigger("Trigger Out");function u(e){this.type=e.type||"point";this.color=e.color||[1,1,1];this.specular=e.specular||[0,0,0];this.position=e.position||null;this.intensity=e.intensity||1;this.constantAttenuation=e.constantAttenuation||0;this.linearAttenuation=e.linearAttenuation||0;this.quadraticAttenuation=e.quadraticAttenuation||0;this.radius=e.radius||1;this.falloff=e.falloff||1;this.spotExponent=e.spotExponent||1;this.coneAngleInner=e.coneAngleInner||0;this.coneAngle=e.coneAngle||0;this.cosConeAngle=Math.cos(CGL.DEG2RAD*this.coneAngle);this.conePointAt=e.conePointAt||[0,0,0];this.nearFar=[0,0];this.shadowStrength=0;this.shadowBias=0;return this}const m=e.patch.cgl;const c=new u({type:"ambient",color:[0,1,2].map(function(e){return s[e].get()}),intensity:o.get()});const d={color:[a,i,r],intensity:o};Object.keys(d).forEach(function(t){if(d[t].length){for(let e=0;e<d[t].length;e+=1){d[t][e].onChange=function(){c[t][e]=d[t][e].get()}}}else{d[t].onChange=function(){c[t]=d[t].get()}}});n.onTriggered=function(){if(!m.frameStore.lightStack)m.frameStore.lightStack=[];m.frameStore.lightStack.push(c);l.trigger();m.frameStore.lightStack.pop()}};Ops.Gl.Phong.AmbientLight_v4.prototype=new CABLES.Op;CABLES.OPS["235a18d1-a8de-4034-962d-2848017e27cd"]={f:Ops.Gl.Phong.AmbientLight_v4,objName:"Ops.Gl.Phong.AmbientLight_v4"};Ops.Gl.Meshes.Cylinder_v2=function(){CABLES.Op.apply(this,arguments);const I=this;const e=I.attachments={};const t=I.inTrigger("render"),n=I.inValueBool("Draw",true),T=I.inValueInt("segments",40),S=I.inValueInt("stacks",1),C=I.inValueFloat("length",1),y=I.inValueFloat("outer radius",.5),E=I.inValueFloat("inner radius",0),M=I.inValueSelect("UV mode",["simple","atlas"],"simple"),P=I.inValueBool("Flip Mapping",false),N=I.inValueBool("Caps",true),j=I.inValueBool("Flat Normals",false),a=I.outTrigger("next"),L=I.outObject("geometry"),w=new CGL.Geometry("cylinder");n.setUiAttribs({title:"Render mesh"});const R=Math.PI*2,i=I.patch.cgl;let k=true;let B=null;M.setUiAttribs({hidePort:true});I.preRender=r;function r(){const e=P.get();const t=Math.max(T.get(),3)|0,n=Math.max(E.get(),0),a=Math.max(y.get(),n),i=Math.max(S.get(),S.defaultValue)|0,r=C.get(),o=r/i,s=R/t,l=M.get();let u=[],m=[],c=[],d=[],h=[],f=[],p,g,v,b,x,_,O,A;if(l=="atlas")A=.5;else A=1;for(b=0,v=-r/2;b<=i;b++,v+=o){for(x=_=0;x<=t;x++,_+=s){u.push((p=Math.sin(_))*a,(g=Math.cos(_))*a,v);O=Math.sqrt(p*p+g*g);p/=O;g/=O;m.push(p,g,0);c.push(-g,p,0);d.push(0,0,1);if(e)h.push(x/t,1-(v/r+.5)*A);else h.push((v/r+.5)*A,x/t)}}for(x=0;x<i;x++){for(b=0,O=x*(t+1);b<t;b++,O++){_=O+1;f.push(O+(t+1),_,O,O+(t+1),_+(t+1),_)}}if(n){O=u.length;for(b=x=0;b<O;b+=3,x+=2){u.push(u[b]/a*n,u[b+1]/a*n,u[b+2]);m.push(-m[b],-m[b+1],0);c.push(-c[b],-c[b+1],0);d.push(0,-d[b+1],-d[b+2]);h.push(h[x],1-h[x+1])}_=O/3;O=f.length;for(b=0;b<O;b+=6){f.push(_+f[b],_+f[b+2],_+f[b+1],_+f[b+3],_+f[b+5],_+f[b+4])}if(N.get()){_=u.length;A=_/2;O=t*3;Array.prototype.push.apply(u,u.slice(0,O));Array.prototype.push.apply(u,u.slice(A,A+O));Array.prototype.push.apply(u,u.slice(A-O,A));Array.prototype.push.apply(u,u.slice(_-O,_));O=t*2;for(b=0;b<O;b++)m.push(0,0,-1),c.push(-1,0,0),d.push(0,-1,0);for(b=0;b<O;b++)m.push(0,0,1),c.push(1,0,0),d.push(0,1,0);if(l=="atlas"){O=n/a*.5;for(b=A=0;b<t;b++,A+=s)h.push(Math.sin(A)*.25+.75,Math.cos(A)*.25+.25);for(b=A=0;b<t;b++,A+=s)h.push((Math.sin(A)*O+.5)*.5+.5,(Math.cos(A)*O+.5)*.5);for(b=A=0;b<t;b++,A+=s)h.push(Math.sin(A)*.25+.75,Math.cos(A)*.25+.75);for(b=A=0;b<t;b++,A+=s)h.push((Math.sin(A)*O+.5)*.5+.5,(Math.cos(A)*O+.5)*.5+.5)}else{for(b=0;b<O;b++)h.push(0,0);for(b=0;b<O;b++)h.push(1,1)}for(b=0,A=_/3+p;b<t-1;b++,A++){f.push(A+1,A+t,A,A+t+1,A+t,A+1)}f.push(A+t,_/3+p,_/3+t+p,A+t,A,_/3+p);p+=t*2;for(b=0,A=_/3+p;b<t-1;b++,A++){f.push(A,A+t,A+1,A+1,A+t,A+t+1)}f.push(_/3+t+p,_/3+p,A+t,_/3+p,A,A+t)}}else{_=u.length;O=_/3;u.push(0,0,-r/2);Array.prototype.push.apply(u,u.slice(0,t*3));for(b=0;b<=t;b++)m.push(0,0,-1),c.push(-1,0,0),d.push(0,-1,0);if(N.get()){u.push(0,0,r/2);Array.prototype.push.apply(u,u.slice(_-t*3,_));for(b=0;b<=t;b++)m.push(0,0,1),c.push(1,0,0),d.push(0,1,0);if(l=="atlas"){h.push(.75,.25);for(b=_=0;b<t;b++,_+=s)h.push(Math.sin(_)*.25+.75,Math.cos(_)*.25+.25);h.push(.75,.75);for(b=_=0;b<t;b++,_+=s)h.push(Math.sin(_)*.25+.75,Math.cos(_)*.25+.75)}else{for(b=0;b<=t;b++)h.push(0,0);for(b=0;b<=t;b++)h.push(1,1)}f.push(O+1,O,O+t);for(b=1;b<t;b++)f.push(O,O+b,O+b+1);O+=t+1;f.push(O,O+1,O+t);for(b=1;b<t;b++)f.push(O,O+b+1,O+b);O+=t+1}}w.clear();w.vertices=u;w.texCoords=h;w.vertexNormals=m;w.tangents=c;w.biTangents=d;w.verticesIndices=f;if(j.get())w.unIndex();L.setRef(w);if(I.patch.cg)if(!B)B=I.patch.cg.createMesh(w,{opId:I.id});else B.setGeom(w);k=false}t.onTriggered=function(){if(k)r();if(n.get()&&B)B.render(i.getShader());a.trigger()};T.onChange=y.onChange=E.onChange=N.onChange=C.onChange=P.onChange=S.onChange=j.onChange=M.onChange=function(){k=true};I.onDelete=function(){if(B)B.dispose()}};Ops.Gl.Meshes.Cylinder_v2.prototype=new CABLES.Op;CABLES.OPS["2899ad67-1e64-4692-af2a-c3b9078f1b5f"]={f:Ops.Gl.Meshes.Cylinder_v2,objName:"Ops.Gl.Meshes.Cylinder_v2"};Ops.Gl.ShaderEffects.Twist_v3=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={twist_vert:"\nfloat MOD_angle_rad = MOD_amount * 3.14159 / 180.0;\n\nfloat MOD_axis=pos.y;\n\n#ifdef MOD_AXIS_Z\n    MOD_axis=pos.z;\n#endif\n\n#ifdef MOD_AXIS_X\n    MOD_axis=pos.x;\n#endif\n\nfloat MOD_ang = (MOD_height*0.5 + MOD_axis)/MOD_height * MOD_angle_rad;\n\npos = MOD_twist(pos, MOD_ang);\n\n\nnorm = normalize(MOD_twist( vec4(norm, 1.0), MOD_ang ).xyz);\n",twist_head_vert:"vec4 MOD_twist(vec4 pos, float t)\n{\n\tfloat st = sin(t);\n\tfloat ct = cos(t);\n\tvec4 new_pos;\n\n\tnew_pos.x = pos.x;\n\tnew_pos.y = pos.y;\n\tnew_pos.z = pos.z;\n\tnew_pos.w = pos.w;\n\n    #ifdef MOD_AXIS_Z\n    \tnew_pos.x = pos.y*ct - pos.x*st;\n    \tnew_pos.y = pos.y*st + pos.x*ct;\n    #endif\n\n    #ifdef MOD_AXIS_Y\n    \tnew_pos.x = pos.x*ct - pos.z*st;\n    \tnew_pos.z = pos.x*st + pos.z*ct;\n    #endif\n\n    #ifdef MOD_AXIS_X\n    \tnew_pos.y = pos.y*ct - pos.z*st;\n    \tnew_pos.z = pos.y*st + pos.z*ct;\n    #endif\n\n\treturn( new_pos );\n}\n"};const n=e.inTrigger("render"),a=e.outTrigger("Trigger"),i=e.inFloat("Degree",180),r=e.inFloat("Height",2),o=e.inValueSelect("Axis",["X","Y","Z"],"Y");const s=e.patch.cgl;o.onChange=u;const l=new CGL.ShaderModifier(s,e.name,{opId:e.id});l.addModule({name:"MODULE_VERTEX_POSITION",srcHeadVert:t.twist_head_vert,srcBodyVert:t.twist_vert});u();l.addUniformVert("f","MOD_amount",i);l.addUniformVert("f","MOD_height",r);function u(){l.toggleDefine("MOD_AXIS_X",o.get()=="X");l.toggleDefine("MOD_AXIS_Y",o.get()=="Y");l.toggleDefine("MOD_AXIS_Z",o.get()=="Z")}n.onTriggered=function(){if(s.shouldDrawHelpers(e)){CABLES.GL_MARKER.drawCube(e,1,r.get()/2,1)}l.bind();a.trigger();l.unbind()}};Ops.Gl.ShaderEffects.Twist_v3.prototype=new CABLES.Op;CABLES.OPS["4635abe3-a6b1-413f-9cd1-fbf64f8c4942"]={f:Ops.Gl.ShaderEffects.Twist_v3,objName:"Ops.Gl.ShaderEffects.Twist_v3"};Ops.Gl.ShaderEffects.Bend_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={bend_vert:"\n\nvoid MOD_bendDistort(inout vec3 pos, inout vec3 norm)\n{\n    pos = (MOD_transMatrix * vec4(pos, 1.0)).xyz;\n    norm = (vec4(norm, 0.0) * MOD_invTransMatrix).xyz;\n\n    float PI = 3.14159265;\n    if (abs(MOD_amount) > 1e-5) {\n        float bendAngle = MOD_amount;\n        float radius = 1.0 / bendAngle;\n\n        // float d = clamp(pos.x, MOD_range.x, MOD_range.y);\n        float d = clamp(pos.x, MOD_range.x, MOD_range.y);\n        float th = PI * 0.5 + (bendAngle * d);\n        float s = sin(th);\n        float c = cos(th);\n        pos.xy = vec2(s * (pos.x - d) - c * (radius + pos.y),\n                      c * (pos.x - d) + s * (radius + pos.y) - radius);\n        norm.xy = vec2(s * norm.x - c * norm.y,\n                       c * norm.x + s * norm.y);\n    }\n\n    pos = (MOD_invTransMatrix * vec4(pos, 1.0)).xyz;\n    norm = (vec4(norm, 0.0) * MOD_transMatrix).xyz;\n}\n"};const n=e.inTrigger("render");const a=e.inValue("Amount");const i=e.inValue("RotX");const r=e.inValue("RotY");const o=e.inValue("RotZ");const s=e.inValue("Scale",2);const l=e.inValue("Offset",.25);const u=e.inValueBool("Limited",true);const m=e.outTrigger("trigger");const c=t.bend_vert;const d="".endl()+"   MOD_bendDistort(pos.xyz, norm);".endl();const h=null;const f=null;const p=null;const g=null;const v=e.patch.cgl;let b=false;const x=mat4.create();const _=mat4.create();let O=0;function A(){b=false}i.onChange=A;r.onChange=A;o.onChange=A;s.onChange=A;l.onChange=A;const I=new CGL.ShaderModifier(v,e.name,{opId:e.id});I.addModule({name:"MODULE_VERTEX_POSITION",srcHeadVert:t.bend_vert,srcBodyVert:d});I.addUniformVert("f","MOD_amount",0);I.addUniformVert("2f","MOD_range",[0,1]);I.addUniformVert("m4","MOD_transMatrix",x);I.addUniformVert("m4","MOD_invTransMatrix",_);a.onChange=function(){O=a.get()*CGL.DEG2RAD};mat4.identity(x);mat4.identity(_);const T=vec3.create();const S=vec4.create();function C(){if(b)return;vec3.set(T,l.get(),0,0);const e=1/s.get();vec3.set(S,e,e,e);mat4.identity(x);mat4.translate(x,x,T);mat4.rotateX(x,x,i.get()*CGL.DEG2RAD);mat4.rotateY(x,x,r.get()*CGL.DEG2RAD);mat4.rotateZ(x,x,o.get()*CGL.DEG2RAD);mat4.scale(x,x,S);mat4.invert(_,x);b=true}n.onTriggered=function(){I.setUniformValue("MOD_range",u.get()?[0,1]:[-99999,99999]);C();I.bind();I.setUniformValue("MOD_amount",O);m.trigger();I.unbind()}};Ops.Gl.ShaderEffects.Bend_v2.prototype=new CABLES.Op;CABLES.OPS["7476156e-3ca3-445a-bd30-1b9373a6af4c"]={f:Ops.Gl.ShaderEffects.Bend_v2,objName:"Ops.Gl.ShaderEffects.Bend_v2"};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 n=e.inTrigger("render");const a=e.outTrigger("trigger");const i=e.inValueFloat("amount");const r=e.inSwitch("direction",["both","vertical","horizontal"],"both");const o=e.inValueBool("Fast",true);const s=e.patch.cgl;i.set(10);let l=new CGL.Shader(s,"blur");l.define("FASTBLUR");o.onChange=function(){if(o.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 m=new CGL.Uniform(l,"f","dirX",0);let c=new CGL.Uniform(l,"f","dirY",0);let d=new CGL.Uniform(l,"f","width",0);let h=new CGL.Uniform(l,"f","height",0);let f=new CGL.Uniform(l,"f","amount",i.get());i.onChange=function(){f.setValue(i.get())};let p=new CGL.Uniform(l,"t","imageMask",1);let g=false;function v(){if(s.currentTextureEffect.getCurrentSourceTexture().width==s.canvasWidth&&s.currentTextureEffect.getCurrentSourceTexture().height==s.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 b=0;r.onChange=function(){if(r.get()=="both")b=0;if(r.get()=="horizontal")b=1;if(r.get()=="vertical")b=2};let x=e.inTexture("mask");x.onChange=function(){if(x.get()&&x.get().tex)l.define("HAS_MASK");else l.removeDefine("HAS_MASK")};n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;s.pushShader(l);d.setValue(s.currentTextureEffect.getCurrentSourceTexture().width);h.setValue(s.currentTextureEffect.getCurrentSourceTexture().height);v();if(b===0||b==2){s.currentTextureEffect.bind();s.setTexture(0,s.currentTextureEffect.getCurrentSourceTexture().tex);if(x.get()&&x.get().tex){s.setTexture(1,x.get().tex)}m.setValue(0);c.setValue(1);s.currentTextureEffect.finish()}if(b===0||b==1){s.currentTextureEffect.bind();s.setTexture(0,s.currentTextureEffect.getCurrentSourceTexture().tex);if(x.get()&&x.get().tex){s.setTexture(1,x.get().tex)}m.setValue(1);c.setValue(0);s.currentTextureEffect.finish()}s.popShader();a.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.ImageCompose.Invert_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={invert_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D texMask;\nUNI float amount;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n    vec4 col=texture(tex,texCoord);\n\n    #ifdef USE_MASK\n        #ifdef MASK_INVERT\n            if(texture(texMask,texCoord).r>0.5)\n            {\n                outColor= col;\n                return;\n            }\n        #endif\n\n        #ifndef MASK_INVERT\n            if(texture(texMask,texCoord).r<0.5)\n            {\n                outColor= col;\n                return;\n            }\n        #endif\n    #endif\n\n\n    vec3 m=vec3( INVR , INVG , INVB );\n    vec4 invert = vec4(clamp(m-col.rgb,0.0,1.0),col.a);\n\n    outColor=cgl_blendPixel(col,invert,amount);\n\n    // outColor.rgb=m;\n}\n"};const n=e.inTrigger("render"),a=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),i=e.inValueSlider("Amount",1),r=e.inBool("Mask Invert",false),o=e.inTexture("Mask"),s=e.inBool("Invert R",true),l=e.inBool("Invert G",true),u=e.inBool("Invert B",true),m=e.outTrigger("trigger");const c=e.patch.cgl;const d=new CGL.Shader(c,e.name,e);d.setSource(d.getDefaultVertexShader(),t.invert_frag);const h=new CGL.Uniform(d,"t","tex",0),f=new CGL.Uniform(d,"f","amount",i),p=new CGL.Uniform(d,"t","texMask",1);CGL.TextureEffect.setupBlending(e,d,a,i);r.onChange=s.onChange=l.onChange=u.onChange=o.onLinkChanged=g;g();function g(){d.toggleDefine("USE_MASK",o.isLinked());d.toggleDefine("MASK_INVERT",r.get());d.define("INVR",s.get()?"1.0":"0.0");d.define("INVG",l.get()?"1.0":"0.0");d.define("INVB",u.get()?"1.0":"0.0")}n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;c.pushShader(d);c.currentTextureEffect.bind();c.setTexture(0,c.currentTextureEffect.getCurrentSourceTexture().tex);if(o.get())c.setTexture(1,o.get().tex);c.currentTextureEffect.finish();c.popShader();m.trigger()}};Ops.Gl.ImageCompose.Invert_v2.prototype=new CABLES.Op;CABLES.OPS["56e8c95b-da89-423b-9d31-23351c263bb6"]={f:Ops.Gl.ImageCompose.Invert_v2,objName:"Ops.Gl.ImageCompose.Invert_v2"};Ops.Gl.Meshes.TextMesh_v2=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={textmesh_frag:"{{MODULES_HEAD}}\n\n#define INSTANCING\n\nUNI sampler2D tex;\n#ifdef DO_MULTEX\n    UNI sampler2D texMul;\n#endif\n#ifdef DO_MULTEX_MASK\n    UNI sampler2D texMulMask;\n#endif\nIN vec2 texCoord;\nIN vec2 texPos;\nUNI float r;\nUNI float g;\nUNI float b;\nUNI float a;\n\nflat IN float frag_instIndex;\n\nvoid main()\n{\n    {{MODULE_BEGIN_FRAG}}\n\n    vec4 col=texture(tex,texCoord);\n    col.a=col.r;\n    col.r*=r;\n    col.g*=g;\n    col.b*=b;\n    col*=a;\n\n    if(col.a==0.0)discard;\n\n    #ifdef DO_MULTEX\n        col*=texture(texMul,texPos);\n    #endif\n\n    #ifdef DO_MULTEX_MASK\n        col*=texture(texMulMask,texPos).r;\n    #endif\n\n    {{MODULE_COLOR}}\n\n    outColor=col;\n}",textmesh_vert:"{{MODULES_HEAD}}\n\nUNI sampler2D tex;\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\nUNI float scale;\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN mat4 instMat;\nIN vec2 attrTexOffsets;\nIN vec2 attrTexSize;\nIN vec2 attrTexPos;\nIN float attrVertIndex;\nIN float instanceIndex;\nflat OUT float frag_instIndex;\n\nOUT vec2 texPos;\n\nOUT vec2 texCoord;\nOUT vec4 modelPos;\n\nvoid main()\n{\n\n    texCoord=(attrTexCoord*(attrTexSize)) + attrTexOffsets;\n    mat4 instMVMat=instMat;\n    instMVMat[3][0]*=scale;\n\n    texPos=attrTexPos;\n\n    vec4 pos=vec4( vPosition.x*(attrTexSize.x/attrTexSize.y)*scale,vPosition.y*scale,vPosition.z*scale, 1. );\n\n    mat4 mvMatrix=viewMatrix * modelMatrix * instMVMat;\n    frag_instIndex=instanceIndex;\n\n    {{MODULE_VERTEX_POSITION}}\n\n    gl_Position = projMatrix * mvMatrix * pos;\n}\n\n"};const n=t.inTrigger("Render"),b=t.inString("Text","cables"),a=t.inFloat("Scale Text",1),i=t.inValueFloat("Scale",1),m=t.inString("Font","Arial"),x=t.inValueSelect("align",["left","center","right"],"center"),r=t.inValueSelect("vertical align",["Top","Middle","Bottom"],"Middle"),_=t.inValueFloat("Line Height",1),O=t.inValueFloat("Letter Spacing"),s=t.inSwitch("filter",["nearest","linear","mipmap"],"mipmap"),l=t.inSwitch("Anisotropic",[0,1,2,4,8,16],0),o=t.inTexture("Texture Color"),u=t.inTexture("Texture Mask"),k=t.outTrigger("Next"),A=t.outTexture("texture"),B=t.outNumber("Total Lines",0),D=t.outNumber("Width",0),G=t.outBoolNum("Font Available",0);const I=t.patch.cgl;const c=vec3.create();vec3.set(c,1,1,1);t.toWorkPortsNeedToBeLinked(n);t.setPortGroup("Masking",[o,u]);i.setUiAttribs({title:"Line Scale"});A.setUiAttribs({hidePort:true});const d=1024;let h=false;let f=true;x.onChange=b.onChange=_.onChange=U;function U(){f=true}let p=null;CABLES.OpTextureMeshCanvas={};let g=0;const F=null;let T=null;let S=true;let C=true;a.onChange=()=>{vec3.set(c,a.get(),a.get(),a.get())};l.onChange=s.onChange=()=>{y().texture=null;C=true};u.onChange=o.onChange=function(){E.toggleDefine("DO_MULTEX",o.get());E.toggleDefine("DO_MULTEX_MASK",u.get())};A.set(null);m.onChange=function(){C=true;S=true;v()};t.patch.on("fontLoaded",e=>{if(e==m.get()){C=true;S=true}});function v(){const e=h;try{h=document.fonts.check('20px "'+m.get()+'"')}catch(e){t.logError(e)}if(!e&&h){G.set(true);C=true;S=true}if(!h)setTimeout(v,250)}r.onChange=function(){if(r.get()=="Middle")g=0;else if(r.get()=="Top")g=1;else if(r.get()=="Bottom")g=2};function y(){p=""+m.get();if(CABLES.OpTextureMeshCanvas.hasOwnProperty(p))return CABLES.OpTextureMeshCanvas[p];const e=document.createElement("canvas");e.dataset.font=m.get();e.id="texturetext_"+CABLES.generateUUID();e.style.display="none";const t=document.getElementsByTagName("body")[0];t.appendChild(e);const n=e.getContext("2d");CABLES.OpTextureMeshCanvas[p]={ctx:n,canvas:e,chars:{},characters:"",fontSize:320};return CABLES.OpTextureMeshCanvas[p]}t.onDelete=function(){if(p&&CABLES.OpTextureMeshCanvas[p])CABLES.OpTextureMeshCanvas[p].canvas.remove()};const E=new CGL.Shader(I,"TextMesh",this);E.setSource(e.textmesh_vert,e.textmesh_frag);const V=new CGL.Uniform(E,"t","tex",0);const z=new CGL.Uniform(E,"t","texMul",1);const X=new CGL.Uniform(E,"t","texMulMask",2);const q=new CGL.Uniform(E,"f","scale",i);const M=t.inValueSlider("r",1),P=t.inValueSlider("g",1),N=t.inValueSlider("b",1),H=t.inValueSlider("a",1),W=new CGL.Uniform(E,"f","r",M),Y=new CGL.Uniform(E,"f","g",P),Z=new CGL.Uniform(E,"f","b",N),K=new CGL.Uniform(E,"f","a",H);M.setUiAttribs({colorPick:true});t.setPortGroup("Display",[i,m]);t.setPortGroup("Alignment",[x,r]);t.setPortGroup("Color",[M,P,N,H]);let j=0;const L=vec3.create();let Q=-1;let w=false;n.onTriggered=function(){if(f){J();f=false}const e=y();if(e.lastChange!=Q){S=true;Q=e.lastChange}if(C)$();if(S)J();if(T&&T.numInstances>0){I.pushBlendMode(CGL.BLEND_NORMAL,true);I.pushShader(E);I.setTexture(0,A.get().tex);const t=o.get();if(t)I.setTexture(1,t.tex);const n=u.get();if(n)I.setTexture(2,n.tex);if(g===2)vec3.set(L,0,j,0);else if(g===1)vec3.set(L,0,0,0);else if(g===0)vec3.set(L,0,j/2,0);L[1]-=_.get();I.pushModelMatrix();mat4.translate(I.mMatrix,I.mMatrix,L);mat4.scale(I.mMatrix,I.mMatrix,c);if(!w)T.render(I.getShader());I.popModelMatrix();I.setTexture(0,null);I.popShader();I.popBlendMode()}k.trigger()};O.onChange=function(){S=true};function J(){const e=String(b.get()+"");if(!A.get())return;const r=y();if(!r.geom){r.geom=new CGL.Geometry("textmesh");r.geom.vertices=[1,1,0,0,1,0,1,0,0,0,0,0];r.geom.texCoords=new Float32Array([1,1,0,1,1,0,0,0]);r.geom.verticesIndices=[0,1,2,2,1,3]}if(!T)T=new CGL.Mesh(I,r.geom);const o=e.split("\n");B.set(o.length);const s=[];const l=[];const u=[];const m=[];const c=mat4.create();let d=0;let h=0;C=false;for(let i=0;i<o.length;i++){const f=o[i];const p=f.length;let t=0;let n=0;let a=0;for(let e=0;e<p;e++){const g=f.substring(e,e+1);const v=r.chars[String(g)];if(v){a+=v.texCoordWidth/v.texCoordHeight;a+=O.get()}}a-=O.get();j=0;if(x.get()=="left")n=0;else if(x.get()=="right")n=a;else if(x.get()=="center")n=a/2;j=(i+1)*_.get();for(let e=0;e<p;e++){const g=f.substring(e,e+1);const v=r.chars[String(g)];if(!v){C=true;return}else{m.push(t/a*.99+.005,(1-i/(o.length-1))*.99+.005);l.push(v.texCoordX,1-v.texCoordY-v.texCoordHeight);u.push(v.texCoordWidth,v.texCoordHeight);mat4.identity(c);mat4.translate(c,c,[t-n,0-i*_.get(),0]);t+=v.texCoordWidth/v.texCoordHeight+O.get();h=Math.max(h,t-n);s.push(Array.prototype.slice.call(c));d++}}}const t=[].concat.apply([],s);w=false;if(t.length==0)w=true;const n=t.length/16;T.setNumInstances(n);if(T.numInstances==0){w=true;return}D.set(h*i.get());T.setAttribute("instMat",new Float32Array(t),16,{instanced:true});T.setAttribute("attrTexOffsets",new Float32Array(l),2,{instanced:true});T.setAttribute("attrTexSize",new Float32Array(u),2,{instanced:true});T.setAttribute("attrTexPos",new Float32Array(m),2,{instanced:true});S=false;if(C)$()}function R(t,n){const a=y();if(!n)a.chars={};const i=a.ctx;i.font=t+"px "+m.get();i.textAlign="left";let r=0;let o=0;const s=t*1.4;const e={fits:true};for(let e=0;e<a.characters.length;e++){const l=String(a.characters.substring(e,e+1));const u=i.measureText(l).width;if(o+u>=d){r+=s+2;o=0}if(!n){a.chars[l]={str:l,texCoordX:o/d,texCoordY:r/d,texCoordWidth:u/d,texCoordHeight:s/d};i.fillText(l,o,r+t)}o+=u+12}if(r>d-s){e.fits=false}e.spaceLeft=d-r;return e}function $(){let e=CGL.Texture.FILTER_LINEAR;if(s.get()=="nearest")e=CGL.Texture.FILTER_NEAREST;if(s.get()=="mipmap")e=CGL.Texture.FILTER_MIPMAP;const t=y();let n=String(b.get());if(n==null||n==undefined)n="";for(let e=0;e<n.length;e++){const o=n.substring(e,e+1);if(t.characters.indexOf(o)==-1){t.characters+=o;C=true}}const a=t.ctx;t.canvas.width=t.canvas.height=d;if(!t.texture)t.texture=CGL.Texture.createFromImage(I,t.canvas,{filter:e,anisotropic:parseFloat(l.get())});t.texture.setSize(d,d);a.fillStyle="transparent";a.clearRect(0,0,d,d);a.fillStyle="rgba(255,255,255,255)";let i=t.fontSize+40;let r=R(i,true);while(!r.fits){i-=5;r=R(i,true)}R(i,false);a.restore();t.texture.initTexture(t.canvas,e);t.texture.unpackAlpha=true;A.set(t.texture);t.lastChange=CABLES.now();S=true;C=false}};Ops.Gl.Meshes.TextMesh_v2.prototype=new CABLES.Op;CABLES.OPS["2390f6b3-2122-412e-8c8d-5c2f574e8bd1"]={f:Ops.Gl.Meshes.TextMesh_v2,objName:"Ops.Gl.Meshes.TextMesh_v2"};Ops.Html.FontFile_v2=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={};const r=i.inUrl("file",[".otf",".ttf",".woff",".woff2"]),o=i.inString("family"),s=i.inBool("Active",true),l=i.outBoolNum("Loaded"),u=i.outTrigger("Loaded Trigger");let m=null;let c;let d=null;let t=null;let h=null;let f="";r.onChange=function(){l.set(false);a(null)};s.onChange=o.onChange=()=>{n()};function n(){clearTimeout(t);t=setTimeout(()=>{a(null)},50)}i.patch.on("windowChanged",e=>{c=null;a(e.document)});function a(e){if(h)h.remove();if(c){const t=d.fonts.delete(c);c=null;setTimeout(()=>{i.patch.emitEvent("fontLoaded",f)},100)}if(!s.get())return;d=e||d||i.patch.cgl.canvas.ownerDocument||document;if(m)m=i.patch.cgl.patch.loading.finished(m);i.setUiError("loadingerror",null);f=o.get();if(r.get()&&o.get()){if(d.fonts){let e="url("+i.patch.getFilePath(String(r.get()))+")";c=new FontFace(o.get(),e);m=i.patch.cgl.patch.loading.start("FontFile",r.get(),i);d.fonts.add(c);c.loaded.then(e=>{l.set(true);u.trigger();m=i.patch.cgl.patch.loading.finished(m);i.patch.emitEvent("fontLoaded",o.get())},e=>{i.setUiError("loadingerror","Font loading error: "+c.status+"("+r.get()+")");m=i.patch.cgl.patch.loading.finished(m);l.set(true)}).catch(e=>{m=i.patch.cgl.patch.loading.finished(m);console.error("catch ",e)});c.load()}else{const n=i.patch.getFilePath(String(r.get()));const a="".endl()+"@font-face".endl()+"{".endl()+'  font-family: "'+o.get()+'";'.endl()+'  src: url("'+n+'") format("truetype");'.endl()+"}";h=document.createElement("style");h.classList.add("cablesEle");h.type="text/css";h.innerHTML=a;document.getElementsByTagName("head")[document.getElementsByTagName("head").length-1].appendChild(h)}}}};Ops.Html.FontFile_v2.prototype=new CABLES.Op;CABLES.OPS["68177370-116e-4c76-aef3-3b10d68e7227"]={f:Ops.Html.FontFile_v2,objName:"Ops.Html.FontFile_v2"};Ops.Sidebar.Incrementor_v2=function(){CABLES.Op.apply(this,arguments);const t=this;const R=t.attachments={};const n=t.inObject("link"),a=t.inString("Label","Incrementor"),i=t.inValue("min",0),r=t.inValue("max",10),o=t.inValue("stepsize",1),s=t.inValue("Default",0),l=t.inArray("Values"),e=t.inBool("Grey Out",false),u=t.inTriggerButton("Increment"),m=t.inTriggerButton("Decrement"),c=t.inTriggerButton("Set Default"),d=t.inTriggerButton("Reset"),h=t.outObject("childs"),f=t.outNumber("value"),p=t.outTrigger("Changed");c.onTriggered=P;let g=0;t.setPortGroup("Trigger",[m,u]);const v=document.createElement("div");v.dataset.op=t.id;v.classList.add("cablesEle");v.classList.add("sidebar__item");const b=document.createElement("div");b.classList.add("sidebar__item-label");b.addEventListener("dblclick",function(){f.set(s.get());p.trigger()});u.onTriggered=j;m.onTriggered=L;const x=document.createTextNode(a.get());b.appendChild(x);v.appendChild(b);const _=document.createElement("span");_.classList.add("sidebar__item__right");const O=document.createElement("span");O.style.marginRight="10px";let A=document.createTextNode(i.get());if(Array.isArray(l.get())){A=document.createTextNode(l.get()[g])}O.appendChild(A);_.appendChild(O);const I=document.createElement("span");I.classList.add("sidebar--button");I.style.marginRight="3px";const T=document.createElement("div");T.classList.add("sidebar__button-input");T.classList.add("minus");I.appendChild(T);T.addEventListener("click",L);const S=document.createTextNode("-");T.appendChild(S);_.appendChild(I);const C=document.createElement("span");C.classList.add("sidebar--button");const y=document.createElement("div");y.classList.add("sidebar__button-input");y.classList.add("plus");C.appendChild(y);y.addEventListener("click",j);const E=document.createTextNode("+");y.appendChild(E);_.appendChild(C);v.appendChild(_);const M=document.createElement("div");M.classList.add("sidebar__greyout");v.appendChild(M);M.style.display="none";t.toWorkNeedsParent("Ops.Sidebar.Sidebar");function P(){s.set(f.get());t.refreshParams()}n.onChange=w;l.onChange=N;a.onChange=k;t.onDelete=B;e.onChange=function(){M.style.display=e.get()?"block":"none"};t.onLoaded=t.onInit=function(){if(Array.isArray(l.get())){s.setUiAttribs({greyout:true})}else{f.set(s.get());A.textContent=s.get();p.trigger()}};d.onTriggered=()=>{f.set(s.get());p.trigger();A.textContent=s.get()};function N(){const e=l.get();let t=i.get();if(Array.isArray(e)){t=e[g];i.setUiAttribs({greyout:true});r.set(e.length-1);r.setUiAttribs({greyout:true});o.setUiAttribs({greyout:true});o.set(1);s.setUiAttribs({greyout:true});s.set(0)}else{i.setUiAttribs({greyout:false});r.setUiAttribs({greyout:false});o.setUiAttribs({greyout:false});s.setUiAttribs({greyout:false})}f.set(t);p.trigger();A.textContent=t}function j(){const e=l.get();let t=0;if(!Array.isArray(e)){const n=f.get();t=Math.min(n+o.get(),r.get())}else{if(g<e.length-1){g+=Math.ceil(o.get())}t=e[g]}A.textContent=t;f.set(t);p.trigger()}function L(){const e=l.get();let t=0;if(!Array.isArray(e)){const n=f.get();t=Math.max(n-o.get(),i.get())}else{if(g>0){g-=Math.ceil(o.get())}t=e[g]}A.textContent=t;f.set(t);p.trigger()}function w(){h.set(null);const e=n.get();if(e&&e.parentElement){e.parentElement.appendChild(v);h.set(e)}else if(v.parentElement){v.parentElement.removeChild(v)}}function k(){const e=a.get();b.textContent=e;if(CABLES.UI)t.setUiAttrib({extendTitle:e})}function B(){D(v)}function D(e){if(e&&e.parentNode&&e.parentNode.removeChild){e.parentNode.removeChild(e)}}};Ops.Sidebar.Incrementor_v2.prototype=new CABLES.Op;CABLES.OPS["13932cbc-2bd4-4b2a-b6e0-cda6df4cec54"]={f:Ops.Sidebar.Incrementor_v2,objName:"Ops.Sidebar.Incrementor_v2"};Ops.Gl.Phong.DirectionalLight_v5=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=t.patch.cgl;const B=t.inTrigger("Trigger In");const a=t.inBool("Cast Light",true);const i=t.inFloat("Intensity",1);const D=[a,i];t.setPortGroup("Light Attributes",D);const r=t.inFloat("X",0);const o=t.inFloat("Y",3);const s=t.inFloat("Z",5);const l=[r,o,s];t.setPortGroup("Direction",l);const u=t.inFloat("R",1);const m=t.inFloat("G",1);const c=t.inFloat("B",1);u.setUiAttribs({colorPick:true});const d=[u,m,c];t.setPortGroup("Color",d);const h=t.inFloat("Specular R",.2);const f=t.inFloat("Specular G",.2);const p=t.inFloat("Specular B",.2);h.setUiAttribs({colorPick:true});const g=[h,f,p];t.setPortGroup("Specular Color",g);const v=t.inBool("Cast Shadow",false);const b=t.inBool("Rendering Active",true);const x=t.inSwitch("Map Size",[256,512,1024,2048],512);const _=t.inFloatSlider("Shadow Strength",1);const O=t.inFloat("LR-BottomTop",8);const A=t.inFloat("Near",.1);const I=t.inFloat("Far",30);const T=t.inFloatSlider("Bias",.004);const S=t.inInt("Polygon Offset",0);const C=t.inFloatSlider("Normal Offset",0);const y=t.inFloatSlider("Blur Amount",0);t.setPortGroup("",[v]);t.setPortGroup("Shadow Map Settings",[x,b,_,O,A,I,T,S,C,y]);x.setUiAttribs({greyout:true});b.setUiAttribs({greyout:true});_.setUiAttribs({greyout:true});O.setUiAttribs({greyout:true,hidePort:true});A.setUiAttribs({greyout:true,hidePort:true});I.setUiAttribs({greyout:true,hidePort:true});T.setUiAttribs({greyout:true,hidePort:true});C.setUiAttribs({greyout:true,hidePort:true});S.setUiAttribs({greyout:true,hidePort:true});y.setUiAttribs({greyout:true});const E=t.inBool("Enable Advanced",false);const M=t.inSwitch("MSAA",["none","2x","4x","8x"],"none");const P=t.inSwitch("Texture Filter",["Linear","Nearest","Mip Map"],"Linear");const N=t.inSwitch("Anisotropic",[0,1,2,4,8,16],"0");M.setUiAttribs({greyout:true,hidePort:true});P.setUiAttribs({greyout:true,hidePort:true});N.setUiAttribs({greyout:true,hidePort:true});t.setPortGroup("Advanced Options",[E,M,P,N]);E.onChange=function(){M.setUiAttribs({greyout:!E.get()});P.setUiAttribs({greyout:!E.get()});N.setUiAttribs({greyout:!E.get()})};const G=t.outTrigger("Trigger Out");const j=t.outTexture("Shadow Map");let U=1/Number(x.get());const L=new CGL.Light(n,{type:"directional",position:[0,1,2].map(function(e){return l[e].get()}),color:[0,1,2].map(function(e){return d[e].get()}),specular:[0,1,2].map(function(e){return g[e].get()}),intensity:i.get(),castShadow:false,shadowStrength:_.get()});L.castLight=a.get();let w=false;function F(){w=true;const e=Number(M.get().charAt(0));let t=null;const n=Number(N.get());if(P.get()=="Linear"){t=CGL.Texture.FILTER_LINEAR}else if(P.get()=="Nearest"){t=CGL.Texture.FILTER_NEAREST}else if(P.get()=="Mip Map"){t=CGL.Texture.FILTER_MIPMAP}const a=Number(x.get());const i={isFloatingPointTexture:true,filter:t};if(e)Object.assign(i,{multisampling:true,multisamplingSamples:e});Object.assign(i,{anisotropic:n});L.createFramebuffer(a,a,i);L.createBlurEffect(i);w=false}function V(){const e=Number(x.get());U=1/e;if(v.get()){L.createFramebuffer(Number(x.get()),Number(x.get()),{});L.createShadowMapShader();L.createBlurEffect({});L.createBlurShader();L.updateProjectionMatrix(O.get(),A.get(),I.get(),null)}if(E.get())F();w=false;R=true}M.onChange=N.onChange=P.onChange=x.onChange=function(){w=true};u.onChange=m.onChange=c.onChange=h.onChange=f.onChange=p.onChange=r.onChange=o.onChange=s.onChange=T.onChange=i.onChange=a.onChange=_.onChange=C.onChange=z;let R=false;function z(e){R=true}v.onChange=function(){w=true;R=true;const e=v.get();x.setUiAttribs({greyout:!e});b.setUiAttribs({greyout:!e});_.setUiAttribs({greyout:!e});O.setUiAttribs({greyout:!e});A.setUiAttribs({greyout:!e});I.setUiAttribs({greyout:!e});y.setUiAttribs({greyout:!e});T.setUiAttribs({greyout:!e});C.setUiAttribs({greyout:!e});S.setUiAttribs({greyout:!e})};O.onChange=A.onChange=I.onChange=function(){R=true};function X(){if(n.shouldDrawHelpers(t)){gui.setTransformGizmo({posX:r,posY:o,posZ:s});CABLES.GL_MARKER.drawLineSourceDest(t,-200*L.position[0],-200*L.position[1],-200*L.position[2],200*L.position[0],200*L.position[1],200*L.position[2])}}let k=false;B.onTriggered=function(){if(w){if(n.frameStore.shadowPass)return;V()}if(!n.frameStore.shadowPass){if(!L.isUsed&&!k){t.setUiError("lightUsed","No operator is using this light. Make sure this op is positioned before an operator that uses lights. Also make sure there is an operator that uses lights after this.",1);k=true}else if(!L.isUsed&&k){}else if(L.isUsed&&k){t.setUiError("lightUsed",null);k=false}else if(L.isUsed&&!k){}L.isUsed=false}if(R){L.color=[u.get(),m.get(),c.get()];L.specular=[h.get(),f.get(),p.get()];L.intensity=i.get();L.castLight=a.get();L.position=[r.get(),o.get(),s.get()];L.updateProjectionMatrix(O.get(),A.get(),I.get(),null);L.castShadow=v.get();L.normalOffset=C.get();L.shadowBias=T.get();L.shadowStrength=_.get();R=false}if(!n.frameStore.lightStack)n.frameStore.lightStack=[];if(!n.frameStore.shadowPass)X();n.frameStore.lightStack.push(L);if(v.get()){const e=1.5*y.get()*U;if(b.get())L.renderPasses(S.get(),e,function(){G.trigger()});L.blurAmount=y.get();j.set(null);j.set(L.getShadowMapDepth());n.frameStore.lightStack.pop();n.frameStore.lightStack.push(L)}else{j.set(null)}G.trigger();n.frameStore.lightStack.pop()}};Ops.Gl.Phong.DirectionalLight_v5.prototype=new CABLES.Op;CABLES.OPS["9f41bf91-f4e0-4ce4-89d8-72627b76261e"]={f:Ops.Gl.Phong.DirectionalLight_v5,objName:"Ops.Gl.Phong.DirectionalLight_v5"};Ops.Gl.RenderToTexture=function(){CABLES.Op.apply(this,arguments);const i=this;const e=i.attachments={};const r=i.patch.cgl;const t=i.inTrigger("render"),n=i.inValueBool("use viewport size",true),a=i.inValueInt("texture width",512),o=i.inValueInt("texture height",512),s=i.inBool("Auto Aspect",false),l=i.inSwitch("filter",["nearest","linear","mipmap"],"linear"),u=i.inSwitch("Wrap",["Clamp","Repeat","Mirror"],"Repeat"),m=i.inSwitch("MSAA",["none","2x","4x","8x"],"none"),c=i.outTrigger("trigger"),d=i.outTexture("texture"),h=i.outTexture("textureDepth"),f=i.inValueBool("HDR"),p=i.inValueBool("Depth",true),g=i.inValueBool("Clear",true);let v=null;let b=true;d.set(CGL.Texture.getEmptyTexture(r));i.setPortGroup("Size",[n,a,o,s]);const x=[0,0,0,0];f.setUiAttribs({title:"Pixelformat Float 32bit"});f.onChange=p.onChange=g.onChange=l.onChange=u.onChange=m.onChange=O;n.onChange=_;t.onTriggered=i.preRender=A;_();function _(){a.setUiAttribs({greyout:n.get()});o.setUiAttribs({greyout:n.get()});s.setUiAttribs({greyout:n.get()})}function O(){b=true}function A(){const e=r.getViewPort();x[0]=e[0];x[1]=e[1];x[2]=e[2];x[3]=e[3];if(!v||b){if(v)v.delete();let n=CGL.Texture.WRAP_REPEAT;if(u.get()=="Clamp")n=CGL.Texture.WRAP_CLAMP_TO_EDGE;else if(u.get()=="Mirror")n=CGL.Texture.WRAP_MIRRORED_REPEAT;let a=CGL.Texture.FILTER_NEAREST;if(l.get()=="nearest")a=CGL.Texture.FILTER_NEAREST;else if(l.get()=="linear")a=CGL.Texture.FILTER_LINEAR;else if(l.get()=="mipmap")a=CGL.Texture.FILTER_MIPMAP;if(f.get()&&l.get()=="mipmap")i.setUiError("fpmipmap","Don't use mipmap and HDR at the same time, many systems do not support this.");else i.setUiError("fpmipmap",null);if(r.glVersion>=2){let e=true;let t=4;if(m.get()=="none"){t=0;e=false}if(m.get()=="2x")t=2;if(m.get()=="4x")t=4;if(m.get()=="8x")t=8;v=new CGL.Framebuffer2(r,8,8,{name:"render2texture "+i.id,isFloatingPointTexture:f.get(),multisampling:e,wrap:n,filter:a,depth:p.get(),multisamplingSamples:t,clear:g.get()})}else{v=new CGL.Framebuffer(r,8,8,{isFloatingPointTexture:f.get(),clear:g.get()});console.log("WEBGL1!!!",v,v.valid)}if(v&&v.valid){h.set(v.getTextureDepth());b=false}else{v=null;b=true}}if(n.get()){a.set(r.getViewPort()[2]);o.set(r.getViewPort()[3])}if(v.getWidth()!=Math.ceil(a.get())||v.getHeight()!=Math.ceil(o.get())){v.setSize(Math.max(1,Math.ceil(a.get())),Math.max(1,Math.ceil(o.get())))}v.renderStart(r);if(s.get())mat4.perspective(r.pMatrix,45,a.get()/o.get(),.1,1e3);c.trigger();v.renderEnd(r);r.setViewPort(x[0],x[1],x[2],x[3]);h.setRef(v.getTextureDepth());d.setRef(v.getTextureColor())}};Ops.Gl.RenderToTexture.prototype=new CABLES.Op;CABLES.OPS["d01fa820-396c-4cb5-9d78-6b14762852af"]={f:Ops.Gl.RenderToTexture,objName:"Ops.Gl.RenderToTexture"};Ops.Gl.Meshes.Rectangle_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTrigger("render"),a=e.outTrigger("trigger"),A=e.inValue("width",1),I=e.inValue("height",1),T=e.inSwitch("pivot x",["left","center","right"]),S=e.inSwitch("pivot y",["top","center","bottom"]),C=e.inValueInt("num columns",1),y=e.inValueInt("num rows",1),E=e.inSwitch("axis",["xy","xz"],"xy"),i=e.inValueBool("Active",true),M=e.outObject("geometry",null,"geometry");M.ignoreValueSerialize=true;i.setUiAttribs({title:"Render mesh"});const P=e.patch.cgl;E.set("xy");T.set("center");S.set("center");e.setPortGroup("Pivot",[T,S]);e.setPortGroup("Size",[A,I]);e.setPortGroup("Structure",[C,y]);e.toWorkPortsNeedToBeLinked(n);const N=new CGL.Geometry("rectangle");let j=null;let L=false;E.onChange=T.onChange=S.onChange=A.onChange=I.onChange=y.onChange=C.onChange=r;o();function r(){L=true}e.preRender=n.onTriggered=function(){if(!CGL.TextureEffect.checkOpNotInTextureEffect(e))return;if(L)o();if(i.get()&&j)j.render(P.getShader());a.trigger()};function o(){let e=A.get();let t=parseFloat(I.get());let n=0;let a=0;if(typeof e=="string")e=parseFloat(e);if(typeof t=="string")t=parseFloat(t);if(T.get()=="center")n=0;else if(T.get()=="right")n=-e/2;else if(T.get()=="left")n=+e/2;if(S.get()=="center")a=0;else if(S.get()=="top")a=-t/2;else if(S.get()=="bottom")a=+t/2;const i=[];const r=[];const o=[];const s=[];const l=[];const u=[];const m=Math.round(y.get());const c=Math.round(C.get());const d=e/c;const h=t/m;let f,p,g;g=E.get();for(p=0;p<=m;p++){for(f=0;f<=c;f++){i.push(f*d-A.get()/2+n);if(g=="xz")i.push(0);i.push(p*h-I.get()/2+a);if(g=="xy")i.push(0);r.push(f/c);r.push(1-p/m);if(g=="xz"){o.push(0,1,0);s.push(1,0,0);l.push(0,0,1)}else if(g=="xy"){o.push(0,0,1);s.push(-1,0,0);l.push(0,-1,0)}}}for(f=0;f<c;f++){for(p=0;p<m;p++){const v=f+(c+1)*p;const b=v;const x=v+1;const _=v+c+1;const O=v+1+c+1;u.push(b);u.push(_);u.push(x);u.push(x);u.push(_);u.push(O)}}N.clear();N.vertices=i;N.texCoords=r;N.verticesIndices=u;N.vertexNormals=o;N.tangents=s;N.biTangents=l;if(c*m>64e3)N.unIndex();if(!j)j=new CGL.Mesh(P,N);else j.setGeom(N);M.setRef(N);L=false}e.onDelete=function(){if(j)j.dispose()}};Ops.Gl.Meshes.Rectangle_v2.prototype=new CABLES.Op;CABLES.OPS["fc5718d6-11a5-496e-8f16-1c78b1a2824c"]={f:Ops.Gl.Meshes.Rectangle_v2,objName:"Ops.Gl.Meshes.Rectangle_v2"};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 n=e.inTrigger("render");const a=e.outTrigger("trigger");const i=e.outObject("shader",null,"shader");i.ignoreValueSerialize=true;e.toWorkPortsNeedToBeLinked(n);e.toWorkShouldNotBeChild("Ops.Gl.TextureEffects.ImageCompose",CABLES.OP_PORT_TYPE_FUNCTION);const r=e.patch.cgl;const o=new CGL.Shader(r,"basicmaterialnew",this);o.addAttribute({type:"vec3",name:"vPosition"});o.addAttribute({type:"vec2",name:"attrTexCoord"});o.addAttribute({type:"vec3",name:"attrVertNormal",nameFrag:"norm"});o.addAttribute({type:"float",name:"attrVertIndex"});o.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG","MODULE_VERTEX_MODELVIEW"]);o.setSource(t.basicmaterial_vert,t.basicmaterial_frag);i.setRef(o);n.onTriggered=y;const s=e.inValueSlider("r",Math.random());const l=e.inValueSlider("g",Math.random());const u=e.inValueSlider("b",Math.random());const m=e.inValueSlider("a",1);s.setUiAttribs({colorPick:true});const c=o.addUniformFrag("4f","color",s,l,u,m);o.uniformColorDiffuse=c;const d=e.inTexture("texture");let h=null;d.onChange=M;const f=e.inValueBool("colorizeTexture",false);const p=e.inValueBool("Vertex Colors",false);const g=e.inTexture("textureOpacity");let v=null;const b=e.inSwitch("Alpha Mask Source",["Luminance","R","G","B","A","1-A","1-R"],"Luminance");b.setUiAttribs({greyout:true});g.onChange=E;const x=e.inValueBool("Opacity TexCoords Transform",false);const _=e.inValueBool("Discard Transparent Pixels");const O=e.inValue("diffuseRepeatX",1),A=e.inValue("diffuseRepeatY",1),I=e.inValue("Tex Offset X",0),T=e.inValue("Tex Offset Y",0),S=e.inBool("Crop TexCoords",false);o.addUniformFrag("f","diffuseRepeatX",O);o.addUniformFrag("f","diffuseRepeatY",A);o.addUniformFrag("f","texOffsetX",I);o.addUniformFrag("f","texOffsetY",T);const C=e.inValueBool("billboard",false);b.onChange=C.onChange=_.onChange=x.onChange=S.onChange=p.onChange=f.onChange=N;e.setPortGroup("Color",[s,l,u,m]);e.setPortGroup("Color Texture",[d,p,f]);e.setPortGroup("Opacity",[g,b,_,x]);e.setPortGroup("Texture Transform",[O,A,I,T,S]);E();M();e.preRender=function(){o.bind();y()};function y(){if(!o)return;r.pushShader(o);o.popTextures();if(h&&d.get())o.pushTexture(h,d.get());if(v&&g.get())o.pushTexture(v,g.get());a.trigger();r.popShader()}function E(){if(g.get()){if(v!==null)return;o.removeUniform("texOpacity");o.define("HAS_TEXTURE_OPACITY");if(!v)v=new CGL.Uniform(o,"t","texOpacity")}else{o.removeUniform("texOpacity");o.removeDefine("HAS_TEXTURE_OPACITY");v=null}N()}function M(){if(d.get()){if(!o.hasDefine("HAS_TEXTURE_DIFFUSE"))o.define("HAS_TEXTURE_DIFFUSE");if(!h)h=new CGL.Uniform(o,"t","texDiffuse")}else{o.removeUniform("texDiffuse");o.removeDefine("HAS_TEXTURE_DIFFUSE");h=null}P()}function P(){const e=d.isLinked()||g.isLinked();O.setUiAttribs({greyout:!e});A.setUiAttribs({greyout:!e});I.setUiAttribs({greyout:!e});T.setUiAttribs({greyout:!e});f.setUiAttribs({greyout:!e});b.setUiAttribs({greyout:!g.get()});x.setUiAttribs({greyout:!g.get()});let t=true;t=d.get()&&!f.get();s.setUiAttribs({greyout:t});l.setUiAttribs({greyout:t});u.setUiAttribs({greyout:t})}function N(){o.toggleDefine("VERTEX_COLORS",p.get());o.toggleDefine("CROP_TEXCOORDS",S.get());o.toggleDefine("COLORIZE_TEXTURE",f.get());o.toggleDefine("TRANSFORMALPHATEXCOORDS",x.get());o.toggleDefine("DISCARDTRANS",_.get());o.toggleDefine("BILLBOARD",C.get());o.toggleDefine("ALPHA_MASK_ALPHA",b.get()=="A");o.toggleDefine("ALPHA_MASK_IALPHA",b.get()=="1-A");o.toggleDefine("ALPHA_MASK_IR",b.get()=="1-R");o.toggleDefine("ALPHA_MASK_LUMI",b.get()=="Luminance");o.toggleDefine("ALPHA_MASK_R",b.get()=="R");o.toggleDefine("ALPHA_MASK_G",b.get()=="G");o.toggleDefine("ALPHA_MASK_B",b.get()=="B");P()}};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.Meshes.Sphere_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const O=Math.PI*2,A=e.patch.cgl,n=e.inTrigger("render"),I=e.inValue("radius",.5),T=e.inValue("stacks",32),S=e.inValue("slices",32),C=e.inValueSlider("Filloffset",1),a=e.inValueBool("Render",true),i=e.outTrigger("trigger"),y=e.outObject("geometry",null,"geometry"),E=vec3.fromValues(0,1,0),M=vec3.fromValues(1,0,0);let P=new CGL.Geometry("Sphere"),N=vec3.create(),j=vec3.create(),L=true,w;n.onTriggered=function(){if(L)r();if(a.get())w.render(A.getShader());i.trigger()};T.onChange=S.onChange=C.onChange=I.onChange=function(){L=true};e.onDelete=function(){if(w)w.dispose()};function r(){const e=Math.ceil(Math.max(T.get(),2)),t=Math.ceil(Math.max(S.get(),3)),n=Math.min(Math.max(C.get()*e,1),e),a=I.get();let i=[],r=[],o=[],s=[],l=[],u=[],m,c,d,h,f,p,g,v,b,x,_;for(x=g=0;x<e+1;x++){b=(x/e-.5)*Math.PI;c=Math.sin(b);p=Math.cos(b);for(_=t;_>=0;_--){v=_/t*O;m=Math.cos(v)*p;d=Math.sin(v)*p;i.push(m*a,c*a,d*a);r.push(_/t,x/(e+1));h=Math.sqrt(m*m+c*c+d*d);o.push(N[0]=m/h,N[1]=c/h,N[2]=d/h);if(c==h)f=M;else f=E;vec3.cross(j,N,f);vec3.normalize(j,j);Array.prototype.push.apply(s,j);vec3.cross(j,j,N);Array.prototype.push.apply(l,j)}if(x==0||x>n)continue;for(_=0;_<t;_++,g++){u.push(g,g+1,g+t+1,g+1,g+t+2,g+t+1)}g++}P.clear();P.vertices=i;P.texCoords=r;P.vertexNormals=o;P.tangents=s;P.biTangents=l;P.verticesIndices=u;y.setRef(P);if(!w)w=new CGL.Mesh(A,P);else w.setGeom(P);L=false}};Ops.Gl.Meshes.Sphere_v2.prototype=new CABLES.Op;CABLES.OPS["450b4d68-2278-4d9f-9849-0abdfa37ef69"]={f:Ops.Gl.Meshes.Sphere_v2,objName:"Ops.Gl.Meshes.Sphere_v2"};Ops.Gl.ShaderEffects.VertexDisplacementMap_v4=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={vertdisplace_body_vert:"\nvec2 MOD_tc=texCoord;\n\n#ifdef MOD_COORD_MESHXY\n    MOD_tc=pos.xy;\n#endif\n#ifdef MOD_COORD_MESHXZ\n    MOD_tc=pos.xz;\n#endif\n\n\n#ifdef MOD_FLIP_Y\n    MOD_tc.y=1.0-MOD_tc.y;\n#endif\n#ifdef MOD_FLIP_X\n    MOD_tc.x=1.0-MOD_tc.x;\n#endif\n#ifdef MOD_FLIP_XY\n    MOD_tc=1.0-MOD_tc;\n#endif\n\nMOD_tc*=MOD_scale;\n\nvec4 MOD_sample=texture( MOD_texture, vec2(MOD_tc.x+MOD_offsetX,MOD_tc.y+MOD_offsetY) );\nvec3 MOD_disp;\n\n#ifdef MOD_INPUT_R\n    MOD_disp=vec3(MOD_sample.r);\n#endif\n#ifdef MOD_INPUT_G\n    MOD_disp=vec3(MOD_sample.g);\n#endif\n#ifdef MOD_INPUT_B\n    MOD_disp=vec3(MOD_sample.b);\n#endif\n#ifdef MOD_INPUT_A\n    MOD_disp=vec3(MOD_sample.a);\n#endif\n#ifdef MOD_INPUT_RGB\n    MOD_disp=MOD_sample.rgb;\n#endif\n#ifdef MOD_INPUT_LUMI\n    MOD_disp=vec3(dot(vec3(0.2126,0.7152,0.0722), MOD_sample.rgb));\n#endif\n\n\n\n#ifdef MOD_HEIGHTMAP_INVERT\n   MOD_disp=1.0-MOD_disp;\n#endif\n// #ifdef MOD_HEIGHTMAP_NORMALIZE\n//   MOD_disp-=0.5;\n//   MOD_disp*=2.0;\n// #endif\n\n\n#ifdef MOD_HEIGHTMAP_NORMALIZE\n    MOD_disp=(MOD_disp-0.5)*2.0;\n    // MOD_disp=(MOD_disp-0.5)*-1.0+0.5;\n#endif\n\n\nfloat MOD_zero=0.0;\n\n#ifdef MOD_MODE_DIV\n    MOD_zero=1.0;\n#endif\n#ifdef MOD_MODE_MUL\n    MOD_zero=1.0;\n#endif\n\n\n\nvec3 MOD_mask=vec3(1.0);\n\n#ifdef MOD_AXIS_X\n    MOD_mask=vec3(1.,0.,0.);\n    MOD_disp*=MOD_mask*MOD_extrude;\n#endif\n#ifdef MOD_AXIS_Y\n    MOD_mask=vec3(0.,1.,0.);\n    MOD_disp*=MOD_mask*MOD_extrude;\n#endif\n#ifdef MOD_AXIS_Z\n    MOD_mask=vec3(0.,0.,1.);\n    MOD_disp*=MOD_mask*MOD_extrude;\n#endif\n#ifdef MOD_AXIS_XY\n    MOD_mask=vec3(1.,1.,0.);\n    MOD_disp*=MOD_mask*MOD_extrude;\n#endif\n#ifdef MOD_AXIS_XYZ\n    MOD_mask=vec3(1.,1.,1.);\n    MOD_disp*=MOD_mask*MOD_extrude;\n#endif\n\n\n// MOD_disp=smoothstep(-1.,1.,MOD_disp*MOD_disp*MOD_disp);\n// MOD_disp=MOD_disp*MOD_disp*MOD_disp;\n\n// #ifdef MOD_FLIP_Y\n//     MOD_mask.y=1.0-MOD_mask.y;\n// #endif\n// #ifdef MOD_FLIP_X\n//     MOD_mask.x=1.0-MOD_mask.x;\n// #endif\n// #ifdef MOD_FLIP_XY\n//     MOD_mask.xy=1.0-MOD_mask.xy;\n// #endif\n\n\n\n#ifdef MOD_MODE_DIV\n    pos.xyz/=MOD_disp*MOD_mask;\n#endif\n\n#ifdef MOD_MODE_MUL\n    pos.xyz*=MOD_disp*MOD_mask;\n#endif\n\n#ifdef MOD_MODE_ADD\n    pos.xyz+=MOD_disp*MOD_mask;\n#endif\n\n#ifdef MOD_MODE_NORMAL\n\n    vec3 MOD_t=norm;\n    #ifdef MOD_SMOOTHSTEP\n        MOD_t=smoothstep(-1.,1.,MOD_t);\n    #endif\n\n    pos.xyz+=MOD_t*MOD_disp*MOD_mask;\n\n#endif\n\n#ifdef MOD_MODE_TANGENT\n    MOD_disp*=-1.0;\n\n    vec3 MOD_t=attrTangent;\n    #ifdef MOD_SMOOTHSTEP\n        MOD_t=smoothstep(-1.,1.,MOD_t);\n    #endif\n\n    pos.xyz+=MOD_t*MOD_disp*MOD_mask;\n\n#endif\n\n#ifdef MOD_MODE_BITANGENT\n    MOD_disp*=-1.0;\n    vec3 MOD_t=attrBiTangent;\n\n    #ifdef MOD_SMOOTHSTEP\n        MOD_t=smoothstep(-1.,1.,MOD_t);\n    #endif\n\n    pos.xyz+=MOD_t*MOD_disp*MOD_mask;\n\n#endif\n\n#ifdef MOD_MODE_VERTCOL\n    vec3 MOD_t=attrVertColor.rgb*vec3(2.0)-vec3(1.0);\n\n    #ifdef MOD_SMOOTHSTEP\n        MOD_t=smoothstep(-1.,1.,MOD_t);\n    #endif\n\n    pos.xyz+=MOD_t*MOD_disp*MOD_mask;\n\n#endif\n\n\n// pos.y*=-1.0;\n    // pos.xy+=vec2(MOD_texVal*MOD_extrude)*normalize(pos.xy);\n\n\nMOD_displHeightMapColor=MOD_disp;\n\n\n#ifdef MOD_CALC_NORMALS\n    norm+=MOD_calcNormal(MOD_texture,MOD_tc);\n#endif",vertdisplace_head_vert:"OUT vec3 MOD_displHeightMapColor;\n\n#ifdef MOD_MODE_VERTCOL\n#ifndef VERTEX_COLORS\nIN vec4 attrVertColor;\n#endif\n#endif\n\n// mat4 rotationX( in float angle ) {\n// \treturn mat4(\t1.0,\t\t0,\t\t\t0,\t\t\t0,\n// \t\t\t \t\t0, \tcos(angle),\t-sin(angle),\t\t0,\n// \t\t\t\t\t0, \tsin(angle),\t cos(angle),\t\t0,\n// \t\t\t\t\t0, \t\t\t0,\t\t\t  0, \t\t1);\n// }\n\n// mat4 rotationY( in float angle ) {\n// \treturn mat4(\tcos(angle),\t\t0,\t\tsin(angle),\t0,\n// \t\t\t \t\t\t\t0,\t\t1.0,\t\t\t 0,\t0,\n// \t\t\t\t\t-sin(angle),\t0,\t\tcos(angle),\t0,\n// \t\t\t\t\t\t\t0, \t\t0,\t\t\t\t0,\t1);\n// }\n\n// mat4 rotationZ( in float angle ) {\n// \treturn mat4(\tcos(angle),\t\t-sin(angle),\t0,\t0,\n// \t\t\t \t\tsin(angle),\t\tcos(angle),\t\t0,\t0,\n// \t\t\t\t\t\t\t0,\t\t\t\t0,\t\t1,\t0,\n// \t\t\t\t\t\t\t0,\t\t\t\t0,\t\t0,\t1);\n// }\n\n\nvec3 MOD_calcNormal(sampler2D tex,vec2 uv)\n{\n    float strength=13.0;\n    // float texelSize=1.0/float(textureSize(tex,0).x); // not on linux intel?!\n    float texelSize=1.0/512.0;\n\n    float tl = abs(texture(tex, uv + texelSize * vec2(-1.0, -1.0)).x);   // top left\n    float  l = abs(texture(tex, uv + texelSize * vec2(-1.0,  0.0)).x);   // left\n    float bl = abs(texture(tex, uv + texelSize * vec2(-1.0,  1.0)).x);   // bottom left\n    float  t = abs(texture(tex, uv + texelSize * vec2( 0.0, -1.0)).x);   // top\n    float  b = abs(texture(tex, uv + texelSize * vec2( 0.0,  1.0)).x);   // bottom\n    float tr = abs(texture(tex, uv + texelSize * vec2( 1.0, -1.0)).x);   // top right\n    float  r = abs(texture(tex, uv + texelSize * vec2( 1.0,  0.0)).x);   // right\n    float br = abs(texture(tex, uv + texelSize * vec2( 1.0,  1.0)).x);   // bottom right\n\n    //     // Compute dx using Sobel:\n    //     //           -1 0 1\n    //     //           -2 0 2\n    //     //           -1 0 1\n    float dX = tr + 2.0*r + br -tl - 2.0*l - bl;\n\n    //     // Compute dy using Sobel:\n    //     //           -1 -2 -1\n    //     //            0  0  0\n    //     //            1  2  1\n    float dY = bl + 2.0*b + br -tl - 2.0*t - tr;\n\n    //     // Build the normalized normal\n\nvec3 N;\n\n#ifdef MOD_NORMALS_Z\n    N = normalize(vec3(dX,dY, 1.0 / strength));\n#endif\n\n#ifdef MOD_NORMALS_Y\n    N = normalize(vec3(dX,1.0/strength,dY));\n#endif\n#ifdef MOD_NORMALS_X\n    N = normalize(vec3(1.0/strength,dX,dY));\n#endif\n// N*=-1.0;\n// N= N * 0.5 + 0.5;\n\n\n   return N;\n}\n"};const n=e.inTrigger("Render"),a=e.inValue("Extrude",.5),i=e.inSwitch("Mode",["Norm","Tang","BiTang","VertCol","*","+","/"],"Norm"),r=e.inSwitch("Axis",["XYZ","XY","X","Y","Z"],"XYZ"),o=e.inSwitch("Coordinates",["Tex Coords","Mesh XY","Mesh XZ"],"Tex Coords"),s=e.inTexture("Texture",null,"texture"),l=e.inSwitch("Channel",["Luminance","R","G","B","A","RGB"],"Luminance"),u=e.inSwitch("Flip",["None","X","Y","XY"],"None"),m=e.inSwitch("Range",["0-1","1-0","Normalized"],"0-1"),c=e.inValueFloat("Offset X"),d=e.inValueFloat("Offset Y"),h=e.inValueFloat("Scale",1),f=e.inValueBool("Calc Normals",false),p=e.inSwitch("Normal Axis",["X","Y","Z"],"Z"),g=e.inValueBool("Discard Zero Values"),v=e.inValueBool("colorize",false),b=e.inValueSlider("Colorize Min",0),x=e.inValueSlider("Colorize Max",1),_=e.outTrigger("trigger");const O=e.patch.cgl;e.setPortGroup("Input",[s,u,l,m,c,d,h]);e.setPortGroup("Colorize",[v,b,x,g]);e.toWorkPortsNeedToBeLinked(s,_,n);n.onTriggered=E;l.onChange=o.onChange=r.onChange=u.onChange=i.onChange=m.onChange=v.onChange=g.onChange=f.onChange=p.onChange=y;const A=t.vertdisplace_head_vert;const I=t.vertdisplace_body_vert;const T="".endl()+"IN vec3 MOD_displHeightMapColor;".endl()+"vec3 MOD_map(vec3 value, float inMin, float inMax, float outMin, float outMax) { return outMin + (outMax - outMin) * (value - inMin) / (inMax - inMin);}".endl();const S="".endl()+"#ifdef MOD_HEIGHTMAP_COLORIZE".endl()+"   col.rgb*=MOD_map( MOD_displHeightMapColor, 0.0,1.0 , MOD_colorizeMin,MOD_colorizeMax);".endl()+"#endif".endl()+"#ifdef MOD_DISPLACE_REMOVE_ZERO".endl()+"   if(MOD_displHeightMapColor.r==0.0)discard;".endl()+"#endif".endl();const C=new CGL.ShaderModifier(O,e.name,{opId:e.id});C.addModule({title:e.name,name:"MODULE_VERTEX_POSITION",srcHeadVert:A,srcBodyVert:I});C.addModule({title:e.name,name:"MODULE_COLOR",srcHeadFrag:T,srcBodyFrag:S});C.addUniformVert("t","MOD_texture",0);C.addUniformVert("f","MOD_extrude",a);C.addUniformVert("f","MOD_offsetX",c);C.addUniformVert("f","MOD_offsetY",d);C.addUniformVert("f","MOD_scale",h);C.addUniformFrag("f","MOD_colorizeMin",b);C.addUniformFrag("f","MOD_colorizeMax",x);y();function y(){C.toggleDefine("MOD_HEIGHTMAP_COLORIZE",v.get());C.toggleDefine("MOD_HEIGHTMAP_INVERT",m.get()=="1-0");C.toggleDefine("MOD_HEIGHTMAP_NORMALIZE",m.get()=="Normalized");C.toggleDefine("MOD_DISPLACE_REMOVE_ZERO",g.get());C.toggleDefine("MOD_INPUT_R",l.get()=="R");C.toggleDefine("MOD_INPUT_G",l.get()=="G");C.toggleDefine("MOD_INPUT_B",l.get()=="B");C.toggleDefine("MOD_INPUT_A",l.get()=="A");C.toggleDefine("MOD_INPUT_RGB",l.get()=="RGB");C.toggleDefine("MOD_INPUT_LUMI",l.get()=="Luminance");C.toggleDefine("MOD_FLIP_X",u.get()=="X");C.toggleDefine("MOD_FLIP_Y",u.get()=="Y");C.toggleDefine("MOD_FLIP_XY",u.get()=="XY");C.toggleDefine("MOD_AXIS_X",r.get()=="X");C.toggleDefine("MOD_AXIS_Y",r.get()=="Y");C.toggleDefine("MOD_AXIS_Z",r.get()=="Z");C.toggleDefine("MOD_AXIS_XYZ",r.get()=="XYZ");C.toggleDefine("MOD_AXIS_XY",r.get()=="XY");C.toggleDefine("MOD_MODE_BITANGENT",i.get()=="BiTang");C.toggleDefine("MOD_MODE_TANGENT",i.get()=="Tang");C.toggleDefine("MOD_MODE_NORMAL",i.get()=="Norm");C.toggleDefine("MOD_MODE_VERTCOL",i.get()=="VertCol");C.toggleDefine("MOD_MODE_MUL",i.get()=="*");C.toggleDefine("MOD_MODE_ADD",i.get()=="+");C.toggleDefine("MOD_MODE_DIV",i.get()=="/");C.toggleDefine("MOD_SMOOTHSTEP",0);C.toggleDefine("MOD_COORD_TC",o.get()=="Tex Coords");C.toggleDefine("MOD_COORD_MESHXY",o.get()=="Mesh XY");C.toggleDefine("MOD_COORD_MESHXZ",o.get()=="Mesh XZ");C.toggleDefine("MOD_CALC_NORMALS",f.get());C.toggleDefine("MOD_NORMALS_X",p.get()=="X");C.toggleDefine("MOD_NORMALS_Y",p.get()=="Y");C.toggleDefine("MOD_NORMALS_Z",p.get()=="Z");p.setUiAttribs({greyout:!f.get()})}function E(){C.bind();if(s.get()&&!s.get().deleted)C.pushTexture("MOD_texture",s.get().tex);else C.pushTexture("MOD_texture",CGL.Texture.getEmptyTexture(O).tex);_.trigger();C.unbind()}};Ops.Gl.ShaderEffects.VertexDisplacementMap_v4.prototype=new CABLES.Op;CABLES.OPS["ed36e5ad-457b-4ac6-a929-11b66951cb6c"]={f:Ops.Gl.ShaderEffects.VertexDisplacementMap_v4,objName:"Ops.Gl.ShaderEffects.VertexDisplacementMap_v4"};Ops.Gl.ImageCompose.Noise.PerlinNoise_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={perlinnoise3d_frag:'UNI float z;\nUNI float x;\nUNI float y;\nUNI float scale;\nUNI float rangeMul;\nUNI float harmonics;\nUNI float aspect;\n\nIN vec2 texCoord;\nUNI sampler2D tex;\n\n#ifdef HAS_TEX_OFFSETMAP\n    UNI sampler2D texOffsetZ;\n    UNI float offMul;\n#endif\n\n#ifdef HAS_TEX_MASK\n    UNI sampler2D texMask;\n#endif\n\nUNI float amount;\n\n{{CGL.BLENDMODES3}}\n\n\nfloat Interpolation_C2( float x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }   //  6x^5-15x^4+10x^3\t( Quintic Curve.  As used by Perlin in Improved Noise.  http://mrl.nyu.edu/~perlin/paper445.pdf )\nvec2 Interpolation_C2( vec2 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec3 Interpolation_C2( vec3 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2( vec4 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2_InterpAndDeriv( vec2 x ) { return x.xyxy * x.xyxy * ( x.xyxy * ( x.xyxy * ( x.xyxy * vec2( 6.0, 0.0 ).xxyy + vec2( -15.0, 30.0 ).xxyy ) + vec2( 10.0, -60.0 ).xxyy ) + vec2( 0.0, 30.0 ).xxyy ); }\nvec3 Interpolation_C2_Deriv( vec3 x ) { return x * x * (x * (x * 30.0 - 60.0) + 30.0); }\n\n\nvoid FAST32_hash_3D( vec3 gridcell, out vec4 lowz_hash, out vec4 highz_hash )\t//\tgenerates a random number for each of the 8 cell corners\n{\n    //    gridcell is assumed to be an integer coordinate\n\n    //\tTODO: \tthese constants need tweaked to find the best possible noise.\n    //\t\t\tprobably requires some kind of brute force computational searching or something....\n    const vec2 OFFSET = vec2( 50.0, 161.0 );\n    const float DOMAIN = 69.0;\n    const float SOMELARGEFLOAT = 635.298681;\n    const float ZINC = 48.500388;\n\n    //\ttruncate the domain\n    gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n    vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n    //\tcalculate the noise\n    vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n    P *= P;\n    P = P.xzxz * P.yyww;\n    highz_hash.xy = vec2( 1.0 / ( SOMELARGEFLOAT + vec2( gridcell.z, gridcell_inc1.z ) * ZINC ) );\n    lowz_hash = fract( P * highz_hash.xxxx );\n    highz_hash = fract( P * highz_hash.yyyy );\n}\n\n\n\n\nvoid FAST32_hash_3D( \tvec3 gridcell,\n                        out vec4 lowz_hash_0,\n                        out vec4 lowz_hash_1,\n                        out vec4 lowz_hash_2,\n                        out vec4 highz_hash_0,\n                        out vec4 highz_hash_1,\n                        out vec4 highz_hash_2\t)\t\t//\tgenerates 3 random numbers for each of the 8 cell corners\n{\n    //    gridcell is assumed to be an integer coordinate\n\n    //\tTODO: \tthese constants need tweaked to find the best possible noise.\n    //\t\t\tprobably requires some kind of brute force computational searching or something....\n    const vec2 OFFSET = vec2( 50.0, 161.0 );\n    const float DOMAIN = 69.0;\n    const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );\n    const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );\n\n    //\ttruncate the domain\n    gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n    vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n    //\tcalculate the noise\n    vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n    P *= P;\n    P = P.xzxz * P.yyww;\n    vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );\n    vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );\n    lowz_hash_0 = fract( P * lowz_mod.xxxx );\n    highz_hash_0 = fract( P * highz_mod.xxxx );\n    lowz_hash_1 = fract( P * lowz_mod.yyyy );\n    highz_hash_1 = fract( P * highz_mod.yyyy );\n    lowz_hash_2 = fract( P * lowz_mod.zzzz );\n    highz_hash_2 = fract( P * highz_mod.zzzz );\n}\nfloat Falloff_Xsq_C1( float xsq ) { xsq = 1.0 - xsq; return xsq*xsq; }\t// ( 1.0 - x*x )^2   ( Used by Humus for lighting falloff in Just Cause 2.  GPUPro 1 )\nfloat Falloff_Xsq_C2( float xsq ) { xsq = 1.0 - xsq; return xsq*xsq*xsq; }\t// ( 1.0 - x*x )^3.   NOTE: 2nd derivative is 0.0 at x=1.0, but non-zero at x=0.0\nvec4 Falloff_Xsq_C2( vec4 xsq ) { xsq = 1.0 - xsq; return xsq*xsq*xsq; }\n\n\n//\n//\tPerlin Noise 3D  ( gradient noise )\n//\tReturn value range of -1.0->1.0\n//\thttp://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg\n//\nfloat Perlin3D( vec3 P )\n{\n    //\testablish our grid cell and unit position\n    vec3 Pi = floor(P);\n    vec3 Pf = P - Pi;\n    vec3 Pf_min1 = Pf - 1.0;\n\n#if 1\n    //\n    //\tclassic noise.\n    //\trequires 3 random values per point.  with an efficent hash function will run faster than improved noise\n    //\n\n    //\tcalculate the hash.\n    //\t( various hashing methods listed in order of speed )\n    vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;\n    FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n    //SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n\n    //\tcalculate the gradients\n    vec4 grad_x0 = hashx0 - 0.49999;\n    vec4 grad_y0 = hashy0 - 0.49999;\n    vec4 grad_z0 = hashz0 - 0.49999;\n    vec4 grad_x1 = hashx1 - 0.49999;\n    vec4 grad_y1 = hashy1 - 0.49999;\n    vec4 grad_z1 = hashz1 - 0.49999;\n    vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );\n    vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );\n\n#if 1\n    //\tClassic Perlin Interpolation\n    vec3 blend = Interpolation_C2( Pf );\n    vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n    vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n    float final = dot( res0, blend2.zxzx * blend2.wwyy );\n    final *= 1.1547005383792515290182975610039;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range    *= 1.0/sqrt(0.75)\n    return final;\n#else\n    //\tClassic Perlin Surflet\n    //\thttp://briansharpe.wordpress.com/2012/03/09/modifications-to-classic-perlin-noise/\n    Pf *= Pf;\n    Pf_min1 *= Pf_min1;\n    vec4 vecs_len_sq = vec4( Pf.x, Pf_min1.x, Pf.x, Pf_min1.x ) + vec4( Pf.yy, Pf_min1.yy );\n    float final = dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf.zzzz ) ), grad_results_0 ) + dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf_min1.zzzz ) ), grad_results_1 );\n    final *= 2.3703703703703703703703703703704;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range    *= 1.0/cube(0.75)\n    return final;\n#endif\n\n#else\n    //\n    //\timproved noise.\n    //\trequires 1 random value per point.  Will run faster than classic noise if a slow hashing function is used\n    //\n\n    //\tcalculate the hash.\n    //\t( various hashing methods listed in order of speed )\n    vec4 hash_lowz, hash_highz;\n    FAST32_hash_3D( Pi, hash_lowz, hash_highz );\n    //BBS_hash_3D( Pi, hash_lowz, hash_highz );\n    //SGPP_hash_3D( Pi, hash_lowz, hash_highz );\n\n    //\n    //\t"improved" noise using 8 corner gradients.  Faster than the 12 mid-edge point method.\n    //\tKen mentions using diagonals like this can cause "clumping", but we\'ll live with that.\n    //\t[1,1,1]  [-1,1,1]  [1,-1,1]  [-1,-1,1]\n    //\t[1,1,-1] [-1,1,-1] [1,-1,-1] [-1,-1,-1]\n    //\n    hash_lowz -= 0.5;\n    vec4 grad_results_0_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_lowz );\n    hash_lowz = abs( hash_lowz ) - 0.25;\n    vec4 grad_results_0_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_lowz );\n    vec4 grad_results_0_2 = Pf.zzzz * sign( abs( hash_lowz ) - 0.125 );\n    vec4 grad_results_0 = grad_results_0_0 + grad_results_0_1 + grad_results_0_2;\n\n    hash_highz -= 0.5;\n    vec4 grad_results_1_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_highz );\n    hash_highz = abs( hash_highz ) - 0.25;\n    vec4 grad_results_1_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_highz );\n    vec4 grad_results_1_2 = Pf_min1.zzzz * sign( abs( hash_highz ) - 0.125 );\n    vec4 grad_results_1 = grad_results_1_0 + grad_results_1_1 + grad_results_1_2;\n\n    //\tblend the gradients and return\n    vec3 blend = Interpolation_C2( Pf );\n    vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n    vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n    return dot( res0, blend2.zxzx * blend2.wwyy ) * (2.0 / 3.0);\t//\t(optionally) mult by (2.0/3.0) to scale to a strict -1.0->1.0 range\n#endif\n}\n\nvoid main()\n{\n    vec4 base=texture(tex,texCoord);\n    vec2 p=vec2(texCoord.x-0.5,texCoord.y-0.5);\n\n    p=p*scale;\n    p=vec2(p.x+0.5-x,p.y+0.5-y);\n\n\n\n    vec3 offset;\n    #ifdef HAS_TEX_OFFSETMAP\n        vec4 offMap=texture(texOffsetZ,texCoord);\n\n        #ifdef OFFSET_X_R\n            offset.x=offMap.r;\n        #endif\n        #ifdef OFFSET_X_G\n            offset.x=offMap.g;\n        #endif\n        #ifdef OFFSET_X_B\n            offset.x=offMap.b;\n        #endif\n\n        #ifdef OFFSET_Y_R\n            offset.y=offMap.r;\n        #endif\n        #ifdef OFFSET_Y_G\n            offset.y=offMap.g;\n        #endif\n        #ifdef OFFSET_Y_B\n            offset.y=offMap.b;\n        #endif\n\n        #ifdef OFFSET_Z_R\n            offset.z=offMap.r;\n        #endif\n        #ifdef OFFSET_Z_G\n            offset.z=offMap.g;\n        #endif\n        #ifdef OFFSET_Z_B\n            offset.z=offMap.b;\n        #endif\n        offset*=offMul;\n    #endif\n\n    float aa=texture(tex,texCoord).r;\n\n    float v = 0.0;\n    p.x*=aspect;\n\n    v+=Perlin3D(vec3(p.x,p.y,z)+offset);\n\n    #ifdef HARMONICS\n        if (harmonics >= 2.0) v += Perlin3D(vec3(p.x,p.y,z)*2.2+offset) * 0.5;\n        if (harmonics >= 3.0) v += Perlin3D(vec3(p.x,p.y,z)*4.3+offset) * 0.25;\n        if (harmonics >= 4.0) v += Perlin3D(vec3(p.x,p.y,z)*8.4+offset) * 0.125;\n        if (harmonics >= 5.0) v += Perlin3D(vec3(p.x,p.y,z)*16.5+offset) * 0.0625;\n    #endif\n\n\n    v*=rangeMul;\n    v=v*0.5+0.5;\n    float v2=v;\n    float v3=v;\n\n    #ifdef RGB\n        v2=Perlin3D(vec3(p.x+2.0,p.y+2.0,z))*0.5+0.5;\n\n        #ifdef HARMONICS\n            if (harmonics >= 2.0) v2 += Perlin3D(vec3(p.x,p.y,z)*2.2+offset) * 0.5;\n            if (harmonics >= 3.0) v2 += Perlin3D(vec3(p.x,p.y,z)*4.3+offset) * 0.25;\n            if (harmonics >= 4.0) v2 += Perlin3D(vec3(p.x,p.y,z)*8.4+offset) * 0.125;\n            if (harmonics >= 5.0) v2 += Perlin3D(vec3(p.x,p.y,z)*16.5+offset) * 0.0625;\n        #endif\n\n        v3=Perlin3D(vec3(p.x+3.0,p.y+3.0,z))*0.5+0.5;\n\n        #ifdef HARMONICS\n            if (harmonics >= 2.0) v3 += Perlin3D(vec3(p.x,p.y,z)*2.2+offset) * 0.5;\n            if (harmonics >= 3.0) v3 += Perlin3D(vec3(p.x,p.y,z)*4.3+offset) * 0.25;\n            if (harmonics >= 4.0) v3 += Perlin3D(vec3(p.x,p.y,z)*8.4+offset) * 0.125;\n            if (harmonics >= 5.0) v3 += Perlin3D(vec3(p.x,p.y,z)*16.5+offset) * 0.0625;\n        #endif\n\n    #endif\n\n    vec4 col=vec4(v,v2,v3,1.0);\n\n    float str=1.0;\n    #ifdef HAS_TEX_MASK\n        str=texture(texMask,texCoord).r;\n    #endif\n\n    #ifdef RANGE_MIN1\n        col=col*2.0-1.0;\n    #endif\n\n    col=cgl_blendPixel(base,col,amount*str);\n\n\n    #ifdef NO_CHANNEL_R\n        col.r=base.r;\n    #endif\n    #ifdef NO_CHANNEL_G\n        col.g=base.g;\n    #endif\n    #ifdef NO_CHANNEL_B\n        col.b=base.b;\n    #endif\n\n\n\n    outColor=col;\n}\n'};const n=e.inTrigger("render"),a=e.inTexture("Mask"),i=CGL.TextureEffect.AddBlendSelect(e),r=CGL.TextureEffect.AddBlendAlphaMask(e),o=e.inValueSlider("Amount",1),s=e.inSwitch("Color",["Mono","RGB","R","G","B"],"Mono"),l=e.inValue("Scale",8),u=e.inValue("Multiply",1),m=e.inSwitch("Value",["0-1","-1-1"],"0-1"),c=e.inSwitch("Harmonics",["1","2","3","4","5"],"1"),d=e.inValue("X",0),h=e.inValue("Y",0),f=e.inValue("Z",0),p=e.outTrigger("trigger");const g=e.patch.cgl;const v=new CGL.Shader(g,"perlinnoise");e.setPortGroup("Position",[d,h,f]);v.setSource(v.getDefaultVertexShader(),t.perlinnoise3d_frag);const b=new CGL.Uniform(v,"t","tex",0),x=new CGL.Uniform(v,"t","texOffsetZ",1),_=new CGL.Uniform(v,"t","texMask",2),O=new CGL.Uniform(v,"f","z",f),A=new CGL.Uniform(v,"f","x",d),I=new CGL.Uniform(v,"f","y",h),T=new CGL.Uniform(v,"f","scale",l),S=new CGL.Uniform(v,"f","amount",o),C=new CGL.Uniform(v,"f","rangeMul",u);CGL.TextureEffect.setupBlending(e,v,i,o,r);const y=e.inTexture("Offset"),E=e.inFloat("Offset Multiply",1),M=e.inSwitch("Offset X",["None","R","G","B"],"None"),P=e.inSwitch("Offset Y",["None","R","G","B"],"None"),N=e.inSwitch("Offset Z",["None","R","G","B"],"R");e.setPortGroup("Offset Map",[y,N,P,M,E]);const R=new CGL.Uniform(v,"f","offMul",E);const j=new CGL.Uniform(v,"f","aspect",1);const L=new CGL.Uniform(v,"f","harmonics",0);c.onChange=()=>{L.setValue(parseFloat(c.get()));v.toggleDefine("HARMONICS",c.get()>1)};m.onChange=M.onChange=P.onChange=N.onChange=a.onChange=s.onChange=y.onChange=w;w();function w(){v.toggleDefine("NO_CHANNEL_R",s.get()=="G"||s.get()=="B");v.toggleDefine("NO_CHANNEL_G",s.get()=="R"||s.get()=="B");v.toggleDefine("NO_CHANNEL_B",s.get()=="R"||s.get()=="G");v.toggleDefine("HAS_TEX_OFFSETMAP",y.get());v.toggleDefine("HAS_TEX_MASK",a.get());v.toggleDefine("OFFSET_X_R",M.get()=="R");v.toggleDefine("OFFSET_X_G",M.get()=="G");v.toggleDefine("OFFSET_X_B",M.get()=="B");v.toggleDefine("OFFSET_Y_R",P.get()=="R");v.toggleDefine("OFFSET_Y_G",P.get()=="G");v.toggleDefine("OFFSET_Y_B",P.get()=="B");v.toggleDefine("OFFSET_Z_R",N.get()=="R");v.toggleDefine("OFFSET_Z_G",N.get()=="G");v.toggleDefine("OFFSET_Z_B",N.get()=="B");v.toggleDefine("RANGE_MIN1",m.get()=="-1-1");M.setUiAttribs({greyout:!y.isLinked()});P.setUiAttribs({greyout:!y.isLinked()});N.setUiAttribs({greyout:!y.isLinked()});E.setUiAttribs({greyout:!y.isLinked()});v.toggleDefine("RGB",s.get()=="RGB")}n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;g.pushShader(v);g.currentTextureEffect.bind();j.setValue(g.currentTextureEffect.aspectRatio);g.setTexture(0,g.currentTextureEffect.getCurrentSourceTexture().tex);if(y.get())g.setTexture(1,y.get().tex);if(a.get())g.setTexture(2,a.get().tex);g.currentTextureEffect.finish();g.popShader();p.trigger()}};Ops.Gl.ImageCompose.Noise.PerlinNoise_v2.prototype=new CABLES.Op;CABLES.OPS["b4b238d3-db68-4206-8dc7-4b52433fc932"]={f:Ops.Gl.ImageCompose.Noise.PerlinNoise_v2,objName:"Ops.Gl.ImageCompose.Noise.PerlinNoise_v2"};Ops.Anim.Timer_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const r=e.inValue("Speed",1),n=e.inValueBool("Play",true),a=e.inTriggerButton("Reset"),i=e.inValueBool("Sync to timeline",false),o=e.outNumber("Time");e.setPortGroup("Controls",[n,a,r]);const s=new CABLES.Timer;let l=null;let u=0;let m=false;n.onChange=c;c();function c(){if(n.get()){s.play();e.patch.addOnAnimFrame(e)}else{s.pause();e.patch.removeOnAnimFrame(e)}}a.onTriggered=d;function d(){u=0;l=null;s.setTime(0);o.set(0)}i.onChange=function(){m=i.get();n.setUiAttribs({greyout:m});a.setUiAttribs({greyout:m})};e.onAnimFrame=function(e,t,n){if(s.isPlaying()){if(CABLES.overwriteTime!==undefined){o.set(CABLES.overwriteTime*r.get())}else if(m){o.set(e*r.get())}else{s.update();const a=s.get();if(l===null){l=a;return}const i=Math.abs(a-l);l=a;u+=i*r.get();if(u!=u)u=0;o.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.Gl.ImageCompose.EdgeDetection_v4=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={edgedetect_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float width;\nUNI float strength;\nUNI float texWidth;\nUNI float texHeight;\nUNI float mulColor;\n\nconst vec4 lumcoeff = vec4(0.299,0.587,0.114, 0.);\n\nvec3 desaturate(vec3 color)\n{\n    return vec3(dot(vec3(0.2126,0.7152,0.0722), color));\n}\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n    // vec4 col=vec4(1.0,0.0,0.0,1.0);\n\n    // float pixelX=0.27/texWidth;\n    // float pixelY=0.27/texHeight;\n    float pixelX=(width+0.01)*4.0/texWidth;\n    float pixelY=(width+0.01)*4.0/texHeight;\n\nvec2 tc=texCoord;\n// #ifdef OFFSETPIXEL\n    tc.x+=1.0/texWidth*0.5;\n    tc.y+=1.0/texHeight*0.5;\n// #endif\n    // col=texture(tex,texCoord);\n\n    float count=1.0;\n    vec4 base=texture(tex,texCoord);\n\n\tvec4 horizEdge = vec4( 0.0 );\n\thorizEdge -= texture( tex, vec2( tc.x - pixelX, tc.y - pixelY ) ) * 1.0;\n\thorizEdge -= texture( tex, vec2( tc.x - pixelX, tc.y     ) ) * 2.0;\n\thorizEdge -= texture( tex, vec2( tc.x - pixelX, tc.y + pixelY ) ) * 1.0;\n\thorizEdge += texture( tex, vec2( tc.x + pixelX, tc.y - pixelY ) ) * 1.0;\n\thorizEdge += texture( tex, vec2( tc.x + pixelX, tc.y     ) ) * 2.0;\n\thorizEdge += texture( tex, vec2( tc.x + pixelX, tc.y + pixelY ) ) * 1.0;\n\tvec4 vertEdge = vec4( 0.0 );\n\tvertEdge -= texture( tex, vec2( tc.x - pixelX, tc.y - pixelY ) ) * 1.0;\n\tvertEdge -= texture( tex, vec2( tc.x    , tc.y - pixelY ) ) * 2.0;\n\tvertEdge -= texture( tex, vec2( tc.x + pixelX, tc.y - pixelY ) ) * 1.0;\n\tvertEdge += texture( tex, vec2( tc.x - pixelX, tc.y + pixelY ) ) * 1.0;\n\tvertEdge += texture( tex, vec2( tc.x    , tc.y + pixelY ) ) * 2.0;\n\tvertEdge += texture( tex, vec2( tc.x + pixelX, tc.y + pixelY ) ) * 1.0;\n\n\thorizEdge*=base.a;\n\tvertEdge*=base.a;\n\n\n\tvec3 edge = sqrt((horizEdge.rgb/count * horizEdge.rgb/count) + (vertEdge.rgb/count * vertEdge.rgb/count));\n\n    edge=desaturate(edge);\n    edge*=strength;\n\n    if(mulColor>0.0) edge*=texture( tex, texCoord ).rgb*mulColor*4.0;\n    edge=max(min(edge,1.0),0.0);\n\n    //blend section\n    vec4 col=vec4(edge,base.a);\n\n    outColor=cgl_blendPixel(base,col,amount*base.a);\n}\n\n"};const n=e.inTrigger("Render"),a=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),i=e.inValueSlider("Amount",1),r=e.inFloat("Strength",4),o=e.inValueSlider("Width",.1),s=e.inValueSlider("Mul Color",0),l=e.outTrigger("Trigger");const u=e.patch.cgl;const m=new CGL.Shader(u,e.name,e);m.setSource(m.getDefaultVertexShader(),t.edgedetect_frag);const c=new CGL.Uniform(m,"t","tex",0),d=new CGL.Uniform(m,"f","amount",i),h=new CGL.Uniform(m,"f","strength",r),f=new CGL.Uniform(m,"f","width",o),p=new CGL.Uniform(m,"f","texWidth",128),g=new CGL.Uniform(m,"f","texHeight",128),v=new CGL.Uniform(m,"f","mulColor",s);CGL.TextureEffect.setupBlending(e,m,a,i);n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;u.pushShader(m);u.currentTextureEffect.bind();u.setTexture(0,u.currentTextureEffect.getCurrentSourceTexture().tex);p.setValue(u.currentTextureEffect.getCurrentSourceTexture().width);g.setValue(u.currentTextureEffect.getCurrentSourceTexture().height);u.currentTextureEffect.finish();u.popShader();l.trigger()}};Ops.Gl.ImageCompose.EdgeDetection_v4.prototype=new CABLES.Op;CABLES.OPS["0240e26e-b86d-43b2-8c72-6795bb86dc76"]={f:Ops.Gl.ImageCompose.EdgeDetection_v4,objName:"Ops.Gl.ImageCompose.EdgeDetection_v4"};Ops.Gl.ImageCompose.LumaKey_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={lumakeyV2_frag:"IN vec2 texCoord;\nUNI float threshholdLow;\nUNI float threshholdHigh;\nUNI sampler2D text;\n\nvoid main()\n{\n   vec4 col = texture(text, texCoord );\n\n   float gray = dot(vec3(0.2126,0.7152,0.0722), col.rgb );\n\n   #ifndef INVERT\n       if(gray < threshholdLow || gray > threshholdHigh) col.r=col.g=col.b=col.a=0.0;\n       #ifdef BLACKWHITE\n           else col.r=col.g=col.b=col.a=1.0;\n       #endif\n   #endif\n\n   #ifdef INVERT\n       if(gray > threshholdLow && gray < threshholdHigh) col.r=col.g=col.b=col.a=0.0;\n       #ifdef BLACKWHITE\n           else col.r=col.g=col.b=col.a=1.0;\n       #endif\n   #endif\n//   col.a=1.0;\n\n   outColor= col;\n}"};const n=e.inTrigger("render"),a=e.outTrigger("trigger"),i=e.inValueBool("Invert"),r=e.inValueBool("Black White"),o=e.inValueSlider("Threshold low ",.5),s=e.inValueSlider("Threshold high",1);const l=e.patch.cgl;const u=new CGL.Shader(l,"lumakey");u.setSource(u.getDefaultVertexShader(),t.lumakeyV2_frag);const m=new CGL.Uniform(u,"t","tex",0);const c=new CGL.Uniform(u,"f","threshholdLow",o);const d=new CGL.Uniform(u,"f","threshholdHigh",s);r.onChange=function(){if(r.get())u.define("BLACKWHITE");else u.removeDefine("BLACKWHITE")};i.onChange=function(){if(i.get())u.define("INVERT");else u.removeDefine("INVERT")};n.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();a.trigger()}};Ops.Gl.ImageCompose.LumaKey_v2.prototype=new CABLES.Op;CABLES.OPS["1699f3fc-355b-4497-a23c-1620a04a9cd4"]={f:Ops.Gl.ImageCompose.LumaKey_v2,objName:"Ops.Gl.ImageCompose.LumaKey_v2"};Ops.Gl.ImageCompose.Interlace=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={interlace_frag:"\n#ifdef HAS_TEXTURES\n  IN vec2 texCoord;\n  UNI sampler2D tex;\n#endif\nUNI float amount;\nUNI float lum;\nUNI float add;\nUNI float lineSize;\nUNI float scroll;\nUNI float displace;\n\n\nvoid main()\n{\n   vec4 col=vec4(1.0,0.0,0.0,1.0);\n\n   col=texture(tex,texCoord);\n    // .endl()+'   col=clamp(col,0.0,1.0);'\n\n    float dir;\n    #ifdef DIRECTION\n        dir = gl_FragCoord.x;\n    #endif\n\n    #ifndef DIRECTION\n        dir = gl_FragCoord.y;\n    #endif\n\n   if( mod(dir+scroll,lineSize)>=lineSize*0.5)\n   {\n       col=texture(tex,vec2(texCoord.x+displace*0.05,texCoord.y));\n       float gray = vec3(dot(vec3(0.2126,0.7152,0.0722), col.rgb)).r;\n       col.rgb=col.rgb*(1.0-amount) + (col.rgb*gray*gray*lum)*amount;\n   }\n   else col+=add;\n\n\n   outColor= col;\n}"};let n=e.inTrigger("render");let a=e.inValueSlider("amount",.5);let i=e.inValueSlider("Lumi Scale",.9);let r=e.inBool("X or Y",false);let o=e.inValue("Line Size",4);let s=e.inValueSlider("Displacement",0);let l=e.inValue("Add",.02);let u=e.inValue("scroll",0);let m=e.outTrigger("trigger");let c=e.patch.cgl;let d=new CGL.Shader(c,e.name,e);d.setSource(d.getDefaultVertexShader(),t.interlace_frag);let h=new CGL.Uniform(d,"t","tex",0);let f=new CGL.Uniform(d,"f","amount",a);let p=new CGL.Uniform(d,"f","lum",i);let g=new CGL.Uniform(d,"f","lineSize",o);let v=new CGL.Uniform(d,"f","add",l);let b=new CGL.Uniform(d,"f","displace",s);let x=new CGL.Uniform(d,"f","scroll",u);r.onChange=function(){d.toggleDefine("DIRECTION",r.get())};n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;c.pushShader(d);c.currentTextureEffect.bind();c.setTexture(0,c.currentTextureEffect.getCurrentSourceTexture().tex);c.currentTextureEffect.finish();c.popShader();m.trigger()}};Ops.Gl.ImageCompose.Interlace.prototype=new CABLES.Op;CABLES.OPS["3cd69d5b-6c05-4522-9551-52458f99421a"]={f:Ops.Gl.ImageCompose.Interlace,objName:"Ops.Gl.ImageCompose.Interlace"};Ops.Trigger.Repeat2d=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTrigger("exe"),o=e.inValueInt("num x",5),s=e.inValueInt("num y",5),l=e.inValueFloat("mul",1),u=e.inValueBool("center"),m=e.outTrigger("trigger"),c=e.outNumber("x"),d=e.outNumber("y"),h=e.outNumber("index"),f=e.outNumber("total iterations");n.onTriggered=function(){let n=0;let e=0;const a=l.get();const i=o.get();const r=s.get();if(u.get()){n=(i-1)*a/2;e=(r-1)*a/2}for(let t=0;t<r;t++){d.set(t*a-e);for(let e=0;e<i;e++){c.set(e*a-n);h.set(e+t*i);m.trigger()}}f.set(o.get()*s.get())}};Ops.Trigger.Repeat2d.prototype=new CABLES.Op;CABLES.OPS["79934693-5887-4173-8b48-3e3a18fcf225"]={f:Ops.Trigger.Repeat2d,objName:"Ops.Trigger.Repeat2d"};Ops.Gl.ShaderEffects.ColorArea_v4=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={colorarea_frag:"\nvec3 MOD_size=vec3(MOD_inSizeAmountFalloffSizeX.x);\n#ifdef MOD_DOSCALE\n    MOD_size=1.0/MOD_scale;\n#endif\n\nvec3 MOD_col=MOD_color;\n\n#ifdef MOD_USE_TEX\n    MOD_col=texture(MOD_tex,gl_FragCoord.xy/ float( textureSize(MOD_tex,0).xy) ).rgb;\n#endif\n\n#ifdef MOD_AREA_SPHERE\n    float MOD_de=distance(\n        MOD_pos*MOD_size,\n        MOD_vertPos.xyz*MOD_size\n        )/MOD_inSizeAmountFalloffSizeX.x;\n#endif\n\n#ifdef MOD_AREA_BOX\n    float MOD_de=1.0;\n\n    if(\n        abs((MOD_vertPos.xyz*MOD_size).x-(MOD_pos.xyz*MOD_size).x) > MOD_inSizeAmountFalloffSizeX.x ||\n        abs((MOD_vertPos.xyz*MOD_size).y-(MOD_pos.xyz*MOD_size).y) > MOD_inSizeAmountFalloffSizeX.x ||\n        abs((MOD_vertPos.xyz*MOD_size).z-(MOD_pos.xyz*MOD_size).z) > MOD_inSizeAmountFalloffSizeX.x )  MOD_de=0.0;\n#endif\n\n#ifdef MOD_AREA_AXIS_X\n    float MOD_de=abs(MOD_pos.x-MOD_vertPos.x);\n#endif\n#ifdef MOD_AREA_AXIS_Y\n    float MOD_de=abs(MOD_pos.y-MOD_vertPos.y);\n#endif\n#ifdef MOD_AREA_AXIS_Z\n    float MOD_de=abs(MOD_pos.z-MOD_vertPos.z);\n#endif\n\n#ifdef MOD_AREA_AXIS_X_INFINITE\n    float MOD_de=MOD_pos.x-MOD_vertPos.x;\n#endif\n#ifdef MOD_AREA_AXIS_Y_INFINITE\n    float MOD_de=MOD_pos.y-MOD_vertPos.y;\n#endif\n#ifdef MOD_AREA_AXIS_Z_INFINITE\n    float MOD_de=MOD_pos.z-MOD_vertPos.z;\n#endif\n\n#ifndef MOD_AREA_BOX\n    MOD_de=1.0-smoothstep(MOD_inSizeAmountFalloffSizeX.z*MOD_inSizeAmountFalloffSizeX.x,MOD_inSizeAmountFalloffSizeX.x,MOD_de);\n#endif\n\n#ifdef MOD_AREA_INVERT\n    MOD_de=1.0-MOD_de;\n#endif\n\n#ifdef MOD_BLEND_NORMAL\n    col.rgb=mix(col.rgb,MOD_col, MOD_de*MOD_inSizeAmountFalloffSizeX.y);\n#endif\n\n\n#ifdef MOD_BLEND_MULTIPLY\n    col.rgb=mix(col.rgb,col.rgb*MOD_col,MOD_de*MOD_inSizeAmountFalloffSizeX.y);\n#endif\n\n#ifdef MOD_BLEND_ADD\n    col.rgb+=MOD_de*MOD_inSizeAmountFalloffSizeX.y*MOD_col;\n#endif\n\n\n#ifdef MOD_BLEND_OPACITY\n    col.a*=(1.0-MOD_de*MOD_inSizeAmountFalloffSizeX.y);\n#endif\n\n#ifdef MOD_BLEND_DISCARD\n    if(MOD_de*MOD_inSizeAmountFalloffSizeX.y>=0.999)discard;\n#endif\n\n// col.rgb=vec3(distance(MOD_vertPos.xyz,MOD_pos.xyz))*0.1\n// col.rgb=MOD_pos.xyz;",colorarea_head_frag:"IN vec4 MOD_vertPos;\n"};const n=e.inTrigger("Render"),a=e.inValueSelect("Area",["Sphere","Box","Axis X","Axis Y","Axis Z","Axis X Infinite","Axis Y Infinite","Axis Z Infinite"],"Sphere"),i=e.inValue("Size",1),r=e.inValueSlider("Amount",.5),o=e.inValueSlider("Falloff",0),s=e.inValueBool("Invert"),l=e.inSwitch("Blend ",["Normal","Multiply","Opacity","Add","Discard"],"Normal"),u=e.inValueSlider("r",Math.random()),m=e.inValueSlider("g",Math.random()),c=e.inValueSlider("b",Math.random()),d=e.inValue("x"),h=e.inValue("y"),f=e.inValue("z"),p=e.inBool("Change Size",false),g=e.inFloat("Size X",1),v=e.inFloat("Size Y",1),b=e.inFloat("Size Z",1),x=e.inTexture("Texture"),_=e.inValueBool("WorldSpace",true),O=e.inBool("Priority",true),A=e.outTrigger("Next");e.setPortGroup("Scale",[p,g,b,v]);e.setPortGroup("Position",[d,h,f]);e.setPortGroup("Color",[l,u,m,c]);u.setUiAttribs({colorPick:true});const I=e.patch.cgl;const T="".endl()+"OUT vec4 MOD_vertPos;".endl();const S="".endl()+"#ifndef MOD_WORLDSPACE".endl()+"   MOD_vertPos=vec4(vPosition,1.0);".endl()+"#endif".endl()+"#ifdef MOD_WORLDSPACE".endl()+"   MOD_vertPos=mMatrix*pos;".endl()+"#endif".endl();_.onChange=x.onLinkChanged=a.onChange=s.onChange=p.onChange=l.onChange=M;n.onTriggered=N;const C="vert_"+e.name;const y=new CGL.ShaderModifier(I,e.name,{opId:e.id});y.addModule({priority:2,title:C,name:"MODULE_VERTEX_POSITION",srcHeadVert:T,srcBodyVert:S});y.addModule({title:e.name,name:"MODULE_COLOR",srcHeadFrag:t.colorarea_head_frag,srcBodyFrag:t.colorarea_frag});y.addUniform("4f","MOD_inSizeAmountFalloffSizeX",i,r,o,0);y.addUniform("3f","MOD_color",u,m,c);y.addUniform("3f","MOD_pos",d,h,f);y.addUniform("3f","MOD_scale",g,v,b);y.addUniform("t","MOD_tex");M();O.onChange=E;E();function E(){y.removeModule(C);const e={title:C,name:"MODULE_VERTEX_POSITION",srcHeadVert:T,srcBodyVert:S};if(O.get())e.priority=2;y.addModule(e)}function M(){y.toggleDefine("MOD_BLEND_NORMAL",l.get()=="Normal");y.toggleDefine("MOD_BLEND_OPACITY",l.get()=="Opacity");y.toggleDefine("MOD_BLEND_MULTIPLY",l.get()=="Multiply");y.toggleDefine("MOD_BLEND_DISCARD",l.get()=="Discard");y.toggleDefine("MOD_BLEND_ADD",l.get()=="Add");y.toggleDefine("MOD_AREA_SIZE",p.get());y.toggleDefine("MOD_AREA_INVERT",s.get());y.toggleDefine("MOD_WORLDSPACE",_.get());y.toggleDefine("MOD_AREA_AXIS_X",a.get()=="Axis X");y.toggleDefine("MOD_AREA_AXIS_Y",a.get()=="Axis Y");y.toggleDefine("MOD_AREA_AXIS_Z",a.get()=="Axis Z");y.toggleDefine("MOD_AREA_AXIS_X_INFINITE",a.get()=="Axis X Infinite");y.toggleDefine("MOD_AREA_AXIS_Y_INFINITE",a.get()=="Axis Y Infinite");y.toggleDefine("MOD_AREA_AXIS_Z_INFINITE",a.get()=="Axis Z Infinite");y.toggleDefine("MOD_AREA_SPHERE",a.get()=="Sphere");y.toggleDefine("MOD_AREA_BOX",a.get()=="Box");y.toggleDefine("MOD_DOSCALE",p.get());g.setUiAttribs({greyout:!p.get()});v.setUiAttribs({greyout:!p.get()});b.setUiAttribs({greyout:!p.get()});y.toggleDefine("MOD_USE_TEX",x.isLinked())}function P(){if(I.frameStore.shadowPass)return;if(I.shouldDrawHelpers(e))gui.setTransformGizmo({posX:d,posY:h,posZ:f})}function N(){y.bind();if(x.isLinked()){let e=x.get();if(!e)e=CGL.Texture.getEmptyTexture(I).tex;else e=e.tex;y.pushTexture("MOD_tex",e)}P();A.trigger();y.unbind()}};Ops.Gl.ShaderEffects.ColorArea_v4.prototype=new CABLES.Op;CABLES.OPS["83a4b2b8-23ff-4491-b538-e89ac7934d1a"]={f:Ops.Gl.ShaderEffects.ColorArea_v4,objName:"Ops.Gl.ShaderEffects.ColorArea_v4"};Ops.Gl.Meshes.Cube_v2=function(){CABLES.Op.apply(this,arguments);const o=this;const e=o.attachments={};const t=o.inTrigger("Render"),n=o.inValueBool("Render Mesh",true),s=o.inValue("Width",1),l=o.inValue("Length",1),u=o.inValue("Height",1),m=o.inValueBool("Center",true),c=o.inSwitch("Mapping",["Side","Cube +-","SideWrap"],"Side"),d=o.inValue("Bias",0),h=o.inValueBool("Flip X",true),f=o.inValueBool("Top",true),p=o.inValueBool("Bottom",true),g=o.inValueBool("Left",true),v=o.inValueBool("Right",true),b=o.inValueBool("Front",true),x=o.inValueBool("Back",true),a=o.outTrigger("Next"),_=o.outObject("geometry",null,"geometry");const i=o.patch.cgl;o.toWorkPortsNeedToBeLinked(t);o.toWorkShouldNotBeChild("Ops.Gl.TextureEffects.ImageCompose",CABLES.OP_PORT_TYPE_FUNCTION);o.setPortGroup("Mapping",[c,d,h]);o.setPortGroup("Geometry",[s,u,l,m]);o.setPortGroup("Sides",[f,p,g,v,b,x]);let O=null,A=null,I=true,T=true;d.onChange=h.onChange=f.onChange=p.onChange=g.onChange=v.onChange=b.onChange=x.onChange=c.onChange=s.onChange=u.onChange=l.onChange=m.onChange=r;function r(){T=true}t.onLinkChanged=function(){if(!t.isLinked())_.set(null);else _.setRef(O)};t.onTriggered=function(){if(T)S();if(n.get()&&A&&I)A.render(i.getShader());a.trigger()};o.preRender=function(){S();if(A&&i)A.render(i.getShader())};function S(){if(!O)O=new CGL.Geometry("cubemesh");O.clear();let e=s.get();let t=-1*s.get();let n=u.get();let a=-1*u.get();let i=l.get();let r=-1*l.get();if(!m.get()){t=0;a=0;r=0}else{e*=.5;t*=.5;n*=.5;a*=.5;i*=.5;r*=.5}E(O,e,n,i,t,a,r);if(c.get()=="Side")C(O,1,1,1);else if(c.get()=="SideWrap")C(O,e,n,i);else y(O);O.verticesIndices=[];if(f.get())O.verticesIndices.push(8,9,10,8,10,11);if(p.get())O.verticesIndices.push(12,13,14,12,14,15);if(g.get())O.verticesIndices.push(20,21,22,20,22,23);if(v.get())O.verticesIndices.push(16,17,18,16,18,19);if(x.get())O.verticesIndices.push(4,5,6,4,6,7);if(b.get())O.verticesIndices.push(0,1,2,0,2,3);if(O.verticesIndices.length===0)I=false;else I=true;if(A)A.dispose();if(o.patch.cg)A=o.patch.cg.createMesh(O,{opId:o.id});_.setRef(O);T=false}o.onDelete=function(){if(A)A.dispose()};function C(e,t,n,a){const i=d.get();let r=1-i;let o=0+i;if(h.get()){[r,o]=[o,r]}let s=1-i;let l=0+i;e.setTexCoords([t*o,n*s,t*r,n*s,t*r,n*l,t*o,n*l,t*r,n*s,t*r,n*l,t*o,n*l,t*o,n*s,t*o,a*l,t*o,a*s,t*r,a*s,t*r,a*l,t*r,n*l,t*o,n*l,t*o,n*s,t*r,n*s,a*r,n*s,a*r,n*l,a*o,n*l,a*o,n*s,a*o,n*s,a*r,n*s,a*r,n*l,a*o,n*l])}function y(e,t,n,a,i,r,o){const s=.25;const l=1/3;const u=d.get();let m=0;if(h.get())m=1;const c=[];c.push(m+s+u,l*2-u,m+s*2-u,l*2-u,m+s*2-u,l+u,m+s+u,l+u,m+s*4-u,l*2-u,m+s*4-u,l+u,m+s*3+u,l+u,m+s*3+u,l*2-u);if(h.get())c.push(s+u,0-u,s*2-u,0-u,s*2-u,l*1+u,s+u,l*1+u,s+u,l*3+u,s+u,l*2-u,s*2-u,l*2-u,s*2-u,l*3+u);else c.push(s+u,0+u,s+u,l*1-u,s*2-u,l*1-u,s*2-u,0+u,s+u,l*3-u,s*2-u,l*3-u,s*2-u,l*2+u,s+u,l*2+u);c.push(m+s*3-u,1-l-u,m+s*3-u,1-l*2+u,m+s*2+u,1-l*2+u,m+s*2+u,1-l-u,m+s*0+u,1-l-u,m+s*1-u,1-l-u,m+s*1-u,1-l*2+u,m+s*0+u,1-l*2+u);e.setTexCoords(c)}function E(e,t,n,a,i,r,o){e.vertices=[i,r,a,t,r,a,t,n,a,i,n,a,i,r,o,i,n,o,t,n,o,t,r,o,i,n,o,i,n,a,t,n,a,t,n,o,i,r,o,t,r,o,t,r,a,i,r,a,t,r,o,t,n,o,t,n,a,t,r,a,i,r,o,i,r,a,i,n,a,i,n,o];e.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]);e.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]);e.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])}};Ops.Gl.Meshes.Cube_v2.prototype=new CABLES.Op;CABLES.OPS["37b92ba4-cea5-42ae-bf28-a513ca28549c"]={f:Ops.Gl.Meshes.Cube_v2,objName:"Ops.Gl.Meshes.Cube_v2"};Ops.Gl.ShaderEffects.PerlinAreaDeform_v4=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={perlindeform_vert:"vec3 MOD_newTangent,MOD_newBiTangent;\n\n#ifndef PERLINDEFORM\n#define PERLINDEFORM\nfloat Interpolation_C2( float x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }   //  6x^5-15x^4+10x^3\t( Quintic Curve.  As used by Perlin in Improved Noise.  http://mrl.nyu.edu/~perlin/paper445.pdf )\nvec2 Interpolation_C2( vec2 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec3 Interpolation_C2( vec3 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2( vec4 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2_InterpAndDeriv( vec2 x ) { return x.xyxy * x.xyxy * ( x.xyxy * ( x.xyxy * ( x.xyxy * vec2( 6.0, 0.0 ).xxyy + vec2( -15.0, 30.0 ).xxyy ) + vec2( 10.0, -60.0 ).xxyy ) + vec2( 0.0, 30.0 ).xxyy ); }\nvec3 Interpolation_C2_Deriv( vec3 x ) { return x * x * (x * (x * 30.0 - 60.0) + 30.0); }\n\n\nvoid FAST32_hash_3D( \tvec3 gridcell,\n                        out vec4 lowz_hash_0,\n                        out vec4 lowz_hash_1,\n                        out vec4 lowz_hash_2,\n                        out vec4 highz_hash_0,\n                        out vec4 highz_hash_1,\n                        out vec4 highz_hash_2\t)\t\t//\tgenerates 3 random numbers for each of the 8 cell corners\n{\n    //    gridcell is assumed to be an integer coordinate\n\n    //\tTODO: \tthese constants need tweaked to find the best possible noise.\n    //\t\t\tprobably requires some kind of brute force computational searching or something....\n    const vec2 OFFSET = vec2( 50.0, 161.0 );\n    const float DOMAIN = 69.0;\n    const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );\n    const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );\n\n    //\ttruncate the domain\n    gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n    vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n    //\tcalculate the noise\n    vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n    P *= P;\n    P = P.xzxz * P.yyww;\n    vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );\n    vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );\n    lowz_hash_0 = fract( P * lowz_mod.xxxx );\n    highz_hash_0 = fract( P * highz_mod.xxxx );\n    lowz_hash_1 = fract( P * lowz_mod.yyyy );\n    highz_hash_1 = fract( P * highz_mod.yyyy );\n    lowz_hash_2 = fract( P * lowz_mod.zzzz );\n    highz_hash_2 = fract( P * highz_mod.zzzz );\n}\n\n//\n//\tPerlin Noise 3D  ( gradient noise )\n//\tReturn value range of -1.0->1.0\n//\thttp://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg\n//\nfloat Perlin3D( vec3 P )\n{\n    //\testablish our grid cell and unit position\n    vec3 Pi = floor(P);\n    vec3 Pf = P - Pi;\n    vec3 Pf_min1 = Pf - 1.0;\n\n#if 1\n    //\n    //\tclassic noise.\n    //\trequires 3 random values per point.  with an efficent hash function will run faster than improved noise\n    //\n\n    //\tcalculate the hash.\n    //\t( various hashing methods listed in order of speed )\n    vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;\n    FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n    //SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n\n    //\tcalculate the gradients\n    vec4 grad_x0 = hashx0 - 0.49999;\n    vec4 grad_y0 = hashy0 - 0.49999;\n    vec4 grad_z0 = hashz0 - 0.49999;\n    vec4 grad_x1 = hashx1 - 0.49999;\n    vec4 grad_y1 = hashy1 - 0.49999;\n    vec4 grad_z1 = hashz1 - 0.49999;\n    vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );\n    vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );\n\n#if 1\n    //\tClassic Perlin Interpolation\n    vec3 blend = Interpolation_C2( Pf );\n    vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n    vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n    float final = dot( res0, blend2.zxzx * blend2.wwyy );\n    final *= 1.1547005383792515290182975610039;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range    *= 1.0/sqrt(0.75)\n    return final;\n#else\n    //\tClassic Perlin Surflet\n    //\thttp://briansharpe.wordpress.com/2012/03/09/modifications-to-classic-perlin-noise/\n    Pf *= Pf;\n    Pf_min1 *= Pf_min1;\n    vec4 vecs_len_sq = vec4( Pf.x, Pf_min1.x, Pf.x, Pf_min1.x ) + vec4( Pf.yy, Pf_min1.yy );\n    float final = dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf.zzzz ) ), grad_results_0 ) + dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf_min1.zzzz ) ), grad_results_1 );\n    final *= 2.3703703703703703703703703703704;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range    *= 1.0/cube(0.75)\n    return final;\n#endif\n\n#else\n    //\n    //\timproved noise.\n    //\trequires 1 random value per point.  Will run faster than classic noise if a slow hashing function is used\n    //\n\n    //\tcalculate the hash.\n    //\t( various hashing methods listed in order of speed )\n    vec4 hash_lowz, hash_highz;\n    FAST32_hash_3D( Pi, hash_lowz, hash_highz );\n    //BBS_hash_3D( Pi, hash_lowz, hash_highz );\n    //SGPP_hash_3D( Pi, hash_lowz, hash_highz );\n\n    //\n    //\t\"improved\" noise using 8 corner gradients.  Faster than the 12 mid-edge point method.\n    //\tKen mentions using diagonals like this can cause \"clumping\", but we'll live with that.\n    //\t[1,1,1]  [-1,1,1]  [1,-1,1]  [-1,-1,1]\n    //\t[1,1,-1] [-1,1,-1] [1,-1,-1] [-1,-1,-1]\n    //\n    hash_lowz -= 0.5;\n    vec4 grad_results_0_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_lowz );\n    hash_lowz = abs( hash_lowz ) - 0.25;\n    vec4 grad_results_0_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_lowz );\n    vec4 grad_results_0_2 = Pf.zzzz * sign( abs( hash_lowz ) - 0.125 );\n    vec4 grad_results_0 = grad_results_0_0 + grad_results_0_1 + grad_results_0_2;\n\n    hash_highz -= 0.5;\n    vec4 grad_results_1_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_highz );\n    hash_highz = abs( hash_highz ) - 0.25;\n    vec4 grad_results_1_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_highz );\n    vec4 grad_results_1_2 = Pf_min1.zzzz * sign( abs( hash_highz ) - 0.125 );\n    vec4 grad_results_1 = grad_results_1_0 + grad_results_1_1 + grad_results_1_2;\n\n    //\tblend the gradients and return\n    vec3 blend = Interpolation_C2( Pf );\n    vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n    vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n    return dot( res0, blend2.zxzx * blend2.wwyy ) * (2.0 / 3.0);\t//\t(optionally) mult by (2.0/3.0) to scale to a strict -1.0->1.0 range\n#endif\n}\n\n#endif\n\nvec3 MOD_deform(vec3 pos,vec3 norm)\n{\n    vec3 modelPos=pos;\n    vec3 forcePos=vec3(MOD_x,MOD_y,MOD_z);\n\n    vec3 vecToOrigin=modelPos-forcePos;\n    float dist=abs(length(vecToOrigin));\n    // float distAlpha = (MOD_size - dist) / MOD_size;\n\n    if(dist*MOD_mScale<MOD_size*MOD_mScale)\n    {\n        vec3 ppos=vec3(pos*MOD_scale*MOD_mScale);\n        ppos.x+=MOD_scrollx;\n        ppos.y+=MOD_scrolly;\n        ppos.z+=MOD_scrollz;\n\n        float p=(Perlin3D(ppos))*MOD_strength;\n\n        float dist=distance(vec3(MOD_x,MOD_y,MOD_z),modelPos);\n        float fallOff=1.0-smoothstep(MOD_fallOff*MOD_size,MOD_size,dist);\n\n        vec3 pnorm=norm;//normalize(pos.xyz);\n\n        #ifdef MOD_METH_MULNORM\n            pos.x+=p*pnorm.x*fallOff;\n            pos.y+=p*pnorm.y*fallOff;\n            pos.z+=p*pnorm.z*fallOff;\n        #endif\n        #ifdef MOD_METH_MULNORM_Y\n            pos.y+=p*pnorm.y*fallOff;\n        #endif\n\n        #ifdef MOD_METH_MUL_Z\n            pos.z+=p*pos.z*fallOff;\n        #endif\n\n        #ifdef MOD_METH_MUL_XYZ\n            pos.x+=p*pos.x*fallOff;\n            pos.y+=p*pos.y*fallOff;\n            pos.z+=p*pos.z*fallOff;\n\n        #endif\n\n        #ifdef MOD_METH_ADD_XYZ\n            pos.x+=p*fallOff;\n            pos.y+=p*fallOff;\n            pos.z+=p*fallOff;\n        #endif\n\n        #ifdef MOD_METH_ADD_Z\n            pos.z+=p*fallOff;\n        #endif\n        #ifdef MOD_METH_ADD_Y\n            pos.y+=p*fallOff;\n        #endif\n        #ifdef MOD_METH_ADD_X\n            pos.x+=p*fallOff;\n        #endif\n    }\n\n    return pos;\n}\n\n// LOOK AT THIS./....\n//https://github.com/spite/perlin-experiments/blob/master/chrome.html\n\n\nvec3 MOD_calcNormal(vec3 pos,vec3 norm,vec3 tangent,vec3 bitangent)\n{\n    //http://diary.conewars.com/vertex-displacement-shader/\n    vec4 position=vec4(MOD_deform(pos,norm),1.0);\n\n    vec3 positionAndTangent = MOD_deform( pos + tangent * 0.1,norm );\n    vec3 positionAndBitangent = MOD_deform( pos + bitangent * 0.1,norm );\n\n    MOD_newTangent = ( positionAndTangent - position.xyz ); // leaves just 'tangent'\n    MOD_newBiTangent = ( positionAndBitangent - position.xyz ); // leaves just 'bitangent'\n\n    vec3 newNormal = cross( MOD_newTangent.xyz, MOD_newBiTangent.xyz );\n    return normalize(newNormal.xyz);\n\n}\n\n",perlindeform_body_vert:"\nvec4 MOD_p=pos;\n\n#ifdef POS_ATTR\n    MOD_p=vec4(vPosition,1.0);\n#endif\n\n#ifdef POS_MMATRIX\n    MOD_p=vec4(mMatrix[3][0],mMatrix[3][1],mMatrix[3][2],1.0);\n#endif\n\n#ifndef MOD_WORLDSPACE\n    pos.xyz=MOD_deform(MOD_p.xyz,norm.xyz);\n\n    #ifdef MOD_CALC_NORMALS\n        norm=MOD_calcNormal(MOD_p.xyz,norm.xyz,tangent,bitangent);\n    #endif\n#endif\n\n#ifdef MOD_WORLDSPACE\n    pos.xyz=MOD_deform( (mMatrix*MOD_p).xyz ,norm.xyz);\n\n    #ifdef MOD_CALC_NORMALS\n        norm=MOD_calcNormal( (mMatrix*MOD_p).xyz,norm.xyz,tangent,bitangent);\n    #endif\n#endif\n\n#ifdef MOD_CALC_NORMALS\n    tangent=MOD_newTangent;\n    bitangent=MOD_newBiTangent;\n#endif\n\n\n\n#ifdef MOD_FLIP_NORMALS\n    norm*=-1.0;\n#endif\n"};const n=t.inTrigger("render"),a=t.outTrigger("trigger"),i=t.inValueFloat("Scale",1),r=t.inValueFloat("Size",1),o=t.inValueFloat("Strength",1),s=t.inValueBool("Calc Normals",false),l=t.inValueBool("Flip Normals",false),u=t.inValueSlider("Falloff",.5),m=t.inValueSelect("Output",["Mul Normal","Mul Z","Mul XYZ",,"Mul Norm Y","Add XYZ","Add X","Add Y","Add Z"],"Add XYZ"),c=t.inSwitch("Source",["Pos","Orig Pos","Model"],"Pos"),d=t.inValueFloat("x"),h=t.inValueFloat("y"),f=t.inValueFloat("z"),p=t.inValueFloat("Scroll X"),g=t.inValueFloat("Scroll Y"),v=t.inValueFloat("Scroll Z");const b=t.patch.cgl;const x=new CGL.ShaderModifier(b,t.name,{opId:t.id});l.onChange=s.onChange=I;const _=t.inValueBool("WorldSpace");const O=null;c.onChange=m.onChange=S;const A=null;_.onChange=T;x.addModule({priority:6,title:t.name,name:"MODULE_VERTEX_POSITION",srcHeadVert:e.perlindeform_vert,srcBodyVert:e.perlindeform_body_vert});x.addUniformVert("f","MOD_size",r);x.addUniformVert("f","MOD_strength",o);x.addUniformVert("f","MOD_scale",i);x.addUniformVert("f","MOD_scrollx",p);x.addUniformVert("f","MOD_scrolly",g);x.addUniformVert("f","MOD_scrollz",v);x.addUniformVert("f","MOD_x",d);x.addUniformVert("f","MOD_y",h);x.addUniformVert("f","MOD_z",f);x.addUniformVert("f","MOD_fallOff",u);x.addUniformVert("f","MOD_mScale",1);S();T();I();function I(){x.toggleDefine("MOD_FLIP_NORMALS",l.get());x.toggleDefine("MOD_CALC_NORMALS",s.get())}function T(){x.toggleDefine("MOD_WORLDSPACE",_.get())}function S(){x.toggleDefine("POS_ATTR",c.get()=="Orig Pos");x.toggleDefine("POS_MMATRIX",c.get()=="Model");x.toggleDefine("MOD_METH_MUL_XYZ",m.get()=="Mul XYZ");x.toggleDefine("MOD_METH_ADD_XYZ",m.get()=="Add XYZ");x.toggleDefine("MOD_METH_ADD_Z",m.get()=="Add Z");x.toggleDefine("MOD_METH_MUL_Z",m.get()=="Mul Z");x.toggleDefine("MOD_METH_ADD_Y",m.get()=="Add Y");x.toggleDefine("MOD_METH_ADD_X",m.get()=="Add X");x.toggleDefine("MOD_METH_MULNORM",m.get()=="Mul Normal");x.toggleDefine("MOD_METH_MULNORM_Y",m.get()=="Mul Norm Y")}function C(e){const t=e[8];const n=e[9];const a=e[10];return Math.hypot(t,n,a)}n.onTriggered=function(){if(!b.getShader()){a.trigger();return}const e=C(b.mMatrix);if(A)A.setValue(e);if(CABLES.UI){b.pushModelMatrix();if(b.shouldDrawHelpers(t)){b.pushModelMatrix();mat4.translate(b.mMatrix,b.mMatrix,[d.get(),h.get(),f.get()]);CABLES.GL_MARKER.drawSphere(t,r.get());b.popModelMatrix()}if(t.isCurrentUiOp())gui.setTransformGizmo({posX:d,posY:h,posZ:f});b.popModelMatrix()}x.bind();a.trigger();x.unbind()}};Ops.Gl.ShaderEffects.PerlinAreaDeform_v4.prototype=new CABLES.Op;CABLES.OPS["060ef3c1-bb79-46a5-9ec0-3272067fe504"]={f:Ops.Gl.ShaderEffects.PerlinAreaDeform_v4,objName:"Ops.Gl.ShaderEffects.PerlinAreaDeform_v4"};Ops.Gl.ImageCompose.Stripes_v4=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={stripes_v3_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float num;\nUNI float width;\nUNI float axis;\nUNI float offset;\nUNI float rotate;\n\nUNI float r;\nUNI float g;\nUNI float b;\n\n\n{{CGL.BLENDMODES3}}\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}\nvoid main()\n{\n    vec2 uv = texCoord-0.5;\n    pR(uv.xy,rotate*TAU);\n    float stripe=0.0;\n\n    float v=0.0;\n    float c=1.0;\n    v=uv.y;\n    v+=offset;\n\n    float m=mod(v,1.0/num);\n\n    #ifdef CIRCULAR\n        m=mod((length(uv)+offset)*1.5,1.0/num);\n    #endif\n\n    float rm=width*2.0*1.0/num/2.0;\n\n    if(m>rm)\n       stripe=mix(stripe,1.,1.0);\n\n    #ifdef STRIPES_SMOOTHED\n       m*=2.0;\n       stripe= r * smoothstep(0.,1., abs((((m-rm) )/(rm))));\n    #endif\n\n    #ifdef INVERT\n    stripe=1.0-stripe;\n    #endif\n\n    //blend section\n    vec4 col=vec4(vec3(r,g,b),1.0);\n    vec4 base=texture(tex,texCoord);\n\n    outColor=cgl_blendPixel(base,col,amount*stripe);\n}\n"};const n=e.inTrigger("Render"),a=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),i=e.inValueSlider("Amount",1),r=CGL.TextureEffect.AddBlendAlphaMask(e),o=e.inValue("Num",5),s=e.inValue("Width",.5),l=e.inValueSlider("Rotate",0),u=e.inValue("Offset",0),m=e.inValueBool("Gradients"),c=e.inValueBool("Circular"),d=e.inValueBool("Invert"),h=e.inValueSlider("r",Math.random()),f=e.inValueSlider("g",Math.random()),p=e.inValueSlider("b",Math.random()),g=e.outTrigger("trigger");h.setUiAttribs({colorPick:true});m.onChange=c.onChange=d.onChange=v;function v(){x.toggleDefine("STRIPES_SMOOTHED",m.get());x.toggleDefine("CIRCULAR",c.get());x.toggleDefine("INVERT",d.get())}const b=e.patch.cgl,x=new CGL.Shader(b,"textureeffect stripes");x.setSource(x.getDefaultVertexShader(),t.stripes_v3_frag);const _=new CGL.Uniform(x,"t","tex",0),O=new CGL.Uniform(x,"f","amount",i),A=new CGL.Uniform(x,"f","rotate",l),I=new CGL.Uniform(x,"f","num",o),T=new CGL.Uniform(x,"f","width",s),S=new CGL.Uniform(x,"f","offset",u),C=new CGL.Uniform(x,"f","r",h),y=new CGL.Uniform(x,"f","g",f),E=new CGL.Uniform(x,"f","b",p);CGL.TextureEffect.setupBlending(e,x,a,i,r);n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;b.pushShader(x);b.currentTextureEffect.bind();b.setTexture(0,b.currentTextureEffect.getCurrentSourceTexture().tex);b.currentTextureEffect.finish();b.popShader();g.trigger()}};Ops.Gl.ImageCompose.Stripes_v4.prototype=new CABLES.Op;CABLES.OPS["a1d57718-20a0-4d18-89d3-69947b0d1acf"]={f:Ops.Gl.ImageCompose.Stripes_v4,objName:"Ops.Gl.ImageCompose.Stripes_v4"};Ops.Gl.Phong.LambertMaterial_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={lambert_frag:"{{MODULES_HEAD}}\n\n#define AMBIENT 0\n#define POINT 1\n#define DIRECTIONAL 2\n#define SPOT 3\n\nIN vec3 norm;\nIN vec4 modelPos;\n\n// UNI mat4 normalMatrix;\nIN mat3 normalMatrix; // when instancing...\n\nIN vec2 texCoord;\n\nIN vec3 mvNormal;\nIN vec3 mvTangent;\nIN vec3 mvBiTangent;\n\nUNI vec4 materialColor;//r,g,b,a;\n\nstruct Light {\n    vec3 position;\n    vec3 color;\n    // * SPOT LIGHT * //\n    #ifdef HAS_SPOT\n        vec3 conePointAt;\n        #define COSCONEANGLE x\n        #define COSCONEANGLEINNER y\n        #define SPOTEXPONENT z\n        vec3 spotProperties;\n    #endif\n\n    #define INTENSITY x\n    #define ATTENUATION y\n    #define FALLOFF z\n    #define RADIUS w\n    vec4 lightProperties;\n\n    int type;\n    int castLight;\n    #define CASTLIGHT x\n    #define TYPE y\n    ivec2 castLightType;\n};\n#ifdef HAS_TEXTURES\n    #ifdef HAS_TEXTURE_DIFFUSE\n        UNI sampler2D texDiffuse;\n    #endif\n#endif\n\nUNI Light lights[NUM_LIGHTS];\n\n// * UTILITY FUNCTIONS */\nfloat when_gt(float x, float y) { return max(sign(x - y), 0.0); } // comparator function\nfloat when_eq(float x, float y) { return 1. - abs(sign(x - y)); } // comparator function\nfloat when_neq(float x, float y) { return abs(sign(x - y)); } // comparator function\n\n\n// * LIGHT CALCULATIONS */\nfloat CalculateFalloff(float radius, float falloff, float distLight)\n{\n    float denom = distLight / radius + 1.0;\n    float attenuation = 1.0 / (denom*denom);\n    float t = (attenuation - 0.1) / (1.0 - 0.1);\n\n    t = t * (20.0 * (1. - falloff) * 20.0 * (1. - falloff));\n\n    return min(1.0,max(t, 0.0));\n}\n\nfloat Falloff2(vec3 lightDirection, float falloff) {\n    float distanceSquared = dot(lightDirection, lightDirection);\n    float factor = distanceSquared * falloff;\n    float smoothFactor = clamp(1. - factor * factor, 0., 1.);\n    float attenuation = smoothFactor * smoothFactor;\n\n    return attenuation * 1. / max(distanceSquared, 0.00001);\n}\n\n#ifdef HAS_SPOT\n    float CalculateSpotLightEffect(vec3 lightPosition, vec3 conePointAt, float cosConeAngle, float cosConeAngleInner, float spotExponent, vec3 lightDirection) {\n        vec3 spotLightDirection = normalize(lightPosition-conePointAt);\n        float spotAngle = dot(-lightDirection, spotLightDirection);\n        float epsilon = cosConeAngle - cosConeAngleInner;\n\n        float spotIntensity = clamp((spotAngle - cosConeAngle)/epsilon, 0.0, 1.0);\n        spotIntensity = pow(spotIntensity, max(0.01, spotExponent));\n\n        return max(0., spotIntensity);\n    }\n#endif\nvec3 CalculateDiffuseColor(vec3 lightDirection, vec3 normal, vec3 lightColor, vec3 materialColor, inout float lambert) {\n    lambert = clamp(dot(lightDirection, normal), 0., 1.);\n    vec3 diffuseColor = lambert * lightColor * materialColor;\n    return diffuseColor;\n}\n\n\n// MAIN\nvoid main()\n{\n    {{MODULE_BEGIN_FRAG}}\n\n    vec4 col=vec4(0.0);\n    vec3 normal = normalize(mat3(normalMatrix)*norm);\n\n    #ifdef DOUBLE_SIDED\n        if(!gl_FrontFacing) normal = normal*-1.0;\n    #endif\n\n    vec3 matColor = materialColor.rgb;\n\n    #ifdef HAS_TEXTURES\n        #ifdef HAS_TEXTURE_DIFFUSE\n            matColor = texture(texDiffuse, texCoord).rgb;\n            #ifdef COLORIZE_TEXTURE\n                matColor *= materialColor.rgb;\n            #endif\n        #endif\n    #endif\n\n    for(int l=0;l<NUM_LIGHTS;l++) {\n        if (lights[l].castLightType.TYPE == AMBIENT) {\n            col.rgb += lights[l].lightProperties.INTENSITY * lights[l].color;\n        } else {\n            if (lights[l].castLightType.CASTLIGHT == 0) continue;\n\n            vec3 lightModelDiff= lights[l].position - modelPos.xyz;\n            vec3 lightDirection = normalize(lightModelDiff);\n\n            if (lights[l].castLightType.TYPE == DIRECTIONAL) lightDirection = lights[l].position;\n\n            float lambert = 1.; // inout variable\n            vec3 diffuseColor = CalculateDiffuseColor(lightDirection, normal, lights[l].color, matColor, lambert);\n\n            if (lights[l].castLightType.TYPE != DIRECTIONAL) diffuseColor *= Falloff2(lightDirection, lights[l].lightProperties.FALLOFF);\n\n            #ifdef HAS_SPOT\n                if (lights[l].castLightType.TYPE == SPOT) diffuseColor *= CalculateSpotLightEffect(\n                    lights[l].position, lights[l].conePointAt, lights[l].spotProperties.COSCONEANGLE,\n                    lights[l].spotProperties.COSCONEANGLEINNER, lights[l].spotProperties.SPOTEXPONENT,\n                    lightDirection\n                );\n            #endif\n\n            diffuseColor *= lights[l].lightProperties.INTENSITY;\n            col.rgb += diffuseColor;\n        }\n    }\n\n\n    col.a = materialColor.a;\n\n    {{MODULE_COLOR}}\n\n\n    outColor = col;\n}\n",lambert_vert:"#define TEX_REPEAT_X x;\n#define TEX_REPEAT_Y y;\n#define TEX_OFFSET_X z;\n#define TEX_OFFSET_Y w;\n\nIN vec3 vPosition;\nIN vec3 attrVertNormal;\nIN vec2 attrTexCoord;\n\nIN vec3 attrTangent;\nIN vec3 attrBiTangent;\nIN float attrVertIndex;\n\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\nOUT vec3 norm;\nOUT mat4 mvMatrix;\nOUT mat3 normalMatrix;\nOUT vec4 modelPos;\nOUT vec2 texCoord;\n{{MODULES_HEAD}}\n\nmat3 transposeMat3(mat3 m)\n{\n    return mat3(\n        m[0][0], m[1][0], m[2][0],\n        m[0][1], m[1][1], m[2][1],\n        m[0][2], m[1][2], m[2][2]);\n}\n\nmat3 inverseMat3(mat3 m)\n{\n    float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\n    float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\n    float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\n\n    float b01 = a22 * a11 - a12 * a21;\n    float b11 = -a22 * a10 + a12 * a20;\n    float b21 = a21 * a10 - a11 * a20;\n\n    float det = a00 * b01 + a01 * b11 + a02 * b21;\n\n    return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\n        b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\n        b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\n}\n\nvoid main()\n{\n    vec4 pos = vec4( vPosition, 1. );\n    mat4 mMatrix=modelMatrix;\n    vec3 tangent=attrTangent,\n        bitangent=attrBiTangent;\n\n    texCoord=attrTexCoord;\n    texCoord.y = 1. - texCoord.y;\n\n    norm=attrVertNormal;\n\n    {{MODULE_VERTEX_POSITION}}\n\n    normalMatrix = transposeMat3(inverseMat3(mat3(mMatrix)));\n\n\n    // this needs only to be done when instancing....\n\n    mat4 modelViewMatrix=viewMatrix*mMatrix;\n    {{MODULE_VERTEX_MODELVIEW}}\n    mvMatrix=modelViewMatrix;\n\n\n    modelPos=mMatrix*pos;\n\n    gl_Position = projMatrix * modelViewMatrix * pos;\n}\n"};const a={ambient:0,point:1,directional:2,spot:3};const n=e.inTrigger("Execute"),i=e.inValueSlider("Diffuse R",Math.random()),r=e.inValueSlider("Diffuse G",Math.random()),o=e.inValueSlider("Diffuse B",Math.random()),s=e.inValueSlider("Diffuse A",1);i.setUiAttribs({colorPick:true});e.setPortGroup("Diffuse Color",[i,r,o,s]);const l=e.inBool("Double Sided",false);l.setUiAttribs({hidePort:true});l.onChange=function(){g.toggleDefine("DOUBLE_SIDED",l.get())};e.setPortGroup("Material Properties",[l]);e.toWorkPortsNeedToBeLinked(n);e.toWorkShouldNotBeChild("Ops.Gl.TextureEffects.ImageCompose",CABLES.OP_PORT_TYPE_FUNCTION);const u=e.inTexture("Diffuse Texture");let m=null;const c=null;u.onChange=C;const d=e.inBool("Colorize Texture",false);d.onChange=function(){g.toggleDefine("COLORIZE_TEXTURE",d.get())};e.setPortGroup("Texture",[u,d]);let h=0;const f=e.outTrigger("next");const p=e.patch.cgl;const g=new CGL.Shader(p,"LambertMaterial");g.define("NUM_LIGHTS","1");const v=new CGL.Uniform(g,"4f","materialColor",i,r,o,s);g.uniformColorDiffuse=v;const b=e.outObject("Shader");b.set(g);const x=p.maxUniformsFrag;const _=x===64?6:16;const O=mat4.create();g.setSource(t.lambert_vert,t.lambert_frag);g.define("MAX_LIGHTS",_.toString());let A=null;const I=[];const T={directional:false,spot:false,ambient:false,point:false};const S=[{type:"point",position:[0,2,1],intensity:1,attenuation:0,falloff:.5,radius:80,castLight:1}];C();function C(){if(u.get()){if(!g.hasDefine("HAS_TEXTURE_DIFFUSE")){g.define("HAS_TEXTURE_DIFFUSE");if(!m)m=new CGL.Uniform(g,"t","texDiffuse",0)}}else{g.removeUniform("texDiffuse");g.removeDefine("HAS_TEXTURE_DIFFUSE");m=null}}function y(){A={color:new CGL.Uniform(g,"3f","lights[0].color",[1,1,1]),position:new CGL.Uniform(g,"3f","lights[0].position",[0,11,0]),lightProperties:new CGL.Uniform(g,"4f","lights[0].lightProperties",[1,1,1,1]),conePointAt:new CGL.Uniform(g,"3f","lights[0].conePointAt",vec3.create()),spotProperties:new CGL.Uniform(g,"3f","lights[0].spotProperties",[0,0,0,0]),castLightType:new CGL.Uniform(g,"2i","lights[0].castLightType",[0,0])}}function E(e){g.define("NUM_LIGHTS","1");g.removeDefine("HAS_SPOT");A.position.setValue(e.position);A.color.setValue(e.color);A.lightProperties.setValue([e.intensity,e.attenuation,e.falloff,e.radius]);A.castLightType.setValue([1,a[e.type]]);A.conePointAt.setValue(e.conePointAt);A.spotProperties.setValue([e.cosConeAngle,e.cosConeAngleInner,e.spotExponent])}function M(t){for(let e=0;e<I.length;e+=1)I[e]=null;T.directional=false;T.spot=false;T.ambient=false;T.point=false;for(let e=0;e<t.length;e+=1){if(e===_)return;I[e]=null;const n=t[e];const a=n.type;if(!T[a])T[a]=true;if(!I[e]){I[e]={color:new CGL.Uniform(g,"3f","lights["+e+"].color",[1,1,1]),position:new CGL.Uniform(g,"3f","lights["+e+"].position",[0,11,0]),lightProperties:new CGL.Uniform(g,"4f","lights["+e+"].lightProperties",[1,1,1,1]),conePointAt:new CGL.Uniform(g,"3f","lights["+e+"].conePointAt",vec3.create()),spotProperties:new CGL.Uniform(g,"3f","lights["+e+"].spotProperties",[0,0,0,0]),castLightType:new CGL.Uniform(g,"2i","lights["+e+"].castLightType",[0,0])}}}for(let e=0,t=Object.keys(T);e<t.length;e+=1){const i=t[e];g.toggleDefine("HAS_"+i.toUpperCase(),T[i])}}function P(t){for(let e=0;e<t.length;e+=1){const n=t[e];n.isUsed=true;I[e].position.setValue(n.position);I[e].color.setValue(n.color);I[e].lightProperties.setValue([n.intensity,n.attenuation,n.falloff,n.radius]);I[e].conePointAt.setValue(n.conePointAt);I[e].spotProperties.setValue([n.cosConeAngle,n.cosConeAngleInner,n.spotExponent]);I[e].castLightType.setValue([Number(n.castLight),a[n.type]])}}function N(e){if(e.length!==h){M(e);h=e.length;g.define("NUM_LIGHTS",""+Math.max(h,1));P(e)}else{P(e)}}function j(){if(!p.frameStore.lightStack||!p.frameStore.lightStack.length){if(!A)y();mat4.invert(O,p.vMatrix);S[0].position=[O[12],O[13],O[14]];E(S[0]);h=-1}else{if(g){if(p.frameStore.lightStack){if(p.frameStore.lightStack.length){A=null;N(p.frameStore.lightStack)}}}}}n.onTriggered=function(){if(!g){e.log("lambert has no shader...");return}if(p.frameStore.lightStack){if(p.frameStore.lightStack.length===0)e.setUiError("deflight","Default light is enabled. Please add lights to your patch to make this warning disappear.",1);else e.setUiError("deflight",null)}p.pushShader(g);g.popTextures();j();if(u.get())g.pushTexture(m,u.get().tex);f.trigger();p.popShader()}};Ops.Gl.Phong.LambertMaterial_v2.prototype=new CABLES.Op;CABLES.OPS["d69316f1-bde9-4645-8280-c635a8982e0d"]={f:Ops.Gl.Phong.LambertMaterial_v2,objName:"Ops.Gl.Phong.LambertMaterial_v2"};Ops.Trigger.TriggerLimiter=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTrigger("In Trigger"),a=e.inValue("Milliseconds",300),i=e.outTrigger("Out Trigger"),r=e.outNumber("Progress");let o=0;n.onTriggered=function(){const e=CABLES.now();let t=(e-o)/a.get();if(t>1)t=1;if(t<0)t=0;r.set(t);if(e>=o+a.get()){o=e;i.trigger()}}};Ops.Trigger.TriggerLimiter.prototype=new CABLES.Op;CABLES.OPS["47641d85-9f81-4287-8aa2-35753b0727e0"]={f:Ops.Trigger.TriggerLimiter,objName:"Ops.Trigger.TriggerLimiter"};Ops.Math.TriggerRandomNumber_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTriggerButton("Generate"),a=e.inValue("min",0),i=e.inValue("max",1),r=e.outTrigger("next"),o=e.outNumber("result"),s=e.inValueBool("Integer",false),l=e.inValueBool("No consecutive duplicates",false);e.setPortGroup("Value Range",[a,i]);n.onTriggered=i.onChange=a.onChange=s.onChange=u;u();function u(){let e=Math.random()*(i.get()-a.get())+a.get();if(s.get())e=m();if(a.get()!=i.get()&&i.get()>a.get())while(l.get()&&e==o.get())e=m();o.set(e);r.trigger()}function m(){return Math.floor(Math.random()*(i.get()-a.get()+1)+a.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"};Ops.Gl.Phong.PointLight_v5=function(){CABLES.Op.apply(this,arguments);const e=this;const R=e.attachments={};const t=e.patch.cgl;const k=t.gl;const B=CGL.MESHES.getSimpleRect(t,"fullscreenRectangle");function D(e){this.type=e.type||"point";this.color=e.color||[1,1,1];this.specular=e.specular||[0,0,0];this.position=e.position||null;this.intensity=e.intensity||1;this.radius=e.radius||1;this.falloff=e.falloff||1;this.spotExponent=e.spotExponent||1;this.cosConeAngle=Math.cos(CGL.DEG2RAD*this.coneAngle);this.conePointAt=e.conePointAt||[0,0,0];this.castShadow=e.castShadow||false;return this}const n=e.inTrigger("Trigger In");const a=e.inBool("Cast Light",true);const i=e.inFloat("Intensity",2);const r=e.inFloat("Radius",15);const o=e.inFloat("X",0);const s=e.inFloat("Y",2);const l=e.inFloat("Z",.75);const u=[o,s,l];e.setPortGroup("Position",u);const m=e.inFloat("R",.8);const c=e.inFloat("G",.8);const d=e.inFloat("B",.8);m.setUiAttribs({colorPick:true});const h=[m,c,d];e.setPortGroup("Color",h);const f=e.inFloat("Specular R",1);const p=e.inFloat("Specular G",1);const g=e.inFloat("Specular B",1);f.setUiAttribs({colorPick:true});const v=[f,p,g];e.setPortGroup("Specular Color",v);const b=e.inFloatSlider("Falloff",.5);const G=[i,a,r];e.setPortGroup("Light Attributes",G);const x=e.inBool("Cast Shadow",false);const _=e.inBool("Rendering Active",true);const O=e.inSwitch("Map Size",[256,512,1024,2048],512);const A=e.inFloatSlider("Shadow Strength",1);const I=e.inFloat("Near",.1);const T=e.inFloat("Far",30);const S=e.inFloatSlider("Bias",.004);const C=e.inInt("Polygon Offset",0);e.setPortGroup("",[x]);e.setPortGroup("Shadow Map Settings",[O,_,A,I,T,S,C]);const U=[I,T];O.setUiAttribs({greyout:!x.get()});_.setUiAttribs({greyout:!x.get()});A.setUiAttribs({greyout:!x.get()});I.setUiAttribs({greyout:!x.get()});S.setUiAttribs({greyout:!x.get()});T.setUiAttribs({greyout:!x.get()});C.setUiAttribs({greyout:!x.get()});let y=false;x.onChange=function(){y=true;N=true;O.setUiAttribs({greyout:!x.get()});_.setUiAttribs({greyout:!x.get()});A.setUiAttribs({greyout:!x.get()});I.setUiAttribs({greyout:!x.get()});T.setUiAttribs({greyout:!x.get()});S.setUiAttribs({greyout:!x.get()});C.setUiAttribs({greyout:!x.get()})};const E=e.outTrigger("Trigger Out");const M=e.outObject("Cubemap",null,"texture");const F=e.outNumber("World Position X");const V=e.outNumber("World Position Y");const z=e.outNumber("World Position Z");const P=new CGL.Light(t,{type:"point",position:[0,1,2].map(function(e){return u[e].get()}),color:[0,1,2].map(function(e){return h[e].get()}),specular:[0,1,2].map(function(e){return v[e].get()}),intensity:i.get(),radius:r.get(),falloff:b.get(),shadowStrength:A.get(),shadowBias:S.get()});P.castLight=a.get();let N=false;o.onChange=s.onChange=l.onChange=m.onChange=c.onChange=d.onChange=f.onChange=p.onChange=g.onChange=i.onChange=a.onChange=r.onChange=b.onChange=I.onChange=T.onChange=A.onChange=function(){N=true};O.onChange=function(){y=true};function X(){if(x.get()){const e=O.get();P.createFramebuffer(e,e,{});P.createShadowMapShader()}y=false}const q=vec3.create();const H=vec3.create();const j=vec3.create();const L=vec3.create();function W(){if(t.frameStore.shadowPass)return;if(CABLES.UI)gui.setTransform(e.id,o.get(),s.get(),l.get());if(e.isCurrentUiOp()){gui.setTransformGizmo({posX:o,posY:s,posZ:l});t.pushModelMatrix();mat4.translate(t.mMatrix,t.mMatrix,L);CABLES.GL_MARKER.drawSphere(e,r.get());t.popModelMatrix()}}let w=false;n.onTriggered=function(){if(y){if(t.frameStore.shadowPass)return;X()}if(!t.frameStore.shadowPass){if(!P.isUsed&&!w){e.setUiError("lightUsed","No operator is using this light. Make sure this op is positioned before an operator that uses lights. Also make sure there is an operator that uses lights after this.",1);w=true}else if(!P.isUsed&&w){}else if(P.isUsed&&w){e.setUiError("lightUsed",null);w=false}else if(P.isUsed&&!w){}P.isUsed=false}if(N){P.position=[0,1,2].map(function(e){return u[e].get()});P.color=[0,1,2].map(function(e){return h[e].get()});P.specular=[0,1,2].map(function(e){return v[e].get()});P.intensity=i.get();P.radius=r.get();P.falloff=b.get();P.castShadow=x.get();P.castLight=a.get();P.updateProjectionMatrix(null,I.get(),T.get(),null);N=false}if(!t.frameStore.lightStack)t.frameStore.lightStack=[];vec3.set(L,o.get(),s.get(),l.get());vec3.transformMat4(j,L,t.mMatrix);P.position=j;F.set(P.position[0]);V.set(P.position[1]);z.set(P.position[2]);if(!t.frameStore.shadowPass)W();t.frameStore.lightStack.push(P);if(x.get()){if(_.get())P.renderPasses(C.get(),null,function(){E.trigger()});if(!t.frameStore.shadowPass){t.frameStore.lightStack.pop();P.castShadow=x.get();P.shadowBias=S.get();P.shadowStrength=A.get();if(P.shadowCubeMap){if(P.shadowCubeMap.cubemap){M.set(null);M.set(P.shadowCubeMap);if(_.get()){P.positionForShadowMap=[P.position[0],P.position[1],P.position[2]]}}}t.frameStore.lightStack.push(P)}}else{M.set(null)}E.trigger();t.frameStore.lightStack.pop()}};Ops.Gl.Phong.PointLight_v5.prototype=new CABLES.Op;CABLES.OPS["54e5d3f5-e3f4-4381-990d-d5e32b9a2d39"]={f:Ops.Gl.Phong.PointLight_v5,objName:"Ops.Gl.Phong.PointLight_v5"};Ops.Gl.ImageCompose.Color_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={color_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float r;\nUNI float g;\nUNI float b;\nUNI float a;\nUNI float amount;\n\n#ifdef MASK\n    UNI sampler2D mask;\n#endif\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n    vec4 col=vec4(r,g,b,a);\n    vec4 base=texture(tex,texCoord);\n\n    float am=amount;\n    #ifdef MASK\n        float msk=texture(mask,texCoord).r;\n        #ifdef INVERTMASK\n            msk=1.0-msk;\n        #endif\n        am*=1.0-msk;\n    #endif\n\n    outColor=cgl_blendPixel(base,col,am);\n}\n"};const n=e.inTrigger("render"),a=CGL.TextureEffect.AddBlendSelect(e),i=e.inValueSlider("Amount",1),r=CGL.TextureEffect.AddBlendAlphaMask(e),o=e.inTexture("Mask"),s=e.inValueBool("Mask Invert"),l=e.inValueSlider("r",Math.random()),u=e.inValueSlider("g",Math.random()),m=e.inValueSlider("b",Math.random()),c=e.inValueSlider("A",1),d=e.outTrigger("trigger");l.setUiAttribs({colorPick:true});e.setPortGroup("Color",[l,u,m]);const h=0;const f=e.patch.cgl;const p=new CGL.Shader(f,"textureeffect color");const g=t.color_frag||"";p.setSource(p.getDefaultVertexShader(),g);CGL.TextureEffect.setupBlending(e,p,a,i,r);const v=new CGL.Uniform(p,"t","tex",h),b=new CGL.Uniform(p,"t","mask",1),x=new CGL.Uniform(p,"f","r",l),_=new CGL.Uniform(p,"f","g",u),O=new CGL.Uniform(p,"f","b",m),A=new CGL.Uniform(p,"f","a",c),I=new CGL.Uniform(p,"f","amount",i);o.onChange=function(){if(o.isLinked())p.define("MASK");else p.removeDefine("MASK")};s.onChange=function(){if(s.get())p.define("INVERTMASK");else p.removeDefine("INVERTMASK")};n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;f.pushShader(p);f.currentTextureEffect.bind();f.setTexture(h,f.currentTextureEffect.getCurrentSourceTexture().tex);if(o.get())f.setTexture(1,o.get().tex);f.currentTextureEffect.finish();f.popShader();d.trigger()}};Ops.Gl.ImageCompose.Color_v2.prototype=new CABLES.Op;CABLES.OPS["6dada2b7-da7c-47ee-87a9-a12e87055208"]={f:Ops.Gl.ImageCompose.Color_v2,objName:"Ops.Gl.ImageCompose.Color_v2"};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 n=e.inTrigger("Render"),a=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),i=e.inValueSlider("Amount",1),r=e.inValue("Sides",10),o=e.inValueSlider("Angle",0),s=e.inValueSlider("Slide X",0),l=e.inValueSlider("Slide Y",0),u=e.inValueSlider("Center X",.5),m=e.inValueSlider("Center Y",.5),c=e.inBool("Aspect Ratio",true),d=e.outTrigger("Next");let h=e.patch.cgl;let f=new CGL.Shader(h,e.name,e);const p=new CGL.Uniform(f,"f","sides",r),g=new CGL.Uniform(f,"f","angle",o),v=new CGL.Uniform(f,"f","slidex",s),b=new CGL.Uniform(f,"f","slidey",l),x=new CGL.Uniform(f,"f","centerX",u),_=new CGL.Uniform(f,"f","centerY",m),O=new CGL.Uniform(f,"f","amount",i),A=new CGL.Uniform(f,"f","aspect",1);CGL.TextureEffect.setupBlending(e,f,a,i);f.setSource(f.getDefaultVertexShader(),t.kaleidoscope_frag);let I=new CGL.Uniform(f,"t","tex",0);n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;h.pushShader(f);h.currentTextureEffect.bind();h.setTexture(0,h.currentTextureEffect.getCurrentSourceTexture().tex);if(c.get())A.setValue(h.currentTextureEffect.aspectRatio);else A.setValue(1);h.currentTextureEffect.finish();h.popShader();d.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.Fog_v4=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={fog_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D texDepth;\n\n#ifdef HAS_GRADIENT_TEX\n    UNI sampler2D texGradient;\n#endif\n\n#ifdef HAS_BG_TEX\n    UNI sampler2D texBg;\n#endif\n\nUNI float nearPlane;\nUNI float farPlane;\nUNI float inAmount;\nUNI vec4 inFogColor;\nUNI float inFogDensity;\nUNI float inFogStart;\nUNI float inFogEnd;\n\n{{CGL.BLENDMODES3}}\n\nfloat map(float value, float min1, float max1, float min2, float max2) {\n  return min2 + (value - min1) * (max2 - min2) / (max1 - min1);\n}\n\nfloat CalcFogDensity(float depth) {\n    float fogAmount = 1.0 - clamp((inFogEnd - depth) / (inFogEnd - inFogStart), 0.0, 1.0);\n\n    // float newDepth = map(depth, nearPlane, farPlane, 0., 1.);\n    // EXPONENTIAL: fogAmount = 1. - exp(MAGIC_NUMBER * -inFogDensity * newDepth); // smoothstep(fogStart, fogEnd, newDepth));\n    // EXP2: fogAmount = 1. - exp(-pow(MAGIC_NUMBER * inFogDensity * smoothstep(fogStart, fogEnd, newDepth), 2.0));\n\n    fogAmount *= inFogDensity;\n\n\n\n    return fogAmount;\n}\n\nvoid main()\n{\n    vec4 color = texture(tex, texCoord);\n\n    float depthFromTexture = texture(texDepth,texCoord).r;\n\n    float distanceToCamera_viewSpace = (nearPlane * farPlane) / (farPlane - depthFromTexture * (farPlane - nearPlane));\n\n    float fogAmount = CalcFogDensity(distanceToCamera_viewSpace);\n\n    vec4 fogColor = inFogColor;\n\n    #ifdef HAS_GRADIENT_TEX\n        vec4 fogColTex = texture(texGradient, vec2(clamp(distanceToCamera_viewSpace / (farPlane - nearPlane), 0.0, 0.9999),0.5));\n        fogColor *= fogColTex;\n    #endif\n\n    #ifdef HAS_BG_TEX\n        vec4 fogColTexBg = texture(texBg, texCoord);\n        fogColor *= fogColTexBg;\n\n    #endif\n\n    fogColor = color * (1.0 - fogAmount) + fogColor * fogAmount;\n    // fogColor = mix(color, fogColor, fogAmount);\n\n\n    #ifdef IGNORE_INF\n        if(depthFromTexture>0.99999) outColor=color;\n        else outColor = cgl_blendPixel(color, fogColor, inAmount);\n    #endif\n\n    #ifndef IGNORE_INF\n        outColor = cgl_blendPixel(color, fogColor, inAmount);\n    #endif\n\n}\n",fog_vert:"IN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\n\nOUT vec2 texCoord;\nOUT vec3 norm;\n\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\nUNI mat4 modelMatrix;\n\nvoid main()\n{\n    texCoord = attrTexCoord;\n    norm = attrVertNormal;\n    vec4 pos = vec4(vPosition,  1.0);\n\n    {{MODULE_VERTEX_POSITION}}\n\n    gl_Position = projMatrix * mvMatrix * pos;\n\n}\n"};const n=t.patch.cgl;const a=t.inTrigger("render"),i=CGL.TextureEffect.AddBlendSelect(t,"blendMode"),r=t.inFloatSlider("Amount",1),o=t.inTexture("Depth Texture"),s=t.inTexture("Gradient Texture"),l=t.inTexture("Background Texture"),u=t.inFloat("Fog Start",1),m=t.inFloat("Fog End",8),c=t.inFloatSlider("Fog Density",1),d=t.inBool("Ignore Infinity",false),h=t.inFloat("nearplane",.1),f=t.inFloat("farplane",20),p=t.inFloatSlider("Fog R",.6),g=t.inFloatSlider("Fog G",.6),v=t.inFloatSlider("Fog B",.6),b=t.inFloatSlider("Fog A",1),x=t.outTrigger("trigger");p.setUiAttribs({colorPick:true});t.setPortGroup("Textures",[o,s,l]);t.setPortGroup("Frustum",[f,h]);t.setPortGroup("Fog Options",[u,m,c]);t.setPortGroup("Fog Color",[p,g,v,b]);const _=new CGL.Shader(n,"Fog");const O=e.fog_frag;const A=e.fog_vert;_.setSource(A,O);const I=new CGL.Uniform(_,"f","inAmount",r),T=new CGL.Uniform(_,"t","tex",0),S=new CGL.Uniform(_,"t","texDepth",1),C=new CGL.Uniform(_,"t","texGradient",2),y=new CGL.Uniform(_,"t","texBg",3),E=new CGL.Uniform(_,"f","farPlane",f),M=new CGL.Uniform(_,"f","nearPlane",h),P=new CGL.Uniform(_,"f","aspectRatio",0),N=new CGL.Uniform(_,"4f","inFogColor",p,g,v,b),j=new CGL.Uniform(_,"f","inFogDensity",c),R=new CGL.Uniform(_,"f","inFogStart",u),k=new CGL.Uniform(_,"f","inFogEnd",m);CGL.TextureEffect.setupBlending(t,_,i,r);let L=false;s.onChange=l.onChange=()=>{L=true};function w(){_.toggleDefine("HAS_BG_TEX",l.get()&&l.get().tex);_.toggleDefine("IGNORE_INF",d.get());_.toggleDefine("HAS_GRADIENT_TEX",s.get()&&s.get().tex)}a.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(t,3))return;if(!o.get()){t.setUiError("noDepthTex","This op needs a depth texture to work properly!",0)}else{t.setUiError("noDepthTex",null)}if(L)w();if(o.get()&&o.get().tex){const e=n.currentTextureEffect.getCurrentSourceTexture().height/n.currentTextureEffect.getCurrentSourceTexture().width;P.set(e);n.pushShader(_);n.currentTextureEffect.bind();n.setTexture(0,n.currentTextureEffect.getCurrentSourceTexture().tex);if(o.get())n.setTexture(1,o.get().tex);if(s.get())n.setTexture(2,s.get().tex);if(l.get())n.setTexture(3,l.get().tex);n.currentTextureEffect.finish();n.popShader()}x.trigger()}};Ops.Gl.ImageCompose.Fog_v4.prototype=new CABLES.Op;CABLES.OPS["9d52bb1d-cf80-4f75-a80b-bdca16421d65"]={f:Ops.Gl.ImageCompose.Fog_v4,objName:"Ops.Gl.ImageCompose.Fog_v4"};Ops.Gl.ImageCompose.Twirl_v4=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={twirl_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float twistAmount;\nUNI float times;\nUNI float radius;\nUNI float centerX;\nUNI float centerY;\nUNI float aspect;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n    vec2 center=vec2(centerX,centerY);\n    center =((center+1.0)/2.0);\n    vec2 tc = texCoord;\n    tc -= center;\n\n    float dist = length(vec2(tc.x,tc.y/aspect));\n    if (dist < radius)\n    {\n        float percent = (radius - dist) / radius;\n        float theta = percent * percent * twistAmount * 8.0;\n        float s = sin(theta);\n        float c = cos(theta);\n        tc = vec2(dot(tc, vec2(c, -s)), dot(tc, vec2(s, c)));\n    }\n    tc += center;\n\n    vec4 col = texture(tex, tc);\n    vec4 base=texture(tex,texCoord);\n    outColor=cgl_blendPixel(base,col,amount);\n}\n"};const n=t.inTrigger("Render"),a=CGL.TextureEffect.AddBlendSelect(t,"Blend Mode","normal"),i=t.inValueSlider("Amount",1),r=t.inValue("Twist amount",500),o=t.inValue("Radius",.5),s=t.inValue("Center X",0),l=t.inValue("Center Y",0),u=t.outTrigger("Next");const m=t.patch.cgl;const c=new CGL.Shader(m,t.name,t);c.setSource(c.getDefaultVertexShader(),e.twirl_frag);const d=new CGL.Uniform(c,"t","tex",0),h=new CGL.Uniform(c,"f","amount",i),f=new CGL.Uniform(c,"f","twistAmount",1),p=new CGL.Uniform(c,"f","radius",o),g=new CGL.Uniform(c,"f","aspect",1),v=new CGL.Uniform(c,"f","centerX",s),b=new CGL.Uniform(c,"f","centerY",l);CGL.TextureEffect.setupBlending(t,c,a,i);n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(t,3))return;let e=m.currentTextureEffect.getCurrentSourceTexture();f.setValue(r.get()*(1/e.width));g.setValue(m.currentTextureEffect.aspectRatio);m.pushShader(c);m.currentTextureEffect.bind();m.setTexture(0,m.currentTextureEffect.getCurrentSourceTexture().tex);m.currentTextureEffect.finish();m.popShader();u.trigger()}};Ops.Gl.ImageCompose.Twirl_v4.prototype=new CABLES.Op;CABLES.OPS["6691bf7f-602d-4a24-b648-cab4b2a2c15e"]={f:Ops.Gl.ImageCompose.Twirl_v4,objName:"Ops.Gl.ImageCompose.Twirl_v4"};Ops.Math.Sine=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValue("value"),a=e.inValue("phase",0),i=e.inValue("frequency",1),r=e.inValue("amplitude",1),o=e.inValueBool("asine",false),s=e.outNumber("result");let l=Math.sin;i.onChange=r.onChange=a.onChange=n.onChange=function(){s.set(r.get()*l(n.get()*i.get()+a.get()))};o.onChange=function(){if(o.get())l=Math.asin;else l=Math.sin}};Ops.Math.Sine.prototype=new CABLES.Op;CABLES.OPS["d24da018-9f3d-428b-85c9-6ff14d77548b"]={f:Ops.Math.Sine,objName:"Ops.Math.Sine"};Ops.Gl.ImageCompose.PixelDisplacement_v4=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={pixeldisplace3_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D displaceTex;\nUNI float amountX;\nUNI float amountY;\nUNI float amount;\n\n#ifdef MAPPING_REPEAT\n    UNI vec2 repeat;\n#endif\n\n{{CGL.BLENDMODES3}}\n\nvec3 getOffset(vec3 offset)\n{\n    #ifdef ZERO_BLACK\n        return offset;\n    #endif\n\n    #ifdef ZERO_GREY\n        return offset*2.0-1.0;\n    #endif\n}\n\nfloat getOffset(float offset)\n{\n    #ifdef ZERO_BLACK\n        return offset;\n    #endif\n\n    #ifdef ZERO_GREY\n        return offset*2.0-1.0;\n    #endif\n}\n\nvoid main()\n{\n    #ifndef MAPPING_REPEAT\n        vec4 rgba=texture(displaceTex,texCoord);\n    #endif\n    #ifdef MAPPING_REPEAT\n        vec4 rgba=texture(displaceTex,texCoord*repeat);\n    #endif\n\n    vec3 offset=rgba.rgb*rgba.a;\n    float x,y;\n\n    #ifdef INPUT_REDGREEN\n        offset=getOffset(offset);\n        x=offset.r*amountX+texCoord.x;\n        y=offset.g*amountY+texCoord.y;\n    #endif\n    #ifdef INPUT_RED\n        offset=getOffset(offset);\n        x=offset.r*amountX+texCoord.x;\n        y=offset.r*amountY+texCoord.y;\n    #endif\n    #ifdef INPUT_GREEN\n        offset=getOffset(offset);\n        x=offset.g*amountX+texCoord.x;\n        y=offset.g*amountY+texCoord.y;\n    #endif\n    #ifdef INPUT_BLUE\n        offset=getOffset(offset);\n        x=offset.b*amountX+texCoord.x;\n        y=offset.b*amountY+texCoord.y;\n    #endif\n    #ifdef INPUT_LUMINANCE\n        float o=dot(vec3(0.2126,0.7152,0.0722), offset);\n        o=getOffset(o);\n        x=o*amountX+texCoord.x;\n        y=o*amountY+texCoord.y;\n    #endif\n    #ifdef WRAP_CLAMP\n        x=clamp(x,0.0,1.0);\n        y=clamp(y,0.0,1.0);\n    #endif\n    #ifdef WRAP_REPEAT\n        x=mod(x,1.0);\n        y=mod(y,1.0);\n    #endif\n    #ifdef WRAP_MIRROR\n        float mx=mod(x,2.0);\n        float my=mod(y,2.0);\n        x=abs((floor(mx)-fract(mx)));\n        y=abs((floor(my)-fract(my)));\n    #endif\n\n\n\n    vec4 col=texture(tex,vec2(x,y));\n    vec4 base=texture(tex,texCoord);\n\n    base.a=0.0;\n\n    outColor=cgl_blendPixel(base,col,amount);\n}\n\n\n//////"};const n=e.inTrigger("render"),a=e.inTexture("displaceTex"),i=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),r=e.inValueSlider("Amount",1),o=e.inValueSlider("amount X",.2),s=e.inValueSlider("amount Y",.2),l=e.inSwitch("Wrap",["Mirror","Clamp","Repeat"],"Mirror"),u=e.inValueSelect("Input",["Luminance","RedGreen","Red","Green","Blue"],"Luminance"),m=e.inSwitch("Zero Displace",["Grey","Black"],"Grey"),c=e.inSwitch("Pixel Mapping",["Stretch","Repeat"],"Stretch"),d=e.outTrigger("trigger");e.setPortGroup("Axis Displacement Strength",[o,s]);e.setPortGroup("Modes",[l,u]);e.toWorkPortsNeedToBeLinked(a);const h=e.patch.cgl,f=new CGL.Shader(h,e.name,e);f.setSource(f.getDefaultVertexShader(),t.pixeldisplace3_frag);const p=new CGL.Uniform(f,"t","tex",0),g=new CGL.Uniform(f,"t","displaceTex",1),v=new CGL.Uniform(f,"f","amountX",o),b=new CGL.Uniform(f,"f","amountY",s),x=new CGL.Uniform(f,"2f","repeat",1,1),_=new CGL.Uniform(f,"f","amount",r);c.onChange=m.onChange=l.onChange=u.onChange=O;O();CGL.TextureEffect.setupBlending(e,f,i,r);function O(){f.toggleDefine("MAPPING_REPEAT",c.get()=="Repeat");f.removeDefine("ZERO_BLACK");f.removeDefine("ZERO_GREY");f.define("ZERO_"+(m.get()+"").toUpperCase());f.removeDefine("WRAP_CLAMP");f.removeDefine("WRAP_REPEAT");f.removeDefine("WRAP_MIRROR");f.define("WRAP_"+(l.get()+"").toUpperCase());f.removeDefine("INPUT_LUMINANCE");f.removeDefine("INPUT_REDGREEN");f.removeDefine("INPUT_RED");f.define("INPUT_"+(u.get()+"").toUpperCase())}n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;if(a.get()){h.pushShader(f);h.currentTextureEffect.bind();x.setValue([h.currentTextureEffect.getCurrentSourceTexture().width/a.get().width,h.currentTextureEffect.getCurrentSourceTexture().height/a.get().height]);h.setTexture(0,h.currentTextureEffect.getCurrentSourceTexture().tex);if(a.get())h.setTexture(1,a.get().tex);h.currentTextureEffect.finish();h.popShader()}d.trigger()}};Ops.Gl.ImageCompose.PixelDisplacement_v4.prototype=new CABLES.Op;CABLES.OPS["c00f79f2-0505-4b4f-b0bf-10ef7875dd87"]={f:Ops.Gl.ImageCompose.PixelDisplacement_v4,objName:"Ops.Gl.ImageCompose.PixelDisplacement_v4"};Ops.Gl.ImageCompose.Noise.GlitchNoise_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={glitchnoise_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\n\n{{CGL.BLENDMODES3}}\n\nUNI float amount;\nUNI float time;\nUNI float frequency;\nUNI float strength;\nUNI float blockSizeA;\nUNI float blockSizeB;\nUNI float blockSizeC;\nUNI float blockSizeD;\nUNI float scrollX;\nUNI float scrollY;\n\nfloat rng2(vec2 seed)\n{\n    return fract(sin(dot(seed * floor(time * (frequency * 10.0)), vec2(127.1,311.7))) * 43758.5453123);//43758.5453123\n}\n\nfloat rng(float seed)\n{\n    return rng2(vec2(seed, 1.0));\n}\n\nvoid main( )\n{\n    //add scroll for x and y\n    vec2 scrollXY = vec2(scrollX,scrollY);\n    vec2 blockS = floor((texCoord + scrollXY ) * vec2(blockSizeA,blockSizeB));\n    vec2 blockL = floor((texCoord )  * vec2(blockSizeC,blockSizeD));\n\n    float r = rng2(texCoord);\n    vec3 noise = (vec3(r, 1. - r, r / 2. + 0.5) * 1.0 - 2.0) * 0.08;\n\n    float lineNoise = pow(rng2(blockS), 8.0) * pow(rng2(blockL), 3.0) - pow(rng(7.2341), 17.0) * 2.;\n\n    vec4 col1 = texture(tex, texCoord);\n    vec4 col2 = texture(tex, texCoord + vec2(lineNoise * (0.05 * strength)  * rng(5.0), 1));\n    vec4 col3 = texture(tex, texCoord - vec2(lineNoise * (0.05 * strength) * rng(31.0), 1));\n\n    float glitch = (lineNoise * strength * rng(5.0)) + (lineNoise * strength * rng(31.));\n    float glitch2 = lineNoise * strength * rng(31.);\n\n    //blend section\n    vec4 col=vec4(vec3(glitch),1.0);\n    //original texture\n    vec4 base=texture(tex,texCoord);\n\n    outColor=cgl_blendPixel(base,col,amount);\n\n}"};const n=e.inTrigger("render"),a=e.inValueSlider("Amount",1),i=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),r=CGL.TextureEffect.AddBlendAlphaMask(e),o=e.inValue("Seed",0),s=e.inValue("frequency",1),l=e.inValue("strength",8),u=e.inValue("Block size small x",24),m=e.inValue("Block size small y",9),c=e.inValue("Block size large x",8),d=e.inValue("Block size large y",4),h=e.inValue("Scroll X",0),f=e.inValue("Scroll Y",0),p=e.outTrigger("trigger");const g=0;const v=e.patch.cgl;const b=new CGL.Shader(v,e.name,e);b.setSource(b.getDefaultVertexShader(),t.glitchnoise_frag);const x=new CGL.Uniform(b,"t","tex",g),_=new CGL.Uniform(b,"f","amount",a),O=new CGL.Uniform(b,"f","time",o),A=new CGL.Uniform(b,"f","frequency",s),I=new CGL.Uniform(b,"f","strength",l),T=new CGL.Uniform(b,"f","blockSizeA",u),S=new CGL.Uniform(b,"f","blockSizeB",m),C=new CGL.Uniform(b,"f","blockSizeC",c),y=new CGL.Uniform(b,"f","blockSizeD",d),E=new CGL.Uniform(b,"f","scrollX",h),M=new CGL.Uniform(b,"f","scrollY",f);CGL.TextureEffect.setupBlending(e,b,i,a,r);n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;v.pushShader(b);v.currentTextureEffect.bind();v.setTexture(g,v.currentTextureEffect.getCurrentSourceTexture().tex);v.currentTextureEffect.finish();v.popShader();p.trigger()}};Ops.Gl.ImageCompose.Noise.GlitchNoise_v2.prototype=new CABLES.Op;CABLES.OPS["87de572e-644a-4613-b0f3-68b9ec74f489"]={f:Ops.Gl.ImageCompose.Noise.GlitchNoise_v2,objName:"Ops.Gl.ImageCompose.Noise.GlitchNoise_v2"};Ops.Math.Compare.LessThan=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValue("number1");const a=e.inValue("number2");const i=e.outBoolNum("result");e.setUiAttribs({mathTitle:true});n.onChange=r;a.onChange=r;r();function r(){i.set(n.get()<a.get())}};Ops.Math.Compare.LessThan.prototype=new CABLES.Op;CABLES.OPS["04fd113f-ade1-43fb-99fa-f8825f8814c0"]={f:Ops.Math.Compare.LessThan,objName:"Ops.Math.Compare.LessThan"};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 n=e.inTrigger("Render"),a=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),i=CGL.TextureEffect.AddBlendAlphaMask(e),r=e.inValueSlider("Amount",1),o=e.inValueSlider("Threshold",0),s=e.inValueBool("Animated",true),l=e.inValueBool("RGB",false),u=e.inValueBool("Normalize",false),m=e.inTexture("Multiply"),c=e.outTrigger("Next");const d=e.patch.cgl,h=new CGL.Shader(d,e.name),f=new CGL.Uniform(h,"f","amount",r),p=new CGL.Uniform(h,"f","time",1),g=new CGL.Uniform(h,"f","thresh",o),v=new CGL.Uniform(h,"t","tex",0),b=new CGL.Uniform(h,"t","texMul",1);h.setSource(h.getDefaultVertexShader(),t.noise_frag);CGL.TextureEffect.setupBlending(e,h,a,r,i);e.toWorkPortsNeedToBeLinked(n);m.onChange=u.onChange=l.onChange=function(){h.toggleDefine("HAS_MULMASK",m.get());h.toggleDefine("RGB",l.get());h.toggleDefine("NORMALIZE",u.get())};n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;if(s.get())p.setValue(e.patch.freeTimer.get()/1e3%100);else p.setValue(0);d.pushShader(h);d.setTexture(0,d.currentTextureEffect.getCurrentSourceTexture().tex);if(m.get())d.setTexture(1,m.get().tex);d.currentTextureEffect.bind();d.currentTextureEffect.finish();d.popShader();c.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.Gl.ImageCompose.Clarity=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={clarity_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float pX,pY;\n\nvec3 desaturate(vec4 color)\n{\n    vec3 c= vec3(dot(vec3(0.2126,0.7152,0.0722), color.rgb));\n    return c;\n}\n\nvoid main()\n{\n    vec4 col=texture(tex,texCoord);\n\n    vec3 gray=desaturate(col);\n    vec3 m=smoothstep(0.2,0.5,gray)*smoothstep(0.75,0.5,gray);\n    vec4 col2=vec4(1.0);\n\n    col2.rgb = ((col.rgb - 0.5) * max(( vec3(amount)*m+0.5)*2.0, 0.0))+0.5;\n\n    outColor= col2;\n}\n\n\n"};const n=e.inTrigger("Render");const a=e.outTrigger("Trigger");const i=e.inFloat("amount",.5);const r=e.patch.cgl;const o=new CGL.Shader(r,e.name,e);o.setSource(o.getDefaultVertexShader(),t.clarity_frag);const s=new CGL.Uniform(o,"t","tex",0);const l=new CGL.Uniform(o,"f","amount",i);n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;r.pushShader(o);r.currentTextureEffect.bind();r.setTexture(0,r.currentTextureEffect.getCurrentSourceTexture().tex);r.currentTextureEffect.finish();r.popShader();a.trigger()}};Ops.Gl.ImageCompose.Clarity.prototype=new CABLES.Op;CABLES.OPS["37d66c32-5594-4509-bba0-0ba2cbb706d8"]={f:Ops.Gl.ImageCompose.Clarity,objName:"Ops.Gl.ImageCompose.Clarity"};Ops.Gl.ImageCompose.Vibrance=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={vibrance_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\n\nconst vec4 lumcoeff = vec4(0.299,0.587,0.114, 0.);\n\nvoid main()\n{\n   vec4 col=vec4(1.0,0.0,0.0,1.0);\n   col=texture(tex,texCoord);\n\n   float luma = dot(col, lumcoeff);\n   vec4 mask = (col - vec4(luma));\n   mask = clamp(mask, 0.0, 1.0);\n   float lumaMask = dot(lumcoeff, mask);\n   lumaMask = 1.0 - lumaMask;\n   vec4 vibrance = mix(vec4(luma), col, 1.0 + amount * lumaMask);\n   outColor= vibrance;\n}"};const n=e.inTrigger("Render");const a=e.outTrigger("Trigger");const i=e.inValue("amount",2);const r=e.patch.cgl;const o=new CGL.Shader(r,e.name,e);o.setSource(o.getDefaultVertexShader(),t.vibrance_frag);const s=new CGL.Uniform(o,"t","tex",0);const l=new CGL.Uniform(o,"f","amount",i);n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;r.pushShader(o);r.currentTextureEffect.bind();r.setTexture(0,r.currentTextureEffect.getCurrentSourceTexture().tex);r.currentTextureEffect.finish();r.popShader();a.trigger()}};Ops.Gl.ImageCompose.Vibrance.prototype=new CABLES.Op;CABLES.OPS["9c71c980-e439-4397-9c2b-c2ae085eaed9"]={f:Ops.Gl.ImageCompose.Vibrance,objName:"Ops.Gl.ImageCompose.Vibrance"};Ops.Gl.MeshInstancer_v4=function(){CABLES.Op.apply(this,arguments);const p=this;const e=p.attachments={billboard_vert:"\n#ifdef BILLBOARDING\n\n    modelViewMatrix[0][0] = 1.0;\n    modelViewMatrix[0][1] = 0.0;\n    modelViewMatrix[0][2] = 0.0;\n\n    #ifndef BILLBOARDING_CYLINDRIC\n        modelViewMatrix[1][0] = 0.0;\n        modelViewMatrix[1][1] = 1.0;\n        modelViewMatrix[1][2] = 0.0;\n    #endif\n\n    modelViewMatrix[2][0] = 0.0;\n    modelViewMatrix[2][1] = 0.0;\n    modelViewMatrix[2][2] = 1.0;\n\n#endif",instancer_body_frag:"#define INSTANCING\n#ifdef COLORIZE_INSTANCES\n    #ifdef BLEND_MODE_MULTIPLY\n        col.rgb *= frag_instColor.rgb;\n        col.a *= frag_instColor.a;\n    #endif\n\n    #ifdef BLEND_MODE_ADD\n        col.rgb += frag_instColor.rgb;\n        col.a += frag_instColor.a;\n    #endif\n\n    #ifdef BLEND_MODE_NONE\n        col.rgb = frag_instColor.rgb;\n        col.a = frag_instColor.a;\n    #endif\n#endif\n",instancer_body_vert:"\n\n#ifdef HAS_TEXCOORDS\ntexCoord=(texCoord*instTexCoords.zw)+instTexCoords.xy;\n#endif\n\nmMatrix*=instMat;\npos.xyz*=MOD_scale;\n\n#ifdef HAS_COLORS\nfrag_instColor=instColor;\n#endif\n#ifndef HAS_COLORS\nfrag_instColor=vec4(1.0);\n#endif\n\n\nfrag_instIndex=instanceIndex;\n\n",instancer_head_frag:"IN vec4 frag_instColor;\n\n#ifdef WEBGL2\n    flat IN float frag_instIndex;\n#endif\n#ifdef WEBGL1\n    IN float frag_instIndex;\n#endif\n",instancer_head_vert:"\nIN vec4 instColor;\nIN mat4 instMat;\nIN vec4 instTexCoords;\nIN float instanceIndex;\nOUT mat4 instModelMat;\nOUT vec4 frag_instColor;\n\n#ifdef WEBGL2\n    flat OUT float frag_instIndex;\n#endif\n#ifdef WEBGL1\n    OUT float frag_instIndex;\n#endif\n\n\n\n#define INSTANCING\n\n"};const t=p.inTrigger("exe"),n=p.inObject("geom",null,"geometry"),a=p.inValue("Scale",1),i=p.inValueBool("Limit Instances",false),r=p.inValueInt("Limit",100),g=p.inArray("positions",3),v=p.inArray("Scale Array",3),b=p.inArray("Rotations",3),x=p.inSwitch("Rotation Type",["Euler","Quaternions","Normals"],"Euler"),o=p.inSwitch("Billboarding",["Off","Spherical","Cylindrical"],"Off"),s=p.inSwitch("Material blend mode",["Multiply","Add","Normal"],"Multiply"),_=p.inArray("Colors",4),O=p.inArray("TexCoords",4),l=p.outTrigger("Trigger Out"),u=p.outNumber("Num");p.setPortGroup("Limit Number of Instances",[r,i]);p.setPortGroup("Parameters",[v,b,g,x]);p.toWorkPortsNeedToBeLinked(n);p.toWorkPortsNeedToBeLinked(t);n.ignoreValueSerialize=true;const m=p.patch.cgl;const A=mat4.create();let I=new Float32Array(1),T=new Float32Array(1),S=new Float32Array(1),C=null,y=true,E=0,M=true,P=true,N=true;const j=new CGL.ShaderModifier(m,p.name,{opId:p.id});j.addModule({name:"MODULE_VERTEX_POSITION",title:p.name,priority:-2,srcHeadVert:e.instancer_head_vert,srcBodyVert:e.instancer_body_vert});j.addModule({name:"MODULE_VERTEX_MODELVIEW",title:p.name+"_billboard",srcBodyVert:e.billboard_vert});j.addModule({name:"MODULE_COLOR",priority:-2,title:p.name,srcHeadFrag:e.instancer_head_frag,srcBodyFrag:e.instancer_body_frag});j.addUniformVert("f","MOD_scale",a);let L=true;s.onChange=()=>{L=true};i.onChange=f;t.onTriggered=R;t.onLinkChanged=function(){if(!t.isLinked())d()};f();b.onChange=v.onChange=g.onChange=x.onChange=function(){N=true;y=true};o.onChange=O.onChange=function(){P=true;y=true;L=true};_.onChange=function(){M=true;y=true;L=true};function c(){M=true,N=true;y=true}function w(){j.toggleDefine("BILLBOARDING",o.get()!="Off");j.toggleDefine("BILLBOARDING_CYLINDRIC",o.get()=="Cylindrical");j.toggleDefine("COLORIZE_INSTANCES",_.get());j.toggleDefine("TEXCOORDS_INSTANCES",O.get());j.toggleDefine("BLEND_MODE_MULTIPLY",s.get()==="Multiply");j.toggleDefine("BLEND_MODE_ADD",s.get()==="Add");j.toggleDefine("BLEND_MODE_NONE",s.get()==="Normal");L=false}n.onChange=function(){if(C)C.dispose();if(!n.get()){C=null;return}C=new CGL.Mesh(m,n.get());c()};function d(){}function h(){if(!C)return;let e=g.get();if(!e)e=[0,0,0];E=Math.floor(e.length/3);if(L)w();const n=_.get();const a=O.get();const i=v.get();const r=x.get()=="Quaternions";const o=x.get()=="Euler";const s=x.get()=="Normals";let t=3;if(r)t=4;b.setUiAttribs({stride:t});if(i&&i.length!=e.length)p.setUiError("lengthScales","Scales array has wrong length");else p.setUiError("lengthScales",null);if(I.length!=E*16)I=new Float32Array(E*16);if(T.length!=E*4){M=true;T=new Float32Array(E*4)}if(S.length!=E*4){P=true;S=new Float32Array(E*4)}const l=b.get();for(let t=0;t<E;t++){mat4.identity(A);mat4.translate(A,A,[e[t*3],e[t*3+1],e[t*3+2]]);if(l){if(r){const u=mat4.create();const m=[l[t*4+0],l[t*4+1],l[t*4+2],l[t*4+3]];quat.normalize(m,m);mat4.fromQuat(u,m);mat4.mul(A,A,u)}else if(s){const c=[l[t*3+0],l[t*3+1],l[t*3+2]];const d=[1,0,0];const h=vec3.create();vec3.cross(h,d,c);vec3.normalize(h,h);const f=Math.acos(vec3.dot(d,c));const m=quat.create();quat.setAxisAngle(m,h,f);quat.normalize(m,m);const u=mat4.create();mat4.fromQuat(u,m);mat4.mul(A,A,u)}if(o){mat4.rotateX(A,A,l[t*3+0]*CGL.DEG2RAD);mat4.rotateY(A,A,l[t*3+1]*CGL.DEG2RAD);mat4.rotateZ(A,A,l[t*3+2]*CGL.DEG2RAD)}}if(M&&n){T[t*4+0]=n[t*4+0];T[t*4+1]=n[t*4+1];T[t*4+2]=n[t*4+2];T[t*4+3]=n[t*4+3]}if(P&&a){S[t*4+0]=a[t*4+0];S[t*4+1]=a[t*4+1];S[t*4+2]=a[t*4+2];S[t*4+3]=a[t*4+3]}if(i&&i.length>t)mat4.scale(A,A,[i[t*3],i[t*3+1],i[t*3+2]]);else mat4.scale(A,A,[1,1,1]);for(let e=0;e<16;e++)I[t*16+e]=A[e]}C.setNumInstances(E);if(N)C.addAttribute("instMat",I,16);if(M)C.addAttribute("instColor",T,4,{instanced:true});if(P)C.addAttribute("instTexCoords",S,4,{instanced:true});j.toggleDefine("HAS_TEXCOORDS",a);j.toggleDefine("HAS_COLORS",n);M=false;y=false}function f(){r.setUiAttribs({greyout:!i.get()})}function R(){if(!C)return;if(y)h();j.bind();if(i.get())C.setNumInstances(Math.min(E,r.get()));else C.setNumInstances(E);u.set(C.numInstances);if(C.numInstances>0)C.render(m.getShader());l.trigger();j.unbind()}};Ops.Gl.MeshInstancer_v4.prototype=new CABLES.Op;CABLES.OPS["cb58f461-a0bd-4159-a3cb-5e396198b4e9"]={f:Ops.Gl.MeshInstancer_v4,objName:"Ops.Gl.MeshInstancer_v4"};Ops.Gl.TextureToRandomPoints=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.patch.cgl,a=e.inTriggerButton("update"),d=e.inValueInt("Num Points",2e3),h=e.inValueFloat("Seed",1),f=e.inSwitch("Z Position",["None","Red","Green","Blue","Alpha"],"Red"),p=e.inValueFloat("Z Multiply",1),g=e.inObject("texture"),v=e.outTrigger("trigger"),b=e.outArray("Points"),x=e.outNumber("NumPoints");let _=null,O=null,A=false;e.toWorkPortsNeedToBeLinked(g,b);g.onChange=function(){A=true};let I=e.patch.cgl.gl.UNSIGNED_BYTE;let T=[];a.onTriggered=i;const S=4;function i(){let a=g.get(),e=n.gl;if(!a)return;if(!_)_=e.createFramebuffer();e.bindFramebuffer(e.FRAMEBUFFER,_);if(A){e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,a.tex,0);O=new Uint8Array(a.width*a.height*S);A=false}e.bindFramebuffer(e.FRAMEBUFFER,_);e.readPixels(0,0,a.width,a.height,e.RGBA,I,O);e.bindFramebuffer(e.FRAMEBUFFER,null);let i=d.get();let t=O.length;if(i*3!=T.length)T.length=i*3;Math.randomSeed=h.get();let r=1/a.width;let o=1/a.height;let s=r*a.width/2;let l=o*a.height/2;let u=0;let m=0;let c=0;if(f.get()=="Green")c=1;else if(f.get()=="Blue")c=2;else if(f.get()=="Alpha")c=3;else if(f.get()=="None")c=4;while(u<i*3){m++;if(m>i*3*100)return;let e=Math.floor(Math.seededRandom()*a.width);let t=Math.floor(Math.seededRandom()*a.height);let n=O[(e+t*a.width)*S+c];if(n>10){T[u++]=e*r-s;T[u++]=t*o-l;if(c<4)T[u++]=n/255*p.get();else T[u++]=0}}x.set(u/3);b.set(null);b.set(T);e.bindFramebuffer(e.FRAMEBUFFER,null);v.trigger()}};Ops.Gl.TextureToRandomPoints.prototype=new CABLES.Op;CABLES.OPS["ff757f51-fbb0-4728-b158-644094cd160e"]={f:Ops.Gl.TextureToRandomPoints,objName:"Ops.Gl.TextureToRandomPoints"};Ops.Array.ArrayUnpack3=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inArray("Array in xyz"),a=e.outArray("Array 1 out"),i=e.outArray("Array 2 out"),r=e.outArray("Array 3 out"),o=e.outNumber("Array lengths");let s=false;const l=[];const u=[];const m=[];n.onChange=c;function c(){let t=n.get();if(!t){a.set(null);return}if(t.length%3!==0){if(!s){e.uiAttr({error:"Arrays length not divisible by 3 !"});o.set(0);s=true}return}if(s){s=false;e.uiAttr({error:null})}l.length=Math.floor(t.length/3);u.length=Math.floor(t.length/3);m.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];m[e]=t[e*3+2]}a.setRef(l);i.setRef(u);r.setRef(m);o.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.Array.Array_v3=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const a=t.inValueInt("Array length",10),n=t.inSwitch("Mode select",["Number","1,2,3,4","0-1"],"Number"),i=t.inValueFloat("Default Value"),r=t.inBool("Reverse",false),o=t.outArray("Array"),s=t.outNumber("Array length out");let l=[];let u=0;const m=0;const c=1;const d=2;n.onChange=h;r.onChange=i.onChange=a.onChange=f;h();f();function h(){let e=n.get();if(e==="Number")u=m;else if(e==="1,2,3,4")u=c;else if(e==="0-1")u=d;i.setUiAttribs({greyout:u!==m});t.setUiAttrib({extendTitle:n.get()});f()}function f(){l.length=0;let e=a.get();let t=i.get();let n;if(u===m){for(n=0;n<e;n++){l[n]=t}}else if(u===c){for(n=0;n<e;n++){l[n]=n}}else if(u===d){if(e>1){for(n=0;n<e;n++){l[n]=n/(e-1)}}else{l=[0]}}if(r.get())l=l.reverse();o.setRef(l);s.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.ArrayPack3=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTrigger("Trigger in"),r=e.inArray("Array 1"),o=e.inArray("Array 2"),s=e.inArray("Array 3"),l=e.outTrigger("Trigger out"),u=e.outArray("Array out",3),m=e.outNumber("Num Points"),c=e.outNumber("Array length");let a=false;let d=[];let h=[];let f=true;n.onTriggered=p;r.onChange=o.onChange=s.onChange=i;function i(){f=true}function p(){let n=r.get();let a=o.get();let i=s.get();if(!n&&!a&&!i){u.set(null);m.set(0);return}if(f){let t=0;if(!n||!a||!i){if(n)t=n.length;else if(a)t=a.length;else if(i)t=i.length;if(h.length!=t)for(let e=0;e<t;e++)h[e]=0;if(!n)n=h;if(!a)a=h;if(!i)i=h}if(n.length!==a.length||a.length!==i.length){e.setUiError("arraylen","Arrays do not have the same length !");return}e.setUiError("arraylen",null);d.length=n.length;for(let e=0;e<n.length;e++){d[e*3+0]=n[e];d[e*3+1]=a[e];d[e*3+2]=i[e]}f=false;u.setRef(d);m.set(d.length/3);c.set(d.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.Gl.TextureToArray=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const r=e.patch.cgl,n=e.inTrigger("update"),o=e.inObject("texture"),s=e.inSwitch("Normalize",["0-255","0-1","-1-1"],"0-255"),l=e.outTrigger("trigger"),u=e.outArray("Colors"),m=e.outBoolNum("Floating Point");let c=null,d=null,h=false;o.onChange=function(){h=true};e.toWorkPortsNeedToBeLinked(o,u);let f=false;let p=e.patch.cgl.gl.UNSIGNED_BYTE;let g=null;let v=false;let b=0;let x=0;n.onTriggered=function(){const e=o.get(),t=r.gl;if(!e)return;if(!c)c=t.createFramebuffer();t.bindFramebuffer(t.FRAMEBUFFER,c);let n=t.RGBA;let a=4;if(h){t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,e.tex,0);f=e.textureType==CGL.Texture.TYPE_FLOAT;if(f)p=t.FLOAT;else p=t.UNSIGNED_BYTE;m.set(f);if(v!=f||b!=e.width||x!=e.height){const i=e.width*e.height*a;if(f)d=new Float32Array(i);else d=new Uint8Array(i);v=f;b=e.width;x=e.height}h=false}t.bindFramebuffer(t.FRAMEBUFFER,c);t.readPixels(0,0,e.width,e.height,n,p,d);if(s.get()=="0-1"){if(!g||g.length!=d.length)g=new Float32Array(d.length);for(let e=0;e<d.length;e++){g[e]=d[e]/255}}if(s.get()=="-1-1"){if(!g||g.length!=d.length)g=new Float32Array(d.length);for(let e=0;e<d.length;e++){g[e]=(d[e]-128)*2/255}}t.bindFramebuffer(t.FRAMEBUFFER,null);u.set(null);u.set(g||d);t.bindFramebuffer(t.FRAMEBUFFER,null);l.trigger()}};Ops.Gl.TextureToArray.prototype=new CABLES.Op;CABLES.OPS["51dbc04e-f970-44ca-9cb0-39596ac4d212"]={f:Ops.Gl.TextureToArray,objName:"Ops.Gl.TextureToArray"};Ops.Array.ArrayUnpack4=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inArray("Array in xyzw"),a=e.outArray("Array 1 out"),i=e.outArray("Array 2 out"),r=e.outArray("Array 3 out"),o=e.outArray("Array 4 out"),s=e.outNumber("Array lengths");let l=false;const u=[];const m=[];const c=[];const d=[];n.onChange=h;function h(){let t=n.get();if(!t){a.set(null);return}if(t.length%4!==0){if(!l){e.uiAttr({error:"Arrays length not divisible by 4 !"});s.set(0);l=true}return}if(l){l=false;e.uiAttr({error:null})}u.length=Math.floor(t.length/4);m.length=Math.floor(t.length/4);c.length=Math.floor(t.length/4);d.length=Math.floor(t.length/4);for(let e=0;e<t.length/4;e++){u[e]=t[e*4];m[e]=t[e*4+1];c[e]=t[e*4+2];d[e]=t[e*4+3]}a.setRef(u);i.setRef(m);r.setRef(c);o.setRef(d);s.set(u.length)}};Ops.Array.ArrayUnpack4.prototype=new CABLES.Op;CABLES.OPS["8d2127d8-f3e4-4036-8cd8-75c6a404b582"]={f:Ops.Array.ArrayUnpack4,objName:"Ops.Array.ArrayUnpack4"};Ops.Array.ArrayMultiply=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const a=e.inArray("In"),i=e.inValue("Value",1),r=e.outArray("Result");let o=[];r.set(o);a.onChange=i.onChange=a.onChange=function(){let t=a.get();if(!t)return;let n=i.get();if(o.length!=t.length)o.length=t.length;for(let e=0;e<t.length;e++)o[e]=t[e]*n;r.setRef(o)};a.onLinkChanged=()=>{if(a)a.copyLinkedUiAttrib("stride",r)}};Ops.Array.ArrayMultiply.prototype=new CABLES.Op;CABLES.OPS["a01c344b-4129-4b01-9c8f-36cefe86d7cc"]={f:Ops.Array.ArrayMultiply,objName:"Ops.Array.ArrayMultiply"};Ops.Gl.ShaderEffects.InstancedPerlinPosition_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={perlin_instposition_vert:'\nfloat MOD_Interpolation_C2( float x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }   //  6x^5-15x^4+10x^3\t( Quintic Curve.  As used by Perlin in Improved Noise.  http://mrl.nyu.edu/~perlin/paper445.pdf )\nvec2 MOD_Interpolation_C2( vec2 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec3 MOD_Interpolation_C2( vec3 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 MOD_Interpolation_C2( vec4 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 MOD_Interpolation_C2_InterpAndDeriv( vec2 x ) { return x.xyxy * x.xyxy * ( x.xyxy * ( x.xyxy * ( x.xyxy * vec2( 6.0, 0.0 ).xxyy + vec2( -15.0, 30.0 ).xxyy ) + vec2( 10.0, -60.0 ).xxyy ) + vec2( 0.0, 30.0 ).xxyy ); }\nvec3 MOD_Interpolation_C2_Deriv( vec3 x ) { return x * x * (x * (x * 30.0 - 60.0) + 30.0); }\n\n\nvoid MOD_FAST32_hash_3D( \tvec3 gridcell,\n                        out vec4 lowz_hash_0,\n                        out vec4 lowz_hash_1,\n                        out vec4 lowz_hash_2,\n                        out vec4 highz_hash_0,\n                        out vec4 highz_hash_1,\n                        out vec4 highz_hash_2\t)\t\t//\tgenerates 3 random numbers for each of the 8 cell corners\n{\n    //    gridcell is assumed to be an integer coordinate\n\n    //\tTODO: \tthese constants need tweaked to find the best possible noise.\n    //\t\t\tprobably requires some kind of brute force computational searching or something....\n    const vec2 OFFSET = vec2( 50.0, 161.0 );\n    const float DOMAIN = 69.0;\n    const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );\n    const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );\n\n    //\ttruncate the domain\n    gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n    vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n    //\tcalculate the noise\n    vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n    P *= P;\n    P = P.xzxz * P.yyww;\n    vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );\n    vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );\n    lowz_hash_0 = fract( P * lowz_mod.xxxx );\n    highz_hash_0 = fract( P * highz_mod.xxxx );\n    lowz_hash_1 = fract( P * lowz_mod.yyyy );\n    highz_hash_1 = fract( P * highz_mod.yyyy );\n    lowz_hash_2 = fract( P * lowz_mod.zzzz );\n    highz_hash_2 = fract( P * highz_mod.zzzz );\n}\n\n//\n//\tPerlin Noise 3D  ( gradient noise )\n//\tReturn value range of -1.0->1.0\n//\thttp://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg\n//\nfloat MOD_Perlin3D( vec3 P )\n{\n    //\testablish our grid cell and unit position\n    vec3 Pi = floor(P);\n    vec3 Pf = P - Pi;\n    vec3 Pf_min1 = Pf - 1.0;\n\n#if 1\n    //\n    //\tclassic noise.\n    //\trequires 3 random values per point.  with an efficent hash function will run faster than improved noise\n    //\n\n    //\tcalculate the hash.\n    //\t( various hashing methods listed in order of speed )\n    vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;\n    MOD_FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n    //SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n\n    //\tcalculate the gradients\n    vec4 grad_x0 = hashx0 - 0.49999;\n    vec4 grad_y0 = hashy0 - 0.49999;\n    vec4 grad_z0 = hashz0 - 0.49999;\n    vec4 grad_x1 = hashx1 - 0.49999;\n    vec4 grad_y1 = hashy1 - 0.49999;\n    vec4 grad_z1 = hashz1 - 0.49999;\n    vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );\n    vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );\n\n#if 1\n    //\tClassic Perlin Interpolation\n    vec3 blend = MOD_Interpolation_C2( Pf );\n    vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n    vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n    float final = dot( res0, blend2.zxzx * blend2.wwyy );\n    final *= 1.1547005383792515290182975610039;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range    *= 1.0/sqrt(0.75)\n    return final;\n#else\n    //\tClassic Perlin Surflet\n    //\thttp://briansharpe.wordpress.com/2012/03/09/modifications-to-classic-perlin-noise/\n    Pf *= Pf;\n    Pf_min1 *= Pf_min1;\n    vec4 vecs_len_sq = vec4( Pf.x, Pf_min1.x, Pf.x, Pf_min1.x ) + vec4( Pf.yy, Pf_min1.yy );\n    float final = dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf.zzzz ) ), grad_results_0 ) + dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf_min1.zzzz ) ), grad_results_1 );\n    final *= 2.3703703703703703703703703703704;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range    *= 1.0/cube(0.75)\n    return final;\n#endif\n\n#else\n    //\n    //\timproved noise.\n    //\trequires 1 random value per point.  Will run faster than classic noise if a slow hashing function is used\n    //\n\n    //\tcalculate the hash.\n    //\t( various hashing methods listed in order of speed )\n    vec4 hash_lowz, hash_highz;\n    MOD_FAST32_hash_3D( Pi, hash_lowz, hash_highz );\n    //BBS_hash_3D( Pi, hash_lowz, hash_highz );\n    //SGPP_hash_3D( Pi, hash_lowz, hash_highz );\n\n    //\n    //\t"improved" noise using 8 corner gradients.  Faster than the 12 mid-edge point method.\n    //\tKen mentions using diagonals like this can cause "clumping", but we\'ll live with that.\n    //\t[1,1,1]  [-1,1,1]  [1,-1,1]  [-1,-1,1]\n    //\t[1,1,-1] [-1,1,-1] [1,-1,-1] [-1,-1,-1]\n    //\n    hash_lowz -= 0.5;\n    vec4 grad_results_0_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_lowz );\n    hash_lowz = abs( hash_lowz ) - 0.25;\n    vec4 grad_results_0_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_lowz );\n    vec4 grad_results_0_2 = Pf.zzzz * sign( abs( hash_lowz ) - 0.125 );\n    vec4 grad_results_0 = grad_results_0_0 + grad_results_0_1 + grad_results_0_2;\n\n    hash_highz -= 0.5;\n    vec4 grad_results_1_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_highz );\n    hash_highz = abs( hash_highz ) - 0.25;\n    vec4 grad_results_1_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_highz );\n    vec4 grad_results_1_2 = Pf_min1.zzzz * sign( abs( hash_highz ) - 0.125 );\n    vec4 grad_results_1 = grad_results_1_0 + grad_results_1_1 + grad_results_1_2;\n\n    //\tblend the gradients and return\n    vec3 blend = MOD_Interpolation_C2( Pf );\n    vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n    vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n    return dot( res0, blend2.zxzx * blend2.wwyy ) * (2.0 / 3.0);\t//\t(optionally) mult by (2.0/3.0) to scale to a strict -1.0->1.0 range\n#endif\n}\n\nvec4 MOD_deform(mat4 mMatrix,mat4 instMat,vec4 pos)\n{\n\n    vec3 ppos=vec3(mMatrix[3][0]+instMat[3][0]*MOD_scale+MOD_scrollx,mMatrix[3][1]+instMat[3][1]*MOD_scale+MOD_scrolly,mMatrix[3][2]+instMat[3][2]*MOD_scale+MOD_scrollz);\n    float p=MOD_Perlin3D(ppos)*MOD_strength;\n\n\n    #ifdef MOD_METH_TRANSLATE\n        pos.x+=p*MOD_mulAxis.x;\n        pos.y+=p*MOD_mulAxis.y;\n        pos.z+=p*MOD_mulAxis.z;\n    #endif\n    #ifdef MOD_METH_SCALE\n        p=clamp(p,0.0,99999.0);\n        pos.x*=p*MOD_mulAxis.x+MOD_minScale;\n        pos.y*=p*MOD_mulAxis.y+MOD_minScale;\n        pos.z*=p*MOD_mulAxis.z+MOD_minScale;\n    #endif\n\n    return pos;\n}\n\n'};const n=e.inTrigger("Render"),a=e.outTrigger("Next"),i=e.inValue("Strength",1),r=e.inValue("Scroll X"),o=e.inValue("Scroll Y"),s=e.inValue("Scroll Z"),l=e.inValue("Scale",1),u=e.inSwitch("Method",["Translate","Scale"],"Translate"),m=e.inValue("Mul X",1),c=e.inValue("Mul Y",1),d=e.inValue("Mul Z",1),h=e.inValue("Min Scale",0),f=e.inValueBool("WorldSpace");const p=e.patch.cgl;let g="".endl()+"#ifdef INSTANCING".endl()+"   pos=MOD_deform(mMatrix,instMat,pos);".endl()+"#endif".endl()+"#ifndef INSTANCING".endl()+"   pos=MOD_deform(mMatrix,mMatrix,pos);".endl()+"#endif".endl();const v=new CGL.ShaderModifier(p,e.name,{opId:e.id});v.addModule({name:"MODULE_VERTEX_POSITION",srcHeadVert:t.perlin_instposition_vert,srcBodyVert:g});v.addUniform("f","MOD_strength",i);v.addUniform("f","MOD_scrollx",r);v.addUniform("f","MOD_scrolly",o);v.addUniform("f","MOD_scrollz",s);v.addUniform("f","MOD_scale",l);v.addUniform("f","MOD_minScale",h);v.addUniform("3f","MOD_mulAxis",m,c,d);u.onChange=f.onChange=b;b();function b(){v.toggleDefine("MOD_WORLDSPACE",f.get());v.toggleDefine("MOD_METH_TRANSLATE",u.get()=="Translate");v.toggleDefine("MOD_METH_SCALE",u.get()=="Scale")}n.onTriggered=function(){v.bind();a.trigger();v.unbind()}};Ops.Gl.ShaderEffects.InstancedPerlinPosition_v2.prototype=new CABLES.Op;CABLES.OPS["716a9004-cbb8-4032-9f29-2b2f8c8973ba"]={f:Ops.Gl.ShaderEffects.InstancedPerlinPosition_v2,objName:"Ops.Gl.ShaderEffects.InstancedPerlinPosition_v2"};Ops.Gl.ImageCompose.ColorMap_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={colormap_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D gradient;\nUNI float pos;\nUNI float amount;\nUNI float vmin;\nUNI float vmax;\n\n{{CGL.BLENDMODES3}}\n\n\nfloat lumi(vec3 color)\n{\n   return vec3(dot(vec3(0.2126,0.7152,0.0722), color)).r;\n}\n\nvoid main()\n{\n    vec4 base=texture(tex,texCoord);\n    float a=base.a;\n\n    base=clamp(base,vmin,vmax);\n\n    #ifdef METH_LUMI\n        vec4 color=texture(gradient,vec2(lumi(base.rgb),pos));\n    #endif\n\n    #ifdef METH_CHANNELS\n        vec4 color=vec4(1.0);\n        color.r=texture(gradient,vec2(base.r,pos)).r;\n        color.g=texture(gradient,vec2(base.g,pos)).g;\n        color.b=texture(gradient,vec2(base.b,pos)).b;\n    #endif\n\n    base.a=color.a=a;\n\n\n    outColor=cgl_blendPixel(base,color,amount);\n\n}\n"};let n=e.inTrigger("render");let a=e.outTrigger("trigger");const i=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal");const r=e.inValueSlider("Amount",1);let o=e.inTexture("Gradient");let s=e.inSwitch("Method",["Luminance","Channels"],"Luminance");let l=e.inFloatSlider("Min",0);let u=e.inFloatSlider("Max",1);let m=e.inValueSlider("Position",.5);e.setPortGroup("Vertical Position",[l,u,m]);let c=e.patch.cgl;let d=new CGL.Shader(c,e.name,e);d.define("METH_LUMI");d.setSource(d.getDefaultVertexShader(),t.colormap_frag);let h=new CGL.Uniform(d,"t","tex",0);let f=new CGL.Uniform(d,"t","gradient",1);let p=new CGL.Uniform(d,"f","pos",m);let g=new CGL.Uniform(d,"f","vmin",l);let v=new CGL.Uniform(d,"f","vmax",u);let b=new CGL.Uniform(d,"f","amount",r);CGL.TextureEffect.setupBlending(e,d,i,r);s.onChange=()=>{d.toggleDefine("METH_LUMI",s.get()=="Luminance");d.toggleDefine("METH_CHANNELS",s.get()=="Channels")};n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;if(!o.get())return;c.pushShader(d);c.currentTextureEffect.bind();c.setTexture(0,c.currentTextureEffect.getCurrentSourceTexture().tex);c.setTexture(1,o.get().tex);c.currentTextureEffect.finish();c.popShader();a.trigger()}};Ops.Gl.ImageCompose.ColorMap_v2.prototype=new CABLES.Op;CABLES.OPS["440c1675-122d-411f-b848-16c60b677120"]={f:Ops.Gl.ImageCompose.ColorMap_v2,objName:"Ops.Gl.ImageCompose.ColorMap_v2"};Ops.Gl.GradientTexture=function(){CABLES.Op.apply(this,arguments);const n=this;const e=n.attachments={};const y=n.inGradient("Gradient"),E=n.inValueSelect("Direction",["X","XX","Y","YY","XY","YX","Radial"],"X"),M=n.inValueBool("Smoothstep",false),P=n.inBool("Step",false),N=n.inBool("Flip",false),j=n.inBool("sRGB",false),L=n.inBool("Oklab",false),w=n.inValueInt("Size",256),R=n.inSwitch("filter",["nearest","linear","mipmap"],"linear"),k=n.inValueSelect("wrap",["clamp to edge","repeat","mirrored repeat"],"clamp to edge"),p=n.inFloatSlider("Dither",0),a=n.inArray("Gradient Array"),t=n.inTriggerButton("Randomize Colors"),B=n.outTexture("Texture"),D=n.outArray("Colors",null,3),G=n.outArray("Colors Pos",null,1);const U=n.patch.cgl;let i=null;y.setUiAttribs({editShortcut:true});const r=[221,125,40,94,163,50,214,174,69,229,135,79,25,92,217,129,103,155,16,237,168,75,212,126,203,157,104,223,50,96,115,189,0,104,199,16,185,242,83,26,123,95,191,175,247,159,32,170,0,88,203,133,106,46,227,14,35,246,66,20,240,205,36,159,74,252,148,231,132,117,6,145,254,39,222,5,111,46,67,197,228,116,181,66,25,245,98,139,172,89,190,149,127,177,64,138,210,169,58,28,70,100,206,188,164,107,60,150,203,126,235,142,56,249,38,222,148,178,195,56,115,230,45,108,7,84,234,21,44,90,110,216,178,37,226,53,14,77,212,31,86,180,100,23,82,14,162,93,122,6,81,156,24,209,75,255,163,218,196,121,237,187,9,152,247,136,158,91,128,232,169,137,251,10,216,154,188,131,211,71,200,34,236,216,129,13,179,136,32,54,99,146,33,131,202,49,84,18,64,197,245,114,21,193,52,74,118,44,243,105,173,50,252,110,63,166,41,102,199,62,117,184,15,77,250,162,69,120,231,107,213,2,177,43,67,102,159,238,171,206,64,29,233,10,151,135,185,87,247,147,223,91,241,152,225,175,3,102,220,25,191,170,36,143,81,152,209,224,133,35,93,2,145,87,124,193,97,22,228,1,120,51,171,8,26,210,108,48,205,59,179,92,147,253,124,99,237,186,11,120,19,181,229,112,198,160,220,76,42,210,160,71,202,31,78,190,130,67,86,138,115,156,243,14,46,74,57,219,28,51,90,250,59,81,140,47,255,17,58,181,243,114,56,178,239,139,228,156,251,40,167,232,28,38,82,136,206,161,9,196,106,139,167,204,150,195,218,70,172,35,132,103,146,27,89,128,16,107,96,57,119,201,15,187,239,126,194,225,112,182,234,131,174,240,72,39,109,29,8,100,122,207,231,4,166,224,198,153,217,44,183,212,4,93,143,72,99,172,64,0,97,34,85,66,20,208,3,125,243,164,186,235,156,82,191,67,248,49,80,10,253,68,23,162,244,179,49,215,24,151,246,51,214,153,251,118,45,157,98,224,53,88,134,62,42,23,116,94,140,33,121,188,169,141,113,76,33,131,227,110,11,202,78,122,168,18,141,194,221,80,187,142,177,210,18,249,144,221,180,12,201,215,106,60,91,226,200,236,150,85,61,164,185,133,42,229,187,73,55,101,27,235,59,12,35,75,113,199,101,163,237,57,152,174,234,134,1,37,53,123,193,6,208,253,34,91,145,104,8,240,211,175,129,164,109,253,123,230,171,6,50,79,27,127,73,43,19,246,161,211,103,17,172,96,46,117,70,241,219,27,162,115,88,38,4,148,204,92,189,154,63,130,217,188,111,254,208,101,86,191,144,75,180,249,65,137,233,157,18,171,192,49,66,201,137,246,218,51,71,15,43,214,29,95,239,38,139,165,7,225,124,30,59,112,221,154,28,197,217,106,58,85,209,128,232,151,15,79,182,120,238,168,134,81,248,146,173,16,88,195,65,150,183,205,242,11,41,89,126,80,8,183,121,141,3,98,180,31,108,58,196,97,24,222,107,198,2,116,70,207,52,230,22,109,47,80,165,132,199,235,170,52,148,247,165,23,242,74,45,254,170,226,155,36,142,179,60,158,48,182,223,154,124,98,178,250,140,5,231,96,68,19,116,204,32,227,43,200,113,161,213,122,87,0,130,248,77,13,241,92,229,30,102,13,244,77,160,33,209,119,55,176,143,190,255,103,71,93,186,62,223,145,12,189,68,202,47,211,114,192,41,127,203,141,65,189,40,135,198,61,89,222,158,24,216,45,1,157,213,130,239,83,104,26,55,134,238,29,159,95,63,167,149,7,78,255,119,166,212,1,233,19,105,186,37,244,110,86,135,56,173,11,151,36,176,196,230,94,149,109,184,226,20,236,215,105,175,22,219,52,87,111,174,128,248,149,78,125,63,184,227,242,118,22,220,138,252,119,76,168,39,250,10,136,84,123,54,69,194,37,95,147,241,73,153,48,68,7,194,17,207,161,31,76,201,90,166,69,4,48,215,21,204,57,73,176,200,30,249,155,133,233,163,9,197,32,183,220,205,137,232,167,94,144,9,105,181,44,111,207,99,132,155,182,85,127,219,147,42,97,184,5,83,208,108,61,125,228,21,100,39,90,114,53,218,41,252,129,61,234,143,30,192,245,12,112,236,101,2,244,113,165,225,118,47,20,176,251,142,84,117,160,254,177,26,238,121,72,193,213,153,13,55,173,79,224,65,140,34,195,158,54,17,206,62,144,240,190,72,40,214,54,192,5,146,60,82,185,3,138,169,25,83,245];const g=32;p.onChange=k.onChange=R.onChange=P.onChange=N.onChange=j.onChange=L.onChange=w.onChange=y.onChange=M.onChange=E.onChange=a.onChange=o;y.set('{"keys" : [{"pos":0,"r":0,"g":0,"b":0},{"pos":1,"r":1,"g":1,"b":1}]}');n.onLoaded=o;t.onTriggered=()=>{const e=l();if(e){e.forEach(e=>{e.r=Math.random();e.g=Math.random();e.b=Math.random()});const t=JSON.stringify({keys:e});y.set(t)}};function F(e,t,n){let a=.4122214708*e+.5363325363*t+.0514459929*n;let i=.2119034982*e+.6806995451*t+.1073969566*n;let r=.0883024619*e+.2817188376*t+.6299787005*n;a=Math.cbrt(a);i=Math.cbrt(i);r=Math.cbrt(r);return[a*+.2104542553+i*+.793617785+r*-.0040720468,a*+1.9779984951+i*-2.428592205+r*+.4505937099,a*+.0259040371+i*+.7827717662+r*-.808675766]}function V(e,t,n){let a=e+t*+.3963377774+n*+.2158037573;let i=e+t*-.1055613458+n*-.0638541728;let r=e+t*-.0894841775+n*-1.291485548;a**=3;i**=3;r**=3;let o=a*+4.0767416621+i*-3.3077115913+r*+.2309699292;let s=a*-1.2684380046+i*+2.6097574011+r*-.3413193965;let l=a*-.0041960863+i*-.7034186147+r*+1.707614701;o=CABLES.clamp(o,0,1);s=CABLES.clamp(s,0,1);l=CABLES.clamp(l,0,1);return[o,s,l]}function z(e,t,n){e/=255;const a=.0031308;let i=12.92*e;let r=1.055*Math.pow(e,.41666)-.055;return(e<a?i:r)*255}function o(){U.addNextFrameOnceCallback(s)}function s(){const e=l();if(e)u(e)}function l(){let t=null;n.setUiError("nodata",null);n.setUiError("parse",null);if(Array.isArray(a.get())){t=a.get()}else{let e=null;if(!y.get()||y.get()===""){return null}try{e=JSON.parse(y.get())}catch(e){n.setUiError("parse","could not parse gradient data")}if(!e||!e.keys){n.setUiError("nodata","gradient no data");return null}t=e.keys}return t}function v(e,t){e%=g;t%=g;return r[e+t*g]/255-.5}function X(i,r,o){if(p.get()==0)return i;for(let a=0;a<r;a++)for(let n=0;n<o;n++){const s=i[(a+n*r)*4+0];const l=i[(a+n*r)*4+1];const u=i[(a+n*r)*4+2];let e=r/8*p.get()*v(a,n);let t=o/8*p.get()*v(a+g/2,n+g/2);if(o==1)t=0;if(r==1)e=0;e=Math.round(e);t=Math.round(t);const m=CABLES.clamp(n+t,0,o-1);const c=CABLES.clamp(a+e,0,r-1);const d=i[(c+m*r)*4+0];const h=i[(c+m*r)*4+1];const f=i[(c+m*r)*4+2];i[(a+n*r)*4+0]=d;i[(a+n*r)*4+1]=h;i[(a+n*r)*4+2]=f;i[(c+m*r)*4+0]=s;i[(c+m*r)*4+1]=l;i[(c+m*r)*4+2]=u}return i}function u(t){let i=Math.round(w.get());if(i<4)i=4;y.setUiAttribs({editShortcut:true,gradEditSmoothstep:M.get(),gradEditStep:P.get(),gradOklab:L.get()});let e=0;let n=0;if(k.get()=="repeat")e=CGL.Texture.WRAP_REPEAT;else if(k.get()=="mirrored repeat")e=CGL.Texture.WRAP_MIRRORED_REPEAT;else if(k.get()=="clamp to edge")e=CGL.Texture.WRAP_CLAMP_TO_EDGE;if(R.get()=="nearest")n=CGL.Texture.FILTER_NEAREST;else if(R.get()=="linear")n=CGL.Texture.FILTER_LINEAR;else if(R.get()=="mipmap")n=CGL.Texture.FILTER_MIPMAP;const a=new CGL.Texture(U);let r=new Uint8Array(i*4);for(let e=0;e<t.length-1;e++){const l=t[e];const u=t[e+1];for(let n=l.pos*i;n<u.pos*i;n++){let e=CABLES.map(n,l.pos*i,u.pos*i,0,1);if(P.get())e=Math.round(e);if(M.get())e=CABLES.smoothStep(e);n=Math.round(n);let t=n;if(N.get())t=i-n-1;if(L.get()){const m=F(l.r,l.g,l.b);const c=m[0];const d=m[1];const h=m[2];const f=F(u.r,u.g,u.b);const p=f[0];const g=f[1];const v=f[2];const b=e*p+(1-e)*c;const x=e*g+(1-e)*d;const _=e*v+(1-e)*h;const O=V(b,x,_);r[t*4+0]=Math.round(O[0]*255);r[t*4+1]=Math.round(O[1]*255);r[t*4+2]=Math.round(O[2]*255)}else{r[t*4+0]=Math.round((e*u.r+(1-e)*l.r)*255);r[t*4+1]=Math.round((e*u.g+(1-e)*l.g)*255);r[t*4+2]=Math.round((e*u.b+(1-e)*l.b)*255)}if(typeof l.a!=="undefined"&&typeof u.a!=="undefined"){const A=Math.round((e*u.a+(1-e)*l.a)*255);r[t*4+3]=A}else{r[t*4+3]=Math.round(255)}}}if(j.get())for(let e=0;e<r.length;e+=4){r[e+0]=z(r[e+0]);r[e+1]=z(r[e+1]);r[e+2]=z(r[e+2])}if(E.get()=="X")a.initFromData(X(r,i,1),i,1,n,e);if(E.get()=="Y")a.initFromData(X(r,1,i),1,i,n,e);if(E.get()=="Radial"){const I=new Uint8Array(i*i*4);for(let a=0;a<i;a++){for(let n=0;n<i;n++){const T=a-(i-1)/2;const S=n-(i-1)/2;let e=Math.sqrt(T*T+S*S)/i*2;if(M.get())e=CABLES.smoothStep(e);let t=Math.round(e*i)*4;if(t>=i*4)t=i*4-4;I[a*4+n*4*i+0]=r[t+0];I[a*4+n*4*i+1]=r[t+1];I[a*4+n*4*i+2]=r[t+2];I[a*4+n*4*i+3]=Math.round(255)}}r=I;a.initFromData(X(r,i,i),i,i,n,e)}if(E.get()=="XX"){const I=new Uint8Array(i*i*4);for(let t=0;t<i;t++)for(let e=0;e<i;e++){const C=t*4;I[t*4+e*4*i+0]=r[C+0];I[t*4+e*4*i+1]=r[C+1];I[t*4+e*4*i+2]=r[C+2];I[t*4+e*4*i+3]=Math.round(255)}r=I;a.initFromData(X(r,i,i),i,i,n,e)}if(E.get()=="YY"){const I=new Uint8Array(i*i*4);for(let t=0;t<i;t++)for(let e=0;e<i;e++){const C=t*4;I[e*4+t*4*i+0]=r[C+0];I[e*4+t*4*i+1]=r[C+1];I[e*4+t*4*i+2]=r[C+2];I[e*4+t*4*i+3]=Math.round(255)}r=I;a.initFromData(X(r,i,i),i,i,n,e)}if(E.get()=="XY"||E.get()=="YX"){const I=new Uint8Array(i*i*4);for(let a=0;a<i;a++){let n=a;if(E.get()=="YX")n=i-a-1;for(let t=0;t<i;t++){let e=Math.round((n+t)/2)*4;I[a*4+t*4*i+0]=r[e+0];I[a*4+t*4*i+1]=r[e+1];I[a*4+t*4*i+2]=r[e+2];I[a*4+t*4*i+3]=Math.round(255)}}r=I;a.initFromData(X(r,i,i),i,i,n,e)}const o=[];for(let e=0;e<t.length-1;e++){o.push(t[e].r,t[e].g,t[e].b)}const s=[];for(let e=0;e<t.length-1;e++){s.push(t[e].pos)}D.set(o);G.set(s);B.setRef(a)}};Ops.Gl.GradientTexture.prototype=new CABLES.Op;CABLES.OPS["01380a50-2dbb-4465-ae80-86349b0b717a"]={f:Ops.Gl.GradientTexture,objName:"Ops.Gl.GradientTexture"};Ops.Array.ArrayPack4Simple=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const o=e.inArray("Array 1"),s=e.inArray("Array 2"),l=e.inArray("Array 3"),u=e.inArray("Array 4"),m=e.outArray("Array out",4),c=e.outNumber("Num Points"),d=e.outNumber("Array length");let n=false;let h=[];let f=[];let p=true;o.onChange=s.onChange=l.onChange=u.onChange=a;function a(){let t=o.get();let n=s.get();let a=l.get();let i=u.get();if(!t&&!n&&!a&&!i){m.set(null);c.set(0);return}let r=0;if(!t||!n||!a||!i){if(t)r=t.length;else if(n)r=n.length;else if(a)r=a.length;else if(i)r=i.length;if(f.length!=r)for(let e=0;e<r;e++)f[e]=0;if(!t)t=f;if(!n)n=f;if(!a)a=f;if(!i)i=f}if(t.length!==n.length||n.length!==a.length||a.length!==i.length||t.length!==i.length||t.length!==a.length){e.setUiError("arraylen","Arrays do not have the same length !",1);return}e.setUiError("arraylen",null);h.length=t.length*4;for(let e=0;e<t.length;e++){h[e*4+0]=t[e];h[e*4+1]=n[e];h[e*4+2]=a[e];h[e*4+3]=i[e]}p=false;m.setRef(h);c.set(h.length/4);d.set(h.length)}};Ops.Array.ArrayPack4Simple.prototype=new CABLES.Op;CABLES.OPS["6fe2bb0e-4bfc-42c1-8bc1-19fda052e091"]={f:Ops.Array.ArrayPack4Simple,objName:"Ops.Array.ArrayPack4Simple"};Ops.Gl.ImageCompose.DepthTextureFocus_v2=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={depth_focus_frag:"IN vec2 texCoord;\nUNI sampler2D image;\nUNI float nearPlane;\nUNI float farPlane;\nUNI float focus; // center\nUNI float width;\n\n\nvoid main()\n{\n    float depthFromTexture = texture(image,texCoord).r;\n\n    float z_viewSpace = (nearPlane * farPlane) / (farPlane - depthFromTexture * (farPlane - nearPlane));\n    z_viewSpace = abs(z_viewSpace - (focus));\n    z_viewSpace = smoothstep(0.0, width, z_viewSpace);\n\n    #ifndef INVERT\n        z_viewSpace = 1. - z_viewSpace;\n    #endif\n\n    outColor = vec4(vec3(z_viewSpace), 1.);\n}"};const n=t.inTrigger("render");const a=t.inTexture("Depth Texture");const i=t.inFloat("Focus",.5);const r=t.inFloat("Width",.2);const o=t.inBool("Invert",false);const s=t.inFloat("nearplane",.1);const l=t.inFloat("farplane",100);const u=t.outTrigger("trigger");t.setPortGroup("Frustum",[l,s]);t.setPortGroup("Focus Settings",[o,i,r]);const m=t.patch.cgl;const c=new CGL.Shader(m,t.name,t);const d=e.depth_focus_frag||"";c.setSource(c.getDefaultVertexShader(),d);const h=new CGL.Uniform(c,"t","depthTexture",0);const f=new CGL.Uniform(c,"f","farPlane",l);const p=new CGL.Uniform(c,"f","nearPlane",s);const g=new CGL.Uniform(c,"f","focus",i);const v=new CGL.Uniform(c,"f","width",r);const b=new CGL.Uniform(c,"f","aspectRatio",0);o.onChange=function(){if(o.get())c.define("INVERT");else c.removeDefine("INVERT")};n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(t))return;if(a.get()&&a.get().tex){const e=m.currentTextureEffect.getCurrentSourceTexture().height/m.currentTextureEffect.getCurrentSourceTexture().width;b.set(e);m.pushShader(c);m.currentTextureEffect.bind();m.setTexture(0,a.get().tex);m.currentTextureEffect.finish();m.popShader()}u.trigger()}};Ops.Gl.ImageCompose.DepthTextureFocus_v2.prototype=new CABLES.Op;CABLES.OPS["f84ac22e-664e-4ff1-b23f-539ac1f5c67e"]={f:Ops.Gl.ImageCompose.DepthTextureFocus_v2,objName:"Ops.Gl.ImageCompose.DepthTextureFocus_v2"};Ops.Gl.GLTF.GltfScene_v3=function(){CABLES.Op.apply(this,arguments);const _=this;const l=_.attachments={inc_camera_js:"const gltfCamera = class\n{\n    constructor(gltf, node)\n    {\n        this.node = node;\n        this.name = node.name;\n        // console.log(gltf);\n        this.config = gltf.json.cameras[node.camera];\n\n        this.pos = vec3.create();\n        this.quat = quat.create();\n        this.vCenter = vec3.create();\n        this.vUp = vec3.create();\n        this.vMat = mat4.create();\n    }\n\n    updateAnim(time)\n    {\n        if (this.node && this.node._animTrans)\n        {\n            vec3.set(this.pos,\n                this.node._animTrans[0].getValue(time),\n                this.node._animTrans[1].getValue(time),\n                this.node._animTrans[2].getValue(time));\n\n            quat.set(this.quat,\n                this.node._animRot[0].getValue(time),\n                this.node._animRot[1].getValue(time),\n                this.node._animRot[2].getValue(time),\n                this.node._animRot[3].getValue(time));\n        }\n    }\n\n    start(time)\n    {\n        if (cgl.frameStore.shadowPass) return;\n\n        this.updateAnim(time);\n        const asp = cgl.getViewPort()[2] / cgl.getViewPort()[3];\n\n        cgl.pushPMatrix();\n        // mat4.perspective(\n        //     cgl.pMatrix,\n        //     this.config.perspective.yfov*0.5,\n        //     asp,\n        //     this.config.perspective.znear,\n        //     this.config.perspective.zfar);\n\n        cgl.pushViewMatrix();\n        // mat4.identity(cgl.vMatrix);\n\n        // if(this.node && this.node.parent)\n        // {\n        //     console.log(this.node.parent)\n        // vec3.add(this.pos,this.pos,this.node.parent._node.translation);\n        // vec3.sub(this.vCenter,this.vCenter,this.node.parent._node.translation);\n        // mat4.translate(cgl.vMatrix,cgl.vMatrix,\n        // [\n        //     -this.node.parent._node.translation[0],\n        //     -this.node.parent._node.translation[1],\n        //     -this.node.parent._node.translation[2]\n        // ])\n        // }\n\n        // vec3.set(this.vUp, 0, 1, 0);\n        // vec3.set(this.vCenter, 0, -1, 0);\n        // // vec3.set(this.vCenter, 0, 1, 0);\n        // vec3.transformQuat(this.vCenter, this.vCenter, this.quat);\n        // vec3.normalize(this.vCenter, this.vCenter);\n        // vec3.add(this.vCenter, this.vCenter, this.pos);\n\n        // mat4.lookAt(cgl.vMatrix, this.pos, this.vCenter, this.vUp);\n\n        let mv = mat4.create();\n        mat4.invert(mv, this.node.modelMatAbs());\n\n        // console.log(this.node.modelMatAbs());\n\n        this.vMat = mv;\n\n        mat4.identity(cgl.vMatrix);\n        // console.log(mv);\n        mat4.mul(cgl.vMatrix, cgl.vMatrix, mv);\n    }\n\n    end()\n    {\n        if (cgl.frameStore.shadowPass) return;\n        cgl.popPMatrix();\n        cgl.popViewMatrix();\n    }\n};\n",inc_gltf_js:'const CHUNK_HEADER_SIZE = 8;\n\nconst Gltf = class\n{\n    constructor()\n    {\n        this.json = {};\n        this.accBuffers = [];\n        this.meshes = [];\n        this.nodes = [];\n        this.shaders = [];\n        this.timing = [];\n        this.cams = [];\n        this.startTime = performance.now();\n        this.bounds = new CABLES.CG.BoundingBox();\n        this.loaded = Date.now();\n        this.accBuffersDelete = [];\n    }\n\n    getNode(n)\n    {\n        for (let i = 0; i < this.nodes.length; i++)\n        {\n            if (this.nodes[i].name == n) return this.nodes[i];\n        }\n    }\n\n    unHideAll()\n    {\n        for (let i = 0; i < this.nodes.length; i++)\n        {\n            this.nodes[i].unHide();\n        }\n    }\n};\n\nfunction Utf8ArrayToStr(array)\n{\n    if (window.TextDecoder) return new TextDecoder("utf-8").decode(array);\n\n    let out, i, len, c;\n    let char2, char3;\n\n    out = "";\n    len = array.length;\n    i = 0;\n    while (i < len)\n    {\n        c = array[i++];\n        switch (c >> 4)\n        {\n        case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:\n            // 0xxxxxxx\n            out += String.fromCharCode(c);\n            break;\n        case 12: case 13:\n            // 110x xxxx   10xx xxxx\n            char2 = array[i++];\n            out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));\n            break;\n        case 14:\n            // 1110 xxxx  10xx xxxx  10xx xxxx\n            char2 = array[i++];\n            char3 = array[i++];\n            out += String.fromCharCode(((c & 0x0F) << 12) |\n                    ((char2 & 0x3F) << 6) |\n                    ((char3 & 0x3F) << 0));\n            break;\n        }\n    }\n\n    return out;\n}\n\nfunction readChunk(dv, bArr, arrayBuffer, offset)\n{\n    const chunk = {};\n\n    if (offset >= dv.byteLength)\n    {\n        op.log("could not read chunk...");\n        return;\n    }\n    chunk.size = dv.getUint32(offset + 0, le);\n\n    // chunk.type = new TextDecoder("utf-8").decode(bArr.subarray(offset+4, offset+4+4));\n    chunk.type = Utf8ArrayToStr(bArr.subarray(offset + 4, offset + 4 + 4));\n\n    if (chunk.type == "BIN\\0")\n    {\n        // console.log(chunk.size,arrayBuffer.length,offset);\n        // try\n        // {\n        chunk.dataView = new DataView(arrayBuffer, offset + 8, chunk.size);\n        // }\n        // catch(e)\n        // {\n        //     chunk.dataView = null;\n        //     console.log(e);\n        // }\n    }\n    else\n    if (chunk.type == "JSON")\n    {\n        const json = Utf8ArrayToStr(bArr.subarray(offset + 8, offset + 8 + chunk.size));\n\n        try\n        {\n            const obj = JSON.parse(json);\n            chunk.data = obj;\n            outGenerator.set(obj.asset.generator);\n        }\n        catch (e)\n        {\n        }\n    }\n    else\n    {\n        op.warn("unknown type", chunk.type);\n    }\n\n    return chunk;\n}\n\nfunction loadAnims(gltf)\n{\n    const uniqueAnimNames = {};\n\n    for (let i = 0; i < gltf.json.animations.length; i++)\n    {\n        const an = gltf.json.animations[i];\n\n        for (let ia = 0; ia < an.channels.length; ia++)\n        {\n            const chan = an.channels[ia];\n\n            const node = gltf.nodes[chan.target.node];\n            const sampler = an.samplers[chan.sampler];\n\n            const acc = gltf.json.accessors[sampler.input];\n            const bufferIn = gltf.accBuffers[sampler.input];\n\n            const accOut = gltf.json.accessors[sampler.output];\n            const bufferOut = gltf.accBuffers[sampler.output];\n\n            gltf.accBuffersDelete.push(sampler.output, sampler.input);\n\n            if (bufferIn && bufferOut)\n            {\n                let numComps = 1;\n                if (accOut.type == "VEC2")numComps = 2;\n                else if (accOut.type == "VEC3")numComps = 3;\n                else if (accOut.type == "VEC4")numComps = 4;\n                else op.warn("unknown accOut.type", accOut.type);\n\n                const anims = [];\n\n                uniqueAnimNames[an.name] = true;\n\n                for (let k = 0; k < numComps; k++)\n                {\n                    const newAnim = new CABLES.Anim();\n                    // newAnim.name=an.name;\n                    anims.push(newAnim);\n                }\n\n                if (sampler.interpolation === "LINEAR") {}\n                else if (sampler.interpolation === "STEP") for (let k = 0; k < numComps; k++) anims[k].defaultEasing = CABLES.EASING_ABSOLUTE;\n                else if (sampler.interpolation === "CUBICSPLINE") for (let k = 0; k < numComps; k++) anims[k].defaultEasing = CABLES.EASING_CUBICSPLINE;\n                else op.warn("unknown interpolation", sampler.interpolation);\n\n                // console.log(bufferOut)\n\n                // if there is no keyframe for time 0 copy value of first keyframe at time 0\n                if (bufferIn[0] !== 0.0)\n                    for (let k = 0; k < numComps; k++)\n                        anims[k].setValue(0, bufferOut[0 * numComps + k]);\n\n                // console.log(sampler.interpolation,bufferOut.length/numComps)\n\n                for (let j = 0; j < bufferIn.length; j++)\n                {\n                    maxTime = Math.max(bufferIn[j], maxTime);\n\n                    for (let k = 0; k < numComps; k++)\n                    {\n                        if (anims[k].defaultEasing === CABLES.EASING_CUBICSPLINE)\n                        {\n                            const idx = ((j * numComps) * 3 + k);\n\n                            const key = anims[k].setValue(bufferIn[j], bufferOut[idx + numComps]);\n                            key.bezTangIn = bufferOut[idx];\n                            key.bezTangOut = bufferOut[idx + (numComps * 2)];\n\n                            // console.log(an.name,k,bufferOut[idx+1]);\n                        }\n                        else\n                        {\n                            // console.log(an.name,k,bufferOut[j * numComps + k]);\n                            anims[k].setValue(bufferIn[j], bufferOut[j * numComps + k]);\n                        }\n                    }\n                }\n\n                node.setAnim(chan.target.path, an.name, anims);\n            }\n            else\n            {\n                op.warn("loadAmins bufferIn undefined ", bufferIn === undefined);\n                op.warn("loadAmins bufferOut undefined ", bufferOut === undefined);\n                op.warn("loadAmins ", sampler, accOut);\n                op.warn("loadAmins num accBuffers", gltf.accBuffers.length);\n                op.warn("loadAmins num accessors", gltf.json.accessors.length);\n            }\n        }\n    }\n\n    gltf.uniqueAnimNames = uniqueAnimNames;\n\n    outAnims.setRef(Object.keys(uniqueAnimNames));\n}\n\nfunction loadCams(gltf)\n{\n    if (!gltf || !gltf.json.cameras) return;\n\n    gltf.cameras = gltf.cameras || [];\n\n    for (let i = 0; i < gltf.nodes.length; i++)\n    {\n        if (gltf.nodes[i].hasOwnProperty("camera"))\n        {\n            const cam = new gltfCamera(gltf, gltf.nodes[i]);\n            gltf.cameras.push(cam);\n        }\n    }\n}\n\nfunction loadAfterDraco()\n{\n    if (!window.DracoDecoder)\n    {\n        setTimeout(() =>\n        {\n            loadAfterDraco();\n        }, 100);\n    }\n\n    reloadSoon();\n}\n\nfunction parseGltf(arrayBuffer)\n{\n    let j = 0, i = 0;\n\n    const gltf = new Gltf();\n    gltf.timing.push(["Start parsing", Math.round((performance.now() - gltf.startTime))]);\n\n    if (!arrayBuffer) return;\n    const byteArray = new Uint8Array(arrayBuffer);\n    let pos = 0;\n\n    // var string = new TextDecoder("utf-8").decode(byteArray.subarray(pos, 4));\n    const string = Utf8ArrayToStr(byteArray.subarray(pos, 4));\n    pos += 4;\n    if (string != "glTF") return;\n\n    gltf.timing.push(["dataview", Math.round((performance.now() - gltf.startTime))]);\n\n    const dv = new DataView(arrayBuffer);\n    const version = dv.getUint32(pos, le);\n    pos += 4;\n    const size = dv.getUint32(pos, le);\n    pos += 4;\n\n    outVersion.set(version);\n\n    const chunks = [];\n    gltf.chunks = chunks;\n\n    chunks.push(readChunk(dv, byteArray, arrayBuffer, pos));\n    pos += chunks[0].size + CHUNK_HEADER_SIZE;\n    gltf.json = chunks[0].data;\n\n    gltf.cables = {\n        "fileUrl": inFile.get(),\n        "shortFileName": CABLES.basename(inFile.get())\n    };\n\n    outJson.set(gltf.json);\n    outExtensions.set(gltf.json.extensionsUsed || []);\n\n    let ch = readChunk(dv, byteArray, arrayBuffer, pos);\n    while (ch)\n    {\n        chunks.push(ch);\n        pos += ch.size + CHUNK_HEADER_SIZE;\n        ch = readChunk(dv, byteArray, arrayBuffer, pos);\n    }\n\n    gltf.chunks = chunks;\n\n    const views = chunks[0].data.bufferViews;\n    const accessors = chunks[0].data.accessors;\n\n    gltf.timing.push(["Parse buffers", Math.round((performance.now() - gltf.startTime))]);\n\n    if (gltf.json.extensionsUsed && gltf.json.extensionsUsed.indexOf("KHR_draco_mesh_compression") > -1)\n    {\n        if (!window.DracoDecoder)\n        {\n            op.setUiError("gltfdraco", "GLTF draco compression lib not found / add draco op to your patch!");\n\n            loadAfterDraco();\n            return gltf;\n        }\n        else\n        {\n            gltf.useDraco = true;\n        }\n    }\n\n    op.setUiError("gltfdraco", null);\n    // let accPos = (view.byteOffset || 0) + (acc.byteOffset || 0);\n\n    if (views)\n    {\n        for (i = 0; i < accessors.length; i++)\n        {\n            const acc = accessors[i];\n            const view = views[acc.bufferView];\n\n            let numComps = 0;\n            if (acc.type == "SCALAR")numComps = 1;\n            else if (acc.type == "VEC2")numComps = 2;\n            else if (acc.type == "VEC3")numComps = 3;\n            else if (acc.type == "VEC4")numComps = 4;\n            else if (acc.type == "MAT4")numComps = 16;\n            else console.error("unknown accessor type", acc.type);\n\n            //   const decoder = new decoderModule.Decoder();\n            //   const decodedGeometry = decodeDracoData(data, decoder);\n            //   // Encode mesh\n            //   encodeMeshToFile(decodedGeometry, decoder);\n\n            //   decoderModule.destroy(decoder);\n            //   decoderModule.destroy(decodedGeometry);\n\n            // 5120 (BYTE)\t1\n            // 5121 (UNSIGNED_BYTE)\t1\n            // 5122 (SHORT)\t2\n\n            if (chunks[1].dataView)\n            {\n                if (view)\n                {\n                    const num = acc.count * numComps;\n                    let accPos = (view.byteOffset || 0) + (acc.byteOffset || 0);\n                    let stride = view.byteStride || 0;\n                    let dataBuff = null;\n\n                    if (acc.componentType == 5126 || acc.componentType == 5125) // 4byte FLOAT or INT\n                    {\n                        stride = stride || 4;\n\n                        const isInt = acc.componentType == 5125;\n                        if (isInt)dataBuff = new Uint32Array(num);\n                        else dataBuff = new Float32Array(num);\n\n                        for (j = 0; j < num; j++)\n                        {\n                            if (isInt) dataBuff[j] = chunks[1].dataView.getUint32(accPos, le);\n                            else dataBuff[j] = chunks[1].dataView.getFloat32(accPos, le);\n\n                            if (stride != 4 && (j + 1) % numComps === 0)accPos += stride - (numComps * 4);\n                            accPos += 4;\n                        }\n                    }\n                    else if (acc.componentType == 5123) // UNSIGNED_SHORT\n                    {\n                        stride = stride || 2;\n\n                        dataBuff = new Uint16Array(num);\n\n                        for (j = 0; j < num; j++)\n                        {\n                            dataBuff[j] = chunks[1].dataView.getUint16(accPos, le);\n\n                            if (stride != 2 && (j + 1) % numComps === 0) accPos += stride - (numComps * 2);\n\n                            accPos += 2;\n                        }\n                    }\n                    else if (acc.componentType == 5121) // UNSIGNED_BYTE\n                    {\n                        stride = stride || 1;\n\n                        dataBuff = new Uint8Array(num);\n\n                        for (j = 0; j < num; j++)\n                        {\n                            dataBuff[j] = chunks[1].dataView.getUint8(accPos, le);\n\n                            if (stride != 1 && (j + 1) % numComps === 0) accPos += stride - (numComps * 1);\n\n                            accPos += 1;\n                        }\n                    }\n\n                    else\n                    {\n                        console.error("unknown component type", acc.componentType);\n                    }\n\n                    gltf.accBuffers.push(dataBuff);\n                }\n                else\n                {\n                    // console.log("has no dataview");\n                }\n            }\n        }\n    }\n\n    gltf.timing.push(["Parse mesh groups", Math.round((performance.now() - gltf.startTime))]);\n\n    gltf.json.meshes = gltf.json.meshes || [];\n\n    if (gltf.json.meshes)\n    {\n        for (i = 0; i < gltf.json.meshes.length; i++)\n        {\n            const mesh = new gltfMeshGroup(gltf, gltf.json.meshes[i]);\n            gltf.meshes.push(mesh);\n        }\n    }\n\n    gltf.timing.push(["Parse nodes", Math.round((performance.now() - gltf.startTime))]);\n\n    for (i = 0; i < gltf.json.nodes.length; i++)\n    {\n        if (gltf.json.nodes[i].children)\n            for (j = 0; j < gltf.json.nodes[i].children.length; j++)\n            {\n                gltf.json.nodes[gltf.json.nodes[i].children[j]].isChild = true;\n            }\n    }\n\n    for (i = 0; i < gltf.json.nodes.length; i++)\n    {\n        const node = new gltfNode(gltf.json.nodes[i], gltf);\n        gltf.nodes.push(node);\n    }\n\n    for (i = 0; i < gltf.nodes.length; i++)\n    {\n        const node = gltf.nodes[i];\n\n        if (!node.children) continue;\n        for (let j = 0; j < node.children.length; j++)\n        {\n            gltf.nodes[node.children[j]].parent = node;\n        }\n    }\n\n    for (i = 0; i < gltf.nodes.length; i++)\n    {\n        gltf.nodes[i].initSkin();\n    }\n\n    needsMatUpdate = true;\n\n    gltf.timing.push(["load anims", Math.round((performance.now() - gltf.startTime))]);\n\n    if (gltf.json.animations) loadAnims(gltf);\n\n    gltf.timing.push(["load cameras", Math.round((performance.now() - gltf.startTime))]);\n\n    if (gltf.json.cameras) loadCams(gltf);\n\n    gltf.timing.push(["finished", Math.round((performance.now() - gltf.startTime))]);\n    return gltf;\n}\n',inc_mesh_js:'let gltfMesh = class\n{\n    constructor(name, prim, gltf, finished)\n    {\n        this.POINTS = 0;\n        this.LINES = 1;\n        this.LINE_LOOP = 2;\n        this.LINE_STRIP = 3;\n        this.TRIANGLES = 4;\n        this.TRIANGLE_STRIP = 5;\n        this.TRIANGLE_FAN = 6;\n\n        this.test = 0;\n        this.name = name;\n        this.submeshIndex = 0;\n        this.material = prim.material;\n        this.mesh = null;\n        this.geom = new CGL.Geometry("gltf_" + this.name);\n        this.geom.verticesIndices = [];\n        this.bounds = null;\n        this.primitive = 4;\n        if (prim.hasOwnProperty("mode")) this.primitive = prim.mode;\n\n        if (prim.hasOwnProperty("indices")) this.geom.verticesIndices = gltf.accBuffers[prim.indices];\n\n        gltf.loadingMeshes = gltf.loadingMeshes || 0;\n        gltf.loadingMeshes++;\n\n        this.materialJson =\n            this._matPbrMetalness =\n            this._matPbrRoughness =\n            this._matDiffuseColor = null;\n\n        if (gltf.json.materials)\n        {\n            if (this.material != -1) this.materialJson = gltf.json.materials[this.material];\n\n            if (this.materialJson && this.materialJson.pbrMetallicRoughness)\n            {\n                if (!this.materialJson.pbrMetallicRoughness.hasOwnProperty("baseColorFactor"))\n                {\n                    this._matDiffuseColor = [1, 1, 1, 1];\n                }\n                else\n                {\n                    this._matDiffuseColor = this.materialJson.pbrMetallicRoughness.baseColorFactor;\n                }\n\n                this._matDiffuseColor = this.materialJson.pbrMetallicRoughness.baseColorFactor;\n\n                if (!this.materialJson.pbrMetallicRoughness.hasOwnProperty("metallicFactor"))\n                {\n                    this._matPbrMetalness = 1.0;\n                }\n                else\n                {\n                    this._matPbrMetalness = this.materialJson.pbrMetallicRoughness.metallicFactor || null;\n                }\n\n                if (!this.materialJson.pbrMetallicRoughness.hasOwnProperty("roughnessFactor"))\n                {\n                    this._matPbrRoughness = 1.0;\n                }\n                else\n                {\n                    this._matPbrRoughness = this.materialJson.pbrMetallicRoughness.roughnessFactor || null;\n                }\n            }\n        }\n\n        if (gltf.useDraco && prim.extensions.KHR_draco_mesh_compression)\n        {\n            const view = gltf.chunks[0].data.bufferViews[prim.extensions.KHR_draco_mesh_compression.bufferView];\n            const num = view.byteLength;\n            const dataBuff = new Int8Array(num);\n            let accPos = (view.byteOffset || 0);// + (acc.byteOffset || 0);\n            for (let j = 0; j < num; j++)\n            {\n                dataBuff[j] = gltf.chunks[1].dataView.getInt8(accPos, le);\n                accPos++;\n            }\n\n            const dracoDecoder = window.DracoDecoder;\n            dracoDecoder.decodeGeometry(dataBuff.buffer, (geometry) =>\n            {\n                const geom = new CGL.Geometry("draco mesh " + name);\n\n                for (let i = 0; i < geometry.attributes.length; i++)\n                {\n                    const attr = geometry.attributes[i];\n\n                    if (attr.name === "position") geom.vertices = attr.array;\n                    else if (attr.name === "normal") geom.vertexNormals = attr.array;\n                    else if (attr.name === "uv") geom.texCoords = attr.array;\n                    else if (attr.name === "color") geom.vertexColors = this.calcVertexColors(attr.array);\n                    else if (attr.name === "joints") geom.setAttribute("attrJoints", Array.from(attr.array), 4);\n                    else if (attr.name === "weights")\n                    {\n                        const arr4 = new Float32Array(attr.array.length / attr.itemSize * 4);\n\n                        for (let k = 0; k < attr.array.length / attr.itemSize; k++)\n                        {\n                            arr4[k * 4] = arr4[k * 4 + 1] = arr4[k * 4 + 2] = arr4[k * 4 + 3] = 0;\n                            for (let j = 0; j < attr.itemSize; j++)\n                                arr4[k * 4 + j] = attr.array[k * attr.itemSize + j];\n                        }\n                        geom.setAttribute("attrWeights", arr4, 4);\n                    }\n                    else op.logWarn("unknown draco attrib", attr);\n                }\n\n                geometry.attributes = null;\n                geom.verticesIndices = geometry.index.array;\n\n                this.setGeom(geom);\n\n                this.mesh = null;\n                gltf.loadingMeshes--;\n                gltf.timing.push(["draco decode", Math.round((performance.now() - gltf.startTime))]);\n\n                if (finished)finished(this);\n            }, (error) => { op.logError(error); });\n        }\n        else\n        {\n            gltf.loadingMeshes--;\n            this.fillGeomAttribs(gltf, this.geom, prim.attributes);\n\n            if (prim.targets)\n            {\n                // console.log("prim.targets", prim.targets.length);\n                for (let j = 0; j < prim.targets.length; j++)\n                {\n                    // var tgeom=new CGL.Geometry("gltf_"+this.name);\n                    let tgeom = this.geom.copy();\n\n                    if (prim.hasOwnProperty("indices")) tgeom.verticesIndices = gltf.accBuffers[prim.indices];\n\n                    this.fillGeomAttribs(gltf, tgeom, prim.targets[j], false);\n\n                    { // calculate normals for final position of morphtarget for later...\n                        for (let i = 0; i < tgeom.vertices.length; i++) tgeom.vertices[i] += this.geom.vertices[i];\n                        tgeom.calculateNormals();\n                        for (let i = 0; i < tgeom.vertices.length; i++) tgeom.vertices[i] -= this.geom.vertices[i];\n                    }\n\n                    this.geom.morphTargets.push(tgeom);\n                }\n            }\n            if (finished)finished(this);\n        }\n    }\n\n    _linearToSrgb(x)\n    {\n        if (x <= 0)\n            return 0;\n        else if (x >= 1)\n            return 1;\n        else if (x < 0.0031308)\n            return x * 12.92;\n        else\n            return x ** (1 / 2.2) * 1.055 - 0.055;\n    }\n\n    calcVertexColors(arr)\n    {\n        let vertexColors = null;\n        if (arr instanceof Float32Array)\n        {\n            let div = false;\n            for (let i = 0; i < arr.length; i++)\n            {\n                if (arr[i] > 1)\n                {\n                    div = true;\n                    continue;\n                }\n            }\n\n            if (div)\n                for (let i = 0; i < arr.length; i++) arr[i] /= 65535;\n\n            vertexColors = arr;\n        }\n\n        else if (arr instanceof Uint16Array)\n        {\n            const fb = new Float32Array(arr.length);\n            for (let i = 0; i < arr.length; i++) fb[i] = arr[i] / 65535;\n\n            vertexColors = fb;\n        }\n        else vertexColors = arr;\n\n        for (let i = 0; i < vertexColors.length; i++)\n        {\n            vertexColors[i] = this._linearToSrgb(vertexColors[i]);\n        }\n\n        return vertexColors;\n    }\n\n    fillGeomAttribs(gltf, tgeom, attribs, setGeom)\n    {\n        if (attribs.hasOwnProperty("POSITION")) tgeom.vertices = gltf.accBuffers[attribs.POSITION];\n        if (attribs.hasOwnProperty("NORMAL")) tgeom.vertexNormals = gltf.accBuffers[attribs.NORMAL];\n        if (attribs.hasOwnProperty("TANGENT")) tgeom.tangents = gltf.accBuffers[attribs.TANGENT];\n\n        if (attribs.hasOwnProperty("COLOR_0")) tgeom.vertexColors = this.calcVertexColors(gltf.accBuffers[attribs.COLOR_0]);\n        if (attribs.hasOwnProperty("COLOR_1")) tgeom.setAttribute("attrVertColor1", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_1]), 4);\n        if (attribs.hasOwnProperty("COLOR_2")) tgeom.setAttribute("attrVertColor2", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_2]), 4);\n        if (attribs.hasOwnProperty("COLOR_3")) tgeom.setAttribute("attrVertColor3", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_3]), 4);\n        if (attribs.hasOwnProperty("COLOR_4")) tgeom.setAttribute("attrVertColor4", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_4]), 4);\n\n        if (attribs.hasOwnProperty("TEXCOORD_0"))tgeom.texCoords = gltf.accBuffers[attribs.TEXCOORD_0];\n        if (attribs.hasOwnProperty("TEXCOORD_1"))tgeom.setAttribute("attrTexCoord1", gltf.accBuffers[attribs.TEXCOORD_1], 2);\n        if (attribs.hasOwnProperty("TEXCOORD_2"))tgeom.setAttribute("attrTexCoord2", gltf.accBuffers[attribs.TEXCOORD_2], 2);\n        if (attribs.hasOwnProperty("TEXCOORD_3"))tgeom.setAttribute("attrTexCoord3", gltf.accBuffers[attribs.TEXCOORD_3], 2);\n        if (attribs.hasOwnProperty("TEXCOORD_4"))tgeom.setAttribute("attrTexCoord4", gltf.accBuffers[attribs.TEXCOORD_4], 2);\n\n        if (attribs.hasOwnProperty("WEIGHTS_0"))\n        {\n            tgeom.setAttribute("attrWeights", gltf.accBuffers[attribs.WEIGHTS_0], 4);\n        }\n        if (attribs.hasOwnProperty("JOINTS_0"))\n        {\n            if (!gltf.accBuffers[attribs.JOINTS_0])console.log("no !gltf.accBuffers[attribs.JOINTS_0]");\n            tgeom.setAttribute("attrJoints", gltf.accBuffers[attribs.JOINTS_0], 4);\n        }\n\n        if (attribs.hasOwnProperty("POSITION")) gltf.accBuffersDelete.push(attribs.POSITION);\n        if (attribs.hasOwnProperty("NORMAL")) gltf.accBuffersDelete.push(attribs.NORMAL);\n        if (attribs.hasOwnProperty("TEXCOORD_0")) gltf.accBuffersDelete.push(attribs.TEXCOORD_0);\n        if (attribs.hasOwnProperty("TANGENT")) gltf.accBuffersDelete.push(attribs.TANGENT);\n        if (attribs.hasOwnProperty("COLOR_0"))gltf.accBuffersDelete.push(attribs.COLOR_0);\n        if (attribs.hasOwnProperty("COLOR_0"))gltf.accBuffersDelete.push(attribs.COLOR_0);\n        if (attribs.hasOwnProperty("COLOR_1"))gltf.accBuffersDelete.push(attribs.COLOR_1);\n        if (attribs.hasOwnProperty("COLOR_2"))gltf.accBuffersDelete.push(attribs.COLOR_2);\n        if (attribs.hasOwnProperty("COLOR_3"))gltf.accBuffersDelete.push(attribs.COLOR_3);\n\n        if (attribs.hasOwnProperty("TEXCOORD_1")) gltf.accBuffersDelete.push(attribs.TEXCOORD_1);\n        if (attribs.hasOwnProperty("TEXCOORD_2")) gltf.accBuffersDelete.push(attribs.TEXCOORD_2);\n        if (attribs.hasOwnProperty("TEXCOORD_3")) gltf.accBuffersDelete.push(attribs.TEXCOORD_3);\n        if (attribs.hasOwnProperty("TEXCOORD_4")) gltf.accBuffersDelete.push(attribs.TEXCOORD_4);\n\n        if (setGeom !== false) if (tgeom && tgeom.verticesIndices) this.setGeom(tgeom);\n    }\n\n    setGeom(geom)\n    {\n        if (inNormFormat.get() == "X-ZY")\n        {\n            for (let i = 0; i < geom.vertexNormals.length; i += 3)\n            {\n                let t = geom.vertexNormals[i + 2];\n                geom.vertexNormals[i + 2] = geom.vertexNormals[i + 1];\n                geom.vertexNormals[i + 1] = -t;\n            }\n        }\n\n        if (inVertFormat.get() == "XZ-Y")\n        {\n            for (let i = 0; i < geom.vertices.length; i += 3)\n            {\n                let t = geom.vertices[i + 2];\n                geom.vertices[i + 2] = -geom.vertices[i + 1];\n                geom.vertices[i + 1] = t;\n            }\n        }\n\n        if (this.primitive == this.TRIANGLES)\n        {\n            if (!geom.vertexNormals.length || inCalcNormals.get()) geom.calculateNormals();\n\n            if ((!geom.biTangents || geom.biTangents.length == 0) && geom.tangents)\n            {\n                const bitan = vec3.create();\n                const tan = vec3.create();\n\n                const tangents = geom.tangents;\n                geom.tangents = new Float32Array(tangents.length / 4 * 3);\n                geom.biTangents = new Float32Array(tangents.length / 4 * 3);\n\n                for (let i = 0; i < tangents.length; i += 4)\n                {\n                    const idx = i / 4 * 3;\n\n                    vec3.cross(\n                        bitan,\n                        [geom.vertexNormals[idx], geom.vertexNormals[idx + 1], geom.vertexNormals[idx + 2]],\n                        [tangents[i], tangents[i + 1], tangents[i + 2]]\n                    );\n\n                    vec3.div(bitan, bitan, [tangents[i + 3], tangents[i + 3], tangents[i + 3]]);\n                    vec3.normalize(bitan, bitan);\n\n                    geom.biTangents[idx + 0] = bitan[0];\n                    geom.biTangents[idx + 1] = bitan[1];\n                    geom.biTangents[idx + 2] = bitan[2];\n\n                    geom.tangents[idx + 0] = tangents[i + 0];\n                    geom.tangents[idx + 1] = tangents[i + 1];\n                    geom.tangents[idx + 2] = tangents[i + 2];\n                }\n            }\n\n            if (geom.tangents.length === 0 || inCalcNormals.get()) geom.calcTangentsBitangents();\n        }\n\n        this.geom = geom;\n\n        this.bounds = geom.getBounds();\n    }\n\n    render(cgl, ignoreMaterial, skinRenderer)\n    {\n        if (!this.mesh && this.geom && this.geom.verticesIndices)\n        {\n            let g = this.geom;\n            if (this.geom.vertices.length / 3 > 64000)\n            {\n                g = this.geom.copy();\n                g.unIndex(false, true);\n            }\n\n            let glprim;\n            if (this.primitive == this.TRIANGLES)glprim = cgl.gl.TRIANGLES;\n            else if (this.primitive == this.LINES)glprim = cgl.gl.LINES;\n            else if (this.primitive == this.LINE_STRIP)glprim = cgl.gl.LINE_STRIP;\n            else if (this.primitive == this.POINTS)glprim = cgl.gl.POINTS;\n            else\n            {\n                op.logWarn("unknown primitive type", this);\n            }\n\n            this.mesh = new CGL.Mesh(cgl, g, glprim);\n            // this.mesh._geom = null;\n        }\n        else\n        {\n            // update morphTargets\n            if (this.geom && this.geom.morphTargets.length)\n            {\n                this.morphGeom = this.geom.copy();\n\n                this.test = time * 11.7;\n\n                if (this.test >= this.geom.morphTargets.length - 1) this.test = 0;\n\n                const mt = this.geom.morphTargets[Math.floor(this.test)];\n                const mt2 = this.geom.morphTargets[Math.floor(this.test + 1)];\n\n                if (mt && mt.vertices && mt2)\n                {\n                    if (this.morphGeom.vertexNormals.length != mt.vertexNormals.length)\n                        this.morphGeom.vertexNormals = new Float32Array(mt.vertexNormals.length);\n\n                    const fract = this.test % 1;\n                    for (let i = 0; i < this.morphGeom.vertices.length; i++)\n                    {\n                        this.morphGeom.vertices[i] =\n                            this.geom.vertices[i] +\n                            (1.0 - fract) * mt.vertices[i] +\n                            fract * mt2.vertices[i];\n\n                        this.morphGeom.vertexNormals[i] =\n                            (1.0 - fract) * mt.vertexNormals[i] +\n                            fract * mt2.vertexNormals[i];\n                    }\n\n                    this.mesh.updateNormals(this.morphGeom);\n                    this.mesh.updateVertices(this.morphGeom);\n                }\n            }\n\n            let useMat = !ignoreMaterial && this.material != -1 && gltf.shaders[this.material];\n            if (skinRenderer)useMat = false;\n\n            if (useMat) cgl.pushShader(gltf.shaders[this.material]);\n\n            const currentShader = cgl.getShader() || {};\n            const uniDiff = currentShader.uniformColorDiffuse;\n\n            const uniPbrMetalness = currentShader.uniformPbrMetalness;\n            const uniPbrRoughness = currentShader.uniformPbrRoughness;\n\n            if (!gltf.shaders[this.material] && inUseMatProps.get())\n            {\n                if (uniDiff && this._matDiffuseColor)\n                {\n                    this._matDiffuseColorOrig = [uniDiff.getValue()[0], uniDiff.getValue()[1], uniDiff.getValue()[2], uniDiff.getValue()[3]];\n                    uniDiff.setValue(this._matDiffuseColor);\n                }\n\n                if (uniPbrMetalness)\n                    if (this._matPbrMetalness != null)\n                    {\n                        this._matPbrMetalnessOrig = uniPbrMetalness.getValue();\n                        uniPbrMetalness.setValue(this._matPbrMetalness);\n                    }\n                    else\n                        uniPbrMetalness.setValue(0);\n\n                if (uniPbrRoughness)\n                    if (this._matPbrRoughness != null)\n                    {\n                        this._matPbrRoughnessOrig = uniPbrRoughness.getValue();\n                        uniPbrRoughness.setValue(this._matPbrRoughness);\n                    }\n                    else\n                    {\n                        uniPbrRoughness.setValue(0);\n                    }\n            }\n\n            if (this.mesh) this.mesh.render(cgl.getShader(), ignoreMaterial);\n\n            if (inUseMatProps.get())\n            {\n                if (uniDiff && this._matDiffuseColor) uniDiff.setValue(this._matDiffuseColorOrig);\n                if (uniPbrMetalness && this._matPbrMetalnessOrig != undefined) uniPbrMetalness.setValue(this._matPbrMetalnessOrig);\n                if (uniPbrRoughness && this._matPbrRoughnessOrig != undefined) uniPbrRoughness.setValue(this._matPbrRoughnessOrig);\n            }\n\n            if (useMat) cgl.popShader();\n        }\n    }\n};\n',inc_meshGroup_js:"const gltfMeshGroup = class\n{\n    constructor(gltf, m)\n    {\n        this.bounds = new CABLES.CG.BoundingBox();\n        this.meshes = [];\n        this.name = m.name;\n        const prims = m.primitives;\n\n        for (let i = 0; i < prims.length; i++)\n        {\n            const mesh = new gltfMesh(this.name, prims[i], gltf,\n                (mesh) =>\n                {\n                    this.bounds.apply(mesh.bounds);\n                });\n\n            mesh.submeshIndex = i;\n            this.meshes.push(mesh);\n        }\n    }\n\n    render(cgl, ignoreMat, skinRenderer, _time)\n    {\n        for (let i = 0; i < this.meshes.length; i++)\n        {\n            const useMat = gltf.shaders[this.meshes[i].material];\n\n            if (!ignoreMat && useMat) cgl.pushShader(gltf.shaders[this.meshes[i].material]);\n            // console.log(gltf.shaders[this.meshes[i].material],this.meshes[i].material)\n            if (skinRenderer)skinRenderer.renderStart(cgl, _time);\n\n            this.meshes[i].render(cgl, ignoreMat, skinRenderer, _time);\n            if (skinRenderer)skinRenderer.renderFinish(cgl);\n            if (!ignoreMat && useMat) cgl.popShader();\n        }\n    }\n};\n",inc_node_js:'const gltfNode = class\n{\n    constructor(node, gltf)\n    {\n        this.isChild = node.isChild || false;\n        this.name = node.name;\n        if (node.hasOwnProperty("camera")) this.camera = node.camera;\n        this.hidden = false;\n        this.mat = mat4.create();\n        this._animMat = mat4.create();\n        this._tempMat = mat4.create();\n        this._tempQuat = quat.create();\n        this._tempRotmat = mat4.create();\n        this.mesh = null;\n        this.children = [];\n        this._node = node;\n        this._gltf = gltf;\n        this.absMat = mat4.create();\n        this.addTranslate = null;\n        this._tempAnimScale = null;\n        this.addMulMat = null;\n        this.updateMatrix();\n        this._animActions = {};\n        this.skinRenderer = null;\n        this.copies = [];\n    }\n\n    get skin()\n    {\n        if (this._node.hasOwnProperty("skin")) return this._node.skin;\n        else return -1;\n    }\n\n    copy()\n    {\n        this.isCopy = true;\n        const n = new gltfNode(this._node, this._gltf);\n        n.copyOf = this;\n\n        n._animActions = this._animActions;\n        n.children = this.children;\n        n.skinRenderer = new GltfSkin(n);\n\n        this.updateMatrix();\n        return n;\n    }\n\n    hasSkin()\n    {\n        if (this._node.hasOwnProperty("skin")) return this._gltf.json.skins[this._node.skin].name || "unknown";\n        return false;\n    }\n\n    initSkin()\n    {\n        if (this.skin > -1)\n        {\n            this.skinRenderer = new GltfSkin(this);\n        }\n    }\n\n    updateMatrix()\n    {\n        mat4.identity(this.mat);\n        if (this._node.translation) mat4.translate(this.mat, this.mat, this._node.translation);\n\n        if (this._node.rotation)\n        {\n            const rotmat = mat4.create();\n            this._rot = this._node.rotation;\n\n            mat4.fromQuat(rotmat, this._node.rotation);\n            mat4.mul(this.mat, this.mat, rotmat);\n        }\n\n        if (this._node.scale)\n        {\n            this._scale = this._node.scale;\n            mat4.scale(this.mat, this.mat, this._scale);\n        }\n\n        if (this._node.hasOwnProperty("mesh"))\n        {\n            this.mesh = this._gltf.meshes[this._node.mesh];\n            if (this.isCopy)\n            {\n                console.log(this.mesh);\n            }\n        }\n\n        if (this._node.children)\n        {\n            for (let i = 0; i < this._node.children.length; i++)\n            {\n                this._gltf.json.nodes[i].isChild = true;\n                if (this._gltf.nodes[this._node.children[i]]) this._gltf.nodes[this._node.children[i]].isChild = true;\n                this.children.push(this._node.children[i]);\n            }\n        }\n    }\n\n    unHide()\n    {\n        this.hidden = false;\n        for (let i = 0; i < this.children.length; i++)\n            if (this.children[i].unHide) this.children[i].unHide();\n    }\n\n    calcBounds(gltf, mat, bounds)\n    {\n        const localMat = mat4.create();\n\n        if (mat) mat4.copy(localMat, mat);\n        if (this.mat) mat4.mul(localMat, localMat, this.mat);\n\n        if (this.mesh)\n        {\n            const bb = this.mesh.bounds.copy();\n            bb.mulMat4(localMat);\n            bounds.apply(bb);\n\n            if (bounds.changed)\n            {\n                boundingPoints.push(\n                    bb._min[0] || 0, bb._min[1] || 0, bb._min[2] || 0,\n                    bb._max[0] || 0, bb._max[1] || 0, bb._max[2] || 0);\n            }\n        }\n\n        for (let i = 0; i < this.children.length; i++)\n        {\n            if (gltf.nodes[this.children[i]] && gltf.nodes[this.children[i]].calcBounds)\n            {\n                const b = gltf.nodes[this.children[i]].calcBounds(gltf, localMat, bounds);\n\n                bounds.apply(b);\n            }\n        }\n\n        if (bounds.changed) return bounds;\n        else return null;\n    }\n\n    setAnimAction(name)\n    {\n        // console.log("setAnimAction:", name);\n        if (!name) return;\n\n        this._currentAnimaction = name;\n\n        if (name && !this._animActions[name])\n        {\n            // console.log("no action found:", name,this._animActions);\n            return null;\n        }\n\n        // else console.log("YES action found:", name);\n        // console.log(this._animActions);\n\n        for (let path in this._animActions[name])\n        {\n            if (path == "translation") this._animTrans = this._animActions[name][path];\n            else if (path == "rotation") this._animRot = this._animActions[name][path];\n            else if (path == "scale") this._animScale = this._animActions[name][path];\n            else console.warn("unknown anim path", path, this._animActions[name][path]);\n        }\n    }\n\n    setAnim(path, name, anims)\n    {\n        if (!path || !name || !anims) return;\n\n        // console.log("setanim", this._node.name, path, name, anims);\n\n        this._animActions[name] = this._animActions[name] || {};\n\n        // console.log(this._animActions);\n        // debugger;\n\n        // for (let i = 0; i < this.copies.length; i++) this.copies[i]._animActions = this._animActions;\n\n        if (this._animActions[name][path]) op.warn("animation action path already exists", name, path, this._animActions[name][path]);\n\n        this._animActions[name][path] = anims;\n\n        if (path == "translation") this._animTrans = anims;\n        else if (path == "rotation") this._animRot = anims;\n        else if (path == "scale") this._animScale = anims;\n        else console.warn("unknown anim path", path, anims);\n    }\n\n    modelMatLocal()\n    {\n        return this._animMat || this.mat;\n    }\n\n    modelMatAbs()\n    {\n        return this.absMat;\n    }\n\n    transform(cgl, _time)\n    {\n        if (!_time && _time != 0)_time = time;\n\n        this._lastTimeTrans = _time;\n\n        // console.log(this._rot)\n\n        gltfTransforms++;\n\n        if (!this._animTrans && !this._animRot && !this._animScale)\n        {\n            mat4.mul(cgl.mMatrix, cgl.mMatrix, this.mat);\n            this._animMat = null;\n        }\n        else\n        {\n            this._animMat = this._animMat || mat4.create();\n            mat4.identity(this._animMat);\n\n            const playAnims = true;\n\n            if (playAnims && this._animTrans)\n            {\n                mat4.translate(this._animMat, this._animMat, [\n                    this._animTrans[0].getValue(_time),\n                    this._animTrans[1].getValue(_time),\n                    this._animTrans[2].getValue(_time)]);\n            }\n            else\n            if (this._node.translation) mat4.translate(this._animMat, this._animMat, this._node.translation);\n\n            if (playAnims && this._animRot)\n            {\n                if (this._animRot[0].defaultEasing == CABLES.EASING_LINEAR) CABLES.Anim.slerpQuaternion(_time, this._tempQuat, this._animRot[0], this._animRot[1], this._animRot[2], this._animRot[3]);\n                else if (this._animRot[0].defaultEasing == CABLES.EASING_ABSOLUTE)\n                {\n                    this._tempQuat[0] = this._animRot[0].getValue(_time);\n                    this._tempQuat[1] = this._animRot[1].getValue(_time);\n                    this._tempQuat[2] = this._animRot[2].getValue(_time);\n                    this._tempQuat[3] = this._animRot[3].getValue(_time);\n                }\n                else if (this._animRot[0].defaultEasing == CABLES.EASING_CUBICSPLINE)\n                {\n                    CABLES.Anim.slerpQuaternion(_time, this._tempQuat, this._animRot[0], this._animRot[1], this._animRot[2], this._animRot[3]);\n                }\n\n                mat4.fromQuat(this._tempMat, this._tempQuat);\n                mat4.mul(this._animMat, this._animMat, this._tempMat);\n            }\n            else if (this._rot)\n            {\n                // mat4.fromQuat(this._tempRotmat, this._rot);\n                // mat4.mul(this._animMat, this._animMat, this._tempRotmat);\n            }\n\n            if (playAnims && this._animScale)\n            {\n                if (!this._tempAnimScale) this._tempAnimScale = [1, 1, 1];\n                this._tempAnimScale[0] = this._animScale[0].getValue(_time);\n                this._tempAnimScale[1] = this._animScale[1].getValue(_time);\n                this._tempAnimScale[2] = this._animScale[2].getValue(_time);\n                mat4.scale(this._animMat, this._animMat, this._tempAnimScale);\n            }\n            else if (this._scale) mat4.scale(this._animMat, this._animMat, this._scale);\n\n            mat4.mul(cgl.mMatrix, cgl.mMatrix, this._animMat);\n        }\n\n        if (this.addTranslate) mat4.translate(cgl.mMatrix, cgl.mMatrix, this.addTranslate);\n\n        if (this.addMulMat) mat4.mul(cgl.mMatrix, cgl.mMatrix, this.addMulMat);\n\n        mat4.copy(this.absMat, cgl.mMatrix);\n    }\n\n    render(cgl, dontTransform, dontDrawMesh, ignoreMaterial, ignoreChilds, drawHidden, _time)\n    {\n        if (!dontTransform) cgl.pushModelMatrix();\n\n        if (_time === undefined) _time = gltf.time;\n\n        if (!dontTransform || this.skinRenderer) this.transform(cgl, _time);\n\n        if (this.hidden && !drawHidden)\n        {\n        }\n        else\n        {\n            if (this.skinRenderer)\n            {\n                this.skinRenderer.time = _time;\n                if (!dontDrawMesh)\n                    this.mesh.render(cgl, ignoreMaterial, this.skinRenderer, _time);\n            }\n            else\n            {\n                if (this.mesh && !dontDrawMesh)\n                    this.mesh.render(cgl, ignoreMaterial, null, _time);\n            }\n        }\n\n        if (!ignoreChilds && !this.hidden)\n            for (let i = 0; i < this.children.length; i++)\n                if (gltf.nodes[this.children[i]])\n                    gltf.nodes[this.children[i]].render(cgl, dontTransform, dontDrawMesh, ignoreMaterial, ignoreChilds, drawHidden, _time);\n\n        if (!dontTransform)cgl.popModelMatrix();\n    }\n};\n',inc_print_js:'let tab = null;\n\nfunction closeTab()\n{\n    if (tab)gui.mainTabs.closeTab(tab.id);\n    tab = null;\n}\n\nfunction formatVec(arr)\n{\n    const nums = [];\n    for (let i = 0; i < arr.length; i++)\n    {\n        nums.push(Math.round(arr[i] * 1000) / 1000);\n    }\n\n    return nums.join(",");\n}\n\nfunction printNode(html, node, level)\n{\n    if (!gltf) return;\n\n    html += "<tr class=\\"row\\">";\n\n    let ident = "";\n    let identSpace = "";\n\n    for (let i = 1; i < level; i++)\n    {\n        identSpace += "&nbsp;&nbsp;&nbsp;";\n        let identClass = "identBg";\n        if (i == 1)identClass = "identBgLevel0";\n        ident += "<td class=\\"ident " + identClass + "\\" ><div style=\\"\\"></div></td>";\n    }\n    let id = CABLES.uuid();\n    html += ident;\n    html += "<td colspan=\\"" + (21 - level) + "\\">";\n\n    if (node.mesh && node.mesh.meshes.length)html += "<span class=\\"icon icon-cube\\"></span>&nbsp;";\n    else html += "<span class=\\"icon icon-box-select\\"></span> &nbsp;";\n\n    html += node.name + "</td><td></td>";\n\n    if (node.mesh)\n    {\n        html += "<td>";\n        for (let i = 0; i < node.mesh.meshes.length; i++)\n        {\n            if (i > 0)html += ", ";\n            html += node.mesh.meshes[i].name;\n        }\n\n        html += "</td>";\n\n        html += "<td>";\n        html += node.hasSkin() || "-";\n        html += "</td>";\n\n        html += "<td>";\n        let countMats = 0;\n        for (let i = 0; i < node.mesh.meshes.length; i++)\n        {\n            if (countMats > 0)html += ", ";\n            if (gltf.json.materials && node.mesh.meshes[i].hasOwnProperty("material"))\n            {\n                if (gltf.json.materials[node.mesh.meshes[i].material])\n                {\n                    html += gltf.json.materials[node.mesh.meshes[i].material].name;\n                    countMats++;\n                }\n            }\n        }\n        if (countMats == 0)html += "none";\n        html += "</td>";\n    }\n    else\n    {\n        html += "<td>-</td><td>-</td><td>-</td>";\n    }\n\n    html += "<td>";\n\n    if (node._node.translation || node._node.rotation || node._node.scale)\n    {\n        let info = "";\n\n        if (node._node.translation)info += "Translate: `" + formatVec(node._node.translation) + "` || ";\n        if (node._node.rotation)info += "Rotation: `" + formatVec(node._node.rotation) + "` || ";\n        if (node._node.scale)info += "Scale: `" + formatVec(node._node.scale) + "` || ";\n\n        html += "<span class=\\"icon icon-gizmo info\\" data-info=\\"" + info + "\\"></span> &nbsp;";\n    }\n\n    if (node._animRot || node._animScale || node._animTrans)\n    {\n        let info = "Animated: ";\n        if (node._animRot) info += "Rot ";\n        if (node._animScale) info += "Scale ";\n        if (node._animTrans) info += "Trans ";\n\n        html += "<span class=\\"icon icon-clock info\\" data-info=\\"" + info + "\\"></span>&nbsp;";\n    }\n\n    if (!node._node.translation && !node._node.rotation && !node._node.scale && !node._animRot && !node._animScale && !node._animTrans) html += "-";\n\n    html += "</td>";\n\n    html += "<td>";\n    let hideclass = "";\n    if (node.hidden)hideclass = "node-hidden";\n\n    // html+=\'\';\n    html += "<a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').exposeNode(\'" + node.name + "\',\'transform\')\\" class=\\"treebutton\\">Transform</a>";\n    html += " <a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').exposeNode(\'" + node.name + "\',\'hierarchy\')\\" class=\\"treebutton\\">Hierarchy</a>";\n    html += " <a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').exposeNode(\'" + node.name + "\')\\" class=\\"treebutton\\">Node</a>";\n\n    if (node.hasSkin())\n        html += " <a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').exposeNode(\'" + node.name + "\',false,{skin:true});\\" class=\\"treebutton\\">Skin</a>";\n\n    html += "</td><td>";\n    html += "&nbsp;<span class=\\"icon iconhover icon-eye " + hideclass + "\\" onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').toggleNodeVisibility(\'" + node.name + "\');this.classList.toggle(\'node-hidden\');\\"></span>";\n    html += "</td>";\n\n    html += "</tr>";\n\n    if (node.children)\n    {\n        for (let i = 0; i < node.children.length; i++)\n            html = printNode(html, gltf.nodes[node.children[i]], level + 1);\n    }\n\n    return html;\n}\n\nfunction printMaterial(mat, idx)\n{\n    let html = "<tr>";\n    html += " <td>" + idx + "</td>";\n    html += " <td>" + mat.name + "</td>";\n    // html+=\' <td><a onclick="" class="treebutton">Assign</a><td>\';\n\n    html += " <td>";\n\n    const info = JSON.stringify(mat, null, 4).replaceAll("\\"", "").replaceAll("\\n", "<br/>");\n\n    html += "<span class=\\"icon icon-info\\" onclick=\\"new CABLES.UI.ModalDialog({ \'html\': \'<pre>" + info + "</pre>\', \'title\': \'" + mat.name + "\' });\\"></span>&nbsp;";\n\n    if (mat.pbrMetallicRoughness && mat.pbrMetallicRoughness.baseColorFactor)\n    {\n        let rgb = "";\n        rgb += "" + Math.round(mat.pbrMetallicRoughness.baseColorFactor[0] * 255);\n        rgb += "," + Math.round(mat.pbrMetallicRoughness.baseColorFactor[1] * 255);\n        rgb += "," + Math.round(mat.pbrMetallicRoughness.baseColorFactor[2] * 255);\n\n        html += "<div style=\\"width:15px;height:15px;background-color:rgb(" + rgb + ");display:inline-block\\">&nbsp;</a>";\n    }\n    html += " <td style=\\"\\">" + (gltf.shaders[idx] ? "-" : "<a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').assignMaterial(\'" + mat.name + "\')\\" class=\\"treebutton\\">Assign</a>") + "<td>";\n    html += "<td>";\n\n    html += "</tr>";\n    return html;\n}\n\nfunction printInfo()\n{\n    if (!gltf) return;\n\n    const startTime = performance.now();\n    const sizes = {};\n    let html = "<div style=\\"overflow:scroll;width:100%;height:100%\\">";\n\n    html += "File: <a href=\\"" + CABLES.platform.getCablesUrl() + "/asset/patches/?filename=" + inFile.get() + "\\" target=\\"_blank\\">" + CABLES.basename(inFile.get()) + "</a><br/>";\n\n    html += "Generator:" + gltf.json.asset.generator;\n\n    let numNodes = 0;\n    if (gltf.json.nodes)numNodes = gltf.json.nodes.length;\n    html += "<div id=\\"groupNodes\\">Nodes (" + numNodes + ")</div>";\n\n    html += "<table id=\\"sectionNodes\\" class=\\"table treetable\\">";\n\n    html += "<tr>";\n    html += " <th colspan=\\"21\\">Name</th>";\n    html += " <th>Mesh</th>";\n    html += " <th>Skin</th>";\n    html += " <th>Material</th>";\n    html += " <th>Transform</th>";\n    html += " <th>Expose</th>";\n    html += " <th></th>";\n    html += "</tr>";\n\n    for (let i = 0; i < gltf.nodes.length; i++)\n    {\n        if (!gltf.nodes[i].isChild)\n            html = printNode(html, gltf.nodes[i], 1);\n    }\n    html += "</table>";\n\n    // / //////////////////\n\n    let numMaterials = 0;\n    if (gltf.json.materials)numMaterials = gltf.json.materials.length;\n    html += "<div id=\\"groupMaterials\\">Materials (" + numMaterials + ")</div>";\n\n    if (!gltf.json.materials || gltf.json.materials.length == 0)\n    {\n    }\n    else\n    {\n        html += "<table id=\\"materialtable\\"  class=\\"table treetable\\">";\n        html += "<tr>";\n        html += " <th>Index</th>";\n        html += " <th>Name</th>";\n        html += " <th>Color</th>";\n        html += " <th>Function</th>";\n        html += " <th></th>";\n        html += "</tr>";\n        for (let i = 0; i < gltf.json.materials.length; i++)\n        {\n            html += printMaterial(gltf.json.materials[i], i);\n        }\n        html += "</table>";\n    }\n\n    // / ///////////////////////\n\n    html += "<div id=\\"groupMeshes\\">Meshes (" + gltf.json.meshes.length + ")</div>";\n\n    html += "<table id=\\"meshestable\\"  class=\\"table treetable\\">";\n    html += "<tr>";\n    html += " <th>Name</th>";\n    html += " <th>Node</th>";\n    html += " <th>Material</th>";\n    html += " <th>Vertices</th>";\n    html += " <th>Attributes</th>";\n    html += "</tr>";\n\n    let sizeBufferViews = [];\n    sizes.meshes = 0;\n\n    for (let i = 0; i < gltf.json.meshes.length; i++)\n    {\n        html += "<tr>";\n        html += "<td>" + gltf.json.meshes[i].name + "</td>";\n\n        html += "<td>";\n        let count = 0;\n        let nodename = "";\n        for (var j = 0; j < gltf.json.nodes.length; j++)\n        {\n            if (gltf.json.nodes[j].mesh == i)\n            {\n                count++;\n                if (count == 1)\n                {\n                    nodename = gltf.json.nodes[j].name;\n                }\n            }\n        }\n        if (count > 1) html += (count) + " nodes (" + nodename + " ...)";\n        else html += nodename;\n        html += "</td>";\n\n        // -------\n\n        html += "<td>";\n        for (var j = 0; j < gltf.json.meshes[i].primitives.length; j++)\n        {\n            if (gltf.json.meshes[i].primitives[j].hasOwnProperty("material"))\n            {\n                if (gltf.json.materials[gltf.json.meshes[i]])\n                {\n                    html += gltf.json.materials[gltf.json.meshes[i].primitives[j].material].name + " ";\n                }\n            }\n            else html += "None";\n        }\n        html += "</td>";\n\n        html += "<td>";\n        let numVerts = 0;\n        for (var j = 0; j < gltf.json.meshes[i].primitives.length; j++)\n        {\n            if (gltf.json.meshes[i].primitives[j].attributes.POSITION != undefined)\n            {\n                let v = parseInt(gltf.json.accessors[gltf.json.meshes[i].primitives[j].attributes.POSITION].count);\n                numVerts += v;\n                html += "" + v + "<br/>";\n            }\n            else html += "-<br/>";\n        }\n\n        if (gltf.json.meshes[i].primitives.length > 0)\n            html += "=" + numVerts;\n        html += "</td>";\n\n        html += "<td style=\\"vertical-align:top;\\">";\n        for (let j = 0; j < gltf.json.meshes[i].primitives.length; j++)\n        {\n            html += Object.keys(gltf.json.meshes[i].primitives[j].attributes);\n            html += " <a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').exposeGeom(\'" + gltf.json.meshes[i].name + "\'," + j + ")\\" class=\\"treebutton\\">Geometry</a>";\n            html += "<br/>";\n        }\n        html += "</td>";\n        html += "</tr>";\n\n        for (let j = 0; j < gltf.json.meshes[i].primitives.length; j++)\n        {\n            const accessor = gltf.json.accessors[gltf.json.meshes[i].primitives[j].indices];\n            if (accessor)\n            {\n                let bufView = accessor.bufferView;\n\n                if (sizeBufferViews.indexOf(bufView) == -1)\n                {\n                    sizeBufferViews.push(bufView);\n                    if (gltf.json.bufferViews[bufView])sizes.meshes += gltf.json.bufferViews[bufView].byteLength;\n                }\n            }\n\n            for (let k in gltf.json.meshes[i].primitives[j].attributes)\n            {\n                const attr = gltf.json.meshes[i].primitives[j].attributes[k];\n                const bufView2 = gltf.json.accessors[attr].bufferView;\n\n                if (sizeBufferViews.indexOf(bufView2) == -1)\n                {\n                    sizeBufferViews.push(bufView2);\n                    if (gltf.json.bufferViews[bufView2])sizes.meshes += gltf.json.bufferViews[bufView2].byteLength;\n                }\n            }\n        }\n    }\n    html += "</table>";\n\n    // / //////////////////////////////////\n\n    let numSamplers = 0;\n    let numAnims = 0;\n\n    if (gltf.json.animations)\n    {\n        numAnims = gltf.json.animations.length;\n        for (let i = 0; i < gltf.json.animations.length; i++)\n            numSamplers += gltf.json.animations[i].samplers.length;\n    }\n\n    html += "<div id=\\"groupAnims\\">Animations (" + numAnims + "/" + numSamplers + ")</div>";\n\n    if (gltf.json.animations)\n    {\n        html += "<table id=\\"sectionAnim\\" class=\\"table treetable\\">";\n        html += "<tr>";\n        html += "  <th>Name</th>";\n        html += "  <th>Target node</th>";\n        html += "  <th>Path</th>";\n        html += "  <th>Interpolation</th>";\n        html += "  <th>Keys</th>";\n        html += "</tr>";\n\n        sizes.animations = 0;\n\n        for (let i = 0; i < gltf.json.animations.length; i++)\n        {\n            for (let j = 0; j < gltf.json.animations[i].samplers.length; j++)\n            {\n                let bufView = gltf.json.accessors[gltf.json.animations[i].samplers[j].input].bufferView;\n                if (sizeBufferViews.indexOf(bufView) == -1)\n                {\n                    sizeBufferViews.push(bufView);\n                    sizes.animations += gltf.json.bufferViews[bufView].byteLength;\n                }\n\n                bufView = gltf.json.accessors[gltf.json.animations[i].samplers[j].output].bufferView;\n                if (sizeBufferViews.indexOf(bufView) == -1)\n                {\n                    sizeBufferViews.push(bufView);\n                    sizes.animations += gltf.json.bufferViews[bufView].byteLength;\n                }\n            }\n\n            for (let j = 0; j < gltf.json.animations[i].channels.length; j++)\n            {\n                html += "<tr>";\n                html += "  <td> Anim " + i + ": " + gltf.json.animations[i].name + "</td>";\n\n                html += "  <td>" + gltf.nodes[gltf.json.animations[i].channels[j].target.node].name + "</td>";\n                html += "  <td>";\n                html += gltf.json.animations[i].channels[j].target.path + " ";\n                html += "  </td>";\n\n                const smplidx = gltf.json.animations[i].channels[j].sampler;\n                const smplr = gltf.json.animations[i].samplers[smplidx];\n\n                html += "  <td>" + smplr.interpolation + "</td>";\n\n                html += "  <td>" + gltf.json.accessors[smplr.output].count;\n\n                // html += "&nbsp;&nbsp;<a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').showAnim(\'" + i + "\',\'" + j + "\')\\" class=\\"icon icon-search\\"></a>";\n\n                html += "</td>";\n\n                html += "</tr>";\n            }\n        }\n        html += "</table>";\n    }\n    else\n    {\n\n    }\n\n    // / ///////////////////\n\n    let numImages = 0;\n    if (gltf.json.images)numImages = gltf.json.images.length;\n    html += "<div id=\\"groupImages\\">Images (" + numImages + ")</div>";\n\n    if (gltf.json.images)\n    {\n        html += "<table id=\\"sectionImages\\" class=\\"table treetable\\">";\n\n        html += "<tr>";\n        html += "  <th>name</th>";\n        html += "  <th>type</th>";\n        html += "  <th>func</th>";\n\n        html += "</tr>";\n\n        sizes.images = 0;\n\n        for (let i = 0; i < gltf.json.images.length; i++)\n        {\n            if (gltf.json.images[i].bufferView)\n                sizes.images += gltf.json.bufferViews[gltf.json.images[i].bufferView].byteLength;\n\n            html += "<tr>";\n            html += "<td>" + gltf.json.images[i].name + "</td>";\n            html += "<td>" + gltf.json.images[i].mimeType + "</td>";\n            html += "<td>";\n\n            let name = gltf.json.images[i].name;\n            if (name === undefined)name = gltf.json.images[i].bufferView;\n\n            html += "<a onclick=\\"gui.corePatch().getOpById(\'" + op.id + "\').exposeTexture(\'" + name + "\')\\" class=\\"treebutton\\">Expose</a>";\n            html += "</td>";\n\n            html += "<tr>";\n        }\n        html += "</table>";\n    }\n\n    // / ///////////////////////\n\n    let numCameras = 0;\n    if (gltf.json.cameras)numCameras = gltf.json.cameras.length;\n    html += "<div id=\\"groupCameras\\">Cameras (" + numCameras + ")</div>";\n\n    if (gltf.json.cameras)\n    {\n        html += "<table id=\\"sectionCameras\\" class=\\"table treetable\\">";\n\n        html += "<tr>";\n        html += "  <th>name</th>";\n        html += "  <th>type</th>";\n        html += "  <th>info</th>";\n        html += "</tr>";\n\n        for (let i = 0; i < gltf.json.cameras.length; i++)\n        {\n            html += "<tr>";\n            html += "<td>" + gltf.json.cameras[i].name + "</td>";\n            html += "<td>" + gltf.json.cameras[i].type + "</td>";\n            html += "<td>";\n\n            if (gltf.json.cameras[i].perspective)\n            {\n                html += "yfov: " + Math.round(gltf.json.cameras[i].perspective.yfov * 100) / 100;\n                html += ", ";\n                html += "zfar: " + Math.round(gltf.json.cameras[i].perspective.zfar * 100) / 100;\n                html += ", ";\n                html += "znear: " + Math.round(gltf.json.cameras[i].perspective.znear * 100) / 100;\n            }\n            html += "</td>";\n\n            html += "<tr>";\n        }\n        html += "</table>";\n    }\n\n    // / ////////////////////////////////////\n\n    let numSkins = 0;\n    if (gltf.json.skins)numSkins = gltf.json.skins.length;\n    html += "<div id=\\"groupSkins\\">Skins (" + numSkins + ")</div>";\n\n    if (gltf.json.skins)\n    {\n        // html += "<h3>Skins (" + gltf.json.skins.length + ")</h3>";\n        html += "<table id=\\"sectionSkins\\" class=\\"table treetable\\">";\n\n        html += "<tr>";\n        html += "  <th>name</th>";\n        html += "  <th></th>";\n        html += "  <th>total joints</th>";\n        html += "</tr>";\n\n        for (let i = 0; i < gltf.json.skins.length; i++)\n        {\n            html += "<tr>";\n            html += "<td>" + gltf.json.skins[i].name + "</td>";\n            html += "<td>" + "</td>";\n            html += "<td>" + gltf.json.skins[i].joints.length + "</td>";\n            html += "<td>";\n            html += "</td>";\n            html += "<tr>";\n        }\n        html += "</table>";\n    }\n\n    // / ////////////////////////////////////\n\n    if (gltf.timing)\n    {\n        html += "<div id=\\"groupTiming\\">Debug Loading Timing </div>";\n\n        html += "<table id=\\"sectionTiming\\" class=\\"table treetable\\">";\n\n        html += "<tr>";\n        html += "  <th>task</th>";\n        html += "  <th>time used</th>";\n        html += "</tr>";\n\n        let lt = 0;\n        for (let i = 0; i < gltf.timing.length - 1; i++)\n        {\n            html += "<tr>";\n            html += "  <td>" + gltf.timing[i][0] + "</td>";\n            html += "  <td>" + (gltf.timing[i + 1][1] - gltf.timing[i][1]) + " ms</td>";\n            html += "</tr>";\n            // lt = gltf.timing[i][1];\n        }\n        html += "</table>";\n    }\n\n    // / //////////////////////////\n\n    let sizeBin = 0;\n    if (gltf.json.buffers)\n        sizeBin = gltf.json.buffers[0].byteLength;\n\n    html += "<div id=\\"groupBinary\\">File Size Allocation (" + Math.round(sizeBin / 1024) + "k )</div>";\n\n    html += "<table id=\\"sectionBinary\\" class=\\"table treetable\\">";\n    html += "<tr>";\n    html += "  <th>name</th>";\n    html += "  <th>size</th>";\n    html += "  <th>%</th>";\n    html += "</tr>";\n    let sizeUnknown = sizeBin;\n    for (let i in sizes)\n    {\n        // html+=i+\':\'+Math.round(sizes[i]/1024);\n        html += "<tr>";\n        html += "<td>" + i + "</td>";\n        html += "<td>" + readableSize(sizes[i]) + " </td>";\n        html += "<td>" + Math.round(sizes[i] / sizeBin * 100) + "% </td>";\n        html += "<tr>";\n        sizeUnknown -= sizes[i];\n    }\n\n    if (sizeUnknown != 0)\n    {\n        html += "<tr>";\n        html += "<td>unknown</td>";\n        html += "<td>" + readableSize(sizeUnknown) + " </td>";\n        html += "<td>" + Math.round(sizeUnknown / sizeBin * 100) + "% </td>";\n        html += "<tr>";\n    }\n\n    html += "</table>";\n    html += "</div>";\n\n    tab = new CABLES.UI.Tab("GLTF " + CABLES.basename(inFile.get()), { "icon": "cube", "infotext": "tab_gltf", "padding": true, "singleton": true });\n    gui.mainTabs.addTab(tab, true);\n\n    tab.addEventListener("close", closeTab);\n    tab.html(html);\n\n    CABLES.UI.Collapsable.setup(ele.byId("groupNodes"), ele.byId("sectionNodes"), false);\n    CABLES.UI.Collapsable.setup(ele.byId("groupMaterials"), ele.byId("materialtable"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupAnims"), ele.byId("sectionAnim"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupMeshes"), ele.byId("meshestable"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupCameras"), ele.byId("sectionCameras"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupImages"), ele.byId("sectionImages"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupSkins"), ele.byId("sectionSkins"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupBinary"), ele.byId("sectionBinary"), true);\n    CABLES.UI.Collapsable.setup(ele.byId("groupTiming"), ele.byId("sectionTiming"), true);\n\n    gui.maintabPanel.show(true);\n}\n\nfunction readableSize(n)\n{\n    if (n > 1024) return Math.round(n / 1024) + " kb";\n    if (n > 1024 * 500) return Math.round(n / 1024) + " mb";\n    else return n + " bytes";\n}\n',inc_skin_js:'const GltfSkin = class\n{\n    constructor(node)\n    {\n        this._mod = null;\n        this._node = node;\n        this._lastTime = 0;\n        this._matArr = [];\n        this._m = mat4.create();\n        this._invBindMatrix = mat4.create();\n        this.identity = true;\n    }\n\n    renderFinish(cgl)\n    {\n        cgl.popModelMatrix();\n        this._mod.unbind();\n    }\n\n    renderStart(cgl, time)\n    {\n        if (!this._mod)\n        {\n            this._mod = new CGL.ShaderModifier(cgl, op.name + this._node.name);\n\n            this._mod.addModule({\n                "priority": -2,\n                "name": "MODULE_VERTEX_POSITION",\n                "srcHeadVert": attachments.skin_head_vert || "",\n                "srcBodyVert": attachments.skin_vert || ""\n            });\n\n            this._mod.addUniformVert("m4[]", "MOD_boneMats", []);// bohnenmatze\n            const tr = vec3.create();\n        }\n\n        const skinIdx = this._node.skin;\n        const arrLength = gltf.json.skins[skinIdx].joints.length * 16;\n\n        // if (this._lastTime != time || !time)\n        {\n            // this._lastTime=inTime.get();\n            if (this._matArr.length != arrLength) this._matArr.length = arrLength;\n\n            for (let i = 0; i < gltf.json.skins[skinIdx].joints.length; i++)\n            {\n                const i16 = i * 16;\n                const jointIdx = gltf.json.skins[skinIdx].joints[i];\n                const nodeJoint = gltf.nodes[jointIdx];\n\n                for (let j = 0; j < 16; j++)\n                    this._invBindMatrix[j] = gltf.accBuffers[gltf.json.skins[skinIdx].inverseBindMatrices][i16 + j];\n\n                mat4.mul(this._m, nodeJoint.modelMatAbs(), this._invBindMatrix);\n\n                for (let j = 0; j < this._m.length; j++) this._matArr[i16 + j] = this._m[j];\n            }\n\n            this._mod.setUniformValue("MOD_boneMats", this._matArr);\n            this._lastTime = time;\n        }\n\n        this._mod.define("SKIN_NUM_BONES", gltf.json.skins[skinIdx].joints.length);\n        this._mod.bind();\n\n        // draw mesh...\n        cgl.pushModelMatrix();\n        if (this.identity)mat4.identity(cgl.mMatrix);\n    }\n};\n',skin_vert:"int index=int(attrJoints.x);\nvec4 newPos = (MOD_boneMats[index] * pos) * attrWeights.x;\nvec3 newNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.x).xyz);\n\nindex=int(attrJoints.y);\nnewPos += (MOD_boneMats[index] * pos) * attrWeights.y;\nnewNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.y).xyz)+newNorm;\n\nindex=int(attrJoints.z);\nnewPos += (MOD_boneMats[index] * pos) * attrWeights.z;\nnewNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.z).xyz)+newNorm;\n\nindex=int(attrJoints.w);\nnewPos += (MOD_boneMats[index] * pos) * attrWeights.w ;\nnewNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.w).xyz)+newNorm;\n\npos=newPos;\n\nnorm=normalize(newNorm.xyz);\n\n\n",skin_head_vert:"\nIN vec4 attrWeights;\nIN vec4 attrJoints;\nUNI mat4 MOD_boneMats[SKIN_NUM_BONES];\n"};const a=class{constructor(e,t){this.node=t;this.name=t.name;this.config=e.json.cameras[t.camera];this.pos=vec3.create();this.quat=quat.create();this.vCenter=vec3.create();this.vUp=vec3.create();this.vMat=mat4.create()}updateAnim(e){if(this.node&&this.node._animTrans){vec3.set(this.pos,this.node._animTrans[0].getValue(e),this.node._animTrans[1].getValue(e),this.node._animTrans[2].getValue(e));quat.set(this.quat,this.node._animRot[0].getValue(e),this.node._animRot[1].getValue(e),this.node._animRot[2].getValue(e),this.node._animRot[3].getValue(e))}}start(e){if(p.frameStore.shadowPass)return;this.updateAnim(e);const t=p.getViewPort()[2]/p.getViewPort()[3];p.pushPMatrix();p.pushViewMatrix();let n=mat4.create();mat4.invert(n,this.node.modelMatAbs());this.vMat=n;mat4.identity(p.vMatrix);mat4.mul(p.vMatrix,p.vMatrix,n)}end(){if(p.frameStore.shadowPass)return;p.popPMatrix();p.popViewMatrix()}};const k=8;const B=class{constructor(){this.json={};this.accBuffers=[];this.meshes=[];this.nodes=[];this.shaders=[];this.timing=[];this.cams=[];this.startTime=performance.now();this.bounds=new CABLES.CG.BoundingBox;this.loaded=Date.now();this.accBuffersDelete=[]}getNode(t){for(let e=0;e<this.nodes.length;e++){if(this.nodes[e].name==t)return this.nodes[e]}}unHideAll(){for(let e=0;e<this.nodes.length;e++){this.nodes[e].unHide()}}};function O(e){if(window.TextDecoder)return new TextDecoder("utf-8").decode(e);let t,n,a,i;let r,o;t="";a=e.length;n=0;while(n<a){i=e[n++];switch(i>>4){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:t+=String.fromCharCode(i);break;case 12:case 13:r=e[n++];t+=String.fromCharCode((i&31)<<6|r&63);break;case 14:r=e[n++];o=e[n++];t+=String.fromCharCode((i&15)<<12|(r&63)<<6|(o&63)<<0);break}}return t}function A(e,t,n,a){const i={};if(a>=e.byteLength){_.log("could not read chunk...");return}i.size=e.getUint32(a+0,S);i.type=O(t.subarray(a+4,a+4+4));if(i.type=="BIN\0"){i.dataView=new DataView(n,a+8,i.size)}else if(i.type=="JSON"){const r=O(t.subarray(a+8,a+8+i.size));try{const o=JSON.parse(r);i.data=o;re.set(o.asset.generator)}catch(e){}}else{_.warn("unknown type",i.type)}return i}function D(t){const a={};for(let e=0;e<t.json.animations.length;e++){const i=t.json.animations[e];for(let e=0;e<i.channels.length;e++){const r=i.channels[e];const o=t.nodes[r.target.node];const s=i.samplers[r.sampler];const n=t.json.accessors[s.input];const l=t.accBuffers[s.input];const u=t.json.accessors[s.output];const m=t.accBuffers[s.output];t.accBuffersDelete.push(s.output,s.input);if(l&&m){let n=1;if(u.type=="VEC2")n=2;else if(u.type=="VEC3")n=3;else if(u.type=="VEC4")n=4;else _.warn("unknown accOut.type",u.type);const c=[];a[i.name]=true;for(let e=0;e<n;e++){const d=new CABLES.Anim;c.push(d)}if(s.interpolation==="LINEAR"){}else if(s.interpolation==="STEP")for(let e=0;e<n;e++)c[e].defaultEasing=CABLES.EASING_ABSOLUTE;else if(s.interpolation==="CUBICSPLINE")for(let e=0;e<n;e++)c[e].defaultEasing=CABLES.EASING_CUBICSPLINE;else _.warn("unknown interpolation",s.interpolation);if(l[0]!==0)for(let e=0;e<n;e++)c[e].setValue(0,m[0*n+e]);for(let t=0;t<l.length;t++){y=Math.max(l[t],y);for(let e=0;e<n;e++){if(c[e].defaultEasing===CABLES.EASING_CUBICSPLINE){const h=t*n*3+e;const f=c[e].setValue(l[t],m[h+n]);f.bezTangIn=m[h];f.bezTangOut=m[h+n*2]}else{c[e].setValue(l[t],m[t*n+e])}}}o.setAnim(r.target.path,i.name,c)}else{_.warn("loadAmins bufferIn undefined ",l===undefined);_.warn("loadAmins bufferOut undefined ",m===undefined);_.warn("loadAmins ",s,u);_.warn("loadAmins num accBuffers",t.accBuffers.length);_.warn("loadAmins num accessors",t.json.accessors.length)}}}t.uniqueAnimNames=a;ce.setRef(Object.keys(a))}function G(n){if(!n||!n.json.cameras)return;n.cameras=n.cameras||[];for(let t=0;t<n.nodes.length;t++){if(n.nodes[t].hasOwnProperty("camera")){const e=new a(n,n.nodes[t]);n.cameras.push(e)}}}function U(){if(!window.DracoDecoder){setTimeout(()=>{U()},100)}L()}function F(e){let i=0,t=0;const r=new B;r.timing.push(["Start parsing",Math.round(performance.now()-r.startTime)]);if(!e)return;const n=new Uint8Array(e);let a=0;const o=O(n.subarray(a,4));a+=4;if(o!="glTF")return;r.timing.push(["dataview",Math.round(performance.now()-r.startTime)]);const s=new DataView(e);const l=s.getUint32(a,S);a+=4;const u=s.getUint32(a,S);a+=4;oe.set(l);const m=[];r.chunks=m;m.push(A(s,n,e,a));a+=m[0].size+k;r.json=m[0].data;r.cables={fileUrl:T.get(),shortFileName:CABLES.basename(T.get())};me.set(r.json);se.set(r.json.extensionsUsed||[]);let c=A(s,n,e,a);while(c){m.push(c);a+=c.size+k;c=A(s,n,e,a)}r.chunks=m;const d=m[0].data.bufferViews;const h=m[0].data.accessors;r.timing.push(["Parse buffers",Math.round(performance.now()-r.startTime)]);if(r.json.extensionsUsed&&r.json.extensionsUsed.indexOf("KHR_draco_mesh_compression")>-1){if(!window.DracoDecoder){_.setUiError("gltfdraco","GLTF draco compression lib not found / add draco op to your patch!");U();return r}else{r.useDraco=true}}_.setUiError("gltfdraco",null);if(d){for(t=0;t<h.length;t++){const f=h[t];const p=d[f.bufferView];let a=0;if(f.type=="SCALAR")a=1;else if(f.type=="VEC2")a=2;else if(f.type=="VEC3")a=3;else if(f.type=="VEC4")a=4;else if(f.type=="MAT4")a=16;else console.error("unknown accessor type",f.type);if(m[1].dataView){if(p){const g=f.count*a;let e=(p.byteOffset||0)+(f.byteOffset||0);let t=p.byteStride||0;let n=null;if(f.componentType==5126||f.componentType==5125){t=t||4;const v=f.componentType==5125;if(v)n=new Uint32Array(g);else n=new Float32Array(g);for(i=0;i<g;i++){if(v)n[i]=m[1].dataView.getUint32(e,S);else n[i]=m[1].dataView.getFloat32(e,S);if(t!=4&&(i+1)%a===0)e+=t-a*4;e+=4}}else if(f.componentType==5123){t=t||2;n=new Uint16Array(g);for(i=0;i<g;i++){n[i]=m[1].dataView.getUint16(e,S);if(t!=2&&(i+1)%a===0)e+=t-a*2;e+=2}}else if(f.componentType==5121){t=t||1;n=new Uint8Array(g);for(i=0;i<g;i++){n[i]=m[1].dataView.getUint8(e,S);if(t!=1&&(i+1)%a===0)e+=t-a*1;e+=1}}else{console.error("unknown component type",f.componentType)}r.accBuffers.push(n)}else{}}}}r.timing.push(["Parse mesh groups",Math.round(performance.now()-r.startTime)]);r.json.meshes=r.json.meshes||[];if(r.json.meshes){for(t=0;t<r.json.meshes.length;t++){const b=new z(r,r.json.meshes[t]);r.meshes.push(b)}}r.timing.push(["Parse nodes",Math.round(performance.now()-r.startTime)]);for(t=0;t<r.json.nodes.length;t++){if(r.json.nodes[t].children)for(i=0;i<r.json.nodes[t].children.length;i++){r.json.nodes[r.json.nodes[t].children[i]].isChild=true}}for(t=0;t<r.json.nodes.length;t++){const x=new X(r.json.nodes[t],r);r.nodes.push(x)}for(t=0;t<r.nodes.length;t++){const x=r.nodes[t];if(!x.children)continue;for(let e=0;e<x.children.length;e++){r.nodes[x.children[e]].parent=x}}for(t=0;t<r.nodes.length;t++){r.nodes[t].initSkin()}M=true;r.timing.push(["load anims",Math.round(performance.now()-r.startTime)]);if(r.json.animations)D(r);r.timing.push(["load cameras",Math.round(performance.now()-r.startTime)]);if(r.json.cameras)G(r);r.timing.push(["finished",Math.round(performance.now()-r.startTime)]);return r}let V=class{constructor(e,n,r,o){this.POINTS=0;this.LINES=1;this.LINE_LOOP=2;this.LINE_STRIP=3;this.TRIANGLES=4;this.TRIANGLE_STRIP=5;this.TRIANGLE_FAN=6;this.test=0;this.name=e;this.submeshIndex=0;this.material=n.material;this.mesh=null;this.geom=new CGL.Geometry("gltf_"+this.name);this.geom.verticesIndices=[];this.bounds=null;this.primitive=4;if(n.hasOwnProperty("mode"))this.primitive=n.mode;if(n.hasOwnProperty("indices"))this.geom.verticesIndices=r.accBuffers[n.indices];r.loadingMeshes=r.loadingMeshes||0;r.loadingMeshes++;this.materialJson=this._matPbrMetalness=this._matPbrRoughness=this._matDiffuseColor=null;if(r.json.materials){if(this.material!=-1)this.materialJson=r.json.materials[this.material];if(this.materialJson&&this.materialJson.pbrMetallicRoughness){if(!this.materialJson.pbrMetallicRoughness.hasOwnProperty("baseColorFactor")){this._matDiffuseColor=[1,1,1,1]}else{this._matDiffuseColor=this.materialJson.pbrMetallicRoughness.baseColorFactor}this._matDiffuseColor=this.materialJson.pbrMetallicRoughness.baseColorFactor;if(!this.materialJson.pbrMetallicRoughness.hasOwnProperty("metallicFactor")){this._matPbrMetalness=1}else{this._matPbrMetalness=this.materialJson.pbrMetallicRoughness.metallicFactor||null}if(!this.materialJson.pbrMetallicRoughness.hasOwnProperty("roughnessFactor")){this._matPbrRoughness=1}else{this._matPbrRoughness=this.materialJson.pbrMetallicRoughness.roughnessFactor||null}}}if(r.useDraco&&n.extensions.KHR_draco_mesh_compression){const a=r.chunks[0].data.bufferViews[n.extensions.KHR_draco_mesh_compression.bufferView];const i=a.byteLength;const s=new Int8Array(i);let t=a.byteOffset||0;for(let e=0;e<i;e++){s[e]=r.chunks[1].dataView.getInt8(t,S);t++}const l=window.DracoDecoder;l.decodeGeometry(s.buffer,t=>{const n=new CGL.Geometry("draco mesh "+e);for(let e=0;e<t.attributes.length;e++){const a=t.attributes[e];if(a.name==="position")n.vertices=a.array;else if(a.name==="normal")n.vertexNormals=a.array;else if(a.name==="uv")n.texCoords=a.array;else if(a.name==="color")n.vertexColors=this.calcVertexColors(a.array);else if(a.name==="joints")n.setAttribute("attrJoints",Array.from(a.array),4);else if(a.name==="weights"){const i=new Float32Array(a.array.length/a.itemSize*4);for(let t=0;t<a.array.length/a.itemSize;t++){i[t*4]=i[t*4+1]=i[t*4+2]=i[t*4+3]=0;for(let e=0;e<a.itemSize;e++)i[t*4+e]=a.array[t*a.itemSize+e]}n.setAttribute("attrWeights",i,4)}else _.logWarn("unknown draco attrib",a)}t.attributes=null;n.verticesIndices=t.index.array;this.setGeom(n);this.mesh=null;r.loadingMeshes--;r.timing.push(["draco decode",Math.round(performance.now()-r.startTime)]);if(o)o(this)},e=>{_.logError(e)})}else{r.loadingMeshes--;this.fillGeomAttribs(r,this.geom,n.attributes);if(n.targets){for(let e=0;e<n.targets.length;e++){let t=this.geom.copy();if(n.hasOwnProperty("indices"))t.verticesIndices=r.accBuffers[n.indices];this.fillGeomAttribs(r,t,n.targets[e],false);{for(let e=0;e<t.vertices.length;e++)t.vertices[e]+=this.geom.vertices[e];t.calculateNormals();for(let e=0;e<t.vertices.length;e++)t.vertices[e]-=this.geom.vertices[e]}this.geom.morphTargets.push(t)}}if(o)o(this)}}_linearToSrgb(e){if(e<=0)return 0;else if(e>=1)return 1;else if(e<.0031308)return e*12.92;else return e**(1/2.2)*1.055-.055}calcVertexColors(n){let a=null;if(n instanceof Float32Array){let t=false;for(let e=0;e<n.length;e++){if(n[e]>1){t=true;continue}}if(t)for(let e=0;e<n.length;e++)n[e]/=65535;a=n}else if(n instanceof Uint16Array){const t=new Float32Array(n.length);for(let e=0;e<n.length;e++)t[e]=n[e]/65535;a=t}else a=n;for(let e=0;e<a.length;e++){a[e]=this._linearToSrgb(a[e])}return a}fillGeomAttribs(e,t,n,a){if(n.hasOwnProperty("POSITION"))t.vertices=e.accBuffers[n.POSITION];if(n.hasOwnProperty("NORMAL"))t.vertexNormals=e.accBuffers[n.NORMAL];if(n.hasOwnProperty("TANGENT"))t.tangents=e.accBuffers[n.TANGENT];if(n.hasOwnProperty("COLOR_0"))t.vertexColors=this.calcVertexColors(e.accBuffers[n.COLOR_0]);if(n.hasOwnProperty("COLOR_1"))t.setAttribute("attrVertColor1",this.calcVertexColors(e.accBuffers[n.COLOR_1]),4);if(n.hasOwnProperty("COLOR_2"))t.setAttribute("attrVertColor2",this.calcVertexColors(e.accBuffers[n.COLOR_2]),4);if(n.hasOwnProperty("COLOR_3"))t.setAttribute("attrVertColor3",this.calcVertexColors(e.accBuffers[n.COLOR_3]),4);if(n.hasOwnProperty("COLOR_4"))t.setAttribute("attrVertColor4",this.calcVertexColors(e.accBuffers[n.COLOR_4]),4);if(n.hasOwnProperty("TEXCOORD_0"))t.texCoords=e.accBuffers[n.TEXCOORD_0];if(n.hasOwnProperty("TEXCOORD_1"))t.setAttribute("attrTexCoord1",e.accBuffers[n.TEXCOORD_1],2);if(n.hasOwnProperty("TEXCOORD_2"))t.setAttribute("attrTexCoord2",e.accBuffers[n.TEXCOORD_2],2);if(n.hasOwnProperty("TEXCOORD_3"))t.setAttribute("attrTexCoord3",e.accBuffers[n.TEXCOORD_3],2);if(n.hasOwnProperty("TEXCOORD_4"))t.setAttribute("attrTexCoord4",e.accBuffers[n.TEXCOORD_4],2);if(n.hasOwnProperty("WEIGHTS_0")){t.setAttribute("attrWeights",e.accBuffers[n.WEIGHTS_0],4)}if(n.hasOwnProperty("JOINTS_0")){if(!e.accBuffers[n.JOINTS_0])console.log("no !gltf.accBuffers[attribs.JOINTS_0]");t.setAttribute("attrJoints",e.accBuffers[n.JOINTS_0],4)}if(n.hasOwnProperty("POSITION"))e.accBuffersDelete.push(n.POSITION);if(n.hasOwnProperty("NORMAL"))e.accBuffersDelete.push(n.NORMAL);if(n.hasOwnProperty("TEXCOORD_0"))e.accBuffersDelete.push(n.TEXCOORD_0);if(n.hasOwnProperty("TANGENT"))e.accBuffersDelete.push(n.TANGENT);if(n.hasOwnProperty("COLOR_0"))e.accBuffersDelete.push(n.COLOR_0);if(n.hasOwnProperty("COLOR_0"))e.accBuffersDelete.push(n.COLOR_0);if(n.hasOwnProperty("COLOR_1"))e.accBuffersDelete.push(n.COLOR_1);if(n.hasOwnProperty("COLOR_2"))e.accBuffersDelete.push(n.COLOR_2);if(n.hasOwnProperty("COLOR_3"))e.accBuffersDelete.push(n.COLOR_3);if(n.hasOwnProperty("TEXCOORD_1"))e.accBuffersDelete.push(n.TEXCOORD_1);if(n.hasOwnProperty("TEXCOORD_2"))e.accBuffersDelete.push(n.TEXCOORD_2);if(n.hasOwnProperty("TEXCOORD_3"))e.accBuffersDelete.push(n.TEXCOORD_3);if(n.hasOwnProperty("TEXCOORD_4"))e.accBuffersDelete.push(n.TEXCOORD_4);if(a!==false)if(t&&t.verticesIndices)this.setGeom(t)}setGeom(n){if(ee.get()=="X-ZY"){for(let t=0;t<n.vertexNormals.length;t+=3){let e=n.vertexNormals[t+2];n.vertexNormals[t+2]=n.vertexNormals[t+1];n.vertexNormals[t+1]=-e}}if(te.get()=="XZ-Y"){for(let t=0;t<n.vertices.length;t+=3){let e=n.vertices[t+2];n.vertices[t+2]=-n.vertices[t+1];n.vertices[t+1]=e}}if(this.primitive==this.TRIANGLES){if(!n.vertexNormals.length||c.get())n.calculateNormals();if((!n.biTangents||n.biTangents.length==0)&&n.tangents){const t=vec3.create();const e=vec3.create();const a=n.tangents;n.tangents=new Float32Array(a.length/4*3);n.biTangents=new Float32Array(a.length/4*3);for(let e=0;e<a.length;e+=4){const i=e/4*3;vec3.cross(t,[n.vertexNormals[i],n.vertexNormals[i+1],n.vertexNormals[i+2]],[a[e],a[e+1],a[e+2]]);vec3.div(t,t,[a[e+3],a[e+3],a[e+3]]);vec3.normalize(t,t);n.biTangents[i+0]=t[0];n.biTangents[i+1]=t[1];n.biTangents[i+2]=t[2];n.tangents[i+0]=a[e+0];n.tangents[i+1]=a[e+1];n.tangents[i+2]=a[e+2]}}if(n.tangents.length===0||c.get())n.calcTangentsBitangents()}this.geom=n;this.bounds=n.getBounds()}render(n,t,a){if(!this.mesh&&this.geom&&this.geom.verticesIndices){let e=this.geom;if(this.geom.vertices.length/3>64e3){e=this.geom.copy();e.unIndex(false,true)}let t;if(this.primitive==this.TRIANGLES)t=n.gl.TRIANGLES;else if(this.primitive==this.LINES)t=n.gl.LINES;else if(this.primitive==this.LINE_STRIP)t=n.gl.LINE_STRIP;else if(this.primitive==this.POINTS)t=n.gl.POINTS;else{_.logWarn("unknown primitive type",this)}this.mesh=new CGL.Mesh(n,e,t)}else{if(this.geom&&this.geom.morphTargets.length){this.morphGeom=this.geom.copy();this.test=E*11.7;if(this.test>=this.geom.morphTargets.length-1)this.test=0;const l=this.geom.morphTargets[Math.floor(this.test)];const u=this.geom.morphTargets[Math.floor(this.test+1)];if(l&&l.vertices&&u){if(this.morphGeom.vertexNormals.length!=l.vertexNormals.length)this.morphGeom.vertexNormals=new Float32Array(l.vertexNormals.length);const m=this.test%1;for(let e=0;e<this.morphGeom.vertices.length;e++){this.morphGeom.vertices[e]=this.geom.vertices[e]+(1-m)*l.vertices[e]+m*u.vertices[e];this.morphGeom.vertexNormals[e]=(1-m)*l.vertexNormals[e]+m*u.vertexNormals[e]}this.mesh.updateNormals(this.morphGeom);this.mesh.updateVertices(this.morphGeom)}}let e=!t&&this.material!=-1&&C.shaders[this.material];if(a)e=false;if(e)n.pushShader(C.shaders[this.material]);const i=n.getShader()||{};const r=i.uniformColorDiffuse;const o=i.uniformPbrMetalness;const s=i.uniformPbrRoughness;if(!C.shaders[this.material]&&ae.get()){if(r&&this._matDiffuseColor){this._matDiffuseColorOrig=[r.getValue()[0],r.getValue()[1],r.getValue()[2],r.getValue()[3]];r.setValue(this._matDiffuseColor)}if(o)if(this._matPbrMetalness!=null){this._matPbrMetalnessOrig=o.getValue();o.setValue(this._matPbrMetalness)}else o.setValue(0);if(s)if(this._matPbrRoughness!=null){this._matPbrRoughnessOrig=s.getValue();s.setValue(this._matPbrRoughness)}else{s.setValue(0)}}if(this.mesh)this.mesh.render(n.getShader(),t);if(ae.get()){if(r&&this._matDiffuseColor)r.setValue(this._matDiffuseColorOrig);if(o&&this._matPbrMetalnessOrig!=undefined)o.setValue(this._matPbrMetalnessOrig);if(s&&this._matPbrRoughnessOrig!=undefined)s.setValue(this._matPbrRoughnessOrig)}if(e)n.popShader()}}};const z=class{constructor(t,e){this.bounds=new CABLES.CG.BoundingBox;this.meshes=[];this.name=e.name;const n=e.primitives;for(let e=0;e<n.length;e++){const a=new V(this.name,n[e],t,e=>{this.bounds.apply(e.bounds)});a.submeshIndex=e;this.meshes.push(a)}}render(t,n,a,i){for(let e=0;e<this.meshes.length;e++){const r=C.shaders[this.meshes[e].material];if(!n&&r)t.pushShader(C.shaders[this.meshes[e].material]);if(a)a.renderStart(t,i);this.meshes[e].render(t,n,a,i);if(a)a.renderFinish(t);if(!n&&r)t.popShader()}}};const X=class{constructor(e,t){this.isChild=e.isChild||false;this.name=e.name;if(e.hasOwnProperty("camera"))this.camera=e.camera;this.hidden=false;this.mat=mat4.create();this._animMat=mat4.create();this._tempMat=mat4.create();this._tempQuat=quat.create();this._tempRotmat=mat4.create();this.mesh=null;this.children=[];this._node=e;this._gltf=t;this.absMat=mat4.create();this.addTranslate=null;this._tempAnimScale=null;this.addMulMat=null;this.updateMatrix();this._animActions={};this.skinRenderer=null;this.copies=[]}get skin(){if(this._node.hasOwnProperty("skin"))return this._node.skin;else return-1}copy(){this.isCopy=true;const e=new X(this._node,this._gltf);e.copyOf=this;e._animActions=this._animActions;e.children=this.children;e.skinRenderer=new Y(e);this.updateMatrix();return e}hasSkin(){if(this._node.hasOwnProperty("skin"))return this._gltf.json.skins[this._node.skin].name||"unknown";return false}initSkin(){if(this.skin>-1){this.skinRenderer=new Y(this)}}updateMatrix(){mat4.identity(this.mat);if(this._node.translation)mat4.translate(this.mat,this.mat,this._node.translation);if(this._node.rotation){const e=mat4.create();this._rot=this._node.rotation;mat4.fromQuat(e,this._node.rotation);mat4.mul(this.mat,this.mat,e)}if(this._node.scale){this._scale=this._node.scale;mat4.scale(this.mat,this.mat,this._scale)}if(this._node.hasOwnProperty("mesh")){this.mesh=this._gltf.meshes[this._node.mesh];if(this.isCopy){console.log(this.mesh)}}if(this._node.children){for(let e=0;e<this._node.children.length;e++){this._gltf.json.nodes[e].isChild=true;if(this._gltf.nodes[this._node.children[e]])this._gltf.nodes[this._node.children[e]].isChild=true;this.children.push(this._node.children[e])}}}unHide(){this.hidden=false;for(let e=0;e<this.children.length;e++)if(this.children[e].unHide)this.children[e].unHide()}calcBounds(t,e,n){const a=mat4.create();if(e)mat4.copy(a,e);if(this.mat)mat4.mul(a,a,this.mat);if(this.mesh){const i=this.mesh.bounds.copy();i.mulMat4(a);n.apply(i);if(n.changed){b.push(i._min[0]||0,i._min[1]||0,i._min[2]||0,i._max[0]||0,i._max[1]||0,i._max[2]||0)}}for(let e=0;e<this.children.length;e++){if(t.nodes[this.children[e]]&&t.nodes[this.children[e]].calcBounds){const r=t.nodes[this.children[e]].calcBounds(t,a,n);n.apply(r)}}if(n.changed)return n;else return null}setAnimAction(t){if(!t)return;this._currentAnimaction=t;if(t&&!this._animActions[t]){return null}for(let e in this._animActions[t]){if(e=="translation")this._animTrans=this._animActions[t][e];else if(e=="rotation")this._animRot=this._animActions[t][e];else if(e=="scale")this._animScale=this._animActions[t][e];else console.warn("unknown anim path",e,this._animActions[t][e])}}setAnim(e,t,n){if(!e||!t||!n)return;this._animActions[t]=this._animActions[t]||{};if(this._animActions[t][e])_.warn("animation action path already exists",t,e,this._animActions[t][e]);this._animActions[t][e]=n;if(e=="translation")this._animTrans=n;else if(e=="rotation")this._animRot=n;else if(e=="scale")this._animScale=n;else console.warn("unknown anim path",e,n)}modelMatLocal(){return this._animMat||this.mat}modelMatAbs(){return this.absMat}transform(e,t){if(!t&&t!=0)t=E;this._lastTimeTrans=t;ge++;if(!this._animTrans&&!this._animRot&&!this._animScale){mat4.mul(e.mMatrix,e.mMatrix,this.mat);this._animMat=null}else{this._animMat=this._animMat||mat4.create();mat4.identity(this._animMat);const n=true;if(n&&this._animTrans){mat4.translate(this._animMat,this._animMat,[this._animTrans[0].getValue(t),this._animTrans[1].getValue(t),this._animTrans[2].getValue(t)])}else if(this._node.translation)mat4.translate(this._animMat,this._animMat,this._node.translation);if(n&&this._animRot){if(this._animRot[0].defaultEasing==CABLES.EASING_LINEAR)CABLES.Anim.slerpQuaternion(t,this._tempQuat,this._animRot[0],this._animRot[1],this._animRot[2],this._animRot[3]);else if(this._animRot[0].defaultEasing==CABLES.EASING_ABSOLUTE){this._tempQuat[0]=this._animRot[0].getValue(t);this._tempQuat[1]=this._animRot[1].getValue(t);this._tempQuat[2]=this._animRot[2].getValue(t);this._tempQuat[3]=this._animRot[3].getValue(t)}else if(this._animRot[0].defaultEasing==CABLES.EASING_CUBICSPLINE){CABLES.Anim.slerpQuaternion(t,this._tempQuat,this._animRot[0],this._animRot[1],this._animRot[2],this._animRot[3])}mat4.fromQuat(this._tempMat,this._tempQuat);mat4.mul(this._animMat,this._animMat,this._tempMat)}else if(this._rot){}if(n&&this._animScale){if(!this._tempAnimScale)this._tempAnimScale=[1,1,1];this._tempAnimScale[0]=this._animScale[0].getValue(t);this._tempAnimScale[1]=this._animScale[1].getValue(t);this._tempAnimScale[2]=this._animScale[2].getValue(t);mat4.scale(this._animMat,this._animMat,this._tempAnimScale)}else if(this._scale)mat4.scale(this._animMat,this._animMat,this._scale);mat4.mul(e.mMatrix,e.mMatrix,this._animMat)}if(this.addTranslate)mat4.translate(e.mMatrix,e.mMatrix,this.addTranslate);if(this.addMulMat)mat4.mul(e.mMatrix,e.mMatrix,this.addMulMat);mat4.copy(this.absMat,e.mMatrix)}render(t,n,a,i,r,o,s){if(!n)t.pushModelMatrix();if(s===undefined)s=C.time;if(!n||this.skinRenderer)this.transform(t,s);if(this.hidden&&!o){}else{if(this.skinRenderer){this.skinRenderer.time=s;if(!a)this.mesh.render(t,i,this.skinRenderer,s)}else{if(this.mesh&&!a)this.mesh.render(t,i,null,s)}}if(!r&&!this.hidden)for(let e=0;e<this.children.length;e++)if(C.nodes[this.children[e]])C.nodes[this.children[e]].render(t,n,a,i,r,o,s);if(!n)t.popModelMatrix()}};let x=null;function I(){if(x)gui.mainTabs.closeTab(x.id);x=null}function s(t){const n=[];for(let e=0;e<t.length;e++){n.push(Math.round(t[e]*1e3)/1e3)}return n.join(",")}function q(n,a,i){if(!C)return;n+='<tr class="row">';let r="";let o="";for(let t=1;t<i;t++){o+="&nbsp;&nbsp;&nbsp;";let e="identBg";if(t==1)e="identBgLevel0";r+='<td class="ident '+e+'" ><div style=""></div></td>'}let e=CABLES.uuid();n+=r;n+='<td colspan="'+(21-i)+'">';if(a.mesh&&a.mesh.meshes.length)n+='<span class="icon icon-cube"></span>&nbsp;';else n+='<span class="icon icon-box-select"></span> &nbsp;';n+=a.name+"</td><td></td>";if(a.mesh){n+="<td>";for(let e=0;e<a.mesh.meshes.length;e++){if(e>0)n+=", ";n+=a.mesh.meshes[e].name}n+="</td>";n+="<td>";n+=a.hasSkin()||"-";n+="</td>";n+="<td>";let t=0;for(let e=0;e<a.mesh.meshes.length;e++){if(t>0)n+=", ";if(C.json.materials&&a.mesh.meshes[e].hasOwnProperty("material")){if(C.json.materials[a.mesh.meshes[e].material]){n+=C.json.materials[a.mesh.meshes[e].material].name;t++}}}if(t==0)n+="none";n+="</td>"}else{n+="<td>-</td><td>-</td><td>-</td>"}n+="<td>";if(a._node.translation||a._node.rotation||a._node.scale){let e="";if(a._node.translation)e+="Translate: `"+s(a._node.translation)+"` || ";if(a._node.rotation)e+="Rotation: `"+s(a._node.rotation)+"` || ";if(a._node.scale)e+="Scale: `"+s(a._node.scale)+"` || ";n+='<span class="icon icon-gizmo info" data-info="'+e+'"></span> &nbsp;'}if(a._animRot||a._animScale||a._animTrans){let e="Animated: ";if(a._animRot)e+="Rot ";if(a._animScale)e+="Scale ";if(a._animTrans)e+="Trans ";n+='<span class="icon icon-clock info" data-info="'+e+'"></span>&nbsp;'}if(!a._node.translation&&!a._node.rotation&&!a._node.scale&&!a._animRot&&!a._animScale&&!a._animTrans)n+="-";n+="</td>";n+="<td>";let t="";if(a.hidden)t="node-hidden";n+="<a onclick=\"gui.corePatch().getOpById('"+_.id+"').exposeNode('"+a.name+"','transform')\" class=\"treebutton\">Transform</a>";n+=" <a onclick=\"gui.corePatch().getOpById('"+_.id+"').exposeNode('"+a.name+"','hierarchy')\" class=\"treebutton\">Hierarchy</a>";n+=" <a onclick=\"gui.corePatch().getOpById('"+_.id+"').exposeNode('"+a.name+'\')" class="treebutton">Node</a>';if(a.hasSkin())n+=" <a onclick=\"gui.corePatch().getOpById('"+_.id+"').exposeNode('"+a.name+'\',false,{skin:true});" class="treebutton">Skin</a>';n+="</td><td>";n+='&nbsp;<span class="icon iconhover icon-eye '+t+'" onclick="gui.corePatch().getOpById(\''+_.id+"').toggleNodeVisibility('"+a.name+"');this.classList.toggle('node-hidden');\"></span>";n+="</td>";n+="</tr>";if(a.children){for(let e=0;e<a.children.length;e++)n=q(n,C.nodes[a.children[e]],i+1)}return n}function H(t,e){let n="<tr>";n+=" <td>"+e+"</td>";n+=" <td>"+t.name+"</td>";n+=" <td>";const a=JSON.stringify(t,null,4).replaceAll('"',"").replaceAll("\n","<br/>");n+="<span class=\"icon icon-info\" onclick=\"new CABLES.UI.ModalDialog({ 'html': '<pre>"+a+"</pre>', 'title': '"+t.name+"' });\"></span>&nbsp;";if(t.pbrMetallicRoughness&&t.pbrMetallicRoughness.baseColorFactor){let e="";e+=""+Math.round(t.pbrMetallicRoughness.baseColorFactor[0]*255);e+=","+Math.round(t.pbrMetallicRoughness.baseColorFactor[1]*255);e+=","+Math.round(t.pbrMetallicRoughness.baseColorFactor[2]*255);n+='<div style="width:15px;height:15px;background-color:rgb('+e+');display:inline-block">&nbsp;</a>'}n+=' <td style="">'+(C.shaders[e]?"-":"<a onclick=\"gui.corePatch().getOpById('"+_.id+"').assignMaterial('"+t.name+'\')" class="treebutton">Assign</a>')+"<td>";n+="<td>";n+="</tr>";return n}function e(){if(!C)return;const e=performance.now();const i={};let r='<div style="overflow:scroll;width:100%;height:100%">';r+='File: <a href="'+CABLES.platform.getCablesUrl()+"/asset/patches/?filename="+T.get()+'" target="_blank">'+CABLES.basename(T.get())+"</a><br/>";r+="Generator:"+C.json.asset.generator;let t=0;if(C.json.nodes)t=C.json.nodes.length;r+='<div id="groupNodes">Nodes ('+t+")</div>";r+='<table id="sectionNodes" class="table treetable">';r+="<tr>";r+=' <th colspan="21">Name</th>';r+=" <th>Mesh</th>";r+=" <th>Skin</th>";r+=" <th>Material</th>";r+=" <th>Transform</th>";r+=" <th>Expose</th>";r+=" <th></th>";r+="</tr>";for(let e=0;e<C.nodes.length;e++){if(!C.nodes[e].isChild)r=q(r,C.nodes[e],1)}r+="</table>";let n=0;if(C.json.materials)n=C.json.materials.length;r+='<div id="groupMaterials">Materials ('+n+")</div>";if(!C.json.materials||C.json.materials.length==0){}else{r+='<table id="materialtable"  class="table treetable">';r+="<tr>";r+=" <th>Index</th>";r+=" <th>Name</th>";r+=" <th>Color</th>";r+=" <th>Function</th>";r+=" <th></th>";r+="</tr>";for(let e=0;e<C.json.materials.length;e++){r+=H(C.json.materials[e],e)}r+="</table>"}r+='<div id="groupMeshes">Meshes ('+C.json.meshes.length+")</div>";r+='<table id="meshestable"  class="table treetable">';r+="<tr>";r+=" <th>Name</th>";r+=" <th>Node</th>";r+=" <th>Material</th>";r+=" <th>Vertices</th>";r+=" <th>Attributes</th>";r+="</tr>";let o=[];i.meshes=0;for(let a=0;a<C.json.meshes.length;a++){r+="<tr>";r+="<td>"+C.json.meshes[a].name+"</td>";r+="<td>";let e=0;let t="";for(var s=0;s<C.json.nodes.length;s++){if(C.json.nodes[s].mesh==a){e++;if(e==1){t=C.json.nodes[s].name}}}if(e>1)r+=e+" nodes ("+t+" ...)";else r+=t;r+="</td>";r+="<td>";for(var s=0;s<C.json.meshes[a].primitives.length;s++){if(C.json.meshes[a].primitives[s].hasOwnProperty("material")){if(C.json.materials[C.json.meshes[a]]){r+=C.json.materials[C.json.meshes[a].primitives[s].material].name+" "}}else r+="None"}r+="</td>";r+="<td>";let n=0;for(var s=0;s<C.json.meshes[a].primitives.length;s++){if(C.json.meshes[a].primitives[s].attributes.POSITION!=undefined){let e=parseInt(C.json.accessors[C.json.meshes[a].primitives[s].attributes.POSITION].count);n+=e;r+=""+e+"<br/>"}else r+="-<br/>"}if(C.json.meshes[a].primitives.length>0)r+="="+n;r+="</td>";r+='<td style="vertical-align:top;">';for(let e=0;e<C.json.meshes[a].primitives.length;e++){r+=Object.keys(C.json.meshes[a].primitives[e].attributes);r+=" <a onclick=\"gui.corePatch().getOpById('"+_.id+"').exposeGeom('"+C.json.meshes[a].name+"',"+e+')" class="treebutton">Geometry</a>';r+="<br/>"}r+="</td>";r+="</tr>";for(let t=0;t<C.json.meshes[a].primitives.length;t++){const f=C.json.accessors[C.json.meshes[a].primitives[t].indices];if(f){let e=f.bufferView;if(o.indexOf(e)==-1){o.push(e);if(C.json.bufferViews[e])i.meshes+=C.json.bufferViews[e].byteLength}}for(let e in C.json.meshes[a].primitives[t].attributes){const p=C.json.meshes[a].primitives[t].attributes[e];const g=C.json.accessors[p].bufferView;if(o.indexOf(g)==-1){o.push(g);if(C.json.bufferViews[g])i.meshes+=C.json.bufferViews[g].byteLength}}}}r+="</table>";let a=0;let l=0;if(C.json.animations){l=C.json.animations.length;for(let e=0;e<C.json.animations.length;e++)a+=C.json.animations[e].samplers.length}r+='<div id="groupAnims">Animations ('+l+"/"+a+")</div>";if(C.json.animations){r+='<table id="sectionAnim" class="table treetable">';r+="<tr>";r+="  <th>Name</th>";r+="  <th>Target node</th>";r+="  <th>Path</th>";r+="  <th>Interpolation</th>";r+="  <th>Keys</th>";r+="</tr>";i.animations=0;for(let n=0;n<C.json.animations.length;n++){for(let t=0;t<C.json.animations[n].samplers.length;t++){let e=C.json.accessors[C.json.animations[n].samplers[t].input].bufferView;if(o.indexOf(e)==-1){o.push(e);i.animations+=C.json.bufferViews[e].byteLength}e=C.json.accessors[C.json.animations[n].samplers[t].output].bufferView;if(o.indexOf(e)==-1){o.push(e);i.animations+=C.json.bufferViews[e].byteLength}}for(let e=0;e<C.json.animations[n].channels.length;e++){r+="<tr>";r+="  <td> Anim "+n+": "+C.json.animations[n].name+"</td>";r+="  <td>"+C.nodes[C.json.animations[n].channels[e].target.node].name+"</td>";r+="  <td>";r+=C.json.animations[n].channels[e].target.path+" ";r+="  </td>";const v=C.json.animations[n].channels[e].sampler;const b=C.json.animations[n].samplers[v];r+="  <td>"+b.interpolation+"</td>";r+="  <td>"+C.json.accessors[b.output].count;r+="</td>";r+="</tr>"}}r+="</table>"}else{}let u=0;if(C.json.images)u=C.json.images.length;r+='<div id="groupImages">Images ('+u+")</div>";if(C.json.images){r+='<table id="sectionImages" class="table treetable">';r+="<tr>";r+="  <th>name</th>";r+="  <th>type</th>";r+="  <th>func</th>";r+="</tr>";i.images=0;for(let t=0;t<C.json.images.length;t++){if(C.json.images[t].bufferView)i.images+=C.json.bufferViews[C.json.images[t].bufferView].byteLength;r+="<tr>";r+="<td>"+C.json.images[t].name+"</td>";r+="<td>"+C.json.images[t].mimeType+"</td>";r+="<td>";let e=C.json.images[t].name;if(e===undefined)e=C.json.images[t].bufferView;r+="<a onclick=\"gui.corePatch().getOpById('"+_.id+"').exposeTexture('"+e+'\')" class="treebutton">Expose</a>';r+="</td>";r+="<tr>"}r+="</table>"}let m=0;if(C.json.cameras)m=C.json.cameras.length;r+='<div id="groupCameras">Cameras ('+m+")</div>";if(C.json.cameras){r+='<table id="sectionCameras" class="table treetable">';r+="<tr>";r+="  <th>name</th>";r+="  <th>type</th>";r+="  <th>info</th>";r+="</tr>";for(let e=0;e<C.json.cameras.length;e++){r+="<tr>";r+="<td>"+C.json.cameras[e].name+"</td>";r+="<td>"+C.json.cameras[e].type+"</td>";r+="<td>";if(C.json.cameras[e].perspective){r+="yfov: "+Math.round(C.json.cameras[e].perspective.yfov*100)/100;r+=", ";r+="zfar: "+Math.round(C.json.cameras[e].perspective.zfar*100)/100;r+=", ";r+="znear: "+Math.round(C.json.cameras[e].perspective.znear*100)/100}r+="</td>";r+="<tr>"}r+="</table>"}let c=0;if(C.json.skins)c=C.json.skins.length;r+='<div id="groupSkins">Skins ('+c+")</div>";if(C.json.skins){r+='<table id="sectionSkins" class="table treetable">';r+="<tr>";r+="  <th>name</th>";r+="  <th></th>";r+="  <th>total joints</th>";r+="</tr>";for(let e=0;e<C.json.skins.length;e++){r+="<tr>";r+="<td>"+C.json.skins[e].name+"</td>";r+="<td>"+"</td>";r+="<td>"+C.json.skins[e].joints.length+"</td>";r+="<td>";r+="</td>";r+="<tr>"}r+="</table>"}if(C.timing){r+='<div id="groupTiming">Debug Loading Timing </div>';r+='<table id="sectionTiming" class="table treetable">';r+="<tr>";r+="  <th>task</th>";r+="  <th>time used</th>";r+="</tr>";let e=0;for(let e=0;e<C.timing.length-1;e++){r+="<tr>";r+="  <td>"+C.timing[e][0]+"</td>";r+="  <td>"+(C.timing[e+1][1]-C.timing[e][1])+" ms</td>";r+="</tr>"}r+="</table>"}let d=0;if(C.json.buffers)d=C.json.buffers[0].byteLength;r+='<div id="groupBinary">File Size Allocation ('+Math.round(d/1024)+"k )</div>";r+='<table id="sectionBinary" class="table treetable">';r+="<tr>";r+="  <th>name</th>";r+="  <th>size</th>";r+="  <th>%</th>";r+="</tr>";let h=d;for(let e in i){r+="<tr>";r+="<td>"+e+"</td>";r+="<td>"+W(i[e])+" </td>";r+="<td>"+Math.round(i[e]/d*100)+"% </td>";r+="<tr>";h-=i[e]}if(h!=0){r+="<tr>";r+="<td>unknown</td>";r+="<td>"+W(h)+" </td>";r+="<td>"+Math.round(h/d*100)+"% </td>";r+="<tr>"}r+="</table>";r+="</div>";x=new CABLES.UI.Tab("GLTF "+CABLES.basename(T.get()),{icon:"cube",infotext:"tab_gltf",padding:true,singleton:true});gui.mainTabs.addTab(x,true);x.addEventListener("close",I);x.html(r);CABLES.UI.Collapsable.setup(ele.byId("groupNodes"),ele.byId("sectionNodes"),false);CABLES.UI.Collapsable.setup(ele.byId("groupMaterials"),ele.byId("materialtable"),true);CABLES.UI.Collapsable.setup(ele.byId("groupAnims"),ele.byId("sectionAnim"),true);CABLES.UI.Collapsable.setup(ele.byId("groupMeshes"),ele.byId("meshestable"),true);CABLES.UI.Collapsable.setup(ele.byId("groupCameras"),ele.byId("sectionCameras"),true);CABLES.UI.Collapsable.setup(ele.byId("groupImages"),ele.byId("sectionImages"),true);CABLES.UI.Collapsable.setup(ele.byId("groupSkins"),ele.byId("sectionSkins"),true);CABLES.UI.Collapsable.setup(ele.byId("groupBinary"),ele.byId("sectionBinary"),true);CABLES.UI.Collapsable.setup(ele.byId("groupTiming"),ele.byId("sectionTiming"),true);gui.maintabPanel.show(true)}function W(e){if(e>1024)return Math.round(e/1024)+" kb";if(e>1024*500)return Math.round(e/1024)+" mb";else return e+" bytes"}const Y=class{constructor(e){this._mod=null;this._node=e;this._lastTime=0;this._matArr=[];this._m=mat4.create();this._invBindMatrix=mat4.create();this.identity=true}renderFinish(e){e.popModelMatrix();this._mod.unbind()}renderStart(e,t){if(!this._mod){this._mod=new CGL.ShaderModifier(e,_.name+this._node.name);this._mod.addModule({priority:-2,name:"MODULE_VERTEX_POSITION",srcHeadVert:l.skin_head_vert||"",srcBodyVert:l.skin_vert||""});this._mod.addUniformVert("m4[]","MOD_boneMats",[]);const i=vec3.create()}const n=this._node.skin;const a=C.json.skins[n].joints.length*16;{if(this._matArr.length!=a)this._matArr.length=a;for(let e=0;e<C.json.skins[n].joints.length;e++){const r=e*16;const o=C.json.skins[n].joints[e];const s=C.nodes[o];for(let e=0;e<16;e++)this._invBindMatrix[e]=C.accBuffers[C.json.skins[n].inverseBindMatrices][r+e];mat4.mul(this._m,s.modelMatAbs(),this._invBindMatrix);for(let e=0;e<this._m.length;e++)this._matArr[r+e]=this._m[e]}this._mod.setUniformValue("MOD_boneMats",this._matArr);this._lastTime=t}this._mod.define("SKIN_NUM_BONES",C.json.skins[n].joints.length);this._mod.bind();e.pushModelMatrix();if(this.identity)mat4.identity(e.mMatrix)}};const Z=_.inTrigger("Render"),t=_.inString("data"),T=_.inUrl("glb File",[".glb"]),K=_.inBool("Draw",true),n=_.inDropDown("Camera",["None"],"None"),Q=_.inString("Animation",""),J=_.inTriggerButton("Show Structure"),i=_.inSwitch("Center",["None","XYZ","XZ"],"XYZ"),r=_.inBool("Rescale",true),o=_.inFloat("Rescale Size",2.5),u=_.inFloat("Time"),m=_.inBool("Sync to timeline",false),$=_.inBool("Loop",true),ee=_.inSwitch("Normals Format",["XYZ","X-ZY"],"XYZ"),te=_.inSwitch("Vertices Format",["XYZ","XZ-Y"],"XYZ"),c=_.inBool("Calc Normals",false),d=_.inObject("Materials"),ne=_.inArray("Hide Nodes"),ae=_.inBool("Use Material Properties",false),h=_.inBool("Active",true),ie=_.outTrigger("Render Before"),f=_.outTrigger("Next"),re=_.outString("Generator"),oe=_.outNumber("GLTF Version"),se=_.outArray("GLTF Extensions Used"),le=_.outNumber("Anim Length",0),ue=_.outNumber("Anim Time",0),me=_.outObject("Json"),ce=_.outArray("Anims"),de=_.outArray("BoundingPoints"),he=_.outObject("Bounds"),fe=_.outTrigger("Finished"),pe=_.outBool("Loading");_.setPortGroup("Timing",[u,m,$]);const S=true;const p=_.patch.cgl;T.onChange=te.onChange=c.onChange=ee.onChange=L;_.toWorkPortsNeedToBeLinked(Z);let ge=0;let g=false;let v=null;let b=[];let C=null;let y=0;let E=0;let M=true;let ve=null;let P=null;let N=null;const be=vec3.create();let xe=0;let _e=false;const j=vec3.create();J.onTriggered=e;t.setUiAttribs({hideParam:true,hidePort:true});t.onChange=Ee;ne.onChange=w;Q.onChange=Pe;_.setPortGroup("Transform",[r,o,i]);i.onChange=Ae;function Oe(){const t=["None"];if(C){for(let e=0;e<C.nodes.length;e++){if(C.nodes[e].camera>=0){t.push(C.nodes[e].name)}}}n.uiAttribs.values=t}function Ae(){_e=i.get()!="None";if(C&&C.bounds){j.set(C.bounds.center);j[0]=-j[0];j[1]=-j[1];j[2]=-j[2];if(i.get()=="XZ")j[1]=-C.bounds.minY}}r.onChange=function(){o.setUiAttribs({greyout:!r.get()})};d.onChange=function(){M=true};_.onDelete=function(){I()};m.onChange=function(){u.setUiAttribs({greyout:m.get()})};n.onChange=Ie;function Ie(){v=null;if(!C)return;for(let e=0;e<C.nodes.length;e++){if(C.nodes[e].name==n.get())v=new a(C,C.nodes[e])}}Z.onTriggered=function(){if(!g)return;if(!h.get())return;ge=0;if(m.get())E=_.patch.timer.getTime();else E=Math.max(0,u.get());if($.get()){E%=y;if(E<xe)fe.trigger()}else{if(y>0&&E>=y)fe.trigger()}xe=E;p.pushModelMatrix();ue.set(E||0);if(g&&C&&C.bounds){if(r.get()){let e=o.get()/C.bounds.maxAxis;C.scale=e;vec3.set(be,e,e,e);mat4.scale(p.mMatrix,p.mMatrix,be)}if(_e){mat4.translate(p.mMatrix,p.mMatrix,j)}}let e=p.frameStore.currentScene||null;p.frameStore.currentScene=C;ie.trigger();if(g){if(M)Ce();if(v)v.start(E);if(C){C.time=E;{if(C.bounds&&p.shouldDrawHelpers(_)){if(CABLES.UI&&gui.shouldDrawOverlay)p.pushShader(CABLES.GL_MARKER.getDefaultShader(p));else p.pushShader(CABLES.GL_MARKER.getSelectedShader(p));C.bounds.render(p);p.popShader()}if(K.get()){for(let e=0;e<C.nodes.length;e++)if(!C.nodes[e].isChild)C.nodes[e].render(p)}else{for(let e=0;e<C.nodes.length;e++)if(!C.nodes[e].isChild)C.nodes[e].render(p,false,true)}}}}f.trigger();p.frameStore.currentScene=e;p.popModelMatrix();if(v)v.end()};function Te(){if(!C){_.setUiError("nogltf","gltf not found");return}_.setUiError("nogltf",null);if(C.loadingMeshes>0){setTimeout(Te,100);return}C.timing.push(["finishLoading()",Math.round(performance.now()-C.startTime)]);M=true;le.set(y);C.bounds=new CABLES.CG.BoundingBox;if(!C)_.setUiError("urlerror",'could not load gltf:<br/>"'+T.get()+'"',2);else _.setUiError("urlerror",null);C.timing.push(["start calc bounds",Math.round(performance.now()-C.startTime)]);for(let e=0;e<C.nodes.length;e++){const t=C.nodes[e];t.updateMatrix();if(!t.isChild)t.calcBounds(C,null,C.bounds)}if(C.bounds)he.set(C.bounds);C.timing.push(["calced bounds",Math.round(performance.now()-C.startTime)]);w();C.timing.push(["hideNodesFromData",Math.round(performance.now()-C.startTime)]);if(x)e();C.timing.push(["printinfo",Math.round(performance.now()-C.startTime)]);Oe();Ie();de.set(b);if(C){if(T.get()&&!T.get().startsWith("data:")){_.setUiAttrib({extendTitle:CABLES.basename(T.get())})}C.loaded=Date.now()}if(C){for(let e=0;e<C.nodes.length;e++){if(!C.nodes[e].isChild){C.nodes[e].render(p,false,true,true,false,true,0)}}for(let e=0;e<C.nodes.length;e++){const t=C.nodes[e];t.children=je(t.children)}}Ae();Pe();pe.set(false);p.patch.loading.finished(P);P=null;_.setUiAttrib({accBuffersDelete:CABLES.basename(T.get())});if(C.accBuffersDelete){for(let e=0;e<C.accBuffersDelete.length;e++){C.accBuffers[C.accBuffersDelete[e]]=null}}C.chunks=null;g=true}function Se(e){if(!h.get())return;if(!P)P=p.patch.loading.start("gltfScene",T.get(),_);let t=T.get();let n=_.patch.getFilePath(String(T.get()));if(T.get()&&!T.get().startsWith("data:")){if(e===true)n+="?rnd="+CABLES.generateUUID()}g=false;pe.set(true);fetch(n).then(e=>{return e.arrayBuffer()}).then(e=>{if(T.get()!=t){p.patch.loading.finished(P);P=null;return}b=[];y=0;C=F(e);Te()}).catch(e=>{console.log(e)});I();const a=new XMLHttpRequest;a.open("GET",n,true);a.responseType="arraybuffer";p.patch.loading.addAssetLoadingTask(()=>{})}_.onFileChanged=function(e){if(T.get()&&T.get().indexOf(e)>-1){L(true)}};h.onChange=()=>{if(h.get())L();if(!h.get()){C=null}};function L(e){clearTimeout(ve);ve=setTimeout(function(){Se(e)},30)}function Ce(){if(!C)return;C.shaders={};if(d.links.length==1&&d.get()){const n=d.links[0].portOut.op;const a=n.getPort("Shader");const i=n.getPort("Material Name");if(!a&&!i){const r=d.get();for(let t in r){if(r[t]&&C.json.materials)for(let e=0;e<C.json.materials.length;e++){if(C.json.materials[e].name==t){if(C.shaders[e]){n.warn("double material assignment:",name)}C.shaders[e]=r[t]}}}}}if(d.get()){for(let e=0;e<d.links.length;e++){const t=d.links[e].portOut.op;const a=t.getPort("Shader");const i=t.getPort("Material Name");if(a&&i&&a.get()){const name=i.get();if(C.json.materials)for(let e=0;e<C.json.materials.length;e++)if(C.json.materials[e].name==name){if(C.shaders[e]){t.warn("double material assignment:",name)}C.shaders[e]=a.get()}}}}M=false;if(x)e()}function ye(){const t=ne.get();if(!C||!N||!N.hiddenNodes)return;if(!t){return}for(let e=0;e<t.length;e++){const n=C.getNode(t[e]);if(n)n.hidden=true}}function w(){if(!N)Ee();if(!C)return;C.unHideAll();if(N&&N.hiddenNodes){for(const e in N.hiddenNodes){const t=C.getNode(e);if(t)t.hidden=true;else _.verbose("node to be hidden not found",e,t)}}ye()}function Ee(){N=t.get();if(!N||N==="")N={};else N=JSON.parse(N);if(C)w();return N}function Me(){t.set(JSON.stringify(N))}function Pe(){if(C&&C.nodes){for(let e=0;e<C.nodes.length;e++){C.nodes[e].setAnimAction(Q.get())}}}function Ne(t,n){for(let e=0;e<C.nodes.length;e++){if(C.nodes[e].children.indexOf(n)>=0){t.push(C.nodes[e]);if(C.nodes[e].isChild)Ne(t,e)}}}_.exposeTexture=function(e){const t=gui.corePatch().addOp("Ops.Gl.GLTF.GltfTexture");t.getPort("Name").set(e);R(t,1);_.patch.link(_,f.name,t,"Render");gui.patchView.testCollision(t);gui.patchView.centerSelectOp(t.id,true)};_.exposeGeom=function(e,t){const n=gui.corePatch().addOp("Ops.Gl.GLTF.GltfGeometry");n.getPort("Name").set(e);n.getPort("Submesh").set(t);R(n,1);_.patch.link(_,f.name,n,"Update");gui.patchView.testCollision(n);gui.patchView.centerSelectOp(n.id,true)};function R(e,t){t=t||1;e.setUiAttrib({subPatch:_.uiAttribs.subPatch,translate:{x:_.uiAttribs.translate.x,y:_.uiAttribs.translate.y+t*CABLES.GLUI.glUiConfig.newOpDistanceY}})}_.exposeNode=function(n,e,a){let t=e=="hierarchy";if(t){let i=[];for(let e=0;e<C.nodes.length;e++){if(C.nodes[e].name==n){let t=[];const r=C.nodes[e];Ne(t,e);t=t.reverse();t.push(r,r);let n=f.name;let a=_;for(let e=0;e<t.length;e++){const o=gui.corePatch().addOp("Ops.Gl.GLTF.GltfNode_v2");o.getPort("Node Name").set(t[e].name);_.patch.link(a,n,o,"Render");R(o,e);if(e==t.length-1){o.getPort("Transformation").set(false)}else{o.getPort("Draw Mesh").set(false);o.getPort("Draw Childs").set(false)}n="Next";a=o;i.push(o);gui.patchView.testCollision(o)}}}for(let e=0;e<i.length;e++){i[e].selectChilds()}}else{let t="Ops.Gl.GLTF.GltfNode_v2";if(a&&a.skin)t="Ops.Gl.GLTF.GltfSkin";if(e=="transform")t="Ops.Gl.GLTF.GltfNodeTransform_v2";gui.serverOps.loadOpLibs(t,()=>{let e=gui.corePatch().addOp(t);e.getPort("Node Name").set(n);R(e);_.patch.link(_,f.name,e,"Render");gui.patchView.testCollision(e);gui.patchView.centerSelectOp(e.id,true)})}gui.closeModal()};_.assignMaterial=function(e){const t=gui.corePatch().addOp("Ops.Gl.GLTF.GltfSetMaterial");t.getPort("Material Name").set(e);_.patch.link(_,d.name,t,"Material");R(t);gui.patchView.testCollision(t);gui.patchView.centerSelectOp(t.id,true);gui.closeModal()};_.toggleNodeVisibility=function(e){const t=C.getNode(e);t.hidden=!t.hidden;N.hiddenNodes=N.hiddenNodes||{};if(t)if(t.hidden)N.hiddenNodes[e]=true;else delete N.hiddenNodes[e];Me()};function je(n){const a={},i=[];for(let e=0,t=n.length;e<t;++e){if(!a.hasOwnProperty(n[e])){i.push(n[e]);a[n[e]]=1}}return i}};Ops.Gl.GLTF.GltfScene_v3.prototype=new CABLES.Op;CABLES.OPS["a9c59d94-8aea-4c20-ab5d-63ce46ecfa16"]={f:Ops.Gl.GLTF.GltfScene_v3,objName:"Ops.Gl.GLTF.GltfScene_v3"};Ops.Gl.GLTF.GltfNode_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTrigger("Render"),a=e.inString("Node Name"),i=e.inBool("Transformation",true),r=e.inBool("Draw Mesh",true),o=e.inBool("Draw Childs",true),s=e.inBool("Ignore Material",true),l=e.inBool("Use Scene Time",true),u=e.inFloat("Time",0),m=e.outTrigger("Next"),c=e.outObject("Geometry",null,"geometry"),d=e.outBool("Found");const h=e.patch.cgl;let f=null;let p=null;a.onChange=function(){c.set(null);f=null;d.set(false);if(!a.isLinked())e.setUiAttrib({extendTitle:a.get()})};l.onChange=g;g();function g(){u.setUiAttribs({greyout:l.get()})}n.onTriggered=function(){if(!h.frameStore.currentScene)return;if(p!=h.frameStore.currentScene.loaded)f=null;if(!f){const t=a.get();if(!h.frameStore||!h.frameStore.currentScene||!h.frameStore.currentScene.nodes){return}p=h.frameStore.currentScene.loaded;for(let e=0;e<h.frameStore.currentScene.nodes.length;e++){if(h.frameStore.currentScene.nodes[e].name==t){f=h.frameStore.currentScene.nodes[e];d.set(true);if(f&&f.mesh&&f.mesh.meshes&&f.mesh.meshes[0].geom){c.setRef(f.mesh.meshes[0].geom)}else{console.log("has no geom?!");c.set(null)}}}}h.pushModelMatrix();if(f){if(i.get()){h.pushModelMatrix();f.transform(h)}let e;if(!l.get())e=u.get();f.render(h,!i.get(),!r.get(),s.get(),!o.get(),true,e)}m.trigger();if(f){if(i.get())h.popModelMatrix()}h.popModelMatrix()}};Ops.Gl.GLTF.GltfNode_v2.prototype=new CABLES.Op;CABLES.OPS["10d09387-0085-4162-ab5b-b89eebbf3cf4"]={f:Ops.Gl.GLTF.GltfNode_v2,objName:"Ops.Gl.GLTF.GltfNode_v2"};Ops.Gl.Shader.PointMaterial_v4=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;\n\n#ifdef USE_ATLAS\nIN float randAtlas;\n#endif\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#ifdef HAS_TEXTURE_ATLASLOOKUP\n    UNI sampler2D texAtlasLookup;\n#endif\n\n#ifdef VERTEX_COLORS\n    IN vec4 vertexColor;\n#endif\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 RAND_ATLAS\n        #ifndef HAS_TEXTURE_ATLASLOOKUP\n            pointCoord.x=pointCoord.x/atlasNumX+randAtlas*(1.0/atlasNumX);\n        #endif\n    #endif\n\n\n\n        #ifdef HAS_TEXTURE_ATLASLOOKUP\n\n            float atlasIdx=texture(texAtlasLookup,pointCoord).r;\n\n            #ifdef ATLAS_XFADE\n                vec2 pointCoord2=vec2(pointCoord);\n                pointCoord2.x=pointCoord.x/atlasNumX+ceil(atlasIdx)*(1.0/atlasNumX);\n            #endif\n\n            pointCoord.x=pointCoord.x/atlasNumX+floor(atlasIdx)*(1.0/atlasNumX);\n\n        #endif\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        \tvec3 lumcoeff = vec3(0.299,0.587,0.114);\n        \tmask = dot(texture(texMask,pointCoord).rgb, lumcoeff);\n        #endif\n\n    #endif\n\n    #ifdef HAS_TEXTURE_DIFFUSE\n\n\n        col=texture(diffTex,pointCoord);\n\n        #ifdef HAS_TEXTURE_ATLASLOOKUP\n        #ifdef ATLAS_XFADE\n            vec4 col2=texture(diffTex,pointCoord2);\n            col=mix(col,col2,fract(atlasIdx));\n        #endif\n        #endif\n\n        #ifdef COLORIZE_TEXTURE\n          col.rgb*=color.rgb;\n        #endif\n\n\n    #endif\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    outColor = col;\n}\n",pointmat_vert:"{{MODULES_HEAD}}\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;\n\nIN float attrVertIndex;\n\nUNI float atlasNumX;\n\n#ifdef RAND_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 RAND_ATLAS\n        randAtlas=floor(atlasNumX*rand(attrVertIndex));\n    #endif\n\n    // float sizeMultiply=1.0;\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    // psMul*=sizeMultiply;\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\n        #ifdef DOTSIZEREMAPABS\n            // addPointSize=(( (texture(texPointSize,texCoord).r) * texPointSizeMul)-0.5)*2.0;\n\n            addPointSize=1.0-(distance(addPointSize,0.5)*2.0);\n            // addPointSize=abs(1.0-(distance(addPointSize,0.5)*2.0));\n            addPointSize=addPointSize*addPointSize*addPointSize*2.0;\n\n            // addPointSize=(( (texture(texPointSize,texCoord).r) * texPointSizeMul)-0.5)*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\n    gl_PointSize += ps;\n\n\n    gl_Position = projMatrix * viewMatrix * model;\n}\n"};const n=e.patch.cgl;const a=e.inTrigger("render"),i=e.inValueFloat("PointSize",3),r=e.inBool("Size in Pixels",false),o=e.inValue("Random Size",0),s=e.inValueBool("Round",true),l=e.inValueBool("Round Antialias",false),u=e.inValueBool("Scale by Distance",false),m=e.inValueSlider("r",Math.random()),c=e.inValueSlider("g",Math.random()),d=e.inValueSlider("b",Math.random()),h=e.inValueSlider("a",1),f=e.inBool("Vertex Colors",false),p=e.inTexture("texture"),g=e.inBool("Colorize Texture"),v=e.inTexture("Texture Mask"),b=e.inSwitch("Mask Channel",["R","A","Luminance"],"R"),x=e.inTexture("Texture Colorize"),_=e.inValueBool("Colorize Randomize",true),O=e.inTexture("Texture Opacity"),A=e.inTexture("Texture Point Size"),I=e.inSwitch("Point Size Channel",["R","G","B"],"R"),T=e.inFloat("Texture Point Size Mul",1),S=e.inSwitch("Map Size 0",["Black","Grey"],"Black"),C=e.inValueBool("Flip Texture",false),y=e.inBool("Random Atlas"),E=e.inFloat("Atlas Repeat X",4),M=e.outTrigger("trigger"),P=e.outObject("shader",null,"shader");e.setPortGroup("Texture",[p,g,v,b,x,O,_]);e.setPortGroup("Color",[m,c,d,h,f]);e.setPortGroup("Size",[i,o,s,l,u,r,A,T,I,S]);m.setUiAttribs({colorPick:true});const N=new CGL.Shader(n,"PointMaterial");N.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"]);N.define("MAKE_ROUND");e.toWorkPortsNeedToBeLinked(a);const R=new CGL.Uniform(N,"f","pointSize",i),k=new CGL.Uniform(N,"f","texPointSizeMul",T),B=new CGL.Uniform(N,"f","randomSize",o),D=new CGL.Uniform(N,"4f","color",m,c,d,h),G=new CGL.Uniform(N,"f","atlasNumX",E),j=new CGL.Uniform(N,"f","canvasWidth",n.canvasWidth),U=new CGL.Uniform(N,"f","canvasHeight",n.canvasHeight),F=new CGL.Uniform(N,"t","diffTex"),V=new CGL.Uniform(N,"t","texColorize"),z=new CGL.Uniform(N,"t","texOpacity"),X=new CGL.Uniform(N,"t","texPointSize"),q=new CGL.Uniform(N,"t","texPointSize"),H=new CGL.Uniform(N,"t","texMask");N.setSource(t.pointmat_vert,t.pointmat_frag);N.glPrimitive=n.gl.POINTS;P.set(N);P.ignoreValueSerialize=true;a.onTriggered=L;u.onChange=y.onChange=s.onChange=l.onChange=p.onChange=x.onChange=v.onChange=_.onChange=C.onChange=b.onChange=r.onChange=O.onChange=A.onChange=S.onChange=I.onChange=g.onChange=f.onChange=W;w();e.preRender=function(){if(N)N.bind();L()};function L(){j.setValue(n.canvasWidth);U.setValue(n.canvasHeight);n.pushShader(N);N.popTextures();if(p.get()&&!p.get().deleted)N.pushTexture(F,p.get());if(v.get())N.pushTexture(H,v.get());if(x.get())N.pushTexture(V,x.get());if(O.get())N.pushTexture(z,O.get());if(A.get())N.pushTexture(q,A.get());M.trigger();n.popShader()}function w(){E.setUiAttribs({greyout:!y.get()});b.setUiAttribs({greyout:!v.isLinked()});I.setUiAttribs({greyout:!A.isLinked()});T.setUiAttribs({greyout:!A.isLinked()});S.setUiAttribs({greyout:!A.isLinked()})}function W(){N.toggleDefine("ATLAS_NUMX",y.get());N.toggleDefine("SCALE_BY_DISTANCE",u.get());N.toggleDefine("MAKE_ROUND",s.get());N.toggleDefine("MAKE_ROUNDAA",l.get());N.toggleDefine("VERTEX_COLORS",f.get());N.toggleDefine("RANDOM_COLORIZE",_.get());N.toggleDefine("HAS_TEXTURE_DIFFUSE",p.get());N.toggleDefine("HAS_TEXTURE_MASK",v.get());N.toggleDefine("HAS_TEXTURE_COLORIZE",x.get());N.toggleDefine("HAS_TEXTURE_OPACITY",O.get());N.toggleDefine("HAS_TEXTURE_POINTSIZE",A.get());N.toggleDefine("TEXTURE_COLORIZE_MUL",g.get());N.toggleDefine("FLIP_TEX",C.get());N.toggleDefine("TEXTURE_MASK_R",b.get()=="R");N.toggleDefine("TEXTURE_MASK_A",b.get()=="A");N.toggleDefine("TEXTURE_MASK_LUMI",b.get()=="Luminance");N.toggleDefine("PIXELSIZE",r.get());N.toggleDefine("POINTSIZE_CHAN_R",I.get()=="R");N.toggleDefine("POINTSIZE_CHAN_G",I.get()=="G");N.toggleDefine("POINTSIZE_CHAN_B",I.get()=="B");N.toggleDefine("DOTSIZEREMAPABS",S.get()=="Grey");w()}};Ops.Gl.Shader.PointMaterial_v4.prototype=new CABLES.Op;CABLES.OPS["a7cb5d1c-cd4a-4c28-bb13-7bb9bda187ed"]={f:Ops.Gl.Shader.PointMaterial_v4,objName:"Ops.Gl.Shader.PointMaterial_v4"};Ops.Gl.Meshes.Icosahedron=function(){CABLES.Op.apply(this,arguments);const a=this;const e=a.attachments={};const t=a.inTrigger("render"),i=a.inValueBool("smooth"),n=a.outTrigger("trigger"),r=a.outObject("geometry");r.ignoreValueSerialize=true;i.onChange=u;const o=a.patch.cgl;let s=new CGL.Geometry(a.name);let l=null;i.set(false);u();t.onTriggered=function(){if(!l)l=new CGL.Mesh(o,s);if(l)l.render(o.getShader());n.trigger()};function u(){let e=Math.sqrt(5)/2;let t=[];let n=[];n.push(-1,e,0);n.push(1,e,0);n.push(-1,-e,0);n.push(1,-e,0);n.push(0,-1,e);n.push(0,1,e);n.push(0,-1,-e);n.push(0,1,-e);n.push(e,0,-1);n.push(e,0,1);n.push(-e,0,-1);n.push(-e,0,1);s=new CGL.Geometry(a.name);s.vertices=n;s.verticesIndices=[];s.verticesIndices.push(0,11,5);s.verticesIndices.push(0,5,1);s.verticesIndices.push(0,1,7);s.verticesIndices.push(0,7,10);s.verticesIndices.push(0,10,11);s.verticesIndices.push(1,5,9);s.verticesIndices.push(5,11,4);s.verticesIndices.push(11,10,2);s.verticesIndices.push(10,7,6);s.verticesIndices.push(7,1,8);s.verticesIndices.push(3,9,4);s.verticesIndices.push(3,4,2);s.verticesIndices.push(3,2,6);s.verticesIndices.push(3,6,8);s.verticesIndices.push(3,8,9);s.verticesIndices.push(4,9,5);s.verticesIndices.push(2,4,11);s.verticesIndices.push(6,2,10);s.verticesIndices.push(8,6,7);s.verticesIndices.push(9,8,1);s.texCoords=t;s.calcNormals(i.get());r.set(s)}};Ops.Gl.Meshes.Icosahedron.prototype=new CABLES.Op;CABLES.OPS["109cead5-8eda-4726-9e3d-b23afe201abd"]={f:Ops.Gl.Meshes.Icosahedron,objName:"Ops.Gl.Meshes.Icosahedron"};Ops.Math.PerlinNoise_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inFloat("X",0),a=e.inFloat("Y",0),i=e.inFloat("Z",0),r=e.inFloat("Scale",4),o=e.inFloat("Seed",1),s=e.outNumber("Result");const g=4;const v=1<<g;const b=8;const x=1<<b;const _=4095;let O=4;let A=.5;const I=e=>.5*(1-Math.cos(e*Math.PI));let T=null;n.onChange=a.onChange=i.onChange=l;function l(){let e=r.get();let t=u(n.get()*e,a.get()*e,i.get()*e);s.set(t)}function u(e,t=0,n=0){if(T==null){T=new Array(_+1);for(let e=0;e<_+1;e++){T[e]=Math.random()}}if(e<0){e=-e}if(t<0){t=-t}if(n<0){n=-n}let a=Math.floor(e),i=Math.floor(t),r=Math.floor(n);let o=e-a;let s=t-i;let l=n-r;let u,m;let c=0;let d=.5;let h,f,p;for(let e=0;e<O;e++){let e=a+(i<<g)+(r<<b);u=I(o);m=I(s);h=T[e&_];h+=u*(T[e+1&_]-h);f=T[e+v&_];f+=u*(T[e+v+1&_]-f);h+=m*(f-h);e+=x;f=T[e&_];f+=u*(T[e+1&_]-f);p=T[e+v&_];p+=u*(T[e+v+1&_]-p);f+=m*(p-f);h+=I(l)*(f-h);c+=h*d;d*=A;a<<=1;o*=2;i<<=1;s*=2;r<<=1;l*=2;if(o>=1){a++;o--}if(s>=1){i++;s--}if(l>=1){r++;l--}}return c}o.onChange=()=>{Math.randomSeed=o.get();T=new Array(_+1);for(let e=0;e<_+1;e++){T[e]=Math.seededRandom()}}};Ops.Math.PerlinNoise_v2.prototype=new CABLES.Op;CABLES.OPS["b1a19b32-4ccd-4bce-a37d-e386e53dfc1c"]={f:Ops.Math.PerlinNoise_v2,objName:"Ops.Math.PerlinNoise_v2"};Ops.Gl.ImageCompose.Pixelate_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={pixelate_frag:"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D multiplierTex;\nUNI float amount;\nUNI float amountX;\nUNI float amountY;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n    vec4 col=vec4(1.0,0.0,0.0,1.0);\n\n    float x=1.0/amountX;\n    float y=1.0/amountY;\n\n    #ifdef PIXELATE_TEXTURE\n        x += texture(multiplierTex,texCoord).r*0.1;//*0.1\n        y += texture(multiplierTex,texCoord).r*0.1;//*0.1\n    #endif\n\n    vec2 coord = vec2(x*floor(texCoord.x/x), y*floor(texCoord.y/y));\n\n    col=texture(tex,coord);\n    vec4 base=texture(tex,texCoord);\n\n    outColor=cgl_blendPixel(base,col,amount);\n}"};const n=e.inTrigger("render"),a=e.inTexture("Multiplier"),i=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),r=e.inValueSlider("Amount",1),o=e.inValue("width",100),s=e.inValue("height",100),l=e.outTrigger("trigger");const u=e.patch.cgl;const m=new CGL.Shader(u,e.name,e);m.setSource(m.getDefaultVertexShader(),t.pixelate_frag);const c=new CGL.Uniform(m,"t","tex",0);const d=new CGL.Uniform(m,"t","multiplierTex",1);const h=new CGL.Uniform(m,"f","amount",r);const f=new CGL.Uniform(m,"f","amountX",o);const p=new CGL.Uniform(m,"f","amountY",s);a.onChange=function(){m.toggleDefine("PIXELATE_TEXTURE",a.isLinked())};CGL.TextureEffect.setupBlending(e,m,i,r);n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;u.pushShader(m);u.currentTextureEffect.bind();u.setTexture(0,u.currentTextureEffect.getCurrentSourceTexture().tex);if(a.get())u.setTexture(1,a.get().tex);u.currentTextureEffect.finish();u.popShader();l.trigger()}};Ops.Gl.ImageCompose.Pixelate_v2.prototype=new CABLES.Op;CABLES.OPS["c06ae168-ff4f-4ae6-b4d0-06c3b24203bc"]={f:Ops.Gl.ImageCompose.Pixelate_v2,objName:"Ops.Gl.ImageCompose.Pixelate_v2"};Ops.Gl.Meshes.Rectangle_v4=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=t.inTrigger("render"),a=t.inValueBool("Render Mesh",true),y=t.inValue("width",1),E=t.inValue("height",1),M=t.inSwitch("pivot x",["left","center","right"],"center"),P=t.inSwitch("pivot y",["top","center","bottom"],"center"),N=t.inSwitch("axis",["xy","xz"],"xy"),j=t.inBool("Flip TexCoord X",false),L=t.inBool("Flip TexCoord Y",true),w=t.inValueInt("num columns",1),R=t.inValueInt("num rows",1),i=t.outTrigger("trigger"),k=t.outObject("geometry",null,"geometry");k.ignoreValueSerialize=true;const B=new CGL.Geometry("rectangle");a.setUiAttribs({title:"Render"});n.setUiAttribs({title:"Trigger"});i.setUiAttribs({title:"Next"});t.setPortGroup("Pivot",[M,P,N]);t.setPortGroup("Size",[y,E]);t.setPortGroup("Structure",[w,R]);t.toWorkPortsNeedToBeLinked(n);t.toWorkShouldNotBeChild("Ops.Gl.TextureEffects.ImageCompose",CABLES.OP_PORT_TYPE_TRIGGER);const D=0;const G=1;let U=D;let F=null;let V=true;let z=true;const r=vec3.create();vec3.set(r,1,1,1);N.onChange=M.onChange=P.onChange=j.onChange=L.onChange=R.onChange=w.onChange=o;X();y.onChange=E.onChange=()=>{if(z)X();else V=true};function X(){if(U===D)vec3.set(r,y.get(),E.get(),1);if(U===G)vec3.set(r,y.get(),1,E.get())}k.onLinkChanged=()=>{z=!k.isLinked();X();V=true};function o(){V=true}n.onTriggered=()=>{if(V)s();const e=t.patch.cg;if(e&&F&&a.get()){if(z){e.pushModelMatrix();mat4.scale(e.mMatrix,e.mMatrix,r)}F.render(e.getShader());if(z)e.popModelMatrix()}i.trigger()};t.onDelete=()=>{if(F)F.dispose();o()};function s(){if(N.get()=="xy")U=D;if(N.get()=="xz")U=G;X();let n=y.get();let a=E.get();if(z)n=a=1;let i=0;let r=0;if(M.get()=="center")i=0;else if(M.get()=="right")i=-n/2;else if(M.get()=="left")i=+n/2;if(P.get()=="center")r=0;else if(P.get()=="top")r=-a/2;else if(P.get()=="bottom")r=+a/2;const o=Math.max(1,Math.round(R.get()));const s=Math.max(1,Math.round(w.get()));const l=n/s;const u=a/o;const m=[];const c=new Float32Array((s+1)*(o+1)*2);const d=new Float32Array((s+1)*(o+1)*3);const h=new Float32Array((s+1)*(o+1)*3);const f=new Float32Array((s+1)*(o+1)*3);const p=new Float32Array((s+1)*(o+1)*3);let g=0;let v=0;let b=0;let x=0;let _=0;for(let t=0;t<=o;t++){for(let e=0;e<=s;e++){d[v++]=e*l-n/2+i;if(U==G)d[v++]=0;d[v++]=t*u-a/2+r;if(U==D)d[v++]=0;c[g++]=e/s;c[g++]=t/o;if(U==D){h[b++]=0;h[b++]=0;h[b++]=1;f[x++]=1;f[x++]=0;f[x++]=0;p[_++]=0;p[_++]=1;p[_++]=0}else if(U==G){h[b++]=0;h[b++]=1;h[b++]=0;p[_++]=0;p[_++]=0;p[_++]=1}}}m.length=s*o*6;let O=0;for(let t=0;t<s;t++){for(let e=0;e<o;e++){const A=t+(s+1)*e;const I=A;const T=A+1;const S=A+s+1;const C=A+1+s+1;if(U==D){m[O++]=I;m[O++]=T;m[O++]=S;m[O++]=S;m[O++]=T;m[O++]=C}else if(U==G){m[O++]=I;m[O++]=S;m[O++]=T;m[O++]=T;m[O++]=S;m[O++]=C}}}if(L.get())for(let e=0;e<c.length;e+=2)c[e+1]=1-c[e+1];if(j.get())for(let e=0;e<c.length;e+=2)c[e]=1-c[e];B.clear();B.vertices=d;B.texCoords=c;B.verticesIndices=m;B.vertexNormals=h;B.tangents=f;B.biTangents=p;if(t.patch.cg)if(!F)F=t.patch.cg.createMesh(B,{opId:t.id});else F.setGeom(B);k.setRef(B);V=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.Trigger.SequenceMultiPort=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inMultiPort("Input",CABLES.OP_PORT_TYPE_FUNCTION),a=e.outMultiPort("Output",CABLES.OP_PORT_TYPE_FUNCTION);n.onTriggered=e=>{const t=a.get();for(let e=0;e<t.length;e++){t[e].trigger()}}};Ops.Trigger.SequenceMultiPort.prototype=new CABLES.Op;CABLES.OPS["be066ff6-85e2-408a-9570-59fb7abff7b2"]={f:Ops.Trigger.SequenceMultiPort,objName:"Ops.Trigger.SequenceMultiPort"};Ops.Gl.Matrix.Translate=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=t.inTrigger("render"),a=t.outTrigger("trigger"),i=t.inValue("x"),r=t.inValue("y"),o=t.inValue("z");const s=vec3.create();n.onTriggered=function(){const e=t.patch.cg;vec3.set(s,i.get(),r.get(),o.get());e.pushModelMatrix();mat4.translate(e.mMatrix,e.mMatrix,s);a.trigger();e.popModelMatrix()}};Ops.Gl.Matrix.Translate.prototype=new CABLES.Op;CABLES.OPS["1f89ba0e-e7eb-46d7-8c66-7814b7c528b9"]={f:Ops.Gl.Matrix.Translate,objName:"Ops.Gl.Matrix.Translate"};Ops.Sidebar.DisplayValue_v2=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=t.inObject("link");const a=t.inString("Text","Value");const i=t.inString("Value","");const r=t.outObject("childs");const o=document.createElement("div");o.dataset.op=t.id;o.classList.add("cablesEle");o.classList.add("sidebar__item");o.classList.add("sidebar__value-display");const s=document.createElement("div");s.classList.add("sidebar__item-label");const l=document.createTextNode(a.get());s.appendChild(l);o.appendChild(s);const u=document.createElement("div");u.textContent=i.get();u.classList.add("sidebar__item-value-label");o.appendChild(u);n.onChange=d;a.onChange=c;i.onChange=m;t.onDelete=p;function m(){u.textContent=i.get()}function c(){const e=a.get();s.textContent=e;if(CABLES.UI){t.setUiAttrib({extendTitle:e})}}function d(){r.set(null);const e=n.get();if(e&&e.parentElement){e.parentElement.appendChild(o);r.set(e)}else{if(o.parentElement){o.parentElement.removeChild(o)}}}function h(e){if(e){e.style.display="block"}}function f(e){if(e){e.style.display="none"}}function p(){g(o)}function g(e){if(e&&e.parentNode&&e.parentNode.removeChild){e.parentNode.removeChild(e)}}};Ops.Sidebar.DisplayValue_v2.prototype=new CABLES.Op;CABLES.OPS["3dd9927e-0d34-4442-8a8a-0ab843aee6e3"]={f:Ops.Sidebar.DisplayValue_v2,objName:"Ops.Sidebar.DisplayValue_v2"};Ops.String.NumberToString_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inValue("Number"),a=e.inInt("Decimal Places",4),i=e.outString("Result");let r=false;let o=1;a.onChange=s;n.onChange=l;s();l();function s(){r=a.get()<100;o=Math.pow(10,a.get());l()}function l(){if(r)i.set(String(Math.round(n.get()*o)/o));else i.set(String(n.get()||0))}};Ops.String.NumberToString_v2.prototype=new CABLES.Op;CABLES.OPS["5c6d375a-82db-4366-8013-93f56b4061a9"]={f:Ops.String.NumberToString_v2,objName:"Ops.String.NumberToString_v2"};Ops.Math.Accumulator=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTrigger("Trigger in"),a=e.inValueFloat("Add to number",0),i=e.inValueFloat("Multiplier to add number",1),r=e.inValueFloat("Default Value",1),o=e.inTriggerButton("Set Default Value"),s=e.outNumber("Current value");let l=performance.now();let u=0;let m=true;o.onTriggered=c;function c(){u=r.get();s.set(u);m=true}n.onTriggered=function(){if(!m){let e=(performance.now()-l)/100;u+=a.get()*e*i.get();s.set(u)}l=performance.now();m=false}};Ops.Math.Accumulator.prototype=new CABLES.Op;CABLES.OPS["460574ca-dca2-4283-8c37-57a8c446a51f"]={f:Ops.Math.Accumulator,objName:"Ops.Math.Accumulator"};Ops.Gl.GLTF.GltfGeometry=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const n=e.inTrigger("Update"),a=e.inString("Name","default"),i=e.inInt("Submesh",0),r=e.outTrigger("Next"),o=e.outObject("Geometry",null,"geometry"),s=e.outBoolNum("Found");const l=e.patch.cgl;let u=null;let m=null;i.onChange=a.onChange=function(){o.set(null);u=null;s.set(false);e.setUiAttrib({extendTitle:a.get()+"."+i.get()})};n.onTriggered=()=>{if(!l.frameStore.currentScene)return;if(m!=l.frameStore.currentScene.loaded)u=null;if(!u){if(!l.frameStore||!l.frameStore.currentScene||!l.frameStore.currentScene.nodes||!l.frameStore.currentScene.loaded){return}s.set(false);o.set(null);const t=a.get();m=l.frameStore.currentScene.loaded;for(let e=0;e<l.frameStore.currentScene.meshes.length;e++){if(l.frameStore.currentScene.meshes[e].name==t){u=l.frameStore.currentScene.meshes[e];const n=Math.abs(i.get());if(u.meshes[n]&&u.meshes[n].geom){s.set(true);o.set(u.meshes[n].geom)}}}}r.trigger()}};Ops.Gl.GLTF.GltfGeometry.prototype=new CABLES.Op;CABLES.OPS["2e59da07-455a-457c-99d8-1c23a1ddeea2"]={f:Ops.Gl.GLTF.GltfGeometry,objName:"Ops.Gl.GLTF.GltfGeometry"};Ops.Graphics.Geometry.ScaleGeometry=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};let n=e.inObject("Geometry");let s=e.inValue("Scale",1);let l=e.outObject("Result");s.onChange=n.onChange=a;function a(){let o=n.get();if(o){let t=o.copy();let e=vec3.create();let n=vec3.create();let a=vec3.create();let i=vec3.create();let r=s.get();for(let e=0;e<t.vertices.length;e+=3){t.vertices[e+0]*=r;t.vertices[e+1]*=r;t.vertices[e+2]*=r}l.set(t)}else l.set(null)}};Ops.Graphics.Geometry.ScaleGeometry.prototype=new CABLES.Op;CABLES.OPS["7730e67b-5916-4481-bcd1-54fa6e3a1d02"]={f:Ops.Graphics.Geometry.ScaleGeometry,objName:"Ops.Graphics.Geometry.ScaleGeometry"};Ops.Array.RandomNumbersArray_v4=function(){CABLES.Op.apply(this,arguments);const m=this;const e=m.attachments={};const c=m.inValueInt("Num Values",100),d=m.inSwitch("Mode",["A","AB","ABC","ABCD"],"A"),h=m.inValueFloat("Random Seed ",0),f=m.inBool("Integer",false),p=m.inValueBool("Last == First"),g=m.outArray("Array Out"),v=m.outNumber("Chunks Amount"),b=m.outNumber("Array length");const t=["A","B","C","D"];const x=[];const _=t.map(function(e){return{min:m.inValueFloat("Min "+e,-1),max:m.inValueFloat("Max "+e,1)}});for(let e=0;e<_.length;e+=1){const n=_[e];const i=Object.keys(n);m.setPortGroup("Value Range "+t[e],i.map(function(e){return n[e]}));if(e>0)i.forEach(function(e){n[e].setUiAttribs({greyout:true})})}d.onChange=function(){const e=d.get();const t=d.uiAttribs.values;g.setUiAttribs({stride:d.get().length});const i=t.indexOf(e);_.forEach(function(n,a){const e=Object.keys(n);e.forEach(function(e,t){if(a<=i)n[e].setUiAttribs({greyout:false});else n[e].setUiAttribs({greyout:true})})});a()};g.ignoreValueSerialize=true;p.onChange=c.onChange=h.onChange=f.onChange=a;const O=[];a();function a(){const e=d.get();const t=d.uiAttribs.values;const n=t.indexOf(e);const a=Math.floor(Math.abs(c.get()));Math.randomSeed=h.get();m.setUiAttrib({extendTitle:a+"*"+e.length});const i=n+1;const r=a*i;x.length=r;const o=r/i;const s=f.get();for(let t=0;t<i;t+=1){const e=_[t];const l=e.max.get();const u=e.min.get();O[t]=[u,l]}for(let t=0;t<o;t+=1){for(let e=0;e<i;e+=1){const u=O[e][0];const l=O[e][1];const n=t*i+e;if(s)x[n]=Math.floor(Math.seededRandom()*(l+1-u)+u);else x[n]=Math.seededRandom()*(l-u)+u}}if(p.get()&&x.length>i){for(let e=0;e<i;e++)x[x.length-3+e]=x[e]}g.setRef(x);v.set(x.length/i);b.set(x.length)}_.forEach(function(n){Object.keys(n).forEach(function(e){const t=n[e];t.onChange=a})})};Ops.Array.RandomNumbersArray_v4.prototype=new CABLES.Op;CABLES.OPS["8a9fa2c6-c229-49a9-9dc8-247001539217"]={f:Ops.Array.RandomNumbersArray_v4,objName:"Ops.Array.RandomNumbersArray_v4"};Ops.Array.ArrayPack3Simple=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const r=e.inArray("Array 1"),o=e.inArray("Array 2"),s=e.inArray("Array 3"),l=e.outArray("Array out",3),u=e.outNumber("Num Points"),m=e.outNumber("Array length");let n=false;let c=[];let d=[];let h=true;r.onChange=o.onChange=s.onChange=a;function a(){let t=r.get();let n=o.get();let a=s.get();if(!t&&!n&&!a){l.set(null);u.set(0);return}let i=0;if(!t||!n||!a){if(t)i=t.length;else if(n)i=n.length;else if(a)i=a.length;if(d.length!=i)for(let e=0;e<i;e++)d[e]=0;if(!t)t=d;if(!n)n=d;if(!a)a=d}if(t.length!==n.length||n.length!==a.length){e.setUiError("arraylen","Arrays do not have the same length !");return}e.setUiError("arraylen",null);c.length=t.length;for(let e=0;e<t.length;e++){c[e*3+0]=t[e];c[e*3+1]=n[e];c[e*3+2]=a[e]}h=false;l.setRef(c);u.set(c.length/3);m.set(c.length)}};Ops.Array.ArrayPack3Simple.prototype=new CABLES.Op;CABLES.OPS["9c48785b-4cac-472c-a70f-dbd3c240b782"]={f:Ops.Array.ArrayPack3Simple,objName:"Ops.Array.ArrayPack3Simple"};Ops.Array.Array1toX=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const r=e.inArray("Array1x"),a=e.inSwitch("Format",["AB","ABC","ABCD"],"ABC"),i=e.inSwitch("A",["Input","index","0-1","-1-1","0","1"],"Input"),o=e.inSwitch("B",["Input","index","0-1","-1-1","0","1"],"0-1"),s=e.inSwitch("C",["Input","index","0-1","-1-1","0","1"],"0"),l=e.inSwitch("D",["Input","index","0-1","-1-1","0","1"],"0"),u=e.outArray("Array3x"),m=e.outNumber("Total points"),c=e.outNumber("Array length");const d=[];i.onChange=o.onChange=s.onChange=l.onChange=r.onChange=n;a.onChange=function(){s.setUiAttribs({greyout:a.get().length<3});l.setUiAttribs({greyout:a.get().length<4});n()};function h(t,n,a){for(let e=0;e<n;e+=a){d[e+t]=0}}function f(t,n,a){for(let e=0;e<n;e+=a){d[e+t]=1}}function p(t,n,a){const i=r.get();for(let e=0;e<n;e+=a){d[e+t]=i[e/a]}}function g(t,n,a){for(let e=0;e<n;e+=a){d[e+t]=e/n||0}}function v(t,n,a){for(let e=0;e<n;e+=a){d[e+t]=e/a}}function b(e,t,n){if(t=="0")h(e,d.length,n);if(t=="0-1")g(e,d.length,n);if(t=="1")f(e,d.length,n);if(t=="Input")p(e,d.length,n);if(t=="index")v(e,d.length,n)}function n(){const e=r.get();if(!e){u.set(null);m.set(0);c.set(0);return}const t=a.get().length;const n=e.length*t;d.length=n;if(t>=2)b(0,i.get(),t);if(t>=2)b(1,o.get(),t);if(t>=3)b(2,s.get(),t);if(t>=4)b(3,l.get(),t);u.setRef(d);m.set(d.length/t);c.set(d.length)}};Ops.Array.Array1toX.prototype=new CABLES.Op;CABLES.OPS["6a8947be-79c8-4998-9853-1e0912654800"]={f:Ops.Array.Array1toX,objName:"Ops.Array.Array1toX"};Ops.Array.ArrayMathExpression=function(){CABLES.Op.apply(this,arguments);const c=this;const e=c.attachments={};const d=c.inArray("A"),h=c.inArray("B"),f=c.inArray("C"),p=c.inFloat("X",1),g=c.inFloat("Y",1),v=c.inFloat("Z",1),t=c.inString("Expression","a*(b+c+d)"),b=c.outArray("Result Array"),x=c.outNumber("Array Length"),_=c.outBoolNum("Expression Valid");c.setPortGroup("Expression",[t]);c.setPortGroup("Parameters",[d,h,f,p,g,v]);const n=false;const a=false;const O=[];let A=t.get();let I=false;let T=false;d.onChange=h.onChange=f.onChange=p.onChange=g.onChange=v.onChange=r;t.onChange=i;function i(){try{A=new Function("m","a","b","c","x","y","z","i","len",`with(m) { return ${t.get()} }`);I=true;r();_.set(I)}catch(e){I=false;_.set(I);b.set(null);if(e instanceof ReferenceError||e instanceof SyntaxError)return}}function r(){const e=d.get();const t=h.get();const n=f.get();const a=[e,t,n];const i=p.get();const r=g.get();const o=v.get();if(a.filter(Boolean).length===0){b.set(null);x.set(0);b.set(null);return}else{const s=a.map(e=>{return e?e.length:undefined});const l=s.find(Boolean);const u=s.filter(Boolean).every(e=>{return e===l});let t=[];if(u){c.setUiError("notsamelength",null);const m=a.find(Boolean);t=a.map((e,t)=>{if(!e)e=a.find(Boolean).map(e=>{return 0});return e});O.length=m.length;if(I){for(let e=0;e<m.length;e+=1){O[e]=A(Math,t[0][e],t[1][e],t[2][e],i,r,o,e,O.length)}b.set(null);b.set(O);x.set(O.length)}}else{b.set(null);x.set(0);c.setUiError("notsamelength","Arrays do not have the same length!",2);T=true}}_.set(I)}};Ops.Array.ArrayMathExpression.prototype=new CABLES.Op;CABLES.OPS["663e32a2-45a1-4141-a387-d8a44d4977d5"]={f:Ops.Array.ArrayMathExpression,objName:"Ops.Array.ArrayMathExpression"};Ops.Array.ArraySum=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={};const a=e.inArray("In"),i=e.inValue("Value",1),r=e.outArray("Result");let o=[];r.set(o);a.onLinkChanged=()=>{if(a)a.copyLinkedUiAttrib("stride",r)};i.onChange=a.onChange=function(){let t=a.get();if(!t)return;let n=i.get();if(o.length!=t.length)o.length=t.length;for(let e=0;e<t.length;e++){o[e]=t[e]+n}r.setRef(o)}};Ops.Array.ArraySum.prototype=new CABLES.Op;CABLES.OPS["c6b5bf63-0be8-4eea-acc0-9d32973e665a"]={f:Ops.Array.ArraySum,objName:"Ops.Array.ArraySum"};Ops.Gl.ImageCompose.Hue=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={hue_frag:"UNI float hue;\n\n#ifdef HAS_TEXTURES\n  IN vec2 texCoord;\n  UNI sampler2D tex;\n#endif\n\n#ifdef TEX_MASK\n    UNI sampler2D texMask;\n#endif\n#ifdef TEX_OFFSET\n    UNI sampler2D texOffset;\n#endif\n\nvec3 rgb2hsv(vec3 c)\n{\n    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n\n    float d = q.x - min(q.w, q.y);\n    float e = 1.0e-10;\n    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n}\n\nvec3 hsv2rgb(vec3 c)\n{\n    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\nvoid main()\n{\n   vec4 col=vec4(1.0,0.0,0.0,1.0);\n    #ifdef HAS_TEXTURES\n        col=texture(tex,texCoord);\n        float h=hue;\n\n        #ifdef TEX_OFFSET\n            h += texture(texOffset,texCoord).r;\n        #endif\n\n\n        vec3 hsv = rgb2hsv(col.rgb);\n        hsv.x=hsv.x+h;\n\n        #ifndef TEX_MASK\n            col.rgb = hsv2rgb(hsv);\n        #endif\n\n        #ifdef TEX_MASK\n            col.rgb = mix(col.rgb,hsv2rgb(hsv),texture(texMask,texCoord).r);\n        #endif\n\n   #endif\n   outColor= col;\n}"};const n=e.inTrigger("render"),a=e.inValueSlider("hue",1),i=e.inTexture("Mask"),r=e.inTexture("Offset"),o=e.outTrigger("trigger");const s=e.patch.cgl;const l=new CGL.Shader(s,e.name,e);l.setSource(l.getDefaultVertexShader(),t.hue_frag);const u=new CGL.Uniform(l,"t","tex",0);const m=new CGL.Uniform(l,"t","texMask",1);const c=new CGL.Uniform(l,"t","texOffset",2);const d=new CGL.Uniform(l,"f","hue",1);a.onChange=function(){d.setValue(a.get())};i.onChange=r.onChange=()=>{l.toggleDefine("TEX_MASK",i.get());l.toggleDefine("TEX_OFFSET",r.get())};n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;s.pushShader(l);s.currentTextureEffect.bind();s.setTexture(0,s.currentTextureEffect.getCurrentSourceTexture().tex);if(i.get())s.setTexture(1,i.get().tex);if(r.get())s.setTexture(2,r.get().tex);s.currentTextureEffect.finish();s.popShader();o.trigger()}};Ops.Gl.ImageCompose.Hue.prototype=new CABLES.Op;CABLES.OPS["94ef0da0-c920-415c-81b0-fecbd437991d"]={f:Ops.Gl.ImageCompose.Hue,objName:"Ops.Gl.ImageCompose.Hue"};Ops.Gl.ShaderEffects.TextureProjection_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={maptexture_frag:"IN vec2 MOD_tc;\n\n#ifdef MOD_MAP_TRIPLANAR\n    IN vec2 MOD_tc1;\n    IN vec2 MOD_tc2;\n    IN vec3 MOD_blendingTri;\n#endif\n\n\n{{CGL.BLENDMODES3}}",maptexture_vert:"vec3 MOD_pos;\n\n#ifndef MOD_WORLDSPACE\n   MOD_pos=(vec4(vPosition,1.0)*1.0/MOD_scale).xyz;\n#endif\n#ifdef MOD_WORLDSPACE\n   MOD_pos=(mMatrix*pos).xyz*1.0/MOD_scale;\n#endif\n\nMOD_pos=(vec4(MOD_pos,1.0)*MOD_rotationX(MOD_rotX*MOD_DEG2RAD)).xyz;\nMOD_pos=(vec4(MOD_pos,1.0)*MOD_rotationY(MOD_rotY*MOD_DEG2RAD)).xyz;\nMOD_pos=(vec4(MOD_pos,1.0)*MOD_rotationZ(MOD_rotZ*MOD_DEG2RAD)).xyz;\n\n#ifdef MOD_MAP_XY\n    MOD_tc=MOD_pos.xy;\n#endif\n#ifdef MOD_MAP_XZ\n    MOD_tc=MOD_pos.xz;\n#endif\n#ifdef MOD_MAP_YZ\n    MOD_tc=MOD_pos.yz;\n#endif\n\nMOD_tc.xy+=vec2(0.5,0.5);\nMOD_tc.xy+=MOD_offset;\n\n\n#ifdef MOD_TARGET_POINTSIZE\n\n    gl_PointSize+=(texture(MOD_tex,MOD_tc).x*MOD_amount);\n\n#endif\n\n\n#ifdef MOD_MAP_TRIPLANAR\n    mapTriplanar((mMatrix*vec4(attrVertNormal,1.0)).xyz,MOD_pos);\n#endif\n\n",maptexture_body_frag:"#ifndef MOD_TARGET_POINTSIZE\n\n\n    vec4 MOD_color;\n\n    #ifdef MOD_MAP_TRIPLANAR\n        vec4 xaxis = texture( MOD_tex, MOD_tc);\n        vec4 yaxis = texture( MOD_tex, MOD_tc1);\n        vec4 zaxis = texture( MOD_tex, MOD_tc2);\n        MOD_color = xaxis *MOD_blendingTri.x + yaxis *MOD_blendingTri.y + zaxis *MOD_blendingTri.z;\n        MOD_color.a=1.0;\n    #endif\n\n\n    vec2 MOD_ntc=MOD_tc;\n\n    #ifdef MOD_MAP_SCREEN\n        MOD_ntc=(vec2(gl_FragCoord.x,gl_FragCoord.y)/vec2(MOD_viewPortW,MOD_viewPortH));\n\n        MOD_ntc-=vec2(0.5,0.5);\n        MOD_ntc*=1.0/MOD_scale;\n        MOD_ntc+=vec2(0.5,0.5);\n        MOD_ntc-=MOD_offset;\n    #endif\n\n    #ifdef MOD_MAP_TEXCOORD\n        MOD_ntc=texCoord*1.0/MOD_scale-MOD_offset;\n    #endif\n\n    #ifdef MOD_MAP_TEXCOORD1\n        MOD_ntc=texCoord1*1.0/MOD_scale-MOD_offset;\n    #endif\n\n    #ifdef MOD_MAP_TEXCOORD2\n        MOD_ntc=texCoord2*1.0/MOD_scale-MOD_offset;\n    #endif\n\n\n    #ifdef MOD_DISCARD\n    if(MOD_ntc.x>0.0 && MOD_ntc.x<1.0 && MOD_ntc.y>0.0 && MOD_ntc.y<1.0)\n    {\n    #endif\n\n        #ifndef MOD_MAP_TRIPLANAR\n            MOD_color=texture(MOD_tex,MOD_ntc);\n        #endif\n\n        #ifdef MOD_USE_IMGALPHA\n            col.a=MOD_color.a;\n        #endif\n\n        #ifdef MOD_TARGET_COLOR\n        col=cgl_blendPixel(col,MOD_color,MOD_amount*col.a);\n        #endif\n        #ifdef MOD_TARGET_ALPHA\n        col.a=1.0-MOD_color.r*MOD_amount;\n        #endif\n\n    #ifdef MOD_DISCARD\n    }\n\n    #endif\n#endif\n",maptexture_body_vert:"OUT vec2 MOD_tc;\n\nconst float MOD_DEG2RAD = 0.017453292519943;\n\n#ifdef MOD_MAP_TRIPLANAR\n\n    OUT vec2 MOD_tc1;\n    OUT vec2 MOD_tc2;\n    OUT vec3 MOD_blendingTri;\n\n    void mapTriplanar(vec3 wNorm,vec3 pos)\n    {\n        vec3 blending = abs( wNorm );\n        blending = normalize(max(blending, 0.1));\n        float b = (blending.x + blending.y + blending.z);\n        blending /= vec3(b);\n        MOD_blendingTri=blending;\n\n        MOD_tc = pos.yz;\n        MOD_tc1 = pos.xz;\n        MOD_tc2 = pos.xy;\n    }\n\n#endif\n\nmat4 MOD_rotationX( in float angle ) {\n\treturn mat4(\t1.0,\t\t0,\t\t\t0,\t\t\t0,\n\t\t\t \t\t0, \tcos(angle),\t-sin(angle),\t\t0,\n\t\t\t\t\t0, \tsin(angle),\t cos(angle),\t\t0,\n\t\t\t\t\t0, \t\t\t0,\t\t\t  0, \t\t1);\n}\n\nmat4 MOD_rotationY( in float angle ) {\n\treturn mat4(\tcos(angle),\t\t0,\t\tsin(angle),\t0,\n\t\t\t \t\t\t\t0,\t\t1.0,\t\t\t 0,\t0,\n\t\t\t\t\t-sin(angle),\t0,\t\tcos(angle),\t0,\n\t\t\t\t\t\t\t0, \t\t0,\t\t\t\t0,\t1);\n}\n\nmat4 MOD_rotationZ( in float angle ) {\n\treturn mat4(\tcos(angle),\t\t-sin(angle),\t0,\t0,\n\t\t\t \t\tsin(angle),\t\tcos(angle),\t\t0,\t0,\n\t\t\t\t\t\t\t0,\t\t\t\t0,\t\t1,\t0,\n\t\t\t\t\t\t\t0,\t\t\t\t0,\t\t0,\t1);\n}\n"};const n=e.inTrigger("render"),a=e.outTrigger("trigger"),i=e.inTexture("Texture"),r=CGL.TextureEffect.AddBlendSelect(e,"blendMode"),o=e.inValueSlider("Amount",.3),s=e.inSwitch("Target",["Color","Pointsize","Alpha"],"Color"),l=e.inValue("Scale",10),u=e.inBool("Use Texture Alpha",false),m=e.inFloat("Pos X",0),c=e.inFloat("Pos Y",0),d=e.inFloat("Rot X",0),h=e.inFloat("Rot Y",0),f=e.inFloat("Rot Z",0),p=e.inValueSelect("Mapping",["Triplanar","XY","XZ","YZ","Screen","TexCoords 1","TexCoords 2","TexCoords 3"],"XY"),g=e.inValueBool("Discard"),v=e.inValueBool("WorldSpace");const b=e.patch.cgl;n.onLinkChanged=u.onChange=s.onChange=r.onChange=g.onChange=v.onChange=i.onLinkChanged=p.onChange=I;e.toWorkPortsNeedToBeLinked(i,a);e.setPortGroup("Rotation",[d,h,f]);e.setPortGroup("Position",[m,c]);const x=new CGL.ShaderModifier(b,e.name,{opId:e.id});x.addModule({title:e.name,name:"MODULE_VERTEX_POSITION",srcHeadVert:t.maptexture_body_vert,srcBodyVert:t.maptexture_vert,attributes:[{type:"vec2",name:"attrTexCoord1",nameFrag:"texCoord1"},{type:"vec2",name:"attrTexCoord2",nameFrag:"texCoord2"}]});let _=t.maptexture_frag;x.addModule({title:e.name,name:"MODULE_COLOR",srcHeadFrag:_,srcBodyFrag:t.maptexture_body_frag});x.addUniformBoth("f","MOD_rotX",d);x.addUniformBoth("f","MOD_rotY",h);x.addUniformBoth("f","MOD_rotZ",f);x.addUniformBoth("t","MOD_tex");x.addUniformBoth("f","MOD_scale",l);x.addUniformBoth("f","MOD_amount",o);x.addUniformBoth("2f","MOD_offset",m,c);const O=x.addUniformFrag("f","MOD_viewPortW");const A=x.addUniformFrag("f","MOD_viewPortH");CGL.TextureEffect.setupBlending(e,x,r,o);I();function I(){x.toggleDefine("MOD_USE_IMGALPHA",u.get());x.toggleDefine("MOD_WORLDSPACE",v.get());x.toggleDefine("MOD_MAP_XY",p.get()=="XY");x.toggleDefine("MOD_MAP_XZ",p.get()=="XZ");x.toggleDefine("MOD_MAP_YZ",p.get()=="YZ");x.toggleDefine("MOD_MAP_TEXCOORD",p.get()=="TexCoords 1");x.toggleDefine("MOD_MAP_TEXCOORD1",p.get()=="TexCoords 2");x.toggleDefine("MOD_MAP_TEXCOORD2",p.get()=="TexCoords 3");x.toggleDefine("MOD_MAP_SCREEN",p.get()=="Screen");x.toggleDefine("MOD_MAP_TRIPLANAR",p.get()=="Triplanar");x.toggleDefine("MOD_DISCARD",g.get());x.toggleDefine("MOD_BLEND_NORMAL",r.get()=="Normal");x.toggleDefine("MOD_BLEND_ADD",r.get()=="Add");x.toggleDefine("MOD_BLEND_MUL",r.get()=="Mul");x.toggleDefine("MOD_BLEND_MUL",r.get()=="Mul");x.toggleDefine("MOD_TARGET_ALPHA",s.get()=="Alpha");x.toggleDefine("MOD_TARGET_COLOR",s.get()=="Color");x.toggleDefine("MOD_TARGET_POINTSIZE",s.get()=="Pointsize");if(s.get()=="Pointsize"&&p.get()=="Screen")e.setUiError("pointscreen","This combination of Mapping and Target is not possible",1);else e.setUiError("pointscreen",null);CGL.TextureEffect.setupBlending(e,x,r,o)}n.onTriggered=function(){const e=b.getViewPort();x.bind();x.setUniformValue("MOD_viewPortW",e[2]);x.setUniformValue("MOD_viewPortH",e[3]);let t=i.get();if(!t)t=CGL.Texture.getEmptyTexture(b).tex;else t=t.tex;x.pushTexture("MOD_tex",t);a.trigger();x.unbind()}};Ops.Gl.ShaderEffects.TextureProjection_v2.prototype=new CABLES.Op;CABLES.OPS["9be647c2-7afd-40ed-b669-9826ea6a50ca"]={f:Ops.Gl.ShaderEffects.TextureProjection_v2,objName:"Ops.Gl.ShaderEffects.TextureProjection_v2"};Ops.Team.Mdlviz_a0rO0B.CustomNoise=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;\n\nfloat nrand( vec2 n )\n{\n\treturn fract(sin(dot(n.xy, vec2(12.9898, 78.233)))* 43758.5453);\n}\n\n// Thanks to Dave Hoskins\nvec3 hash32(vec2 p)\n{\n\tp  = fract(p * vec2(5.3983, 5.4427));\n    p += dot(p.yx, p.xy +  vec2(21.5351, 14.3137));\n\treturn fract(vec3(p.x * p.y * 95.4337, p.x * p.y * 97.597, p.x * p.y * 93.8365));\n}\n\nfloat n1rand( vec2 n )\n{\n\tfloat t = fract( time );\n\tfloat nrnd0 = nrand( n + 0.07*t );\n\treturn nrnd0;\n}\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(n1rand(texCoord.xy+vec2(time)),1.0);\n    #else\n        float r=n1rand(texCoord.xy+vec2(time));\n        rnd=vec4( hash32(texCoord.xy + time * 1.),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    outColor=cgl_blendPixel(base,col,amount);\n    // outColor=vec4( mix( col.rgb, base.rgb ,1.0-base.a*amount),1.0);\n}"};const n=e.inTrigger("Render"),a=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),i=CGL.TextureEffect.AddBlendAlphaMask(e),r=e.inValueSlider("Amount",1),o=e.inValueBool("Animated",true),s=e.inValueBool("RGB",false),l=e.inValueBool("Normalize",false),u=e.inTexture("Multiply"),m=e.outTrigger("Next");const c=e.patch.cgl,d=new CGL.Shader(c,e.name),h=new CGL.Uniform(d,"f","amount",r),f=new CGL.Uniform(d,"f","time",1),p=new CGL.Uniform(d,"t","tex",0),g=new CGL.Uniform(d,"t","texMul",1);d.setSource(d.getDefaultVertexShader(),t.noise_frag);CGL.TextureEffect.setupBlending(e,d,a,r,i);e.toWorkPortsNeedToBeLinked(n);u.onChange=l.onChange=s.onChange=function(){d.toggleDefine("HAS_MULMASK",u.get());d.toggleDefine("RGB",s.get());d.toggleDefine("NORMALIZE",l.get())};n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;if(o.get())f.setValue(e.patch.freeTimer.get()/1e3%100);else f.setValue(0);c.pushShader(d);c.setTexture(0,c.currentTextureEffect.getCurrentSourceTexture().tex);if(u.get())c.setTexture(1,u.get().tex);c.currentTextureEffect.bind();c.currentTextureEffect.finish();c.popShader();m.trigger()}};Ops.Team.Mdlviz_a0rO0B.CustomNoise.prototype=new CABLES.Op;CABLES.OPS["56672509-2487-45da-be8f-85795b267840"]={f:Ops.Team.Mdlviz_a0rO0B.CustomNoise,objName:"Ops.Team.Mdlviz_a0rO0B.CustomNoise"};Ops.Gl.ImageCompose.Desaturate=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={desaturate_frag:"\nIN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\n\n#ifdef MASK\n    UNI sampler2D mask;\n#endif\n\nvec3 desaturate(vec3 color, float amount)\n{\n   vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), color));\n   return vec3(mix(color, gray, amount));\n}\n\nvoid main()\n{\n    vec4 col=texture(tex,texCoord);\n\n    float am=amount;\n    #ifdef MASK\n        am*=1.0-texture(mask,texCoord).r;\n        #ifdef INVERTMASK\n        am=1.0-am;\n        #endif\n    #endif\n\n    col.rgb=desaturate(col.rgb,am);\n    outColor= col;\n}"};const n=e.inTrigger("render");const a=e.outTrigger("trigger");const i=e.inValueSlider("amount",1);const r=e.inTexture("Mask");const o=e.inValueBool("Invert Mask");const s=e.patch.cgl;const l=new CGL.Shader(s,e.name,e);l.setSource(l.getDefaultVertexShader(),t.desaturate_frag);let u=new CGL.Uniform(l,"t","tex",0);let m=new CGL.Uniform(l,"t","mask",1);let c=new CGL.Uniform(l,"f","amount",i);o.onChange=function(){if(o.get())l.define("INVERTMASK");else l.removeDefine("INVERTMASK")};r.onChange=function(){if(r.get())l.define("MASK");else l.removeDefine("MASK")};n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e))return;s.pushShader(l);s.currentTextureEffect.bind();s.setTexture(0,s.currentTextureEffect.getCurrentSourceTexture().tex);if(r.get())s.setTexture(1,r.get().tex);s.currentTextureEffect.finish();s.popShader();a.trigger()}};Ops.Gl.ImageCompose.Desaturate.prototype=new CABLES.Op;CABLES.OPS["340efbd5-be53-4bd5-92ad-8f38d8eeecf1"]={f:Ops.Gl.ImageCompose.Desaturate,objName:"Ops.Gl.ImageCompose.Desaturate"};Ops.Gl.ImageCompose.Noise.ValueNoise_v2=function(){CABLES.Op.apply(this,arguments);const e=this;const t=e.attachments={valuenoise3d_frag:"UNI float z;\nUNI float x;\nUNI float y;\nUNI float scale;\nUNI float amount;\nIN vec2 texCoord;\nUNI sampler2D tex;\nUNI float aspect;\n\n{{CGL.BLENDMODES3}}\n\n//\n//\tValue Noise 3D\n//\tReturn value range of 0.0->1.0\n//\thttp://briansharpe.files.wordpress.com/2011/11/valuesample1.jpg\n//\n\nfloat Interpolation_C2( float x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }   //  6x^5-15x^4+10x^3\t( Quintic Curve.  As used by Perlin in Improved Noise.  http://mrl.nyu.edu/~perlin/paper445.pdf )\nvec2 Interpolation_C2( vec2 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec3 Interpolation_C2( vec3 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2( vec4 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2_InterpAndDeriv( vec2 x ) { return x.xyxy * x.xyxy * ( x.xyxy * ( x.xyxy * ( x.xyxy * vec2( 6.0, 0.0 ).xxyy + vec2( -15.0, 30.0 ).xxyy ) + vec2( 10.0, -60.0 ).xxyy ) + vec2( 0.0, 30.0 ).xxyy ); }\nvec3 Interpolation_C2_Deriv( vec3 x ) { return x * x * (x * (x * 30.0 - 60.0) + 30.0); }\n\nvoid FAST32_hash_3D( vec3 gridcell, out vec4 lowz_hash, out vec4 highz_hash )\t//\tgenerates a random number for each of the 8 cell corners\n{\n    //    gridcell is assumed to be an integer coordinate\n\n    //\tTODO: \tthese constants need tweaked to find the best possible noise.\n    //\t\t\tprobably requires some kind of brute force computational searching or something....\n    const vec2 OFFSET = vec2( 50.0, 161.0 );\n    const float DOMAIN = 69.0;\n    const float SOMELARGEFLOAT = 635.298681;\n    const float ZINC = 48.500388;\n\n    //\ttruncate the domain\n    gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n    vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n    //\tcalculate the noise\n    vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n    P *= P;\n    P = P.xzxz * P.yyww;\n    highz_hash.xy = vec2( 1.0 / ( SOMELARGEFLOAT + vec2( gridcell.z, gridcell_inc1.z ) * ZINC ) );\n    lowz_hash = fract( P * highz_hash.xxxx );\n    highz_hash = fract( P * highz_hash.yyyy );\n}\n\n\nfloat Value3D( vec3 P )\n{\n    //\testablish our grid cell and unit position\n    vec3 Pi = floor(P);\n    vec3 Pf = P - Pi;\n\n    //\tcalculate the hash.\n    //\t( various hashing methods listed in order of speed )\n    vec4 hash_lowz, hash_highz;\n    FAST32_hash_3D( Pi, hash_lowz, hash_highz );\n    //FAST32_2_hash_3D( Pi, hash_lowz, hash_highz );\n    //BBS_hash_3D( Pi, hash_lowz, hash_highz );\n    //SGPP_hash_3D( Pi, hash_lowz, hash_highz );\n\n    //\tblend the results and return\n    vec3 blend = Interpolation_C2( Pf );\n    vec4 res0 = mix( hash_lowz, hash_highz, blend.z );\n    vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n    return dot( res0, blend2.zxzx * blend2.wwyy );\n}\n\nvoid main()\n{\n    vec2 tc=texCoord;\n    tc.y/=aspect;\n    vec4 base=texture(tex,tc);\n\n    vec2 p=vec2(tc.x-0.5,tc.y-0.5);\n    p=p*scale;\n\n    p=vec2(p.x+0.5-x,p.y+0.5-y);\n\n    float v=Value3D(vec3(p.x,p.y,z));\n    vec4 col=vec4(v,v,v,1.0);\n\n    outColor=cgl_blendPixel(base,col,amount);\n\n}\n"};const n=e.inTrigger("render"),a=CGL.TextureEffect.AddBlendSelect(e,"Blend Mode","normal"),i=e.inValueSlider("Amount",1),r=e.inValue("Scale",25),o=e.inValue("X",0),s=e.inValue("Y",0),l=e.inValue("Z",0),u=e.outTrigger("trigger");e.setPortGroup("Position",[o,s,l]);e.setPortGroup("Look",[r]);const m=e.patch.cgl;const c=new CGL.Shader(m,e.name,e);c.setSource(CGL.Shader.getDefaultVertexShader(),t.valuenoise3d_frag);const d=new CGL.Uniform(c,"t","tex",0),h=new CGL.Uniform(c,"f","z",l),f=new CGL.Uniform(c,"f","x",o),p=new CGL.Uniform(c,"f","y",s),g=new CGL.Uniform(c,"f","scale",r),v=new CGL.Uniform(c,"f","aspect",1),b=new CGL.Uniform(c,"f","amount",i);CGL.TextureEffect.setupBlending(e,c,a,i);n.onTriggered=function(){if(!CGL.TextureEffect.checkOpInEffect(e,3))return;m.pushShader(c);m.currentTextureEffect.bind();m.setTexture(0,m.currentTextureEffect.getCurrentSourceTexture().tex);v.setValue(m.currentTextureEffect.aspectRatio);m.currentTextureEffect.finish();m.popShader();u.trigger()}};Ops.Gl.ImageCompose.Noise.ValueNoise_v2.prototype=new CABLES.Op;CABLES.OPS["d2748c53-9ac1-4cd7-8176-66d3eb5d1bb6"]={f:Ops.Gl.ImageCompose.Noise.ValueNoise_v2,objName:"Ops.Gl.ImageCompose.Noise.ValueNoise_v2"};Ops.Gl.Matrix.Scale=function(){CABLES.Op.apply(this,arguments);const t=this;const e=t.attachments={};const n=t.inTrigger("render"),a=t.inValueFloat("scale",1),i=t.inValueFloat("x",1),r=t.inValueFloat("y",1),o=t.inValueFloat("z",1),s=t.outTrigger("trigger");t.setPortGroup("Axis",[i,r,o]);const l=vec3.create();i.onChange=r.onChange=o.onChange=a.onChange=u;u();n.onTriggered=function(){const e=t.patch.cg||t.patch.cgl;e.pushModelMatrix();mat4.scale(e.mMatrix,e.mMatrix,l);s.trigger();e.popModelMatrix()};function u(){const e=a.get();vec3.set(l,e*i.get(),e*r.get(),e*o.get())}};Ops.Gl.Matrix.Scale.prototype=new CABLES.Op;CABLES.OPS["50e7f565-0cdb-47ca-912b-87c04e2f00e3"]={f:Ops.Gl.Matrix.Scale,objName:"Ops.Gl.Matrix.Scale"};window.addEventListener("load",function(e){CABLES.jsLoaded=new Event("CABLES.jsLoaded");document.dispatchEvent(CABLES.jsLoaded)});(()=>{"use strict";var e={};const t=class{constructor(){this.patch=null;this.fsElement=null;this.callbacks={}}add(e,t,n){this.patch=e;this.callbacks[t]=n;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 m{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(!CABLES.UI&&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 i={};i.float32Concat=function(e,t){if(!(e instanceof Float32Array))e=new Float32Array(e);if(!(t instanceof Float32Array))t=new Float32Array(t);const n=new Float32Array(e.length+t.length);n.set(e);n.set(t,e.length);return n};const k=function(e){let t=e.split(".")[e.split(".").length-1];if(t.contains(CONSTANTS.OP.OP_VERSION_PREFIX)){const n=t.split(CONSTANTS.OP.OP_VERSION_PREFIX)[1];t=t.substring(0,t.length-(CONSTANTS.OP.OP_VERSION_PREFIX+n).length)}return t};const B=function(t){for(let e=t.length-1;e>0;e--){const n=Math.floor(Math.seededRandom()*(e+1));const a=t[e];t[e]=t[n];t[n]=a}return t};const t={};const n=function(){let e=Math.random().toString(36).substr(2,9);if(t.hasOwnProperty(e))e=n();t[e]=true;return e};const D=null&&n;const a=function(){let n=(new Date).getTime();const e="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=(n+Math.random()*16)%16|0;n=Math.floor(n/16);return(e=="x"?t:t&3|8).toString(16)});return e};const G=null&&a;const U=null&&a;function r(e){for(const t in e){if(e[t]&&typeof objValue==="object"&&e[t].constructor===Object)e[t]=r(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 o=function(n,e="id"){let a=0;if(Array.prototype.reduce){a=n.split("").reduce((e,t)=>{e=(e<<5)-e+t.charCodeAt(0);return e&e},0)}else{if(n.length>0){for(let t=0;t<n.length;t++){let e=n.charCodeAt(t);a=(a<<5)-a+e;a&=a}}}return e+""+a};const F=null&&o;let s=0;const V=function(){s++;return s};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 X=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 q=function(e,t,n){return Math.min(Math.max(e,t),n)};const H=function(e,t,n,a,i,r){if(e>=n)return i;if(e<=t)return a;let o=false;const s=Math.min(t,n);const l=Math.max(t,n);if(s!=t)o=true;let u=false;const m=Math.min(a,i);const c=Math.max(a,i);if(m!=a)u=true;let d=0;let h=0;if(o)d=(l-e)*(c-m)/(l-s);else d=(e-s)*(c-m)/(l-s);if(u)h=c-d;else h=d+m;if(!r)return h;if(r==1){e=Math.max(0,Math.min(1,(h-a)/(i-a)));return a+e*e*(3-2*e)*(i-a)}if(r==2){e=Math.max(0,Math.min(1,(h-a)/(i-a)));return a+e*e*e*(e*(e*6-15)+10)*(i-a)}return h};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 n=Math.randomSeed/233280;return t+n*(e-t)};i.isNumeric=function(e){return!isNaN(parseFloat(e))&&isFinite(e)};i.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 W=function(e=""){if(!e)return"";if(e.startsWith("data:"))return;if(e.contains("?"))e+="&";else e+="?";return e+"cache="+CABLES.uuid()};const Y=function(t,n){if(!t)return null;n=n||[];n.length=t.length;for(let e=0;e<t.length;e++){n[e]=t[e]}return n};const Z=function(e){let t=CABLES.filename(e);const n=t.split(".");t=n[0];return t};const K=function(){console.log("logstack",(new Error).stack)};const Q=function(e){let t="";if(!e)return"";if(e.startsWith("data:")&&e.contains(":")){const n=e.split(",");return n[0]}let n=(e+"").split("/");if(n.length>0){const a=n[n.length-1];let e=a.split("?");t=e[0]}return t||""};const J=function(e,t,n,a,i){u({url:e,cb:t,method:n,data:a,contenttype:i,sync:true})};const $=function(e,t,n,a,i,r,o={},s={}){const l={url:e,cb:t,method:n,data:a,contenttype:i,sync:false,jsonP:r,headers:o};if(s&&s.credentials)l.credentials=s.credentials;u(l)};const u=function(t){if(!t.hasOwnProperty("asynch"))t.asynch=true;let n;try{n=new XMLHttpRequest}catch(e){}n.onreadystatechange=function(){if(n.readyState!=4)return;if(t.cb){if(n.status==200||n.status==0)t.cb(false,n.responseText,n);else t.cb(true,n.responseText,n)}};try{n.open(t.method?t.method.toUpperCase():"GET",t.url,!t.sync)}catch(e){if(t.cb&&e)t.cb(true,e.msg,n)}if(typeof t.headers==="object"){if(t.headers){const a=Object.keys(t.headers);for(let e=0;e<a.length;e++){const i=a[e];const r=t.headers[i];n.setRequestHeader(i,r)}}}if(t.credentials&&t.credentials!=="omit"){n.withCredentials=true}try{if(!t.post&&!t.data){n.send()}else{n.setRequestHeader("Content-type",t.contenttype?t.contenttype:"application/x-www-form-urlencoded");n.send(t.data||t.post)}}catch(e){if(t.cb)t.cb(true,e.msg,n)}};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 a="ERROR<br/>for more info, open your browsers dev tools console (Ctrl+Shift+I or Command+Alt+I)<br/>";for(let n=0;n<CABLES.errorConsole.log.length;n++){a+=CABLES.errorConsole.log[n].initiator+" ";for(let e=1;e<CABLES.errorConsole.log[n].arguments.length;e++){if(e>2)a+=", ";let t=CABLES.errorConsole.log[n].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;a+=e}else if(typeof t=="string")a+=t;else if(typeof t=="number")a+=String(t)+" "}a+="<br/>"}CABLES.errorConsole.ele.innerHTML=a};class l{constructor(e){this._init();this._first=true;this._wireMesh=null;if(e)this.apply(e)}_init(){this._max=[-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE];this._min=[Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE];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 n=t;this.applyPos(n.maxX,n.maxY,n.maxZ);this.applyPos(n.minX,n.minY,n.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,n){if(e==Number.MAX_VALUE||e==-Number.MAX_VALUE||t==Number.MAX_VALUE||t==-Number.MAX_VALUE||n==Number.MAX_VALUE||n==-Number.MAX_VALUE)return;if(!CABLES.UTILS.isNumeric(e)||!CABLES.UTILS.isNumeric(t)||!CABLES.UTILS.isNumeric(n))return;if(this._first){this._max[0]=e;this._max[1]=t;this._max[2]=n;this._min[0]=e;this._min[1]=t;this._min[2]=n;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],n);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],n)}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,n){if(!this._wireMesh)this._wireMesh=new CGL.WireCube(e);e.pushModelMatrix();mat4.translate(e.mMatrix,e.mMatrix,this._center);if(CABLES.UI&&n){CABLES.UI.OverlayMeshes.drawCube(n,this._size[0]/2,this._size[1]/2,this._size[2]/2)}e.popModelMatrix()}}const c=function(e){this.name=e||"unknown";this._log=new m("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)}})};c.prototype.clear=function(){this._vertices=new Float32Array([]);this.verticesIndices=[];this.texCoords=new Float32Array([]);this.vertexNormals=new Float32Array([]);this.tangents=[];this.biTangents=[];this._attributes={}};c.prototype.getAttributes=function(){return this._attributes};c.prototype.getAttribute=function(e){for(const t in this._attributes){if(this._attributes[t].name==e)return this._attributes[t]}return null};c.prototype.setAttribute=function(e,t,n){let a="";if(!n||n>4){console.log("itemsize wrong?",n,e);this._log.stack("itemsize");n=3}if(n==1)a="float";else if(n==2)a="vec2";else if(n==3)a="vec3";else if(n==4)a="vec4";const i={name:e,data:t,itemSize:n,type:a};this._attributes[e]=i};c.prototype.copyAttribute=function(e,t){const n=this.getAttribute(e);t.setAttribute(e,new Float32Array(n.data),n.itemSize)};c.prototype.setVertices=function(e){if(e instanceof Float32Array)this._vertices=e;else this._vertices=new Float32Array(e)};c.prototype.setTexCoords=function(e){if(e instanceof Float32Array)this.texCoords=e;else this.texCoords=new Float32Array(e)};c.prototype.calcNormals=function(e){const t={smooth:e};this.calculateNormals(t)};c.prototype.flipNormals=function(t,n,a){let i=vec3.create();if(t==undefined)t=1;if(n==undefined)n=1;if(a==undefined)a=1;for(let e=0;e<this.vertexNormals.length;e+=3){vec3.set(i,this.vertexNormals[e+0],this.vertexNormals[e+1],this.vertexNormals[e+2]);i[0]*=-t;i[1]*=-n;i[2]*=-a;vec3.normalize(i,i);this.vertexNormals[e+0]=i[0];this.vertexNormals[e+1]=i[1];this.vertexNormals[e+2]=i[2]}};c.prototype.getNumTriangles=function(){if(this.verticesIndices&&this.verticesIndices.length)return this.verticesIndices.length/3;return this.vertices.length/3};c.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};c.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}};c.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 n=this.verticesIndices.length;const a=this._vertices.length/3;this.verticesIndices.length+=t.verticesIndices.length;for(let e=0;e<t.verticesIndices.length;e++)this.verticesIndices[n+e]=t.verticesIndices[e]+a;this.vertices=i.float32Concat(this._vertices,t.vertices);this.texCoords=i.float32Concat(this.texCoords,t.texCoords);this.vertexNormals=i.float32Concat(this.vertexNormals,t.vertexNormals);this.tangents=i.float32Concat(this.tangents,t.tangents);this.biTangents=i.float32Concat(this.biTangents,t.biTangents)};c.prototype.copy=function(){const t=new c(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};c.prototype.calculateNormals=function(t){t=t||{};if(t.smooth===false)this.unIndex();const n=vec3.create();const a=vec3.create();const i=vec3.create();function r(e){vec3.subtract(n,e[0],e[1]);vec3.subtract(a,e[0],e[2]);vec3.cross(i,n,a);vec3.normalize(i,i);if(t&&t.forceZUp){if(i[2]<0){i[0]*=-1;i[1]*=-1;i[2]*=-1}}return i}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 o=[];for(let e=0;e<this.vertices.length;e+=9){const s=[[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=r(s);o.push(l[0],l[1],l[2],l[0],l[1],l[2],l[0],l[1],l[2])}this.vertexNormals=o}else{const u=[];u.length=Math.floor(this.verticesIndices.length/3);for(let e=0;e<this.verticesIndices.length;e+=3){const s=[this.getVertexVec(this.verticesIndices[e+0]),this.getVertexVec(this.verticesIndices[e+1]),this.getVertexVec(this.verticesIndices[e+2])];u[e/3]=r(s);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 m=[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(m,m);this.vertexNormals[this.verticesIndices[t+e]*3+0]=m[0];this.vertexNormals[this.verticesIndices[t+e]*3+1]=m[1];this.vertexNormals[this.verticesIndices[t+e]*3+2]=m[2]}}}};c.prototype.calcTangentsBitangents=function(){if(!this.vertices.length){return}if(!this.vertexNormals.length){return}if(!this.texCoords.length){const _=this.vertices.length/3*2;this.texCoords=new Float32Array(_);for(let e=0;e<_;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 n=this.vertices.length/3;this.tangents=new Float32Array(this.vertexNormals.length);this.biTangents=new Float32Array(this.vertexNormals.length);const a=[];a.length=n*2;const i=vec3.create();const r=vec3.create();const o=vec3.create();const s=vec2.create();const l=vec2.create();const u=vec2.create();const m=vec3.create();const c=vec3.create();for(let e=0;e<t;e+=1){const O=this.verticesIndices[e*3];const A=this.verticesIndices[e*3+1];const I=this.verticesIndices[e*3+2];vec3.set(i,this.vertices[O*3],this.vertices[O*3+1],this.vertices[O*3+2]);vec3.set(r,this.vertices[A*3],this.vertices[A*3+1],this.vertices[A*3+2]);vec3.set(o,this.vertices[I*3],this.vertices[I*3+1],this.vertices[I*3+2]);vec2.set(s,this.texCoords[O*2],this.texCoords[O*2+1]);vec2.set(l,this.texCoords[A*2],this.texCoords[A*2+1]);vec2.set(u,this.texCoords[I*2],this.texCoords[I*2+1]);const T=r[0]-i[0];const S=o[0]-i[0];const C=r[1]-i[1];const y=o[1]-i[1];const E=r[2]-i[2];const M=o[2]-i[2];const P=l[0]-s[0];const N=u[0]-s[0];const j=l[1]-s[1];const L=u[1]-s[1];const w=1/(P*L-N*j);vec3.set(m,(L*T-j*S)*w,(L*C-j*y)*w,(L*E-j*M)*w);vec3.set(c,(P*S-N*T)*w,(P*y-N*C)*w,(P*M-N*E)*w);a[O]=m;a[A]=m;a[I]=m;a[O+n]=c;a[A+n]=c;a[I+n]=c}const d=vec3.create();const h=vec3.create();const f=vec3.create();const p=vec3.create();const g=vec3.create();const v=vec3.create();const b=vec3.create();const x=vec3.create();for(let e=0;e<n;e+=1){if(!a[e])continue;vec3.set(d,this.vertexNormals[e*3],this.vertexNormals[e*3+1],this.vertexNormals[e*3+2]);vec3.set(h,a[e][0],a[e][1],a[e][2]);const R=vec3.dot(d,h);vec3.scale(g,d,R);vec3.subtract(v,h,g);vec3.normalize(x,v);vec3.cross(b,d,h);const k=1;vec3.scale(f,x,1/k);vec3.cross(p,d,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]=p[0];this.biTangents[e*3+1]=p[1];this.biTangents[e*3+2]=p[2]}};c.prototype.isIndexed=function(){if(this._vertices.length==0)return true;return this.verticesIndices.length!=0};c.prototype.unIndex=function(e,t){const n=[];const a=[];let i=0;for(let e in this._attributes){const r=this._attributes[e];let n=[];for(let t=0;t<this.verticesIndices.length;t+=3){for(let e=0;e<3;e++){if(r.itemSize==3)n.push(r.data[this.verticesIndices[t+e]*3+0],r.data[this.verticesIndices[t+e]*3+1],r.data[this.verticesIndices[t+e]*3+2]);else if(r.itemSize==4)n.push(r.data[this.verticesIndices[t+e]*4+0],r.data[this.verticesIndices[t+e]*4+1],r.data[this.verticesIndices[t+e]*4+2],r.data[this.verticesIndices[t+e]*4+3]);else if(r.itemSize==2)n.push(r.data[this.verticesIndices[t+e]*2+0],r.data[this.verticesIndices[t+e]*2+1]);else if(r.itemSize==1)n.push(r.data[this.verticesIndices[t+e]]);else console.log("unknown attr",r)}}this.setAttribute(r.name,n,r.itemSize)}for(let e=0;e<this.verticesIndices.length;e+=3){n.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]);a.push(i);i++;n.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]);a.push(i);i++;n.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]);a.push(i);i++}this.vertices=n;this.verticesIndices=[];if(e)this.verticesIndices=a;if(!t)this.calculateNormals()};c.prototype.calcBarycentric=function(){let t=[];t.length=this.vertices.length;for(let e=0;e<this.vertices.length;e++)t[e]=0;let n=0;for(let e=0;e<this.vertices.length;e+=3){t[e+n]=1;n++;if(n==3)n=0}this.setAttribute("attrBarycentric",t,3)};c.prototype.getBounds=function(){return new l(this)};c.prototype.center=function(e,t,n){if(e===undefined){e=true;t=true;n=true}let a=0;const i=this.getBounds();const r=[i.minX+(i.maxX-i.minX)/2,i.minY+(i.maxY-i.minY)/2,i.minZ+(i.maxZ-i.minZ)/2];for(a=0;a<this.vertices.length;a+=3){if(this.vertices[a+0]==this.vertices[a+0]){if(e)this.vertices[a+0]-=r[0];if(t)this.vertices[a+1]-=r[1];if(n)this.vertices[a+2]-=r[2]}}return r};c.prototype.mapTexCoords2d=function(){const t=this.getBounds();const n=this.vertices.length/3;this.texCoords=new Float32Array(n*2);for(let e=0;e<n;e++){const a=this.vertices[e*3+0];const i=this.vertices[e*3+1];this.texCoords[e*2+0]=a/(t.maxX-t.minX)+.5;this.texCoords[e*2+1]=1-i/(t.maxY-t.minY)+.5}};c.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};c.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};c.buildFromFaces=function(t,e,n){const a=[];const i=[];for(let e=0;e<t.length;e+=3){const o=t[e+0];const s=t[e+1];const l=t[e+2];const u=[-1,-1,-1];if(n)for(let e=0;e<a.length;e+=3){if(a[e+0]==o[0]&&a[e+1]==o[1]&&a[e+2]==o[2])u[0]=e/3;if(a[e+0]==s[0]&&a[e+1]==s[1]&&a[e+2]==s[2])u[1]=e/3;if(a[e+0]==l[0]&&a[e+1]==l[1]&&a[e+2]==l[2])u[2]=e/3}if(u[0]==-1){a.push(o[0],o[1],o[2]);u[0]=(a.length-1)/3}if(u[1]==-1){a.push(s[0],s[1],s[2]);u[1]=(a.length-1)/3}if(u[2]==-1){a.push(l[0],l[1],l[2]);u[2]=(a.length-1)/3}i.push(parseInt(u[0],10));i.push(parseInt(u[1],10));i.push(parseInt(u[2],10))}const r=new c(e);r.name=e;r.vertices=a;r.verticesIndices=i;return r};const d=function(){this._log=new m("eventtarget");this._eventCallbacks={};this._logName="";this._logEvents=false;this._listeners={};this.addEventListener=this.on=function(e,t,n){const a={id:(n||"")+CABLES.simpleId(),name:e,cb:t};if(!this._eventCallbacks[e])this._eventCallbacks[e]=[a];else this._eventCallbacks[e].push(a);this._listeners[a.id]=a;return a.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 n=this._eventCallbacks[e].indexOf(t);if(n==-1)return false;return true}}}};this.hasListenerForEventName=function(e){return this._eventCallbacks[e]&&this._eventCallbacks[e].length>0};this.removeEventListener=this.off=function(a,t){if(a===null||a===undefined)return;if(!t){const i=this._listeners[a];if(!i){this._log.log("could not find event...",a,this);return}let n=true;while(n){n=false;let t=-1;for(let e=0;e<this._eventCallbacks[i.name].length;e++){if(this._eventCallbacks[i.name][e].id.startsWith(a)){n=true;t=e}}if(t!==-1){this._eventCallbacks[i.name].splice(t,1);delete this._listeners[a]}}return}this._log.info("[eventtaget] ","old function signature: removeEventListener! use listener id");this._log.log((new Error).stack);let n=null;for(let e=0;e<this._eventCallbacks[a].length;e++)if(this._eventCallbacks[a][e].cb==t)n=e;if(n!==null){delete this._eventCallbacks[n]}else this._log.warn("removeEventListener not found "+a)};this.logEvents=function(e,t){this._logEvents=e;this._logName=t};this.emitEvent=function(t,n,a,i,r,o,s){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(n,a,i,r,o,s)}}}else{if(this._logEvents)this._log.log("[event] has no event callback",t,this._eventCallbacks)}}};const h={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(h.ANIM.EASING_LINEAR);this.set(e)};f.cubicSpline=function(e,t,n){let a=t.value,i=t.bezTangOut,r=n.value,o=n.bezTangIn;let s=e;let l=s*s;let u=l*s;return(2*u-3*l+1)*a+(u-2*l+s)*i+(-2*u+3*l)*r+(u-l)*o};f.easeCubicSpline=function(e,t){return f.cubicSpline(e,this,t)};f.linear=function(e,t,n){return parseFloat(t.value)+parseFloat(n.value-t.value)*e};f.easeLinear=function(e,t){return f.linear(e,this,t)};f.easeAbsolute=function(e,t){return this.value};const p=function(e){return e=2**(10*(e-1))};f.easeExpoIn=function(e,t){e=p(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 b=function(e){e=e*e*e;return e};f.easeCubicIn=function(e,t){e=b(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 n=1.70158;let a=0;let i=1;const r=0;const o=1;const s=1;if(e===0)e=r;else if((e/=o)==1)e=r+s;else{if(!a)a=o*.3;if(i<Math.abs(s)){i=s;n=a/4}else n=a/(2*Math.PI)*Math.asin(s/i);e=-(i*2**(10*(e-=1))*Math.sin((e*o-n)*(2*Math.PI)/a))+r}return f.linear(e,this,t)};f.easeOutElastic=function(e,t){let n=1.70158;let a=0;let i=1;const r=0;const o=1;const s=1;if(e===0)e=r;else if((e/=o)==1)e=r+s;else{if(!a)a=o*.3;if(i<Math.abs(s)){i=s;n=a/4}else n=a/(2*Math.PI)*Math.asin(s/i);e=i*2**(-10*e)*Math.sin((e*o-n)*(2*Math.PI)/a)+s+r}return f.linear(e,this,t)};f.easeInBack=function(e,t){const n=1.70158;e=e*e*((n+1)*e-n);return f.linear(e,this,t)};f.easeOutBack=function(e,t){const n=1.70158;e=(e=e/1-1)*e*((n+1)*e+n)+1;return f.linear(e,this,t)};f.easeInOutBack=function(e,t){let n=1.70158;const a=1/2;if((e/=1/2)<1)e=a*(e*e*(((n*=1.525)+1)*e-n));else e=a*((e-=2)*e*(((n*=1.525)+1)*e+n)+2);return f.linear(e,this,t)};const x=function(e){e--;e=e*e*e+1;return e};f.easeCubicOut=function(e,t){e=x(e);return f.linear(e,this,t)};const _=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=_(e);return f.linear(e,this,t)};f.easeSmoothStep=function(e,t){const n=Math.max(0,Math.min(1,e));e=n*n*(3-2*n);return f.linear(e,this,t)};f.easeSmootherStep=function(e,t){const n=Math.max(0,Math.min(1,(e-0)/(1-0)));e=n*n*n*(n*(n*6-15)+10);return f.linear(e,this,t)};f.prototype.setEasing=function(e){this._easing=e;if(this._easing==h.ANIM.EASING_LINEAR)this.ease=f.easeLinear;else if(this._easing==h.ANIM.EASING_ABSOLUTE)this.ease=f.easeAbsolute;else if(this._easing==h.ANIM.EASING_SMOOTHSTEP)this.ease=f.easeSmoothStep;else if(this._easing==h.ANIM.EASING_SMOOTHERSTEP)this.ease=f.easeSmootherStep;else if(this._easing==h.ANIM.EASING_CUBIC_IN)this.ease=f.easeCubicIn;else if(this._easing==h.ANIM.EASING_CUBIC_OUT)this.ease=f.easeCubicOut;else if(this._easing==h.ANIM.EASING_CUBIC_INOUT)this.ease=f.easeCubicInOut;else if(this._easing==h.ANIM.EASING_EXPO_IN)this.ease=f.easeExpoIn;else if(this._easing==h.ANIM.EASING_EXPO_OUT)this.ease=f.easeExpoOut;else if(this._easing==h.ANIM.EASING_EXPO_INOUT)this.ease=f.easeExpoInOut;else if(this._easing==h.ANIM.EASING_SIN_IN)this.ease=f.easeSinIn;else if(this._easing==h.ANIM.EASING_SIN_OUT)this.ease=f.easeSinOut;else if(this._easing==h.ANIM.EASING_SIN_INOUT)this.ease=f.easeSinInOut;else if(this._easing==h.ANIM.EASING_BACK_OUT)this.ease=f.easeOutBack;else if(this._easing==h.ANIM.EASING_BACK_IN)this.ease=f.easeInBack;else if(this._easing==h.ANIM.EASING_BACK_INOUT)this.ease=f.easeInOutBack;else if(this._easing==h.ANIM.EASING_ELASTIC_IN)this.ease=f.easeInElastic;else if(this._easing==h.ANIM.EASING_ELASTIC_OUT)this.ease=f.easeOutElastic;else if(this._easing==h.ANIM.EASING_ELASTIC_INOUT)this.ease=f.easeElasticInOut;else if(this._easing==h.ANIM.EASING_BOUNCE_IN)this.ease=f.easeInBounce;else if(this._easing==h.ANIM.EASING_BOUNCE_OUT)this.ease=f.easeOutBounce;else if(this._easing==h.ANIM.EASING_QUART_OUT)this.ease=f.easeOutQuart;else if(this._easing==h.ANIM.EASING_QUART_IN)this.ease=f.easeInQuart;else if(this._easing==h.ANIM.EASING_QUART_INOUT)this.ease=f.easeInOutQuart;else if(this._easing==h.ANIM.EASING_QUINT_OUT)this.ease=f.easeOutQuint;else if(this._easing==h.ANIM.EASING_QUINT_IN)this.ease=f.easeInQuint;else if(this._easing==h.ANIM.EASING_QUINT_INOUT)this.ease=f.easeInOutQuint;else if(this._easing==h.ANIM.EASING_CUBICSPLINE){this.ease=f.easeCubicSpline}else{this._easing=h.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 O=function(e){d.apply(this);e=e||{};this.keys=[];this.onChange=null;this.stayInTimeline=false;this.loop=false;this._log=new m("Anim");this._lastKeyIndex=0;this._cachedIndex=0;this.name=e.name||null;this.defaultEasing=e.defaultEasing||h.ANIM.EASING_LINEAR;this.onLooped=null;this._timesLooped=0;this._needsSort=false};O.prototype.forceChangeCallback=function(){if(this.onChange!==null)this.onChange();this.emitEvent("onChange",this)};O.prototype.getLoop=function(){return this.loop};O.prototype.setLoop=function(e){this.loop=e;this.emitEvent("onChange",this)};O.prototype.hasEnded=function(e){if(this.keys.length===0)return true;if(this.keys[this._lastKeyIndex].time<=e)return true;return false};O.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};O.prototype.clearBefore=function(e){const t=this.getValue(e);const n=this.getKeyIndex(e);this.setValue(e,t);if(n>1)this.keys.splice(0,n);this._updateLastIndex()};O.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)};O.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)};O.prototype.getLength=function(){if(this.keys.length===0)return 0;return this.keys[this.keys.length-1].time};O.prototype.getKeyIndex=function(t){let n=0;let a=0;if(this._cachedIndex&&this.keys.length>this._cachedIndex&&t>=this.keys[this._cachedIndex].time)a=this._cachedIndex;for(let e=a;e<this.keys.length;e++){if(t>=this.keys[e].time)n=e;if(this.keys[e].time>t){if(t!=0)this._cachedIndex=n;return n}}return n};O.prototype.setValue=function(t,n,a){let i=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){i=this.keys[e];this.keys[e].setValue(n);this.keys[e].cb=a;break}if(!i){i=new f({time:t,value:n,e:this.defaultEasing,cb:a});this.keys.push(i);this._updateLastIndex()}if(this.onChange)this.onChange();this.emitEvent("onChange",this);this._needsSort=true;return i};O.prototype.setKeyEasing=function(e,t){if(this.keys[e]){this.keys[e].setEasing(t);this.emitEvent("onChange",this)}};O.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};O.prototype.getKey=function(e){const t=this.getKeyIndex(e);return this.keys[t]};O.prototype.getNextKey=function(e){let t=this.getKeyIndex(e)+1;if(t>=this.keys.length)t=this.keys.length-1;return this.keys[t]};O.prototype.isFinished=function(e){if(this.keys.length<=0)return true;return e>this.keys[this.keys.length-1].time};O.prototype.isStarted=function(e){if(this.keys.length<=0)return false;return e>=this.keys[0].time};O.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 o=e/this.keys[this._lastKeyIndex].time;if(o>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 n=t+1;const a=this.keys[t];const i=this.keys[n];if(a.cb&&!a.cbTriggered)a.trigger();if(!i)return-1;const r=(e-a.time)/(i.time-a.time);if(!a.ease)this.log._warn("has no ease",a,i);return a.ease(r,i)};O.prototype._updateLastIndex=function(){this._lastKeyIndex=this.keys.length-1};O.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()};O.prototype.easingFromString=function(e){if(e=="linear")return h.ANIM.EASING_LINEAR;if(e=="absolute")return h.ANIM.EASING_ABSOLUTE;if(e=="smoothstep")return h.ANIM.EASING_SMOOTHSTEP;if(e=="smootherstep")return h.ANIM.EASING_SMOOTHERSTEP;if(e=="Cubic In")return h.ANIM.EASING_CUBIC_IN;if(e=="Cubic Out")return h.ANIM.EASING_CUBIC_OUT;if(e=="Cubic In Out")return h.ANIM.EASING_CUBIC_INOUT;if(e=="Expo In")return h.ANIM.EASING_EXPO_IN;if(e=="Expo Out")return h.ANIM.EASING_EXPO_OUT;if(e=="Expo In Out")return h.ANIM.EASING_EXPO_INOUT;if(e=="Sin In")return h.ANIM.EASING_SIN_IN;if(e=="Sin Out")return h.ANIM.EASING_SIN_OUT;if(e=="Sin In Out")return h.ANIM.EASING_SIN_INOUT;if(e=="Back In")return h.ANIM.EASING_BACK_IN;if(e=="Back Out")return h.ANIM.EASING_BACK_OUT;if(e=="Back In Out")return h.ANIM.EASING_BACK_INOUT;if(e=="Elastic In")return h.ANIM.EASING_ELASTIC_IN;if(e=="Elastic Out")return h.ANIM.EASING_ELASTIC_OUT;if(e=="Bounce In")return h.ANIM.EASING_BOUNCE_IN;if(e=="Bounce Out")return h.ANIM.EASING_BOUNCE_OUT;if(e=="Quart Out")return h.ANIM.EASING_QUART_OUT;if(e=="Quart In")return h.ANIM.EASING_QUART_IN;if(e=="Quart In Out")return h.ANIM.EASING_QUART_INOUT;if(e=="Quint Out")return h.ANIM.EASING_QUINT_OUT;if(e=="Quint In")return h.ANIM.EASING_QUINT_IN;if(e=="Quint In Out")return h.ANIM.EASING_QUINT_INOUT};O.prototype.createPort=function(e,t,n){const a=e.inDropDown(t,h.ANIM.EASINGS,"Cubic Out");a.set("linear");a.defaultValue="linear";a.onChange=function(){this.defaultEasing=this.easingFromString(a.get());this.emitEvent("onChangeDefaultEasing",this);if(n)n()}.bind(this);return a};O.slerpQuaternion=function(e,t,n,a,i,r){if(!O.slerpQuaternion.q1){O.slerpQuaternion.q1=quat.create();O.slerpQuaternion.q2=quat.create()}const o=n.getKeyIndex(e);let s=o+1;if(s>=n.keys.length)s=n.keys.length-1;if(o==s){quat.set(t,n.keys[o].value,a.keys[o].value,i.keys[o].value,r.keys[o].value)}else{const l=n.keys[o].time;const u=n.keys[s].time;const m=(e-l)/(u-l);quat.set(O.slerpQuaternion.q1,n.keys[o].value,a.keys[o].value,i.keys[o].value,r.keys[o].value);quat.set(O.slerpQuaternion.q2,n.keys[s].value,a.keys[s].value,i.keys[s].value,r.keys[s].value);quat.slerp(t,O.slerpQuaternion.q1,O.slerpQuaternion.q2,m)}return t};const A={Key:f};const I=function(e,t,n,a){d.apply(this);this.data={};this._log=new m("core_port");this.direction=h.PORT.PORT_DIR_IN;this.id=String(CABLES.simpleId());this._op=e;this.links=[];this.value=0;this.name=t;this.type=n||h.OP.OP_PORT_TYPE_VALUE;this.uiAttribs=a||{};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)}})};I.prototype.copyLinkedUiAttrib=function(e,t){if(!CABLES.UI)return;if(!this.isLinked())return;const n={};n[e]=this.links[0].getOtherPort(this).getUiAttrib(e);t.setUiAttribs(n)};I.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};I.prototype.onAnimToggle=function(){};I.prototype._onAnimToggle=function(){this.onAnimToggle()};I.prototype.remove=function(){this.removeLinks();this._op.removePort(this)};I.prototype.setUiAttribs=function(e){let t=false;if(!this.uiAttribs)this.uiAttribs={};for(const n in e){if(e[n]===undefined){delete this.uiAttribs[n];continue}if(this.uiAttribs[n]!=e[n])t=true;this.uiAttribs[n]=e[n];if(n=="group"&&this.indexPort)this.indexPort.setUiAttribs({group:e[n]})}if(e.hasOwnProperty("expose"))this._op.patch.emitEvent("subpatchExpose",this._op.uiAttribs.subPatch);if(t)this.emitEvent("onUiAttrChange",e,this)};I.prototype.getUiAttribs=function(){return this.uiAttribs};I.prototype.getUiAttrib=function(e){if(!this.uiAttribs||!this.uiAttribs.hasOwnProperty(e)){return null}return this.uiAttribs[e]};I.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};I.prototype.setRef=function(e){this.forceRefChange=true;this.set(e)};I.prototype.set=I.prototype.setValue=function(e){if(e===undefined)e=null;if(this._op.enabled&&!this.crashed){if(e!==this.value||this.changeAlways||this.type==h.OP.OP_PORT_TYPE_TEXTURE||this.type==h.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==h.OP.OP_PORT_TYPE_TEXTURE)gui.texturePreview().updateTexturePort(this)}if(this.direction==h.PORT.PORT_DIR_OUT)for(let e=0;e<this.links.length;++e)this.links[e].setValue()}}};I.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}};I.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)};I.prototype.getTypeString=function(){if(this.type==h.OP.OP_PORT_TYPE_VALUE)return"Number";if(this.type==h.OP.OP_PORT_TYPE_FUNCTION)return"Trigger";if(this.type==h.OP.OP_PORT_TYPE_OBJECT)return"Object";if(this.type==h.OP.OP_PORT_TYPE_DYNAMIC)return"Dynamic";if(this.type==h.OP.OP_PORT_TYPE_ARRAY)return"Array";if(this.type==h.OP.OP_PORT_TYPE_STRING)return"String";return"Unknown"};I.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 O({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 A.Key(e.anim.keys[t]))}this.anim.sortKeys()}};I.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};I.prototype.getSerialized=function(){let e={name:this.getName()};if(!this.ignoreValueSerialize&&this.links.length===0){if(this.type==h.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==h.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==h.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 n=this.links[t].getOtherPort(this);if(n.op.isInBlueprint2&&this.op.isInBlueprint2){if(n.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===h.OP.OP_PORT_TYPE_FUNCTION)delete e.value;if(this.type===h.OP.OP_PORT_TYPE_FUNCTION&&this.links.length==0)e=null;if(e&&Object.keys(e).length==1&&e.name)e=null;r(e);return e};I.prototype.shouldLink=function(){return true};I.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()}};I.prototype.removeLink=function(e){for(const t in this.links)if(this.links[t]==e)this.links.splice(t,1);if(this.direction==h.PORT.PORT_DIR_IN){if(this.type==h.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();if(this.onLinkChanged)this.onLinkChanged();this.emitEvent("onLinkChanged");this.emitEvent("onLinkRemoved");this._op.emitEvent("onLinkChanged")};I.prototype.getName=function(){return this.name};I.prototype.getTitle=function(){if(this.uiAttribs.title)return this.uiAttribs.title;return this.name};I.prototype.addLink=function(e){this._valueBeforeLink=this.value;this.links.push(e);if(CABLES.UI&&this._op.checkLinkTimeWarnings)this._op.checkLinkTimeWarnings();if(this.onLinkChanged)this.onLinkChanged();this.emitEvent("onLinkChanged");this._op.emitEvent("onLinkChanged")};I.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]};I.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}}};I.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};I.prototype._activity=function(){this.activityCounter++};I.prototype.trigger=function(){const t=this.links.length;this._activity();if(t===0)return;if(!this._op.enabled)return;let n=null;try{for(let e=0;e<t;++e){if(this.links[e].portIn){n=this.links[e].portIn;n.op.patch.pushTriggerStack(n);n._onTriggered();n.op.patch.popTriggerStack()}if(this.links[e])this.links[e].activity()}}catch(e){n.op.enabled=false;if(this._op.patch.isEditorMode()){if(n.op.onError)n.op.onError(e)}this._log.error("exception in port: "+n.op.name,n.op);this._log.error(e)}};I.prototype.call=function(){this._log.warn("call deprecated - use trigger() ");this.trigger()};I.prototype.execute=function(){this._log.warn("### execute port: "+this.getName(),this.goals.length)};I.prototype.setVariableName=function(e){this._useVariableName=e;this._op.patch.on("variableRename",(e,t)=>{if(e!=this._useVariableName)return;this._useVariableName=t})};I.prototype.getVariableName=function(){return this._useVariableName};I.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==h.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)};I.prototype._handleNoTriggerOpAnimUpdates=function(e){let t=false;for(let e=0;e<this._op.portsIn.length;e++){if(this._op.portsIn.type==h.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)}};I.prototype.setAnimated=function(e){if(this._animated!=e){this._animated=e;this._op._hasAnimPort=true;if(this._animated&&!this.anim){this.anim=new O({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})};I.prototype.toggleAnim=function(){this._animated=!this._animated;if(this._animated&&!this.anim){this.anim=new O({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})};I.prototype.getType=function(){return this.type};I.prototype.isLinked=function(){return this.links.length>0||this._animated||this._useVariableName!=null};I.prototype.isBoundToVar=function(){const e=this._useVariableName!=null;this.uiAttribs.boundToVar=e;return e};I.prototype.isAnimated=function(){return this._animated};I.prototype.isHidden=function(){return this.uiAttribs.hidePort};I.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")};I.prototype._onSetProfiling=function(e){this._op.patch.profiler.add("port",this);this.setValue(e);this._op.patch.profiler.add("port",null)};I.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)}};I.prototype.getUiActiveState=function(){return this._uiActiveState};I.prototype.setUiActiveState=function(e){this._uiActiveState=e;if(this.onUiActiveStateChange)this.onUiActiveStateChange()};I.prototype.onValueChange=function(e){this.onChange=e};I.prototype.hidePort=function(){};I.portTypeNumberToString=function(e){if(e==h.OP.OP_PORT_TYPE_VALUE)return"value";if(e==h.OP.OP_PORT_TYPE_FUNCTION)return"function";if(e==h.OP.OP_PORT_TYPE_OBJECT)return"object";if(e==h.OP.OP_PORT_TYPE_ARRAY)return"array";if(e==h.OP.OP_PORT_TYPE_STRING)return"string";if(e==h.OP.OP_PORT_TYPE_DYNAMIC)return"dynamic";return"unknown"};class T{constructor(e,t,n,a,i,r,o,s,l,u){this._log=new m("cg_uniform");this._type=t;this._name=n;this._shader=e;this._value=1e-5;this._oldValue=null;this._port=null;this._structName=l;this._structUniformName=s;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 a=="object"&&a instanceof I){this._port=a;this._value=this._port.get();if(i&&r&&o){if(!(i instanceof I)||!(r instanceof I)||!(o instanceof I)){this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ",this._name)}this._value=[0,0,0,0];this._port2=i;this._port3=r;this._port4=o;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(i&&r){if(!(i instanceof I)||!(r instanceof I)){this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ",this._name)}this._value=[0,0,0];this._port2=i;this._port3=r;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(i){if(!(i instanceof I)){this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ",this._name)}this._value=[0,0];this._port2=i;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=a;this.setValue(this._value);this.needsUpdate=true}getType(){return this._type}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 S=T;class C extends S{constructor(e,t,n,a,i,r,o,s,l,u){super(e,t,n,a,i,r,o,s,l,u);this._loc=-1;this._cgl=e._cgl}get name(){return this._name}copy(e){const t=new C(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 C.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}}C.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 y={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 M=180/Math.PI;const P=Math.PI/180;const N={MATH:{DEG2RAD:P,RAD2DEG:M},SHADER:y,BLEND_MODES:E};const j={};j.lastMesh=null;const L=function(e,t,n){this._cgl=e;let a=n||{};if(CABLES.UTILS.isNumeric(a))a={glPrimitive:n};this._log=new m("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=a.glPrimitive;this.opId=a.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)}})};L.prototype.freeMem=function(){this.memFreed=true;for(let e=0;e<this._attributes.length;e++){this._attributes[e].floatArray=null}};L.prototype.updateVertices=function(e){this.setAttribute(N.SHADER.SHADERVAR_VERTEX_POSITION,e.vertices,3);this._numVerts=e.vertices.length/3};L.prototype.setAttributePointer=function(t,n,a,i){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:n,stride:a,offset:i,instanced:t==N.SHADER.SHADERVAR_INSTANCE_MMATRIX})}}};L.prototype.getAttribute=function(t){for(let e=0;e<this._attributes.length;e++)if(this._attributes[e].name==t)return this._attributes[e]};L.prototype.setAttributeRange=function(e,t,n,a){if(!e)return;if(!n&&!a)return;if(!e.name){this._log.stack("no attrname?!")}this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER,e.buffer);this._cgl.profileData.profileMeshAttributes+=a-n||0;this._cgl.profileData.profileSingleMeshAttribute[this._name]=this._cgl.profileData.profileSingleMeshAttribute[this._name]||0;this._cgl.profileData.profileSingleMeshAttribute[this._name]+=a-n||0;if(e.numItems<t.length/e.itemSize){this._resizeAttr(t,e)}if(a>t.length){if(CABLES.platform.isDevEnv())this._log.log(this._cgl.canvas.id+" "+e.name+" buffersubdata out of bounds ?",t.length,a,n,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,n*4,t,n,a-n)};L.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};L.prototype._bufferArray=function(e,t){let n=t.floatArray||null;if(!e)return;if(this._cgl.debugOneFrame){console.log("_bufferArray",e.length,t.name)}if(!(e instanceof Float32Array)){if(t&&n&&n.length==e.length){n.set(e)}else{n=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 n=e;t.arrayLength=n.length;t.floatArray=null;this._cgl.gl.bufferData(this._cgl.gl.ARRAY_BUFFER,n,this._cgl.gl.DYNAMIC_DRAW)};L.prototype.addAttribute=L.prototype.updateAttribute=L.prototype.setAttribute=function(e,t,n,a){if(!t){this._log.error("mesh addAttribute - no array given! "+e);throw new Error}let i=null;let r=false;let o=0;const s=t.length/n;this._cgl.profileData.profileMeshAttributes+=s||0;if(typeof a=="function"){i=a}if(typeof a=="object"){if(a.cb)i=a.cb;if(a.instanced)r=a.instanced}if(e==N.SHADER.SHADERVAR_INSTANCE_MMATRIX)r=true;for(o=0;o<this._attributes.length;o++){const m=this._attributes[o];if(m.name==e){if(m.numItems===s){}else{this._resizeAttr(t,m)}this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER,m.buffer);this._bufferArray(t,m);return m}}const l=this._cgl.gl.createBuffer();this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER,l);let u=this._cgl.gl.FLOAT;if(a&&a.type)u=a.type;const m={buffer:l,name:e,cb:i,itemSize:n,numItems:s,startItem:0,instanced:r,type:u};this._bufferArray(t,m);if(e==N.SHADER.SHADERVAR_VERTEX_POSITION)this._bufVertexAttrib=m;this._attributes.push(m);this._attribLocs={};return m};L.prototype.getAttributes=function(){return this._attributes};L.prototype.updateTexCoords=function(e){if(e.texCoords&&e.texCoords.length>0){this.setAttribute(N.SHADER.SHADERVAR_VERTEX_TEXCOORD,e.texCoords,2)}else{const t=new Float32Array(Math.round(e.vertices.length/3*2));this.setAttribute(N.SHADER.SHADERVAR_VERTEX_TEXCOORD,t,2)}};L.prototype.updateNormals=function(e){if(e.vertexNormals&&e.vertexNormals.length>0){this.setAttribute(N.SHADER.SHADERVAR_VERTEX_NORMAL,e.vertexNormals,3)}else{const t=new Float32Array(Math.round(e.vertices.length));this.setAttribute(N.SHADER.SHADERVAR_VERTEX_NORMAL,t,3)}};L.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(N.SHADER.SHADERVAR_VERTEX_NUMBER,this._verticesNumbers,1,(e,t,n)=>{if(!n.uniformNumVertices)n.uniformNumVertices=new C(n,"f","numVertices",this._numVerts);n.uniformNumVertices.setValue(this._numVerts)})}};L.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};L.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;j.lastMesh=null;this._cgl.profileData.profileMeshSetGeom++;this._disposeAttributes();this.updateVertices(this._geom);this.setVertexIndices(this._geom.verticesIndices);if(this.addVertexNumbers)this._setVertexNumbers();const n=this._geom.getAttributes();const a={texCoords:N.SHADER.SHADERVAR_VERTEX_TEXCOORD,vertexNormals:N.SHADER.SHADERVAR_VERTEX_NORMAL,vertexColors:N.SHADER.SHADERVAR_VERTEX_COLOR,tangents:"attrTangent",biTangents:"attrBiTangent"};for(const i in n)if(n[i].data&&n[i].data.length)this.setAttribute(a[i]||i,n[i].data,n[i].itemSize);if(t){this._geom=null}};L.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)};L.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}}};L.prototype._bind=function(t){if(!t.isValid())return;let n=[];if(this._attribLocs[t.id])n=this._attribLocs[t.id];else this._attribLocs[t.id]=n;this._lastShader=t;if(t.lastCompile>this._lastAttrUpdate||n.length!=this._attributes.length){this._lastAttrUpdate=t.lastCompile;for(let e=0;e<this._attributes.length;e++)n[e]=-1}for(let e=0;e<this._attributes.length;e++){const a=this._attributes[e];if(n[e]==-1){if(a._attrLocationLastShaderTime!=t.lastCompile){a._attrLocationLastShaderTime=t.lastCompile;n[e]=this._cgl.glGetAttribLocation(t.getProgram(),a.name);this._cgl.profileData.profileAttrLoc++}}if(n[e]!=-1){this._cgl.gl.enableVertexAttribArray(n[e]);this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER,a.buffer);if(a.instanced){if(a.itemSize<=4){if(!a.itemSize||a.itemSize==0)this._log.warn("instanced attrib itemsize error",this._geom.name,a);this._cgl.gl.vertexAttribPointer(n[e],a.itemSize,a.type,false,a.itemSize*4,0);this._cgl.gl.vertexAttribDivisor(n[e],1)}else if(a.itemSize==16){const i=16*4;this._cgl.gl.vertexAttribPointer(n[e],4,a.type,false,i,0);this._cgl.gl.enableVertexAttribArray(n[e]+1);this._cgl.gl.vertexAttribPointer(n[e]+1,4,a.type,false,i,4*4*1);this._cgl.gl.enableVertexAttribArray(n[e]+2);this._cgl.gl.vertexAttribPointer(n[e]+2,4,a.type,false,i,4*4*2);this._cgl.gl.enableVertexAttribArray(n[e]+3);this._cgl.gl.vertexAttribPointer(n[e]+3,4,a.type,false,i,4*4*3);this._cgl.gl.vertexAttribDivisor(n[e],1);this._cgl.gl.vertexAttribDivisor(n[e]+1,1);this._cgl.gl.vertexAttribDivisor(n[e]+2,1);this._cgl.gl.vertexAttribDivisor(n[e]+3,1)}else{this._log.warn("unknown instance attrib size",a.name)}}else{if(!a.itemSize||a.itemSize==0)this._log.warn("attrib itemsize error",this._name,a);this._cgl.gl.vertexAttribPointer(n[e],a.itemSize,a.type,false,a.itemSize*4,0);if(a.pointer){for(let e=0;e<a.pointer.length;e++){const r=a.pointer[e];if(r.loc==-1)r.loc=this._cgl.glGetAttribLocation(t.getProgram(),r.name);this._cgl.profileData.profileAttrLoc++;this._cgl.gl.enableVertexAttribArray(r.loc);this._cgl.gl.vertexAttribPointer(r.loc,a.itemSize,a.type,false,r.stride,r.offset)}}if(this.bindFeedback)this.bindFeedback(a)}}}if(this._bufVerticesIndizes&&this._bufVerticesIndizes.numItems!==0)this._cgl.gl.bindBuffer(this._cgl.gl.ELEMENT_ARRAY_BUFFER,this._bufVerticesIndizes)};L.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;j.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])}};L.prototype.meshChanged=function(){return this._cgl.lastMesh&&this._cgl.lastMesh!=this};L.prototype.printDebug=function(e){console.log("--attributes");for(let e=0;e<this._attributes.length;e++){console.log("attribute "+e+" "+this._attributes[e].name)}};L.prototype.setNumVertices=function(e){this._bufVertexAttrib.numItems=e};L.prototype.getNumVertices=function(){return this._bufVertexAttrib.numItems};L.prototype.render=function(n){if(!n||!n.isValid()||this._cgl.aborted)return;this._checkAttrLengths();if(this._geom){if(this._preWireframeGeom&&!n.wireframe&&!this._geom.isIndexed()){this.setGeom(this._preWireframeGeom);this._preWireframeGeom=null}if(n.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(j.lastMesh!=this){if(j.lastMesh)j.lastMesh.unBind();e=true}if(e)this._preBind(n);if(!n.bind())return;this._bind(n);if(this.addVertexNumbers)this._setVertexNumbers();j.lastMesh=this;let t=this._cgl.gl.TRIANGLES;if(this._glPrimitive!==undefined)t=this._glPrimitive;if(n.glPrimitive!==null)t=n.glPrimitive;let a=1;let i=this._cgl.profileData.doProfileGlQuery;let r=false;if(i){let e=this._name+" - "+n.getName()+" #"+n.id;if(this._numInstances)e+=" instanced "+this._numInstances+"x";let t=this._cgl.profileData.glQueryData[e];if(!t)t={id:e,num:0};if(n.opId)t.shaderOp=n.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 o=this._cgl.gl.getQueryParameter(t._drawQuery,this._cgl.gl.QUERY_RESULT_AVAILABLE);if(o){const s=this._cgl.gl.getQueryParameter(t._drawQuery,this._cgl.gl.QUERY_RESULT);const l=s/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);r=t.queryStarted=true}}}if(this.hasFeedbacks&&this.hasFeedbacks())this.drawFeedbacks(n,t);else if(!this._bufVerticesIndizes||this._bufVerticesIndizes.numItems===0){if(t==this._cgl.gl.TRIANGLES)a=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)a=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",n);const u=[];for(let e=0;e<this._cgl.gl.getProgramParameter(n.getProgram(),this._cgl.gl.ACTIVE_ATTRIBUTES);e++){const m=this._cgl.gl.getActiveAttrib(n.getProgram(),e).name;this._log.error("attrib ",m)}}this._cgl.profileData.profileMeshNumElements+=this._bufVertexAttrib.numItems/a*(this._numInstances||1);this._cgl.profileData.profileMeshDraw++;if(i&&r){this._cgl.gl.endQuery(this._queryExt.TIME_ELAPSED_EXT)}this._cgl.printError("mesh render "+this._name);this.unBind()};L.prototype.setNumInstances=function(t){t=Math.max(0,t);if(this._numInstances!=t){this._numInstances=t;const n=new Float32Array(t);for(let e=0;e<t;e++)n[e]=e;this.setAttribute(N.SHADER.SHADERVAR_INSTANCE_INDEX,n,1,{instanced:true})}};L.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};L.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,n=1){const a=new c(t);a.vertices=[1*n,1*n,0,-1*n,1*n,0,1*n,-1*n,0,-1*n,-1*n,0];a.texCoords=[1,1,0,1,1,0,0,0];a.verticesIndices=[0,1,2,2,1,3];a.vertexNormals=[0,0,0,0,0,0,0,0,0,0,0,0];return e.createMesh(a)};w.getSimpleCube=function(e,t){const n=new c(t);n.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];n.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]);n.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];n.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]);n.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]);n.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 L(e,n)};class R{constructor(e,t,n){this.cgl=e;this._options=n;this.fb=null;let a=n.shader;this._useDefaultShader=true;if(n.shader)this._useDefaultShader=false;n.numRenderBuffers=n.numRenderBuffers||1;if(!a){a="".endl()+"IN vec2 texCoord;";for(let e=0;e<n.numRenderBuffers;e++){a=a.endl()+"UNI sampler2D tex"+e+";".endl()}a=a.endl()+"void main()".endl()+"{";if(n.numRenderBuffers==1){a=a.endl()+"    outColor= texture(tex0,texCoord);".endl()}else for(let e=0;e<n.numRenderBuffers;e++){a=a.endl()+"outColor"+e+" = texture(tex"+e+",texCoord);".endl()}a=a.endl()+"}"}const i=n.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(i,a);if(!n.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,n,a,i){const r=this.cgl;if(!e)e=CGL.Texture.getEmptyTexture(this.cgl);let o=this._options.width||e.width,s=this._options.height||e.height;if(this.fb){if(o<=0)o=8;if(s<=0)s=8;if(this.fb.getWidth()!=o||this.fb.getHeight()!=s)this.fb.setSize(o,s)}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(r.glVersion==1)this.fb=new CGL.Framebuffer(r,o,s,l);else this.fb=new CGL.Framebuffer2(r,o,s,l)}r.frameStore.renderOffscreen=true;this.fb.renderStart(r);r.setTexture(0,e.tex);if(t)r.setTexture(1,t.tex);if(n)r.setTexture(2,n.tex);if(a)r.setTexture(3,a.tex);if(i)r.setTexture(4,i.tex);r.pushShader(this.bgShader);this.mesh.render(this.bgShader);r.popShader();this.fb.renderEnd();r.frameStore.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={};const o={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,n,a,i,r){this._valuePort=n;this._varNamePort=a;this._op=t;this._type=e;this._typeId=-1;this._triggerPort=i;this._nextPort=r;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]);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=o.OP.OP_PORT_TYPE_ARRAY;else if(e=="object")this._typeId=o.OP.OP_PORT_TYPE_OBJECT;else if(e=="string")this._typeId=o.OP.OP_PORT_TYPE_STRING;else if(e=="texture")this._typeId=o.OP.OP_PORT_TYPE_TEXTURE;else this._typeId=o.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 n=this._op.patch.getVars();for(const a in n)if(n[a].type==this._type&&a!="0")t.push(a);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 n=this._valuePort.get();if(this._typeId==o.OP.OP_PORT_TYPE_VALUE||this._typeId==o.OP.OP_PORT_TYPE_STRING){this._op.patch.setVarValue(t,n)}else if(this._typeId==o.OP.OP_PORT_TYPE_ARRAY){this._arr=[];CABLES.copyArray(n,this._arr);this._op.patch.setVarValue(t,this._arr)}else{if(this._typeId==o.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(n&&n.tex&&n._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,n)}if(e&&this._nextPort)this._nextPort.trigger()}};const n=class{constructor(e,t,n,a){this._op=e;this._type=t;this._varnamePort=n;this._variable=null;this._valueOutPort=a;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()});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 n in t)if(t[n].type==this._type&&n!="0")e.push(n);this._op.varName.uiAttribs.values=e}}_setValueOut(e){if(this._valueOutPort)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=n;((this.CABLES=this.CABLES||{}).COREMODULES=this.CABLES.COREMODULES||{}).Vargetset=e.Cables})();(()=>{"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(!CABLES.UI&&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 n{constructor(){this._log=new t("LoadingStatus");this.pixelData=null;this._finishedFence=true;this._size=0;this._pbo=null}_fence(r){const o=r.gl;this._finishedFence=false;return new Promise(function(t,n){if(r.aborted)return;let a=o.fenceSync(o.SYNC_GPU_COMMANDS_COMPLETE,0);if(!a)return;o.flush();function i(){if(r.aborted)return;const e=o.clientWaitSync(a,0,0);if(e==o.WAIT_FAILED){console.error("fence wait failed");if(n)n()}else if(e==o.TIMEOUT_EXPIRED){return setTimeout(i,0)}else if(e==o.CONDITION_SATISFIED){t();o.deleteSync(a)}else if(e==o.ALREADY_SIGNALED){t();o.deleteSync(a)}else{this._log.log("unknown fence status",e)}}i()})}read(e,t,n,a,i,r,o,s){if(CABLES.UI)if(!CABLES.UI.loaded||performance.now()-CABLES.UI.loadedTime<1e3)return;if(!this._finishedFence)return;const l=e.gl;let u=1;if(e.aborted)return;if(!t)return;if(n===CGL.Texture.TYPE_FLOAT)n=CGL.Texture.PFORMATSTR_RGBA32F;let m=CGL.Texture.isPixelFormatFloat(n);if(m)u=4;if(CGL.Texture.isPixelFormatHalfFloat(n))u=2;const c=CGL.Texture.setUpGlPixelFormat(e,n);const d=c.numColorChannels*r*o;if(r==0||o==0||d==0)return;if(!this._pixelData||this._size!=d*u){if(m)this._pixelData=new Float32Array(d);else this._pixelData=new Uint8Array(d);this._size=d*u}let h=l.UNSIGNED_BYTE;if(m)h=l.FLOAT;if(this._size==0||!this._pixelData){this._log.error("readpixel size 0",this._size,r,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,t);l.bindBuffer(l.PIXEL_PACK_BUFFER,this._pbo);e.profileData.profileFencedPixelRead++;if(this._size!=d*u)this._log.error("buffer size invalid",d,r,o,u);l.readPixels(a,i,r,o,c.glDataFormat,c.glDataType,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(e).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(s)s(this._pixelData)}l.deleteBuffer(this._pbo);this._pbo=null});return true}}CGL.PixelReader=n;((this.CGL=this.CGL||{}).COREMODULES=this.CGL.COREMODULES||{}).Pixelreader=e.Pixelreader})();(()=>{"use strict";var e={};class t{constructor(e,t,n){this._cgl=e;this._name=t;this._origShaders={};this._uniforms=[];this._structUniforms=[];this._definesToggled={};this._defines={};this._mods=[];this._textures=[];this._boundShader=null;this._changedDefines=true;this._changedUniforms=true;this._modulesChanged=false;this.needsTexturePush=false;this._lastShader=null;this._attributes=[];if(n&&n.opId)this.opId=n.opId;if(this._cgl.glVersion==1){this._cgl.enableExtension("OES_texture_float");this._cgl.enableExtension("OES_texture_float_linear");this._cgl.enableExtension("OES_texture_half_float");this._cgl.enableExtension("OES_texture_half_float_linear")}}bind(e,t){const n=e||this._cgl.getShader();if(!n)return;this._boundShader=this._origShaders[n.id];let a=false;if(this._boundShader&&this._lastShader!=this._boundShader.shader){if(!this._boundShader.shader.hasModule(this._mods[0].id))a=true}if(a||!this._boundShader||n.lastCompile!=this._boundShader.lastCompile||this._modulesChanged||n._needsRecompile){if(this._boundShader)this._boundShader.shader.dispose();if(n._needsRecompile)n.compile();this.needsTexturePush=true;this._boundShader=this._origShaders[n.id]={lastCompile:n.lastCompile,orig:n,shader:n.copy()};this._addModulesToShader(this._boundShader.shader);this._updateDefinesShader(this._boundShader.shader);this._updateUniformsShader(this._boundShader.shader)}this._boundShader.wireframe=n.wireframe;if(this._changedDefines)this._updateDefines();if(this._changedUniforms)this._updateUniforms();if(t!==false)this._cgl.pushShader(this._boundShader.shader);this._boundShader.shader.copyUniformValues(this._boundShader.orig);if(this.needsTexturePush){for(let e=0;e<this._textures.length;e++){const i=this._textures[e][0];const r=this._textures[e][1];const o=this._textures[e][2];if(this._getUniform(i)){const s=this.getPrefixedName(i);const l=this._boundShader.shader.getUniform(s);if(l)this._boundShader.shader.pushTexture(l,r,o)}}this.needsTexturePush=false;this._textures.length=0}this._modulesChanged=false;this._boundShader.shader.fromMod=this;if(this.onBind)this.onBind(this._boundShader.shader);return this._boundShader.shader}unbind(e){if(this._boundShader){if(e!==false)this._cgl.popShader()}this._boundShader=null}_addModulesToShader(t){let n;if(this._mods.length>1)n=this._mods[0];for(let e=0;e<this._mods.length;e++)t.addModule(this._mods[e],n)}_removeModulesFromShader(e){for(const t in this._origShaders)this._origShaders[t].shader.removeModule(e)}addModule(e){this._mods.push(e);this._modulesChanged=true}removeModule(t){const n=[];let a=false;for(let e=0;e<this._mods.length;e++){if(this._mods[e].title==t){a=true;this._removeModulesFromShader(this._mods[e]);n.push(e)}}for(let e=n.length-1;e>=0;e-=1)this._mods.splice(n[e],1);this._modulesChanged=true}_updateUniformsShader(a){for(let e=0;e<this._uniforms.length;e++){const t=this._uniforms[e];const n=this.getPrefixedName(t.name);if(!a.hasUniform(n)&&!t.structName){let e=null;if(t.shaderType==="both"){e=a.addUniformBoth(t.type,n,t.v1,t.v2,t.v3,t.v4);e.comment="mod: "+this._name}else if(t.shaderType==="frag"){e=a.addUniformFrag(t.type,n,t.v1,t.v2,t.v3,t.v4);e.comment="mod: "+this._name}else if(t.shaderType==="vert"){e=a.addUniformVert(t.type,n,t.v1,t.v2,t.v3,t.v4);e.comment="mod: "+this._name}}}for(let n=0;n<this._structUniforms.length;n+=1){const i=this._structUniforms[n];let e=i.uniformName;let t=i.structName;const r=i.members;e=this.getPrefixedName(i.uniformName);t=this.getPrefixedName(i.structName);if(i.shaderType==="frag"){a.addUniformStructFrag(t,e,r)}if(i.shaderType==="vert"){a.addUniformStructVert(t,e,r)}if(i.shaderType==="both"){a.addUniformStructBoth(t,e,r)}}}_updateUniforms(){for(const e in this._origShaders)this._updateUniformsShader(this._origShaders[e].shader);this._changedUniforms=false}_setUniformValue(e,t,n){const a=e.getUniform(t);if(a)a.setValue(n)}setUniformValue(e,t){const n=this._getUniform(e);if(!n)return;const a=this.getPrefixedName(e);for(const i in this._origShaders){this._setUniformValue(this._origShaders[i].shader,a,t)}}hasUniform(e){return this._getUniform(e)}_getUniform(t){for(let e=0;e<this._uniforms.length;e++){if(this._uniforms[e].name==t)return this._uniforms[e];if(this._uniforms[e].structName){if(this._uniforms[e].propertyName==t)return this._uniforms[e]}}return false}_getStructUniform(t){for(let e=0;e<this._structUniforms.length;e+=1)if(this._structUniforms[e].uniformName===t)return this._structUniforms[e];return null}_isStructUniform(t){for(let e=0;e<this._uniforms.length;e++){if(this._uniforms[e].name==t)return false;if(this._uniforms[e].structName){if(this._uniforms[e].propertyName==t)return true}}return false}addUniform(t,n,a,i,r,o,s,l,u,m){if(!this._getUniform(n)){let e="both";if(m)e=m;this._uniforms.push({type:t,name:n,v1:a,v2:i,v3:r,v4:o,structUniformName:s,structName:l,propertyName:u,shaderType:e});this._changedUniforms=true}}addUniformFrag(e,t,n,a,i,r){this.addUniform(e,t,n,a,i,r,null,null,null,"frag");this._changedUniforms=true}addUniformVert(e,t,n,a,i,r){this.addUniform(e,t,n,a,i,r,null,null,null,"vert");this._changedUniforms=true}addUniformBoth(e,t,n,a,i,r){this.addUniform(e,t,n,a,i,r,null,null,null,"both");this._changedUniforms=true}addUniformStruct(t,n,a,i){for(let e=0;e<a.length;e+=1){const r=a[e];if((r.type==="2i"||r.type==="i"||r.type==="3i")&&i==="both")console.error("Adding an integer struct member to both shaders can potentially error. Please use different structs for each shader. Error occured in struct:",t," with member:",r.name," of type:",r.type,".");if(!this._getUniform(n+"."+r.name)){this.addUniform(r.type,n+"."+r.name,r.v1,r.v2,r.v3,r.v4,n,t,r.name,i)}}if(!this._getStructUniform(n)){this._structUniforms.push({structName:t,uniformName:n,members:a,shaderType:i})}}addUniformStructVert(e,t,n){this.addUniformStruct(e,t,n,"vert")}addUniformStructFrag(e,t,n){this.addUniformStruct(e,t,n,"frag")}addUniformStructBoth(e,t,n){this.addUniformStruct(e,t,n,"both")}addAttribute(t){for(let e=0;e<this._attributes.length;e++){if(this._attributes[e].name==t.name&&this._attributes[e].nameFrag==t.nameFrag)return}this._attributes.push(t)}pushTexture(e,t,n){if(!t)throw new Error("no texture given to texturestack");this._textures.push([e,t,n]);this.needsTexturePush=true}_removeUniformFromShader(e,t){if(t.hasUniform(e))t.removeUniform(e)}removeUniform(t){if(this._getUniform(t)){for(let e=this._uniforms.length-1;e>=0;e-=1){const n=t;if(this._uniforms[e].name==t&&!this._uniforms[e].structName){for(const a in this._origShaders){this._removeUniformFromShader(this.getPrefixedName(n),this._origShaders[a].shader)}this._uniforms.splice(e,1)}}this._changedUniforms=true}}removeUniformStruct(t){if(this._getStructUniform(t)){for(let e=this._structUniforms.length-1;e>=0;e-=1){const n=this._structUniforms[e];if(n.uniformName===t){for(const a in this._origShaders){for(let e=0;e<n.members.length;e+=1){const i=n.members[e];this._removeUniformFromShader(this.getPrefixedName(i.name),this._origShaders[a].shader)}}this._structUniforms.splice(e,1)}}this._changedUniforms=true}}getPrefixedName(e){const t=this._mods[0].group;if(t===undefined){return}if(e.startsWith("MOD_")){e=e.substr("MOD_".length);e="mod"+t+"_"+e}return e}_updateDefinesShader(e){for(const t in this._defines){const n=this.getPrefixedName(t);if(this._defines[t]!==null&&this._defines[t]!==undefined)e.define(n,this._defines[t]);else e.removeDefine(n)}for(const t in this._definesToggled){const n=this.getPrefixedName(t);e.toggleDefine(n,this._definesToggled[t])}}_updateDefines(){for(const e in this._origShaders)this._updateDefinesShader(this._origShaders[e].shader);this._changedDefines=false}define(e,t){if(t===undefined)t=true;this._defines[e]=t;this._changedDefines=true}removeDefine(e){this._defines[e]=null;this._changedDefines=true}hasDefine(e){if(this._defines[e]!==null&&this._defines[e]!==undefined)return true;return false}toggleDefine(e,t){this._changedDefines=true;this._definesToggled[e]=t}currentShader(){if(!this._boundShader)return null;return this._boundShader.shader}dispose(){}}CGL.ShaderModifier=t;((this.CGL=this.CGL||{}).COREMODULES=this.CGL.COREMODULES||{}).Shadermodifier=e.Shadermodifier})();(()=>{"use strict";var e={};function t(){return`
IN vec3 vPosition;
IN vec2 attrTexCoord;
IN vec3 attrVertNormal;
IN float attrVertIndex;
IN vec3 attrTangent;
IN vec3 attrBiTangent;

UNI mat4 projMatrix;
UNI mat4 modelMatrix;
UNI mat4 viewMatrix;


OUT vec2 texCoord;
OUT vec3 norm;

{{MODULES_HEAD}}

${this.type==="point"?"OUT vec3 modelPos;":""}
void main() {
    texCoord=attrTexCoord;
    texCoord.y = 1. - texCoord.y;
    norm=attrVertNormal;
    vec4 pos = vec4(vPosition, 1.0);
    mat4 mMatrix=modelMatrix;
    vec3 tangent = attrTangent;
    vec3 bitangent = attrBiTangent;

    {{MODULE_VERTEX_POSITION}}

    mat4 mvMatrix=viewMatrix * mMatrix;
    vec4 vPos = projMatrix * mvMatrix * pos;
    ${this.type==="point"?"modelPos = (mMatrix * pos).xyz;":""}
    gl_Position = vPos;
}
`}function n(){return`
   {{MODULES_HEAD}}
   ${this.type==="point"?"IN vec3 modelPos;":""}
   ${this.type==="point"?"UNI vec3 inLightPosition;":""}
   ${this.type==="point"?"UNI vec2 inNearFar;":""}

    IN vec2 texCoord;

    void main() {
        {{MODULE_BEGIN_FRAG}}
        vec4 col = vec4(1.);


        outColor = vec4(1.);

        {{MODULE_COLOR}}

        ${this.type==="point"?"vec3 fromLightToFrag = (modelPos - inLightPosition);":""}


        ${this.type==="point"?"float depth = (length(fromLightToFrag) - inNearFar.x) / (inNearFar.y - inNearFar.x);":"float depth = gl_FragCoord.z;"}

        float dx = dFdx(depth); // for biasing depth-per-pixel
        float dy = dFdy(depth); // for biasing depth-per-pixel

        float clampedDerivative = clamp(dot(dx, dx) + dot(dy, dy), 0., 1.);
        float moment2 = dot(depth, depth) + 0.25 * clampedDerivative;

        outColor.x = depth;
        outColor.y = moment2;
        outColor.z = depth;
    }
`}function a(){if(this.type==="point")return"";return`

IN vec3 vPosition;
IN vec2 attrTexCoord;

OUT vec2 texCoord;
OUT vec2 coord0;
OUT vec2 coord1;
OUT vec2 coord2;
OUT vec2 coord3;
OUT vec2 coord4;
OUT vec2 coord5;
OUT vec2 coord6;

UNI mat4 projMatrix;
UNI mat4 mvMatrix;
UNI mat4 modelMatrix;

UNI vec2 inXY;

void main() {
    texCoord=attrTexCoord;

    vec4 pos = vec4(vPosition,  1.0);

    {{MODULE_VERTEX_POSITION}}

    coord3 = attrTexCoord;


    coord0 = attrTexCoord + (-3.0368997744118595 * inXY);
    coord0 = clamp(coord0, 0., 1.);
    coord1 = attrTexCoord + (-2.089778445362373 * inXY);
    coord1 = clamp(coord1, 0., 1.);
    coord2 = attrTexCoord + (-1.2004366090034069 * inXY);
    coord2 = clamp(coord2, 0., 1.);
    coord4 = attrTexCoord + (1.2004366090034069 * inXY);
    coord4 = clamp(coord4, 0., 1.);
    coord5 = attrTexCoord + (2.089778445362373* inXY);
    coord5 = clamp(coord5, 0., 1.);
    coord6 = attrTexCoord + (3.0368997744118595 * inXY);
    coord6 = clamp(coord6, 0., 1.);

    gl_Position = projMatrix * mvMatrix * pos;
}
    `}function i(){if(this.type==="point")return"";return`
UNI sampler2D tex;

IN vec2 coord0;
IN vec2 coord1;
IN vec2 coord2;
IN vec2 coord3;
IN vec2 coord4;
IN vec2 coord5;
IN vec2 coord6;

void main() {

    vec4 color = vec4(0.0);


    color.xyz += texture(tex, coord0).xyz * 0.06927096443792478;  // 1/64
    color.xyz += texture(tex, coord1).xyz * 0.1383328848652136;   // 6/64
    color.xyz += texture(tex, coord2).xyz * 0.21920904690397863;  // 15/64
    color.xyz += texture(tex, coord3).xyz * 0.14637421;           // 20/64
    color.xyz += texture(tex, coord4).xyz * 0.21920904690397863;  // 15/64
    color.xyz += texture(tex, coord5).xyz * 0.1383328848652136;   // 6/64
    color.xyz += texture(tex, coord6).xyz * 0.06927096443795711;  // 1/64

    color.a = 1.;

    outColor = color;
}
    `}function r(e,t){this.type=t.type||"point";this.color=t.color||[1,1,1];this.specular=t.specular||[0,0,0];this.position=t.position||null;this.intensity=t.intensity||1;this.radius=t.radius||1;this.falloff=t.falloff||1;this.spotExponent=t.spotExponent||1;this.cosConeAngleInner=t.cosConeAngleInner||0;this.cosConeAngle=t.cosConeAngle||0;this.conePointAt=t.conePointAt||[0,0,0];this.castShadow=t.castShadow||false;this.nearFar=t.nearFar||[0,0];this.normalOffset=t.normalOffset||0;this.shadowBias=t.shadowBias||0;this.shadowStrength=t.shadowStrength||0;this.lightMatrix=null;this.shadowMap=null;this.shadowMapDepth=null;this.shadowCubeMap=null;this._cgl=e;this.state={isUpdating:false};this._framebuffer=null;this._shaderShadowMap={shader:null,uniforms:{lightPosition:null,nearFar:null},matrices:{modelMatrix:mat4.create(),viewMatrix:mat4.create(),projMatrix:mat4.create(),biasMatrix:mat4.fromValues(.5,0,0,0,0,.5,0,0,0,0,.5,0,.5,.5,.5,1)},vectors:{lookAt:vec3.create(),camPos:vec3.create(),up:vec3.fromValues(0,1,0)}};this._effectBlur=null;this._shaderBlur={shader:null,uniforms:{XY:null}};this._cubemap=null;return this}r.prototype.getModifiableParameters=function(){return["color","specular","position","intensity","radius","falloff","spotExponent","cosConeAngleInner","cosConeAngle","conePointAt"]};r.prototype.createProjectionMatrix=r.prototype.updateProjectionMatrix=function(e,t,n,a){if(this.type==="spot"){mat4.perspective(this._shaderShadowMap.matrices.projMatrix,-2*CGL.DEG2RAD*a,1,t,n)}else if(this.type==="directional"){mat4.ortho(this._shaderShadowMap.matrices.projMatrix,-1*e,e,-1*e,e,t,n)}else if(this.type==="point"){mat4.perspective(this._shaderShadowMap.matrices.projMatrix,CGL.DEG2RAD*90,1,t,n);this.nearFar=[t,n]}};r.prototype.hasFramebuffer=function(){return!!this._framebuffer};r.prototype.hasShadowMapShader=function(){return!!this._shaderShadowMap.shader};r.prototype.hasBlurShader=function(){return!!this._shaderBlur.shader};r.prototype.hasBlurEffect=function(){return!!this._effectBlur};r.prototype.getShadowMap=function(){if(this.type==="point")return null;return this._framebuffer.getTextureColor()};r.prototype.getShadowMapDepth=function(){if(this.type==="point")return null;return this._framebuffer.getTextureDepth()};r.prototype.createFramebuffer=function(e,t,n){this.state.isUpdating=true;const a=e||512;const i=t||512;if(this.type==="point"){if(!this.hasCubemap()){this._cubemap=new CGL.CubemapFramebuffer(this._cgl,a,i,{name:"point light shadowmap"})}else{this._cubemap.setSize(a,i)}this._cubemap.setCamPos(this.position);this._cubemap.setMatrices(this._shaderShadowMap.matrices.modelMatrix,this._shaderShadowMap.matrices.viewMatrix,this._shaderShadowMap.matrices.projMatrix);this.state.isUpdating=false;return}if(this.hasFramebuffer())this._framebuffer.delete();if(n){if(n.filter){n.isFloatingPointTexture=n.filter!==CGL.Texture.FILTER_MIPMAP}}if(this._cgl.glVersion==1){this._framebuffer=new CGL.Framebuffer(this._cgl,a,i,{isFloatingPointTexture:true,filter:CGL.Texture.FILTER_LINEAR,wrap:CGL.Texture.WRAP_CLAMP_TO_EDGE,...n})}else{this._framebuffer=new CGL.Framebuffer2(this._cgl,a,i,{isFloatingPointTexture:true,filter:CGL.Texture.FILTER_LINEAR,wrap:CGL.Texture.WRAP_CLAMP_TO_EDGE,...n})}this.state.isUpdating=false};r.prototype.hasCubemap=function(){return!!this._cubemap};r.prototype.setFramebufferSize=function(e){if(this.hasFramebuffer())this._framebuffer.setSize(e,e)};r.prototype.createShadowMapShader=function(e,t){if(this.hasShadowMapShader())return;this.state.isUpdating=true;this._shaderShadowMap.shader=new CGL.Shader(this._cgl,"shadowPass"+this.type.charAt(0).toUpperCase()+this.type.slice(1));this._shaderShadowMap.shader.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"]);const n=e||this.getShadowPassVertexShader();const a=t||this.getShadowPassFragmentShader();this._shaderShadowMap.shader.setSource(n,a);this._shaderShadowMap.shader.offScreenPass=true;if(this.type==="point"){this._shaderShadowMap.uniforms.lightPosition=new CGL.Uniform(this._shaderShadowMap.shader,"3f","inLightPosition",vec3.create());this._shaderShadowMap.uniforms.nearFar=new CGL.Uniform(this._shaderShadowMap.shader,"2f","inNearFar",vec2.create())}if(this._cgl.glVersion==1){this._cgl.enableExtension("OES_texture_float");this._cgl.enableExtension("OES_texture_float_linear");this._cgl.enableExtension("OES_texture_half_float");this._cgl.enableExtension("OES_texture_half_float_linear");this._shaderShadowMap.shader.enableExtension("GL_OES_standard_derivatives");this._shaderShadowMap.shader.enableExtension("GL_OES_texture_float");this._shaderShadowMap.shader.enableExtension("GL_OES_texture_float_linear");this._shaderShadowMap.shader.enableExtension("GL_OES_texture_half_float");this._shaderShadowMap.shader.enableExtension("GL_OES_texture_half_float_linear")}this.state.isUpdating=false};r.prototype.createBlurEffect=function(e){if(this.type==="point")return;this.state.isUpdating=true;if(this.hasBlurEffect())this._effectBlur.delete();this._effectBlur=new CGL.TextureEffect(this._cgl,{isFloatingPointTexture:true,filter:CGL.Texture.FILTER_LINEAR,wrap:CGL.Texture.WRAP_CLAMP_TO_EDGE,...e});this.state.isUpdating=false};r.prototype.createBlurShader=function(e,t){if(this.hasBlurShader()){return}if(this.type==="point")return;this.state.isUpdating=true;const n=e||this.getBlurPassVertexShader();const a=t||this.getBlurPassFragmentShader();this._shaderBlur.shader=new CGL.Shader(this._cgl,"blurPass"+this.type.charAt(0).toUpperCase()+this.type.slice(1));this._shaderBlur.shader.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"]);this._shaderBlur.shader.setSource(n,a);this._shaderBlur.uniforms.XY=new CGL.Uniform(this._shaderBlur.shader,"2f","inXY",vec2.create());this._shaderBlur.shader.offScreenPass=true;this.state.isUpdating=false};r.prototype.renderPasses=function(e,t,n){if(this.state.isUpdating)return;if(this._cgl.frameStore.shadowPass)return;this._cgl.pushCullFace(true);this._cgl.pushCullFaceFacing(this._cgl.gl.FRONT);this._cgl.gl.enable(this._cgl.gl.POLYGON_OFFSET_FILL);this._cgl.gl.polygonOffset(e,e);this._cgl.frameStore.renderOffscreen=true;this._cgl.frameStore.shadowPass=true;this._cgl.pushBlend(false);this._cgl.gl.colorMask(true,true,this.type==="point",this.type==="point");this.renderShadowPass(n);this._cgl.gl.cullFace(this._cgl.gl.BACK);this._cgl.gl.disable(this._cgl.gl.CULL_FACE);this._cgl.gl.disable(this._cgl.gl.POLYGON_OFFSET_FILL);if(this.type!=="point")this.renderBlurPass(t);this._cgl.gl.colorMask(true,true,true,true);this._cgl.popBlend();this._cgl.popCullFaceFacing();this._cgl.popCullFace();this._cgl.frameStore.shadowPass=false;this._cgl.frameStore.renderOffscreen=false;if(this.type!=="point"){this.shadowMap=this._framebuffer.getTextureColor();this.shadowMapDepth=this._framebuffer.getTextureDepth()}else{this.shadowMap=null;this.shadowMapDepth=null}};r.prototype.renderShadowPass=function(t){if(this.state.isUpdating)return;if(this.type==="point"){this._shaderShadowMap.uniforms.nearFar.setValue(this.nearFar);this._shaderShadowMap.uniforms.lightPosition.setValue(this.position);this._cubemap.setCamPos(this.position);this._cubemap.setMatrices(this._shaderShadowMap.matrices.modelMatrix,this._shaderShadowMap.matrices.viewMatrix,this._shaderShadowMap.matrices.projMatrix);this._cgl.pushShader(this._shaderShadowMap.shader);this._cubemap.renderStart();for(let e=0;e<6;e+=1){this._cubemap.renderStartCubemapFace(e);if(t)t();this._cubemap.renderEndCubemapFace()}this._cubemap.renderEnd();this._cgl.popShader();this.shadowCubeMap=this._cubemap.getTextureColor();return}this._cgl.pushShader(this._shaderShadowMap.shader);this._cgl.pushModelMatrix();this._cgl.pushViewMatrix();this._cgl.pushPMatrix();this._framebuffer.renderStart(this._cgl);mat4.copy(this._cgl.mMatrix,this._shaderShadowMap.matrices.modelMatrix);vec3.set(this._shaderShadowMap.vectors.camPos,this.position[0],this.position[1],this.position[2]);if(this.type==="spot")vec3.set(this._shaderShadowMap.vectors.lookAt,this.conePointAt[0],this.conePointAt[1],this.conePointAt[2]);mat4.lookAt(this._cgl.vMatrix,this._shaderShadowMap.vectors.camPos,this._shaderShadowMap.vectors.lookAt,this._shaderShadowMap.vectors.up);mat4.copy(this._cgl.pMatrix,this._shaderShadowMap.matrices.projMatrix);if(!this.lightMatrix)this.lightMatrix=mat4.create();mat4.mul(this.lightMatrix,this._cgl.pMatrix,this._cgl.vMatrix);mat4.mul(this.lightMatrix,this._cgl.mMatrix,this.lightMatrix);mat4.mul(this.lightMatrix,this._shaderShadowMap.matrices.biasMatrix,this.lightMatrix);this._cgl.gl.clearColor(1,1,1,1);this._cgl.gl.clear(this._cgl.gl.DEPTH_BUFFER_BIT|this._cgl.gl.COLOR_BUFFER_BIT);if(t)t();this._framebuffer.renderEnd(this._cgl);this._cgl.popPMatrix();this._cgl.popModelMatrix();this._cgl.popViewMatrix();this._cgl.popShader()};r.prototype.renderBlurPass=function(e){if(this.state.isUpdating)return;this._cgl.pushShader(this._shaderBlur.shader);this._effectBlur.setSourceTexture(this._framebuffer.getTextureColor());this._effectBlur.startEffect();this._effectBlur.bind();this._cgl.setTexture(0,this._effectBlur.getCurrentSourceTexture().tex);this._shaderBlur.uniforms.XY.setValue([e,0]);this._effectBlur.finish();this._effectBlur.bind();this._cgl.setTexture(0,this._effectBlur.getCurrentSourceTexture().tex);this._shaderBlur.uniforms.XY.setValue([0,e]);this._effectBlur.finish();this._effectBlur.endEffect();this._cgl.popShader()};r.prototype.getShadowPassVertexShader=t;r.prototype.getShadowPassFragmentShader=n;r.prototype.getBlurPassVertexShader=a;r.prototype.getBlurPassFragmentShader=i;CGL.Light=r;((this.CGL=this.CGL||{}).COREMODULES=this.CGL.COREMODULES||{}).Light=e.Light})();(()=>{"use strict";var e={};class n{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(!CABLES.UI&&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 t=8;class a{constructor(e={}){this.id=CABLES.uuid();this.width=0;this.height=0;this.name="unknown";e=e||{};this.pixelFormat=e.pixelFormat||a.PFORMATSTR_RGBA8UB;this.name=e.name||"unknown";if(!e.width)e.width=t;if(!e.height)e.height=t}}a.getDefaultTextureData=(e,r,o={})=>{if(e=="empty"){return new Uint8Array(r*r*4).fill(0)}else if(e=="color"){const i=new Uint8Array(r*r*4);let t=o.r||1;let n=o.g||1;let a=o.b||1;for(let e=0;e<r*r;e++){i[e*4+0]=t;i[e*4+1]=n;i[e*4+2]=a;i[e*4+3]=255}return i}else if(e=="randomUInt"){const i=new Uint8Array(r*r*4);for(let e=0;e<r*r;e++){i[e*4+0]=Math.random()*255;i[e*4+1]=Math.random()*255;i[e*4+2]=Math.random()*255;i[e*4+3]=255}return i}else if(e=="random"||e=="randomFloat"){const i=new Float32Array(r*r*4);for(let e=0;e<r*r;e++){i[e*4+0]=(Math.random()-.5)*2;i[e*4+1]=(Math.random()-.5)*2;i[e*4+2]=(Math.random()-.5)*2;i[e*4+3]=1}return i}else if(e=="stripes"){const s=[];let n=o.r;let a=o.g;let i=o.b;if(n===undefined)n=1;if(a===undefined)a=1;if(i===undefined)i=1;for(let t=0;t<r;t++){for(let e=0;e<r;e++){if((e+t)%64<32){s.push((200+t/r*25+e/r*25)*n);s.push((200+t/r*25+e/r*25)*a);s.push((200+t/r*25+e/r*25)*i)}else{s.push((40+t/r*25+e/r*25)*n);s.push((40+t/r*25+e/r*25)*a);s.push((40+t/r*25+e/r*25)*i)}s.push(255)}}return new Uint8Array(s)}else{console.warn("unknown default texture",e);return a.getDefaultTextureData("stripes",r,{r:1,g:0,b:0})}};a.FILTER_NEAREST=0;a.FILTER_LINEAR=1;a.FILTER_MIPMAP=2;a.WRAP_REPEAT=0;a.WRAP_MIRRORED_REPEAT=1;a.WRAP_CLAMP_TO_EDGE=2;a.TYPE_DEFAULT=0;a.TYPE_DEPTH=1;a.TYPE_FLOAT=2;a.PFORMATSTR_RGB565="RGB 5/6/5bit ubyte";a.PFORMATSTR_R8UB="R 8bit ubyte";a.PFORMATSTR_RG8UB="RG 8bit ubyte";a.PFORMATSTR_RGB8UB="RGB 8bit ubyte";a.PFORMATSTR_RGBA8UB="RGBA 8bit ubyte";a.PFORMATSTR_SRGBA8="SRGBA 8bit ubyte";a.PFORMATSTR_R11FG11FB10F="RGB 11/11/10bit float";a.PFORMATSTR_R16F="R 16bit float";a.PFORMATSTR_RG16F="RG 16bit float";a.PFORMATSTR_RGB16F="RGB 16bit float";a.PFORMATSTR_RGBA16F="RGBA 16bit float";a.PFORMATSTR_R32F="R 32bit float";a.PFORMATSTR_RG32F="RG 32bit float";a.PFORMATSTR_RGB32F="RGB 32bit float";a.PFORMATSTR_RGBA32F="RGBA 32bit float";a.PFORMATSTR_DEPTH="DEPTH";a.PIXELFORMATS=[a.PFORMATSTR_RGB565,a.PFORMATSTR_R8UB,a.PFORMATSTR_RG8UB,a.PFORMATSTR_RGB8UB,a.PFORMATSTR_RGBA8UB,a.PFORMATSTR_SRGBA8,a.PFORMATSTR_R11FG11FB10F,a.PFORMATSTR_R16F,a.PFORMATSTR_RG16F,a.PFORMATSTR_RGBA16F,a.PFORMATSTR_R32F,a.PFORMATSTR_RGBA32F];const i=8;class u extends a{constructor(e,t={}){super(t);if(!e)throw new Error("no cgl");this._log=new n("cgl_texture");this._cgl=e;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=u.FILTER_NEAREST;this.wrap=u.WRAP_CLAMP_TO_EDGE;this.texTarget=this._cgl.gl.TEXTURE_2D;if(t&&t.type)this.texTarget=t.type;this.textureType=u.TYPE_DEFAULT;this.unpackAlpha=true;this._fromData=true;this._glDataType=-1;this._glInternalFormat=-1;this._glDataFormat=-1;if(t){if(t.isDepthTexture)this.textureType=u.TYPE_DEPTH;if(t.isFloatingPointTexture===true)this.textureType=u.TYPE_FLOAT;if("textureType"in t)this.textureType=t.textureType;if("filter"in t)this.filter=t.filter;if("wrap"in t)this.wrap=t.wrap;if("unpackAlpha"in t)this.unpackAlpha=t.unpackAlpha;if("flip"in t)this.flip=t.flip;if("shadowMap"in t)this.shadowMap=t.shadowMap;if("anisotropic"in t)this.anisotropic=t.anisotropic}else{t={}}if(!t.pixelFormat&&t.isFloatingPointTexture)this.pixelFormat=u.PFORMATSTR_RGBA32F;if(this.textureType==u.TYPE_DEPTH)this.pixelFormat=u.PFORMATSTR_DEPTH;this._cgl.profileData.profileTextureNew++;this.setFormat(u.setUpGlPixelFormat(this._cgl,this.pixelFormat));this._cgl.profileData.addHeavyEvent("texture created",this.name,t.width+"x"+t.height);this.setSize(t.width,t.height);this.getInfoOneLine()}isFloatingPoint(){return u.isPixelFormatFloat(this.pixelFormat)}compareSettings(e){if(!e)return false;return e.width==this.width&&e.height==this.height&&e.filter==this.filter&&e.wrap==this.wrap&&e.textureType==this.textureType&&e.unpackAlpha==this.unpackAlpha&&e.anisotropic==this.anisotropic&&e.shadowMap==this.shadowMap&&e.texTarget==this.texTarget&&e.flip==this.flip}clone(){const e=new u(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(e)){this._log.error("Cloned texture settings do not compare!");this._log.error(this);this._log.error(e)}return e}setFormat(e){this.pixelFormat=e.pixelFormat;this._glDataFormat=e.glDataFormat;this._glInternalFormat=e.glInternalFormat;this._glDataType=e.glDataType}setSize(e,t){if(this._cgl.aborted)return;if(e!=e||e<=0||!e)e=i;if(t!=t||t<=0||!t)t=i;if(e>this._cgl.maxTexSize||t>this._cgl.maxTexSize)this._log.error("texture size too big! "+e+"x"+t+" / max: "+this._cgl.maxTexSize);e=Math.min(e,this._cgl.maxTexSize);t=Math.min(t,this._cgl.maxTexSize);e=Math.floor(e);t=Math.floor(t);if(this.width==e&&this.height==t)return;e=this._cgl.checkTextureSize(e);t=this._cgl.checkTextureSize(t);this.width=e;this.height=t;this.deleted=false;this.setFormat(u.setUpGlPixelFormat(this._cgl,this.pixelFormat));this.shortInfoString=this.getInfoOneLine();this._cgl.gl.bindTexture(this.texTarget,this.tex);this._cgl.profileData.profileTextureResize++;const n=null;this._cgl.gl.texImage2D(this.texTarget,0,this._glInternalFormat,e,t,0,this._glDataFormat,this._glDataType,n);this._setFilter();this.updateMipMap();this._cgl.gl.bindTexture(this.texTarget,null)}initFromData(e,t,n,a,i){this.filter=a;this.wrap=i;if(a==undefined)this.filter=u.FILTER_LINEAR;if(i==undefined)this.wrap=u.WRAP_CLAMP_TO_EDGE;this.width=t;this.height=n;this._fromData=true;this.deleted=false;if(this.height>this._cgl.maxTexSize||this.width>this._cgl.maxTexSize){const r=CGL.Texture.getTempTexture(this._cgl);this.width=r.width;this.height=r.height;this.tex=r.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(u.setUpGlPixelFormat(this._cgl,this.pixelFormat));this._cgl.gl.texImage2D(this.texTarget,0,this._glInternalFormat,t,n,0,this._glDataFormat,this._glDataType,e);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==u.FILTER_MIPMAP){this._cgl.gl.generateMipmap(this.texTarget);this._cgl.profileData.profileGenMipMap++}}initTexture(e,t){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(e.width||e.videoWidth)this.width=e.videoWidth||e.width;if(e.height||e.videoHeight)this.height=e.videoHeight||e.height;if(t!==undefined)this.filter=t;if(e.height>this._cgl.maxTexSize||e.width>this._cgl.maxTexSize){const n=CGL.Texture.getTempTexture(this._cgl);this.width=n.width;this.height=n.height;this.tex=n.tex;this._log.warn("[cgl_texture] texture size too big!",e.width,e.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(u.setUpGlPixelFormat(this._cgl,this.pixelFormat));this._cgl.gl.texImage2D(this.texTarget,0,this._glInternalFormat,this._glDataFormat,this._glDataType,e);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")}dispose(){this.delete()}delete(){if(this.loading){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}isPowerOfTwo(){return u.isPowerOfTwo(this.width)&&u.isPowerOfTwo(this.height)}printInfo(){console.log(this.getInfo())}getInfoReadable(){const e=this.getInfo();let t="";e.name=e.name.substr(0,e.name.indexOf("?rnd="));for(const n in e){t+="* "+n+":  **"+e[n]+"**\n"}return t}getInfoOneLine(){let e=""+this.width+"x"+this.height;e+=" ";e+=this.pixelFormat;if(this.filter===CGL.Texture.FILTER_NEAREST)e+=" nearest";if(this.filter===CGL.Texture.FILTER_LINEAR)e+=" linear";if(this.filter===CGL.Texture.FILTER_MIPMAP)e+=" mipmap";if(this.wrap===CGL.Texture.WRAP_CLAMP_TO_EDGE)e+=" clamp";if(this.wrap===CGL.Texture.WRAP_REPEAT)e+=" repeat";if(this.wrap===CGL.Texture.WRAP_MIRRORED_REPEAT)e+=" repeatmir";this.shortInfoString=e;return e}getInfoOneLineShort(){let e=""+this.width+"x"+this.height;e+=" ";e+=this.pixelFormat;this.shortInfoString=e;return e}getInfo(){return u.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==u.TYPE_FLOAT&&this.filter==u.FILTER_MIPMAP){this.filter=u.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=u.FILTER_NEAREST;this.wrap=u.WRAP_CLAMP_TO_EDGE}else{if(this.wrap==u.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==u.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==u.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==u.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==u.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==u.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 e=this._cgl.enableExtension("EXT_texture_filter_anisotropic");if(this._cgl.maxAnisotropic){const t=Math.min(this._cgl.maxAnisotropic,this.anisotropic);this._cgl.gl.texParameterf(this._cgl.gl.TEXTURE_2D,e.TEXTURE_MAX_ANISOTROPY_EXT,t)}}}this.getInfoOneLine();this._cgl.printError("_setFilter")}}u.load=function(n,a,i,e){if(!a)return i({error:true});let r=null;if(!n.patch.loading.existByName(a))r=n.patch.loading.start("cgl.texture",a);const o=new u(n);o.name=a;o.image=new Image;o.image.crossOrigin="anonymous";o.loading=true;if(e&&e.hasOwnProperty("filter"))o.filter=e.filter;if(e&&e.hasOwnProperty("flip"))o.flip=e.flip;if(e&&e.hasOwnProperty("wrap"))o.wrap=e.wrap;if(e&&e.hasOwnProperty("anisotropic"))o.anisotropic=e.anisotropic;if(e&&e.hasOwnProperty("unpackAlpha"))o.unpackAlpha=e.unpackAlpha;if(e&&e.hasOwnProperty("pixelFormat"))o.pixelFormat=e.pixelFormat;o.image.onabort=o.image.onerror=e=>{console.warn("[cgl.texture.load] error loading texture",a,e);o.loading=false;if(r)n.patch.loading.finished(r);const t={error:true};if(i)i(t,o)};o.image.onload=function(e){n.addNextFrameOnceCallback(()=>{o.initTexture(o.image);if(r)n.patch.loading.finished(r);o.loading=false;if(i)i(null,o)})};o.image.src=a;return o};u.getTempTexture=function(e){if(!e)console.error("[getTempTexture] no cgl!");if(!e.tempTexture)e.tempTexture=u.getTemporaryTexture(e,256,u.FILTER_LINEAR,u.REPEAT);return e.tempTexture};u.getErrorTexture=function(e){if(!e)console.error("[getTempTexture] no cgl!");if(!e.errorTexture)e.errorTexture=u.getTemporaryTexture(e,256,u.FILTER_LINEAR,u.REPEAT,1,.2,.2);return e.errorTexture};u.getEmptyTexture=function(e,t){if(t)return u.getEmptyTextureFloat(e);if(!e)console.error("[getEmptyTexture] no cgl!");if(e.tempTextureEmpty)return e.tempTextureEmpty;let n=8;e.tempTextureEmpty=new u(e,{name:"emptyTexture"});const a=u.getDefaultTextureData("empty",n);e.tempTextureEmpty.initFromData(a,n,n,u.FILTER_NEAREST,u.WRAP_REPEAT);return e.tempTextureEmpty};u.getEmptyTextureFloat=function(e){if(!e)console.error("[getEmptyTextureFloat] no cgl!");if(e.tempTextureEmptyFloat)return e.tempTextureEmptyFloat;e.tempTextureEmptyFloat=new u(e,{name:"emptyTexture",isFloatingPointTexture:true});const t=new Float32Array(8*8*4).fill(1);for(let e=0;e<8*8*4;e+=4)t[e+3]=0;e.tempTextureEmptyFloat.initFromData(t,8,8,u.FILTER_NEAREST,u.WRAP_REPEAT);return e.tempTextureEmptyFloat};u.getRandomTexture=function(e){if(!e)console.error("[getRandomTexture] no cgl!");if(e.randomTexture)return e.randomTexture;const t=256;const n=u.getDefaultTextureData("randomUInt",t);e.randomTexture=new u(e);e.randomTexture.initFromData(n,t,t,u.FILTER_NEAREST,u.WRAP_REPEAT);return e.randomTexture};u.getRandomFloatTexture=function(e){if(!e)console.error("[getRandomTexture] no cgl!");if(e.getRandomFloatTexture)return e.getRandomFloatTexture;const t=256;const n=u.getDefaultTextureData("randomFloat",t);e.getRandomFloatTexture=new u(e,{isFloatingPointTexture:true});e.getRandomFloatTexture.initFromData(n,t,t,u.FILTER_NEAREST,u.WRAP_REPEAT);return e.getRandomFloatTexture};u.getBlackTexture=function(e){if(!e)this._log.error("[getBlackTexture] no cgl!");if(e.blackTexture)return e.blackTexture;const t=8;const n=u.getDefaultTextureData("color",t,{r:0,g:0,b:0});e.blackTexture=new u(e);e.blackTexture.initFromData(n,t,t,u.FILTER_NEAREST,u.WRAP_REPEAT);return e.blackTexture};u.getEmptyCubemapTexture=function(t){const n=[t.gl.TEXTURE_CUBE_MAP_POSITIVE_X,t.gl.TEXTURE_CUBE_MAP_NEGATIVE_X,t.gl.TEXTURE_CUBE_MAP_POSITIVE_Y,t.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,t.gl.TEXTURE_CUBE_MAP_POSITIVE_Z,t.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];const e=t.gl.createTexture();const a=t.gl.TEXTURE_CUBE_MAP;const i=u.FILTER_NEAREST;const r=u.WRAP_CLAMP_TO_EDGE;const o=8;const s=8;t.profileData.profileTextureNew++;t.gl.bindTexture(a,e);t.profileData.profileTextureResize++;for(let e=0;e<6;e+=1){const l=new Uint8Array(8*8*4);t.gl.texImage2D(n[e],0,t.gl.RGBA,8,8,0,t.gl.RGBA,t.gl.UNSIGNED_BYTE,l);t.gl.texParameteri(a,t.gl.TEXTURE_MAG_FILTER,t.gl.NEAREST);t.gl.texParameteri(a,t.gl.TEXTURE_MIN_FILTER,t.gl.NEAREST);t.gl.texParameteri(a,t.gl.TEXTURE_WRAP_S,t.gl.CLAMP_TO_EDGE);t.gl.texParameteri(a,t.gl.TEXTURE_WRAP_T,t.gl.CLAMP_TO_EDGE)}t.gl.bindTexture(a,null);return{id:CABLES.uuid(),tex:e,cubemap:e,width:o,height:s,filter:i,wrap:r,unpackAlpha:true,flip:true,_fromData:true,name:"emptyCubemapTexture",anisotropic:0}};u.getTempGradientTexture=function(e){if(!e)console.error("[getTempGradientTexture] no cgl!");return u.getTempTexture(e)};u.getTemporaryTexture=function(e,t,n,a,i,r,o){const s=u.getDefaultTextureData("stripes",256,{r:i,g:r,b:o});const l=new u(e);l.initFromData(s,t,t,n,a);return l};u.createFromImage=function(e,t,n){n=n||{};const a=new u(e,n);a.flip=false;a.image=t;a.width=t.videoWidth||t.width||8;a.height=t.videoHeight||t.height||8;if(n.hasOwnProperty("wrap"))a.wrap=n.wrap;a.initTexture(t,n.filter);return a};u.fromImage=function(e,t,n,a){console.error("deprecated texture from image...");const i=new u(e);i.flip=false;if(n)i.filter=n;if(a)i.wrap=a;i.image=t;i.initTexture(t);return i};u.isPowerOfTwo=function(e){return e==1||e==2||e==4||e==8||e==16||e==32||e==64||e==128||e==256||e==512||e==1024||e==2048||e==4096||e==8192||e==16384};u.getTexInfo=function(e){const t={};t.name=e.name;t["power of two"]=e.isPowerOfTwo();t.size=e.width+" x "+e.height;let n=e.texTarget;if(e.texTarget==e._cgl.gl.TEXTURE_2D)n="TEXTURE_2D";t.target=n;t.unpackAlpha=e.unpackAlpha;if(e.cubemap)t.cubemap=true;if(e.textureType==u.TYPE_FLOAT)t.textureType="TYPE_FLOAT";if(e.textureType==u.TYPE_HALF_FLOAT)t.textureType="TYPE_HALF_FLOAT";else if(e.textureType==u.TYPE_DEPTH)t.textureType="TYPE_DEPTH";else if(e.textureType==u.TYPE_DEFAULT)t.textureType="TYPE_DEFAULT";else t.textureType="UNKNOWN "+this.textureType;if(e.wrap==u.WRAP_CLAMP_TO_EDGE)t.wrap="CLAMP_TO_EDGE";else if(e.wrap==u.WRAP_REPEAT)t.wrap="WRAP_REPEAT";else if(e.wrap==u.WRAP_MIRRORED_REPEAT)t.wrap="WRAP_MIRRORED_REPEAT";else t.wrap="UNKNOWN";if(e.filter==u.FILTER_NEAREST)t.filter="FILTER_NEAREST";else if(e.filter==u.FILTER_LINEAR)t.filter="FILTER_LINEAR";else if(e.filter==u.FILTER_MIPMAP)t.filter="FILTER_MIPMAP";else t.filter="UNKNOWN";t.pixelFormat=e.pixelFormat||"unknown";return t};u.setUpGlPixelFormat=function(e,t){const n={};if(!t){e._log.error("no pixelformatstr!");e._log.log(new Error);t=u.PFORMATSTR_RGBA8UB}n.pixelFormatBase=t;n.pixelFormat=t;n.glDataType=e.gl.UNSIGNED_BYTE;n.glInternalFormat=e.gl.RGBA8;n.glDataFormat=e.gl.RGBA;let a=e.gl.FLOAT;if(e.glUseHalfFloatTex){if(t==u.PFORMATSTR_RGBA32F)t=u.PFORMATSTR_RGBA16F;if(t==u.PFORMATSTR_RG32F)t=u.PFORMATSTR_RG16F;if(t==u.PFORMATSTR_R32F)t=u.PFORMATSTR_R16F}if(t.contains("16bit")){if(e.glVersion==2){const i=e.enableExtension("EXT_color_buffer_half_float");if(!i){console.warn("no 16bit extension, fallback to 32bit",t);if(t==u.PFORMATSTR_RGBA16F)t=u.PFORMATSTR_RGBA32F;if(t==u.PFORMATSTR_RGB16F)t=u.PFORMATSTR_RGB32F;if(t==u.PFORMATSTR_RG16F)t=u.PFORMATSTR_RG32F;if(t==u.PFORMATSTR_R16F)t=u.PFORMATSTR_R32F}else{a=e.gl.HALF_FLOAT}}}if(e.glVersion==1){n.glInternalFormat=e.gl.RGBA;if(t==u.PFORMATSTR_RGBA16F||t==u.PFORMATSTR_RG16F||t==u.PFORMATSTR_R16F){const r=e.enableExtension("OES_texture_half_float");if(!r)throw new Error("no half float texture extension");a=r.HALF_FLOAT_OES}}if(t==u.PFORMATSTR_RGBA8UB){}else if(t==u.PFORMATSTR_RGB565){n.glInternalFormat=e.gl.RGB565;n.glDataFormat=e.gl.RGB}else if(t==u.PFORMATSTR_R8UB){n.glInternalFormat=e.gl.R8;n.glDataFormat=e.gl.RED}else if(t==u.PFORMATSTR_RG8UB){n.glInternalFormat=e.gl.RG8;n.glDataFormat=e.gl.RG}else if(t==u.PFORMATSTR_RGB8UB){n.glInternalFormat=e.gl.RGB8;n.glDataFormat=e.gl.RGB}else if(t==u.PFORMATSTR_SRGBA8){n.glInternalFormat=e.gl.SRGB8_ALPHA8}else if(t==u.PFORMATSTR_R32F){n.glInternalFormat=e.gl.R32F;n.glDataFormat=e.gl.RED;n.glDataType=a}else if(t==u.PFORMATSTR_R16F){n.glInternalFormat=e.gl.R16F;n.glDataType=a;n.glDataFormat=e.gl.RED}else if(t==u.PFORMATSTR_RG16F){n.glInternalFormat=e.gl.RG16F;n.glDataType=a;n.glDataFormat=e.gl.RG}else if(t==u.PFORMATSTR_RGBA16F){if(e.glVersion==1)n.glInternalFormat=e.gl.RGBA;else n.glInternalFormat=e.gl.RGBA16F;n.glDataType=a}else if(t==u.PFORMATSTR_R11FG11FB10F){n.glInternalFormat=e.gl.R11F_G11F_B10F;n.glDataType=a;n.glDataFormat=e.gl.RGB}else if(t==u.PFORMATSTR_RGBA32F){if(e.glVersion==1)n.glInternalFormat=e.gl.RGBA;else n.glInternalFormat=e.gl.RGBA32F;n.glDataType=a}else if(t==u.PFORMATSTR_DEPTH){if(e.glVersion==1){n.glInternalFormat=e.gl.DEPTH_COMPONENT;n.glDataType=e.gl.UNSIGNED_SHORT;n.glDataFormat=e.gl.DEPTH_COMPONENT}else{n.glInternalFormat=e.gl.DEPTH_COMPONENT32F;n.glDataType=e.gl.FLOAT;n.glDataFormat=e.gl.DEPTH_COMPONENT}}else{console.log("unknown pixelformat ",t)}if(t.contains("32bit")||t==u.PFORMATSTR_R11FG11FB10F){if(e.glVersion==2)e.enableExtension("EXT_color_buffer_float");if(e.glVersion==2)e.enableExtension("EXT_float_blend");e.enableExtension("OES_texture_float_linear")}n.numColorChannels=u.getPixelFormatNumChannels(t);if(!n.glDataType||!n.glInternalFormat||!n.glDataFormat)console.log("pixelformat wrong ?!",t,n.glDataType,n.glInternalFormat,n.glDataFormat,this);return n};u.getPixelFormatNumChannels=e=>{if(e.startsWith("RGBA"))return 4;if(e.startsWith("RGB"))return 3;if(e.startsWith("RG"))return 2;return 1};u.isPixelFormatFloat=e=>{return(e||"").contains("float")};u.isPixelFormatHalfFloat=e=>{return(e||"").contains("float")&&(e||"").contains("16bit")};const r=8;class o{constructor(e,t){this.id=CABLES.uuid();this.name=t.name||"unknown cubemap texture";this._cgl=e;this.textureType=u.TYPE_DEFAULT;this._options=t;this._cubemapFaces=[this._cgl.gl.TEXTURE_CUBE_MAP_POSITIVE_X,this._cgl.gl.TEXTURE_CUBE_MAP_NEGATIVE_X,this._cgl.gl.TEXTURE_CUBE_MAP_POSITIVE_Y,this._cgl.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,this._cgl.gl.TEXTURE_CUBE_MAP_POSITIVE_Z,this._cgl.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];this.cubemap=this.tex=this._cgl.gl.createTexture();this.texTarget=this._cgl.gl.TEXTURE_CUBE_MAP;this.width=r;this.height=r;this.filter=t.filter||CGL.Texture.FILTER_NEAREST;this.wrap=t.wrap||CGL.Texture.WRAP_CLAMP_TO_EDGE;this.unpackAlpha=t.unpackAlpha||true;this.flip=t.flip||true;if(!t.hasOwnProperty("pixelFormat")||!t.pixelFormat){if(t.isFloatingPointTexture)t.pixelFormat=u.PFORMATSTR_RGBA32F;else t.pixelFormat=u.PFORMATSTR_RGBA8UB}this.pixelFormat=t.pixelFormat;this._cgl.profileData.profileTextureNew++;this.setSize(t.width,t.height)}getInfo(){return{pixelFormat:this.pixelFormat}}setSize(e,t){this.delete();this.cubemap=this.tex=this._cgl.gl.createTexture();this._cgl.checkFrameStarted("cubemap corelib setsize");if(e!=e||e<=0||!e)e=r;if(t!=t||t<=0||!t)t=r;if(e>this._cgl.maxTexSize||t>this._cgl.maxTexSize)console.error("texture size too big! "+e+"x"+t+" / max: "+this._cgl.maxTexSize);e=Math.min(e,this._cgl.maxTexSize);t=Math.min(t,this._cgl.maxTexSize);e=Math.floor(e);t=Math.floor(t);this.width=e;this.height=t;this._cgl.gl.bindTexture(this.texTarget,this.tex);this._cgl.profileData.profileTextureResize++;const n=u.setUpGlPixelFormat(this._cgl,this._options.pixelFormat);this.pixelFormat=n.pixelFormat;if(CGL.Texture.isPixelFormatHalfFloat(n.pixelFormat)){const a=this._cgl.enableExtension("EXT_color_buffer_half_float");if(!this._cgl.enableExtension("OES_texture_float_linear")){this.filter=u.FILTER_NEAREST}}else if(CGL.Texture.isPixelFormatFloat(n.pixelFormat)){if(!this._cgl.enableExtension("OES_texture_float_linear")){console.log("no linear pixelformat,using nearest");this.filter=u.FILTER_NEAREST}}for(let e=0;e<6;e++){this._cgl.gl.texImage2D(this._cubemapFaces[e],0,n.glInternalFormat,this.width,this.height,0,n.glDataFormat,n.glDataType,null)}this._setFilter();this.updateMipMap();this._cgl.gl.bindTexture(this.texTarget,null)}_setFilter(){this._cgl.checkFrameStarted("cubemap corelib");this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,this.unpackAlpha);if(CGL.Texture.isPixelFormatFloat(this.pixelFormat)&&this.filter==CGL.Texture.FILTER_MIPMAP){console.log("texture: HDR and mipmap filtering at the same time is not possible");this.filter=CGL.Texture.FILTER_LINEAR}if(this._cgl.glVersion==1&&!u.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=CGL.Texture.FILTER_NEAREST;this.wrap=CGL.Texture.WRAP_CLAMP_TO_EDGE}else{if(this.wrap==CGL.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==CGL.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==CGL.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)}else{throw new Error("[CubemapTexture] unknown texture filter!"+this.filter)}if(this.filter==CGL.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==CGL.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==CGL.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{throw new Error("[CubemapTexture] unknown texture filter!"+this.filter)}}}updateMipMap(){if(this.filter==CGL.Texture.FILTER_MIPMAP){this._cgl.gl.bindTexture(this.texTarget,this.tex);this._cgl.gl.generateMipmap(this.texTarget);this._cgl.profileData.profileGenMipMap++}}delete(){this._cgl.gl.deleteTexture(this.tex)}}class s{constructor(e,t,n,a){this._cgl=e;this.width=t||8;this.height=n||8;this._cubemapProperties=[{face:this._cgl.gl.TEXTURE_CUBE_MAP_POSITIVE_X,lookAt:vec3.fromValues(1,0,0),up:vec3.fromValues(0,-1,0)},{face:this._cgl.gl.TEXTURE_CUBE_MAP_NEGATIVE_X,lookAt:vec3.fromValues(-1,0,0),up:vec3.fromValues(0,-1,0)},{face:this._cgl.gl.TEXTURE_CUBE_MAP_POSITIVE_Y,lookAt:vec3.fromValues(0,1,0),up:vec3.fromValues(0,0,1)},{face:this._cgl.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,lookAt:vec3.fromValues(0,-1,0),up:vec3.fromValues(0,0,-1)},{face:this._cgl.gl.TEXTURE_CUBE_MAP_POSITIVE_Z,lookAt:vec3.fromValues(0,0,1),up:vec3.fromValues(0,-1,0)},{face:this._cgl.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,lookAt:vec3.fromValues(0,0,-1),up:vec3.fromValues(0,-1,0)}];this._lookAtTemp=vec3.fromValues(0,0,0);this.camPos=vec3.fromValues(0,0,0);this._modelMatrix=mat4.create();this._viewMatrix=mat4.create();this._projectionMatrix=mat4.perspective(mat4.create(),CGL.DEG2RAD*90,1,.1,1e3);this._depthRenderbuffer=null;this._framebuffer=null;this._depthbuffer=null;this._textureDepth=null;this._options=a||{};this.name=this._options.name||"unknown cubemapframebuffer";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.gl.getParameter(this._cgl.gl.MAX_SAMPLES),this._options.multisamplingSamples)}if(!this._options.hasOwnProperty("filter"))this._options.filter=CGL.Texture.FILTER_LINEAR;if(!this._options.hasOwnProperty("wrap"))this._options.wrap=CGL.Texture.WRAP_CLAMP_TO_EDGE;this._cgl.checkFrameStarted("cubemap framebuffer");let i=a.pixeFormat;if(!i&&a.isFloatingPointTexture)i=CGL.Texture.PFORMATSTR_RGBA32F;this.texture=new o(this._cgl,{width:this.width,height:this.height,pixelFormat:a.pixelFormat,filter:this._options.filter,wrap:this._options.wrap,name:this.name+" cubemaptexture"});this.initializeRenderbuffers();this.setSize(this.width,this.height)}initializeRenderbuffers(){this._framebuffer=this._cgl.gl.createFramebuffer();this._depthbuffer=this._cgl.gl.createRenderbuffer();this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER,this._framebuffer);this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER,this._depthbuffer);this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,this._cgl.gl.DEPTH_COMPONENT16,this.width,this.height);this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER,this._cgl.gl.DEPTH_ATTACHMENT,this._cgl.gl.RENDERBUFFER,this._depthbuffer);this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER,null);this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER,null)}getWidth(){return this.width}getHeight(){return this.height}getGlFrameBuffer(){return this._framebuffer}getDepthRenderBuffer(){return this._depthRenderbuffer}getTextureColor(){return this.texture}getTextureDepth(){return this._textureDepth}dispose(){if(this.texture)this.texture=this.texture.delete();if(this._framebuffer)this._cgl.gl.deleteFramebuffer(this._framebuffer);if(this._depthRenderbuffer)this._cgl.gl.deleteRenderbuffer(this._depthbuffer)}delete(){this.dispose()}setSize(e,t){this._cgl.printError("before cubemap setsize");this.width=Math.floor(e);this.height=Math.floor(t);this.width=Math.min(this.width,this._cgl.maxTexSize);this.height=Math.min(this.height,this._cgl.maxTexSize);this._cgl.profileData.profileFrameBuffercreate++;this._framebuffer=this._cgl.gl.createFramebuffer();this._depthbuffer=this._cgl.gl.createRenderbuffer();this.texture.setSize(this.width,this.height);this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER,this._framebuffer);this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER,this._depthbuffer);this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,this._cgl.gl.DEPTH_COMPONENT16,this.width,this.height);this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER,this._cgl.gl.DEPTH_ATTACHMENT,this._cgl.gl.RENDERBUFFER,this._depthbuffer);if(!this._cgl.gl.isFramebuffer(this._framebuffer)){console.error("invalid framebuffer...")}const n=this._cgl.gl.checkFramebufferStatus(this._cgl.gl.FRAMEBUFFER);this.checkErrorsByStatus(n);this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_CUBE_MAP,null);this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER,null);this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER,null);this._cgl.printError("cubemap setsize")}checkErrorsByStatus(e){switch(e){case this._cgl.gl.FRAMEBUFFER_COMPLETE:break;case this._cgl.gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:console.error("FRAMEBUFFER_INCOMPLETE_ATTACHMENT...",this.width,this.height,this.texture.tex,this._depthBuffer);throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_ATTACHMENT");case this._cgl.gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:console.error("FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");case this._cgl.gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:console.error("FRAMEBUFFER_INCOMPLETE_DIMENSIONS");throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS");case this._cgl.gl.FRAMEBUFFER_UNSUPPORTED:console.error("FRAMEBUFFER_UNSUPPORTED");throw new Error("Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED");case 36059:console.error("Incomplete: FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER from ext. Or Safari/iOS undefined behaviour.");break;default:console.error("incomplete framebuffer",e);console.log(this);throw new Error("Incomplete framebuffer: "+e)}}setFilter(e){this.texture.filter=e;this.texture.setSize(this.width,this.height)}setCamPos(e){this.camPos=e||this.camPos}setMatrices(e,t,n){this._modelMatrix=e||this._modelMatrix;this._viewMatrix=t||this._viewMatrix;this._projectionMatrix=n||this._projectionMatrix}renderStart(){this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_CUBE_MAP,this.texture.tex);this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER,this._framebuffer);this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER,this._depthbuffer);this._cgl.gl.viewport(0,0,this.width,this.height);this._cgl.pushGlFrameBuffer(this._framebuffer);this._cgl.pushFrameBuffer(this)}renderStartCubemapFace(e){this._cgl.pushModelMatrix();this._cgl.pushViewMatrix();this._cgl.pushPMatrix();this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER,this._cgl.gl.COLOR_ATTACHMENT0,this._cubemapProperties[e].face,this.texture.tex,0);this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER,this._cgl.gl.DEPTH_ATTACHMENT,this._cgl.gl.RENDERBUFFER,this._depthbuffer);if(this._options.clear){this._cgl.gl.clearColor(0,0,0,1);this._cgl.gl.clear(this._cgl.gl.COLOR_BUFFER_BIT|this._cgl.gl.DEPTH_BUFFER_BIT)}this.setMatricesCubemapFace(e)}setMatricesCubemapFace(e){mat4.copy(this._cgl.mMatrix,this._modelMatrix);vec3.add(this._lookAtTemp,this.camPos,this._cubemapProperties[e].lookAt);mat4.lookAt(this._cgl.vMatrix,this.camPos,this._lookAtTemp,this._cubemapProperties[e].up);mat4.copy(this._cgl.pMatrix,this._projectionMatrix)}renderEndCubemapFace(){this._cgl.popPMatrix();this._cgl.popModelMatrix();this._cgl.popViewMatrix()}renderEnd(){this._cgl.profileData.profileFramebuffer++;if(this._cgl.glVersion!==1){this._cgl.gl.bindFramebuffer(this._cgl.gl.READ_FRAMEBUFFER,this._framebuffer)}this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER,this._cgl.popGlFrameBuffer());this._cgl.popFrameBuffer();this._cgl.resetViewPort();this.updateMipMap()}updateMipMap(){if(!this.texture)return;this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_CUBE_MAP,this.texture.tex);this.texture.updateMipMap();this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_CUBE_MAP,null)}}CGL.CubemapFramebuffer=s;((this.CGL=this.CGL||{}).COREMODULES=this.CGL.COREMODULES||{}).Cubemapframebuffer=e.Cubemapframebuffer})();