diff --git a/.gitignore b/.gitignore index dd813fc..7be71c2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,6 @@ node_modules/ package-lock.json localhost* *.git -cypress/screenshots -cypress/videos /test-results/ /playwright-report/ /blob-report/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 54b421b..6140f7d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,10 @@ 120 ], "typescript.tsserver.experimental.enableProjectDiagnostics": true, - "js/ts.implicitProjectConfig.target": "ES2022", + "js/ts.implicitProjectConfig.target": "ESNext", "typescript.format.semicolons": "remove", + "javascript.preferences.importModuleSpecifier": "relative", + "javascript.preferences.importModuleSpecifierEnding": "js", + "javascript.updateImportsOnFileMove.enabled": "always", + "editor.formatOnSave": true, } diff --git a/dist/ueblueprint.js b/dist/ueblueprint.js index 7ff9855..0a05686 100755 --- a/dist/ueblueprint.js +++ b/dist/ueblueprint.js @@ -177,6 +177,7 @@ class Configuration { makeMap: "/Script/BlueprintGraph.K2Node_MakeMap", makeSet: "/Script/BlueprintGraph.K2Node_MakeSet", makeStruct: "/Script/BlueprintGraph.K2Node_MakeStruct", + materialExpressionComponentMask: "/Script/Engine.MaterialExpressionComponentMask", materialExpressionConstant: "/Script/Engine.MaterialExpressionConstant", materialExpressionConstant2Vector: "/Script/Engine.MaterialExpressionConstant2Vector", materialExpressionConstant3Vector: "/Script/Engine.MaterialExpressionConstant3Vector", @@ -352,6 +353,8 @@ class Configuration { "Alt", "Meta", ] + /** @type {["R", "G", "B", "A"]} */ + static rgba = ["R", "G", "B", "A"] static Keys = { /* UE name: JS name */ "Backspace": "Backspace", @@ -445,6 +448,677 @@ class Configuration { } } +class Shortcuts { + static deleteNodes = "Delete" + static duplicateNodes = "(bCtrl=True,Key=D)" + static enableLinkDelete = "LeftAlt" + static enableZoomIn = ["LeftControl", "RightControl"] // Button to enable more than 1:1 zoom + static selectAllNodes = "(bCtrl=True,Key=A)" +} + +class ComputedType { + + #f + + /** @param {Function} f */ + constructor(f) { + this.#f = f; + } + + /** @param {IEntity} entity */ + compute(entity) { + return this.#f(entity) + } +} + +/** + * @template T + * @typedef {{ + * type?: AttributeTypeDescription, + * default?: T, + * nullable?: Boolean, + * ignored?: Boolean, + * serialized?: Boolean, + * expected?: Boolean, + * inlined?: Boolean, + * quoted?: Boolean, + * silent?: Boolean, + * predicate?: (value: T) => Boolean, + * }} AttributeInfoSource + */ + +/** @template T */ +class AttributeInfo { + + /** @typedef {keyof AttributeInfo} AttributeKey */ + + static #default = { + nullable: false, + ignored: false, // Never serialize or deserialize + serialized: false, // Value is written and read as string + expected: false, // Must be there + inlined: false, // The key is a subobject or array and printed as inlined (A.B=123, A(0)=123) + quoted: false, // Key is serialized with quotes + silent: false, // Do not serialize if default + } + + /** @param {AttributeInfoSource} source */ + constructor(source) { + this.type = source.type ?? source.default?.constructor; + this.default = source.default; + this.nullable = source.nullable ?? source.default === null; + this.ignored = source.ignored; + this.serialized = source.serialized; + this.expected = source.expected; + this.inlined = source.inlined; + this.quoted = source.quoted; + this.silent = source.silent; + this.predicate = source.predicate; + if (this.type === Array && this.default instanceof Array && this.default.length > 0) { + this.type = this.default + .map(v => v.constructor) + .reduce((acc, cur) => acc.includes(cur) ? acc : (acc.push(cur), acc), []); + } + } + + /** + * @template {AttributeTypeDescription} D + * @param {D} type + * @returns {AttributeInfo>} + */ + static createType(type) { + return new AttributeInfo({ type }) + } + + /** + * @template V + * @param {V} value + */ + static createValue(value) { + return new AttributeInfo({ default: value }) + } + + /** + * @param {IEntity | Object} source + * @param {String} attribute + * @param {AttributeKey} key + */ + static hasAttribute(source, attribute, key, type = /** @type {EntityConstructor} */(source.constructor)) { + const entity = /** @type {IEntity} */(source); + const result = entity.attributes[attribute]?.[key]; + return /** @type {result} */( + result + ?? type?.attributes?.[attribute]?.[key] + ?? AttributeInfo.#default[key] + ) + } + + /** + * @template {IEntity | Object} S + * @template {EntityConstructor} C + * @template {keyof C["attributes"]} A + * @template {keyof C["attributes"][attribute]} K + * @param {S} source + * @param {A} attribute + * @param {K} key + * @param {C} type + * @returns {C["attributes"][attribute][key]} + */ + static getAttribute(source, attribute, key, type = /** @type {C} */(source.constructor)) { + let result = source["attributes"]?.[attribute]?.[key]; + // Remember null is a valid asignment value for some attributes + if (result !== undefined) { + return result + } + result = /** @type {C["attributes"]} */(type?.attributes)?.[attribute]?.[key]; + if (result !== undefined) { + return result + } + result = /** @type {C["attributes"][attribute]} */(AttributeInfo.#default)[key]; + if (result !== undefined) { + return result + } + } + + /** @param {AttributeKey} key */ + get(key) { + return this[key] ?? AttributeInfo.#default[key] + } +} + +/** @template {Attribute} T */ +class MirroredEntity { + + static attributes = { + type: new AttributeInfo({ + ignored: true, + }), + getter: new AttributeInfo({ + ignored: true, + }), + } + + /** + * @param {ConstructorType} type + * @param {() => T} getter + */ + constructor(type, getter = null) { + this.type = type; + this.getter = getter; + } + + get() { + return this.getter() + } + + /** @returns {AttributeConstructor} */ + getTargetType() { + const result = this.type; + if (result instanceof MirroredEntity) { + return result.getTargetType() + } + return result + } +} + +/** @template {any[]} T */ +class Union { + + /** @type {T} */ + #values + get values() { + return this.#values + } + + /** @param {T} values */ + constructor(...values) { + this.#values = values; + } +} + +class Utility { + + static booleanConverter = { + fromAttribute: (value, type) => { + }, + toAttribute: (value, type) => { + if (value === true) { + return "true" + } + if (value === false) { + return "false" + } + return "" + } + } + + /** @param {Number} x */ + static sigmoid(x, curvature = 1.7) { + return 1 / (1 + (x / (1 - x) ** -curvature)) + } + + /** @param {Number} x */ + static sigmoidPositive(x, curvature = 3.7, length = 1.1) { + return 1 - Math.exp(-((x / length) ** curvature)) + } + + /** @param {Number} value */ + static clamp(value, min = -Infinity, max = Infinity) { + return Math.min(Math.max(value, min), max) + } + + /** @param {HTMLElement} element */ + static getScale(element) { + // @ts-expect-error + const scale = element.blueprint?.getScale() ?? getComputedStyle(element).getPropertyValue("--ueb-scale"); + return scale != "" ? parseFloat(scale) : 1 + } + + /** + * @param {Number} num + * @param {Number} decimals + */ + static minDecimals(num, decimals = 1, epsilon = 1e-8) { + const powered = num * 10 ** decimals; + if (Math.abs(powered % 1) > epsilon) { + // More decimal digits than required + return num.toString() + } + return num.toFixed(decimals) + } + + /** @param {String} value */ + static numberFromText(value = "") { + value = value.toLowerCase(); + switch (value) { + case "zero": return 0 + case "one": return 1 + case "two": return 2 + case "three": return 3 + case "four": return 4 + case "five": return 5 + case "six": return 6 + case "seven": return 7 + case "eight": return 8 + case "nine": return 9 + } + } + + /** + * @param {Number} num + * @param {Number} decimals + */ + static roundDecimals(num, decimals = 1) { + const power = 10 ** decimals; + return Math.round(num * power) / power + } + + /** @param {Number} num */ + static printNumber(num) { + if (num == Number.POSITIVE_INFINITY) { + return "inf" + } else if (num == Number.NEGATIVE_INFINITY) { + return "-inf" + } + return Utility.minDecimals(num) + } + + /** @param {Number} num */ + static printExponential(num) { + if (num == Number.POSITIVE_INFINITY) { + return "inf" + } else if (num == Number.NEGATIVE_INFINITY) { + return "-inf" + } + const int = Math.round(num); + if (int >= 1000) { + const exp = Math.floor(Math.log10(int)); + const dec = Math.round(num / 10 ** (exp - 2)) / 100; + // Not using num.toExponential() because of the omitted leading 0 on the exponential + return `${dec}e+${exp < 10 ? "0" : ""}${exp}` + } + const intPart = Math.floor(num); + if (intPart == 0) { + return num.toString() + } + return this.roundDecimals(num, Math.max(0, 3 - Math.floor(num).toString().length)).toString() + } + + /** + * @param {Number} a + * @param {Number} b + */ + static approximatelyEqual(a, b, epsilon = 1e-8) { + return !(Math.abs(a - b) > epsilon) + } + + /** + * @param {Coordinates} viewportLocation + * @param {HTMLElement} movementElement + */ + static convertLocation(viewportLocation, movementElement, ignoreScale = false) { + const scaleCorrection = ignoreScale ? 1 : 1 / Utility.getScale(movementElement); + const bounding = movementElement.getBoundingClientRect(); + const location = /** @type {Coordinates} */([ + Math.round((viewportLocation[0] - bounding.x) * scaleCorrection), + Math.round((viewportLocation[1] - bounding.y) * scaleCorrection) + ]); + return location + } + + /** + * @param {Attribute} entity + * @param {String} key + * @returns {Boolean} + */ + static isSerialized(entity, key) { + return entity["attributes"]?.[key]?.serialized + ?? entity.constructor["attributes"]?.[key]?.serialized + ?? false + } + + /** @param {String[]} keys */ + static objectGet(target, keys, defaultValue = undefined) { + if (target === undefined) { + return undefined + } + if (!(keys instanceof Array)) { + throw new TypeError("UEBlueprint: Expected keys to be an array") + } + if (keys.length == 0 || !(keys[0] in target) || target[keys[0]] === undefined) { + return defaultValue + } + if (keys.length == 1) { + return target[keys[0]] + } + return Utility.objectGet(target[keys[0]], keys.slice(1), defaultValue) + } + + /** + * @param {String[]} keys + * @returns {Boolean} + */ + static objectSet(target, keys, value, defaultDictType = Object) { + if (!(keys instanceof Array)) { + throw new TypeError("Expected keys to be an array.") + } + if (keys.length == 1) { + if (keys[0] in target || target[keys[0]] === undefined) { + target[keys[0]] = value; + return true + } + } else if (keys.length > 0) { + if (!(target[keys[0]] instanceof Object)) { + target[keys[0]] = new defaultDictType(); + } + return Utility.objectSet(target[keys[0]], keys.slice(1), value, defaultDictType) + } + return false + } + + /** + * @param {Attribute} a + * @param {Attribute} b + */ + static equals(a, b) { + while (a instanceof MirroredEntity) { + a = a.get(); + } + while (b instanceof MirroredEntity) { + b = b.get(); + } + // Here we cannot check both instanceof IEntity because this would introduce a circular include dependency + if (/** @type {IEntity?} */(a)?.equals && /** @type {IEntity?} */(b)?.equals) { + return /** @type {IEntity} */(a).equals(/** @type {IEntity} */(b)) + } + a = Utility.sanitize(a); + b = Utility.sanitize(b); + if (a?.constructor === BigInt && b?.constructor === Number) { + b = BigInt(b); + } else if (a?.constructor === Number && b?.constructor === BigInt) { + a = BigInt(a); + } + if (a === b) { + return true + } + if (a instanceof Array && b instanceof Array) { + return a.length === b.length && a.every((value, i) => Utility.equals(value, b[i])) + } + return false + } + + /** + * @template {Attribute | AttributeTypeDescription} T + * @param {T} value + * @returns {AttributeConstructor} + */ + static getType(value) { + if (value === null) { + return null + } + if (value?.constructor === Object && /** @type {AttributeInformation} */(value)?.type instanceof Function) { + return /** @type {AttributeInformation} */(value).type + } + return /** @type {AttributeConstructor} */(value?.constructor) + } + + /** + * @template {Attribute} V + * @template {AttributeConstructor} C + * @param {C} type + * @returns {value is InstanceType} + */ + static isValueOfType(value, type, acceptNull = false) { + if (type instanceof MirroredEntity) { + type = type.getTargetType(); + } + return (acceptNull && value === null) || value instanceof type || value?.constructor === type + } + + /** @param {Attribute} value */ + static sanitize(value, targetType = /** @type {AttributeTypeDescription } */(value?.constructor)) { + if (targetType instanceof Array) { + targetType = targetType[0]; + } + if (targetType instanceof ComputedType) { + return value // The type is computed, can't say anything about it + } + if (targetType instanceof Union) { + let type = targetType.values.find(t => Utility.isValueOfType(value, t, false)); + if (!type) { + type = targetType.values[0]; + } + targetType = type; + } + if (targetType instanceof MirroredEntity) { + if (value instanceof MirroredEntity) { + return value + } + return Utility.sanitize(value, targetType.getTargetType()) + } + if (targetType && !Utility.isValueOfType(value, targetType, true)) { + value = targetType === BigInt + ? BigInt(/** @type {Number} */(value)) + : new /** @type {EntityConstructor} */(targetType)(value); + } + if (value instanceof Boolean || value instanceof Number || value instanceof String) { + value = /** @type {TerminalAttribute} */(value.valueOf()); // Get the relative primitive value + } + return value + } + + /** + * @param {Number} x + * @param {Number} y + * @param {Number} gridSize + * @returns {Coordinates} + */ + static snapToGrid(x, y, gridSize) { + if (gridSize === 1) { + return [x, y] + } + return [ + gridSize * Math.floor(x / gridSize), + gridSize * Math.floor(y / gridSize) + ] + } + + /** + * @template T + * @param {Array} a + * @param {Array} b + */ + static mergeArrays(a = [], b = []) { + let result = []; + a = [...a]; + b = [...b]; + restart: + while (true) { + for (let j = 0; j < b.length; ++j) { + for (let i = 0; i < a.length; ++i) { + if (a[i] == b[j]) { + // Found an element in common in the two arrays + result.push( + // Take and append all the elements skipped from a + ...a.splice(0, i), + // Take and append all the elements skippend from b + ...b.splice(0, j), + // Take and append the element in common + ...a.splice(0, 1) + ); + b.shift(); // Remove the same element from b + continue restart + } + } + } + break restart + } + // Append remaining the elements in the arrays and make it unique + return [...(new Set(result.concat(...a, ...b)))] + } + + /** @param {String} value */ + static escapeString(value) { + return value + .replaceAll(new RegExp(`(${Configuration.stringEscapedCharacters.source})`, "g"), '\\$1') + .replaceAll("\n", "\\n") // Replace newline with \n + .replaceAll("\t", "\\t") // Replace tab with \t + } + + /** @param {String} value */ + static unescapeString(value) { + return value + .replaceAll(new RegExp(Configuration.unescapedBackslash.source + "t", "g"), "\t") // Replace tab with \t + .replaceAll(new RegExp(Configuration.unescapedBackslash.source + "n", "g"), "\n") // Replace newline with \n + .replaceAll(new RegExp(`\\\\(${Configuration.stringEscapedCharacters.source})`, "g"), "$1") + } + + /** @param {String} value */ + static clearHTMLWhitespace(value) { + return value + .replaceAll(" ", "\u00A0") // whitespace + .replaceAll(/|
/g, "\n") // newlines + .replaceAll(/(\)/g, "") // html comments + } + + /** @param {String} value */ + static encodeHTMLWhitespace(value) { + return value.replaceAll(" ", "\u00A0") + } + + /** @param {String} value */ + static capitalFirstLetter(value) { + if (value.length === 0) { + return value + } + return value.charAt(0).toUpperCase() + value.slice(1) + } + + /** @param {String} value */ + static formatStringName(value = "") { + return value + // Remove leading b (for boolean values) or newlines + .replace(/^\s*b(?=[A-Z])/, "") + // Insert a space where needed, possibly removing unnecessary elading characters + .replaceAll(Configuration.nameRegexSpaceReplacement, " ") + .trim() + .split(" ") + .map(v => Utility.capitalFirstLetter(v)) + .join(" ") + } + + /** @param {String} value */ + static getIdFromReference(value) { + return value + .replace(/(?:.+\.)?([^\.]+)$/, "$1") + .replaceAll(/(?<=[a-z\d])(?=[A-Z])|(?<=[a-zA-Z])(?=\d)|(?<=[A-Z]{2})(?=[A-Z][a-z])/g, "-") + .toLowerCase() + } + + /** @param {String} pathValue */ + static getNameFromPath(pathValue) { + return pathValue.match(/[^\.\/]+$/)?.[0] ?? "" + } + + /** @param {LinearColorEntity} value */ + static printLinearColor(value) { + return `${Math.round(value.R.valueOf() * 255)}, ${Math.round(value.G.valueOf() * 255)}, ${Math.round(value.B.valueOf() * 255)}` + } + + /** + * @param {Number} x + * @param {Number} y + * @returns {Coordinates} + */ + static getPolarCoordinates(x, y, positiveTheta = false) { + let theta = Math.atan2(y, x); + if (positiveTheta && theta < 0) { + theta = 2 * Math.PI + theta; + } + return [ + Math.sqrt(x * x + y * y), + theta, + ] + } + + /** + * @param {Number} r + * @param {Number} theta + * @returns {Coordinates} + */ + static getCartesianCoordinates(r, theta) { + return [ + r * Math.cos(theta), + r * Math.sin(theta) + ] + } + + /** + * @param {Number} begin + * @param {Number} end + */ + static range(begin = 0, end = 0, step = end >= begin ? 1 : -1) { + return Array.from({ length: Math.ceil((end - begin) / step) }, (_, i) => begin + (i * step)) + } + + /** @param {String[]} words */ + static getFirstWordOrder(words) { + return new RegExp(/\s*/.source + words.join(/[^\n]+\n\s*/.source) + /\s*/.source) + } + + /** + * @param {HTMLElement} element + * @param {String} value + */ + static paste(element, value) { + const event = new ClipboardEvent("paste", { + bubbles: true, + cancelable: true, + clipboardData: new DataTransfer(), + }); + event.clipboardData.setData("text", value); + element.dispatchEvent(event); + } + + /** @param {Blueprint} blueprint */ + static async copy(blueprint) { + const event = new ClipboardEvent("copy", { + bubbles: true, + cancelable: true, + clipboardData: new DataTransfer(), + }); + blueprint.dispatchEvent(event); + } + + static animate( + from, + to, + intervalSeconds, + callback, + acknowledgeRequestAnimationId = id => { }, + timingFunction = x => { + const v = x ** 3.5; + return v / (v + ((1 - x) ** 3.5)) + } + ) { + let startTimestamp; + const doAnimation = currentTimestamp => { + if (startTimestamp === undefined) { + startTimestamp = currentTimestamp; + } + let delta = (currentTimestamp - startTimestamp) / intervalSeconds; + if (Utility.approximatelyEqual(delta, 1) || delta > 1) { + delta = 1; + } else { + acknowledgeRequestAnimationId(requestAnimationFrame(doAnimation)); + } + const currentValue = from + (to - from) * timingFunction(delta); + callback(currentValue); + }; + acknowledgeRequestAnimationId(requestAnimationFrame(doAnimation)); + } +} + /** * @typedef {{ * consumeEvent?: Boolean, @@ -522,56 +1196,6 @@ class IInput { } } -class ComputedType { - - #f - - /** @param {Function} f */ - constructor(f) { - this.#f = f; - } - - /** @param {IEntity} entity */ - compute(entity) { - return this.#f(entity) - } -} - -/** @template {Attribute} T */ -class MirroredEntity { - - static attributes = { - type: { - ignored: true, - }, - getter: { - ignored: true, - }, - } - - /** - * @param {ConstructorType} type - * @param {() => T} getter - */ - constructor(type, getter = null) { - this.type = type; - this.getter = getter; - } - - get() { - return this.getter() - } - - /** @returns {AttributeConstructor} */ - getTargetType() { - const result = this.type; - if (result instanceof MirroredEntity) { - return result.getTargetType() - } - return result - } -} - class Reply { /** @@ -1765,2610 +2389,6 @@ class Parsernostrum { } } -class Serializable { - - static grammar = this.createGrammar() - - /** @protected */ - static createGrammar() { - return /** @type {Parsernostrum} */(Parsernostrum.failure()) - } -} - -class SerializerFactory { - - static #serializers = new Map() - - /** - * @template {AttributeConstructor} T - * @param {T} type - * @param {Serializer} object - */ - static registerSerializer(type, object) { - SerializerFactory.#serializers.set(type, object); - } - - /** - * @template {AttributeConstructor} T - * @param {T} type - * @returns {Serializer} - */ - static getSerializer(type) { - return SerializerFactory.#serializers.get(type) - } -} - -/** - * @template {[...U]} T - * @template {any[]} U - */ -class Union { - - /** @type {T} */ - #values - get values() { - return this.#values - } - - /** @param {T} values */ - constructor(...values) { - this.#values = values; - } -} - -class Utility { - - static booleanConverter = { - fromAttribute: (value, type) => { - }, - toAttribute: (value, type) => { - if (value === true) { - return "true" - } - if (value === false) { - return "false" - } - return "" - } - } - - /** @param {Number} x */ - static sigmoid(x, curvature = 1.7) { - return 1 / (1 + (x / (1 - x) ** -curvature)) - } - - /** @param {Number} x */ - static sigmoidPositive(x, curvature = 3.7, length = 1.1) { - return 1 - Math.exp(-((x / length) ** curvature)) - } - - /** @param {Number} value */ - static clamp(value, min = -Infinity, max = Infinity) { - return Math.min(Math.max(value, min), max) - } - - /** @param {HTMLElement} element */ - static getScale(element) { - // @ts-expect-error - const scale = element.blueprint?.getScale() ?? getComputedStyle(element).getPropertyValue("--ueb-scale"); - return scale != "" ? parseFloat(scale) : 1 - } - - /** - * @param {Number} num - * @param {Number} decimals - */ - static minDecimals(num, decimals = 1, epsilon = 1e-8) { - const powered = num * 10 ** decimals; - if (Math.abs(powered % 1) > epsilon) { - // More decimal digits than required - return num.toString() - } - return num.toFixed(decimals) - } - - /** @param {String} value */ - static numberFromText(value = "") { - value = value.toLowerCase(); - switch (value) { - case "zero": return 0 - case "one": return 1 - case "two": return 2 - case "three": return 3 - case "four": return 4 - case "five": return 5 - case "six": return 6 - case "seven": return 7 - case "eight": return 8 - case "nine": return 9 - } - } - - /** - * @param {Number} num - * @param {Number} decimals - */ - static roundDecimals(num, decimals = 1) { - const power = 10 ** decimals; - return Math.round(num * power) / power - } - - /** @param {Number} num */ - static printNumber(num) { - if (num == Number.POSITIVE_INFINITY) { - return "inf" - } else if (num == Number.NEGATIVE_INFINITY) { - return "-inf" - } - return Utility.minDecimals(num) - } - - /** @param {Number} num */ - static printExponential(num) { - if (num == Number.POSITIVE_INFINITY) { - return "inf" - } else if (num == Number.NEGATIVE_INFINITY) { - return "-inf" - } - const int = Math.round(num); - if (int >= 1000) { - const exp = Math.floor(Math.log10(int)); - const dec = Math.round(num / 10 ** (exp - 2)) / 100; - // Not using num.toExponential() because of the omitted leading 0 on the exponential - return `${dec}e+${exp < 10 ? "0" : ""}${exp}` - } - const intPart = Math.floor(num); - if (intPart == 0) { - return num.toString() - } - return this.roundDecimals(num, Math.max(0, 3 - Math.floor(num).toString().length)).toString() - } - - /** - * @param {Number} a - * @param {Number} b - */ - static approximatelyEqual(a, b, epsilon = 1e-8) { - return !(Math.abs(a - b) > epsilon) - } - - /** - * @param {Coordinates} viewportLocation - * @param {HTMLElement} movementElement - */ - static convertLocation(viewportLocation, movementElement, ignoreScale = false) { - const scaleCorrection = ignoreScale ? 1 : 1 / Utility.getScale(movementElement); - const bounding = movementElement.getBoundingClientRect(); - const location = /** @type {Coordinates} */([ - Math.round((viewportLocation[0] - bounding.x) * scaleCorrection), - Math.round((viewportLocation[1] - bounding.y) * scaleCorrection) - ]); - return location - } - - /** - * @param {Attribute} entity - * @param {String} key - * @returns {Boolean} - */ - static isSerialized(entity, key) { - return entity["attributes"]?.[key]?.serialized - ?? entity.constructor["attributes"]?.[key]?.serialized - ?? false - } - - /** @param {String[]} keys */ - static objectGet(target, keys, defaultValue = undefined) { - if (target === undefined) { - return undefined - } - if (!(keys instanceof Array)) { - throw new TypeError("UEBlueprint: Expected keys to be an array") - } - if (keys.length == 0 || !(keys[0] in target) || target[keys[0]] === undefined) { - return defaultValue - } - if (keys.length == 1) { - return target[keys[0]] - } - return Utility.objectGet(target[keys[0]], keys.slice(1), defaultValue) - } - - /** - * @param {String[]} keys - * @returns {Boolean} - */ - static objectSet(target, keys, value, defaultDictType = Object) { - if (!(keys instanceof Array)) { - throw new TypeError("Expected keys to be an array.") - } - if (keys.length == 1) { - if (keys[0] in target || target[keys[0]] === undefined) { - target[keys[0]] = value; - return true - } - } else if (keys.length > 0) { - if (!(target[keys[0]] instanceof Object)) { - target[keys[0]] = new defaultDictType(); - } - return Utility.objectSet(target[keys[0]], keys.slice(1), value, defaultDictType) - } - return false - } - - /** - * @param {Attribute} a - * @param {Attribute} b - */ - static equals(a, b) { - // Here we cannot check both instanceof IEntity because this would introduce a circular include dependency - if (/** @type {IEntity?} */(a)?.equals && /** @type {IEntity?} */(b)?.equals) { - return /** @type {IEntity} */(a).equals(/** @type {IEntity} */(b)) - } - a = Utility.sanitize(a); - b = Utility.sanitize(b); - if (a?.constructor === BigInt && b?.constructor === Number) { - b = BigInt(b); - } else if (a?.constructor === Number && b?.constructor === BigInt) { - a = BigInt(a); - } - if (a === b) { - return true - } - if (a instanceof Array && b instanceof Array) { - return a.length === b.length && a.every((value, i) => Utility.equals(value, b[i])) - } - return false - } - - /** - * @template {Attribute | AttributeTypeDescription} T - * @param {T} value - * @returns {AttributeConstructor} - */ - static getType(value) { - if (value === null) { - return null - } - if (value?.constructor === Object && /** @type {AttributeInformation} */(value)?.type instanceof Function) { - return /** @type {AttributeInformation} */(value).type - } - return /** @type {AttributeConstructor} */(value?.constructor) - } - - /** - * @template {Attribute} V - * @template {AttributeConstructor} C - * @param {C} type - * @returns {value is InstanceType} - */ - static isValueOfType(value, type, acceptNull = false) { - if (type instanceof MirroredEntity) { - type = type.getTargetType(); - } - return (acceptNull && value === null) || value instanceof type || value?.constructor === type - } - - /** @param {Attribute} value */ - static sanitize(value, targetType = /** @type {AttributeTypeDescription } */(value?.constructor)) { - if (targetType instanceof Array) { - targetType = targetType[0]; - } - if (targetType instanceof ComputedType) { - return value // The type is computed, can't say anything about it - } - if (targetType instanceof Union) { - let type = targetType.values.find(t => Utility.isValueOfType(value, t, false)); - if (!type) { - type = targetType.values[0]; - } - targetType = type; - } - if (targetType instanceof MirroredEntity) { - if (value instanceof MirroredEntity) { - return value - } - return Utility.sanitize(value, targetType.getTargetType()) - } - if (targetType && !Utility.isValueOfType(value, targetType, true)) { - value = targetType === BigInt - ? BigInt(/** @type {Number} */(value)) - : new /** @type {EntityConstructor} */(targetType)(value); - } - if (value instanceof Boolean || value instanceof Number || value instanceof String) { - value = /** @type {TerminalAttribute} */(value.valueOf()); // Get the relative primitive value - } - return value - } - - /** - * @param {Number} x - * @param {Number} y - * @param {Number} gridSize - * @returns {Coordinates} - */ - static snapToGrid(x, y, gridSize) { - if (gridSize === 1) { - return [x, y] - } - return [ - gridSize * Math.floor(x / gridSize), - gridSize * Math.floor(y / gridSize) - ] - } - - /** - * @template T - * @param {Array} a - * @param {Array} b - */ - static mergeArrays(a = [], b = []) { - let result = []; - a = [...a]; - b = [...b]; - restart: - while (true) { - for (let j = 0; j < b.length; ++j) { - for (let i = 0; i < a.length; ++i) { - if (a[i] == b[j]) { - // Found an element in common in the two arrays - result.push( - // Take and append all the elements skipped from a - ...a.splice(0, i), - // Take and append all the elements skippend from b - ...b.splice(0, j), - // Take and append the element in common - ...a.splice(0, 1) - ); - b.shift(); // Remove the same element from b - continue restart - } - } - } - break restart - } - // Append remaining the elements in the arrays and make it unique - return [...(new Set(result.concat(...a, ...b)))] - } - - /** @param {String} value */ - static escapeString(value) { - return value - .replaceAll(new RegExp(`(${Configuration.stringEscapedCharacters.source})`, "g"), '\\$1') - .replaceAll("\n", "\\n") // Replace newline with \n - .replaceAll("\t", "\\t") // Replace tab with \t - } - - /** @param {String} value */ - static unescapeString(value) { - return value - .replaceAll(new RegExp(Configuration.unescapedBackslash.source + "t", "g"), "\t") // Replace tab with \t - .replaceAll(new RegExp(Configuration.unescapedBackslash.source + "n", "g"), "\n") // Replace newline with \n - .replaceAll(new RegExp(`\\\\(${Configuration.stringEscapedCharacters.source})`, "g"), "$1") - } - - /** @param {String} value */ - static clearHTMLWhitespace(value) { - return value - .replaceAll(" ", "\u00A0") // whitespace - .replaceAll(/|
/g, "\n") // newlines - .replaceAll(/(\)/g, "") // html comments - } - - /** @param {String} value */ - static encodeHTMLWhitespace(value) { - return value.replaceAll(" ", "\u00A0") - } - - /** @param {String} value */ - static capitalFirstLetter(value) { - if (value.length === 0) { - return value - } - return value.charAt(0).toUpperCase() + value.slice(1) - } - - /** @param {String} value */ - static formatStringName(value = "") { - return value - // Remove leading b (for boolean values) or newlines - .replace(/^\s*b(?=[A-Z])/, "") - // Insert a space where needed, possibly removing unnecessary elading characters - .replaceAll(Configuration.nameRegexSpaceReplacement, " ") - .trim() - .split(" ") - .map(v => Utility.capitalFirstLetter(v)) - .join(" ") - } - - /** @param {String} value */ - static getIdFromReference(value) { - return value - .replace(/(?:.+\.)?([^\.]+)$/, "$1") - .replaceAll(/(?<=[a-z\d])(?=[A-Z])|(?<=[a-zA-Z])(?=\d)|(?<=[A-Z]{2})(?=[A-Z][a-z])/g, "-") - .toLowerCase() - } - - /** @param {String} pathValue */ - static getNameFromPath(pathValue) { - return pathValue.match(/[^\.\/]+$/)?.[0] ?? "" - } - - /** @param {LinearColorEntity} value */ - static printLinearColor(value) { - return `${Math.round(value.R.valueOf() * 255)}, ${Math.round(value.G.valueOf() * 255)}, ${Math.round(value.B.valueOf() * 255)}` - } - - /** - * @param {Number} x - * @param {Number} y - * @returns {Coordinates} - */ - static getPolarCoordinates(x, y, positiveTheta = false) { - let theta = Math.atan2(y, x); - if (positiveTheta && theta < 0) { - theta = 2 * Math.PI + theta; - } - return [ - Math.sqrt(x * x + y * y), - theta, - ] - } - - /** - * @param {Number} r - * @param {Number} theta - * @returns {Coordinates} - */ - static getCartesianCoordinates(r, theta) { - return [ - r * Math.cos(theta), - r * Math.sin(theta) - ] - } - - /** - * @param {Number} begin - * @param {Number} end - */ - static range(begin = 0, end = 0, step = end >= begin ? 1 : -1) { - return Array.from({ length: Math.ceil((end - begin) / step) }, (_, i) => begin + (i * step)) - } - - /** - * @param {HTMLElement} element - * @param {String} value - */ - static paste(element, value) { - const event = new ClipboardEvent("paste", { - bubbles: true, - cancelable: true, - clipboardData: new DataTransfer(), - }); - event.clipboardData.setData("text", value); - element.dispatchEvent(event); - } - - /** @param {Blueprint} blueprint */ - static async copy(blueprint) { - const event = new ClipboardEvent("copy", { - bubbles: true, - cancelable: true, - clipboardData: new DataTransfer(), - }); - blueprint.dispatchEvent(event); - } - - static animate( - from, - to, - intervalSeconds, - callback, - acknowledgeRequestAnimationId = id => { }, - timingFunction = x => { - const v = x ** 3.5; - return v / (v + ((1 - x) ** 3.5)) - } - ) { - let startTimestamp; - const doAnimation = currentTimestamp => { - if (startTimestamp === undefined) { - startTimestamp = currentTimestamp; - } - let delta = (currentTimestamp - startTimestamp) / intervalSeconds; - if (Utility.approximatelyEqual(delta, 1) || delta > 1) { - delta = 1; - } else { - acknowledgeRequestAnimationId(requestAnimationFrame(doAnimation)); - } - const currentValue = from + (to - from) * timingFunction(delta); - callback(currentValue); - }; - acknowledgeRequestAnimationId(requestAnimationFrame(doAnimation)); - } -} - -/** @abstract */ -class IEntity extends Serializable { - - /** @type {String | Union} */ - static lookbehind = "" - /** @type {AttributeDeclarations} */ - static attributes = { - lookbehind: { - ignored: true, - } - } - static defaultAttribute = { - nullable: false, - ignored: false, - serialized: false, // Value is written and read as string - expected: false, // Must be there - inlined: false, // The key is a subobject or array and printed as inlined (A.B=123, A(0)=123) - quoted: false, // Key is serialized with quotes - } - - constructor(values = {}, suppressWarns = false) { - super(); - /** @type {String} */ this.lookbehind; - const Self = /** @type {typeof IEntity} */(this.constructor); - let attributes = Self.attributes; - if (values.attributes) { - attributes = { ...Self.attributes }; - Utility.mergeArrays(Object.keys(values.attributes), Object.keys(attributes)) - .forEach(k => { - attributes[k] = { - ...IEntity.defaultAttribute, - ...attributes[k], - ...values.attributes[k], - }; - if (!attributes[k].type) { - attributes[k].type = values[k] instanceof Array - ? [Utility.getType(values[k][0])] - : Utility.getType(values[k]); - } - }); - IEntity.defineAttributes(this, attributes); - } - /** @type {AttributeDeclarations?} */ this.attributes; - const valuesNames = Object.keys(values); - const attributesNames = Object.keys(attributes); - const allAttributesNames = Utility.mergeArrays(valuesNames, attributesNames); - if (valuesNames.includes("lookbehind")) { - this.lookbehind = undefined; // To keep it first - } - for (const attributeName of allAttributesNames) { - if (attributeName == "attributes") { - // Ignore this special attribute describing all the attributes - continue - } - let value = values[attributeName]; - let attribute = attributes[attributeName]; - - if (!suppressWarns && value !== undefined) { - if ( - !(attributeName in attributes) - && !attributeName.startsWith(Configuration.subObjectAttributeNamePrefix) - ) { - const typeName = value instanceof Array ? `[${value[0]?.constructor.name}]` : value.constructor.name; - console.warn( - `UEBlueprint: Attribute ${attributeName} (of type ${typeName}) in the serialized data is not ` - + `defined in ${Self.name}.attributes` - ); - } - } - - if (!attribute) { - // Remember attributeName can come from the values and be not defined in the attributes. - // In that case just assign it and skip the rest. - this[attributeName] = value; - continue - } - - const assignAttribute = !attribute.predicate - ? v => this[attributeName] = v - : v => { - Object.defineProperties(this, { - ["#" + attributeName]: { - writable: true, - enumerable: false, - }, - [attributeName]: { - enumerable: true, - get() { - return this["#" + attributeName] - }, - set(v) { - if (!attribute.predicate?.(v)) { - console.warn( - `UEBlueprint: Tried to assign attribute ${attributeName} to ${Self.name} not ` - + "satisfying the predicate" - ); - return - } - this["#" + attributeName] = v; - } - }, - }); - this[attributeName] = v; - }; - - let defaultValue = attribute.default; - if (defaultValue instanceof Function) { - defaultValue = defaultValue(this); - } - let defaultType = attribute.type; - if (defaultType instanceof ComputedType) { - defaultType = defaultType.compute(this); - } - if (defaultType instanceof Array) { - defaultType = Array; - } - if (defaultType === undefined) { - defaultType = Utility.getType(defaultValue); - } - - if (value !== undefined) { - // Remember value can still be null - if (value?.constructor === String && attribute.serialized && defaultType !== String) { - value = SerializerFactory - // @ts-expect-error - .getSerializer(defaultType) - .read(/** @type {String} */(value)); - } - assignAttribute(Utility.sanitize(value, /** @type {AttributeConstructor} */(defaultType))); - continue // We have a value, need nothing more - } - if (Object.hasOwn(attribute, "default")) { // Accept also explicit undefined - assignAttribute(defaultValue); - } - } - } - - /** @param {AttributeTypeDescription} attributeType */ - static defaultValueProviderFromType(attributeType) { - if (attributeType === Boolean) { - return false - } else if (attributeType === Number) { - return 0 - } else if (attributeType === BigInt) { - return 0n - } else if (attributeType === String) { - return "" - } else if (attributeType === Array || attributeType instanceof Array) { - return () => [] - } else if (attributeType instanceof Union) { - return this.defaultValueProviderFromType(attributeType.values[0]) - } else if (attributeType instanceof MirroredEntity) { - return () => new MirroredEntity(attributeType.type, attributeType.getter) - } else if (attributeType instanceof ComputedType) { - return undefined - } else { - return () => new /** @type {AnyConstructor} */(attributeType)() - } - } - - /** @param {AttributeDeclarations} attributes */ - static cleanupAttributes(attributes, prefix = "") { - for (const attributeName in attributes) { - attributes[attributeName] = { - ...IEntity.defaultAttribute, - ...attributes[attributeName], - }; - const attribute = /** @type {AttributeInformation} */(attributes[attributeName]); - if (attribute.type === undefined && !(attribute.default instanceof Function)) { - attribute.type = attribute.default instanceof Array - ? [Utility.getType(attribute.default[0])] - : Utility.getType(attribute.default); - } - if (!attribute.ignored && attribute.default === undefined && attribute.type === undefined) { - throw new Error( - `UEBlueprint: Expected either "type" or "value" property in ${this.name} attribute ${prefix}` - + attributeName - ) - } - if (attribute.default === null) { - attribute.nullable = true; - } - } - } - - /** - * @template {new (...args: any) => any} C - * @param {C} type - * @returns {value is InstanceType} - */ - static isValueOfType(value, type) { - return value != null && (value instanceof type || value.constructor === type) - } - - static expectsAllKeys() { - return !Object.values(this.attributes) - .filter(/** @param {AttributeInformation} attribute */attribute => !attribute.ignored) - .some(/** @param {AttributeInformation} attribute */attribute => !attribute.expected) - } - - static getAttribute(object, attribute) { - return this.getAttributes(object)[attribute] - } - - /** @returns {AttributeDeclarations} */ - static getAttributes(object) { - return object.attributes ?? object.constructor?.attributes ?? {} - } - - static defineAttributes(object, attributes) { - Object.defineProperty(object, "attributes", { - writable: true, - configurable: false, - }); - object.attributes = attributes; - } - - getLookbehind() { - let lookbehind = this.lookbehind ?? /** @type {EntityConstructor} */(this.constructor).lookbehind; - lookbehind = lookbehind instanceof Union ? lookbehind.values[0] : lookbehind; - return lookbehind - } - - unexpectedKeys() { - return Object.keys(this).length - Object.keys(/** @type {typeof IEntity} */(this.constructor).attributes).length - } - - /** @param {IEntity} other */ - equals(other) { - const thisKeys = Object.keys(this); - const otherKeys = Object.keys(other); - if (thisKeys.length != otherKeys.length) { - return false - } - for (const key of thisKeys) { - if (this[key] instanceof IEntity && !this[key].equals(other[key])) { - return false - } else if (!Utility.equals(this[key], other[key])) { - return false - } - } - return true - } -} - -class Grammar { - - static separatedBy = (source, separator, min = 1) => - new RegExp( - source + "(?:" + separator + source + ")" - + (min === 1 ? "*" : min === 2 ? "+" : `{${min},}`) - ) - - static Regex = class { - static HexDigit = /[0-9a-fA-F]/ - static InsideString = /(?:[^"\\]|\\.)*/ - static InsideSingleQuotedString = /(?:[^'\\]|\\.)*/ - static Integer = /[\-\+]?\d+(?!\d|\.)/ - static Number = /[-\+]?(?:\d*\.)?\d+(?!\d|\.)/ - static RealUnit = /\+?(?:0(?:\.\d+)?|1(?:\.0+)?)(?![\.\d])/ // A number between 0 and 1 included - static Word = Grammar.separatedBy("[a-zA-Z]", "_") - static Symbol = /[a-zA-Z_]\w*/ - static DotSeparatedSymbols = Grammar.separatedBy(this.Symbol.source, "\\.") - static PathFragment = Grammar.separatedBy(this.Symbol.source, "[\\.:]") - static PathSpaceFragment = Grammar.separatedBy(this.Symbol.source, "[\\.:\\ ]") - static Path = new RegExp(`(?:\\/${this.PathFragment.source}){2,}`) // Multiple (2+) /PathFragment - } - - /* --- Primitive --- */ - - static null = Parsernostrum.reg(/\(\s*\)/).map(() => null) - static true = Parsernostrum.reg(/true/i).map(() => true) - static false = Parsernostrum.reg(/false/i).map(() => false) - static boolean = Parsernostrum.regArray(/(true)|false/i).map(v => v[1] ? true : false) - static number = Parsernostrum.regArray( - new RegExp(`(${Parsernostrum.number.getParser().parser.regexp.source})|(\\+?inf)|(-inf)`) - ).map(([_0, n, plusInf, minusInf]) => n ? Number(n) : plusInf ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY) - static bigInt = Parsernostrum.reg(new RegExp(Parsernostrum.number.getParser().parser.regexp.source)).map(BigInt) - .map(result => - result[2] !== undefined - ? Number.POSITIVE_INFINITY - : result[3] !== undefined - ? Number.NEGATIVE_INFINITY - : Number(result[1]) - ) - static naturalNumber = Parsernostrum.lazy(() => Parsernostrum.reg(/\d+/).map(Number)) - static string = Parsernostrum.doubleQuotedString.map(insideString => Utility.unescapeString(insideString)) - - /* --- Fragment --- */ - - static colorValue = Parsernostrum.numberByte - static word = Parsernostrum.reg(Grammar.Regex.Word) - static symbol = Parsernostrum.reg(Grammar.Regex.Symbol) - static symbolQuoted = Parsernostrum.reg(new RegExp('"(' + Grammar.Regex.Symbol.source + ')"'), 1) - static attributeName = Parsernostrum.reg(Grammar.Regex.DotSeparatedSymbols) - static attributeNameQuoted = Parsernostrum.reg(new RegExp('"(' + Grammar.Regex.DotSeparatedSymbols.source + ')"'), 1) - static guid = Parsernostrum.reg(new RegExp(`${Grammar.Regex.HexDigit.source}{32}`)) - static commaSeparation = Parsernostrum.reg(/\s*,\s*(?!\))/) - static commaOrSpaceSeparation = Parsernostrum.reg(/\s*,\s*(?!\))|\s+/) - static equalSeparation = Parsernostrum.reg(/\s*=\s*/) - static hexColorChannel = Parsernostrum.reg(new RegExp(Grammar.Regex.HexDigit.source + "{2}")) - - /* --- Factory --- */ - - /** - * @template {AttributeTypeDescription} T - * @param {T} type - */ - static grammarFor( - attribute, - type = attribute?.constructor === Object - ? attribute.type - : attribute?.constructor, - defaultGrammar = this.unknownValue - ) { - let result = defaultGrammar; - if (type instanceof Array) { - if (attribute?.inlined) { - return this.grammarFor(undefined, type[0]) - } - result = Parsernostrum.seq( - Parsernostrum.reg(/\(\s*/), - this.grammarFor(undefined, type[0]).sepBy(this.commaSeparation), - Parsernostrum.reg(/\s*(?:,\s*)?\)/), - ).map(([_0, values, _3]) => values); - } else if (type instanceof Union) { - result = type.values - .map(v => this.grammarFor(undefined, v)) - .reduce((acc, cur) => !cur || cur === this.unknownValue || acc === this.unknownValue - ? this.unknownValue - : Parsernostrum.alt(acc, cur) - ); - } else if (type instanceof MirroredEntity) { - return this.grammarFor(undefined, type.getTargetType()) - .map(v => new MirroredEntity(type.type, () => v)) - } else if (attribute?.constructor === Object) { - result = this.grammarFor(undefined, type); - } else { - switch (type) { - case Boolean: - result = this.boolean; - break - case Number: - result = this.number; - break - case BigInt: - result = this.bigInt; - break - case String: - result = this.string; - break - default: - if (/** @type {AttributeConstructor} */(type)?.prototype instanceof Serializable) { - return /** @type {typeof Serializable} */(type).grammar - } - } - } - if (attribute?.constructor === Object) { - if (attribute.serialized && type.constructor !== String) { - if (result == this.unknownValue) { - result = this.string; - } else { - result = Parsernostrum.seq(Parsernostrum.str('"'), result, Parsernostrum.str('"')); - } - } - if (attribute.nullable) { - result = Parsernostrum.alt(result, this.null); - } - } - return result - } - - /** - * @template {AttributeConstructor} T - * @param {T} entityType - * @param {String[]} key - * @returns {AttributeInformation} - */ - static getAttribute(entityType, key) { - let result; - let type; - if (entityType instanceof Union) { - for (let t of entityType.values) { - if (result = this.getAttribute(t, key)) { - return result - } - } - } - if (entityType instanceof IEntity.constructor) { - // @ts-expect-error - result = entityType.attributes[key[0]]; - type = result?.type; - } else if (entityType instanceof Array) { - result = entityType[key[0]]; - type = result; - } - if (key.length > 1) { - return this.getAttribute(type, key.slice(1)) - } - return result - } - - static createAttributeGrammar( - entityType, - attributeName = this.attributeName, - valueSeparator = this.equalSeparation, - handleObjectSet = (obj, k, v) => { } - ) { - return Parsernostrum.seq( - attributeName, - valueSeparator, - ).chain(([attributeName, _1]) => { - const attributeKey = attributeName.split(Configuration.keysSeparator); - const attributeValue = this.getAttribute(entityType, attributeKey); - return this - .grammarFor(attributeValue) - .map(attributeValue => - values => { - handleObjectSet(values, attributeKey, attributeValue); - Utility.objectSet(values, attributeKey, attributeValue); - } - ) - }) - } - - /** - * @template {IEntity} T - * @param {(new (...args: any) => T) & EntityConstructor} entityType - * @param {Boolean | Number} acceptUnknownKeys Number to specify the limit or true, to let it be a reasonable value - */ - static createEntityGrammar = (entityType, acceptUnknownKeys = true, entriesSeparator = this.commaSeparation) => - Parsernostrum.seq( - Parsernostrum.reg( - entityType.lookbehind instanceof Union - ? new RegExp(`(${entityType.lookbehind.values.reduce((acc, cur) => acc + "|" + cur)})\\s*\\(\\s*`) - : entityType.lookbehind.constructor == String && entityType.lookbehind.length - ? new RegExp(`(${entityType.lookbehind})\\s*\\(\\s*`) - : /()\(\s*/, - 1 - ), - this.createAttributeGrammar(entityType).sepBy(entriesSeparator), - Parsernostrum.reg(/\s*(?:,\s*)?\)/), // trailing comma - ) - .map(([lookbehind, attributes, _2]) => { - let values = {}; - attributes.forEach(attributeSetter => attributeSetter(values)); - if (lookbehind.length) { - values.lookbehind = lookbehind; - } - return values - }) - // Decide if we accept the entity or not. It is accepted if it doesn't have too many unexpected keys - .chain(values => { - let totalKeys = Object.keys(values); - // Check missing values - if ( - Object.keys(/** @type {AttributeInformation} */(entityType.attributes)) - .filter(key => entityType.attributes[key].expected) - .find(key => !totalKeys.includes(key) && (key)) - ) { - return Parsernostrum.failure() - } - const unknownKeys = Object.keys(values).filter(key => !(key in entityType.attributes)).length; - if (!acceptUnknownKeys && unknownKeys > 0) { - return Parsernostrum.failure() - } - return Parsernostrum.success().map(() => new entityType(values)) - }) - - /* --- Entity --- */ - - static unknownValue // Defined in initializeSerializerFactor to avoid circular include -} - -class GuidEntity extends IEntity { - - static attributes = { - ...super.attributes, - value: { - default: "", - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Grammar.guid.map(v => new this(v)) - } - - static generateGuid(random = true) { - let values = new Uint32Array(4); - if (random === true) { - crypto.getRandomValues(values); - } - let guid = ""; - values.forEach(n => { - guid += ("0".repeat(8) + n.toString(16).toUpperCase()).slice(-8); - }); - return new GuidEntity({ value: guid }) - } - - constructor(values) { - if (!values) { - values = GuidEntity.generateGuid().value; - } - if (values.constructor !== Object) { - values = { - value: values, - }; - } - super(values); - /** @type {String} */ this.value; - } - - valueOf() { - return this.value - } - - toString() { - return this.value - } -} - -class ObjectReferenceEntity extends IEntity { - - static attributes = { - ...super.attributes, - type: { - default: "", - serialized: true, - }, - path: { - default: "", - serialized: true, - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static quoted = Parsernostrum.regArray(new RegExp( - `'"(` + Grammar.Regex.InsideString.source + `)"'` - + `|'(` + Grammar.Regex.InsideSingleQuotedString.source + `)'` - + `|"(` + Grammar.Regex.InsideString.source + `)"` - )).map(([_0, a, b, c]) => a ?? b ?? c) - static path = this.quoted.getParser().parser.regexp.source + "|" + Grammar.Regex.Path.source - static typeReference = Parsernostrum.reg( - new RegExp(Grammar.Regex.Path.source + "|" + Grammar.symbol.getParser().regexp.source) - ) - static fullReferenceGrammar = Parsernostrum.regArray( - new RegExp( - "(" + this.typeReference.getParser().regexp.source + ")" - + /\s*/.source - + "(?:" + this.quoted.getParser().parser.regexp.source + ")" - ) - ).map(([_0, type, ...path]) => new this({ type, path: path.find(v => v) })) - static fullReferenceSerializedGrammar = Parsernostrum.regArray( - new RegExp( - "(" + this.typeReference.getParser().regexp.source + ")" - + /\s*/.source - + `'(` + Grammar.Regex.InsideSingleQuotedString.source + `)'` - ) - ).map(([_0, type, ...path]) => new this({ type, path: path.find(v => v) })) - static typeReferenceGrammar = this.typeReference.map(v => new this({ type: v, path: "" })) - static grammar = this.createGrammar() - - static createGrammar() { - return Parsernostrum.alt( - Parsernostrum.seq( - Parsernostrum.str('"'), - Parsernostrum.alt( - this.fullReferenceSerializedGrammar, - this.typeReferenceGrammar, - ), - Parsernostrum.str('"'), - ).map(([_0, objectReference, _1]) => objectReference), - this.fullReferenceGrammar.map(v => (Utility.objectSet(v, ["attributes", "type", "serialized"], false), v)), - this.typeReferenceGrammar.map(v => (Utility.objectSet(v, ["attributes", "type", "serialized"], false), v)), - ) - } - - constructor(values = {}) { - if (values.constructor === String) { - values = { - path: values - }; - } - super(values); - /** @type {String} */ this.type; - /** @type {String} */ this.path; - } - - static createNoneInstance() { - return new ObjectReferenceEntity({ type: "None", path: "" }) - } - - sanitize() { - if (this.type && !this.type.startsWith("/")) { - let deprecatedType = this.type + "_Deprecated"; - let path = Object.keys(Configuration.paths) - .find(type => { - const name = Utility.getNameFromPath(Configuration.paths[type]); - return name === this.type || name === deprecatedType - }); - if (path) { - this.type = Configuration.paths[path]; - } - } - } - - getName() { - return Utility.getNameFromPath(this.path.replace(/_C$/, "")) - } - - toString() { - return this.type + (this.path ? `'${this.path}'` : "") - } -} - -class FunctionReferenceEntity extends IEntity { - - static attributes = { - ...super.attributes, - MemberParent: { - type: ObjectReferenceEntity, - }, - MemberName: { - type: String, - }, - MemberGuid: { - type: GuidEntity, - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Grammar.createEntityGrammar(this) - } - - constructor(values) { - super(values); - /** @type {ObjectReferenceEntity} */ this.MemberParent; - /** @type {String} */ this.MemberName; - /** @type {GuidEntity} */ this.MemberGuid; - } -} - -class IdentifierEntity extends IEntity { - - static attributes = { - ...super.attributes, - value: { - default: "", - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static attributeConverter = { - fromAttribute: (value, type) => new IdentifierEntity(value), - toAttribute: (value, type) => value.toString() - } - static grammar = this.createGrammar() - - static createGrammar() { - return Grammar.symbol.map(v => new this(v)) - } - - constructor(values) { - if (values.constructor !== Object) { - values = { - value: values, - }; - } - super(values); - /** @type {String} */ this.value; - } - - valueOf() { - return this.value - } - - toString() { - return this.value - } -} - -class IntegerEntity extends IEntity { - - static attributes = { - ...super.attributes, - value: { - default: 0, - predicate: v => v % 1 == 0 && v > 1 << 31 && v < -(1 << 31), - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Parsernostrum.numberInteger.map(v => new this(v)) - } - - /** @param {Number | AttributeInformation} value */ - constructor(value = 0) { - if (value === -0) { - value = 0; - } - super(value.constructor === Object - ? value - : { - value: value, - } - ); - /** @type {Number} */ this.value; - } - - valueOf() { - return this.value - } - - toString() { - return this.value.toString() - } -} - -class ColorChannelEntity extends IEntity { - - static attributes = { - ...super.attributes, - value: { - default: 0, - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Parsernostrum.number.map(value => new this(value)) - } - - constructor(values = 0) { - if (values.constructor !== Object) { - // @ts-expect-error - values = { - value: values, - }; - } - super(values); - /** @type {Number} */ this.value; - } - - valueOf() { - return this.value - } - - toString() { - return this.value.toFixed(6) - } -} - -class LinearColorEntity extends IEntity { - - static attributes = { - ...super.attributes, - R: { - type: ColorChannelEntity, - default: () => new ColorChannelEntity(), - expected: true, - }, - G: { - type: ColorChannelEntity, - default: () => new ColorChannelEntity(), - expected: true, - }, - B: { - type: ColorChannelEntity, - default: () => new ColorChannelEntity(), - expected: true, - }, - A: { - type: ColorChannelEntity, - default: () => new ColorChannelEntity(1), - }, - H: { - type: ColorChannelEntity, - default: () => new ColorChannelEntity(), - ignored: true, - }, - S: { - type: ColorChannelEntity, - default: () => new ColorChannelEntity(), - ignored: true, - }, - V: { - type: ColorChannelEntity, - default: () => new ColorChannelEntity(), - ignored: true, - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - /** @param {Number} x */ - static linearToSRGB(x) { - if (x <= 0) { - return 0 - } else if (x >= 1) { - return 1 - } else if (x < 0.0031308) { - return x * 12.92 - } else { - return Math.pow(x, 1 / 2.4) * 1.055 - 0.055 - } - } - - /** @param {Number} x */ - static sRGBtoLinear(x) { - if (x <= 0) { - return 0 - } else if (x >= 1) { - return 1 - } else if (x < 0.04045) { - return x / 12.92 - } else { - return Math.pow((x + 0.055) / 1.055, 2.4) - } - } - - static getWhite() { - return new LinearColorEntity({ - R: 1, - G: 1, - B: 1, - }) - } - - static createGrammar() { - return Grammar.createEntityGrammar(this, false) - } - - static getLinearColorFromHexGrammar() { - return Parsernostrum.regArray(new RegExp( - "#(" + Grammar.Regex.HexDigit.source + "{2})" - + "(" + Grammar.Regex.HexDigit.source + "{2})" - + "(" + Grammar.Regex.HexDigit.source + "{2})" - + "(" + Grammar.Regex.HexDigit.source + "{2})?" - )).map(([m, R, G, B, A]) => new this({ - R: parseInt(R, 16) / 255, - G: parseInt(G, 16) / 255, - B: parseInt(B, 16) / 255, - A: parseInt(A ?? "FF", 16) / 255, - })) - } - - static getLinearColorRGBListGrammar() { - return Parsernostrum.seq( - Parsernostrum.numberByte, - Grammar.commaSeparation, - Parsernostrum.numberByte, - Grammar.commaSeparation, - Parsernostrum.numberByte, - ).map(([R, _1, G, _3, B]) => new this({ - R: R / 255, - G: G / 255, - B: B / 255, - A: 1, - })) - } - - static getLinearColorRGBGrammar() { - return Parsernostrum.seq( - Parsernostrum.reg(/rgb\s*\(\s*/), - this.getLinearColorRGBListGrammar(), - Parsernostrum.reg(/\s*\)/) - ).map(([_0, linearColor, _2]) => linearColor) - } - - static getLinearColorRGBAGrammar() { - return Parsernostrum.seq( - Parsernostrum.reg(/rgba\s*\(\s*/), - this.getLinearColorRGBListGrammar(), - Parsernostrum.reg(/\s*\)/) - ).map(([_0, linearColor, _2]) => linearColor) - } - - static getLinearColorFromAnyFormat() { - return Parsernostrum.alt( - this.getLinearColorFromHexGrammar(), - this.getLinearColorRGBAGrammar(), - this.getLinearColorRGBGrammar(), - this.getLinearColorRGBListGrammar(), - ) - } - - constructor(values) { - if (values instanceof Array) { - values = { - R: values[0] ?? 0, - G: values[1] ?? 0, - B: values[2] ?? 0, - A: values[3] ?? 1, - }; - } - super(values); - /** @type {ColorChannelEntity} */ this.R; - /** @type {ColorChannelEntity} */ this.G; - /** @type {ColorChannelEntity} */ this.B; - /** @type {ColorChannelEntity} */ this.A; - /** @type {ColorChannelEntity} */ this.H; - /** @type {ColorChannelEntity} */ this.S; - /** @type {ColorChannelEntity} */ this.V; - this.#updateHSV(); - } - - #updateHSV() { - const r = this.R.value; - const g = this.G.value; - const b = this.B.value; - if (Utility.approximatelyEqual(r, g) && Utility.approximatelyEqual(r, b) && Utility.approximatelyEqual(g, b)) { - this.S.value = 0; - this.V.value = r; - return - } - const max = Math.max(r, g, b); - const min = Math.min(r, g, b); - const d = max - min; - let h; - switch (max) { - case min: - h = 0; - break - case r: - h = (g - b) / d + (g < b ? 6 : 0); - break - case g: - h = (b - r) / d + 2; - break - case b: - h = (r - g) / d + 4; - break - } - h /= 6; - this.H.value = h; - this.S.value = max == 0 ? 0 : d / max; - this.V.value = max; - } - - /** - * @param {Number} r - * @param {Number} g - * @param {Number} b - * @param {Number} a - */ - setFromRGBA(r, g, b, a = 1) { - this.R.value = r; - this.G.value = g; - this.B.value = b; - this.A.value = a; - this.#updateHSV(); - } - - /** - * @param {Number} h - * @param {Number} s - * @param {Number} v - * @param {Number} a - */ - setFromHSVA(h, s, v, a = 1) { - const i = Math.floor(h * 6); - const f = h * 6 - i; - const p = v * (1 - s); - const q = v * (1 - f * s); - const t = v * (1 - (1 - f) * s); - const values = [v, q, p, p, t, v]; - const [r, g, b] = [values[i % 6], values[(i + 4) % 6], values[(i + 2) % 6]]; - this.R.value = r; - this.G.value = g; - this.B.value = b; - this.A.value = a; - this.H.value = h; - this.S.value = s; - this.V.value = v; - } - - /** - * @param {Number} x - * @param {Number} y - * @param {Number} v - * @param {Number} a - */ - setFromWheelLocation(x, y, v, a) { - const [r, theta] = Utility.getPolarCoordinates(x, y, true); - this.setFromHSVA(1 - theta / (2 * Math.PI), r, v, a); - } - - toDimmedColor(minV = 0) { - const result = new LinearColorEntity(); - result.setFromRGBANumber(this.toNumber()); - result.setFromHSVA( - result.H.value, - result.S.value * 0.6, - Math.pow(result.V.value + minV, 0.55) * 0.7 - ); - return result - } - - toCSSRGBValues() { - const r = Math.round(this.R.value * 255); - const g = Math.round(this.G.value * 255); - const b = Math.round(this.B.value * 255); - return i$3`${r}, ${g}, ${b}` - } - - toRGBA() { - return [ - Math.round(this.R.value * 255), - Math.round(this.G.value * 255), - Math.round(this.B.value * 255), - Math.round(this.A.value * 255), - ] - } - - toSRGBA() { - return [ - Math.round(LinearColorEntity.linearToSRGB(this.R.value) * 255), - Math.round(LinearColorEntity.linearToSRGB(this.G.value) * 255), - Math.round(LinearColorEntity.linearToSRGB(this.B.value) * 255), - Math.round(this.A.value * 255), - ] - } - - toRGBAString() { - return this - .toRGBA() - .map(v => v.toString(16).toUpperCase().padStart(2, "0")) - .join("") - } - - toSRGBAString() { - return this - .toSRGBA() - .map(v => v.toString(16).toUpperCase().padStart(2, "0")) - .join("") - } - - toHSVA() { - return [this.H.value, this.S.value, this.V.value, this.A.value] - } - - toNumber() { - return ( - Math.round(this.R.value * 0xff) << 24) - + (Math.round(this.G.value * 0xff) << 16) - + (Math.round(this.B.value * 0xff) << 8) - + Math.round(this.A.value * 0xff) - } - - /** @param {Number} number */ - setFromRGBANumber(number) { - this.A.value = (number & 0xff) / 0xff; - this.B.value = ((number >> 8) & 0xff) / 0xff; - this.G.value = ((number >> 16) & 0xff) / 0xff; - this.R.value = ((number >> 24) & 0xff) / 0xff; - this.#updateHSV(); - } - - /** @param {Number} number */ - setFromSRGBANumber(number) { - this.A.value = (number & 0xff) / 0xff; - this.B.value = LinearColorEntity.sRGBtoLinear(((number >> 8) & 0xff) / 0xff); - this.G.value = LinearColorEntity.sRGBtoLinear(((number >> 16) & 0xff) / 0xff); - this.R.value = LinearColorEntity.sRGBtoLinear(((number >> 24) & 0xff) / 0xff); - this.#updateHSV(); - } - - /** @returns {[Number, Number, Number, Number]} */ - toArray() { - return [this.R.value, this.G.value, this.B.value, this.A.value] - } - - toString() { - return Utility.printLinearColor(this) - } -} - -class MacroGraphReferenceEntity extends IEntity { - - static attributes = { - ...super.attributes, - MacroGraph: { - type: ObjectReferenceEntity, - default: () => new ObjectReferenceEntity(), - }, - GraphBlueprint: { - type: ObjectReferenceEntity, - default: () => new ObjectReferenceEntity(), - }, - GraphGuid: { - type: GuidEntity, - default: () => new GuidEntity(), - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Grammar.createEntityGrammar(this) - } - - constructor(values) { - super(values); - /** @type {ObjectReferenceEntity} */ this.MacroGraph; - /** @type {ObjectReferenceEntity} */ this.GraphBlueprint; - /** @type {GuidEntity} */ this.GuidEntity; - } - - getMacroName() { - const colonIndex = this.MacroGraph.path.search(":"); - return this.MacroGraph.path.substring(colonIndex + 1) - } -} - -class ByteEntity extends IntegerEntity { - - static attributes = { - ...super.attributes, - value: { - ...super.attributes.value, - predicate: v => v % 1 == 0 && v >= 0 && v < 1 << 8, - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Parsernostrum.numberByte.map(v => new this(v)) - } - - constructor(values = 0) { - super(values); - } -} - -class SymbolEntity extends IEntity { - - static attributes = { - ...super.attributes, - value: { - default: "", - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Grammar.symbol.map(v => new this(v)) - } - - /** @param {String | Object} values */ - constructor(values) { - if (values.constructor !== Object) { - values = { - value: values, - }; - } - super(values); - /** @type {String} */ this.value; - } - - valueOf() { - return this.value - } - - toString() { - return this.value - } -} - -class EnumEntity extends SymbolEntity { - - static grammar = this.createGrammar() - - static createGrammar() { - return Grammar.symbol.map(v => new this(v)) - } -} - -class EnumDisplayValueEntity extends EnumEntity { - - static grammar = this.createGrammar() - - static createGrammar() { - return Parsernostrum.reg(Grammar.Regex.InsideString).map(v => new this(v)) - } -} - -class InvariantTextEntity extends IEntity { - - static lookbehind = "INVTEXT" - static attributes = { - ...super.attributes, - value: { - default: "", - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Parsernostrum.alt( - Parsernostrum.seq( - Parsernostrum.reg(new RegExp(`${this.lookbehind}\\s*\\(`)), - Grammar.grammarFor(this.attributes.value), - Parsernostrum.reg(/\s*\)/) - ) - .map(([_0, value, _2]) => value), - Parsernostrum.reg(new RegExp(this.lookbehind)) // InvariantTextEntity can not have arguments - .map(() => "") - ).map(value => new this(value)) - } - - constructor(values) { - if (values.constructor !== Object) { - values = { - value: values, - }; - } - super(values); - /** @type {String} */ this.value; - } -} - -class LocalizedTextEntity extends IEntity { - - static lookbehind = "NSLOCTEXT" - static attributes = { - ...super.attributes, - namespace: { - default: "", - }, - key: { - default: "", - }, - value: { - default: "", - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Parsernostrum.regArray(new RegExp( - String.raw`${this.lookbehind}\s*\(` - + String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*,` - + String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*,` - + String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*` - + String.raw`(?:,\s+)?` - + String.raw`\)`, - "m" - )).map(matchResult => new this({ - namespace: Utility.unescapeString(matchResult[1]), - key: Utility.unescapeString(matchResult[2]), - value: Utility.unescapeString(matchResult[3]), - })) - } - - constructor(values) { - super(values); - /** @type {String} */ this.namespace; - /** @type {String} */ this.key; - /** @type {String} */ this.value; - } - - toString() { - return Utility.capitalFirstLetter(this.value) - } -} - -class FormatTextEntity extends IEntity { - - static lookbehind = new Union("LOCGEN_FORMAT_NAMED", "LOCGEN_FORMAT_ORDERED") - static attributes = { - ...super.attributes, - value: { - type: [new Union(String, LocalizedTextEntity, InvariantTextEntity, FormatTextEntity)], - default: [], - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Parsernostrum.seq( - Parsernostrum.reg( - // Resulting regex: /(LOCGEN_FORMAT_NAMED|LOCGEN_FORMAT_ORDERED)\s*/ - new RegExp(`(${this.lookbehind.values.reduce((acc, cur) => acc + "|" + cur)})\\s*`), - 1 - ), - Grammar.grammarFor(this.attributes.value) - ) - .map(([lookbehind, values]) => { - const result = new this({ - value: values, - }); - result.lookbehind = lookbehind; - return result - }) - } - - constructor(values) { - super(values); - /** @type {(String | LocalizedTextEntity | InvariantTextEntity | FormatTextEntity)[]} */ this.value; - } - - toString() { - const pattern = this.value?.[0]?.toString(); // The pattern is always the first element of the array - if (!pattern) { - return "" - } - const values = this.value.slice(1).map(v => v.toString()); - return this.lookbehind == "LOCGEN_FORMAT_NAMED" - ? pattern.replaceAll(/\{([a-zA-Z]\w*)\}/g, (substring, arg) => { - const argLocation = values.indexOf(arg) + 1; - return argLocation > 0 && argLocation < values.length - ? values[argLocation] - : substring - }) - : this.lookbehind == "LOCGEN_FORMAT_ORDERED" - ? pattern.replaceAll(/\{(\d+)\}/g, (substring, arg) => { - const argValue = Number(arg); - return argValue < values.length - ? values[argValue] - : substring - }) - : "" - } -} - -class Integer64Entity extends IEntity { - - static attributes = { - ...super.attributes, - value: { - default: 0n, - predicate: v => v >= -(1n << 63n) && v < 1n << 63n, - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Parsernostrum.numberBigInteger.map(v => new this(v)) - } - - /** @param {BigInt | Number} value */ - constructor(value = 0) { - if (value.constructor !== Object) { - value = { - // @ts-expect-error - value: value, - }; - } - super(value); - /** @type {BigInt | Number} */ this.value; - } - - valueOf() { - return this.value - } - - toString() { - return this.value.toString() - } -} - -class PathSymbolEntity extends IEntity { - - static attributes = { - ...super.attributes, - value: { - default: "", - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Grammar.symbol.map(v => new this(v)) - } - - constructor(values) { - if (values.constructor !== Object) { - values = { - value: values, - }; - } - super(values); - /** @type {String} */ this.value; - } - - valueOf() { - return this.value - } - - toString() { - return this.value - } -} - -class PinReferenceEntity extends IEntity { - - static attributes = { - ...super.attributes, - objectName: { - type: PathSymbolEntity, - }, - pinGuid: { - type: GuidEntity, - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Parsernostrum.seq( - PathSymbolEntity.createGrammar(), - Parsernostrum.whitespace, - GuidEntity.createGrammar() - ).map( - ([objectName, _1, pinGuid]) => new this({ - objectName: objectName, - pinGuid: pinGuid, - }) - ) - } - - constructor(values) { - super(values); - /** @type {PathSymbolEntity} */ this.objectName; - /** @type {GuidEntity} */ this.pinGuid; - } -} - -class PinTypeEntity extends IEntity { - - static attributes = { - ...super.attributes, - PinCategory: { - default: "", - }, - PinSubCategory: { - default: "", - }, - PinSubCategoryObject: { - type: ObjectReferenceEntity, - default: () => ObjectReferenceEntity.createNoneInstance(), - }, - PinSubCategoryMemberReference: { - type: FunctionReferenceEntity, - default: null, - }, - PinValueType: { - type: PinTypeEntity, - default: null, - }, - ContainerType: { - type: PathSymbolEntity, - }, - bIsReference: { - default: false, - }, - bIsConst: { - default: false, - }, - bIsWeakPointer: { - default: false, - }, - bIsUObjectWrapper: { - default: false, - }, - bSerializeAsSinglePrecisionFloat: { - default: false, - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Grammar.createEntityGrammar(this) - } - - constructor(values = {}, suppressWarns = false) { - super(values, suppressWarns); - /** @type {String} */ this.PinCategory; - /** @type {String} */ this.PinSubCategory; - /** @type {ObjectReferenceEntity} */ this.PinSubCategoryObject; - /** @type {FunctionReferenceEntity} */ this.PinSubCategoryMemberReference; - /** @type {PinTypeEntity} */ this.PinValueType; - /** @type {PathSymbolEntity} */ this.ContainerType; - /** @type {Boolean} */ this.bIsReference; - /** @type {Boolean} */ this.bIsConst; - /** @type {Boolean} */ this.bIsWeakPointer; - /** @type {Boolean} */ this.bIsUObjectWrapper; - /** @type {Boolean} */ this.bIsUObjectWrapper; - /** @type {Boolean} */ this.bSerializeAsSinglePrecisionFloat; - } - - /** @param {PinTypeEntity} other */ - copyTypeFrom(other) { - this.PinCategory = other.PinCategory; - this.PinSubCategory = other.PinSubCategory; - this.PinSubCategoryObject = other.PinSubCategoryObject; - this.PinSubCategoryMemberReference = other.PinSubCategoryMemberReference; - this.PinValueType = other.PinValueType; - this.ContainerType = other.ContainerType; - this.bIsReference = other.bIsReference; - this.bIsConst = other.bIsConst; - this.bIsWeakPointer = other.bIsWeakPointer; - this.bIsUObjectWrapper = other.bIsUObjectWrapper; - this.bSerializeAsSinglePrecisionFloat = other.bSerializeAsSinglePrecisionFloat; - } -} - -class Vector2DEntity extends IEntity { - - static attributes = { - ...super.attributes, - X: { - default: 0, - expected: true, - }, - Y: { - default: 0, - expected: true, - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Grammar.createEntityGrammar(this, false) - } - - constructor(values) { - super(values); - /** @type {Number} */ this.X; - /** @type {Number} */ this.Y; - } - - /** @returns {[Number, Number]} */ - toArray() { - return [this.X, this.Y] - } -} - -class RBSerializationVector2DEntity extends Vector2DEntity { - - static grammar = this.createGrammar() - - static createGrammar() { - return Parsernostrum.alt( - Parsernostrum.regArray(new RegExp( - /X\s*=\s*/.source + "(?" + Parsernostrum.number.getParser().parser.regexp.source + ")" - + "\\s+" - + /Y\s*=\s*/.source + "(?" + Parsernostrum.number.getParser().parser.regexp.source + ")" - )).map(({ groups: { x, y } }) => new this({ - X: Number(x), - Y: Number(y), - })), - Vector2DEntity.createGrammar() - ) - } -} - -class RotatorEntity extends IEntity { - - static attributes = { - ...super.attributes, - R: { - default: 0, - expected: true, - }, - P: { - default: 0, - expected: true, - }, - Y: { - default: 0, - expected: true, - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Grammar.createEntityGrammar(this, false) - } - - constructor(values) { - super(values); - /** @type {Number} */ this.R; - /** @type {Number} */ this.P; - /** @type {Number} */ this.Y; - } - - getRoll() { - return this.R - } - - getPitch() { - return this.P - } - - getYaw() { - return this.Y - } -} - -class SimpleSerializationRotatorEntity extends RotatorEntity { - - static grammar = this.createGrammar() - - static createGrammar() { - const number = Parsernostrum.number.getParser().parser.regexp.source; - return Parsernostrum.alt( - Parsernostrum.reg(new RegExp( - "(" + number + ")" - + "\\s*,\\s" - + "(" + number + ")" - + "\\s*,\\s" - + "(" + number + ")" - )).map(([p, y, r]) => new this({ - R: Number(r), - P: Number(p), - Y: Number(y), - })), - RotatorEntity.createGrammar() - ) - } -} - -class SimpleSerializationVector2DEntity extends Vector2DEntity { - - static grammar = this.createGrammar() - - static createGrammar() { - const number = Parsernostrum.number.getParser().parser.regexp.source; - return Parsernostrum.alt( - Parsernostrum.reg(new RegExp( - "(" + number + ")" - + "\\s*,\\s" - + "(" + number + ")" - )).map(([x, y]) => new this({ - X: Number(x), - Y: Number(y), - })), - Vector2DEntity.createGrammar() - ) - } -} - -class VectorEntity extends IEntity { - - static attributes = { - ...super.attributes, - X: { - default: 0, - expected: true, - }, - Y: { - default: 0, - expected: true, - }, - Z: { - default: 0, - expected: true, - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Grammar.createEntityGrammar(VectorEntity, false) - } - - constructor(values) { - super(values); - /** @type {Number} */ this.X; - /** @type {Number} */ this.Y; - /** @type {Number} */ this.Z; - } - - /** @returns {[Number, Number, Number]} */ - toArray() { - return [this.X, this.Y, this.Z] - } -} - -class SimpleSerializationVectorEntity extends VectorEntity { - - static grammar = this.createGrammar() - - static createGrammar() { - const number = Parsernostrum.number.getParser().parser.regexp.source; - return Parsernostrum.alt( - Parsernostrum.regArray(new RegExp( - "(" + number + ")" - + "\\s*,\\s*" - + "(" + number + ")" - + "\\s*,\\s*" - + "(" + number + ")" - )) - .map(([_0, x, y, z]) => new this({ - X: Number(x), - Y: Number(y), - Z: Number(z), - })), - VectorEntity.createGrammar() - ) - } -} - -/** @template {TerminalAttribute} T */ -class PinEntity extends IEntity { - - static #typeEntityMap = { - [Configuration.paths.linearColor]: LinearColorEntity, - [Configuration.paths.rotator]: RotatorEntity, - [Configuration.paths.vector]: VectorEntity, - [Configuration.paths.vector2D]: Vector2DEntity, - "bool": Boolean, - "byte": ByteEntity, - "enum": EnumEntity, - "exec": String, - "int": IntegerEntity, - "int64": Integer64Entity, - "name": String, - "real": Number, - "string": String, - } - static #alternativeTypeEntityMap = { - "enum": EnumDisplayValueEntity, - "rg": RBSerializationVector2DEntity, - [Configuration.paths.rotator]: SimpleSerializationRotatorEntity, - [Configuration.paths.vector]: SimpleSerializationVectorEntity, - [Configuration.paths.vector2D]: SimpleSerializationVector2DEntity, - } - static lookbehind = "Pin" - static attributes = { - ...super.attributes, - objectEntity: { - ignored: true, - }, - pinIndex: { - type: Number, - ignored: true, - }, - PinId: { - type: GuidEntity, - default: () => new GuidEntity() - }, - PinName: { - default: "", - }, - PinFriendlyName: { - type: new Union(LocalizedTextEntity, FormatTextEntity, String), - }, - PinToolTip: { - type: String, - }, - Direction: { - type: String, - }, - PinType: { - type: PinTypeEntity, - default: () => new PinTypeEntity(), - inlined: true, - }, - LinkedTo: { - type: [PinReferenceEntity], - }, - SubPins: { - type: [PinReferenceEntity], - }, - ParentPin: { - type: PinReferenceEntity, - }, - DefaultValue: { - type: new ComputedType( - /** @param {PinEntity} pinEntity */ - pinEntity => pinEntity.getEntityType(true) ?? String - ), - serialized: true, - }, - AutogeneratedDefaultValue: { - type: String, - }, - DefaultObject: { - type: ObjectReferenceEntity, - }, - PersistentGuid: { - type: GuidEntity, - }, - bHidden: { - default: false, - }, - bNotConnectable: { - default: false, - }, - bDefaultValueIsReadOnly: { - default: false, - }, - bDefaultValueIsIgnored: { - default: false, - }, - bAdvancedView: { - default: false, - }, - bOrphanedPin: { - default: false, - }, - } - static { - this.cleanupAttributes(this.attributes); - } - static grammar = this.createGrammar() - - static createGrammar() { - return Grammar.createEntityGrammar(this) - } - - constructor(values = {}, suppressWarns = false) { - super(values, suppressWarns); - /** @type {ObjectEntity} */ this.objectEntity; - /** @type {Number} */ this.pinIndex; - /** @type {GuidEntity} */ this.PinId; - /** @type {String} */ this.PinName; - /** @type {LocalizedTextEntity | String} */ this.PinFriendlyName; - /** @type {String} */ this.PinToolTip; - /** @type {String} */ this.Direction; - /** @type {PinTypeEntity} */ this.PinType; - /** @type {PinReferenceEntity[]} */ this.LinkedTo; - /** @type {T} */ this.DefaultValue; - /** @type {String} */ this.AutogeneratedDefaultValue; - /** @type {ObjectReferenceEntity} */ this.DefaultObject; - /** @type {GuidEntity} */ this.PersistentGuid; - /** @type {Boolean} */ this.bHidden; - /** @type {Boolean} */ this.bNotConnectable; - /** @type {Boolean} */ this.bDefaultValueIsReadOnly; - /** @type {Boolean} */ this.bDefaultValueIsIgnored; - /** @type {Boolean} */ this.bAdvancedView; - /** @type {Boolean} */ this.bOrphanedPin; - } - - /** @param {ObjectEntity} objectEntity */ - static fromLegacyObject(objectEntity) { - return new PinEntity(objectEntity, true) - } - - getType() { - const category = this.PinType.PinCategory; - if (category === "struct" || category === "object") { - return this.PinType.PinSubCategoryObject.path - } - if (category === "optional") { - switch (this.PinType.PinSubCategory) { - case "int": - return "int" - case "red": - return "real" - case "rg": - return "rg" - case "rgb": - return Configuration.paths.vector - case "rgba": - return Configuration.paths.linearColor - } - } - if (this.isEnum()) { - return "enum" - } - if (this.objectEntity?.isPcg()) { - const pcgSuboject = this.objectEntity.getPcgSubobject(); - const pinObjectReference = this.isInput() - ? pcgSuboject.InputPins?.[this.pinIndex] - : pcgSuboject.OutputPins?.[this.pinIndex]; - if (pinObjectReference) { - /** @type {ObjectEntity} */ - const pinObject = pcgSuboject[Configuration.subObjectAttributeNameFromReference(pinObjectReference, true)]; - let allowedTypes = pinObject.Properties?.AllowedTypes?.toString() ?? ""; - if (allowedTypes == "") { - allowedTypes = this.PinType.PinCategory ?? ""; - if (allowedTypes == "") { - allowedTypes = "Any"; - } - } - if (allowedTypes) { - if ( - pinObject.Properties.bAllowMultipleData !== false - && pinObject.Properties.bAllowMultipleConnections !== false - ) { - allowedTypes += "[]"; - } - return allowedTypes - } - } - } - return category - } - - getEntityType(alternative = false) { - const typeString = this.getType(); - const entity = PinEntity.#typeEntityMap[typeString]; - const alternativeEntity = PinEntity.#alternativeTypeEntityMap[typeString]; - return alternative && alternativeEntity !== undefined - ? alternativeEntity - : entity - } - - pinDisplayName() { - let result = this.PinFriendlyName - ? this.PinFriendlyName.toString() - : Utility.formatStringName(this.PinName ?? ""); - let match; - if ( - this.PinToolTip - // Match up until the first \n excluded or last character - && (match = this.PinToolTip.match(/\s*(.+?(?=\n)|.+\S)\s*/)) - ) { - if (match[1].toLowerCase() === result.toLowerCase()) { - return match[1] // In case they match, then keep the case of the PinToolTip - } - } - return result - } - - /** @param {PinEntity} other */ - copyTypeFrom(other) { - this.PinType.PinCategory = other.PinType.PinCategory; - this.PinType.PinSubCategory = other.PinType.PinSubCategory; - this.PinType.PinSubCategoryObject = other.PinType.PinSubCategoryObject; - this.PinType.PinSubCategoryMemberReference = other.PinType.PinSubCategoryMemberReference; - this.PinType.PinValueType = other.PinType.PinValueType; - this.PinType.ContainerType = other.PinType.ContainerType; - this.PinType.bIsReference = other.PinType.bIsReference; - this.PinType.bIsConst = other.PinType.bIsConst; - this.PinType.bIsWeakPointer = other.PinType.bIsWeakPointer; - this.PinType.bIsUObjectWrapper = other.PinType.bIsUObjectWrapper; - this.PinType.bSerializeAsSinglePrecisionFloat = other.PinType.bSerializeAsSinglePrecisionFloat; - } - - getDefaultValue(maybeCreate = false) { - if (this.DefaultValue === undefined && maybeCreate) { - // @ts-expect-error - this.DefaultValue = new (this.getEntityType(true))(); - } - return this.DefaultValue - } - - isEnum() { - const type = this.PinType.PinSubCategoryObject.type; - return type === Configuration.paths.enum - || type === Configuration.paths.userDefinedEnum - || type.toLowerCase() === "enum" - } - - isExecution() { - return this.PinType.PinCategory === "exec" - } - - isHidden() { - return this.bHidden - } - - isInput() { - return !this.bHidden && this.Direction != "EGPD_Output" - } - - isOutput() { - return !this.bHidden && this.Direction == "EGPD_Output" - } - - isLinked() { - return this.LinkedTo?.length > 0 ?? false - } - - /** - * @param {String} targetObjectName - * @param {PinEntity} targetPinEntity - */ - linkTo(targetObjectName, targetPinEntity) { - const linkFound = this.LinkedTo?.some(pinReferenceEntity => - pinReferenceEntity.objectName.toString() == targetObjectName - && pinReferenceEntity.pinGuid.valueOf() == targetPinEntity.PinId.valueOf() - ); - if (!linkFound) { - (this.LinkedTo ??= []).push(new PinReferenceEntity({ - objectName: targetObjectName, - pinGuid: targetPinEntity.PinId, - })); - return true - } - return false // Already linked - } - - /** - * @param {String} targetObjectName - * @param {PinEntity} targetPinEntity - */ - unlinkFrom(targetObjectName, targetPinEntity) { - const indexElement = this.LinkedTo?.findIndex(pinReferenceEntity => { - return pinReferenceEntity.objectName.toString() == targetObjectName - && pinReferenceEntity.pinGuid.valueOf() == targetPinEntity.PinId.valueOf() - }); - if (indexElement >= 0) { - this.LinkedTo.splice(indexElement, 1); - if (this.LinkedTo.length === 0 && PinEntity.attributes.LinkedTo.default === undefined) { - this.LinkedTo = undefined; - } - return true - } - return false - } - - getSubCategory() { - return this.PinType.PinSubCategoryObject.path - } - - /** @return {CSSResult} */ - pinColor() { - if (this.PinType.PinCategory == "mask") { - const result = Configuration.pinColor[this.PinType.PinSubCategory]; - if (result) { - return result - } - } else if (this.PinType.PinCategory == "optional") { - return Configuration.pinColorMaterial - } - return Configuration.pinColor[this.getType()] - ?? Configuration.pinColor[this.PinType.PinCategory.toLowerCase()] - ?? Configuration.pinColor["default"] - } -} - class SVGIcon { static arrayPin = x` @@ -4777,15 +2797,1965 @@ class SVGIcon { ` } +class Serializable { + + static grammar = this.createGrammar() + + /** @protected */ + static createGrammar() { + return /** @type {Parsernostrum} */(Parsernostrum.failure()) + } +} + +class SerializerFactory { + + static #serializers = new Map() + + /** + * @template {AttributeConstructor} T + * @param {T} type + * @param {Serializer} object + */ + static registerSerializer(type, object) { + SerializerFactory.#serializers.set(type, object); + } + + /** + * @template {AttributeConstructor} T + * @param {T} type + * @returns {Serializer} + */ + static getSerializer(type) { + return SerializerFactory.#serializers.get(type) + } +} + +/** @abstract */ +class IEntity extends Serializable { + + static attributes = { + attributes: new AttributeInfo({ + ignored: true, + }), + lookbehind: new AttributeInfo({ + default: /** @type {String | Union} */(""), + ignored: true, + }), + } + + constructor(values = {}, suppressWarns = false) { + super(); + const Self = /** @type {typeof IEntity} */(this.constructor); + /** @type {AttributeDeclarations?} */ this.attributes; + /** @type {String} */ this.lookbehind; + const valuesKeys = Object.keys(values); + const attributesKeys = values.attributes + ? Utility.mergeArrays(Object.keys(values.attributes), Object.keys(Self.attributes)) + : Object.keys(Self.attributes); + const allAttributesKeys = Utility.mergeArrays(valuesKeys, attributesKeys); + for (const key of allAttributesKeys) { + let value = values[key]; + if (!suppressWarns && !(key in values)) { + if (!(key in Self.attributes) && !key.startsWith(Configuration.subObjectAttributeNamePrefix)) { + const typeName = value instanceof Array ? `[${value[0]?.constructor.name}]` : value.constructor.name; + console.warn( + `UEBlueprint: Attribute ${key} (of type ${typeName}) in the serialized data is not defined in ${Self.name}.attributes` + ); + } + } + if (!(key in Self.attributes)) { + // Remember attributeName can come from the values and be not defined in the attributes. + // In that case just assign it and skip the rest. + this[key] = value; + continue + } + Self.attributes.lookbehind; + const predicate = AttributeInfo.getAttribute(values, key, "predicate", Self); + const assignAttribute = !predicate + ? v => this[key] = v + : v => { + Object.defineProperties(this, { + ["#" + key]: { + writable: true, + enumerable: false, + }, + [key]: { + enumerable: true, + get() { + return this["#" + key] + }, + set(v) { + if (!predicate(v)) { + console.warn( + `UEBlueprint: Tried to assign attribute ${key} to ${Self.name} not satisfying the predicate` + ); + return + } + this["#" + key] = v; + } + }, + }); + this[key] = v; + }; + + let defaultValue = AttributeInfo.getAttribute(values, key, "default", Self); + if (defaultValue instanceof Function) { + defaultValue = defaultValue(this); + } + let defaultType = AttributeInfo.getAttribute(values, key, "type", Self); + if (defaultType instanceof ComputedType) { + defaultType = defaultType.compute(this); + } + if (defaultType instanceof Array) { + defaultType = Array; + } + if (defaultType === undefined) { + defaultType = Utility.getType(defaultValue); + } + + if (value !== undefined) { + // Remember value can still be null + if ( + value?.constructor === String + && AttributeInfo.getAttribute(values, key, "serialized", Self) + && defaultType !== String + ) { + try { + value = SerializerFactory + .getSerializer(defaultType) + .read(/** @type {String} */(value)); + } catch (e) { + assignAttribute(value); + continue + } + } + assignAttribute(Utility.sanitize(value, /** @type {AttributeConstructor} */(defaultType))); + continue // We have a value, need nothing more + } + if (defaultValue !== undefined) { + assignAttribute(defaultValue); + } + } + } + + /** @param {AttributeTypeDescription} attributeType */ + static defaultValueProviderFromType(attributeType) { + if (attributeType === Boolean) { + return false + } else if (attributeType === Number) { + return 0 + } else if (attributeType === BigInt) { + return 0n + } else if (attributeType === String) { + return "" + } else if (attributeType === Array || attributeType instanceof Array) { + return () => [] + } else if (attributeType instanceof Union) { + return this.defaultValueProviderFromType(attributeType.values[0]) + } else if (attributeType instanceof MirroredEntity) { + return () => new MirroredEntity(attributeType.type, attributeType.getter) + } else if (attributeType instanceof ComputedType) { + return undefined + } else { + return () => new /** @type {AnyConstructor} */(attributeType)() + } + } + + /** + * @template {new (...args: any) => any} C + * @param {C} type + * @returns {value is InstanceType} + */ + static isValueOfType(value, type) { + return value != null && (value instanceof type || value.constructor === type) + } + + static expectsAllKeys() { + return !Object.values(this.attributes) + .filter(/** @param {AttributeInformation} attribute */attribute => !attribute.ignored) + .some(/** @param {AttributeInformation} attribute */attribute => !attribute.expected) + } + + static getAttribute(object, attribute) { + return this.getAttributes(object)[attribute] + } + + /** @returns {AttributeDeclarations} */ + static getAttributes(object) { + return object.attributes ?? object.constructor?.attributes ?? {} + } + + static defineAttributes(object, attributes) { + Object.defineProperty(object, "attributes", { + writable: true, + configurable: false, + }); + object.attributes = attributes; + } + + getLookbehind() { + let lookbehind = this.lookbehind ?? AttributeInfo.getAttribute(this, "lookbehind", "default"); + lookbehind = lookbehind instanceof Union ? lookbehind.values[0] : lookbehind; + return lookbehind + } + + unexpectedKeys() { + return Object.keys(this).length - Object.keys(/** @type {typeof IEntity} */(this.constructor).attributes).length + } + + /** @param {IEntity} other */ + equals(other) { + const thisKeys = Object.keys(this); + const otherKeys = Object.keys(other); + if (thisKeys.length != otherKeys.length) { + return false + } + for (const key of thisKeys) { + if (this[key] instanceof IEntity && !this[key].equals(other[key])) { + return false + } else if (!Utility.equals(this[key], other[key])) { + return false + } + } + return true + } +} + +class Grammar { + + static separatedBy = (source, separator, min = 1) => + new RegExp( + source + "(?:" + separator + source + ")" + + (min === 1 ? "*" : min === 2 ? "+" : `{${min},}`) + ) + + static Regex = class { + static HexDigit = /[0-9a-fA-F]/ + static InsideString = /(?:[^"\\]|\\.)*/ + static InsideSingleQuotedString = /(?:[^'\\]|\\.)*/ + static Integer = /[\-\+]?\d+(?!\d|\.)/ + static Number = /[-\+]?(?:\d*\.)?\d+(?!\d|\.)/ + static RealUnit = /\+?(?:0(?:\.\d+)?|1(?:\.0+)?)(?![\.\d])/ // A number between 0 and 1 included + static Word = Grammar.separatedBy("[a-zA-Z]", "_") + static Symbol = /[a-zA-Z_]\w*/ + static DotSeparatedSymbols = Grammar.separatedBy(this.Symbol.source, "\\.") + static PathFragment = Grammar.separatedBy(this.Symbol.source, "[\\.:]") + static PathSpaceFragment = Grammar.separatedBy(this.Symbol.source, "[\\.:\\ ]") + static Path = new RegExp(`(?:\\/${this.PathFragment.source}){2,}`) // Multiple (2+) /PathFragment + } + + /* --- Primitive --- */ + + static null = Parsernostrum.reg(/\(\s*\)/).map(() => null) + static true = Parsernostrum.reg(/true/i).map(() => true) + static false = Parsernostrum.reg(/false/i).map(() => false) + static boolean = Parsernostrum.regArray(/(true)|false/i).map(v => v[1] ? true : false) + static number = Parsernostrum.regArray( + new RegExp(`(${Parsernostrum.number.getParser().parser.regexp.source})|(\\+?inf)|(-inf)`) + ).map(([_0, n, plusInf, minusInf]) => n ? Number(n) : plusInf ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY) + static bigInt = Parsernostrum.reg(new RegExp(Parsernostrum.number.getParser().parser.regexp.source)).map(BigInt) + .map(result => + result[2] !== undefined + ? Number.POSITIVE_INFINITY + : result[3] !== undefined + ? Number.NEGATIVE_INFINITY + : Number(result[1]) + ) + static naturalNumber = Parsernostrum.lazy(() => Parsernostrum.reg(/\d+/).map(Number)) + static string = Parsernostrum.doubleQuotedString.map(insideString => Utility.unescapeString(insideString)) + + /* --- Fragment --- */ + + static colorValue = Parsernostrum.numberByte + static word = Parsernostrum.reg(Grammar.Regex.Word) + static symbol = Parsernostrum.reg(Grammar.Regex.Symbol) + static symbolQuoted = Parsernostrum.reg(new RegExp('"(' + Grammar.Regex.Symbol.source + ')"'), 1) + static attributeName = Parsernostrum.reg(Grammar.Regex.DotSeparatedSymbols) + static attributeNameQuoted = Parsernostrum.reg(new RegExp('"(' + Grammar.Regex.DotSeparatedSymbols.source + ')"'), 1) + static guid = Parsernostrum.reg(new RegExp(`${Grammar.Regex.HexDigit.source}{32}`)) + static commaSeparation = Parsernostrum.reg(/\s*,\s*(?!\))/) + static commaOrSpaceSeparation = Parsernostrum.reg(/\s*,\s*(?!\))|\s+/) + static equalSeparation = Parsernostrum.reg(/\s*=\s*/) + static hexColorChannel = Parsernostrum.reg(new RegExp(Grammar.Regex.HexDigit.source + "{2}")) + + /* --- Factory --- */ + + /** + * @template T + * @param {AttributeInfo} attribute + */ + static grammarFor(attribute, type = attribute?.type, defaultGrammar = this.unknownValue) { + let result = defaultGrammar; + if (type instanceof Array) { + if (attribute?.inlined) { + return this.grammarFor(undefined, type[0]) + } + result = Parsernostrum.seq( + Parsernostrum.reg(/\(\s*/), + this.grammarFor(undefined, type[0]).sepBy(this.commaSeparation), + Parsernostrum.reg(/\s*(?:,\s*)?\)/), + ).map(([_0, values, _3]) => values); + } else if (type instanceof Union) { + result = type.values + .map(v => this.grammarFor(undefined, v)) + .reduce((acc, cur) => !cur || cur === this.unknownValue || acc === this.unknownValue + ? this.unknownValue + : Parsernostrum.alt(acc, cur) + ); + } else if (type instanceof MirroredEntity) { + return this.grammarFor(undefined, type.getTargetType()) + .map(v => new MirroredEntity(type.type, () => v)) + } else if (attribute?.constructor === Object) { + result = this.grammarFor(undefined, type); + } else { + switch (type) { + case Boolean: + result = this.boolean; + break + case null: + result = this.null; + break + case Number: + result = this.number; + break + case BigInt: + result = this.bigInt; + break + case String: + result = this.string; + break + default: + if (/** @type {AttributeConstructor} */(type)?.prototype instanceof Serializable) { + result = /** @type {typeof Serializable} */(type).grammar; + } + } + } + if (attribute) { + if (attribute.serialized && type.constructor !== String) { + if (result == this.unknownValue) { + result = this.string; + } else { + result = Parsernostrum.seq(Parsernostrum.str('"'), result, Parsernostrum.str('"')); + } + } + if (attribute.nullable) { + result = Parsernostrum.alt(result, this.null); + } + } + return result + } + + /** + * @template {AttributeConstructor} T + * @param {T} entityType + * @param {String[]} key + * @returns {AttributeInfo} + */ + static getAttribute(entityType, key) { + let result; + let type; + if (entityType instanceof Union) { + for (let t of entityType.values) { + if (result = this.getAttribute(t, key)) { + return result + } + } + } + if (entityType instanceof IEntity.constructor) { + // @ts-expect-error + result = entityType.attributes[key[0]]; + type = result?.type; + } else if (entityType instanceof Array) { + result = entityType[key[0]]; + type = result; + } + if (key.length > 1) { + return this.getAttribute(type, key.slice(1)) + } + return result + } + + static createAttributeGrammar( + entityType, + attributeName = this.attributeName, + valueSeparator = this.equalSeparation, + handleObjectSet = (obj, k, v) => { } + ) { + return Parsernostrum.seq( + attributeName, + valueSeparator, + ).chain(([attributeName, _1]) => { + const attributeKey = attributeName.split(Configuration.keysSeparator); + const attributeValue = this.getAttribute(entityType, attributeKey); + return this + .grammarFor(attributeValue) + .map(attributeValue => + values => { + handleObjectSet(values, attributeKey, attributeValue); + Utility.objectSet(values, attributeKey, attributeValue); + } + ) + }) + } + + /** + * @template {IEntity} T + * @param {(new (...args: any) => T) & EntityConstructor} entityType + * @param {Boolean | Number} acceptUnknownKeys Number to specify the limit or true, to let it be a reasonable value + */ + static createEntityGrammar(entityType, acceptUnknownKeys = true, entriesSeparator = this.commaSeparation) { + const lookbehind = entityType.attributes.lookbehind.default; + return Parsernostrum.seq( + Parsernostrum.reg( + lookbehind instanceof Union + ? new RegExp(`(${lookbehind.values.reduce((acc, cur) => acc + "|" + cur)})\\s*\\(\\s*`) + : lookbehind.constructor == String && lookbehind.length > 0 + ? new RegExp(`(${lookbehind})\\s*\\(\\s*`) + : /()\(\s*/, + 1 + ), + this.createAttributeGrammar(entityType).sepBy(entriesSeparator), + Parsernostrum.reg(/\s*(?:,\s*)?\)/), // trailing comma + ) + .map(([lookbehind, attributes, _2]) => { + let values = {}; + attributes.forEach(attributeSetter => attributeSetter(values)); + if (lookbehind.length) { + values.lookbehind = lookbehind; + } + return values + }) + // Decide if we accept the entity or not. It is accepted if it doesn't have too many unexpected keys + .chain(values => { + let totalKeys = Object.keys(values); + // Check missing values + if ( + Object.keys(/** @type {AttributeDeclarations} */(entityType.attributes)) + .filter(key => entityType.attributes[key].expected) + .find(key => !totalKeys.includes(key) && (key)) + ) { + return Parsernostrum.failure() + } + const unknownKeys = Object.keys(values).filter(key => !(key in entityType.attributes)).length; + if (!acceptUnknownKeys && unknownKeys > 0) { + return Parsernostrum.failure() + } + return Parsernostrum.success().map(() => new entityType(values)) + }) + } + + /* --- Entity --- */ + + static unknownValue // Defined in initializeSerializerFactor to avoid circular include +} + +var crypto; +if (typeof window === "undefined") { + import('crypto').then(mod => crypto = mod.default).catch(); +} else { + crypto = window.crypto; +} + +class GuidEntity extends IEntity { + + static attributes = { + ...super.attributes, + value: AttributeInfo.createValue(""), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Grammar.guid.map(v => new this(v)) + } + + static generateGuid(random = true) { + let values = new Uint32Array(4); + if (random === true) { + crypto.getRandomValues(values); + } + let guid = ""; + values.forEach(n => { + guid += ("0".repeat(8) + n.toString(16).toUpperCase()).slice(-8); + }); + return new GuidEntity({ value: guid }) + } + + constructor(values) { + if (!values) { + values = GuidEntity.generateGuid().value; + } + if (values.constructor !== Object) { + values = { + value: values, + }; + } + super(values); + /** @type {String} */ this.value; + } + + valueOf() { + return this.value + } + + toString() { + return this.value + } +} + +class ObjectReferenceEntity extends IEntity { + + static attributes = { + ...super.attributes, + type: new AttributeInfo({ + default: "", + serialized: true, + }), + path: new AttributeInfo({ + default: "", + serialized: true, + }), + } + static quoted = Parsernostrum.regArray(new RegExp( + `'"(` + Grammar.Regex.InsideString.source + `)"'` + + `|'(` + Grammar.Regex.InsideSingleQuotedString.source + `)'` + + `|"(` + Grammar.Regex.InsideString.source + `)"` + )).map(([_0, a, b, c]) => a ?? b ?? c) + static path = this.quoted.getParser().parser.regexp.source + "|" + Grammar.Regex.Path.source + static typeReference = Parsernostrum.reg( + new RegExp(Grammar.Regex.Path.source + "|" + Grammar.symbol.getParser().regexp.source) + ) + static fullReferenceGrammar = Parsernostrum.regArray( + new RegExp( + "(" + this.typeReference.getParser().regexp.source + ")" + + /\s*/.source + + "(?:" + this.quoted.getParser().parser.regexp.source + ")" + ) + ).map(([_0, type, ...path]) => new this({ type, path: path.find(v => v) })) + static fullReferenceSerializedGrammar = Parsernostrum.regArray( + new RegExp( + "(" + this.typeReference.getParser().regexp.source + ")" + + /\s*/.source + + `'(` + Grammar.Regex.InsideSingleQuotedString.source + `)'` + ) + ).map(([_0, type, ...path]) => new this({ type, path: path.find(v => v) })) + static typeReferenceGrammar = this.typeReference.map(v => new this({ type: v, path: "" })) + static grammar = this.createGrammar() + + static createGrammar() { + return Parsernostrum.alt( + Parsernostrum.seq( + Parsernostrum.str('"'), + Parsernostrum.alt( + this.fullReferenceSerializedGrammar, + this.typeReferenceGrammar, + ), + Parsernostrum.str('"'), + ).map(([_0, objectReference, _1]) => objectReference), + this.fullReferenceGrammar.map(v => (Utility.objectSet(v, ["attributes", "type", "serialized"], false), v)), + this.typeReferenceGrammar.map(v => (Utility.objectSet(v, ["attributes", "type", "serialized"], false), v)), + ) + } + + constructor(values = {}) { + if (values.constructor === String) { + values = { + path: values + }; + } + super(values); + /** @type {String} */ this.type; + /** @type {String} */ this.path; + } + + static createNoneInstance() { + return new ObjectReferenceEntity({ type: "None", path: "" }) + } + + sanitize() { + if (this.type && !this.type.startsWith("/")) { + let deprecatedType = this.type + "_Deprecated"; + let path = Object.keys(Configuration.paths) + .find(type => { + const name = Utility.getNameFromPath(Configuration.paths[type]); + return name === this.type || name === deprecatedType + }); + if (path) { + this.type = Configuration.paths[path]; + } + } + } + + getName() { + return Utility.getNameFromPath(this.path.replace(/_C$/, "")) + } + + toString() { + return this.type + (this.path ? `'${this.path}'` : "") + } +} + +class FunctionReferenceEntity extends IEntity { + + static attributes = { + ...super.attributes, + MemberParent: AttributeInfo.createType(ObjectReferenceEntity), + MemberName: AttributeInfo.createType(String), + MemberGuid: AttributeInfo.createType(GuidEntity), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Grammar.createEntityGrammar(this) + } + + constructor(values) { + super(values); + /** @type {ObjectReferenceEntity} */ this.MemberParent; + /** @type {String} */ this.MemberName; + /** @type {GuidEntity} */ this.MemberGuid; + } +} + +class IdentifierEntity extends IEntity { + + static attributes = { + ...super.attributes, + value: AttributeInfo.createValue(""), + } + static attributeConverter = { + fromAttribute: (value, type) => new IdentifierEntity(value), + toAttribute: (value, type) => value.toString() + } + static grammar = this.createGrammar() + + static createGrammar() { + return Grammar.symbol.map(v => new this(v)) + } + + constructor(values) { + if (values.constructor !== Object) { + values = { + value: values, + }; + } + super(values); + /** @type {String} */ this.value; + } + + valueOf() { + return this.value + } + + toString() { + return this.value + } +} + +class IntegerEntity extends IEntity { + + static attributes = { + ...super.attributes, + value: new AttributeInfo({ + default: 0, + predicate: v => v % 1 == 0 && v > 1 << 31 && v < -(1 << 31), + }), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Parsernostrum.numberInteger.map(v => new this(v)) + } + + /** @param {Number | AttributeInfo} value */ + constructor(value = 0) { + if (value === -0) { + value = 0; + } + super(value.constructor === Object + ? value + : { + value: value, + } + ); + /** @type {Number} */ this.value; + } + + valueOf() { + return this.value + } + + toString() { + return this.value.toString() + } +} + +class ColorChannelEntity extends IEntity { + + static attributes = { + ...super.attributes, + value: AttributeInfo.createValue(0), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Parsernostrum.number.map(value => new this(value)) + } + + constructor(values = 0) { + if (values.constructor !== Object) { + // @ts-expect-error + values = { + value: values, + }; + } + super(values); + /** @type {Number} */ this.value; + } + + valueOf() { + return this.value + } + + toString() { + return this.value.toFixed(6) + } +} + +class LinearColorEntity extends IEntity { + + static attributes = { + ...super.attributes, + R: new AttributeInfo({ + type: ColorChannelEntity, + default: () => new ColorChannelEntity(), + expected: true, + }), + G: new AttributeInfo({ + type: ColorChannelEntity, + default: () => new ColorChannelEntity(), + expected: true, + }), + B: new AttributeInfo({ + type: ColorChannelEntity, + default: () => new ColorChannelEntity(), + expected: true, + }), + A: new AttributeInfo({ + type: ColorChannelEntity, + default: () => new ColorChannelEntity(1), + }), + H: new AttributeInfo({ + type: ColorChannelEntity, + default: () => new ColorChannelEntity(), + ignored: true, + }), + S: new AttributeInfo({ + type: ColorChannelEntity, + default: () => new ColorChannelEntity(), + ignored: true, + }), + V: new AttributeInfo({ + type: ColorChannelEntity, + default: () => new ColorChannelEntity(), + ignored: true, + }), + } + static grammar = this.createGrammar() + + /** @param {Number} x */ + static linearToSRGB(x) { + if (x <= 0) { + return 0 + } else if (x >= 1) { + return 1 + } else if (x < 0.0031308) { + return x * 12.92 + } else { + return Math.pow(x, 1 / 2.4) * 1.055 - 0.055 + } + } + + /** @param {Number} x */ + static sRGBtoLinear(x) { + if (x <= 0) { + return 0 + } else if (x >= 1) { + return 1 + } else if (x < 0.04045) { + return x / 12.92 + } else { + return Math.pow((x + 0.055) / 1.055, 2.4) + } + } + + static getWhite() { + return new LinearColorEntity({ + R: 1, + G: 1, + B: 1, + }) + } + + static createGrammar() { + return Grammar.createEntityGrammar(this, false) + } + + static getLinearColorFromHexGrammar() { + return Parsernostrum.regArray(new RegExp( + "#(" + Grammar.Regex.HexDigit.source + "{2})" + + "(" + Grammar.Regex.HexDigit.source + "{2})" + + "(" + Grammar.Regex.HexDigit.source + "{2})" + + "(" + Grammar.Regex.HexDigit.source + "{2})?" + )).map(([m, R, G, B, A]) => new this({ + R: parseInt(R, 16) / 255, + G: parseInt(G, 16) / 255, + B: parseInt(B, 16) / 255, + A: parseInt(A ?? "FF", 16) / 255, + })) + } + + static getLinearColorRGBListGrammar() { + return Parsernostrum.seq( + Parsernostrum.numberByte, + Grammar.commaSeparation, + Parsernostrum.numberByte, + Grammar.commaSeparation, + Parsernostrum.numberByte, + ).map(([R, _1, G, _3, B]) => new this({ + R: R / 255, + G: G / 255, + B: B / 255, + A: 1, + })) + } + + static getLinearColorRGBGrammar() { + return Parsernostrum.seq( + Parsernostrum.reg(/rgb\s*\(\s*/), + this.getLinearColorRGBListGrammar(), + Parsernostrum.reg(/\s*\)/) + ).map(([_0, linearColor, _2]) => linearColor) + } + + static getLinearColorRGBAGrammar() { + return Parsernostrum.seq( + Parsernostrum.reg(/rgba\s*\(\s*/), + this.getLinearColorRGBListGrammar(), + Parsernostrum.reg(/\s*\)/) + ).map(([_0, linearColor, _2]) => linearColor) + } + + static getLinearColorFromAnyFormat() { + return Parsernostrum.alt( + this.getLinearColorFromHexGrammar(), + this.getLinearColorRGBAGrammar(), + this.getLinearColorRGBGrammar(), + this.getLinearColorRGBListGrammar(), + ) + } + + constructor(values) { + if (values instanceof Array) { + values = { + R: values[0] ?? 0, + G: values[1] ?? 0, + B: values[2] ?? 0, + A: values[3] ?? 1, + }; + } + super(values); + /** @type {ColorChannelEntity} */ this.R; + /** @type {ColorChannelEntity} */ this.G; + /** @type {ColorChannelEntity} */ this.B; + /** @type {ColorChannelEntity} */ this.A; + /** @type {ColorChannelEntity} */ this.H; + /** @type {ColorChannelEntity} */ this.S; + /** @type {ColorChannelEntity} */ this.V; + this.#updateHSV(); + } + + #updateHSV() { + const r = this.R.value; + const g = this.G.value; + const b = this.B.value; + if (Utility.approximatelyEqual(r, g) && Utility.approximatelyEqual(r, b) && Utility.approximatelyEqual(g, b)) { + this.S.value = 0; + this.V.value = r; + return + } + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + const d = max - min; + let h; + switch (max) { + case min: + h = 0; + break + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break + case g: + h = (b - r) / d + 2; + break + case b: + h = (r - g) / d + 4; + break + } + h /= 6; + this.H.value = h; + this.S.value = max == 0 ? 0 : d / max; + this.V.value = max; + } + + /** + * @param {Number} r + * @param {Number} g + * @param {Number} b + * @param {Number} a + */ + setFromRGBA(r, g, b, a = 1) { + this.R.value = r; + this.G.value = g; + this.B.value = b; + this.A.value = a; + this.#updateHSV(); + } + + /** + * @param {Number} h + * @param {Number} s + * @param {Number} v + * @param {Number} a + */ + setFromHSVA(h, s, v, a = 1) { + const i = Math.floor(h * 6); + const f = h * 6 - i; + const p = v * (1 - s); + const q = v * (1 - f * s); + const t = v * (1 - (1 - f) * s); + const values = [v, q, p, p, t, v]; + const [r, g, b] = [values[i % 6], values[(i + 4) % 6], values[(i + 2) % 6]]; + this.R.value = r; + this.G.value = g; + this.B.value = b; + this.A.value = a; + this.H.value = h; + this.S.value = s; + this.V.value = v; + } + + /** + * @param {Number} x + * @param {Number} y + * @param {Number} v + * @param {Number} a + */ + setFromWheelLocation(x, y, v, a) { + const [r, theta] = Utility.getPolarCoordinates(x, y, true); + this.setFromHSVA(1 - theta / (2 * Math.PI), r, v, a); + } + + toDimmedColor(minV = 0) { + const result = new LinearColorEntity(); + result.setFromRGBANumber(this.toNumber()); + result.setFromHSVA( + result.H.value, + result.S.value * 0.6, + Math.pow(result.V.value + minV, 0.55) * 0.7 + ); + return result + } + + toCSSRGBValues() { + const r = Math.round(this.R.value * 255); + const g = Math.round(this.G.value * 255); + const b = Math.round(this.B.value * 255); + return i$3`${r}, ${g}, ${b}` + } + + toRGBA() { + return [ + Math.round(this.R.value * 255), + Math.round(this.G.value * 255), + Math.round(this.B.value * 255), + Math.round(this.A.value * 255), + ] + } + + toSRGBA() { + return [ + Math.round(LinearColorEntity.linearToSRGB(this.R.value) * 255), + Math.round(LinearColorEntity.linearToSRGB(this.G.value) * 255), + Math.round(LinearColorEntity.linearToSRGB(this.B.value) * 255), + Math.round(this.A.value * 255), + ] + } + + toRGBAString() { + return this + .toRGBA() + .map(v => v.toString(16).toUpperCase().padStart(2, "0")) + .join("") + } + + toSRGBAString() { + return this + .toSRGBA() + .map(v => v.toString(16).toUpperCase().padStart(2, "0")) + .join("") + } + + toHSVA() { + return [this.H.value, this.S.value, this.V.value, this.A.value] + } + + toNumber() { + return ( + Math.round(this.R.value * 0xff) << 24) + + (Math.round(this.G.value * 0xff) << 16) + + (Math.round(this.B.value * 0xff) << 8) + + Math.round(this.A.value * 0xff) + } + + /** @param {Number} number */ + setFromRGBANumber(number) { + this.A.value = (number & 0xff) / 0xff; + this.B.value = ((number >> 8) & 0xff) / 0xff; + this.G.value = ((number >> 16) & 0xff) / 0xff; + this.R.value = ((number >> 24) & 0xff) / 0xff; + this.#updateHSV(); + } + + /** @param {Number} number */ + setFromSRGBANumber(number) { + this.A.value = (number & 0xff) / 0xff; + this.B.value = LinearColorEntity.sRGBtoLinear(((number >> 8) & 0xff) / 0xff); + this.G.value = LinearColorEntity.sRGBtoLinear(((number >> 16) & 0xff) / 0xff); + this.R.value = LinearColorEntity.sRGBtoLinear(((number >> 24) & 0xff) / 0xff); + this.#updateHSV(); + } + + /** @returns {[Number, Number, Number, Number]} */ + toArray() { + return [this.R.value, this.G.value, this.B.value, this.A.value] + } + + toString() { + return Utility.printLinearColor(this) + } +} + +class MacroGraphReferenceEntity extends IEntity { + + static attributes = { + ...super.attributes, + MacroGraph: new AttributeInfo({ + type: ObjectReferenceEntity, + default: () => new ObjectReferenceEntity(), + }), + GraphBlueprint: new AttributeInfo({ + type: ObjectReferenceEntity, + default: () => new ObjectReferenceEntity(), + }), + GraphGuid: new AttributeInfo({ + type: GuidEntity, + default: () => new GuidEntity(), + }), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Grammar.createEntityGrammar(this) + } + + constructor(values) { + super(values); + /** @type {ObjectReferenceEntity} */ this.MacroGraph; + /** @type {ObjectReferenceEntity} */ this.GraphBlueprint; + /** @type {GuidEntity} */ this.GuidEntity; + } + + getMacroName() { + const colonIndex = this.MacroGraph.path.search(":"); + return this.MacroGraph.path.substring(colonIndex + 1) + } +} + +class ByteEntity extends IntegerEntity { + + static attributes = { + ...super.attributes, + value: new AttributeInfo({ + ...super.attributes.value, + predicate: v => v % 1 == 0 && v >= 0 && v < 1 << 8, + }), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Parsernostrum.numberByte.map(v => new this(v)) + } + + constructor(values = 0) { + super(values); + } +} + +class SymbolEntity extends IEntity { + + static attributes = { + ...super.attributes, + value: AttributeInfo.createValue(""), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Grammar.symbol.map(v => new this(v)) + } + + /** @param {String | Object} values */ + constructor(values) { + if (values.constructor !== Object) { + values = { + value: values, + }; + } + super(values); + /** @type {String} */ this.value; + } + + valueOf() { + return this.value + } + + toString() { + return this.value + } +} + +class EnumEntity extends SymbolEntity { + + static grammar = this.createGrammar() + + static createGrammar() { + return Grammar.symbol.map(v => new this(v)) + } +} + +class EnumDisplayValueEntity extends EnumEntity { + + static grammar = this.createGrammar() + + static createGrammar() { + return Parsernostrum.reg(Grammar.Regex.InsideString).map(v => new this(v)) + } +} + +class InvariantTextEntity extends IEntity { + + static attributes = { + ...super.attributes, + value: AttributeInfo.createValue(""), + lookbehind: new AttributeInfo({ + ...super.attributes.lookbehind, + default: "INVTEXT", + }), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Parsernostrum.alt( + Parsernostrum.seq( + Parsernostrum.reg(new RegExp(`${this.attributes.lookbehind.default}\\s*\\(`)), + Grammar.grammarFor(this.attributes.value), + Parsernostrum.reg(/\s*\)/) + ) + .map(([_0, value, _2]) => value), + Parsernostrum.reg(new RegExp(this.attributes.lookbehind.default)) // InvariantTextEntity can not have arguments + .map(() => "") + ).map(value => new this(value)) + } + + constructor(values) { + if (values.constructor !== Object) { + values = { + value: values, + }; + } + super(values); + /** @type {String} */ this.value; + } +} + +class LocalizedTextEntity extends IEntity { + + static attributes = { + ...super.attributes, + namespace: AttributeInfo.createValue(""), + key: AttributeInfo.createValue(""), + value: AttributeInfo.createValue(""), + lookbehind: new AttributeInfo({ + ...super.attributes.lookbehind, + default: "NSLOCTEXT", + }), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Parsernostrum.regArray(new RegExp( + String.raw`${this.attributes.lookbehind.default}\s*\(` + + String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*,` + + String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*,` + + String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*` + + String.raw`(?:,\s+)?` + + String.raw`\)`, + "m" + )).map(matchResult => new this({ + namespace: Utility.unescapeString(matchResult[1]), + key: Utility.unescapeString(matchResult[2]), + value: Utility.unescapeString(matchResult[3]), + })) + } + + constructor(values) { + super(values); + /** @type {String} */ this.namespace; + /** @type {String} */ this.key; + /** @type {String} */ this.value; + } + + toString() { + return Utility.capitalFirstLetter(this.value) + } +} + +class FormatTextEntity extends IEntity { + + static attributes = { + ...super.attributes, + value: new AttributeInfo({ + type: [new Union(String, LocalizedTextEntity, InvariantTextEntity, FormatTextEntity)], + default: [], + }), + lookbehind: /** @type {AttributeInfo>} */(new AttributeInfo({ + ...super.attributes.lookbehind, + default: new Union("LOCGEN_FORMAT_NAMED", "LOCGEN_FORMAT_ORDERED"), + })), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Parsernostrum.seq( + Parsernostrum.reg( + // Resulting regex: /(LOCGEN_FORMAT_NAMED|LOCGEN_FORMAT_ORDERED)\s*/ + new RegExp(`(${this.attributes.lookbehind.default.values.reduce((acc, cur) => acc + "|" + cur)})\\s*`), + 1 + ), + Grammar.grammarFor(this.attributes.value) + ) + .map(([lookbehind, values]) => { + const result = new this({ + value: values, + lookbehind, + }); + return result + }) + } + + constructor(values) { + super(values); + /** @type {(String | LocalizedTextEntity | InvariantTextEntity | FormatTextEntity)[]} */ this.value; + } + + toString() { + const pattern = this.value?.[0]?.toString(); // The pattern is always the first element of the array + if (!pattern) { + return "" + } + const values = this.value.slice(1).map(v => v.toString()); + return this.lookbehind == "LOCGEN_FORMAT_NAMED" + ? pattern.replaceAll(/\{([a-zA-Z]\w*)\}/g, (substring, arg) => { + const argLocation = values.indexOf(arg) + 1; + return argLocation > 0 && argLocation < values.length + ? values[argLocation] + : substring + }) + : this.lookbehind == "LOCGEN_FORMAT_ORDERED" + ? pattern.replaceAll(/\{(\d+)\}/g, (substring, arg) => { + const argValue = Number(arg); + return argValue < values.length + ? values[argValue] + : substring + }) + : "" + } +} + +class Integer64Entity extends IEntity { + + static attributes = { + ...super.attributes, + value: new AttributeInfo({ + default: 0n, + predicate: v => v >= -(1n << 63n) && v < 1n << 63n, + }), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Parsernostrum.numberBigInteger.map(v => new this(v)) + } + + /** @param {BigInt | Number} value */ + constructor(value = 0) { + if (value.constructor !== Object) { + value = { + // @ts-expect-error + value: value, + }; + } + super(value); + /** @type {BigInt | Number} */ this.value; + } + + valueOf() { + return this.value + } + + toString() { + return this.value.toString() + } +} + +class PathSymbolEntity extends IEntity { + + static attributes = { + ...super.attributes, + value: new AttributeInfo({ + default: "", + }), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Grammar.symbol.map(v => new this(v)) + } + + constructor(values) { + if (values.constructor !== Object) { + values = { + value: values, + }; + } + super(values); + /** @type {String} */ this.value; + } + + valueOf() { + return this.value + } + + toString() { + return this.value + } +} + +class PinReferenceEntity extends IEntity { + + static attributes = { + ...super.attributes, + objectName: AttributeInfo.createType(PathSymbolEntity), + pinGuid: AttributeInfo.createType(GuidEntity), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Parsernostrum.seq( + PathSymbolEntity.createGrammar(), + Parsernostrum.whitespace, + GuidEntity.createGrammar() + ).map( + ([objectName, _1, pinGuid]) => new this({ + objectName: objectName, + pinGuid: pinGuid, + }) + ) + } + + constructor(values) { + super(values); + /** @type {PathSymbolEntity} */ this.objectName; + /** @type {GuidEntity} */ this.pinGuid; + } +} + +class PinTypeEntity extends IEntity { + + static attributes = { + ...super.attributes, + PinCategory: AttributeInfo.createValue(""), + PinSubCategory: AttributeInfo.createValue(""), + PinSubCategoryObject: new AttributeInfo({ + type: ObjectReferenceEntity, + default: () => ObjectReferenceEntity.createNoneInstance(), + }), + PinSubCategoryMemberReference: new AttributeInfo({ + type: FunctionReferenceEntity, + default: null, + }), + PinValueType: new AttributeInfo({ + type: PinTypeEntity, + default: null, + }), + ContainerType: AttributeInfo.createType(PathSymbolEntity), + bIsReference: AttributeInfo.createValue(false), + bIsConst: AttributeInfo.createValue(false), + bIsWeakPointer: AttributeInfo.createValue(false), + bIsUObjectWrapper: AttributeInfo.createValue(false), + bSerializeAsSinglePrecisionFloat: AttributeInfo.createValue(false), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Grammar.createEntityGrammar(this) + } + + constructor(values = {}, suppressWarns = false) { + super(values, suppressWarns); + /** @type {String} */ this.PinCategory; + /** @type {String} */ this.PinSubCategory; + /** @type {ObjectReferenceEntity} */ this.PinSubCategoryObject; + /** @type {FunctionReferenceEntity} */ this.PinSubCategoryMemberReference; + /** @type {PinTypeEntity} */ this.PinValueType; + /** @type {PathSymbolEntity} */ this.ContainerType; + /** @type {Boolean} */ this.bIsReference; + /** @type {Boolean} */ this.bIsConst; + /** @type {Boolean} */ this.bIsWeakPointer; + /** @type {Boolean} */ this.bIsUObjectWrapper; + /** @type {Boolean} */ this.bIsUObjectWrapper; + /** @type {Boolean} */ this.bSerializeAsSinglePrecisionFloat; + } + + /** @param {PinTypeEntity} other */ + copyTypeFrom(other) { + this.PinCategory = other.PinCategory; + this.PinSubCategory = other.PinSubCategory; + this.PinSubCategoryObject = other.PinSubCategoryObject; + this.PinSubCategoryMemberReference = other.PinSubCategoryMemberReference; + this.PinValueType = other.PinValueType; + this.ContainerType = other.ContainerType; + this.bIsReference = other.bIsReference; + this.bIsConst = other.bIsConst; + this.bIsWeakPointer = other.bIsWeakPointer; + this.bIsUObjectWrapper = other.bIsUObjectWrapper; + this.bSerializeAsSinglePrecisionFloat = other.bSerializeAsSinglePrecisionFloat; + } +} + +class Vector2DEntity extends IEntity { + + static attributes = { + ...super.attributes, + X: new AttributeInfo({ + default: 0, + expected: true, + }), + Y: new AttributeInfo({ + default: 0, + expected: true, + }), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Grammar.createEntityGrammar(this, false) + } + + constructor(values) { + super(values); + /** @type {Number} */ this.X; + /** @type {Number} */ this.Y; + } + + /** @returns {[Number, Number]} */ + toArray() { + return [this.X, this.Y] + } +} + +class RBSerializationVector2DEntity extends Vector2DEntity { + + static grammar = this.createGrammar() + + static createGrammar() { + return Parsernostrum.alt( + Parsernostrum.regArray(new RegExp( + /X\s*=\s*/.source + "(?" + Parsernostrum.number.getParser().parser.regexp.source + ")" + + "\\s+" + + /Y\s*=\s*/.source + "(?" + Parsernostrum.number.getParser().parser.regexp.source + ")" + )).map(({ groups: { x, y } }) => new this({ + X: Number(x), + Y: Number(y), + })), + Vector2DEntity.createGrammar() + ) + } +} + +class RotatorEntity extends IEntity { + + static attributes = { + ...super.attributes, + R: new AttributeInfo({ + default: 0, + expected: true, + }), + P: new AttributeInfo({ + default: 0, + expected: true, + }), + Y: new AttributeInfo({ + default: 0, + expected: true, + }), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Grammar.createEntityGrammar(this, false) + } + + constructor(values) { + super(values); + /** @type {Number} */ this.R; + /** @type {Number} */ this.P; + /** @type {Number} */ this.Y; + } + + getRoll() { + return this.R + } + + getPitch() { + return this.P + } + + getYaw() { + return this.Y + } +} + +class SimpleSerializationRotatorEntity extends RotatorEntity { + + static grammar = this.createGrammar() + + static createGrammar() { + const number = Parsernostrum.number.getParser().parser.regexp.source; + return Parsernostrum.alt( + Parsernostrum.reg(new RegExp( + "(" + number + ")" + + "\\s*,\\s" + + "(" + number + ")" + + "\\s*,\\s" + + "(" + number + ")" + )).map(([p, y, r]) => new this({ + R: Number(r), + P: Number(p), + Y: Number(y), + })), + RotatorEntity.createGrammar() + ) + } +} + +class SimpleSerializationVector2DEntity extends Vector2DEntity { + + static grammar = this.createGrammar() + + static createGrammar() { + const number = Parsernostrum.number.getParser().parser.regexp.source; + return Parsernostrum.alt( + Parsernostrum.reg(new RegExp( + "(" + number + ")" + + "\\s*,\\s" + + "(" + number + ")" + )).map(([x, y]) => new this({ + X: Number(x), + Y: Number(y), + })), + Vector2DEntity.createGrammar() + ) + } +} + +class VectorEntity extends IEntity { + + static attributes = { + ...super.attributes, + X: new AttributeInfo({ + default: 0, + expected: true, + }), + Y: new AttributeInfo({ + default: 0, + expected: true, + }), + Z: new AttributeInfo({ + default: 0, + expected: true, + }), + } + static grammar = this.createGrammar() + + static createGrammar() { + return Grammar.createEntityGrammar(VectorEntity, false) + } + + constructor(values) { + super(values); + /** @type {Number} */ this.X; + /** @type {Number} */ this.Y; + /** @type {Number} */ this.Z; + } + + /** @returns {[Number, Number, Number]} */ + toArray() { + return [this.X, this.Y, this.Z] + } +} + +class SimpleSerializationVectorEntity extends VectorEntity { + + static grammar = this.createGrammar() + + static createGrammar() { + const number = Parsernostrum.number.getParser().parser.regexp.source; + return Parsernostrum.alt( + Parsernostrum.regArray(new RegExp( + "(" + number + ")" + + "\\s*,\\s*" + + "(" + number + ")" + + "\\s*,\\s*" + + "(" + number + ")" + )) + .map(([_0, x, y, z]) => new this({ + X: Number(x), + Y: Number(y), + Z: Number(z), + })), + VectorEntity.createGrammar() + ) + } +} + +/** @template {TerminalAttribute} T */ +class PinEntity extends IEntity { + + static #typeEntityMap = { + [Configuration.paths.linearColor]: LinearColorEntity, + [Configuration.paths.rotator]: RotatorEntity, + [Configuration.paths.vector]: VectorEntity, + [Configuration.paths.vector2D]: Vector2DEntity, + "bool": Boolean, + "byte": ByteEntity, + "enum": EnumEntity, + "exec": String, + "int": IntegerEntity, + "int64": Integer64Entity, + "name": String, + "real": Number, + "string": String, + } + static #alternativeTypeEntityMap = { + "enum": EnumDisplayValueEntity, + "rg": RBSerializationVector2DEntity, + [Configuration.paths.rotator]: SimpleSerializationRotatorEntity, + [Configuration.paths.vector]: SimpleSerializationVectorEntity, + [Configuration.paths.vector2D]: SimpleSerializationVector2DEntity, + } + static attributes = { + ...super.attributes, + lookbehind: new AttributeInfo({ + default: "Pin", + ignored: true, + }), + objectEntity: new AttributeInfo({ + ignored: true, + }), + pinIndex: new AttributeInfo({ + type: Number, + ignored: true, + }), + PinId: new AttributeInfo({ + type: GuidEntity, + default: () => new GuidEntity() + }), + PinName: AttributeInfo.createValue(""), + PinFriendlyName: AttributeInfo.createType(new Union(LocalizedTextEntity, FormatTextEntity, String)), + PinToolTip: AttributeInfo.createType(String), + Direction: AttributeInfo.createType(String), + PinType: new AttributeInfo({ + type: PinTypeEntity, + default: () => new PinTypeEntity(), + inlined: true, + }), + LinkedTo: AttributeInfo.createType([PinReferenceEntity]), + SubPins: AttributeInfo.createType([PinReferenceEntity]), + ParentPin: AttributeInfo.createType(PinReferenceEntity), + DefaultValue: new AttributeInfo({ + type: new ComputedType( + /** @param {PinEntity} pinEntity */ + pinEntity => pinEntity.getEntityType(true) ?? String + ), + serialized: true, + }), + AutogeneratedDefaultValue: AttributeInfo.createType(String), + DefaultObject: AttributeInfo.createType(ObjectReferenceEntity), + PersistentGuid: AttributeInfo.createType(GuidEntity), + bHidden: AttributeInfo.createValue(false), + bNotConnectable: AttributeInfo.createValue(false), + bDefaultValueIsReadOnly: AttributeInfo.createValue(false), + bDefaultValueIsIgnored: AttributeInfo.createValue(false), + bAdvancedView: AttributeInfo.createValue(false), + bOrphanedPin: AttributeInfo.createValue(false), + } + static grammar = this.createGrammar() + + #recomputesNodeTitleOnChange = false + set recomputesNodeTitleOnChange(value) { + this.#recomputesNodeTitleOnChange = value; + } + get recomputesNodeTitleOnChange() { + return this.#recomputesNodeTitleOnChange + } + + static createGrammar() { + return Grammar.createEntityGrammar(this) + } + + constructor(values = {}, suppressWarns = false) { + super(values, suppressWarns); + /** @type {ObjectEntity} */ this.objectEntity; + /** @type {Number} */ this.pinIndex; + /** @type {GuidEntity} */ this.PinId; + /** @type {String} */ this.PinName; + /** @type {LocalizedTextEntity | String} */ this.PinFriendlyName; + /** @type {String} */ this.PinToolTip; + /** @type {String} */ this.Direction; + /** @type {PinTypeEntity} */ this.PinType; + /** @type {PinReferenceEntity[]} */ this.LinkedTo; + /** @type {T} */ this.DefaultValue; + /** @type {String} */ this.AutogeneratedDefaultValue; + /** @type {ObjectReferenceEntity} */ this.DefaultObject; + /** @type {GuidEntity} */ this.PersistentGuid; + /** @type {Boolean} */ this.bHidden; + /** @type {Boolean} */ this.bNotConnectable; + /** @type {Boolean} */ this.bDefaultValueIsReadOnly; + /** @type {Boolean} */ this.bDefaultValueIsIgnored; + /** @type {Boolean} */ this.bAdvancedView; + /** @type {Boolean} */ this.bOrphanedPin; + } + + /** @param {ObjectEntity} objectEntity */ + static fromLegacyObject(objectEntity) { + return new PinEntity(objectEntity, true) + } + + getType() { + const category = this.PinType.PinCategory; + if (category === "struct" || category === "object") { + return this.PinType.PinSubCategoryObject.path + } + if (this.isEnum()) { + return "enum" + } + if (this.objectEntity?.isPcg()) { + const pcgSuboject = this.objectEntity.getPcgSubobject(); + const pinObjectReference = this.isInput() + ? pcgSuboject.InputPins?.[this.pinIndex] + : pcgSuboject.OutputPins?.[this.pinIndex]; + if (pinObjectReference) { + /** @type {ObjectEntity} */ + const pinObject = pcgSuboject[Configuration.subObjectAttributeNameFromReference(pinObjectReference, true)]; + let allowedTypes = pinObject.Properties?.AllowedTypes?.toString() ?? ""; + if (allowedTypes == "") { + allowedTypes = this.PinType.PinCategory ?? ""; + if (allowedTypes == "") { + allowedTypes = "Any"; + } + } + if (allowedTypes) { + if ( + pinObject.Properties.bAllowMultipleData !== false + && pinObject.Properties.bAllowMultipleConnections !== false + ) { + allowedTypes += "[]"; + } + return allowedTypes + } + } + } + if (category === "optional") { + switch (this.PinType.PinSubCategory) { + case "red": + return "real" + case "rg": + return "rg" + case "rgb": + return Configuration.paths.vector + case "rgba": + return Configuration.paths.linearColor + default: + return this.PinType.PinSubCategory + } + } + return category + } + + getEntityType(alternative = false) { + const typeString = this.getType(); + const entity = PinEntity.#typeEntityMap[typeString]; + const alternativeEntity = PinEntity.#alternativeTypeEntityMap[typeString]; + return alternative && alternativeEntity !== undefined + ? alternativeEntity + : entity + } + + pinDisplayName() { + let result = this.PinFriendlyName + ? this.PinFriendlyName.toString() + : Utility.formatStringName(this.PinName ?? ""); + let match; + if ( + this.PinToolTip + // Match up until the first \n excluded or last character + && (match = this.PinToolTip.match(/\s*(.+?(?=\n)|.+\S)\s*/)) + ) { + if (match[1].toLowerCase() === result.toLowerCase()) { + return match[1] // In case they match, then keep the case of the PinToolTip + } + } + return result + } + + /** @param {PinEntity} other */ + copyTypeFrom(other) { + this.PinType.PinCategory = other.PinType.PinCategory; + this.PinType.PinSubCategory = other.PinType.PinSubCategory; + this.PinType.PinSubCategoryObject = other.PinType.PinSubCategoryObject; + this.PinType.PinSubCategoryMemberReference = other.PinType.PinSubCategoryMemberReference; + this.PinType.PinValueType = other.PinType.PinValueType; + this.PinType.ContainerType = other.PinType.ContainerType; + this.PinType.bIsReference = other.PinType.bIsReference; + this.PinType.bIsConst = other.PinType.bIsConst; + this.PinType.bIsWeakPointer = other.PinType.bIsWeakPointer; + this.PinType.bIsUObjectWrapper = other.PinType.bIsUObjectWrapper; + this.PinType.bSerializeAsSinglePrecisionFloat = other.PinType.bSerializeAsSinglePrecisionFloat; + } + + getDefaultValue(maybeCreate = false) { + if (this.DefaultValue === undefined && maybeCreate) { + // @ts-expect-error + this.DefaultValue = new (this.getEntityType(true))(); + } + return this.DefaultValue + } + + isEnum() { + const type = this.PinType.PinSubCategoryObject.type; + return type === Configuration.paths.enum + || type === Configuration.paths.userDefinedEnum + || type.toLowerCase() === "enum" + } + + isExecution() { + return this.PinType.PinCategory === "exec" + } + + isHidden() { + return this.bHidden + } + + isInput() { + return !this.bHidden && this.Direction != "EGPD_Output" + } + + isOutput() { + return !this.bHidden && this.Direction == "EGPD_Output" + } + + isLinked() { + return this.LinkedTo?.length > 0 ?? false + } + + /** + * @param {String} targetObjectName + * @param {PinEntity} targetPinEntity + * @returns true if it was not already linked to the tarket + */ + linkTo(targetObjectName, targetPinEntity) { + const linkFound = this.LinkedTo?.some(pinReferenceEntity => + pinReferenceEntity.objectName.toString() == targetObjectName + && pinReferenceEntity.pinGuid.valueOf() == targetPinEntity.PinId.valueOf() + ); + if (!linkFound) { + (this.LinkedTo ??= []).push(new PinReferenceEntity({ + objectName: targetObjectName, + pinGuid: targetPinEntity.PinId, + })); + return true + } + return false // Already linked + } + + /** + * @param {String} targetObjectName + * @param {PinEntity} targetPinEntity + * @returns true if it was linked to the target + */ + unlinkFrom(targetObjectName, targetPinEntity) { + const indexElement = this.LinkedTo?.findIndex(pinReferenceEntity => { + return pinReferenceEntity.objectName.toString() == targetObjectName + && pinReferenceEntity.pinGuid.valueOf() == targetPinEntity.PinId.valueOf() + }); + if (indexElement >= 0) { + this.LinkedTo.splice(indexElement, 1); + if (this.LinkedTo.length === 0 && PinEntity.attributes.LinkedTo.default === undefined) { + this.LinkedTo = undefined; + } + return true + } + return false + } + + getSubCategory() { + return this.PinType.PinSubCategoryObject.path + } + + /** @return {CSSResult} */ + pinColor() { + if (this.PinType.PinCategory == "mask") { + const result = Configuration.pinColor[this.PinType.PinSubCategory]; + if (result) { + return result + } + } else if (this.PinType.PinCategory == "optional") { + return Configuration.pinColorMaterial + } + return Configuration.pinColor[this.getType()] + ?? Configuration.pinColor[this.PinType.PinCategory.toLowerCase()] + ?? Configuration.pinColor["default"] + } +} + class UnknownPinEntity extends PinEntity { - static lookbehind = "" static grammar = this.createGrammar() static createGrammar() { return Parsernostrum.seq( Parsernostrum.reg( - new RegExp(`${Grammar.Regex.Symbol.source}\\s*\\(\\s*`), + new RegExp(`(${Grammar.Regex.Symbol.source})\\s*\\(\\s*`), 1 ), Grammar.createAttributeGrammar(this).sepBy(Grammar.commaSeparation), @@ -4810,21 +4780,10 @@ class VariableReferenceEntity extends IEntity { static attributes = { ...super.attributes, - MemberScope: { - type: String, - }, - MemberName: { - default: "", - }, - MemberGuid: { - type: GuidEntity, - }, - bSelfContext: { - type: Boolean, - }, - } - static { - this.cleanupAttributes(this.attributes); + MemberScope: AttributeInfo.createType(String), + MemberName: AttributeInfo.createValue(""), + MemberGuid: AttributeInfo.createType(GuidEntity), + bSelfContext: AttributeInfo.createType(Boolean), } static grammar = this.createGrammar() @@ -4872,112 +4831,123 @@ class ObjectEntity extends IEntity { } static attributes = { ...super.attributes, - AdvancedPinDisplay: { type: IdentifierEntity }, - Archetype: { type: ObjectReferenceEntity }, - AxisKey: { type: SymbolEntity }, - bAlt: { type: Boolean }, - bCanRenameNode: { type: Boolean }, - bColorCommentBubble: { type: Boolean }, - bCommand: { type: Boolean }, - bCommentBubblePinned: { type: Boolean }, - bCommentBubbleVisible_InDetailsPanel: { type: Boolean }, - bCommentBubbleVisible: { type: Boolean }, - bConsumeInput: { type: Boolean }, - bControl: { type: Boolean }, - bExecuteWhenPaused: { type: Boolean }, - bExposeToLibrary: { type: Boolean }, - bInternalEvent: { type: Boolean }, - bIsCaseSensitive: { type: Boolean }, - bIsConstFunc: { type: Boolean }, - bIsPureFunc: { type: Boolean }, - BlueprintElementInstance: { type: ObjectReferenceEntity }, - BlueprintElementType: { type: ObjectReferenceEntity }, - bOverrideFunction: { type: Boolean }, - bOverrideParentBinding: { type: Boolean }, - bShift: { type: Boolean }, - Class: { type: ObjectReferenceEntity }, - CommentColor: { type: LinearColorEntity }, - ComponentPropertyName: { type: String }, - CustomFunctionName: { type: String }, - CustomProperties: { type: [new Union(PinEntity, UnknownPinEntity)] }, - DelegateOwnerClass: { type: ObjectReferenceEntity }, - DelegatePropertyName: { type: String }, - DelegateReference: { type: VariableReferenceEntity }, - EnabledState: { type: IdentifierEntity }, - Enum: { type: ObjectReferenceEntity }, - EnumEntries: { + R: new AttributeInfo({ + default: false, + silent: true, + }), + G: new AttributeInfo({ + default: false, + silent: true, + }), + B: new AttributeInfo({ + default: false, + silent: true, + }), + A: new AttributeInfo({ + default: false, + silent: true, + }), + AdvancedPinDisplay: AttributeInfo.createType(IdentifierEntity), + Archetype: AttributeInfo.createType(ObjectReferenceEntity), + AxisKey: AttributeInfo.createType(SymbolEntity), + bAlt: AttributeInfo.createType(Boolean), + bCanRenameNode: AttributeInfo.createType(Boolean), + bColorCommentBubble: AttributeInfo.createType(Boolean), + bCommand: AttributeInfo.createType(Boolean), + bCommentBubblePinned: AttributeInfo.createType(Boolean), + bCommentBubbleVisible_InDetailsPanel: AttributeInfo.createType(Boolean), + bCommentBubbleVisible: AttributeInfo.createType(Boolean), + bConsumeInput: AttributeInfo.createType(Boolean), + bControl: AttributeInfo.createType(Boolean), + bExecuteWhenPaused: AttributeInfo.createType(Boolean), + bExposeToLibrary: AttributeInfo.createType(Boolean), + bInternalEvent: AttributeInfo.createType(Boolean), + bIsCaseSensitive: AttributeInfo.createType(Boolean), + bIsConstFunc: AttributeInfo.createType(Boolean), + bIsPureFunc: AttributeInfo.createType(Boolean), + BlueprintElementInstance: AttributeInfo.createType(ObjectReferenceEntity), + BlueprintElementType: AttributeInfo.createType(ObjectReferenceEntity), + bOverrideFunction: AttributeInfo.createType(Boolean), + bOverrideParentBinding: AttributeInfo.createType(Boolean), + bShift: AttributeInfo.createType(Boolean), + Class: AttributeInfo.createType(ObjectReferenceEntity), + CommentColor: AttributeInfo.createType(LinearColorEntity), + ComponentPropertyName: AttributeInfo.createType(String), + CustomFunctionName: AttributeInfo.createType(String), + CustomProperties: AttributeInfo.createType([new Union(PinEntity, UnknownPinEntity)]), + DelegateOwnerClass: AttributeInfo.createType(ObjectReferenceEntity), + DelegatePropertyName: AttributeInfo.createType(String), + DelegateReference: AttributeInfo.createType(VariableReferenceEntity), + EnabledState: AttributeInfo.createType(IdentifierEntity), + Enum: AttributeInfo.createType(ObjectReferenceEntity), + EnumEntries: new AttributeInfo({ type: [String], inlined: true, - }, - ErrorMsg: { type: String }, - ErrorType: { type: IntegerEntity }, - EventReference: { type: FunctionReferenceEntity }, - ExportPath: { type: ObjectReferenceEntity }, - FunctionReference: { type: FunctionReferenceEntity }, - G: { type: Number }, - Graph: { type: ObjectReferenceEntity }, - HiGenGridSize: { type: SymbolEntity }, - InputAxisKey: { type: SymbolEntity }, - InputKey: { type: SymbolEntity }, - InputName: { type: String }, - InputPins: { + }), + ErrorMsg: AttributeInfo.createType(String), + ErrorType: AttributeInfo.createType(IntegerEntity), + EventReference: AttributeInfo.createType(FunctionReferenceEntity), + ExportPath: AttributeInfo.createType(ObjectReferenceEntity), + FunctionReference: AttributeInfo.createType(FunctionReferenceEntity), + Graph: AttributeInfo.createType(ObjectReferenceEntity), + HiGenGridSize: AttributeInfo.createType(SymbolEntity), + InputAxisKey: AttributeInfo.createType(SymbolEntity), + InputKey: AttributeInfo.createType(SymbolEntity), + InputName: AttributeInfo.createType(String), + InputPins: new AttributeInfo({ type: [ObjectReferenceEntity], inlined: true, - }, - InputType: { type: SymbolEntity }, - MacroGraphReference: { type: MacroGraphReferenceEntity }, - MaterialExpression: { type: ObjectReferenceEntity }, - MaterialExpressionComment: { type: ObjectReferenceEntity }, - MaterialExpressionEditorX: { type: new MirroredEntity(IntegerEntity) }, - MaterialExpressionEditorY: { type: new MirroredEntity(IntegerEntity) }, - MaterialFunction: { type: ObjectReferenceEntity }, - MoveMode: { type: SymbolEntity }, - Name: { type: String }, - Node: { type: new MirroredEntity(ObjectReferenceEntity) }, - NodeComment: { type: String }, - NodeGuid: { type: GuidEntity }, - NodeHeight: { type: IntegerEntity }, - NodePosX: { type: IntegerEntity }, - NodePosY: { type: IntegerEntity }, - NodeTitle: { type: String }, - NodeTitleColor: { type: LinearColorEntity }, - NodeWidth: { type: IntegerEntity }, - NumAdditionalInputs: { type: Number }, - ObjectRef: { type: ObjectReferenceEntity }, - Operation: { type: SymbolEntity }, - OutputPins: { + }), + InputType: AttributeInfo.createType(SymbolEntity), + MacroGraphReference: AttributeInfo.createType(MacroGraphReferenceEntity), + MaterialExpression: AttributeInfo.createType(ObjectReferenceEntity), + MaterialExpressionComment: AttributeInfo.createType(ObjectReferenceEntity), + MaterialExpressionEditorX: AttributeInfo.createType(new MirroredEntity(IntegerEntity)), + MaterialExpressionEditorY: AttributeInfo.createType(new MirroredEntity(IntegerEntity)), + MaterialFunction: AttributeInfo.createType(ObjectReferenceEntity), + MoveMode: AttributeInfo.createType(SymbolEntity), + Name: AttributeInfo.createType(String), + Node: AttributeInfo.createType(new MirroredEntity(ObjectReferenceEntity)), + NodeComment: AttributeInfo.createType(String), + NodeGuid: AttributeInfo.createType(GuidEntity), + NodeHeight: AttributeInfo.createType(IntegerEntity), + NodePosX: AttributeInfo.createType(IntegerEntity), + NodePosY: AttributeInfo.createType(IntegerEntity), + NodeTitle: AttributeInfo.createType(String), + NodeTitleColor: AttributeInfo.createType(LinearColorEntity), + NodeWidth: AttributeInfo.createType(IntegerEntity), + NumAdditionalInputs: AttributeInfo.createType(Number), + ObjectRef: AttributeInfo.createType(ObjectReferenceEntity), + Operation: AttributeInfo.createType(SymbolEntity), + OutputPins: new AttributeInfo({ type: [ObjectReferenceEntity], inlined: true, - }, - PCGNode: { type: ObjectReferenceEntity }, - PinNames: { + }), + PCGNode: AttributeInfo.createType(ObjectReferenceEntity), + PinNames: new AttributeInfo({ type: [String], inlined: true, - }, - PinTags: { + }), + PinTags: new AttributeInfo({ type: [null], inlined: true, - }, - PositionX: { type: new MirroredEntity(IntegerEntity) }, - PositionY: { type: new MirroredEntity(IntegerEntity) }, - ProxyClass: { type: ObjectReferenceEntity }, - ProxyFactoryClass: { type: ObjectReferenceEntity }, - ProxyFactoryFunctionName: { type: String }, - R: { type: Number }, - SelfContextInfo: { type: SymbolEntity }, - SettingsInterface: { type: ObjectReferenceEntity }, - SizeX: { type: new MirroredEntity(IntegerEntity) }, - SizeY: { type: new MirroredEntity(IntegerEntity) }, - StructType: { type: ObjectReferenceEntity }, - SubgraphInstance: { type: String }, - TargetType: { type: ObjectReferenceEntity }, - Text: { type: new MirroredEntity(String) }, - TimelineGuid: { type: GuidEntity }, - TimelineName: { type: String }, - VariableReference: { type: VariableReferenceEntity }, - } - static { - this.cleanupAttributes(this.attributes); + }), + PositionX: AttributeInfo.createType(new MirroredEntity(IntegerEntity)), + PositionY: AttributeInfo.createType(new MirroredEntity(IntegerEntity)), + ProxyClass: AttributeInfo.createType(ObjectReferenceEntity), + ProxyFactoryClass: AttributeInfo.createType(ObjectReferenceEntity), + ProxyFactoryFunctionName: AttributeInfo.createType(String), + SelfContextInfo: AttributeInfo.createType(SymbolEntity), + SettingsInterface: AttributeInfo.createType(ObjectReferenceEntity), + SizeX: AttributeInfo.createType(new MirroredEntity(IntegerEntity)), + SizeY: AttributeInfo.createType(new MirroredEntity(IntegerEntity)), + StructType: AttributeInfo.createType(ObjectReferenceEntity), + SubgraphInstance: AttributeInfo.createType(String), + TargetType: AttributeInfo.createType(ObjectReferenceEntity), + Text: AttributeInfo.createType(new MirroredEntity(String)), + TimelineGuid: AttributeInfo.createType(GuidEntity), + TimelineName: AttributeInfo.createType(String), + VariableReference: AttributeInfo.createType(VariableReferenceEntity), } static nameRegex = /^(\w+?)(?:_(\d+))?$/ static sequencerScriptingNameRegex = /\/Script\/SequencerScripting\.MovieSceneScripting(.+)Channel/ @@ -5109,33 +5079,21 @@ class ObjectEntity extends IEntity { }; } super(values, suppressWarns); + + // Attributes not assigned a strong type in attributes because the names are too generic + /** @type {Number | MirroredEntity} */ this.R; + /** @type {Number | MirroredEntity} */ this.G; + /** @type {Number | MirroredEntity} */ this.B; + /** @type {Number | MirroredEntity} */ this.A; + + // Attributes /** @type {(PinEntity | UnknownPinEntity)[]} */ this.CustomProperties; - /** @type {Boolean} */ this.bAlt; - /** @type {Boolean} */ this.bCanRenameNode; - /** @type {Boolean} */ this.bColorCommentBubble; - /** @type {Boolean} */ this.bCommand; - /** @type {Boolean} */ this.bCommentBubblePinned; - /** @type {Boolean} */ this.bCommentBubbleVisible; - /** @type {Boolean} */ this.bCommentBubbleVisible_InDetailsPanel; - /** @type {Boolean} */ this.bConsumeInput; - /** @type {Boolean} */ this.bControl; - /** @type {Boolean} */ this.bExecuteWhenPaused; - /** @type {Boolean} */ this.bExposeToLibrary; - /** @type {Boolean} */ this.bInternalEvent; - /** @type {Boolean} */ this.bIsCaseSensitive; - /** @type {Boolean} */ this.bIsConstFunc; /** @type {Boolean} */ this.bIsPureFunc; - /** @type {Boolean} */ this.bOverrideFunction; - /** @type {Boolean} */ this.bOverrideParentBinding; - /** @type {Boolean} */ this.bShift; /** @type {FunctionReferenceEntity} */ this.ComponentPropertyName; /** @type {FunctionReferenceEntity} */ this.EventReference; /** @type {FunctionReferenceEntity} */ this.FunctionReference; - /** @type {GuidEntity} */ this.NodeGuid; - /** @type {GuidEntity} */ this.TimelineGuid; /** @type {IdentifierEntity} */ this.AdvancedPinDisplay; /** @type {IdentifierEntity} */ this.EnabledState; - /** @type {IntegerEntity} */ this.ErrorType; /** @type {IntegerEntity} */ this.NodeHeight; /** @type {IntegerEntity} */ this.NodePosX; /** @type {IntegerEntity} */ this.NodePosY; @@ -5152,16 +5110,13 @@ class ObjectEntity extends IEntity { /** @type {MirroredEntity} */ this.PositionY; /** @type {MirroredEntity} */ this.Node; /** @type {null[]} */ this.PinTags; - /** @type {Number} */ this.G; /** @type {Number} */ this.NumAdditionalInputs; - /** @type {Number} */ this.R; /** @type {ObjectReferenceEntity[]} */ this.InputPins; /** @type {ObjectReferenceEntity[]} */ this.OutputPins; /** @type {ObjectReferenceEntity} */ this.Archetype; /** @type {ObjectReferenceEntity} */ this.BlueprintElementInstance; /** @type {ObjectReferenceEntity} */ this.BlueprintElementType; /** @type {ObjectReferenceEntity} */ this.Class; - /** @type {ObjectReferenceEntity} */ this.DelegateOwnerClass; /** @type {ObjectReferenceEntity} */ this.Enum; /** @type {ObjectReferenceEntity} */ this.ExportPath; /** @type {ObjectReferenceEntity} */ this.Graph; @@ -5170,8 +5125,6 @@ class ObjectEntity extends IEntity { /** @type {ObjectReferenceEntity} */ this.MaterialFunction; /** @type {ObjectReferenceEntity} */ this.ObjectRef; /** @type {ObjectReferenceEntity} */ this.PCGNode; - /** @type {ObjectReferenceEntity} */ this.ProxyClass; - /** @type {ObjectReferenceEntity} */ this.ProxyFactoryClass; /** @type {ObjectReferenceEntity} */ this.SettingsInterface; /** @type {ObjectReferenceEntity} */ this.StructType; /** @type {ObjectReferenceEntity} */ this.TargetType; @@ -5179,7 +5132,6 @@ class ObjectEntity extends IEntity { /** @type {String[]} */ this.PinNames; /** @type {String} */ this.CustomFunctionName; /** @type {String} */ this.DelegatePropertyName; - /** @type {String} */ this.ErrorMsg; /** @type {String} */ this.InputName; /** @type {String} */ this.Name; /** @type {String} */ this.NodeComment; @@ -5188,14 +5140,11 @@ class ObjectEntity extends IEntity { /** @type {String} */ this.ProxyFactoryFunctionName; /** @type {String} */ this.SubgraphInstance; /** @type {String} */ this.Text; - /** @type {String} */ this.TimelineName; /** @type {SymbolEntity} */ this.AxisKey; /** @type {SymbolEntity} */ this.HiGenGridSize; /** @type {SymbolEntity} */ this.InputAxisKey; /** @type {SymbolEntity} */ this.InputKey; /** @type {SymbolEntity} */ this.InputType; - /** @type {SymbolEntity} */ this.MoveMode; - /** @type {SymbolEntity} */ this.SelfContextInfo; /** @type {VariableReferenceEntity} */ this.DelegateReference; /** @type {VariableReferenceEntity} */ this.VariableReference; @@ -5223,11 +5172,21 @@ class ObjectEntity extends IEntity { const materialSubobject = this.getMaterialSubobject(); if (materialSubobject) { const obj = materialSubobject; - obj.SizeX && (obj.SizeX.getter = () => this.NodeWidth); + obj.SizeX !== undefined && (obj.SizeX.getter = () => this.NodeWidth); obj.SizeY && (obj.SizeY.getter = () => this.NodeHeight); obj.Text && (obj.Text.getter = () => this.NodeComment); obj.MaterialExpressionEditorX && (obj.MaterialExpressionEditorX.getter = () => this.NodePosX); obj.MaterialExpressionEditorY && (obj.MaterialExpressionEditorY.getter = () => this.NodePosY); + if (this.getType() === Configuration.paths.materialExpressionComponentMask) { + // The following attributes are too generic therefore not assigned a MirroredEntity + const rgbaPins = Configuration.rgba.map(pinName => + this.getPinEntities().find(pin => pin.PinName === pinName && (pin.recomputesNodeTitleOnChange = true)) + ); + obj.R = new MirroredEntity(Boolean, () => rgbaPins[0].DefaultValue); + obj.G = new MirroredEntity(Boolean, () => rgbaPins[1].DefaultValue); + obj.B = new MirroredEntity(Boolean, () => rgbaPins[2].DefaultValue); + obj.A = new MirroredEntity(Boolean, () => rgbaPins[3].DefaultValue); + } } /** @type {ObjectEntity} */ const pcgObject = this.getPcgSubobject(); @@ -5527,6 +5486,13 @@ class ObjectEntity extends IEntity { if (this.StructType) { return `Make ${this.StructType.getName()}` } + case Configuration.paths.materialExpressionComponentMask: { + const materialObject = this.getMaterialSubobject(); + return `Mask ( ${Configuration.rgba + .filter(k => /** @type {MirroredEntity} */(materialObject[k]).get() === true) + .map(v => v + " ") + .join("")})` + } case Configuration.paths.materialExpressionConstant: input ??= [this.getCustomproperties().find(pinEntity => pinEntity.PinName == "Value")?.DefaultValue]; case Configuration.paths.materialExpressionConstant2Vector: @@ -5554,11 +5520,12 @@ class ObjectEntity extends IEntity { return input.map(v => Utility.printExponential(v)).reduce((acc, cur) => acc + "," + cur) } break - case Configuration.paths.materialExpressionFunctionInput: + case Configuration.paths.materialExpressionFunctionInput: { const materialObject = this.getMaterialSubobject(); const inputName = materialObject?.InputName ?? "In"; const inputType = materialObject?.InputType?.value.match(/^.+?_(\w+)$/)?.[1] ?? "Vector3"; return `Input ${inputName} (${inputType})` + } case Configuration.paths.materialExpressionLogarithm: return "Ln" case Configuration.paths.materialExpressionLogarithm10: @@ -6116,7 +6083,11 @@ class Serializer { let grammar = Grammar.grammarFor(undefined, this.entityType); const parseResult = grammar.run(value); if (!parseResult.status) { - throw new Error(`Error when trying to parse the entity ${this.entityType.prototype.constructor.name}.`) + throw new Error( + this.entityType + ? `Error when trying to parse the entity ${this.entityType.prototype.constructor.name}` + : "Error when trying to parse null" + ) } return parseResult.value } @@ -6147,7 +6118,7 @@ class Serializer { if (attributes[key]?.quoted) { keyValue = `"${keyValue}"`; } - const isSerialized = Utility.isSerialized(entity, key); + const isSerialized = AttributeInfo.getAttribute(entity, key, "serialized"); if (first) { first = false; } else { @@ -6202,10 +6173,21 @@ class Serializer { return serializer.doWrite(value, insideString, indentation) } + /** + * @param {IEntity} entity + * @param {String} key + */ showProperty(entity, key) { - const attribute = /** @type {EntityConstructor} */(this.entityType).attributes[key]; - if (attribute?.constructor === Object && attribute.ignored) { - return false + if (entity instanceof IEntity) { + if ( + AttributeInfo.getAttribute(entity, key, "ignored") + || AttributeInfo.getAttribute(entity, key, "silent") && Utility.equals( + AttributeInfo.getAttribute(entity, key, "default"), + entity[key] + ) + ) { + return false + } } return true } @@ -6398,89 +6380,99 @@ class Cut extends IInput { } } -/** @template {IElement} ElementT */ -class ITemplate { +class ElementFactory { - /** @type {ElementT} */ - element + /** @type {Map>} */ + static #elementConstructors = new Map() - get blueprint() { - return this.element.blueprint + /** + * @param {String} tagName + * @param {AnyConstructor} entityConstructor + */ + static registerElement(tagName, entityConstructor) { + ElementFactory.#elementConstructors.set(tagName, entityConstructor); } - /** @type {IInput[]} */ - #inputObjects = [] - get inputObjects() { - return this.#inputObjects + /** @param {String} tagName */ + static getConstructor(tagName) { + return ElementFactory.#elementConstructors.get(tagName) } +} - /** @param {ElementT} element */ - initialize(element) { - this.element = element; - } - - createInputObjects() { - return /** @type {IInput[]} */([]) - } - - setup() { - this.#inputObjects.forEach(v => v.setup()); - } - - cleanup() { - this.#inputObjects.forEach(v => v.cleanup()); - } - - /** @param {PropertyValues} changedProperties */ - willUpdate(changedProperties) { - } - - /** @param {PropertyValues} changedProperties */ - update(changedProperties) { - } - - render() { - return x`` - } - - /** @param {PropertyValues} changedProperties */ - firstUpdated(changedProperties) { - } - - /** @param {PropertyValues} changedProperties */ - updated(changedProperties) { - } - - inputSetup() { - this.#inputObjects = this.createInputObjects(); - } +/** + * @typedef {import("../IInput.js").Options & { + * listenOnFocus?: Boolean, + * unlistenOnTextEdit?: Boolean, + * }} Options + */ + +class Paste extends IInput { + + static #serializer = new ObjectSerializer() + + /** @type {(e: ClipboardEvent) => void} */ + #pasteHandle + + /** + * @param {Element} target + * @param {Blueprint} blueprint + * @param {Options} options + */ + constructor(target, blueprint, options = {}) { + options.listenOnFocus ??= true; + options.unlistenOnTextEdit ??= true; // No nodes paste if inside a text field, just text (default behavior) + super(target, blueprint, options); + let self = this; + this.#pasteHandle = e => self.pasted(e.clipboardData.getData("Text")); + } + + listenEvents() { + window.addEventListener("paste", this.#pasteHandle); + } + + unlistenEvents() { + window.removeEventListener("paste", this.#pasteHandle); + } + + /** @param {String} value */ + pasted(value) { + let top = 0; + let left = 0; + let count = 0; + let nodes = Paste.#serializer.readMultiple(value).map(entity => { + let node = /** @type {NodeElementConstructor} */(ElementFactory.getConstructor("ueb-node")) + .newObject(entity); + top += node.locationY; + left += node.locationX; + ++count; + return node + }); + top /= count; + left /= count; + if (nodes.length > 0) { + this.blueprint.unselectAll(); + } + let mousePosition = this.blueprint.mousePosition; + nodes.forEach(node => { + node.addLocation(mousePosition[0] - left, mousePosition[1] - top); + node.snapToGrid(); + node.setSelected(true); + }); + this.blueprint.addGraphElement(...nodes); + return true + } } class KeyBindingEntity extends IEntity { static attributes = { ...super.attributes, - ActionName: { - default: "", - }, - bShift: { - default: false, - }, - bCtrl: { - default: false, - }, - bAlt: { - default: false, - }, - bCmd: { - default: false, - }, - Key: { - type: IdentifierEntity, - }, - } - static { - this.cleanupAttributes(this.attributes); + ActionName: AttributeInfo.createValue(""), + bShift: AttributeInfo.createValue(false), + bCtrl: AttributeInfo.createValue(false), + bAlt: AttributeInfo.createValue(false), + bCmd: AttributeInfo.createValue(false), + Key: AttributeInfo.createType(IdentifierEntity), } static grammar = this.createGrammar() @@ -6633,14 +6625,6 @@ class KeyboardShortcut extends IInput { } } -class Shortcuts { - static deleteNodes = "Delete" - static duplicateNodes = "(bCtrl=True,Key=D)" - static enableLinkDelete = "LeftAlt" - static enableZoomIn = ["LeftControl", "RightControl"] // Button to enable more than 1:1 zoom - static selectAllNodes = "(bCtrl=True,Key=A)" -} - /** * @typedef {import("../IInput.js").Options & { * ignoreTranslateCompensate?: Boolean, @@ -7378,89 +7362,6 @@ class MouseTracking extends IPointing { } } -class ElementFactory { - - /** @type {Map>} */ - static #elementConstructors = new Map() - - /** - * @param {String} tagName - * @param {AnyConstructor} entityConstructor - */ - static registerElement(tagName, entityConstructor) { - ElementFactory.#elementConstructors.set(tagName, entityConstructor); - } - - /** @param {String} tagName */ - static getConstructor(tagName) { - return ElementFactory.#elementConstructors.get(tagName) - } -} - -/** - * @typedef {import("../IInput.js").Options & { - * listenOnFocus?: Boolean, - * unlistenOnTextEdit?: Boolean, - * }} Options - */ - -class Paste extends IInput { - - static #serializer = new ObjectSerializer() - - /** @type {(e: ClipboardEvent) => void} */ - #pasteHandle - - /** - * @param {Element} target - * @param {Blueprint} blueprint - * @param {Options} options - */ - constructor(target, blueprint, options = {}) { - options.listenOnFocus ??= true; - options.unlistenOnTextEdit ??= true; // No nodes paste if inside a text field, just text (default behavior) - super(target, blueprint, options); - let self = this; - this.#pasteHandle = e => self.pasted(e.clipboardData.getData("Text")); - } - - listenEvents() { - window.addEventListener("paste", this.#pasteHandle); - } - - unlistenEvents() { - window.removeEventListener("paste", this.#pasteHandle); - } - - /** @param {String} value */ - pasted(value) { - let top = 0; - let left = 0; - let count = 0; - let nodes = Paste.#serializer.readMultiple(value).map(entity => { - let node = /** @type {NodeElementConstructor} */(ElementFactory.getConstructor("ueb-node")) - .newObject(entity); - top += node.locationY; - left += node.locationX; - ++count; - return node - }); - top /= count; - left /= count; - if (nodes.length > 0) { - this.blueprint.unselectAll(); - } - let mousePosition = this.blueprint.mousePosition; - nodes.forEach(node => { - node.addLocation(mousePosition[0] - left, mousePosition[1] - top); - node.snapToGrid(); - node.setSelected(true); - }); - this.blueprint.addGraphElement(...nodes); - return true - } -} - /** * @typedef {import("./IMouseClickDrag.js").Options & { * scrollGraphEdge?: Boolean, @@ -7541,6 +7442,64 @@ class Unfocus extends IInput { } } +/** @template {IElement} ElementT */ +class ITemplate { + + /** @type {ElementT} */ + element + + get blueprint() { + return this.element.blueprint + } + + /** @type {IInput[]} */ + #inputObjects = [] + get inputObjects() { + return this.#inputObjects + } + + /** @param {ElementT} element */ + initialize(element) { + this.element = element; + } + + createInputObjects() { + return /** @type {IInput[]} */([]) + } + + setup() { + this.#inputObjects.forEach(v => v.setup()); + } + + cleanup() { + this.#inputObjects.forEach(v => v.cleanup()); + } + + /** @param {PropertyValues} changedProperties */ + willUpdate(changedProperties) { + } + + /** @param {PropertyValues} changedProperties */ + update(changedProperties) { + } + + render() { + return x`` + } + + /** @param {PropertyValues} changedProperties */ + firstUpdated(changedProperties) { + } + + /** @param {PropertyValues} changedProperties */ + updated(changedProperties) { + } + + inputSetup() { + this.#inputObjects = this.createInputObjects(); + } +} + /** @extends ITemplate */ class BlueprintTemplate extends ITemplate { @@ -7564,10 +7523,13 @@ class BlueprintTemplate extends ITemplate { this.viewportSize[1] = size.blockSize; } }) + /** @type {Copy} */ #copyInputObject + /** @type {Paste} */ #pasteInputObject + /** @type {Zoom} */ #zoomInputObject @@ -7885,38 +7847,6 @@ class IFromToPositionedElement extends IElement { } } -/** - * @template {IFromToPositionedElement} T - * @extends {ITemplate} - */ -class IFromToPositionedTemplate extends ITemplate { - - /** @param {PropertyValues} changedProperties */ - update(changedProperties) { - super.update(changedProperties); - const [fromX, fromY, toX, toY] = [ - Math.round(this.element.fromX), - Math.round(this.element.fromY), - Math.round(this.element.toX), - Math.round(this.element.toY), - ]; - const [left, top, width, height] = [ - Math.min(fromX, toX), - Math.min(fromY, toY), - Math.abs(fromX - toX), - Math.abs(fromY - toY), - ]; - if (changedProperties.has("fromX") || changedProperties.has("toX")) { - this.element.style.left = `${left}px`; - this.element.style.width = `${width}px`; - } - if (changedProperties.has("fromY") || changedProperties.has("toY")) { - this.element.style.top = `${top}px`; - this.element.style.height = `${height}px`; - } - } -} - class KnotEntity extends ObjectEntity { /** @@ -8117,6 +8047,38 @@ class MouseDbClick extends IPointing { } } +/** + * @template {IFromToPositionedElement} T + * @extends {ITemplate} + */ +class IFromToPositionedTemplate extends ITemplate { + + /** @param {PropertyValues} changedProperties */ + update(changedProperties) { + super.update(changedProperties); + const [fromX, fromY, toX, toY] = [ + Math.round(this.element.fromX), + Math.round(this.element.fromY), + Math.round(this.element.toX), + Math.round(this.element.toY), + ]; + const [left, top, width, height] = [ + Math.min(fromX, toX), + Math.min(fromY, toY), + Math.abs(fromX - toX), + Math.abs(fromY - toY), + ]; + if (changedProperties.has("fromX") || changedProperties.has("toX")) { + this.element.style.left = `${left}px`; + this.element.style.width = `${width}px`; + } + if (changedProperties.has("fromY") || changedProperties.has("toY")) { + this.element.style.top = `${top}px`; + this.element.style.height = `${height}px`; + } + } +} + /** @extends {IFromToPositionedTemplate} */ class LinkTemplate extends IFromToPositionedTemplate { @@ -8720,6 +8682,37 @@ class MouseClickDrag extends MouseMoveDraggable { } } +/** @extends {MouseMoveDraggable} */ +class MouseMoveNodes extends MouseMoveDraggable { + + startDrag() { + if (!this.target.selected) { + this.blueprint.unselectAll(); + this.target.setSelected(true); + } + } + + dragAction(location, offset) { + this.target.acknowledgeDrag(offset); + } + + unclicked() { + if (!this.started) { + this.blueprint.unselectAll(); + this.target.setSelected(true); + } else { + this.blueprint.getNodes(true).forEach(node => + node.boundComments + .filter(comment => !node.isInsideComment(comment)) + .forEach(comment => node.unbindFromComment(comment)) + ); + this.blueprint.getCommentNodes().forEach(comment => + /** @type {CommentNodeTemplate} */(comment.template).manageNodesBind() + ); + } + } +} + /** * @template {IDraggableElement} T * @extends {ITemplate} @@ -8817,37 +8810,6 @@ class IDraggablePositionedTemplate extends IDraggableTemplate { } } -/** @extends {MouseMoveDraggable} */ -class MouseMoveNodes extends MouseMoveDraggable { - - startDrag() { - if (!this.target.selected) { - this.blueprint.unselectAll(); - this.target.setSelected(true); - } - } - - dragAction(location, offset) { - this.target.acknowledgeDrag(offset); - } - - unclicked() { - if (!this.started) { - this.blueprint.unselectAll(); - this.target.setSelected(true); - } else { - this.blueprint.getNodes(true).forEach(node => - node.boundComments - .filter(comment => !node.isInsideComment(comment)) - .forEach(comment => node.unbindFromComment(comment)) - ); - this.blueprint.getCommentNodes().forEach(comment => - /** @type {CommentNodeTemplate} */(comment.template).manageNodesBind() - ); - } - } -} - /** * @template {NodeElement} T * @extends {IDraggablePositionedTemplate} @@ -8970,7 +8932,7 @@ class NodeTemplate extends ISelectableDraggableTemplate { } renderNodeName() { - return this.element.getNodeDisplayName() + return this.element.nodeDisplayName } renderTop() { @@ -9453,7 +9415,7 @@ class VariableManagementNodeTemplate extends NodeTemplate { /** @param {NodeElement} element */ initialize(element) { super.initialize(element); - this.#displayName = this.element.getNodeDisplayName(); + this.#displayName = this.element.nodeDisplayName; } render() { @@ -9747,56 +9709,6 @@ class EventNodeTemplate extends NodeTemplate { } } -/** - * @template {IEntity} EntityT - * @template {ISelectableDraggableTemplate} TemplateT - * @extends {IDraggableElement} - */ -class ISelectableDraggableElement extends IDraggableElement { - - static properties = { - ...super.properties, - selected: { - type: Boolean, - attribute: "data-selected", - reflect: true, - converter: Utility.booleanConverter, - }, - } - - /** @param {UEBDragEvent} e */ - dragHandler = e => this.addLocation(...e.detail.value) - - constructor() { - super(); - this.selected = false; - this.listeningDrag = false; - } - - setup() { - super.setup(); - this.setSelected(this.selected); - } - - cleanup() { - super.cleanup(); - this.blueprint.removeEventListener(Configuration.nodeDragGeneralEventName, this.dragHandler); - } - - setSelected(value = true) { - this.selected = value; - if (this.blueprint) { - if (this.selected) { - this.listeningDrag = true; - this.blueprint.addEventListener(Configuration.nodeDragGeneralEventName, this.dragHandler); - } else { - this.blueprint.removeEventListener(Configuration.nodeDragGeneralEventName, this.dragHandler); - this.listeningDrag = false; - } - } - } -} - /** @extends MinimalPinTemplate */ class KnotPinTemplate extends MinimalPinTemplate { @@ -9816,6 +9728,7 @@ class KnotPinTemplate extends MinimalPinTemplate { : this ) .iconElement.getBoundingClientRect(); + /** @type {Coordinates} */ const boundingLocation = [this.element.isInput() ? rect.left : rect.right + 1, (rect.top + rect.bottom) / 2]; const location = Utility.convertLocation(boundingLocation, this.blueprint.template.gridElement); return this.blueprint.compensateTranslation(location[0], location[1]) @@ -9921,6 +9834,56 @@ class VariableAccessNodeTemplate extends VariableManagementNodeTemplate { } } +/** + * @template {IEntity} EntityT + * @template {ISelectableDraggableTemplate} TemplateT + * @extends {IDraggableElement} + */ +class ISelectableDraggableElement extends IDraggableElement { + + static properties = { + ...super.properties, + selected: { + type: Boolean, + attribute: "data-selected", + reflect: true, + converter: Utility.booleanConverter, + }, + } + + /** @param {UEBDragEvent} e */ + dragHandler = e => this.addLocation(...e.detail.value) + + constructor() { + super(); + this.selected = false; + this.listeningDrag = false; + } + + setup() { + super.setup(); + this.setSelected(this.selected); + } + + cleanup() { + super.cleanup(); + this.blueprint.removeEventListener(Configuration.nodeDragGeneralEventName, this.dragHandler); + } + + setSelected(value = true) { + this.selected = value; + if (this.blueprint) { + if (this.selected) { + this.listeningDrag = true; + this.blueprint.addEventListener(Configuration.nodeDragGeneralEventName, this.dragHandler); + } else { + this.blueprint.removeEventListener(Configuration.nodeDragGeneralEventName, this.dragHandler); + this.listeningDrag = false; + } + } + } +} + /** @extends {ISelectableDraggableElement} */ class NodeElement extends ISelectableDraggableElement { @@ -10107,15 +10070,15 @@ class NodeElement extends ISelectableDraggableElement { } initialize(entity = new ObjectEntity(), template = new (NodeElement.getTypeTemplate(entity))()) { + this.typePath = entity.getType(); + this.nodeTitle = entity.getObjectName(); + this.advancedPinDisplay = entity.AdvancedPinDisplay?.toString(); + this.enabledState = entity.EnabledState; + this.nodeDisplayName = entity.nodeDisplayName(); + this.pureFunction = entity.bIsPureFunc; + this.dragLinkObjects = []; super.initialize(entity, template); this.#pins = this.template.createPinElements(); - this.typePath = this.entity.getType(); - this.nodeTitle = this.entity.getObjectName(); - this.advancedPinDisplay = this.entity.AdvancedPinDisplay?.toString(); - this.enabledState = this.entity.EnabledState; - this.nodeDisplayName = this.getNodeDisplayName(); - this.pureFunction = this.entity.bIsPureFunc; - this.dragLinkObjects = []; super.setLocation(this.entity.getNodePosX(), this.entity.getNodePosY()); if (this.entity.NodeWidth && this.entity.NodeHeight) { this.sizeX = this.entity.NodeWidth.value; @@ -10167,8 +10130,8 @@ class NodeElement extends ISelectableDraggableElement { return this.entity.getObjectName() } - getNodeDisplayName() { - return this.entity.nodeDisplayName() + computeNodeDisplayName() { + this.nodeDisplayName = this.entity.nodeDisplayName(); } /** @param {Number} value */ @@ -11108,7 +11071,7 @@ class BoolPinTemplate extends PinTemplate { renderInput() { return x` - + ` } } @@ -12232,6 +12195,9 @@ class PinElement extends IElement { setDefaultValue(value) { this.entity.DefaultValue = value; this.defaultValue = value; + if (this.entity.recomputesNodeTitleOnChange) { + this.nodeElement?.computeNodeDisplayName(); + } } /** @param {IElement[]} nodesWhitelist */ @@ -12267,6 +12233,9 @@ class PinElement extends IElement { if (this.entity.linkTo(targetPinElement.getNodeElement().getNodeName(), targetPinElement.entity)) { this.isLinked = this.entity.isLinked(); this.nodeElement?.template.linksChanged(); + if (this.entity.recomputesNodeTitleOnChange) { + this.nodeElement?.computeNodeDisplayName(); + } } } @@ -12278,6 +12247,9 @@ class PinElement extends IElement { if (removeLink) { this.blueprint.getLink(this, targetPinElement)?.remove(); // Might be called after the link is removed } + if (this.entity.recomputesNodeTitleOnChange) { + this.nodeElement?.computeNodeDisplayName(); + } } } @@ -12708,57 +12680,15 @@ function defineElements() { define("ueb-window", WindowElement); } -/** - * @template {AttributeConstructor} T - * @extends {Serializer} - */ -class CustomSerializer extends Serializer { - - #objectWriter - - /** - * @param {(v: ConstructedType, insideString: Boolean) => String} objectWriter - * @param {T} entityType - */ - constructor(objectWriter, entityType) { - super(entityType); - this.#objectWriter = objectWriter; - } - - /** - * @param {ConstructedType} entity - * @param {Boolean} insideString - * @returns {String} - */ - doWrite(entity, insideString, indentation = "") { - let result = this.#objectWriter(entity, insideString); - return result - } -} - class TerminalTypeEntity extends IEntity { static attributes = { ...super.attributes, - TerminalCategory: { - type: String, - }, - TerminalSubCategory: { - type: String, - }, - bTerminalIsConst: { - type: Boolean, - }, - bTerminalIsWeakPointer: { - type: Boolean, - }, - bTerminalIsUObjectWrapper: { - type: Boolean, - }, - } - - static { - this.cleanupAttributes(this.attributes); + TerminalCategory: AttributeInfo.createType(String), + TerminalSubCategory: AttributeInfo.createType(String), + bTerminalIsConst: AttributeInfo.createType(Boolean), + bTerminalIsWeakPointer: AttributeInfo.createType(Boolean), + bTerminalIsUObjectWrapper: AttributeInfo.createType(Boolean), } constructor(values) { @@ -12771,40 +12701,9 @@ class TerminalTypeEntity extends IEntity { } } -/** - * @template {AttributeConstructor} T - * @extends {Serializer} - */ -class ToStringSerializer extends Serializer { - - /** @param {T} entityType */ - constructor(entityType) { - super(entityType); - } - - /** - * @param {ConstructedType} entity - * @param {Boolean} insideString - */ - doWrite(entity, insideString, indentation = "") { - return !insideString && entity.constructor === String - ? `"${Utility.escapeString(entity.toString())}"` // String will have quotes if not inside a string already - : Utility.escapeString(entity.toString()) - } -} - class UnknownKeysEntity extends IEntity { - static attributes = { - ...super.attributes, - lookbehind: { - default: "", - ignored: true, - }, - } - static { - this.cleanupAttributes(this.attributes); - } + static grammar = this.createGrammar() static createGrammar() { @@ -12835,10 +12734,59 @@ class UnknownKeysEntity extends IEntity { constructor(values) { super(values, true); - /** @type {String} */ this.lookbehind; } } +/** + * @template {AttributeConstructor} T + * @extends {Serializer} + */ +class CustomSerializer extends Serializer { + + #objectWriter + + /** + * @param {(v: ConstructedType, insideString: Boolean) => String} objectWriter + * @param {T} entityType + */ + constructor(objectWriter, entityType) { + super(entityType); + this.#objectWriter = objectWriter; + } + + /** + * @param {ConstructedType} entity + * @param {Boolean} insideString + * @returns {String} + */ + doWrite(entity, insideString, indentation = "") { + let result = this.#objectWriter(entity, insideString); + return result + } +} + +/** + * @template {AttributeConstructor} T + * @extends {Serializer} + */ +class ToStringSerializer extends Serializer { + + /** @param {T} entityType */ + constructor(entityType) { + super(entityType); + } + + /** + * @param {ConstructedType} entity + * @param {Boolean} insideString + */ + doWrite(entity, insideString, indentation = "") { + return !insideString && entity.constructor === String + ? `"${Utility.escapeString(entity.toString())}"` // String will have quotes if not inside a string already + : Utility.escapeString(entity.toString()) + } +} + Grammar.unknownValue = Parsernostrum.alt( // Remember to keep the order, otherwise parsing might fail @@ -12847,8 +12795,8 @@ Grammar.unknownValue = Parsernostrum.str("None").map(() => new ObjectReferenceEntity({ type: "None" })), Grammar.null, Grammar.number, - Grammar.string, ObjectReferenceEntity.fullReferenceGrammar, + Grammar.string, LocalizedTextEntity.createGrammar(), InvariantTextEntity.createGrammar(), FormatTextEntity.createGrammar(), @@ -13043,6 +12991,11 @@ function initializeSerializerFactory() { new Serializer(PinReferenceEntity, undefined, " ", false, "", () => "") ); + SerializerFactory.registerSerializer( + PinTypeEntity, + new Serializer(PinTypeEntity) + ); + SerializerFactory.registerSerializer( TerminalTypeEntity, new Serializer(TerminalTypeEntity, Serializer.bracketsWrapped) diff --git a/dist/ueblueprint.min.js b/dist/ueblueprint.min.js index c0ca0df..6d1d79d 100644 --- a/dist/ueblueprint.min.js +++ b/dist/ueblueprint.min.js @@ -8,26 +8,26 @@ const e=window,t=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&" * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */;var o;const l=window,u=l.trustedTypes,c=u?u.emptyScript:"",h=l.reactiveElementPolyfillSupport,p={toAttribute(e,t){switch(t){case Boolean:e=e?c:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let i=e;switch(t){case Boolean:i=null!==e;break;case Number:i=null===e?null:Number(e);break;case Object:case Array:try{i=JSON.parse(e)}catch(e){i=null}}return i}},d=(e,t)=>t!==e&&(t==t||e==e),m={attribute:!0,type:String,converter:p,reflect:!1,hasChanged:d},g="finalized";class b extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(e){var t;this.finalize(),(null!==(t=this.h)&&void 0!==t?t:this.h=[]).push(e)}static get observedAttributes(){this.finalize();const e=[];return this.elementProperties.forEach(((t,i)=>{const s=this._$Ep(i,t);void 0!==s&&(this._$Ev.set(s,i),e.push(s))})),e}static createProperty(e,t=m){if(t.state&&(t.attribute=!1),this.finalize(),this.elementProperties.set(e,t),!t.noAccessor&&!this.prototype.hasOwnProperty(e)){const i="symbol"==typeof e?Symbol():"__"+e,s=this.getPropertyDescriptor(e,i,t);void 0!==s&&Object.defineProperty(this.prototype,e,s)}}static getPropertyDescriptor(e,t,i){return{get(){return this[t]},set(s){const r=this[e];this[t]=s,this.requestUpdate(e,r,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)||m}static finalize(){if(this.hasOwnProperty(g))return!1;this[g]=!0;const e=Object.getPrototypeOf(this);if(e.finalize(),void 0!==e.h&&(this.h=[...e.h]),this.elementProperties=new Map(e.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const e=this.properties,t=[...Object.getOwnPropertyNames(e),...Object.getOwnPropertySymbols(e)];for(const i of t)this.createProperty(i,e[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const i=new Set(e.flat(1/0).reverse());for(const e of i)t.unshift(a(e))}else void 0!==e&&t.push(a(e));return t}static _$Ep(e,t){const i=t.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof e?e.toLowerCase():void 0}_$Eu(){var e;this._$E_=new Promise((e=>this.enableUpdating=e)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(e=this.constructor.h)||void 0===e||e.forEach((e=>e(this)))}addController(e){var t,i;(null!==(t=this._$ES)&&void 0!==t?t:this._$ES=[]).push(e),void 0!==this.renderRoot&&this.isConnected&&(null===(i=e.hostConnected)||void 0===i||i.call(e))}removeController(e){var t;null===(t=this._$ES)||void 0===t||t.splice(this._$ES.indexOf(e)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((e,t)=>{this.hasOwnProperty(t)&&(this._$Ei.set(t,this[t]),delete this[t])}))}createRenderRoot(){var i;const s=null!==(i=this.shadowRoot)&&void 0!==i?i:this.attachShadow(this.constructor.shadowRootOptions);return((i,s)=>{t?i.adoptedStyleSheets=s.map((e=>e instanceof CSSStyleSheet?e:e.styleSheet)):s.forEach((t=>{const s=document.createElement("style"),r=e.litNonce;void 0!==r&&s.setAttribute("nonce",r),s.textContent=t.cssText,i.appendChild(s)}))})(s,this.constructor.elementStyles),s}connectedCallback(){var e;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(e=this._$ES)||void 0===e||e.forEach((e=>{var t;return null===(t=e.hostConnected)||void 0===t?void 0:t.call(e)}))}enableUpdating(e){}disconnectedCallback(){var e;null===(e=this._$ES)||void 0===e||e.forEach((e=>{var t;return null===(t=e.hostDisconnected)||void 0===t?void 0:t.call(e)}))}attributeChangedCallback(e,t,i){this._$AK(e,i)}_$EO(e,t,i=m){var s;const r=this.constructor._$Ep(e,i);if(void 0!==r&&!0===i.reflect){const n=(void 0!==(null===(s=i.converter)||void 0===s?void 0:s.toAttribute)?i.converter:p).toAttribute(t,i.type);this._$El=e,null==n?this.removeAttribute(r):this.setAttribute(r,n),this._$El=null}}_$AK(e,t){var i;const s=this.constructor,r=s._$Ev.get(e);if(void 0!==r&&this._$El!==r){const e=s.getPropertyOptions(r),n="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==(null===(i=e.converter)||void 0===i?void 0:i.fromAttribute)?e.converter:p;this._$El=r,this[r]=n.fromAttribute(t,e.type),this._$El=null}}requestUpdate(e,t,i){let s=!0;void 0!==e&&(((i=i||this.constructor.getPropertyOptions(e)).hasChanged||d)(this[e],t)?(this._$AL.has(e)||this._$AL.set(e,t),!0===i.reflect&&this._$El!==e&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(e,i))):s=!1),!this.isUpdatePending&&s&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var e;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((e,t)=>this[t]=e)),this._$Ei=void 0);let t=!1;const i=this._$AL;try{t=this.shouldUpdate(i),t?(this.willUpdate(i),null===(e=this._$ES)||void 0===e||e.forEach((e=>{var t;return null===(t=e.hostUpdate)||void 0===t?void 0:t.call(e)})),this.update(i)):this._$Ek()}catch(e){throw t=!1,this._$Ek(),e}t&&this._$AE(i)}willUpdate(e){}_$AE(e){var t;null===(t=this._$ES)||void 0===t||t.forEach((e=>{var t;return null===(t=e.hostUpdated)||void 0===t?void 0:t.call(e)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(e){return!0}update(e){void 0!==this._$EC&&(this._$EC.forEach(((e,t)=>this._$EO(t,this[t],e))),this._$EC=void 0),this._$Ek()}updated(e){}firstUpdated(e){}} + */;var o;const l=window,c=l.trustedTypes,u=c?c.emptyScript:"",h=l.reactiveElementPolyfillSupport,p={toAttribute(e,t){switch(t){case Boolean:e=e?u:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let i=e;switch(t){case Boolean:i=null!==e;break;case Number:i=null===e?null:Number(e);break;case Object:case Array:try{i=JSON.parse(e)}catch(e){i=null}}return i}},d=(e,t)=>t!==e&&(t==t||e==e),m={attribute:!0,type:String,converter:p,reflect:!1,hasChanged:d},g="finalized";class b extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(e){var t;this.finalize(),(null!==(t=this.h)&&void 0!==t?t:this.h=[]).push(e)}static get observedAttributes(){this.finalize();const e=[];return this.elementProperties.forEach(((t,i)=>{const s=this._$Ep(i,t);void 0!==s&&(this._$Ev.set(s,i),e.push(s))})),e}static createProperty(e,t=m){if(t.state&&(t.attribute=!1),this.finalize(),this.elementProperties.set(e,t),!t.noAccessor&&!this.prototype.hasOwnProperty(e)){const i="symbol"==typeof e?Symbol():"__"+e,s=this.getPropertyDescriptor(e,i,t);void 0!==s&&Object.defineProperty(this.prototype,e,s)}}static getPropertyDescriptor(e,t,i){return{get(){return this[t]},set(s){const r=this[e];this[t]=s,this.requestUpdate(e,r,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)||m}static finalize(){if(this.hasOwnProperty(g))return!1;this[g]=!0;const e=Object.getPrototypeOf(this);if(e.finalize(),void 0!==e.h&&(this.h=[...e.h]),this.elementProperties=new Map(e.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const e=this.properties,t=[...Object.getOwnPropertyNames(e),...Object.getOwnPropertySymbols(e)];for(const i of t)this.createProperty(i,e[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const i=new Set(e.flat(1/0).reverse());for(const e of i)t.unshift(a(e))}else void 0!==e&&t.push(a(e));return t}static _$Ep(e,t){const i=t.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof e?e.toLowerCase():void 0}_$Eu(){var e;this._$E_=new Promise((e=>this.enableUpdating=e)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(e=this.constructor.h)||void 0===e||e.forEach((e=>e(this)))}addController(e){var t,i;(null!==(t=this._$ES)&&void 0!==t?t:this._$ES=[]).push(e),void 0!==this.renderRoot&&this.isConnected&&(null===(i=e.hostConnected)||void 0===i||i.call(e))}removeController(e){var t;null===(t=this._$ES)||void 0===t||t.splice(this._$ES.indexOf(e)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((e,t)=>{this.hasOwnProperty(t)&&(this._$Ei.set(t,this[t]),delete this[t])}))}createRenderRoot(){var i;const s=null!==(i=this.shadowRoot)&&void 0!==i?i:this.attachShadow(this.constructor.shadowRootOptions);return((i,s)=>{t?i.adoptedStyleSheets=s.map((e=>e instanceof CSSStyleSheet?e:e.styleSheet)):s.forEach((t=>{const s=document.createElement("style"),r=e.litNonce;void 0!==r&&s.setAttribute("nonce",r),s.textContent=t.cssText,i.appendChild(s)}))})(s,this.constructor.elementStyles),s}connectedCallback(){var e;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(e=this._$ES)||void 0===e||e.forEach((e=>{var t;return null===(t=e.hostConnected)||void 0===t?void 0:t.call(e)}))}enableUpdating(e){}disconnectedCallback(){var e;null===(e=this._$ES)||void 0===e||e.forEach((e=>{var t;return null===(t=e.hostDisconnected)||void 0===t?void 0:t.call(e)}))}attributeChangedCallback(e,t,i){this._$AK(e,i)}_$EO(e,t,i=m){var s;const r=this.constructor._$Ep(e,i);if(void 0!==r&&!0===i.reflect){const n=(void 0!==(null===(s=i.converter)||void 0===s?void 0:s.toAttribute)?i.converter:p).toAttribute(t,i.type);this._$El=e,null==n?this.removeAttribute(r):this.setAttribute(r,n),this._$El=null}}_$AK(e,t){var i;const s=this.constructor,r=s._$Ev.get(e);if(void 0!==r&&this._$El!==r){const e=s.getPropertyOptions(r),n="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==(null===(i=e.converter)||void 0===i?void 0:i.fromAttribute)?e.converter:p;this._$El=r,this[r]=n.fromAttribute(t,e.type),this._$El=null}}requestUpdate(e,t,i){let s=!0;void 0!==e&&(((i=i||this.constructor.getPropertyOptions(e)).hasChanged||d)(this[e],t)?(this._$AL.has(e)||this._$AL.set(e,t),!0===i.reflect&&this._$El!==e&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(e,i))):s=!1),!this.isUpdatePending&&s&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var e;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((e,t)=>this[t]=e)),this._$Ei=void 0);let t=!1;const i=this._$AL;try{t=this.shouldUpdate(i),t?(this.willUpdate(i),null===(e=this._$ES)||void 0===e||e.forEach((e=>{var t;return null===(t=e.hostUpdate)||void 0===t?void 0:t.call(e)})),this.update(i)):this._$Ek()}catch(e){throw t=!1,this._$Ek(),e}t&&this._$AE(i)}willUpdate(e){}_$AE(e){var t;null===(t=this._$ES)||void 0===t||t.forEach((e=>{var t;return null===(t=e.hostUpdated)||void 0===t?void 0:t.call(e)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(e){return!0}update(e){void 0!==this._$EC&&(this._$EC.forEach(((e,t)=>this._$EO(t,this[t],e))),this._$EC=void 0),this._$Ek()}updated(e){}firstUpdated(e){}} /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ -var v;b[g]=!0,b.elementProperties=new Map,b.elementStyles=[],b.shadowRootOptions={mode:"open"},null==h||h({ReactiveElement:b}),(null!==(o=l.reactiveElementVersions)&&void 0!==o?o:l.reactiveElementVersions=[]).push("1.6.3");const y=window,f=y.trustedTypes,w=f?f.createPolicy("lit-html",{createHTML:e=>e}):void 0,S="$lit$",E=`lit$${(Math.random()+"").slice(9)}$`,C="?"+E,P=`<${C}>`,x=document,N=()=>x.createComment(""),k=e=>null===e||"object"!=typeof e&&"function"!=typeof e,A=Array.isArray,L="[ \t\n\f\r]",M=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,T=/-->/g,I=/>/g,B=RegExp(`>|${L}(?:([^\\s"'>=/]+)(${L}*=${L}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),$=/'/g,H=/"/g,G=/^(?:script|style|textarea|title)$/i,D=(e=>(t,...i)=>({_$litType$:e,strings:t,values:i}))(1),O=Symbol.for("lit-noChange"),V=Symbol.for("lit-nothing"),R=new WeakMap,z=x.createTreeWalker(x,129,null,!1);function _(e,t){if(!Array.isArray(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==w?w.createHTML(t):t}const F=(e,t)=>{const i=e.length-1,s=[];let r,n=2===t?"":"",a=M;for(let t=0;t"===l[0]?(a=null!=r?r:M,u=-1):void 0===l[1]?u=-2:(u=a.lastIndex-l[2].length,o=l[1],a=void 0===l[3]?B:'"'===l[3]?H:$):a===H||a===$?a=B:a===T||a===I?a=M:(a=B,r=void 0);const h=a===B&&e[t+1].startsWith("/>")?" ":"";n+=a===M?i+P:u>=0?(s.push(o),i.slice(0,u)+S+i.slice(u)+E+h):i+E+(-2===u?(s.push(void 0),t):h)}return[_(e,n+(e[i]||"")+(2===t?"":"")),s]};class j{constructor({strings:e,_$litType$:t},i){let s;this.parts=[];let r=0,n=0;const a=e.length-1,o=this.parts,[l,u]=F(e,t);if(this.el=j.createElement(l,i),z.currentNode=this.el.content,2===t){const e=this.el.content,t=e.firstChild;t.remove(),e.append(...t.childNodes)}for(;null!==(s=z.nextNode())&&o.length0){s.textContent=f?f.emptyScript:"";for(let i=0;iA(e)||"function"==typeof(null==e?void 0:e[Symbol.iterator]))(e)?this.T(e):this._(e)}k(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}$(e){this._$AH!==e&&(this._$AR(),this._$AH=this.k(e))}_(e){this._$AH!==V&&k(this._$AH)?this._$AA.nextSibling.data=e:this.$(x.createTextNode(e)),this._$AH=e}g(e){var t;const{values:i,_$litType$:s}=e,r="number"==typeof s?this._$AC(e):(void 0===s.el&&(s.el=j.createElement(_(s.h,s.h[0]),this.options)),s);if((null===(t=this._$AH)||void 0===t?void 0:t._$AD)===r)this._$AH.v(i);else{const e=new W(r,this),t=e.u(this.options);e.v(i),this.$(t),this._$AH=e}}_$AC(e){let t=R.get(e.strings);return void 0===t&&R.set(e.strings,t=new j(e)),t}T(e){A(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,s=0;for(const r of e)s===t.length?t.push(i=new K(this.k(N()),this.k(N()),this,this.options)):i=t[s],i._$AI(r),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=V}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(e,t=this,i,s){const r=this.strings;let n=!1;if(void 0===r)e=U(this,e,t,0),n=!k(e)||e!==this._$AH&&e!==O,n&&(this._$AH=e);else{const s=e;let a,o;for(e=r[0],a=0;ae}):void 0,S="$lit$",E=`lit$${(Math.random()+"").slice(9)}$`,C="?"+E,x=`<${C}>`,P=document,N=()=>P.createComment(""),k=e=>null===e||"object"!=typeof e&&"function"!=typeof e,T=Array.isArray,A="[ \t\n\f\r]",L=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,M=/-->/g,I=/>/g,B=RegExp(`>|${A}(?:([^\\s"'>=/]+)(${A}*=${A}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),$=/'/g,H=/"/g,V=/^(?:script|style|textarea|title)$/i,G=(e=>(t,...i)=>({_$litType$:e,strings:t,values:i}))(1),D=Symbol.for("lit-noChange"),O=Symbol.for("lit-nothing"),R=new WeakMap,z=P.createTreeWalker(P,129,null,!1);function _(e,t){if(!Array.isArray(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==w?w.createHTML(t):t}const F=(e,t)=>{const i=e.length-1,s=[];let r,n=2===t?"":"",a=L;for(let t=0;t"===l[0]?(a=null!=r?r:L,c=-1):void 0===l[1]?c=-2:(c=a.lastIndex-l[2].length,o=l[1],a=void 0===l[3]?B:'"'===l[3]?H:$):a===H||a===$?a=B:a===M||a===I?a=L:(a=B,r=void 0);const h=a===B&&e[t+1].startsWith("/>")?" ":"";n+=a===L?i+x:c>=0?(s.push(o),i.slice(0,c)+S+i.slice(c)+E+h):i+E+(-2===c?(s.push(void 0),t):h)}return[_(e,n+(e[i]||"")+(2===t?"":"")),s]};class j{constructor({strings:e,_$litType$:t},i){let s;this.parts=[];let r=0,n=0;const a=e.length-1,o=this.parts,[l,c]=F(e,t);if(this.el=j.createElement(l,i),z.currentNode=this.el.content,2===t){const e=this.el.content,t=e.firstChild;t.remove(),e.append(...t.childNodes)}for(;null!==(s=z.nextNode())&&o.length0){s.textContent=f?f.emptyScript:"";for(let i=0;iT(e)||"function"==typeof(null==e?void 0:e[Symbol.iterator]))(e)?this.T(e):this._(e)}k(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}$(e){this._$AH!==e&&(this._$AR(),this._$AH=this.k(e))}_(e){this._$AH!==O&&k(this._$AH)?this._$AA.nextSibling.data=e:this.$(P.createTextNode(e)),this._$AH=e}g(e){var t;const{values:i,_$litType$:s}=e,r="number"==typeof s?this._$AC(e):(void 0===s.el&&(s.el=j.createElement(_(s.h,s.h[0]),this.options)),s);if((null===(t=this._$AH)||void 0===t?void 0:t._$AD)===r)this._$AH.v(i);else{const e=new W(r,this),t=e.u(this.options);e.v(i),this.$(t),this._$AH=e}}_$AC(e){let t=R.get(e.strings);return void 0===t&&R.set(e.strings,t=new j(e)),t}T(e){T(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,s=0;for(const r of e)s===t.length?t.push(i=new K(this.k(N()),this.k(N()),this,this.options)):i=t[s],i._$AI(r),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=O}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(e,t=this,i,s){const r=this.strings;let n=!1;if(void 0===r)e=U(this,e,t,0),n=!k(e)||e!==this._$AH&&e!==D,n&&(this._$AH=e);else{const s=e;let a,o;for(e=r[0],a=0;a{var s,r;const n=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:t;let a=n._$litPart$;if(void 0===a){const e=null!==(r=null==i?void 0:i.renderBefore)&&void 0!==r?r:null;n._$litPart$=a=new K(t.insertBefore(N(),e),e,void 0,null!=i?i:{})}return a._$AI(e),a})(t,this.renderRoot,this.renderOptions)}connectedCallback(){var e;super.connectedCallback(),null===(e=this._$Do)||void 0===e||e.setConnected(!0)}disconnectedCallback(){var e;super.disconnectedCallback(),null===(e=this._$Do)||void 0===e||e.setConnected(!1)}render(){return O}}se.finalized=!0,se._$litElement$=!0,null===(te=globalThis.litElementHydrateSupport)||void 0===te||te.call(globalThis,{LitElement:se});const re=globalThis.litElementPolyfillSupport;null==re||re({LitElement:se}),(null!==(ie=globalThis.litElementVersions)&&void 0!==ie?ie:globalThis.litElementVersions=[]).push("3.3.3");class ne{static nodeColors={black:n``,blue:n``,darkBlue:n``,darkTurquoise:n``,gray:n``,green:n``,lime:n``,red:n``,turquoise:n``,violet:n``,yellow:n``};static alphaPattern="repeating-conic-gradient(#7c8184 0% 25%, #c2c3c4 0% 50%) 50% / 10px 10px";static colorDragEventName="ueb-color-drag";static colorPickEventName="ueb-color-pick";static colorWindowEventName="ueb-color-window";static colorWindowName="Color Picker";static defaultCommentHeight=96;static defaultCommentWidth=400;static distanceThreshold=5;static dragEventName="ueb-drag";static dragGeneralEventName="ueb-drag-general";static edgeScrollThreshold=50;static editTextEventName={begin:"ueb-edit-text-begin",end:"ueb-edit-text-end"};static expandGridSize=400;static focusEventName={begin:"blueprint-focus",end:"blueprint-unfocus"};static fontSize=n``;static gridAxisLineColor=n``;static gridExpandThreshold=.25;static gridLineColor=n``;static gridLineWidth=1;static gridSet=8;static gridSetLineColor=n``;static gridShrinkThreshold=4;static gridSize=16;static hexColorRegex=/^\s*#(?[0-9a-fA-F]{2})(?[0-9a-fA-F]{2})(?[0-9a-fA-F]{2})([0-9a-fA-F]{2})?|#(?[0-9a-fA-F])(?[0-9a-fA-F])(?[0-9a-fA-F])\s*$/;static indentation=" ";static keysSeparator=/[\.\(\)]/;static knotOffset=[-ne.gridSize,-.5*ne.gridSize];static lineTracePattern=/LineTrace(Single|Multi)(\w*)/;static linkCurveHeight=15;static linkCurveWidth=80;static linkMinWidth=100;static nameRegexSpaceReplacement=new RegExp("^K2(?:[Nn]ode)?_|(?<=[a-z])(?=[A-Z0-9])|(?<=[A-Z])(?{let s=100-e;return`M ${e} 0 C ${t.toFixed(3)} 0, ${i.toFixed(3)} 0, 50 50 S ${(s-t+e).toFixed(3)} 100, ${s.toFixed(3)} 100`};static maxZoom=7;static minZoom=-12;static mouseClickButton=0;static mouseRightClickButton=2;static mouseWheelZoomThreshold=80;static nodeDragEventName="ueb-node-drag";static nodeDragGeneralEventName="ueb-node-drag-general";static nodeTitle=(e,t)=>`${e}_${t}`;static nodeRadius=8;static nodeReflowEventName="ueb-node-reflow";static paths={actorBoundEvent:"/Script/BlueprintGraph.K2Node_ActorBoundEvent",addDelegate:"/Script/BlueprintGraph.K2Node_AddDelegate",ambientSound:"/Script/Engine.AmbientSound",asyncAction:"/Script/BlueprintGraph.K2Node_AsyncAction",blueprint:"/Script/Engine.Blueprint",blueprintGameplayTagLibrary:"/Script/GameplayTags.BlueprintGameplayTagLibrary",blueprintMapLibrary:"/Script/Engine.BlueprintMapLibrary",blueprintSetLibrary:"/Script/Engine.BlueprintSetLibrary",callArrayFunction:"/Script/BlueprintGraph.K2Node_CallArrayFunction",callDelegate:"/Script/BlueprintGraph.K2Node_CallDelegate",callFunction:"/Script/BlueprintGraph.K2Node_CallFunction",comment:"/Script/UnrealEd.EdGraphNode_Comment",commutativeAssociativeBinaryOperator:"/Script/BlueprintGraph.K2Node_CommutativeAssociativeBinaryOperator",componentBoundEvent:"/Script/BlueprintGraph.K2Node_ComponentBoundEvent",createDelegate:"/Script/BlueprintGraph.K2Node_CreateDelegate",customEvent:"/Script/BlueprintGraph.K2Node_CustomEvent",doN:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:Do N",doOnce:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:DoOnce",dynamicCast:"/Script/BlueprintGraph.K2Node_DynamicCast",eAttachmentRule:"/Script/Engine.EAttachmentRule",edGraph:"/Script/Engine.EdGraph",edGraphPinDeprecated:"/Script/Engine.EdGraphPin_Deprecated",eDrawDebugTrace:"/Script/Engine.EDrawDebugTrace",eMaterialSamplerType:"/Script/Engine.EMaterialSamplerType",enum:"/Script/CoreUObject.Enum",enumLiteral:"/Script/BlueprintGraph.K2Node_EnumLiteral",eSamplerSourceMode:"/Script/Engine.ESamplerSourceMode",eSearchCase:"/Script/CoreUObject.ESearchCase",eSearchDir:"/Script/CoreUObject.ESearchDir",eSpawnActorCollisionHandlingMethod:"/Script/Engine.ESpawnActorCollisionHandlingMethod",eTextureMipValueMode:"/Script/Engine.ETextureMipValueMode",eTraceTypeQuery:"/Script/Engine.ETraceTypeQuery",event:"/Script/BlueprintGraph.K2Node_Event",executionSequence:"/Script/BlueprintGraph.K2Node_ExecutionSequence",flipflop:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:FlipFlop",forEachElementInEnum:"/Script/BlueprintGraph.K2Node_ForEachElementInEnum",forEachLoop:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:ForEachLoop",forEachLoopWithBreak:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:ForEachLoopWithBreak",forLoop:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:ForLoop",forLoopWithBreak:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:ForLoopWithBreak",functionEntry:"/Script/BlueprintGraph.K2Node_FunctionEntry",functionResult:"/Script/BlueprintGraph.K2Node_FunctionResult",gameplayTag:"/Script/GameplayTags.GameplayTag",getInputAxisKeyValue:"/Script/BlueprintGraph.K2Node_GetInputAxisKeyValue",ifThenElse:"/Script/BlueprintGraph.K2Node_IfThenElse",inputAxisKeyEvent:"/Script/BlueprintGraph.K2Node_InputAxisKeyEvent",inputDebugKey:"/Script/InputBlueprintNodes.K2Node_InputDebugKey",inputKey:"/Script/BlueprintGraph.K2Node_InputKey",inputVectorAxisEvent:"/Script/BlueprintGraph.K2Node_InputVectorAxisEvent",isValid:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:IsValid",kismetArrayLibrary:"/Script/Engine.KismetArrayLibrary",kismetMathLibrary:"/Script/Engine.KismetMathLibrary",knot:"/Script/BlueprintGraph.K2Node_Knot",linearColor:"/Script/CoreUObject.LinearColor",literal:"/Script/BlueprintGraph.K2Node_Literal",macro:"/Script/BlueprintGraph.K2Node_MacroInstance",makeArray:"/Script/BlueprintGraph.K2Node_MakeArray",makeMap:"/Script/BlueprintGraph.K2Node_MakeMap",makeSet:"/Script/BlueprintGraph.K2Node_MakeSet",makeStruct:"/Script/BlueprintGraph.K2Node_MakeStruct",materialExpressionConstant:"/Script/Engine.MaterialExpressionConstant",materialExpressionConstant2Vector:"/Script/Engine.MaterialExpressionConstant2Vector",materialExpressionConstant3Vector:"/Script/Engine.MaterialExpressionConstant3Vector",materialExpressionConstant4Vector:"/Script/Engine.MaterialExpressionConstant4Vector",materialExpressionFunctionInput:"/Script/Engine.MaterialExpressionFunctionInput",materialExpressionLogarithm:"/Script/InterchangeImport.MaterialExpressionLogarithm",materialExpressionLogarithm10:"/Script/Engine.MaterialExpressionLogarithm10",materialExpressionLogarithm2:"/Script/Engine.MaterialExpressionLogarithm2",materialExpressionMaterialFunctionCall:"/Script/Engine.MaterialExpressionMaterialFunctionCall",materialExpressionSquareRoot:"/Script/Engine.MaterialExpressionSquareRoot",materialExpressionTextureCoordinate:"/Script/Engine.MaterialExpressionTextureCoordinate",materialExpressionTextureSample:"/Script/Engine.MaterialExpressionTextureSample",materialGraphNode:"/Script/UnrealEd.MaterialGraphNode",materialGraphNodeComment:"/Script/UnrealEd.MaterialGraphNode_Comment",multiGate:"/Script/BlueprintGraph.K2Node_MultiGate",pawn:"/Script/Engine.Pawn",pcgEditorGraphNode:"/Script/PCGEditor.PCGEditorGraphNode",pcgEditorGraphNodeInput:"/Script/PCGEditor.PCGEditorGraphNodeInput",pcgEditorGraphNodeOutput:"/Script/PCGEditor.PCGEditorGraphNodeOutput",pcgHiGenGridSizeSettings:"/Script/PCG.PCGHiGenGridSizeSettings",pcgSubgraphSettings:"/Script/PCG.PCGSubgraphSettings",promotableOperator:"/Script/BlueprintGraph.K2Node_PromotableOperator",reverseForEachLoop:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:ReverseForEachLoop",rotator:"/Script/CoreUObject.Rotator",select:"/Script/BlueprintGraph.K2Node_Select",slateBlueprintLibrary:"/Script/UMG.SlateBlueprintLibrary",spawnActorFromClass:"/Script/BlueprintGraph.K2Node_SpawnActorFromClass",switchEnum:"/Script/BlueprintGraph.K2Node_SwitchEnum",switchGameplayTag:"/Script/GameplayTagsEditor.GameplayTagsK2Node_SwitchGameplayTag",switchInteger:"/Script/BlueprintGraph.K2Node_SwitchInteger",switchName:"/Script/BlueprintGraph.K2Node_SwitchName",switchString:"/Script/BlueprintGraph.K2Node_SwitchString",timeline:"/Script/BlueprintGraph.K2Node_Timeline",timeManagementBlueprintLibrary:"/Script/TimeManagement.TimeManagementBlueprintLibrary",transform:"/Script/CoreUObject.Transform",userDefinedEnum:"/Script/Engine.UserDefinedEnum",variableGet:"/Script/BlueprintGraph.K2Node_VariableGet",variableSet:"/Script/BlueprintGraph.K2Node_VariableSet",vector:"/Script/CoreUObject.Vector",vector2D:"/Script/CoreUObject.Vector2D",whileLoop:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:WhileLoop"};static pinColor={[this.paths.rotator]:n``,[this.paths.transform]:n``,[this.paths.vector]:n``,Any:n``,"Any[]":n``,blue:n``,bool:n``,byte:n``,class:n``,default:n``,delegate:n``,enum:n``,exec:n``,green:n``,int:n``,int64:n``,interface:n``,name:n``,object:n``,Param:n``,"Param[]":n``,Point:n``,"Point[]":n``,real:n``,red:n``,string:n``,struct:n``,Surface:n``,"Surface[]":n``,text:n``,Volume:n``,"Volume[]":n``,wildcard:n``};static pinColorMaterial=n``;static pinInputWrapWidth=143;static removeEventName="ueb-element-delete";static scale={[-12]:.133333,[-11]:.166666,[-10]:.2,[-9]:.233333,[-8]:.266666,[-7]:.3,[-6]:.333333,[-5]:.375,[-4]:.5,[-3]:.675,[-2]:.75,[-1]:.875,0:1,1:1.25,2:1.375,3:1.5,4:1.675,5:1.75,6:1.875,7:2};static smoothScrollTime=1e3;static stringEscapedCharacters=/['"\\]/g;static subObjectAttributeNamePrefix="#SubObject";static subObjectAttributeNameFromEntity=(e,t=!1)=>this.subObjectAttributeNamePrefix+(!t&&e.Class?`_${e.Class.type}`:"")+"_"+e.Name;static subObjectAttributeNameFromReference=(e,t=!1)=>this.subObjectAttributeNamePrefix+(t?"":"_"+e.type)+"_"+e.path;static subObjectAttributeNameFromName=e=>this.subObjectAttributeNamePrefix+"_"+e;static switchTargetPattern=/\/Script\/[\w\.\/\:]+K2Node_Switch([A-Z]\w+)+/;static trackingMouseEventName={begin:"ueb-tracking-mouse-begin",end:"ueb-tracking-mouse-end"};static unescapedBackslash=/(?<=(?:[^\\]|^)(?:\\\\)*)\\(?!\\)/;static windowApplyEventName="ueb-window-apply";static windowApplyButtonText="OK";static windowCancelEventName="ueb-window-cancel";static windowCancelButtonText="Cancel";static windowCloseEventName="ueb-window-close";static CommonEnums={[this.paths.eAttachmentRule]:["KeepRelative","KeepWorld","SnapToTarget"],[this.paths.eMaterialSamplerType]:["Color","Grayscale","Alpha","Normal","Masks","Distance Field Font","Linear Color","Linear Grayscale","Data","External","Virtual Color","Virtual Grayscale","Virtual Alpha","Virtual Normal","Virtual Mask","Virtual Linear Color","Virtual Linear Grayscal"],[this.paths.eSamplerSourceMode]:["From texture asset","Shared: Wrap","Shared: Clamp","Hidden"],[this.paths.eSpawnActorCollisionHandlingMethod]:[["Undefined","Default"],["AlwaysSpawn","Always Spawn, Ignore Collisions"],["AdjustIfPossibleButAlwaysSpawn","Try To Adjust Location, But Always Spawn"],["AdjustIfPossibleButDontSpawnIfColliding","Try To Adjust Location, Don't Spawn If Still Colliding"],["DontSpawnIfColliding","Do Not Spawn"]],[this.paths.eSearchCase]:["CaseSensitive","IgnoreCase"],[this.paths.eSearchDir]:["FromStart","FromEnd"],[this.paths.eDrawDebugTrace]:["None","ForOneFrame","ForDuration","Persistent"],[this.paths.eTextureMipValueMode]:["None (use computed mip level)","MipLevel (absolute, 0 is full resolution)","MipBias (relative to the computed mip level)","Derivative (explicit derivative to compute mip level)"],[this.paths.eTraceTypeQuery]:[["TraceTypeQuery1","Visibility"],["TraceTypeQuery2","Camera"]]};static ModifierKeys=["Ctrl","Shift","Alt","Meta"];static Keys={Backspace:"Backspace",Tab:"Tab",LeftControl:"ControlLeft",RightControl:"ControlRight",LeftShift:"ShiftLeft",RightShift:"ShiftRight",LeftAlt:"AltLeft",RightAlt:"AltRight",Enter:"Enter",Pause:"Pause",CapsLock:"CapsLock",Escape:"Escape",Space:"Space",PageUp:"PageUp",PageDown:"PageDown",End:"End",Home:"Home",ArrowLeft:"ArrowLeft",ArrowUp:"ArrowUp",ArrowRight:"ArrowRight",ArrowDown:"ArrowDown",PrintScreen:"PrintScreen",Insert:"Insert",Delete:"Delete",Zero:"Digit0",One:"Digit1",Two:"Digit2",Three:"Digit3",Four:"Digit4",Five:"Digit5",Six:"Digit6",Seven:"Digit7",Eight:"Digit8",Nine:"Digit9",A:"KeyA",B:"KeyB",C:"KeyC",D:"KeyD",E:"KeyE",F:"KeyF",G:"KeyG",H:"KeyH",I:"KeyI",K:"KeyK",L:"KeyL",M:"KeyM",N:"KeyN",O:"KeyO",P:"KeyP",Q:"KeyQ",R:"KeyR",S:"KeyS",T:"KeyT",U:"KeyU",V:"KeyV",W:"KeyW",X:"KeyX",Y:"KeyY",Z:"KeyZ",NumPadZero:"Numpad0",NumPadOne:"Numpad1",NumPadTwo:"Numpad2",NumPadThree:"Numpad3",NumPadFour:"Numpad4",NumPadFive:"Numpad5",NumPadSix:"Numpad6",NumPadSeven:"Numpad7",NumPadEight:"Numpad8",NumPadNine:"Numpad9",Multiply:"NumpadMultiply",Add:"NumpadAdd",Subtract:"NumpadSubtract",Decimal:"NumpadDecimal",Divide:"NumpadDivide",F1:"F1",F2:"F2",F3:"F3",F4:"F4",F5:"F5",F6:"F6",F7:"F7",F8:"F8",F9:"F9",F10:"F10",F11:"F11",F12:"F12",NumLock:"NumLock",ScrollLock:"ScrollLock"}}class ae{#e;get target(){return this.#e}#t;get blueprint(){return this.#t}consumeEvent;options;listenHandler=()=>this.listenEvents();unlistenHandler=()=>this.unlistenEvents();constructor(e,t,i={}){i.consumeEvent??=!1,i.listenOnFocus??=!1,i.unlistenOnTextEdit??=!1,this.#e=e,this.#t=t,this.consumeEvent=i.consumeEvent,this.options=i}setup(){this.options.listenOnFocus&&(this.blueprint.addEventListener(ne.focusEventName.begin,this.listenHandler),this.blueprint.addEventListener(ne.focusEventName.end,this.unlistenHandler)),this.options.unlistenOnTextEdit&&(this.blueprint.addEventListener(ne.editTextEventName.begin,this.unlistenHandler),this.blueprint.addEventListener(ne.editTextEventName.end,this.listenHandler)),this.blueprint.focused&&this.listenEvents()}cleanup(){this.unlistenEvents(),this.blueprint.removeEventListener(ne.focusEventName.begin,this.listenHandler),this.blueprint.removeEventListener(ne.focusEventName.end,this.unlistenHandler),this.blueprint.removeEventListener(ne.editTextEventName.begin,this.unlistenHandler),this.blueprint.removeEventListener(ne.editTextEventName.end,this.listenHandler)}listenEvents(){}unlistenEvents(){}}class oe{#i;constructor(e){this.#i=e}compute(e){return this.#i(e)}}class le{static attributes={type:{ignored:!0},getter:{ignored:!0}};constructor(e,t=null){this.type=e,this.getter=t}get(){return this.getter()}getTargetType(){const e=this.type;return e instanceof le?e.getTargetType():e}}class ue{static makeSuccess(e,t,i=null,s=0){return{status:!0,value:t,position:e,bestParser:i,bestPosition:s}}static makeFailure(e=0,t=null,i=0){return{status:!1,value:null,position:e,bestParser:t,bestPosition:i}}static makeContext(e=null,t=""){return{parsernostrum:e,input:t,highlighted:null}}static makePathNode(e,t=0,i=null){return{parent:i,parser:e,index:t}}}class ce{static indentation=" ";static highlight="Last valid parser";Self;static appendBeforeHighlight(e,t){return e.endsWith(ce.highlight)?e=e.replace(/(?=(?:\n|^).+$)/,t):e+=t,e}static lastRowLength(e,t=0){const i=e.match(/(?:\n|(^))([^\n]*)$/),s=void 0!==i[1]?t:0;return i[2].length+s}isHighlighted(e,t){if(e.highlighted instanceof ce)return e.highlighted===this;if(!e.highlighted||!t)return!1;let i,s,r,n;e:for(i=t,r=e.highlighted;i&&r;s=i,i=i.parent,n=r,r=r.parent)if(i.parser!==r.parser||i.index!==r.index){if(!s||!n)return!1;let e,t;for(e=i,t=r;e||t;e=e?.parent,t=t?.parent){const a=e?.parser===s.parser,o=t?.parser===n.parser;if(a||o){a&&(s=e),o&&(n=t),i=s,r=n;continue e}}return!1}return!0}isVisited(e){if(!e)return!1;for(e=e.parent;null!=e;e=e.parent)if(e.parser===this)return!0;return!1}parse(e,t,i){return null}toString(e=ue.makeContext(null,""),t=0,i=null){if(this.isVisited(i))return"<...>";return this.doToString(e,t,i)}doToString(e,t,i){return`${this.constructor.name} does not implement toString()`}}class he extends ce{#s;get value(){return this.#s}constructor(e){super(),this.#s=e}parse(e,t,i){const s=t+this.#s.length,r=e.input.substring(t,s);return this.#s===r?ue.makeSuccess(s,this.#s,i,s):ue.makeFailure()}doToString(e,t,i){const s=this.value.replaceAll("\n","\\n");let r=this.value.match(/^[a-zA-Z]$/)?s:`"${s.replaceAll('"','\\"')}"`;return this.isHighlighted(e,i)&&(r+="\n"+ce.indentation.repeat(t)+"^".repeat(r.length)+" "+ce.highlight),r}}class pe extends ce{static instance=new pe;parse(e,t,i){return ue.makeSuccess(t,"",i,0)}doToString(e,t,i){return""+(this.isHighlighted(e,i)?`\n${ce.indentation.repeat(t)}^^^^^^^^^ ${ce.highlight}`:"")}}class de extends ce{static highlightRegexp=new RegExp(String.raw`(?<=[^\S\n]*\| .*\n)^(?=[^\S\n]*\^+ ${ce.highlight}(?:\n|$))`,"m");#r;get parsers(){return this.#r}constructor(...e){super(),this.#r=e}parse(e,t,i){const s=ue.makeSuccess(0,"");for(let r=0;rs.bestPosition&&(s.bestParser=n.bestParser,s.bestPosition=n.bestPosition),n.status)return s.value=n.value,s.position=n.position,s}return s.status=!1,s.value=null,s}doToString(e,t,i){const s=ce.indentation.repeat(t),r=ce.indentation.repeat(t+1);if(2===this.#r.length&&this.#r[1]instanceof pe){let s=this.#r[0].toString(e,t,{parent:i,parser:this.#r[0],index:0});return this.#r[0]instanceof he||(s="<"+s+">"),s+="?",s}let n=this.#r.map(((s,r)=>s.toString(e,t+1,{parent:i,parser:s,index:r}))).join("\n"+r+"| ");return e.highlighted&&(n=n.replace(de.highlightRegexp," ")),"ALT<\n"+(this.isHighlighted(e,i)?`${s}^^^ ${ce.highlight}\n`:"")+r+n+"\n"+s+">"}}class me extends ce{#n;get parser(){return this.#n}#a;constructor(e,t){super(),this.#n=e,this.#a=t}parse(e,t,i){const s=this.#n.parse(e,t,{parent:i,parser:this.#n,index:0});if(!s.status)return s;const r=this.#a(s.value,e.input,s.position).getParser().parse(e,s.position);return s.bestPosition>r.bestPosition&&(r.bestParser=s.bestParser,r.bestPosition=s.bestPosition),r}doToString(e,t,i){const s="chained";let r=this.#n.toString(e,t,{parent:i,parser:this.#n,index:0});return this.isHighlighted(e,i)?r+=" => "+s+"\n"+ce.indentation.repeat(t)+" ".repeat(r.match(/(?:\n|^)([^\n]+)$/)?.[1].length+4)+"^".repeat(12)+" "+ce.highlight:r=ce.appendBeforeHighlight(r," => "+s),r}}class ge extends ce{static instance=new ge;parse(e,t,i){return ue.makeFailure()}doToString(e,t,i){return""+(this.isHighlighted(e,i)?`\n${ce.indentation.repeat(t)}^^^^^^^^^ ${ce.highlight}`:"")}}class be extends ce{#n;#o;constructor(e){super(),this.#n=e}resolve(){return this.#o||(this.#o=this.#n().getParser()),this.#o}parse(e,t,i){return this.resolve(),this.#o.parse(e,t,{parent:i,parser:this.#o,index:0})}doToString(e,t,i){const s={parent:i,parser:this.#o,index:0};return this.isHighlighted(e,i)&&(e.highlighted=e.highlighted instanceof ce?this.#o:s),this.resolve().toString(e,t,s)}}class ve extends ce{#n;get parser(){return this.#n}#l;get type(){return this.#l}static Type={NEGATIVE_AHEAD:"?!",NEGATIVE_BEHIND:"?String.raw`[^${e}\\]*(?:\\.[^${e}\\]*)*`;static#d=/[-\+]?(?:\d*\.)?\d+/;static common={number:new RegExp(this.#d.source+String.raw`(?!\.)`),numberInteger:/[\-\+]?\d+(?!\.\d)/,numberNatural:/\d+/,numberExponential:new RegExp(this.#d.source+String.raw`(?:[eE][\+\-]?\d+)?(?!\.)`),numberUnit:/\+?(?:0(?:\.\d+)?|1(?:\.0+)?)(?![\.\d])/,numberByte:/0*(?:25[0-5]|2[0-4]\d|1?\d?\d)(?!\d|\.)/,whitespace:/\s+/,whitespaceOpt:/\s*/,whitespaceInline:/[^\S\n]+/,whitespaceInlineOpt:/[^\S\n]*/,whitespaceMultiline:/\s*?\n\s*/,doubleQuotedString:new RegExp(`"(${this.#p('"')})"`),singleQuotedString:new RegExp(`'(${this.#p("'")})'`),backtickQuotedString:new RegExp("`("+this.#p("`")+")`")};constructor(e,t){super(),this.#u=e,this.#c=new RegExp(`^(?:${e.source})`,e.flags),this.#h=t}parse(e,t,i){const s=this.#c.exec(e.input.substring(t));s&&(t+=s[0].length);return s?ue.makeSuccess(t,this.#h(s),i,t):ue.makeFailure()}doToString(e,t,i){let s="/"+this.#u.source+"/";const r=Object.entries(ye.common).find((([e,t])=>t.source===this.#u.source))?.[0];return r&&(s="P."+r),this.isHighlighted(e,i)&&(s+="\n"+ce.indentation.repeat(t)+"^".repeat(s.length)+" "+ce.highlight),s}}class fe extends ce{#n;get parser(){return this.#n}#m;get mapper(){return this.#m}constructor(e,t){super(),this.#n=e,this.#m=t}parse(e,t,i){const s=this.#n.parse(e,t,{parent:i,parser:this.#n,index:0});return s.status&&(s.value=this.#m(s.value)),s}doToString(e,t,i){const s={parent:i,parser:this.#n,index:0};this.isHighlighted(e,i)&&(e.highlighted=e.highlighted instanceof ce?this.#n:s);let r=this.#n.toString(e,t,s);if(this.#n instanceof ye&&Object.values(ye.common).includes(this.#n.regexp))return this.#n.regexp===ye.common.numberInteger&&this.#m===BigInt?"P.numberBigInteger":r;let n=this.#m.toString();return(n.length>60||n.includes("\n"))&&(n="(...) => { ... }"),n=` -> map<${n}>`,r=ce.appendBeforeHighlight(r,n),r}}class we extends ye{static#m=e=>e;constructor(e){super(e,we.#m)}}class Se extends ye{constructor(e,t=0){super(e,(e=>e[t]))}}class Ee extends ce{#r;get parsers(){return this.#r}constructor(...e){super(),this.#r=e}parse(e,t,i){const s=new Array(this.#r.length),r=ue.makeSuccess(t,s);for(let t=0;tr.bestPosition&&(r.bestParser=s.bestParser,r.bestPosition=s.bestPosition),!s.status){r.status=!1,r.value=null;break}r.value[t]=s.value,r.position=s.position}return r}doToString(e,t,i){const s=ce.indentation.repeat(t),r=ce.indentation.repeat(t+1);return"SEQ<\n"+(this.isHighlighted(e,i)?`${s}^^^ ${ce.highlight}\n`:"")+this.#r.map(((s,n)=>r+s.toString(e,t+1,{parent:i,parser:s,index:n}))).join("\n")+"\n"+s+">"}}class Ce extends ce{#n;get parser(){return this.#n}#g;get min(){return this.#g}#b;get max(){return this.#b}constructor(e,t=0,i=Number.POSITIVE_INFINITY){if(super(),t>i)throw new Error("Min is greater than max");this.#n=e,this.#g=t,this.#b=i}parse(e,t,i){const s=ue.makeSuccess(t,[],i);for(let t=0;ts.bestPosition&&(s.bestParser=r.bestParser,s.bestPosition=r.bestPosition),!r.status){te;static#y=([e,t])=>t;static#f=([e,t])=>[e,...t];static#w=e=>e instanceof Array?e.join(""):e;static#p=e=>String.raw`[^${e}\\]*(?:\\.[^${e}\\]*)*`;static number=this.reg(ye.common.number).map(Number);static numberInteger=this.reg(ye.common.numberInteger).map(Number);static numberBigInteger=this.reg(this.numberInteger.getParser().parser.regexp).map(BigInt);static numberNatural=this.reg(ye.common.numberNatural).map(Number);static numberExponential=this.reg(ye.common.numberExponential).map(Number);static numberUnit=this.reg(ye.common.numberUnit).map(Number);static numberByte=this.reg(ye.common.numberByte).map(Number);static whitespace=this.reg(ye.common.whitespace);static whitespaceOpt=this.reg(ye.common.whitespaceOpt);static whitespaceInline=this.reg(ye.common.whitespaceInline);static whitespaceInlineOpt=this.reg(ye.common.whitespaceInlineOpt);static whitespaceMultiline=this.reg(ye.common.whitespaceMultiline);static doubleQuotedString=this.reg(ye.common.doubleQuotedString,1);static singleQuotedString=this.reg(ye.common.singleQuotedString,1);static backtickQuotedString=this.reg(ye.common.backtickQuotedString,1);constructor(e,t=!1){this.#n=e}getParser(){return this.#n}run(e){const t=this.#n.parse(ue.makeContext(this,e),0,ue.makePathNode(this.#n));return t.position!==e.length&&(t.status=!1),t}parse(e){const t=this.run(e);if(!t.status){const i=60,s=[Math.ceil(i/2),Math.floor(i/2)],r=Pe.lineColumnFromOffset(e,t.bestPosition);let n=t.bestPosition;const a=e.replaceAll(/^(\s)+|\s{6,}|\s*?\n\s*/g,((e,i,s)=>{let r=i?"...":" ... ";return s<=t.bestPosition&&(t.bestPosition0&&(c="..."+c,u+=3),s[1]e.getParser()))));return t}static alt(...e){return new this(new de(...e.map((e=>e.getParser()))))}static lookahead(e){return new this(new ve(e.getParser(),ve.Type.POSITIVE_AHEAD))}static lazy(e){return new this(new be(e))}times(e,t=e){return new Pe(new Ce(this.#n,e,t))}many(){return this.times(0,Number.POSITIVE_INFINITY)}atLeast(e){return this.times(e,Number.POSITIVE_INFINITY)}atMost(e){return this.times(0,e)}opt(){return Pe.alt(this,Pe.success())}sepBy(e,t=!1){return Pe.seq(this,Pe.seq(e,this).map(Pe.#y).many()).map(Pe.#f)}skipSpace(){return Pe.seq(this,Pe.whitespaceOpt).map(Pe.#v)}map(e){return new Pe(new fe(this.#n,e))}chain(e){return new Pe(new me(this.#n,e))}assert(e){return this.chain(((t,i,s)=>e(t,i,s)?Pe.success().map((()=>t)):Pe.failure()))}join(e=""){return this.map(Pe.#w)}toString(e=0,t=!1,i=null){i instanceof Pe&&(i=i.getParser());const s=ue.makeContext(this,"");return s.highlighted=i,(t?"\n"+ce.indentation.repeat(e):"")+this.#n.toString(s,e,ue.makePathNode(this.#n))}}class xe{static grammar=this.createGrammar();static createGrammar(){return Pe.failure()}}class Ne{static#S=new Map;static registerSerializer(e,t){Ne.#S.set(e,t)}static getSerializer(e){return Ne.#S.get(e)}}class ke{#E;get values(){return this.#E}constructor(...e){this.#E=e}}class Ae{static booleanConverter={fromAttribute:(e,t)=>{},toAttribute:(e,t)=>!0===e?"true":!1===e?"false":""};static sigmoid(e,t=1.7){return 1/(1+e/(1-e)**-t)}static sigmoidPositive(e,t=3.7,i=1.1){return 1-Math.exp(-((e/i)**t))}static clamp(e,t=-1/0,i=1/0){return Math.min(Math.max(e,t),i)}static getScale(e){const t=e.blueprint?.getScale()??getComputedStyle(e).getPropertyValue("--ueb-scale");return""!=t?parseFloat(t):1}static minDecimals(e,t=1,i=1e-8){const s=e*10**t;return Math.abs(s%1)>i?e.toString():e.toFixed(t)}static numberFromText(e=""){switch(e=e.toLowerCase()){case"zero":return 0;case"one":return 1;case"two":return 2;case"three":return 3;case"four":return 4;case"five":return 5;case"six":return 6;case"seven":return 7;case"eight":return 8;case"nine":return 9}}static roundDecimals(e,t=1){const i=10**t;return Math.round(e*i)/i}static printNumber(e){return e==Number.POSITIVE_INFINITY?"inf":e==Number.NEGATIVE_INFINITY?"-inf":Ae.minDecimals(e)}static printExponential(e){if(e==Number.POSITIVE_INFINITY)return"inf";if(e==Number.NEGATIVE_INFINITY)return"-inf";const t=Math.round(e);if(t>=1e3){const i=Math.floor(Math.log10(t));return`${Math.round(e/10**(i-2))/100}e+${i<10?"0":""}${i}`}return 0==Math.floor(e)?e.toString():this.roundDecimals(e,Math.max(0,3-Math.floor(e).toString().length)).toString()}static approximatelyEqual(e,t,i=1e-8){return!(Math.abs(e-t)>i)}static convertLocation(e,t,i=!1){const s=i?1:1/Ae.getScale(t),r=t.getBoundingClientRect();return[Math.round((e[0]-r.x)*s),Math.round((e[1]-r.y)*s)]}static isSerialized(e,t){return e.attributes?.[t]?.serialized??e.constructor.attributes?.[t]?.serialized??!1}static objectGet(e,t,i=void 0){if(void 0!==e){if(!(t instanceof Array))throw new TypeError("UEBlueprint: Expected keys to be an array");return 0!=t.length&&t[0]in e&&void 0!==e[t[0]]?1==t.length?e[t[0]]:Ae.objectGet(e[t[0]],t.slice(1),i):i}}static objectSet(e,t,i,s=Object){if(!(t instanceof Array))throw new TypeError("Expected keys to be an array.");if(1==t.length){if(t[0]in e||void 0===e[t[0]])return e[t[0]]=i,!0}else if(t.length>0)return e[t[0]]instanceof Object||(e[t[0]]=new s),Ae.objectSet(e[t[0]],t.slice(1),i,s);return!1}static equals(e,t){return e?.equals&&t?.equals?e.equals(t):(e=Ae.sanitize(e),t=Ae.sanitize(t),e?.constructor===BigInt&&t?.constructor===Number?t=BigInt(t):e?.constructor===Number&&t?.constructor===BigInt&&(e=BigInt(e)),e===t||e instanceof Array&&t instanceof Array&&(e.length===t.length&&e.every(((e,i)=>Ae.equals(e,t[i])))))}static getType(e){return null===e?null:e?.constructor===Object&&e?.type instanceof Function?e.type:e?.constructor}static isValueOfType(e,t,i=!1){return t instanceof le&&(t=t.getTargetType()),i&&null===e||e instanceof t||e?.constructor===t}static sanitize(e,t=e?.constructor){if(t instanceof Array&&(t=t[0]),t instanceof oe)return e;if(t instanceof ke){let i=t.values.find((t=>Ae.isValueOfType(e,t,!1)));i||(i=t.values[0]),t=i}return t instanceof le?e instanceof le?e:Ae.sanitize(e,t.getTargetType()):(t&&!Ae.isValueOfType(e,t,!0)&&(e=t===BigInt?BigInt(e):new t(e)),(e instanceof Boolean||e instanceof Number||e instanceof String)&&(e=e.valueOf()),e)}static snapToGrid(e,t,i){return 1===i?[e,t]:[i*Math.floor(e/i),i*Math.floor(t/i)]}static mergeArrays(e=[],t=[]){let i=[];e=[...e],t=[...t];e:for(;;){for(let s=0;s|
/g,"\n").replaceAll(/(\)/g,"")}static encodeHTMLWhitespace(e){return e.replaceAll(" "," ")}static capitalFirstLetter(e){return 0===e.length?e:e.charAt(0).toUpperCase()+e.slice(1)}static formatStringName(e=""){return e.replace(/^\s*b(?=[A-Z])/,"").replaceAll(ne.nameRegexSpaceReplacement," ").trim().split(" ").map((e=>Ae.capitalFirstLetter(e))).join(" ")}static getIdFromReference(e){return e.replace(/(?:.+\.)?([^\.]+)$/,"$1").replaceAll(/(?<=[a-z\d])(?=[A-Z])|(?<=[a-zA-Z])(?=\d)|(?<=[A-Z]{2})(?=[A-Z][a-z])/g,"-").toLowerCase()}static getNameFromPath(e){return e.match(/[^\.\/]+$/)?.[0]??""}static printLinearColor(e){return`${Math.round(255*e.R.valueOf())}, ${Math.round(255*e.G.valueOf())}, ${Math.round(255*e.B.valueOf())}`}static getPolarCoordinates(e,t,i=!1){let s=Math.atan2(t,e);return i&&s<0&&(s=2*Math.PI+s),[Math.sqrt(e*e+t*t),s]}static getCartesianCoordinates(e,t){return[e*Math.cos(t),e*Math.sin(t)]}static range(e=0,t=0,i=(t>=e?1:-1)){return Array.from({length:Math.ceil((t-e)/i)},((t,s)=>e+s*i))}static paste(e,t){const i=new ClipboardEvent("paste",{bubbles:!0,cancelable:!0,clipboardData:new DataTransfer});i.clipboardData.setData("text",t),e.dispatchEvent(i)}static async copy(e){const t=new ClipboardEvent("copy",{bubbles:!0,cancelable:!0,clipboardData:new DataTransfer});e.dispatchEvent(t)}static animate(e,t,i,s,r=(e=>{}),n=(e=>{const t=e**3.5;return t/(t+(1-e)**3.5)})){let a;const o=l=>{void 0===a&&(a=l);let u=(l-a)/i;Ae.approximatelyEqual(u,1)||u>1?u=1:r(requestAnimationFrame(o));const c=e+(t-e)*n(u);s(c)};r(requestAnimationFrame(o))}}class Le extends xe{static lookbehind="";static attributes={lookbehind:{ignored:!0}};static defaultAttribute={nullable:!1,ignored:!1,serialized:!1,expected:!1,inlined:!1,quoted:!1};constructor(e={},t=!1){super(),this.lookbehind;const i=this.constructor;let s=i.attributes;e.attributes&&(s={...i.attributes},Ae.mergeArrays(Object.keys(e.attributes),Object.keys(s)).forEach((t=>{s[t]={...Le.defaultAttribute,...s[t],...e.attributes[t]},s[t].type||(s[t].type=e[t]instanceof Array?[Ae.getType(e[t][0])]:Ae.getType(e[t]))})),Le.defineAttributes(this,s)),this.attributes;const r=Object.keys(e),n=Object.keys(s),a=Ae.mergeArrays(r,n);r.includes("lookbehind")&&(this.lookbehind=void 0);for(const r of a){if("attributes"==r)continue;let n=e[r],a=s[r];if(!t&&void 0!==n&&!(r in s)&&!r.startsWith(ne.subObjectAttributeNamePrefix)){const e=n instanceof Array?`[${n[0]?.constructor.name}]`:n.constructor.name;console.warn(`UEBlueprint: Attribute ${r} (of type ${e}) in the serialized data is not defined in ${i.name}.attributes`)}if(!a){this[r]=n;continue}const o=a.predicate?e=>{Object.defineProperties(this,{["#"+r]:{writable:!0,enumerable:!1},[r]:{enumerable:!0,get(){return this["#"+r]},set(e){a.predicate?.(e)?this["#"+r]=e:console.warn(`UEBlueprint: Tried to assign attribute ${r} to ${i.name} not satisfying the predicate`)}}}),this[r]=e}:e=>this[r]=e;let l=a.default;l instanceof Function&&(l=l(this));let u=a.type;u instanceof oe&&(u=u.compute(this)),u instanceof Array&&(u=Array),void 0===u&&(u=Ae.getType(l)),void 0===n?Object.hasOwn(a,"default")&&o(l):(n?.constructor===String&&a.serialized&&u!==String&&(n=Ne.getSerializer(u).read(n)),o(Ae.sanitize(n,u)))}}static defaultValueProviderFromType(e){return e!==Boolean&&(e===Number?0:e===BigInt?0n:e===String?"":e===Array||e instanceof Array?()=>[]:e instanceof ke?this.defaultValueProviderFromType(e.values[0]):e instanceof le?()=>new le(e.type,e.getter):e instanceof oe?void 0:()=>new e)}static cleanupAttributes(e,t=""){for(const i in e){e[i]={...Le.defaultAttribute,...e[i]};const s=e[i];if(void 0!==s.type||s.default instanceof Function||(s.type=s.default instanceof Array?[Ae.getType(s.default[0])]:Ae.getType(s.default)),!s.ignored&&void 0===s.default&&void 0===s.type)throw new Error(`UEBlueprint: Expected either "type" or "value" property in ${this.name} attribute ${t}`+i);null===s.default&&(s.nullable=!0)}}static isValueOfType(e,t){return null!=e&&(e instanceof t||e.constructor===t)}static expectsAllKeys(){return!Object.values(this.attributes).filter((e=>!e.ignored)).some((e=>!e.expected))}static getAttribute(e,t){return this.getAttributes(e)[t]}static getAttributes(e){return e.attributes??e.constructor?.attributes??{}}static defineAttributes(e,t){Object.defineProperty(e,"attributes",{writable:!0,configurable:!1}),e.attributes=t}getLookbehind(){let e=this.lookbehind??this.constructor.lookbehind;return e=e instanceof ke?e.values[0]:e,e}unexpectedKeys(){return Object.keys(this).length-Object.keys(this.constructor.attributes).length}equals(e){const t=Object.keys(this),i=Object.keys(e);if(t.length!=i.length)return!1;for(const i of t){if(this[i]instanceof Le&&!this[i].equals(e[i]))return!1;if(!Ae.equals(this[i],e[i]))return!1}return!0}}class Me{static separatedBy=(e,t,i=1)=>new RegExp(e+"(?:"+t+e+")"+(1===i?"*":2===i?"+":`{${i},}`));static Regex=class{static HexDigit=/[0-9a-fA-F]/;static InsideString=/(?:[^"\\]|\\.)*/;static InsideSingleQuotedString=/(?:[^'\\]|\\.)*/;static Integer=/[\-\+]?\d+(?!\d|\.)/;static Number=/[-\+]?(?:\d*\.)?\d+(?!\d|\.)/;static RealUnit=/\+?(?:0(?:\.\d+)?|1(?:\.0+)?)(?![\.\d])/;static Word=Me.separatedBy("[a-zA-Z]","_");static Symbol=/[a-zA-Z_]\w*/;static DotSeparatedSymbols=Me.separatedBy(this.Symbol.source,"\\.");static PathFragment=Me.separatedBy(this.Symbol.source,"[\\.:]");static PathSpaceFragment=Me.separatedBy(this.Symbol.source,"[\\.:\\ ]");static Path=new RegExp(`(?:\\/${this.PathFragment.source}){2,}`)};static null=Pe.reg(/\(\s*\)/).map((()=>null));static true=Pe.reg(/true/i).map((()=>!0));static false=Pe.reg(/false/i).map((()=>!1));static boolean=Pe.regArray(/(true)|false/i).map((e=>!!e[1]));static number=Pe.regArray(new RegExp(`(${Pe.number.getParser().parser.regexp.source})|(\\+?inf)|(-inf)`)).map((([e,t,i,s])=>t?Number(t):i?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY));static bigInt=Pe.reg(new RegExp(Pe.number.getParser().parser.regexp.source)).map(BigInt).map((e=>void 0!==e[2]?Number.POSITIVE_INFINITY:void 0!==e[3]?Number.NEGATIVE_INFINITY:Number(e[1])));static naturalNumber=Pe.lazy((()=>Pe.reg(/\d+/).map(Number)));static string=Pe.doubleQuotedString.map((e=>Ae.unescapeString(e)));static colorValue=Pe.numberByte;static word=Pe.reg(Me.Regex.Word);static symbol=Pe.reg(Me.Regex.Symbol);static symbolQuoted=Pe.reg(new RegExp('"('+Me.Regex.Symbol.source+')"'),1);static attributeName=Pe.reg(Me.Regex.DotSeparatedSymbols);static attributeNameQuoted=Pe.reg(new RegExp('"('+Me.Regex.DotSeparatedSymbols.source+')"'),1);static guid=Pe.reg(new RegExp(`${Me.Regex.HexDigit.source}{32}`));static commaSeparation=Pe.reg(/\s*,\s*(?!\))/);static commaOrSpaceSeparation=Pe.reg(/\s*,\s*(?!\))|\s+/);static equalSeparation=Pe.reg(/\s*=\s*/);static hexColorChannel=Pe.reg(new RegExp(Me.Regex.HexDigit.source+"{2}"));static grammarFor(e,t=(e?.constructor===Object?e.type:e?.constructor),i=this.unknownValue){let s=i;if(t instanceof Array){if(e?.inlined)return this.grammarFor(void 0,t[0]);s=Pe.seq(Pe.reg(/\(\s*/),this.grammarFor(void 0,t[0]).sepBy(this.commaSeparation),Pe.reg(/\s*(?:,\s*)?\)/)).map((([e,t,i])=>t))}else if(t instanceof ke)s=t.values.map((e=>this.grammarFor(void 0,e))).reduce(((e,t)=>t&&t!==this.unknownValue&&e!==this.unknownValue?Pe.alt(e,t):this.unknownValue));else{if(t instanceof le)return this.grammarFor(void 0,t.getTargetType()).map((e=>new le(t.type,(()=>e))));if(e?.constructor===Object)s=this.grammarFor(void 0,t);else switch(t){case Boolean:s=this.boolean;break;case Number:s=this.number;break;case BigInt:s=this.bigInt;break;case String:s=this.string;break;default:if(t?.prototype instanceof xe)return t.grammar}}return e?.constructor===Object&&(e.serialized&&t.constructor!==String&&(s=s==this.unknownValue?this.string:Pe.seq(Pe.str('"'),s,Pe.str('"'))),e.nullable&&(s=Pe.alt(s,this.null))),s}static getAttribute(e,t){let i,s;if(e instanceof ke)for(let s of e.values)if(i=this.getAttribute(s,t))return i;return e instanceof Le.constructor?(i=e.attributes[t[0]],s=i?.type):e instanceof Array&&(i=e[t[0]],s=i),t.length>1?this.getAttribute(s,t.slice(1)):i}static createAttributeGrammar(e,t=this.attributeName,i=this.equalSeparation,s=((e,t,i)=>{})){return Pe.seq(t,i).chain((([t,i])=>{const r=t.split(ne.keysSeparator),n=this.getAttribute(e,r);return this.grammarFor(n).map((e=>t=>{s(t,r,e),Ae.objectSet(t,r,e)}))}))}static createEntityGrammar=(e,t=!0,i=this.commaSeparation)=>Pe.seq(Pe.reg(e.lookbehind instanceof ke?new RegExp(`(${e.lookbehind.values.reduce(((e,t)=>e+"|"+t))})\\s*\\(\\s*`):e.lookbehind.constructor==String&&e.lookbehind.length?new RegExp(`(${e.lookbehind})\\s*\\(\\s*`):/()\(\s*/,1),this.createAttributeGrammar(e).sepBy(i),Pe.reg(/\s*(?:,\s*)?\)/)).map((([e,t,i])=>{let s={};return t.forEach((e=>e(s))),e.length&&(s.lookbehind=e),s})).chain((i=>{let s=Object.keys(i);if(Object.keys(e.attributes).filter((t=>e.attributes[t].expected)).find((e=>!s.includes(e)&&e)))return Pe.failure();const r=Object.keys(i).filter((t=>!(t in e.attributes))).length;return!t&&r>0?Pe.failure():Pe.success().map((()=>new e(i)))}));static unknownValue}class Te extends Le{static attributes={...super.attributes,value:{default:""}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Me.guid.map((e=>new this(e)))}static generateGuid(e=!0){let t=new Uint32Array(4);!0===e&&crypto.getRandomValues(t);let i="";return t.forEach((e=>{i+=("0".repeat(8)+e.toString(16).toUpperCase()).slice(-8)})),new Te({value:i})}constructor(e){e||(e=Te.generateGuid().value),e.constructor!==Object&&(e={value:e}),super(e),this.value}valueOf(){return this.value}toString(){return this.value}}class Ie extends Le{static attributes={...super.attributes,type:{default:"",serialized:!0},path:{default:"",serialized:!0}};static{this.cleanupAttributes(this.attributes)}static quoted=Pe.regArray(new RegExp("'\"("+Me.Regex.InsideString.source+")\"'|'("+Me.Regex.InsideSingleQuotedString.source+")'|\"("+Me.Regex.InsideString.source+')"')).map((([e,t,i,s])=>t??i??s));static path=this.quoted.getParser().parser.regexp.source+"|"+Me.Regex.Path.source;static typeReference=Pe.reg(new RegExp(Me.Regex.Path.source+"|"+Me.symbol.getParser().regexp.source));static fullReferenceGrammar=Pe.regArray(new RegExp("("+this.typeReference.getParser().regexp.source+")"+/\s*/.source+"(?:"+this.quoted.getParser().parser.regexp.source+")")).map((([e,t,...i])=>new this({type:t,path:i.find((e=>e))})));static fullReferenceSerializedGrammar=Pe.regArray(new RegExp("("+this.typeReference.getParser().regexp.source+")"+/\s*/.source+"'("+Me.Regex.InsideSingleQuotedString.source+")'")).map((([e,t,...i])=>new this({type:t,path:i.find((e=>e))})));static typeReferenceGrammar=this.typeReference.map((e=>new this({type:e,path:""})));static grammar=this.createGrammar();static createGrammar(){return Pe.alt(Pe.seq(Pe.str('"'),Pe.alt(this.fullReferenceSerializedGrammar,this.typeReferenceGrammar),Pe.str('"')).map((([e,t,i])=>t)),this.fullReferenceGrammar.map((e=>(Ae.objectSet(e,["attributes","type","serialized"],!1),e))),this.typeReferenceGrammar.map((e=>(Ae.objectSet(e,["attributes","type","serialized"],!1),e))))}constructor(e={}){e.constructor===String&&(e={path:e}),super(e),this.type,this.path}static createNoneInstance(){return new Ie({type:"None",path:""})}sanitize(){if(this.type&&!this.type.startsWith("/")){let e=this.type+"_Deprecated",t=Object.keys(ne.paths).find((t=>{const i=Ae.getNameFromPath(ne.paths[t]);return i===this.type||i===e}));t&&(this.type=ne.paths[t])}}getName(){return Ae.getNameFromPath(this.path.replace(/_C$/,""))}toString(){return this.type+(this.path?`'${this.path}'`:"")}}class Be extends Le{static attributes={...super.attributes,MemberParent:{type:Ie},MemberName:{type:String},MemberGuid:{type:Te}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Me.createEntityGrammar(this)}constructor(e){super(e),this.MemberParent,this.MemberName,this.MemberGuid}}class $e extends Le{static attributes={...super.attributes,value:{default:""}};static{this.cleanupAttributes(this.attributes)}static attributeConverter={fromAttribute:(e,t)=>new $e(e),toAttribute:(e,t)=>e.toString()};static grammar=this.createGrammar();static createGrammar(){return Me.symbol.map((e=>new this(e)))}constructor(e){e.constructor!==Object&&(e={value:e}),super(e),this.value}valueOf(){return this.value}toString(){return this.value}}class He extends Le{static attributes={...super.attributes,value:{default:0,predicate:e=>e%1==0&&e>1<<31&&e<-(1<<31)}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Pe.numberInteger.map((e=>new this(e)))}constructor(e=0){-0===e&&(e=0),super(e.constructor===Object?e:{value:e}),this.value}valueOf(){return this.value}toString(){return this.value.toString()}}class Ge extends Le{static attributes={...super.attributes,value:{default:0}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Pe.number.map((e=>new this(e)))}constructor(e=0){e.constructor!==Object&&(e={value:e}),super(e),this.value}valueOf(){return this.value}toString(){return this.value.toFixed(6)}}class De extends Le{static attributes={...super.attributes,R:{type:Ge,default:()=>new Ge,expected:!0},G:{type:Ge,default:()=>new Ge,expected:!0},B:{type:Ge,default:()=>new Ge,expected:!0},A:{type:Ge,default:()=>new Ge(1)},H:{type:Ge,default:()=>new Ge,ignored:!0},S:{type:Ge,default:()=>new Ge,ignored:!0},V:{type:Ge,default:()=>new Ge,ignored:!0}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static linearToSRGB(e){return e<=0?0:e>=1?1:e<.0031308?12.92*e:1.055*Math.pow(e,1/2.4)-.055}static sRGBtoLinear(e){return e<=0?0:e>=1?1:e<.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)}static getWhite(){return new De({R:1,G:1,B:1})}static createGrammar(){return Me.createEntityGrammar(this,!1)}static getLinearColorFromHexGrammar(){return Pe.regArray(new RegExp("#("+Me.Regex.HexDigit.source+"{2})("+Me.Regex.HexDigit.source+"{2})("+Me.Regex.HexDigit.source+"{2})("+Me.Regex.HexDigit.source+"{2})?")).map((([e,t,i,s,r])=>new this({R:parseInt(t,16)/255,G:parseInt(i,16)/255,B:parseInt(s,16)/255,A:parseInt(r??"FF",16)/255})))}static getLinearColorRGBListGrammar(){return Pe.seq(Pe.numberByte,Me.commaSeparation,Pe.numberByte,Me.commaSeparation,Pe.numberByte).map((([e,t,i,s,r])=>new this({R:e/255,G:i/255,B:r/255,A:1})))}static getLinearColorRGBGrammar(){return Pe.seq(Pe.reg(/rgb\s*\(\s*/),this.getLinearColorRGBListGrammar(),Pe.reg(/\s*\)/)).map((([e,t,i])=>t))}static getLinearColorRGBAGrammar(){return Pe.seq(Pe.reg(/rgba\s*\(\s*/),this.getLinearColorRGBListGrammar(),Pe.reg(/\s*\)/)).map((([e,t,i])=>t))}static getLinearColorFromAnyFormat(){return Pe.alt(this.getLinearColorFromHexGrammar(),this.getLinearColorRGBAGrammar(),this.getLinearColorRGBGrammar(),this.getLinearColorRGBListGrammar())}constructor(e){e instanceof Array&&(e={R:e[0]??0,G:e[1]??0,B:e[2]??0,A:e[3]??1}),super(e),this.R,this.G,this.B,this.A,this.H,this.S,this.V,this.#C()}#C(){const e=this.R.value,t=this.G.value,i=this.B.value;if(Ae.approximatelyEqual(e,t)&&Ae.approximatelyEqual(e,i)&&Ae.approximatelyEqual(t,i))return this.S.value=0,void(this.V.value=e);const s=Math.max(e,t,i),r=Math.min(e,t,i),n=s-r;let a;switch(s){case r:a=0;break;case e:a=(t-i)/n+(te.toString(16).toUpperCase().padStart(2,"0"))).join("")}toSRGBAString(){return this.toSRGBA().map((e=>e.toString(16).toUpperCase().padStart(2,"0"))).join("")}toHSVA(){return[this.H.value,this.S.value,this.V.value,this.A.value]}toNumber(){return(Math.round(255*this.R.value)<<24)+(Math.round(255*this.G.value)<<16)+(Math.round(255*this.B.value)<<8)+Math.round(255*this.A.value)}setFromRGBANumber(e){this.A.value=(255&e)/255,this.B.value=(e>>8&255)/255,this.G.value=(e>>16&255)/255,this.R.value=(e>>24&255)/255,this.#C()}setFromSRGBANumber(e){this.A.value=(255&e)/255,this.B.value=De.sRGBtoLinear((e>>8&255)/255),this.G.value=De.sRGBtoLinear((e>>16&255)/255),this.R.value=De.sRGBtoLinear((e>>24&255)/255),this.#C()}toArray(){return[this.R.value,this.G.value,this.B.value,this.A.value]}toString(){return Ae.printLinearColor(this)}}class Oe extends Le{static attributes={...super.attributes,MacroGraph:{type:Ie,default:()=>new Ie},GraphBlueprint:{type:Ie,default:()=>new Ie},GraphGuid:{type:Te,default:()=>new Te}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Me.createEntityGrammar(this)}constructor(e){super(e),this.MacroGraph,this.GraphBlueprint,this.GuidEntity}getMacroName(){const e=this.MacroGraph.path.search(":");return this.MacroGraph.path.substring(e+1)}}class Ve extends He{static attributes={...super.attributes,value:{...super.attributes.value,predicate:e=>e%1==0&&e>=0&&e<256}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Pe.numberByte.map((e=>new this(e)))}constructor(e=0){super(e)}}class Re extends Le{static attributes={...super.attributes,value:{default:""}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Me.symbol.map((e=>new this(e)))}constructor(e){e.constructor!==Object&&(e={value:e}),super(e),this.value}valueOf(){return this.value}toString(){return this.value}}class ze extends Re{static grammar=this.createGrammar();static createGrammar(){return Me.symbol.map((e=>new this(e)))}}class _e extends ze{static grammar=this.createGrammar();static createGrammar(){return Pe.reg(Me.Regex.InsideString).map((e=>new this(e)))}}class Fe extends Le{static lookbehind="INVTEXT";static attributes={...super.attributes,value:{default:""}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Pe.alt(Pe.seq(Pe.reg(new RegExp(`${this.lookbehind}\\s*\\(`)),Me.grammarFor(this.attributes.value),Pe.reg(/\s*\)/)).map((([e,t,i])=>t)),Pe.reg(new RegExp(this.lookbehind)).map((()=>""))).map((e=>new this(e)))}constructor(e){e.constructor!==Object&&(e={value:e}),super(e),this.value}}class je extends Le{static lookbehind="NSLOCTEXT";static attributes={...super.attributes,namespace:{default:""},key:{default:""},value:{default:""}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Pe.regArray(new RegExp(String.raw`${this.lookbehind}\s*\(`+String.raw`\s*"(${Me.Regex.InsideString.source})"\s*,`+String.raw`\s*"(${Me.Regex.InsideString.source})"\s*,`+String.raw`\s*"(${Me.Regex.InsideString.source})"\s*`+String.raw`(?:,\s+)?`+String.raw`\)`,"m")).map((e=>new this({namespace:Ae.unescapeString(e[1]),key:Ae.unescapeString(e[2]),value:Ae.unescapeString(e[3])})))}constructor(e){super(e),this.namespace,this.key,this.value}toString(){return Ae.capitalFirstLetter(this.value)}}class Ue extends Le{static lookbehind=new ke("LOCGEN_FORMAT_NAMED","LOCGEN_FORMAT_ORDERED");static attributes={...super.attributes,value:{type:[new ke(String,je,Fe,Ue)],default:[]}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Pe.seq(Pe.reg(new RegExp(`(${this.lookbehind.values.reduce(((e,t)=>e+"|"+t))})\\s*`),1),Me.grammarFor(this.attributes.value)).map((([e,t])=>{const i=new this({value:t});return i.lookbehind=e,i}))}constructor(e){super(e),this.value}toString(){const e=this.value?.[0]?.toString();if(!e)return"";const t=this.value.slice(1).map((e=>e.toString()));return"LOCGEN_FORMAT_NAMED"==this.lookbehind?e.replaceAll(/\{([a-zA-Z]\w*)\}/g,((e,i)=>{const s=t.indexOf(i)+1;return s>0&&s{const s=Number(i);return se>=-(1n<<63n)&&e<1n<<63n}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Pe.numberBigInteger.map((e=>new this(e)))}constructor(e=0){e.constructor!==Object&&(e={value:e}),super(e),this.value}valueOf(){return this.value}toString(){return this.value.toString()}}class Ke extends Le{static attributes={...super.attributes,value:{default:""}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Me.symbol.map((e=>new this(e)))}constructor(e){e.constructor!==Object&&(e={value:e}),super(e),this.value}valueOf(){return this.value}toString(){return this.value}}class Ye extends Le{static attributes={...super.attributes,objectName:{type:Ke},pinGuid:{type:Te}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Pe.seq(Ke.createGrammar(),Pe.whitespace,Te.createGrammar()).map((([e,t,i])=>new this({objectName:e,pinGuid:i})))}constructor(e){super(e),this.objectName,this.pinGuid}}class Ze extends Le{static attributes={...super.attributes,PinCategory:{default:""},PinSubCategory:{default:""},PinSubCategoryObject:{type:Ie,default:()=>Ie.createNoneInstance()},PinSubCategoryMemberReference:{type:Be,default:null},PinValueType:{type:Ze,default:null},ContainerType:{type:Ke},bIsReference:{default:!1},bIsConst:{default:!1},bIsWeakPointer:{default:!1},bIsUObjectWrapper:{default:!1},bSerializeAsSinglePrecisionFloat:{default:!1}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Me.createEntityGrammar(this)}constructor(e={},t=!1){super(e,t),this.PinCategory,this.PinSubCategory,this.PinSubCategoryObject,this.PinSubCategoryMemberReference,this.PinValueType,this.ContainerType,this.bIsReference,this.bIsConst,this.bIsWeakPointer,this.bIsUObjectWrapper,this.bIsUObjectWrapper,this.bSerializeAsSinglePrecisionFloat}copyTypeFrom(e){this.PinCategory=e.PinCategory,this.PinSubCategory=e.PinSubCategory,this.PinSubCategoryObject=e.PinSubCategoryObject,this.PinSubCategoryMemberReference=e.PinSubCategoryMemberReference,this.PinValueType=e.PinValueType,this.ContainerType=e.ContainerType,this.bIsReference=e.bIsReference,this.bIsConst=e.bIsConst,this.bIsWeakPointer=e.bIsWeakPointer,this.bIsUObjectWrapper=e.bIsUObjectWrapper,this.bSerializeAsSinglePrecisionFloat=e.bSerializeAsSinglePrecisionFloat}}class Xe extends Le{static attributes={...super.attributes,X:{default:0,expected:!0},Y:{default:0,expected:!0}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Me.createEntityGrammar(this,!1)}constructor(e){super(e),this.X,this.Y}toArray(){return[this.X,this.Y]}}class qe extends Xe{static grammar=this.createGrammar();static createGrammar(){return Pe.alt(Pe.regArray(new RegExp(/X\s*=\s*/.source+"(?"+Pe.number.getParser().parser.regexp.source+")\\s+"+/Y\s*=\s*/.source+"(?"+Pe.number.getParser().parser.regexp.source+")")).map((({groups:{x:e,y:t}})=>new this({X:Number(e),Y:Number(t)}))),Xe.createGrammar())}}class Qe extends Le{static attributes={...super.attributes,R:{default:0,expected:!0},P:{default:0,expected:!0},Y:{default:0,expected:!0}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Me.createEntityGrammar(this,!1)}constructor(e){super(e),this.R,this.P,this.Y}getRoll(){return this.R}getPitch(){return this.P}getYaw(){return this.Y}}class Je extends Qe{static grammar=this.createGrammar();static createGrammar(){const e=Pe.number.getParser().parser.regexp.source;return Pe.alt(Pe.reg(new RegExp("("+e+")\\s*,\\s("+e+")\\s*,\\s("+e+")")).map((([e,t,i])=>new this({R:Number(i),P:Number(e),Y:Number(t)}))),Qe.createGrammar())}}class et extends Xe{static grammar=this.createGrammar();static createGrammar(){const e=Pe.number.getParser().parser.regexp.source;return Pe.alt(Pe.reg(new RegExp("("+e+")\\s*,\\s("+e+")")).map((([e,t])=>new this({X:Number(e),Y:Number(t)}))),Xe.createGrammar())}}class tt extends Le{static attributes={...super.attributes,X:{default:0,expected:!0},Y:{default:0,expected:!0},Z:{default:0,expected:!0}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Me.createEntityGrammar(tt,!1)}constructor(e){super(e),this.X,this.Y,this.Z}toArray(){return[this.X,this.Y,this.Z]}}class it extends tt{static grammar=this.createGrammar();static createGrammar(){const e=Pe.number.getParser().parser.regexp.source;return Pe.alt(Pe.regArray(new RegExp("("+e+")\\s*,\\s*("+e+")\\s*,\\s*("+e+")")).map((([e,t,i,s])=>new this({X:Number(t),Y:Number(i),Z:Number(s)}))),tt.createGrammar())}}class st extends Le{static#P={[ne.paths.linearColor]:De,[ne.paths.rotator]:Qe,[ne.paths.vector]:tt,[ne.paths.vector2D]:Xe,bool:Boolean,byte:Ve,enum:ze,exec:String,int:He,int64:We,name:String,real:Number,string:String};static#x={enum:_e,rg:qe,[ne.paths.rotator]:Je,[ne.paths.vector]:it,[ne.paths.vector2D]:et};static lookbehind="Pin";static attributes={...super.attributes,objectEntity:{ignored:!0},pinIndex:{type:Number,ignored:!0},PinId:{type:Te,default:()=>new Te},PinName:{default:""},PinFriendlyName:{type:new ke(je,Ue,String)},PinToolTip:{type:String},Direction:{type:String},PinType:{type:Ze,default:()=>new Ze,inlined:!0},LinkedTo:{type:[Ye]},SubPins:{type:[Ye]},ParentPin:{type:Ye},DefaultValue:{type:new oe((e=>e.getEntityType(!0)??String)),serialized:!0},AutogeneratedDefaultValue:{type:String},DefaultObject:{type:Ie},PersistentGuid:{type:Te},bHidden:{default:!1},bNotConnectable:{default:!1},bDefaultValueIsReadOnly:{default:!1},bDefaultValueIsIgnored:{default:!1},bAdvancedView:{default:!1},bOrphanedPin:{default:!1}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Me.createEntityGrammar(this)}constructor(e={},t=!1){super(e,t),this.objectEntity,this.pinIndex,this.PinId,this.PinName,this.PinFriendlyName,this.PinToolTip,this.Direction,this.PinType,this.LinkedTo,this.DefaultValue,this.AutogeneratedDefaultValue,this.DefaultObject,this.PersistentGuid,this.bHidden,this.bNotConnectable,this.bDefaultValueIsReadOnly,this.bDefaultValueIsIgnored,this.bAdvancedView,this.bOrphanedPin}static fromLegacyObject(e){return new st(e,!0)}getType(){const e=this.PinType.PinCategory;if("struct"===e||"object"===e)return this.PinType.PinSubCategoryObject.path;if("optional"===e)switch(this.PinType.PinSubCategory){case"int":return"int";case"red":return"real";case"rg":return"rg";case"rgb":return ne.paths.vector;case"rgba":return ne.paths.linearColor}if(this.isEnum())return"enum";if(this.objectEntity?.isPcg()){const e=this.objectEntity.getPcgSubobject(),t=this.isInput()?e.InputPins?.[this.pinIndex]:e.OutputPins?.[this.pinIndex];if(t){const i=e[ne.subObjectAttributeNameFromReference(t,!0)];let s=i.Properties?.AllowedTypes?.toString()??"";if(""==s&&(s=this.PinType.PinCategory??"",""==s&&(s="Any")),s)return!1!==i.Properties.bAllowMultipleData&&!1!==i.Properties.bAllowMultipleConnections&&(s+="[]"),s}}return e}getEntityType(e=!1){const t=this.getType(),i=st.#P[t],s=st.#x[t];return e&&void 0!==s?s:i}pinDisplayName(){let e,t=this.PinFriendlyName?this.PinFriendlyName.toString():Ae.formatStringName(this.PinName??"");return this.PinToolTip&&(e=this.PinToolTip.match(/\s*(.+?(?=\n)|.+\S)\s*/))&&e[1].toLowerCase()===t.toLowerCase()?e[1]:t}copyTypeFrom(e){this.PinType.PinCategory=e.PinType.PinCategory,this.PinType.PinSubCategory=e.PinType.PinSubCategory,this.PinType.PinSubCategoryObject=e.PinType.PinSubCategoryObject,this.PinType.PinSubCategoryMemberReference=e.PinType.PinSubCategoryMemberReference,this.PinType.PinValueType=e.PinType.PinValueType,this.PinType.ContainerType=e.PinType.ContainerType,this.PinType.bIsReference=e.PinType.bIsReference,this.PinType.bIsConst=e.PinType.bIsConst,this.PinType.bIsWeakPointer=e.PinType.bIsWeakPointer,this.PinType.bIsUObjectWrapper=e.PinType.bIsUObjectWrapper,this.PinType.bSerializeAsSinglePrecisionFloat=e.PinType.bSerializeAsSinglePrecisionFloat}getDefaultValue(e=!1){return void 0===this.DefaultValue&&e&&(this.DefaultValue=new(this.getEntityType(!0))),this.DefaultValue}isEnum(){const e=this.PinType.PinSubCategoryObject.type;return e===ne.paths.enum||e===ne.paths.userDefinedEnum||"enum"===e.toLowerCase()}isExecution(){return"exec"===this.PinType.PinCategory}isHidden(){return this.bHidden}isInput(){return!this.bHidden&&"EGPD_Output"!=this.Direction}isOutput(){return!this.bHidden&&"EGPD_Output"==this.Direction}isLinked(){return this.LinkedTo?.length>0??!1}linkTo(e,t){const i=this.LinkedTo?.some((i=>i.objectName.toString()==e&&i.pinGuid.valueOf()==t.PinId.valueOf()));return!i&&((this.LinkedTo??=[]).push(new Ye({objectName:e,pinGuid:t.PinId})),!0)}unlinkFrom(e,t){const i=this.LinkedTo?.findIndex((i=>i.objectName.toString()==e&&i.pinGuid.valueOf()==t.PinId.valueOf()));return i>=0&&(this.LinkedTo.splice(i,1),0===this.LinkedTo.length&&void 0===st.attributes.LinkedTo.default&&(this.LinkedTo=void 0),!0)}getSubCategory(){return this.PinType.PinSubCategoryObject.path}pinColor(){if("mask"==this.PinType.PinCategory){const e=ne.pinColor[this.PinType.PinSubCategory];if(e)return e}else if("optional"==this.PinType.PinCategory)return ne.pinColorMaterial;return ne.pinColor[this.getType()]??ne.pinColor[this.PinType.PinCategory.toLowerCase()]??ne.pinColor.default}}class rt{static arrayPin=D``;static branchNode=D``;static breakStruct=D``;static cast=D``;static close=D``;static convert=D``;static correct=D``;static delegate=D``;static doN=D``;static doOnce=D``;static enum=D``;static event=D``;static execPin=D``;static expandIcon=D``;static flipflop=D``;static forEachLoop=D``;static functionSymbol=D``;static gamepad=D``;static genericPin=D``;static keyboard=D``;static loop=D``;static macro=D``;static mapPin=D``;static makeArray=D``;static makeMap=D``;static makeSet=D``;static makeStruct=D``;static mouse=D``;static node=D``;static operationPin=D``;static pcgStackPin=D``;static pcgPin=D``;static pcgParamPin=D``;static pcgSpatialPin=D``;static plusCircle=D``;static questionMark=D``;static referencePin=D``;static reject=D``;static setPin=D``;static select=D``;static sequence=D``;static sound=D``;static spawnActor=D``;static switch=D``;static timer=D``;static touchpad=D``}class nt extends st{static lookbehind="";static grammar=this.createGrammar();static createGrammar(){return Pe.seq(Pe.reg(new RegExp(`${Me.Regex.Symbol.source}\\s*\\(\\s*`),1),Me.createAttributeGrammar(this).sepBy(Me.commaSeparation),Pe.reg(/\s*(?:,\s*)?\)/)).map((([e,t,i])=>{e??="";let s={};return e.length&&(s.lookbehind=e),t.forEach((e=>e(s))),new this(s)}))}constructor(e={}){super(e,!0)}}class at extends Le{static attributes={...super.attributes,MemberScope:{type:String},MemberName:{default:""},MemberGuid:{type:Te},bSelfContext:{type:Boolean}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Me.createEntityGrammar(this)}constructor(e){super(e),this.MemberName,this.GuidEntity,this.bSelfContext}}class ot extends Le{static#N={A_AccentGrave:"à",Add:"Num +",C_Cedille:"ç",Decimal:"Num .",Divide:"Num /",E_AccentAigu:"é",E_AccentGrave:"è",F1:"F1",F10:"F10",F11:"F11",F12:"F12",F2:"F2",F3:"F3",F4:"F4",F5:"F5",F6:"F6",F7:"F7",F8:"F8",F9:"F9",Gamepad_Special_Left_X:"Touchpad Button X Axis",Gamepad_Special_Left_Y:"Touchpad Button Y Axis",Mouse2D:"Mouse XY 2D-Axis",Multiply:"Num *",Section:"§",Subtract:"Num -",Tilde:"`"};static attributes={...super.attributes,AdvancedPinDisplay:{type:$e},Archetype:{type:Ie},AxisKey:{type:Re},bAlt:{type:Boolean},bCanRenameNode:{type:Boolean},bColorCommentBubble:{type:Boolean},bCommand:{type:Boolean},bCommentBubblePinned:{type:Boolean},bCommentBubbleVisible_InDetailsPanel:{type:Boolean},bCommentBubbleVisible:{type:Boolean},bConsumeInput:{type:Boolean},bControl:{type:Boolean},bExecuteWhenPaused:{type:Boolean},bExposeToLibrary:{type:Boolean},bInternalEvent:{type:Boolean},bIsCaseSensitive:{type:Boolean},bIsConstFunc:{type:Boolean},bIsPureFunc:{type:Boolean},BlueprintElementInstance:{type:Ie},BlueprintElementType:{type:Ie},bOverrideFunction:{type:Boolean},bOverrideParentBinding:{type:Boolean},bShift:{type:Boolean},Class:{type:Ie},CommentColor:{type:De},ComponentPropertyName:{type:String},CustomFunctionName:{type:String},CustomProperties:{type:[new ke(st,nt)]},DelegateOwnerClass:{type:Ie},DelegatePropertyName:{type:String},DelegateReference:{type:at},EnabledState:{type:$e},Enum:{type:Ie},EnumEntries:{type:[String],inlined:!0},ErrorMsg:{type:String},ErrorType:{type:He},EventReference:{type:Be},ExportPath:{type:Ie},FunctionReference:{type:Be},G:{type:Number},Graph:{type:Ie},HiGenGridSize:{type:Re},InputAxisKey:{type:Re},InputKey:{type:Re},InputName:{type:String},InputPins:{type:[Ie],inlined:!0},InputType:{type:Re},MacroGraphReference:{type:Oe},MaterialExpression:{type:Ie},MaterialExpressionComment:{type:Ie},MaterialExpressionEditorX:{type:new le(He)},MaterialExpressionEditorY:{type:new le(He)},MaterialFunction:{type:Ie},MoveMode:{type:Re},Name:{type:String},Node:{type:new le(Ie)},NodeComment:{type:String},NodeGuid:{type:Te},NodeHeight:{type:He},NodePosX:{type:He},NodePosY:{type:He},NodeTitle:{type:String},NodeTitleColor:{type:De},NodeWidth:{type:He},NumAdditionalInputs:{type:Number},ObjectRef:{type:Ie},Operation:{type:Re},OutputPins:{type:[Ie],inlined:!0},PCGNode:{type:Ie},PinNames:{type:[String],inlined:!0},PinTags:{type:[null],inlined:!0},PositionX:{type:new le(He)},PositionY:{type:new le(He)},ProxyClass:{type:Ie},ProxyFactoryClass:{type:Ie},ProxyFactoryFunctionName:{type:String},R:{type:Number},SelfContextInfo:{type:Re},SettingsInterface:{type:Ie},SizeX:{type:new le(He)},SizeY:{type:new le(He)},StructType:{type:Ie},SubgraphInstance:{type:String},TargetType:{type:Ie},Text:{type:new le(String)},TimelineGuid:{type:Te},TimelineName:{type:String},VariableReference:{type:at}};static{this.cleanupAttributes(this.attributes)}static nameRegex=/^(\w+?)(?:_(\d+))?$/;static sequencerScriptingNameRegex=/\/Script\/SequencerScripting\.MovieSceneScripting(.+)Channel/;static customPropertyGrammar=Pe.seq(Pe.reg(/CustomProperties\s+/),Me.grammarFor(void 0,this.attributes.CustomProperties.type[0])).map((([e,t])=>e=>{e.CustomProperties||(e.CustomProperties=[]),e.CustomProperties.push(t)}));static inlinedArrayEntryGrammar=Pe.seq(Pe.alt(Me.symbolQuoted.map((e=>[e,!0])),Me.symbol.map((e=>[e,!1]))),Pe.reg(new RegExp("\\s*\\(\\s*(\\d+)\\s*\\)\\s*\\=\\s*"),1).map(Number)).chain((([[e,t],i])=>Me.grammarFor(this.attributes[e]).map((s=>r=>{(r[e]??=[])[i]=s,Ae.objectSet(r,["attributes",e,"quoted"],t),this.attributes[e]?.inlined||(r.attributes||Le.defineAttributes(r,{}),Ae.objectSet(r,["attributes",e,"inlined"],!0))}))));static grammar=this.createGrammar();static createSubObjectGrammar(){return Pe.lazy((()=>this.grammar)).map((e=>t=>t[ne.subObjectAttributeNameFromEntity(e)]=e))}static createGrammar(){return Pe.seq(Pe.reg(/Begin\s+Object/),Pe.seq(Pe.whitespace,Pe.alt(this.customPropertyGrammar,Me.createAttributeGrammar(this),Me.createAttributeGrammar(this,Me.attributeNameQuoted,void 0,((e,t,i)=>Ae.objectSet(e,["attributes",...t,"quoted"],!0))),this.inlinedArrayEntryGrammar,this.createSubObjectGrammar())).map((([e,t])=>t)).many(),Pe.reg(/\s+End\s+Object/)).map((([e,t,i])=>{const s={};return t.forEach((e=>e(s))),new this(s)}))}static keyName(e){let t=ot.#N[e];if(t)return t;if(t=Ae.numberFromText(e)?.toString(),t)return t;const i=e.match(/NumPad([a-zA-Z]+)/);return i&&(t=Ae.numberFromText(i[1]).toString(),t)?"Num "+t:void 0}static getMultipleObjectsGrammar(){return Pe.seq(Pe.whitespaceOpt,this.createGrammar(),Pe.seq(Pe.whitespace,this.createGrammar()).map((([e,t])=>t)).many(),Pe.whitespaceOpt).map((([e,t,i,s])=>[t,...i]))}constructor(e={},t=!1){let i=Object.keys(e);if(i.some((e=>e.startsWith(ne.subObjectAttributeNamePrefix)))){let t=i.filter((e=>e.startsWith(ne.subObjectAttributeNamePrefix))).reduce(((t,i)=>(t[i]=e[i],t)),{});e={...t,...e}}super(e,t),this.CustomProperties,this.bAlt,this.bCanRenameNode,this.bColorCommentBubble,this.bCommand,this.bCommentBubblePinned,this.bCommentBubbleVisible,this.bCommentBubbleVisible_InDetailsPanel,this.bConsumeInput,this.bControl,this.bExecuteWhenPaused,this.bExposeToLibrary,this.bInternalEvent,this.bIsCaseSensitive,this.bIsConstFunc,this.bIsPureFunc,this.bOverrideFunction,this.bOverrideParentBinding,this.bShift,this.ComponentPropertyName,this.EventReference,this.FunctionReference,this.NodeGuid,this.TimelineGuid,this.AdvancedPinDisplay,this.EnabledState,this.ErrorType,this.NodeHeight,this.NodePosX,this.NodePosY,this.NodeWidth,this.CommentColor,this.NodeTitleColor,this.MacroGraphReference,this.MaterialExpressionEditorX,this.MaterialExpressionEditorY,this.SizeX,this.SizeY,this.Text,this.PositionX,this.PositionY,this.Node,this.PinTags,this.G,this.NumAdditionalInputs,this.R,this.InputPins,this.OutputPins,this.Archetype,this.BlueprintElementInstance,this.BlueprintElementType,this.Class,this.DelegateOwnerClass,this.Enum,this.ExportPath,this.Graph,this.MaterialExpression,this.MaterialExpressionComment,this.MaterialFunction,this.ObjectRef,this.PCGNode,this.ProxyClass,this.ProxyFactoryClass,this.SettingsInterface,this.StructType,this.TargetType,this.EnumEntries,this.PinNames,this.CustomFunctionName,this.DelegatePropertyName,this.ErrorMsg,this.InputName,this.Name,this.NodeComment,this.NodeTitle,this.Operation,this.ProxyFactoryFunctionName,this.SubgraphInstance,this.Text,this.TimelineName,this.AxisKey,this.HiGenGridSize,this.InputAxisKey,this.InputKey,this.InputType,this.MoveMode,this.SelfContextInfo,this.DelegateReference,this.VariableReference,this.Pins instanceof Array&&(this.Pins.forEach((e=>{const t=this[ne.subObjectAttributeNameFromReference(e,!0)];if(t){const e=st.fromLegacyObject(t);e.LinkedTo=[],this.getCustomproperties(!0).push(e)}})),delete this.Pins),this.Class?.sanitize(),this.MacroGraphReference&&(this.MacroGraphReference.MacroGraph?.sanitize(),this.MacroGraphReference.GraphBlueprint?.sanitize());const s=this.getMaterialSubobject();if(s){const e=s;e.SizeX&&(e.SizeX.getter=()=>this.NodeWidth),e.SizeY&&(e.SizeY.getter=()=>this.NodeHeight),e.Text&&(e.Text.getter=()=>this.NodeComment),e.MaterialExpressionEditorX&&(e.MaterialExpressionEditorX.getter=()=>this.NodePosX),e.MaterialExpressionEditorY&&(e.MaterialExpressionEditorY.getter=()=>this.NodePosY)}const r=this.getPcgSubobject();r&&(r.PositionX&&(r.PositionX.getter=()=>this.NodePosX),r.PositionY&&(r.PositionY.getter=()=>this.NodePosY),r.getSubobjects().forEach((e=>{if(void 0!==e.Node){const t=e.Node.get();t.type===this.PCGNode.type&&t.path===`${this.Name}.${this.PCGNode.path}`&&(e.Node.getter=()=>new Ie({type:this.PCGNode.type,path:`${this.Name}.${this.PCGNode.path}`}))}})));let n=0,a=0;this.CustomProperties?.forEach(((e,t)=>{e.objectEntity=this,e.pinIndex=e.isInput()?n++:e.isOutput()?a++:t}))}getClass(){return(this.Class?.path?this.Class.path:this.Class?.type)??(this.ExportPath?.path?this.ExportPath.path:this.ExportPath?.type)??""}getType(){let e=this.getClass();return this.MacroGraphReference?.MacroGraph?.path?this.MacroGraphReference.MacroGraph.path:this.MaterialExpression?this.MaterialExpression.type:e}getObjectName(e=!1){return e?this.getNameAndCounter()[0]:this.Name}getNameAndCounter(){const e=this.getObjectName(!1).match(ot.nameRegex);let t="",i=null;return e?(e.length>1&&(t=e[1]),e.length>2&&(i=parseInt(e[2])),[t,i]):["",0]}getCounter(){return this.getNameAndCounter()[1]}getNodeWidth(){return this.NodeWidth??this.isComment()?ne.defaultCommentWidth:void 0}setNodeWidth(e){this.NodeWidth||(this.NodeWidth=new He),this.NodeWidth.value=e}getNodeHeight(){return this.NodeHeight??this.isComment()?ne.defaultCommentHeight:void 0}setNodeHeight(e){this.NodeHeight||(this.NodeHeight=new He),this.NodeHeight.value=e}getNodePosX(){return this.NodePosX?.value??0}setNodePosX(e){this.NodePosX||(this.NodePosX=new He),this.NodePosX.value=Math.round(e)}getNodePosY(){return this.NodePosY?.value??0}setNodePosY(e){this.NodePosY||(this.NodePosY=new He),this.NodePosY.value=Math.round(e)}getCustomproperties(e=!1){return e&&!this.CustomProperties&&(this.CustomProperties=[]),this.CustomProperties??[]}getPinEntities(){return this.getCustomproperties().filter((e=>e.constructor===st))}getSubobjects(){return Object.keys(this).filter((e=>e.startsWith(ne.subObjectAttributeNamePrefix))).flatMap((e=>[this[e],...this[e].getSubobjects()]))}switchTarget(){const e=this.getClass().match(ne.switchTargetPattern);if(e)return e[1]}isEvent(){switch(this.getClass()){case ne.paths.actorBoundEvent:case ne.paths.componentBoundEvent:case ne.paths.customEvent:case ne.paths.event:case ne.paths.inputAxisKeyEvent:case ne.paths.inputVectorAxisEvent:return!0}return!1}isComment(){switch(this.getClass()){case ne.paths.comment:case ne.paths.materialGraphNodeComment:return!0}return!1}isMaterial(){return this.getClass()===ne.paths.materialGraphNode}getMaterialSubobject(){const e=this.MaterialExpression??this.MaterialExpressionComment;return e?this[ne.subObjectAttributeNameFromReference(e,!0)]:null}isPcg(){return this.getClass()===ne.paths.pcgEditorGraphNode||this.getPcgSubobject()}getPcgSubobject(){const e=this.PCGNode;return e?this[ne.subObjectAttributeNameFromReference(e,!0)]:null}getSettingsObject(){const e=this.SettingsInterface;return e?this[ne.subObjectAttributeNameFromReference(e,!0)]:null}getSubgraphObject(){const e=this.SubgraphInstance;return e?this[ne.subObjectAttributeNameFromName(e)]:null}isDevelopmentOnly(){const e=this.getClass();return"DevelopmentOnly"===this.EnabledState?.toString()||e.includes("Debug",Math.max(0,e.lastIndexOf(".")))}getHIDAttribute(){return this.InputKey??this.AxisKey??this.InputAxisKey}getDelegatePin(){return this.getCustomproperties().find((e=>"delegate"===e.PinType.PinCategory))}nodeDisplayName(){let e;switch(this.getType()){case ne.paths.asyncAction:if(this.ProxyFactoryFunctionName)return Ae.formatStringName(this.ProxyFactoryFunctionName);case ne.paths.actorBoundEvent:case ne.paths.componentBoundEvent:return`${Ae.formatStringName(this.DelegatePropertyName)} (${this.ComponentPropertyName??"Unknown"})`;case ne.paths.callDelegate:return`Call ${this.DelegateReference?.MemberName??"None"}`;case ne.paths.createDelegate:return"Create Event";case ne.paths.customEvent:if(this.CustomFunctionName)return this.CustomFunctionName;case ne.paths.dynamicCast:return this.TargetType?`Cast To ${this.TargetType?.getName()}`:"Bad cast node";case ne.paths.enumLiteral:return`Literal enum ${this.Enum?.getName()}`;case ne.paths.event:return`Event ${(this.EventReference?.MemberName??"").replace(/^Receive/,"")}`;case ne.paths.executionSequence:return"Sequence";case ne.paths.forEachElementInEnum:return`For Each ${this.Enum?.getName()}`;case ne.paths.forEachLoopWithBreak:return"For Each Loop with Break";case ne.paths.functionEntry:return"UserConstructionScript"===this.FunctionReference?.MemberName?"Construction Script":this.FunctionReference?.MemberName;case ne.paths.functionResult:return"Return Node";case ne.paths.ifThenElse:return"Branch";case ne.paths.makeStruct:if(this.StructType)return`Make ${this.StructType.getName()}`;case ne.paths.materialExpressionConstant:e??=[this.getCustomproperties().find((e=>"Value"==e.PinName))?.DefaultValue];case ne.paths.materialExpressionConstant2Vector:e??=[this.getCustomproperties().find((e=>"X"==e.PinName))?.DefaultValue,this.getCustomproperties().find((e=>"Y"==e.PinName))?.DefaultValue];case ne.paths.materialExpressionConstant3Vector:if(!e){const t=this.getCustomproperties().find((e=>"Constant"==e.PinName))?.DefaultValue;e=[t.X,t.Y,t.Z]}case ne.paths.materialExpressionConstant4Vector:if(!e){const t=this.getCustomproperties().find((e=>"Constant"==e.PinName))?.DefaultValue;e=[t.R,t.G,t.B,t.A].map((e=>e.valueOf()))}if(e.length>0)return e.map((e=>Ae.printExponential(e))).reduce(((e,t)=>e+","+t));break;case ne.paths.materialExpressionFunctionInput:const t=this.getMaterialSubobject();return`Input ${t?.InputName??"In"} (${t?.InputType?.value.match(/^.+?_(\w+)$/)?.[1]??"Vector3"})`;case ne.paths.materialExpressionLogarithm:return"Ln";case ne.paths.materialExpressionLogarithm10:return"Log10";case ne.paths.materialExpressionLogarithm2:return"Log2";case ne.paths.materialExpressionMaterialFunctionCall:const i=this.getMaterialSubobject()?.MaterialFunction;if(i)return i.getName();break;case ne.paths.materialExpressionSquareRoot:return"Sqrt";case ne.paths.pcgEditorGraphNodeInput:return"Input";case ne.paths.pcgEditorGraphNodeOutput:return"Output";case ne.paths.spawnActorFromClass:return`SpawnActor ${Ae.formatStringName(this.getCustomproperties().find((e=>"class"==e.getType()))?.DefaultObject?.getName()??"NONE")}`;case ne.paths.switchEnum:return`Switch on ${this.Enum?.getName()??"Enum"}`;case ne.paths.switchInteger:return"Switch on Int";case ne.paths.variableGet:return"";case ne.paths.variableSet:return"SET"}let t=this.switchTarget();if(t)return"E"!==t[0]&&(t=Ae.formatStringName(t)),`Switch on ${t}`;if(this.isComment())return this.NodeComment;const i=this.getHIDAttribute();if(i){const e=i.toString();let t=ot.keyName(e)??Ae.formatStringName(e);return this.getClass()===ne.paths.inputDebugKey?t="Debug Key "+t:this.getClass()===ne.paths.getInputAxisKeyValue&&(t="Get "+t),t}if(this.getClass()===ne.paths.macro)return Ae.formatStringName(this.MacroGraphReference?.getMacroName());if(this.isMaterial()&&this.getMaterialSubobject()){let e=this.getMaterialSubobject().nodeDisplayName();return e=e.match(/Material Expression (.+)/)?.[1]??e,e}if(this.isPcg()&&this.getPcgSubobject()){let e=this.getPcgSubobject();return e.NodeTitle?e.NodeTitle:e.nodeDisplayName()}const s=this.getSubgraphObject();if(s)return s.Graph.getName();const r=this.getSettingsObject();if(r){if(r.ExportPath.type===ne.paths.pcgHiGenGridSizeSettings)return`Grid Size: ${r.HiGenGridSize?.toString().match(/\d+/)?.[0]?.concat("00")??r.HiGenGridSize?.toString().match(/^\w+$/)?.[0]??"256"}`;if(r.BlueprintElementInstance)return Ae.formatStringName(r.BlueprintElementType.getName());if(r.Operation){const e=r.Name.match(/PCGMetadata(\w+)Settings_\d+/);if(e)return Ae.formatStringName(e[1]+": "+r.Operation)}const e=r.getSubgraphObject();if(e&&e.Graph)return e.Graph.getName()}let n=this.FunctionReference?.MemberName;if(n){const e=this.FunctionReference.MemberParent?.path??"";switch(n){case"AddKey":let t=e.match(ot.sequencerScriptingNameRegex);if(t)return`Add Key (${Ae.formatStringName(t[1])})`;case"Concat_StrStr":return"Append"}const t=n.match(ne.lineTracePattern);if(t)return"Line Trace"+("Multi"===t[1]?" Multi ":" ")+(""===t[2]?"By Channel":Ae.formatStringName(t[2]));switch(e){case ne.paths.blueprintGameplayTagLibrary:case ne.paths.kismetMathLibrary:case ne.paths.slateBlueprintLibrary:case ne.paths.timeManagementBlueprintLibrary:const e=n.match(/[BF]([A-Z]\w+)/);switch(e&&(n=e[1]),n){case"Abs":return"ABS";case"BooleanAND":return"AND";case"BooleanNAND":return"NAND";case"BooleanOR":return"OR";case"Exp":return"e";case"LineTraceSingle":return"Line Trace By Channel";case"Max":case"MaxInt64":return"MAX";case"Min":case"MinInt64":return"MIN";case"Not_PreBool":return"NOT";case"Sin":return"SIN";case"Sqrt":return"SQRT";case"Square":return"^2";case"CrossProduct2D":return"cross";case"Vector4_CrossProduct3":return"cross3";case"DotProduct2D":case"Vector4_DotProduct":return"dot";case"Vector4_DotProduct3":return"dot3"}if(n.startsWith("Add_"))return"+";if(n.startsWith("And_"))return"&";if(n.startsWith("Conv_"))return"";if(n.startsWith("Cross_"))return"cross";if(n.startsWith("Divide_"))return String.fromCharCode(247);if(n.startsWith("Dot_"))return"dot";if(n.startsWith("EqualEqual_"))return"==";if(n.startsWith("Greater_"))return">";if(n.startsWith("GreaterEqual_"))return">=";if(n.startsWith("Less_"))return"<";if(n.startsWith("LessEqual_"))return"<=";if(n.startsWith("Multiply_"))return String.fromCharCode(10799);if(n.startsWith("Not_"))return"~";if(n.startsWith("NotEqual_"))return"!=";if(n.startsWith("Or_"))return"|";if(n.startsWith("Percent_"))return"%";if(n.startsWith("Subtract_"))return"-";if(n.startsWith("Xor_"))return"^";break;case ne.paths.blueprintSetLibrary:{const e=n.match(/Set_(\w+)/);if(e)return Ae.formatStringName(e[1]).toUpperCase()}break;case ne.paths.blueprintMapLibrary:{const e=n.match(/Map_(\w+)/);if(e)return Ae.formatStringName(e[1]).toUpperCase()}break;case ne.paths.kismetArrayLibrary:{const e=n.match(/Array_(\w+)/);if(e)return e[1].toUpperCase()}}return Ae.formatStringName(n)}return this.ObjectRef?this.ObjectRef.getName():Ae.formatStringName(this.getNameAndCounter()[0])}nodeColor(){switch(this.getType()){case ne.paths.materialExpressionConstant2Vector:case ne.paths.materialExpressionConstant3Vector:case ne.paths.materialExpressionConstant4Vector:return ne.nodeColors.yellow;case ne.paths.makeStruct:return ne.nodeColors.darkBlue;case ne.paths.materialExpressionMaterialFunctionCall:return ne.nodeColors.blue;case ne.paths.materialExpressionFunctionInput:return ne.nodeColors.red;case ne.paths.materialExpressionTextureSample:return ne.nodeColors.darkTurquoise;case ne.paths.materialExpressionTextureCoordinate:case ne.paths.pcgEditorGraphNodeInput:case ne.paths.pcgEditorGraphNodeOutput:return ne.nodeColors.red}switch(this.getClass()){case ne.paths.callFunction:return this.bIsPureFunc?ne.nodeColors.green:ne.nodeColors.blue;case ne.paths.dynamicCast:return ne.nodeColors.turquoise;case ne.paths.inputDebugKey:case ne.paths.inputKey:return ne.nodeColors.red;case ne.paths.createDelegate:case ne.paths.enumLiteral:case ne.paths.makeArray:case ne.paths.makeMap:case ne.paths.materialGraphNode:case ne.paths.select:return ne.nodeColors.green;case ne.paths.executionSequence:case ne.paths.ifThenElse:case ne.paths.macro:case ne.paths.multiGate:return ne.nodeColors.gray;case ne.paths.functionEntry:case ne.paths.functionResult:return ne.nodeColors.violet;case ne.paths.timeline:return ne.nodeColors.yellow}if(this.switchTarget())return ne.nodeColors.lime;if(this.isEvent())return ne.nodeColors.red;if(this.isComment())return(this.CommentColor?this.CommentColor:De.getWhite()).toDimmedColor().toCSSRGBValues();const e=this.getPcgSubobject();return e&&e.NodeTitleColor?e.NodeTitleColor.toDimmedColor(.1).toCSSRGBValues():this.bIsPureFunc?ne.nodeColors.green:ne.nodeColors.blue}nodeIcon(){if(this.isMaterial()||this.isPcg())return null;switch(this.getType()){case ne.paths.addDelegate:case ne.paths.asyncAction:case ne.paths.callDelegate:case ne.paths.createDelegate:case ne.paths.functionEntry:case ne.paths.functionResult:return rt.node;case ne.paths.customEvent:return rt.event;case ne.paths.doN:return rt.doN;case ne.paths.doOnce:return rt.doOnce;case ne.paths.dynamicCast:return rt.cast;case ne.paths.enumLiteral:return rt.enum;case ne.paths.event:return rt.event;case ne.paths.executionSequence:case ne.paths.multiGate:return rt.sequence;case ne.paths.flipflop:return rt.flipflop;case ne.paths.forEachElementInEnum:case ne.paths.forLoop:case ne.paths.forLoopWithBreak:case ne.paths.whileLoop:return rt.loop;case ne.paths.forEachLoop:case ne.paths.forEachLoopWithBreak:return rt.forEachLoop;case ne.paths.ifThenElse:return rt.branchNode;case ne.paths.isValid:return rt.questionMark;case ne.paths.makeArray:return rt.makeArray;case ne.paths.makeMap:return rt.makeMap;case ne.paths.makeSet:return rt.makeSet;case ne.paths.makeStruct:return rt.makeStruct;case ne.paths.select:return rt.select;case ne.paths.spawnActorFromClass:return rt.spawnActor;case ne.paths.timeline:return rt.timer}if(this.switchTarget())return rt.switch;if(this.nodeDisplayName().startsWith("Break"))return rt.breakStruct;if(this.getClass()===ne.paths.macro)return rt.macro;const e=this.getHIDAttribute()?.toString();return e?e.includes("Mouse")?rt.mouse:e.includes("Gamepad_Special")?rt.keyboard:e.includes("Gamepad")||e.includes("Steam")?rt.gamepad:e.includes("Touch")?rt.touchpad:rt.keyboard:this.getDelegatePin()?rt.event:this.ObjectRef?.type===ne.paths.ambientSound?rt.sound:rt.functionSymbol}additionalPinInserter(){let e,t,i;switch(this.getType()){case ne.paths.commutativeAssociativeBinaryOperator:case ne.paths.promotableOperator:switch(this.FunctionReference?.MemberName){default:if(!(this.FunctionReference?.MemberName?.startsWith("Add_")||this.FunctionReference?.MemberName?.startsWith("Subtract_")||this.FunctionReference?.MemberName?.startsWith("Multiply_")||this.FunctionReference?.MemberName?.startsWith("Divide_")))break;case"And_Int64Int64":case"And_IntInt":case"BMax":case"BMin":case"BooleanAND":case"BooleanNAND":case"BooleanOR":case"Concat_StrStr":case"FMax":case"FMin":case"Max":case"MaxInt64":case"Min":case"MinInt64":case"Or_Int64Int64":case"Or_IntInt":e??=()=>this.getPinEntities().filter((e=>e.isInput())),t??=e=>e.PinName.match(/^\s*([A-Z])\s*$/)?.[1]?.charCodeAt(0)-"A".charCodeAt(0),i??=(t,i=-1,s=-1)=>{const r=String.fromCharCode(t>=0?t:s+"A".charCodeAt(0)+1);return this.NumAdditionalInputs=e().length-1,r}}break;case ne.paths.multiGate:e??=()=>this.getPinEntities().filter((e=>e.isOutput())),t??=e=>Number(e.PinName.match(/^\s*Out[_\s]+(\d+)\s*$/i)?.[1]),i??=(e,t=-1,i=-1)=>`Out ${e>=0?e:t>0?"Out 0":i+1}`;break;case ne.paths.switchInteger:e??=()=>this.getPinEntities().filter((e=>e.isOutput())),t??=e=>Number(e.PinName.match(/^\s*(\d+)\s*$/)?.[1]),i??=(e,t=-1,i=-1)=>(e<0?i+1:e).toString();break;case ne.paths.switchGameplayTag:i??=(e,t=-1,i=-1)=>{const s=`Case_${e>=0?e:t>0?"0":i+1}`;return this.PinNames??=[],this.PinNames.push(s),delete this.PinTags[this.PinTags.length-1],this.PinTags[this.PinTags.length]=null,s};case ne.paths.switchName:case ne.paths.switchString:e??=()=>this.getPinEntities().filter((e=>e.isOutput())),t??=e=>Number(e.PinName.match(/^\s*Case[_\s]+(\d+)\s*$/i)?.[1]),i??=(e,t=-1,i=-1)=>{const s=`Case_${e>=0?e:t>0?"0":i+1}`;return this.PinNames??=[],this.PinNames.push(s),s}}if(e)return()=>{let s=Number.MAX_SAFE_INTEGER,r=Number.MIN_SAFE_INTEGER,n=[];const a=e().reduce(((e,i)=>{const a=t(i);if(isNaN(a)){if(void 0===e)return i}else if(n.push(a),s=Math.min(a,s),a>r)return r=a,i;return e}),void 0);if(s!==Number.MAX_SAFE_INTEGER&&r!==Number.MIN_SAFE_INTEGER||(s=void 0,r=void 0),!a)return null;n.sort(((e,t)=>e{const t=e-o>1;return o=e,t}));const u=new st(a);return u.PinId=Te.generateGuid(),u.PinName=i(l,s,r),u.PinToolTip=void 0,this.CustomProperties.push(u),u}}}class lt{static same=e=>e;static notWrapped=(e,t)=>t;static bracketsWrapped=(e,t)=>`(${t})`;constructor(e,t=((e,t)=>t),i=",",s=!1,r="=",n=lt.same){this.entityType=e,this.wrap=t,this.attributeSeparator=i,this.trailingSeparator=s,this.attributeValueConjunctionSign=r,this.attributeKeyPrinter=n}read(e){return this.doRead(e.trim())}write(e,t=!1){return this.doWrite(e,t)}doRead(e){const t=Me.grammarFor(void 0,this.entityType).run(e);if(!t.status)throw new Error(`Error when trying to parse the entity ${this.entityType.prototype.constructor.name}.`);return t.value}doWrite(e,t=!1,i="",s=this.wrap,r=this.attributeSeparator,n=this.trailingSeparator,a=this.attributeValueConjunctionSign,o=this.attributeKeyPrinter){let l="";const u=Le.getAttributes(e),c=Object.keys(e);let h=!0;for(const s of c){const n=e[s];if(void 0!==n&&this.showProperty(e,s)){let c=e instanceof Array?`(${s})`:s;u[s]?.quoted&&(c=`"${c}"`);const p=Ae.isSerialized(e,s);if(h?h=!1:l+=r,u[s]?.inlined){l+=this.doWrite(n,t,i,lt.notWrapped,r,!1,a,u[s].type instanceof Array?e=>o(`${c}${e}`):e=>o(`${c}.${e}`));continue}const d=o(c),m=r.includes("\n")?i:"";l+=(d.length?m+d+this.attributeValueConjunctionSign:"")+(p?`"${this.doWriteValue(n,!0,i)}"`:this.doWriteValue(n,t,i))}}return n&&l.length&&(l+=r),s(e,l)}doWriteValue(e,t,i=""){const s=Ae.getType(e),r=Ne.getSerializer(s);if(!r)throw new Error(`Unknown value type "${s.name}", a serializer must be registered in the SerializerFactory class, check initializeSerializerFactory.js`);return r.doWrite(e,t,i)}showProperty(e,t){const i=this.entityType.attributes[t];return i?.constructor!==Object||!i.ignored}}class ut extends lt{constructor(e=ot){super(e,void 0,"\n",!0,void 0,lt.same)}showProperty(e,t){switch(t){case"Class":case"Name":case"Archetype":case"ExportPath":case"CustomProperties":return!1}return super.showProperty(e,t)}write(e,t=!1){return this.doWrite(e,t)+"\n"}doRead(e){return Me.grammarFor(void 0,this.entityType).parse(e)}readMultiple(e){return ot.getMultipleObjectsGrammar().parse(e)}doWrite(e,t,i="",s=this.wrap,r=this.attributeSeparator,n=this.trailingSeparator,a=this.attributeValueConjunctionSign,o=this.attributeKeyPrinter){const l=i+ne.indentation;if(!(e instanceof ot))return super.doWrite(e,t,i,s,r,n,a,(t=>e[t]instanceof ot?"":o(t)));return i+"Begin Object"+(e.Class?.type||e.Class?.path?` Class=${this.doWriteValue(e.Class,t)}`:"")+(e.Name?` Name=${this.doWriteValue(e.Name,t)}`:"")+(e.Archetype?` Archetype=${this.doWriteValue(e.Archetype,t)}`:"")+(e.ExportPath?.type||e.ExportPath?.path?` ExportPath=${this.doWriteValue(e.ExportPath,t)}`:"")+"\n"+super.doWrite(e,t,l,s,r,!0,a,(t=>e[t]instanceof ot?"":o(t)))+e.getCustomproperties().map((e=>l+o("CustomProperties ")+Ne.getSerializer(st).doWrite(e,t)+this.attributeSeparator)).join("")+i+"End Object"}}class ct extends ae{static#k=new ut;#A;constructor(e,t,i={}){i.listenOnFocus??=!0,i.unlistenOnTextEdit??=!0,super(e,t,i);let s=this;this.#A=()=>s.copied()}listenEvents(){window.addEventListener("copy",this.#A)}unlistenEvents(){window.removeEventListener("copy",this.#A)}getSerializedText(){return this.blueprint.getNodes(!0).map((e=>ct.#k.write(e.entity,!1))).join("")}copied(){const e=this.getSerializedText();return navigator.clipboard.writeText(e),e}}class ht extends ae{static#k=new ut;#L;constructor(e,t,i={}){i.listenOnFocus??=!0,i.unlistenOnTextEdit??=!0,super(e,t,i);let s=this;this.#L=()=>s.cut()}listenEvents(){window.addEventListener("cut",this.#L)}unlistenEvents(){window.removeEventListener("cut",this.#L)}getSerializedText(){return this.blueprint.getNodes(!0).map((e=>ht.#k.write(e.entity,!1))).join("")}cut(){this.blueprint.template.getCopyInputObject().copied(),this.blueprint.removeGraphElement(...this.blueprint.getNodes(!0))}}class pt{element;get blueprint(){return this.element.blueprint}#M=[];get inputObjects(){return this.#M}initialize(e){this.element=e}createInputObjects(){return[]}setup(){this.#M.forEach((e=>e.setup()))}cleanup(){this.#M.forEach((e=>e.cleanup()))}willUpdate(e){}update(e){}render(){return D``}firstUpdated(e){}updated(e){}inputSetup(){this.#M=this.createInputObjects()}}class dt extends Le{static attributes={...super.attributes,ActionName:{default:""},bShift:{default:!1},bCtrl:{default:!1},bAlt:{default:!1},bCmd:{default:!1},Key:{type:$e}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Pe.alt($e.grammar.map((e=>new this({Key:e}))),Me.createEntityGrammar(this))}constructor(e={}){super(e,!0),this.ActionName,this.bShift,this.bCtrl,this.bAlt,this.bCmd,this.Key}}class mt extends ae{static#T=e=>{};#I;pressedKey="";constructor(e,t,i={},s=mt.#T,r=mt.#T){i.activationKeys??=[],i.consumeEvent??=!0,i.listenOnFocus??=!0,i.unlistenOnTextEdit??=!0,i.activationKeys instanceof Array||(i.activationKeys=[i.activationKeys]),i.activationKeys=i.activationKeys.map((e=>{if(e instanceof dt)return e;if(e.constructor===String){const t=dt.grammar.run(e);if(t.status)return t.value}throw new Error("Unexpected key value")})),super(e,t,i),this.onKeyDown=s,this.onKeyUp=r,this.#I=this.options.activationKeys??[];let n=this;this.keyDownHandler=e=>{n.#I.some((t=>(e=>e.bShift||"LeftShift"==e.Key||"RightShift"==e.Key)(t)==e.shiftKey&&(e=>e.bCtrl||"LeftControl"==e.Key||"RightControl"==e.Key)(t)==e.ctrlKey&&(e=>e.bAlt||"LeftAlt"==e.Key||"RightAlt"==e.Key)(t)==e.altKey&&ne.Keys[t.Key.value]==e.code))&&(this.consumeEvent&&(e.preventDefault(),e.stopImmediatePropagation()),this.pressedKey=e.code,n.fire(),document.removeEventListener("keydown",n.keyDownHandler),document.addEventListener("keyup",n.keyUpHandler))},this.keyUpHandler=e=>{n.#I.some((t=>t.bShift&&"Shift"==e.key||t.bCtrl&&"Control"==e.key||t.bAlt&&"Alt"==e.key||t.bCmd&&"Meta"==e.key||ne.Keys[t.Key.value]==e.code))&&(this.consumeEvent&&e.stopImmediatePropagation(),n.unfire(),this.pressedKey="",document.removeEventListener("keyup",this.keyUpHandler),document.addEventListener("keydown",this.keyDownHandler))}}listenEvents(){document.addEventListener("keydown",this.keyDownHandler)}unlistenEvents(){document.removeEventListener("keydown",this.keyDownHandler)}fire(){this.onKeyDown(this)}unfire(){this.onKeyUp(this)}}class gt{static deleteNodes="Delete";static duplicateNodes="(bCtrl=True,Key=D)";static enableLinkDelete="LeftAlt";static enableZoomIn=["LeftControl","RightControl"];static selectAllNodes="(bCtrl=True,Key=A)"}class bt extends ae{#B=[0,0];get location(){return this.#B}#$;get enablerKey(){return this.#$}#H=!0;get enablerActivated(){return this.#H}constructor(e,t,i={}){i.ignoreTranslateCompensate??=!1,i.ignoreScale??=!1,i.movementSpace??=t.getGridDOMElement()??document.documentElement,super(e,t,i),this.movementSpace=i.movementSpace,i.enablerKey&&(this.#$=i.enablerKey,this.#$.onKeyDown=()=>this.#H=!0,this.#$.onKeyUp=()=>this.#H=!1,this.#$.consumeEvent=!1,this.#$.listenEvents(),this.#H=!1)}setLocationFromEvent(e){let t=Ae.convertLocation([e.clientX,e.clientY],this.movementSpace,this.options.ignoreScale);return t=this.options.ignoreTranslateCompensate?t:this.blueprint.compensateTranslation(t[0],t[1]),this.#B=[...t],this.#B}}class vt extends bt{static#T=e=>{};#G=0;get variation(){return this.#G}#D=e=>{this.enablerKey&&!this.enablerActivated||(e.preventDefault(),this.#G=e.deltaY,this.setLocationFromEvent(e),this.wheel())};#O=e=>e.preventDefault();constructor(e,t,i={},s=vt.#T){i.listenOnFocus=!0,i.strictTarget??=!1,super(e,t,i),this.strictTarget=i.strictTarget,this.onWheel=s}listenEvents(){this.movementSpace.addEventListener("wheel",this.#D,!1),this.movementSpace.parentElement?.addEventListener("wheel",this.#O)}unlistenEvents(){this.movementSpace.removeEventListener("wheel",this.#D,!1),this.movementSpace.parentElement?.removeEventListener("wheel",this.#O)}wheel(){this.onWheel(this)}}class yt extends vt{#V=0;#R=!1;get enableZoonIn(){return this.#R}set enableZoonIn(e){e!=this.#R&&(this.#R=e)}wheel(){if(this.#V+=-this.variation,Math.abs(this.#V)0||(e+=Math.sign(this.#V),this.blueprint.setZoom(e,this.location),this.#V=0)}}class ft extends mt{#z;constructor(e,t,i={}){i.activationKeys=gt.enableZoomIn,super(e,t,i)}fire(){this.#z=this.blueprint.template.getZoomInputObject(),this.#z.enableZoonIn=!0}unfire(){this.#z.enableZoonIn=!1}}class wt extends se{#t;get blueprint(){return this.#t}set blueprint(e){this.#t=e}#_;get entity(){return this.#_}set entity(e){this.#_=e}#F;get template(){return this.#F}isInitialized=!1;isSetup=!1;inputObjects=[];initialize(e,t){this.requestUpdate(),this.#_=e,this.#F=t,this.#F.initialize(this),this.isConnected&&this.updateComplete.then((()=>this.setup())),this.isInitialized=!0}connectedCallback(){super.connectedCallback(),this.blueprint=this.closest("ueb-blueprint"),this.isInitialized&&(this.requestUpdate(),this.updateComplete.then((()=>this.setup())))}disconnectedCallback(){super.disconnectedCallback(),this.isSetup&&this.updateComplete.then((()=>this.cleanup())),this.acknowledgeDelete()}createRenderRoot(){return this}setup(){this.template.setup(),this.isSetup=!0}cleanup(){this.template.cleanup(),this.isSetup=!1}willUpdate(e){super.willUpdate(e),this.template.willUpdate(e)}update(e){super.update(e),this.template.update(e)}render(){return this.template.render()}firstUpdated(e){super.firstUpdated(e),this.template.firstUpdated(e),this.template.inputSetup()}updated(e){super.updated(e),this.template.updated(e)}acknowledgeDelete(){let e=new CustomEvent(ne.removeEventName);this.dispatchEvent(e)}isSameGraph(e){return this.blueprint&&this.blueprint==e?.blueprint}}class St extends wt{static properties={...super.properties,locationX:{type:Number,attribute:!1},locationY:{type:Number,attribute:!1},sizeX:{type:Number,attribute:!1},sizeY:{type:Number,attribute:!1}};static dragEventName=ne.dragEventName;static dragGeneralEventName=ne.dragGeneralEventName;constructor(){super(),this.locationX=0,this.locationY=0,this.sizeX=0,this.sizeY=0}computeSizes(){const e=this.getBoundingClientRect();this.sizeX=this.blueprint.scaleCorrect(e.width),this.sizeY=this.blueprint.scaleCorrect(e.height)}firstUpdated(e){super.firstUpdated(e),this.computeSizes()}setLocation(e,t,i=!0){const s=e-this.locationX,r=t-this.locationY;if(this.locationX=e,this.locationY=t,this.blueprint&&i){const e=new CustomEvent(this.constructor.dragEventName,{detail:{value:[s,r]},bubbles:!1,cancelable:!0});this.dispatchEvent(e)}}addLocation(e,t,i=!0){this.setLocation(this.locationX+e,this.locationY+t,i)}acknowledgeDrag(e){const t=new CustomEvent(this.constructor.dragGeneralEventName,{detail:{value:e},bubbles:!0,cancelable:!0});this.dispatchEvent(t)}snapToGrid(){const e=Ae.snapToGrid(this.locationX,this.locationY,ne.gridSize);this.locationX==e[0]&&this.locationY==e[1]||this.setLocation(e[0],e[1])}topBoundary(e=!1){return this.template.topBoundary(e)}rightBoundary(e=!1){return this.template.rightBoundary(e)}bottomBoundary(e=!1){return this.template.bottomBoundary(e)}leftBoundary(e=!1){return this.template.leftBoundary(e)}}class Et extends bt{#j=e=>{if(this.blueprint.setFocused(!0),e.button===this.options.clickButton)this.options.strictTarget&&e.target!=e.currentTarget||(this.consumeEvent&&e.stopImmediatePropagation(),this.#U.addEventListener("mousemove",this.#W),document.addEventListener("mouseup",this.#K),this.setLocationFromEvent(e),this.clickedPosition[0]=this.location[0],this.clickedPosition[1]=this.location[1],this.blueprint.mousePosition[0]=this.location[0],this.blueprint.mousePosition[1]=this.location[1],this.target instanceof St&&(this.clickedOffset=[this.clickedPosition[0]-this.target.locationX,this.clickedPosition[1]-this.target.locationY]),this.clicked(this.clickedPosition));else this.options.exitAnyButton||this.#K(e)};#W=e=>{this.consumeEvent&&e.stopImmediatePropagation(),this.#U.removeEventListener("mousemove",this.#W),this.#U.addEventListener("mousemove",this.#Y);const t=this.getEvent(ne.trackingMouseEventName.begin);this.#Z=0==this.target.dispatchEvent(t),this.setLocationFromEvent(e),this.lastLocation=Ae.snapToGrid(this.clickedPosition[0],this.clickedPosition[1],this.stepSize),this.startDrag(this.location),this.started=!0,this.#Y(e)};#Y=e=>{this.consumeEvent&&e.stopImmediatePropagation();const t=this.setLocationFromEvent(e),i=[e.movementX,e.movementY];if(this.dragTo(t,i),this.#Z&&(this.blueprint.mousePosition=t),this.options.scrollGraphEdge){const e=Math.sqrt(i[0]*i[0]+i[1]*i[1]),s=this.blueprint.scaleCorrect(ne.edgeScrollThreshold),r=this.blueprint.template.gridLeftVisibilityBoundary()+s,n=this.blueprint.template.gridRightVisibilityBoundary()-s;let a=0;t[0]n&&(a=t[0]-n);const o=this.blueprint.template.gridTopVisibilityBoundary()+s,l=this.blueprint.template.gridBottomVisibilityBoundary()-s;let u=0;t[1]l&&(u=t[1]-l),a=Ae.clamp(this.blueprint.scaleCorrectReverse(a)**3*e*.6,-20,20),u=Ae.clamp(this.blueprint.scaleCorrectReverse(u)**3*e*.6,-20,20),this.blueprint.scrollDelta(a,u)}};#K=e=>{if(!this.options.exitAnyButton||e.button==this.options.clickButton){if(this.consumeEvent&&e.stopImmediatePropagation(),this.#U.removeEventListener("mousemove",this.#W),this.#U.removeEventListener("mousemove",this.#Y),document.removeEventListener("mouseup",this.#K),this.started&&this.endDrag(),this.unclicked(),this.#Z){const e=this.getEvent(ne.trackingMouseEventName.end);this.target.dispatchEvent(e),this.#Z=!1}this.started=!1}};#Z=!1;#U;#X;clickedOffset=[0,0];clickedPosition=[0,0];lastLocation=[0,0];started=!1;stepSize=1;constructor(e,t,i={}){i.clickButton??=ne.mouseClickButton,i.consumeEvent??=!0,i.draggableElement??=e,i.exitAnyButton??=!0,i.moveEverywhere??=!1,i.movementSpace??=t?.getGridDOMElement(),i.repositionOnClick??=!1,i.scrollGraphEdge??=!1,i.strictTarget??=!1,super(e,t,i),this.stepSize=Number(i.stepSize??ne.gridSize),this.#U=this.options.moveEverywhere?document.documentElement:this.movementSpace,this.#X=this.options.draggableElement,this.listenEvents()}listenEvents(){super.listenEvents(),this.#X.addEventListener("mousedown",this.#j),this.options.clickButton===ne.mouseRightClickButton&&this.#X.addEventListener("contextmenu",(e=>e.preventDefault()))}unlistenEvents(){super.unlistenEvents(),this.#X.removeEventListener("mousedown",this.#j)}getEvent(e){return new CustomEvent(e,{detail:{tracker:this},bubbles:!0,cancelable:!0})}clicked(e){}startDrag(e){}dragTo(e,t){}endDrag(){}unclicked(e){}}class Ct extends Et{startDrag(){this.blueprint.scrolling=!0}dragTo(e,t){this.blueprint.scrollDelta(-t[0],-t[1])}endDrag(){this.blueprint.scrolling=!1}}class Pt extends bt{#q=null;#Q=e=>{e.preventDefault(),this.setLocationFromEvent(e),this.blueprint.mousePosition=[...this.location]};#J=e=>{this.#q||(e.preventDefault(),this.#q=e.detail.tracker,this.unlistenMouseMove())};#ee=e=>{this.#q==e.detail.tracker&&(e.preventDefault(),this.#q=null,this.listenMouseMove())};constructor(e,t,i={}){i.listenOnFocus=!0,super(e,t,i)}listenMouseMove(){this.target.addEventListener("mousemove",this.#Q)}unlistenMouseMove(){this.target.removeEventListener("mousemove",this.#Q)}listenEvents(){this.listenMouseMove(),this.blueprint.addEventListener(ne.trackingMouseEventName.begin,this.#J),this.blueprint.addEventListener(ne.trackingMouseEventName.end,this.#ee)}unlistenEvents(){this.unlistenMouseMove(),this.blueprint.removeEventListener(ne.trackingMouseEventName.begin,this.#J),this.blueprint.removeEventListener(ne.trackingMouseEventName.end,this.#ee)}}class xt{static#te=new Map;static registerElement(e,t){xt.#te.set(e,t)}static getConstructor(e){return xt.#te.get(e)}}class Nt extends ae{static#k=new ut;#ie;constructor(e,t,i={}){i.listenOnFocus??=!0,i.unlistenOnTextEdit??=!0,super(e,t,i);let s=this;this.#ie=e=>s.pasted(e.clipboardData.getData("Text"))}listenEvents(){window.addEventListener("paste",this.#ie)}unlistenEvents(){window.removeEventListener("paste",this.#ie)}pasted(e){let t=0,i=0,s=0,r=Nt.#k.readMultiple(e).map((e=>{let r=xt.getConstructor("ueb-node").newObject(e);return t+=r.locationY,i+=r.locationX,++s,r}));t/=s,i/=s,r.length>0&&this.blueprint.unselectAll();let n=this.blueprint.mousePosition;return r.forEach((e=>{e.addLocation(n[0]-i,n[1]-t),e.snapToGrid(),e.setSelected(!0)})),this.blueprint.addGraphElement(...r),!0}}class kt extends Et{constructor(e,t,i={}){i.scrollGraphEdge??=!0,super(e,t,i),this.selectorElement=this.blueprint.template.selectorElement}startDrag(){this.selectorElement.beginSelect(this.clickedPosition)}dragTo(e,t){this.selectorElement.selectTo(e)}endDrag(){this.started&&this.selectorElement.endSelect()}unclicked(){this.started||this.blueprint.unselectAll()}}class At extends ae{#se=e=>this.clickedSomewhere(e.target);constructor(e,t,i={}){i.listenOnFocus=!0,super(e,t,i),this.blueprint.focus&&document.addEventListener("click",this.#se)}clickedSomewhere(e){e.closest("ueb-blueprint")||this.blueprint.setFocused(!1)}listenEvents(){document.addEventListener("click",this.#se)}unlistenEvents(){document.removeEventListener("click",this.#se)}}class Lt extends pt{static styleVariables={"--ueb-font-size":`${ne.fontSize}`,"--ueb-grid-axis-line-color":`${ne.gridAxisLineColor}`,"--ueb-grid-expand":`${ne.expandGridSize}px`,"--ueb-grid-line-color":`${ne.gridLineColor}`,"--ueb-grid-line-width":`${ne.gridLineWidth}px`,"--ueb-grid-set-line-color":`${ne.gridSetLineColor}`,"--ueb-grid-set":`${ne.gridSet}`,"--ueb-grid-size":`${ne.gridSize}px`,"--ueb-link-min-width":`${ne.linkMinWidth}`,"--ueb-node-radius":`${ne.nodeRadius}px`};#re=new ResizeObserver((e=>{const t=e.find((e=>e.target===this.viewportElement))?.devicePixelContentBoxSize?.[0];t&&(this.viewportSize[0]=t.inlineSize,this.viewportSize[1]=t.blockSize)}));#ne;#ae;#z;headerElement;overlayElement;viewportElement;selectorElement;gridElement;linksContainerElement;nodesContainerElement;viewportSize=[0,0];#oe(){}initialize(e){super.initialize(e),this.element.style.cssText=Object.entries(Lt.styleVariables).map((([e,t])=>`${e}:${t};`)).join("");const t=this.element.querySelector(":scope > template")?.content.textContent;t&&(this.element.requestUpdate(),this.element.updateComplete.then((()=>{this.blueprint.mousePosition=[Math.round(this.viewportSize[0]/2),Math.round(this.viewportSize[1]/2)],this.getPasteInputObject().pasted(t),this.blueprint.unselectAll()})))}setup(){super.setup(),this.#re.observe(this.viewportElement,{box:"device-pixel-content-box"});const e=this.viewportElement.getBoundingClientRect();this.viewportSize[0]=e.width,this.viewportSize[1]=e.height,this.blueprint.nodes.length>0&&(this.blueprint.requestUpdate(),this.blueprint.updateComplete.then((()=>this.centerContentInViewport())))}cleanup(){super.cleanup(),this.#re.unobserve(this.viewportElement)}createInputObjects(){const e=this.element.getGridDOMElement();return this.#ne=new ct(e,this.blueprint),this.#ae=new Nt(e,this.blueprint),this.#z=new yt(e,this.blueprint),[...super.createInputObjects(),this.#ne,this.#ae,this.#z,new ht(e,this.blueprint),new mt(e,this.blueprint,{activationKeys:gt.duplicateNodes},(()=>this.blueprint.template.getPasteInputObject().pasted(this.blueprint.template.getCopyInputObject().copied()))),new mt(e,this.blueprint,{activationKeys:gt.deleteNodes},(()=>this.blueprint.removeGraphElement(...this.blueprint.getNodes(!0)))),new mt(e,this.blueprint,{activationKeys:gt.selectAllNodes},(()=>this.blueprint.selectAll())),new kt(e,this.blueprint,{clickButton:ne.mouseClickButton,exitAnyButton:!0,moveEverywhere:!0}),new Ct(e,this.blueprint,{clickButton:ne.mouseRightClickButton,exitAnyButton:!1,moveEverywhere:!0}),new At(e,this.blueprint),new Pt(e,this.blueprint),new ft(e,this.blueprint)]}render(){return D`
Zoom ${0==this.blueprint.zoom?"1:1":(this.blueprint.zoom>0?"+":"")+this.blueprint.zoom}
`}firstUpdated(e){super.firstUpdated(e),this.headerElement=this.blueprint.querySelector(".ueb-viewport-header"),this.overlayElement=this.blueprint.querySelector(".ueb-viewport-overlay"),this.viewportElement=this.blueprint.querySelector(".ueb-viewport-body"),this.selectorElement=this.blueprint.querySelector("ueb-selector"),this.gridElement=this.viewportElement.querySelector(".ueb-grid"),this.linksContainerElement=this.blueprint.querySelector("[data-links]"),this.linksContainerElement.append(...this.blueprint.getLinks()),this.nodesContainerElement=this.blueprint.querySelector("[data-nodes]"),this.nodesContainerElement.append(...this.blueprint.getNodes()),this.viewportElement.scroll(ne.expandGridSize,ne.expandGridSize)}willUpdate(e){super.willUpdate(e),this.headerElement&&e.has("zoom")&&(this.headerElement.classList.add("ueb-zoom-changed"),this.headerElement.addEventListener("animationend",(()=>this.headerElement.classList.remove("ueb-zoom-changed"))))}updated(e){if(super.updated(e),(e.has("scrollX")||e.has("scrollY"))&&this.viewportElement.scroll(this.blueprint.scrollX,this.blueprint.scrollY),e.has("zoom")){this.blueprint.style.setProperty("--ueb-scale",this.blueprint.getScale());const t=e.get("zoom"),i=Math.min(t,this.blueprint.zoom),s=Math.max(t,this.blueprint.zoom),r=Ae.range(i,s),n=e=>`ueb-zoom-${e}`;te<0)).map(n)),this.blueprint.classList.add(...r.filter((e=>e>0)).map(n))):(this.blueprint.classList.remove(...r.filter((e=>e>0)).map(n)),this.blueprint.classList.add(...r.filter((e=>e<0)).map(n)))}}getCommentNodes(e=!1){return this.blueprint.querySelectorAll(`ueb-node[data-type="${ne.paths.comment}"]${e?'[data-selected="true"]':""}, ueb-node[data-type="${ne.paths.materialGraphNodeComment}"]${e?'[data-selected="true"]':""}`)}getPin(e){return this.blueprint.querySelector(`ueb-node[data-title="${e.objectName}"] ueb-pin[data-id="${e.pinGuid}"]`)}getCopyInputObject(){return this.#ne}getPasteInputObject(){return this.#ae}getZoomInputObject(){return this.#z}isPointVisible(e,t){return!1}gridTopVisibilityBoundary(){return this.blueprint.scaleCorrect(this.blueprint.scrollY)-this.blueprint.translateY}gridRightVisibilityBoundary(){return this.gridLeftVisibilityBoundary()+this.blueprint.scaleCorrect(this.viewportSize[0])}gridBottomVisibilityBoundary(){return this.gridTopVisibilityBoundary()+this.blueprint.scaleCorrect(this.viewportSize[1])}gridLeftVisibilityBoundary(){return this.blueprint.scaleCorrect(this.blueprint.scrollX)-this.blueprint.translateX}centerViewport(e=0,t=0,i=!0){const s=this.gridLeftVisibilityBoundary()+this.blueprint.scaleCorrect(this.viewportSize[0]/2),r=this.gridTopVisibilityBoundary()+this.blueprint.scaleCorrect(this.viewportSize[1]/2);this.blueprint.scrollDelta(this.blueprint.scaleCorrectReverse(e-s),this.blueprint.scaleCorrectReverse(t-r),i)}centerContentInViewport(e=!0){let t=0,i=0,s=Number.MAX_SAFE_INTEGER,r=Number.MIN_SAFE_INTEGER,n=Number.MAX_SAFE_INTEGER,a=Number.MIN_SAFE_INTEGER;const o=this.blueprint.getNodes();for(const e of o)t+=e.leftBoundary()+e.rightBoundary(),i+=e.topBoundary()+e.bottomBoundary(),s=Math.min(s,e.leftBoundary()),r=Math.max(r,e.rightBoundary()),n=Math.min(n,e.topBoundary()),a=Math.max(a,e.bottomBoundary());t=Math.round(r-s<=this.viewportSize[0]?(r+s)/2:t/(2*o.length)),i=Math.round(a-n<=this.viewportSize[1]?(a+n)/2:i/(2*o.length)),this.centerViewport(t,i,e)}}class Mt extends wt{static properties={...super.properties,fromX:{type:Number,attribute:!1},fromY:{type:Number,attribute:!1},toX:{type:Number,attribute:!1},toY:{type:Number,attribute:!1}};constructor(){super(),this.fromX=0,this.fromY=0,this.toX=0,this.toY=0}setBothLocations([e,t]){this.fromX=e,this.fromY=t,this.toX=e,this.toY=t}addSourceLocation(e,t){this.fromX+=e,this.fromY+=t}addDestinationLocation(e,t){this.toX+=e,this.toY+=t}}class Tt extends pt{update(e){super.update(e);const[t,i,s,r]=[Math.round(this.element.fromX),Math.round(this.element.fromY),Math.round(this.element.toX),Math.round(this.element.toY)],[n,a,o,l]=[Math.min(t,s),Math.min(i,r),Math.abs(t-s),Math.abs(i-r)];(e.has("fromX")||e.has("toX"))&&(this.element.style.left=`${n}px`,this.element.style.width=`${o}px`),(e.has("fromY")||e.has("toY"))&&(this.element.style.top=`${a}px`,this.element.style.height=`${l}px`)}}class It extends ot{constructor(e={},t=void 0){e.Class=new Ie(ne.paths.knot),e.Name="K2Node_Knot";const i=new st({PinName:"InputPin"},!0),s=new st({PinName:"OutputPin",Direction:"EGPD_Output"},!0);t&&(i.copyTypeFrom(t),s.copyTypeFrom(t)),e.CustomProperties=[i,s],super(e,!0)}}class Bt extends bt{static#T=e=>{};#j=e=>{if(this.blueprint.setFocused(!0),!this.enablerKey||this.enablerActivated)if(e.button===this.options.clickButton)this.options.strictTarget&&e.target!==e.currentTarget||(this.consumeEvent&&e.stopImmediatePropagation(),document.addEventListener("mouseup",this.#K),this.setLocationFromEvent(e),this.clickedPosition[0]=this.location[0],this.clickedPosition[1]=this.location[1],this.blueprint.mousePosition[0]=this.location[0],this.blueprint.mousePosition[1]=this.location[1],this.clicked(this.clickedPosition));else this.options.exitAnyButton||this.#K(e)};#K=e=>{this.options.exitAnyButton&&e.button!=this.options.clickButton||(this.consumeEvent&&e.stopImmediatePropagation(),document.removeEventListener("mouseup",this.#K),this.unclicked())};clickedPosition=[0,0];constructor(e,t,i={},s=Bt.#T,r=Bt.#T){i.clickButton??=ne.mouseClickButton,i.consumeEvent??=!0,i.exitAnyButton??=!0,i.strictTarget??=!1,super(e,t,i),this.onClick=s,this.onUnclick=r,this.listenEvents()}listenEvents(){this.target.addEventListener("mousedown",this.#j),this.options.clickButton===ne.mouseRightClickButton&&this.target.addEventListener("contextmenu",(e=>e.preventDefault()))}unlistenEvents(){this.target.removeEventListener("mousedown",this.#j)}clicked(e){this.onClick(this)}unclicked(e){this.onUnclick(this)}}class $t extends bt{static ignoreDbClick=e=>{};#le=e=>{this.options.strictTarget&&e.target!==e.currentTarget||(this.consumeEvent&&e.stopImmediatePropagation(),this.clickedPosition=this.setLocationFromEvent(e),this.blueprint.mousePosition=[...this.clickedPosition],this.dbclicked(this.clickedPosition))};#ue;get onDbClick(){return this.#ue}set onDbClick(e){this.#ue=e}clickedPosition=[0,0];constructor(e,t,i={},s=$t.ignoreDbClick){i.consumeEvent??=!0,i.strictTarget??=!1,super(e,t,i),this.#ue=s,this.listenEvents()}listenEvents(){this.target.addEventListener("dblclick",this.#le)}unlistenEvents(){this.target.removeEventListener("dblclick",this.#le)}dbclicked(e){this.onDbClick(e)}}class Ht extends Tt{static decreasingValue(e,t){const i=-e*t[0]**2,s=t[1]-i/t[0];return e=>i/e+s}static clampedLine(e,t){if(e[0]>t[0]){const i=e;e=t,t=i}const i=(t[1]-e[1])/(t[0]-e[0]),s=e[1]-i*e[0];return r=>rt[0]?t[1]:i*r+s}static c1DecreasingValue=Ht.decreasingValue(-.15,[100,15]);static c2DecreasingValue=Ht.decreasingValue(-.05,[500,130]);static c2Clamped=Ht.clampedLine([0,80],[200,40]);#ce=`ueb-id-${Math.floor(1e12*Math.random())}`;#he=e=>{const t=new It({},this.element.source.entity),i=xt.getConstructor("ueb-node").newObject(t);i.setLocation(...this.blueprint.snapToGrid(...e));const s=i.template;this.blueprint.addGraphElement(i);const r=this.element.getInputPin(),n=this.element.getOutputPin();this.element.source=null,this.element.destination=null;const a=xt.getConstructor("ueb-link").newObject(n,s.inputPin);this.blueprint.addGraphElement(a),this.element.source=s.outputPin,this.element.destination=r};createInputObjects(){const e=this.element.querySelector(".ueb-link-area");return[...super.createInputObjects(),new $t(e,this.blueprint,void 0,(e=>{e[0]+=ne.knotOffset[0],e[1]+=ne.knotOffset[1],e=Ae.snapToGrid(e[0],e[1],ne.gridSize),this.#he(e)})),new Bt(e,this.blueprint,{enablerKey:new mt(this.blueprint,this.blueprint,{activationKeys:gt.enableLinkDelete})},(()=>this.blueprint.removeGraphElement(this.element)))]}willUpdate(e){super.willUpdate(e);const t=this.element.source,i=this.element.destination;if(e.has("fromX")||e.has("toX")){const e=this.element.fromX,s=this.element.toX,r=t?.nodeElement.getType()==ne.paths.knot,n=i?.nodeElement.getType()==ne.paths.knot;!r||i&&!n||(t?.isInput()&&s>e+ne.distanceThreshold?this.element.source=t.nodeElement.template.outputPin:t?.isOutput()&&se+ne.distanceThreshold&&(this.element.destination=i.nodeElement.template.inputPin))}const s=Math.max(Math.abs(this.element.fromX-this.element.toX),1),r=Math.max(Math.abs(this.element.fromY-this.element.toY),1),n=Math.max(s,ne.linkMinWidth),a=s/n,o=this.element.originatesFromInput?this.element.fromXthis.element.toY?1:0)),this.element.style.setProperty("--ueb-start-percentage",`${Math.round(this.element.startPercentage)}%`),this.element.style.setProperty("--ueb-link-start",`${Math.round(this.element.startPixels)}`)}render(){return D` ${this.element.linkMessageIcon||this.element.linkMessageText?D``:V}`}}class Gt extends Mt{static properties={...super.properties,dragging:{type:Boolean,attribute:"data-dragging",converter:Ae.booleanConverter,reflect:!0},originatesFromInput:{type:Boolean,attribute:!1},svgPathD:{type:String,attribute:!1},linkMessageIcon:{type:String,attribute:!1},linkMessageText:{type:String,attribute:!1}};#pe;get source(){return this.#pe}set source(e){this.#de(e,!1)}#me;get destination(){return this.#me}set destination(e){this.#de(e,!0)}#ge=()=>this.remove();#be=e=>this.addSourceLocation(...e.detail.value);#ve=e=>this.addDestinationLocation(...e.detail.value);#ye=e=>this.setSourceLocation();#fe=e=>this.setDestinationLocation();linkMessageIcon=V;linkMessageText=V;pathElement;constructor(){super(),this.dragging=!1,this.originatesFromInput=!1,this.startPercentage=0,this.svgPathD="",this.startPixels=0}static newObject(e,t){const i=new Gt;return i.initialize(e,t),i}initialize(e,t){super.initialize({},new Ht),e&&(this.source=e,t||(this.toX=this.fromX,this.toY=this.fromY)),t&&(this.destination=t,e||(this.fromX=this.toX,this.fromY=this.toY))}#de(e,t){const i=()=>t?this.destination:this.source;if(i()!=e){if(i()){const e=i().getNodeElement();e.removeEventListener(ne.removeEventName,this.#ge),e.removeEventListener(ne.nodeDragEventName,t?this.#ve:this.#be),e.removeEventListener(ne.nodeReflowEventName,t?this.#fe:this.#ye),this.#we()}if(t?this.#me=e:this.#pe=e,i()){const e=i().getNodeElement();e.addEventListener(ne.removeEventName,this.#ge),e.addEventListener(ne.nodeDragEventName,t?this.#ve:this.#be),e.addEventListener(ne.nodeReflowEventName,t?this.#fe:this.#ye),t?this.setDestinationLocation():(this.setSourceLocation(),this.originatesFromInput=this.source.isInput()),this.#Se()}}}#Se(){this.source&&this.destination&&(this.source.linkTo(this.destination),this.destination.linkTo(this.source))}#we(){this.source&&this.destination&&(this.source.unlinkFrom(this.destination,!1),this.destination.unlinkFrom(this.source,!1))}cleanup(){super.cleanup(),this.#we(),this.source=null,this.destination=null}setSourceLocation(e=null,t=!0){if(null==e){const i=this;if(t&&(!this.hasUpdated||!this.source.hasUpdated))return void Promise.all([this.updateComplete,this.source.updateComplete]).then((()=>i.setSourceLocation(null,!1)));e=this.source.template.getLinkLocation()}const[i,s]=e;this.fromX=i,this.fromY=s}setDestinationLocation(e=null,t=!0){if(null==e){const i=this;if(t&&(!this.hasUpdated||!this.destination.hasUpdated))return void Promise.all([this.updateComplete,this.destination.updateComplete]).then((()=>i.setDestinationLocation(null,!1)));e=this.destination.template.getLinkLocation()}this.toX=e[0],this.toY=e[1]}getInputPin(){return this.source?.isInput()?this.source:this.destination}setInputPin(e){this.source?.isInput()&&(this.source=e),this.destination=e}getOutputPin(){return this.destination?.isOutput()?this.destination:this.source}setOutputPin(e){this.destination?.isOutput()&&(this.destination=e),this.source=e}startDragging(){this.dragging=!0}finishDragging(){this.dragging=!1}removeMessage(){this.linkMessageIcon=V,this.linkMessageText=V}setMessageConvertType(){this.linkMessageIcon=rt.convert,this.linkMessageText=D`Convert ${this.source.pinType} to ${this.destination.pinType}.`}setMessageCorrect(){this.linkMessageIcon=rt.correct,this.linkMessageText=V}setMessageReplace(){this.linkMessageIcon=rt.correct,this.linkMessageText=V}setMessageDirectionsIncompatible(){this.linkMessageIcon=rt.reject,this.linkMessageText=D`Directions are not compatbile.`}setMessagePlaceNode(){this.linkMessageIcon=V,this.linkMessageText=D`Place a new node.`}setMessageReplaceLink(){this.linkMessageIcon=rt.correct,this.linkMessageText=D`Replace existing input connections.`}setMessageReplaceOutputLink(){this.linkMessageIcon=rt.correct,this.linkMessageText=D`Replace existing output connections.`}setMessageSameNode(){this.linkMessageIcon=rt.reject,this.linkMessageText=D`Both are on the same node.`}setMessageTypesIncompatible(e,t){this.linkMessageIcon=rt.reject,this.linkMessageText=D`${Ae.capitalFirstLetter(e.pinType)} is not compatible with ${Ae.capitalFirstLetter(t.pinType)}.`}}class Dt extends Et{clicked(e){this.options.repositionOnClick&&(this.target.setLocation(...this.stepSize>1?Ae.snapToGrid(e[0],e[1],this.stepSize):e),this.clickedOffset=[0,0])}dragTo(e,t){const i=[this.target.locationX??this.lastLocation[0],this.target.locationY??this.lastLocation[1]],[s,r]=this.stepSize>1?[Ae.snapToGrid(e[0],e[1],this.stepSize),Ae.snapToGrid(i[0],i[1],this.stepSize)]:[e,i];0==(t=[s[0]-this.lastLocation[0],s[1]-this.lastLocation[1]])[0]&&0==t[1]||(t[0]+=r[0]-i[0],t[1]+=r[1]-i[1],this.dragAction(s,t),this.lastLocation=s)}dragAction(e,t){this.target.setLocation(e[0]-this.clickedOffset[0],e[1]-this.clickedOffset[1])}}class Ot extends Dt{#Ee;#Ce;#Pe;#xe;constructor(e,t,i={}){super(e,t,i),i.onClicked&&(this.#Ee=i.onClicked),i.onStartDrag&&(this.#Ce=i.onStartDrag),i.onDrag&&(this.#Pe=i.onDrag),i.onEndDrag&&(this.#xe=i.onEndDrag)}clicked(e){super.clicked(e),this.#Ee?.()}startDrag(){super.startDrag(),this.#Ce?.()}dragAction(e,t){this.#Pe?.(e,t)}endDrag(){super.endDrag(),this.#xe?.()}}class Vt extends pt{getDraggableElement(){return this.element}createDraggableObject(){return new Dt(this.element,this.blueprint,{draggableElement:this.getDraggableElement()})}createInputObjects(){return[...super.createInputObjects(),this.createDraggableObject(),new mt(this.element,this.blueprint,{activationKeys:[ne.Keys.ArrowUp,ne.Keys.ArrowRight,ne.Keys.ArrowDown,ne.Keys.ArrowLeft]},(e=>e.target.acknowledgeDrag([e.pressedKey===ne.Keys.ArrowLeft?-ne.gridSize:e.pressedKey===ne.Keys.ArrowRight?ne.gridSize:0,e.pressedKey===ne.Keys.ArrowUp?-ne.gridSize:e.pressedKey===ne.Keys.ArrowDown?ne.gridSize:0])))]}topBoundary(e=!1){return this.element.locationY}rightBoundary(e=!1){return this.element.locationX+this.element.sizeX}bottomBoundary(e=!1){return this.element.locationY+this.element.sizeY}leftBoundary(e=!1){return this.element.locationX}centerInViewport(){const e=Math.min(this.blueprint.template.viewportSize[0]/10,this.blueprint.template.viewportSize[1]/10),t=this.leftBoundary()-this.blueprint.template.gridLeftVisibilityBoundary(),i=this.blueprint.template.gridRightVisibilityBoundary()-this.rightBoundary();let s=Math.max((t+i)/2,e);const r=this.topBoundary()-this.blueprint.template.gridTopVisibilityBoundary(),n=this.blueprint.template.gridBottomVisibilityBoundary()-this.bottomBoundary();let a=Math.max((r+n)/2,e);this.blueprint.scrollDelta(t-s,r-a,!0)}}class Rt extends Vt{update(e){super.update(e),e.has("locationX")&&(this.element.style.left=`${this.element.locationX}px`),e.has("locationY")&&(this.element.style.top=`${this.element.locationY}px`)}}class zt extends Dt{startDrag(){this.target.selected||(this.blueprint.unselectAll(),this.target.setSelected(!0))}dragAction(e,t){this.target.acknowledgeDrag(t)}unclicked(){this.started?(this.blueprint.getNodes(!0).forEach((e=>e.boundComments.filter((t=>!e.isInsideComment(t))).forEach((t=>e.unbindFromComment(t))))),this.blueprint.getCommentNodes().forEach((e=>e.template.manageNodesBind()))):(this.blueprint.unselectAll(),this.target.setSelected(!0))}}class _t extends Rt{getDraggableElement(){return this.element}createDraggableObject(){return new zt(this.element,this.blueprint,{draggableElement:this.getDraggableElement(),scrollGraphEdge:!0})}firstUpdated(e){super.firstUpdated(e),this.element.selected&&!this.element.listeningDrag&&this.element.setSelected(!0)}}class Ft extends _t{static nodeStyleClasses=["ueb-node-style-default"];#Ne=!1;pinInserter;inputContainer;outputContainer;pinElement;addPinHandler=()=>{const e=this.pinInserter?.();e&&(this.defaultPin&&this.defaultPin.isInput()===e.isInput()?this.defaultPin.before(this.createPinElement(e)):(e.isInput()?this.inputContainer:this.outputContainer).appendChild(this.createPinElement(e)),this.element.acknowledgeReflow())};toggleAdvancedDisplayHandler=()=>{this.element.toggleShowAdvancedPinDisplay(),this.element.requestUpdate(),this.element.updateComplete.then((()=>this.element.acknowledgeReflow()))};createPinElement(e){const t=xt.getConstructor("ueb-pin").newObject(e,void 0,this.element);return this.pinInserter&&!this.defaultPin&&"Default"===t.getPinName()&&(this.defaultPin=t,this.defaultPin.classList.add("ueb-node-variadic-default")),t}initialize(e){super.initialize(e),this.element.classList.add(...this.constructor.nodeStyleClasses),this.element.style.setProperty("--ueb-node-color",this.getColor().cssText),this.pinInserter=this.element.entity.additionalPinInserter(),this.pinInserter&&this.element.classList.add("ueb-node-is-variadic")}getColor(){return this.element.entity.nodeColor()}render(){return D`
${this.renderTop()}
${this.pinInserter?D`
Add pin ${rt.plusCircle}
`:V} ${this.element.entity.isDevelopmentOnly()?D`
Development Only
`:V} ${this.element.advancedPinDisplay?D`
${rt.expandIcon}
`:V}
`}renderNodeIcon(){return this.element.entity.nodeIcon()}renderNodeName(){return this.element.getNodeDisplayName()}renderTop(){const e=this.renderNodeIcon(),t=this.renderNodeName();return D`
${e?D`
${e}
`:V} ${t?D`
${t} ${this.#Ne&&this.getTargetType().length>0?D`
Target is ${Ae.formatStringName(this.getTargetType())}
`:V}
`:V}
`}firstUpdated(e){super.firstUpdated(e),this.inputContainer=this.element.querySelector(".ueb-node-inputs"),this.outputContainer=this.element.querySelector(".ueb-node-outputs"),this.setupPins(),this.element.updateComplete.then((()=>this.element.acknowledgeReflow()))}setupPins(){this.element.nodeNameElement=this.element.querySelector(".ueb-node-name-text");let e=!1,t=!1;for(const i of this.element.getPinElements())i!==this.defaultPin&&(i.isInput()?(this.inputContainer.appendChild(i),e=!0):i.isOutput()&&(this.outputContainer.appendChild(i),t=!0));this.defaultPin&&(this.defaultPin.isInput()?this.inputContainer:this.outputContainer).appendChild(this.defaultPin),e&&this.element.classList.add("ueb-node-has-inputs"),t&&this.element.classList.add("ueb-node-has-outputs")}createPinElements(){return this.element.getPinEntities().filter((e=>!e.isHidden())).map((e=>(this.#Ne=this.#Ne||"self"===e.PinName&&"Target"===e.pinDisplayName(),this.createPinElement(e))))}getTargetType(){return this.element.entity.FunctionReference?.MemberParent?.getName()??"Untitled"}getPinElements(e){return e.querySelectorAll("ueb-pin")}linksChanged(){}}class jt extends Ft{#ke=document.createElement("div");#Ae=document.createElement("div");#Le=document.createElement("div");#Me=document.createElement("div");#Te=document.createElement("div");#Ie=document.createElement("div");#Be=document.createElement("div");#$e=document.createElement("div");initialize(e){super.initialize(e),this.element.classList.add("ueb-resizeable"),this.#ke.classList.add("ueb-resizeable-top"),this.#Ae.classList.add("ueb-resizeable-right"),this.#Le.classList.add("ueb-resizeable-bottom"),this.#Me.classList.add("ueb-resizeable-left"),this.#Te.classList.add("ueb-resizeable-top-right"),this.#Ie.classList.add("ueb-resizeable-bottom-right"),this.#Be.classList.add("ueb-resizeable-bottom-left"),this.#$e.classList.add("ueb-resizeable-top-left")}update(e){super.update(e),this.element.sizeX>=0&&e.has("sizeX")&&(this.element.style.width=`${this.element.sizeX}px`),this.element.sizeY>=0&&e.has("sizeY")&&(this.element.style.height=`${this.element.sizeY}px`)}firstUpdated(e){super.firstUpdated(e),this.element.append(this.#ke,this.#Ae,this.#Le,this.#Me,this.#Te,this.#Ie,this.#Be,this.#$e)}createInputObjects(){return[...super.createInputObjects(),new Ot(this.#ke,this.blueprint,{onDrag:(e,t)=>{t[1]=e[1]-this.element.topBoundary(),this.setSizeY(this.element.sizeY-t[1])&&this.element.addLocation(0,t[1],!1)},onEndDrag:()=>this.endResize()}),new Ot(this.#Ae,this.blueprint,{onDrag:(e,t)=>{t[0]=e[0]-this.element.rightBoundary(),this.setSizeX(this.element.sizeX+t[0])},onEndDrag:()=>this.endResize()}),new Ot(this.#Le,this.blueprint,{onDrag:(e,t)=>{t[1]=e[1]-this.element.bottomBoundary(),this.setSizeY(this.element.sizeY+t[1])},onEndDrag:()=>this.endResize()}),new Ot(this.#Me,this.blueprint,{onDrag:(e,t)=>{t[0]=e[0]-this.element.leftBoundary(),this.setSizeX(this.element.sizeX-t[0])&&this.element.addLocation(t[0],0,!1)},onEndDrag:()=>this.endResize()}),new Ot(this.#Te,this.blueprint,{onDrag:(e,t)=>{t[0]=e[0]-this.element.rightBoundary(),t[1]=e[1]-this.element.topBoundary(),this.setSizeX(this.element.sizeX+t[0]),this.setSizeY(this.element.sizeY-t[1])&&this.element.addLocation(0,t[1],!1)},onEndDrag:()=>this.endResize()}),new Ot(this.#Ie,this.blueprint,{onDrag:(e,t)=>{t[0]=e[0]-this.element.rightBoundary(),t[1]=e[1]-this.element.bottomBoundary(),this.setSizeX(this.element.sizeX+t[0]),this.setSizeY(this.element.sizeY+t[1])},onEndDrag:()=>this.endResize()}),new Ot(this.#Be,this.blueprint,{onDrag:(e,t)=>{t[0]=e[0]-this.element.leftBoundary(),t[1]=e[1]-this.element.bottomBoundary(),this.setSizeX(this.element.sizeX-t[0])&&this.element.addLocation(t[0],0,!1),this.setSizeY(this.element.sizeY+t[1])},onEndDrag:()=>this.endResize()}),new Ot(this.#$e,this.blueprint,{onDrag:(e,t)=>{t[0]=e[0]-this.element.leftBoundary(),t[1]=e[1]-this.element.topBoundary(),this.setSizeX(this.element.sizeX-t[0])&&this.element.addLocation(t[0],0,!1),this.setSizeY(this.element.sizeY-t[1])&&this.element.addLocation(0,t[1],!1)},onEndDrag:()=>this.endResize()})]}setSizeX(e){return this.element.setNodeWidth(e),!0}setSizeY(e){return this.element.setNodeHeight(e),!0}endResize(){}}class Ut extends jt{#He=0;initialize(e){super.initialize(e),e.classList.add("ueb-node-style-comment","ueb-node-resizeable"),e.sizeX=25*ne.gridSize,e.sizeY=6*ne.gridSize,super.initialize(e)}getDraggableElement(){return this.element.querySelector(".ueb-node-top")}render(){return D`
`}firstUpdated(e){super.firstUpdated(e);const t=this.getDraggableElement().getBoundingClientRect();this.#He=t.height}manageNodesBind(){let e=this.blueprint.getNodes();for(let t of e)t.topBoundary()>=this.element.topBoundary()&&t.rightBoundary()<=this.element.rightBoundary()&&t.bottomBoundary()<=this.element.bottomBoundary()&&t.leftBoundary()>=this.element.leftBoundary()?t.bindToComment(this.element):t.unbindFromComment(this.element)}setSizeX(e){return(e=Math.round(e))>=2*ne.gridSize&&(this.element.setNodeWidth(e),!0)}setSizeY(e){return(e=Math.round(e))>=2*ne.gridSize&&(this.element.setNodeHeight(e),!0)}endResize(){this.manageNodesBind()}topBoundary(e=!1){return this.element.locationY}rightBoundary(e=!1){return this.element.locationX+this.element.sizeX}bottomBoundary(e=!1){return e?this.element.locationY+this.#He:super.bottomBoundary()}leftBoundary(e=!1){return this.element.locationX}}class Wt extends Et{#Ge;#De=null;#Oe=e=>{if(!this.enteredPin){this.linkValid=!1,this.enteredPin=e.target;const t=this.link.source??this.target,i=this.enteredPin,s=t.isOutput()?t:i;t.nodeElement.getType()===ne.paths.knot||i.nodeElement.getType()===ne.paths.knot?(this.link.setMessageCorrect(),this.linkValid=!0):t.getNodeElement()===i.getNodeElement()?this.link.setMessageSameNode():t.isOutput()===i.isOutput()?this.link.setMessageDirectionsIncompatible():this.blueprint.getLinks(t,i).length?(this.link.setMessageReplaceLink(),this.linkValid=!0):"exec"===s.entity.getType()&&s.isLinked?(this.link.setMessageReplaceOutputLink(),this.linkValid=!0):"object"==t.entity.PinType.PinCategory&&"object"==i.entity.PinType.PinCategory||t.pinType==i.pinType?(this.link.setMessageCorrect(),this.linkValid=!0):(this.link.setMessageTypesIncompatible(t,i),this.linkValid=!1)}};#Ve=e=>{this.enteredPin==e.target&&(this.enteredPin=null,this.linkValid=!1,this.link?.setMessagePlaceNode())};link;enteredPin;linkValid=!1;constructor(e,t,i={}){i.scrollGraphEdge??=!0,super(e,t,i)}startDrag(e){this.target.nodeElement.getType()==ne.paths.knot&&(this.#De=this.target),this.link=xt.getConstructor("ueb-link").newObject(this.target,null),this.blueprint.template.linksContainerElement.prepend(this.link),this.link.setMessagePlaceNode(),this.#Ge=this.blueprint.querySelectorAll("ueb-pin"),this.#Ge.forEach((e=>{e!=this.target&&(e.addEventListener("mouseenter",this.#Oe),e.addEventListener("mouseleave",this.#Ve))})),this.link.startDragging(),this.link.setDestinationLocation(e)}dragTo(e,t){this.link.setDestinationLocation(e)}endDrag(){if(this.#Ge.forEach((e=>{e.removeEventListener("mouseenter",this.#Oe),e.removeEventListener("mouseleave",this.#Ve)})),this.#Ge=null,this.enteredPin&&this.linkValid){if(this.#De){const e=this.#De!==this.link.source?this.link.source:this.enteredPin;if(this.#De.isInput()&&e.isInput()||this.#De.isOutput()&&e.isOutput()){const e=this.#De.template.getOppositePin();this.#De===this.link.source?this.link.source=e:this.enteredPin=e}}else this.enteredPin.nodeElement.getType()===ne.paths.knot&&(this.enteredPin=this.enteredPin.template.getOppositePin());this.link.source.getLinks().find((e=>e.equals(this.enteredPin.createPinReference())))?this.link.remove():(this.blueprint.addGraphElement(this.link),this.link.destination=this.enteredPin)}else this.link.remove();this.enteredPin=null,this.link.removeMessage(),this.link.finishDragging(),this.link=null}}class Kt extends Ft{#Re=!1;#ze=!1;#_e="";static nodeStyleClasses=["ueb-node-style-glass"];initialize(e){super.initialize(e),this.#_e=this.element.getNodeDisplayName()}render(){return D`
${this.#_e?D`
${this.#_e}
`:V} ${this.#Re?D`
`:V} ${this.#ze?D`
`:V} ${this.pinInserter?D`
Add pin ${rt.plusCircle}
`:V}
`}createPinElements(){return this.element.getPinEntities().filter((e=>!e.isHidden())).map((e=>{this.#Re||=e.isInput(),this.#ze||=e.isOutput();return xt.getConstructor("ueb-pin").newObject(e,void 0,this.element)}))}}class Yt extends Kt{static nodeStyleClasses=[...super.nodeStyleClasses,"ueb-node-style-conversion"]}class Zt extends Kt{static nodeStyleClasses=[...super.nodeStyleClasses,"ueb-node-style-operation"]}class Xt extends pt{static canWrapInput=!0;#Fe;get iconElement(){return this.#Fe}#je;get wrapperElement(){return this.#je}isNameRendered=!0;initialize(e){if(super.initialize(e),this.element.nodeElement){const e=this.element.nodeElement.template;this.isNameRendered=!(e instanceof Yt||e instanceof Zt)}}setup(){super.setup(),this.element.nodeElement=this.element.closest("ueb-node");const e=this.element.nodeElement.template;(e instanceof Yt||e instanceof Zt)&&(this.isNameRendered=!1,this.element.requestUpdate())}createInputObjects(){return[new Wt(this.element,this.blueprint,{moveEverywhere:!0,draggableElement:this.getClickableElement()})]}render(){const e=D`
${this.renderIcon()}
`,t=D`
${this.isNameRendered?this.renderName():V} ${this.isInputRendered()?this.renderInput():D``}
`;return D`
${this.element.isInput()?D`${e}${t}`:D`${t}${e}`}
`}renderIcon(){if(this.element.nodeElement.entity.isPcg())switch(this.element.entity.getType()){case"Any":return rt.pcgPin;case"Param":case"Param[]":return rt.pcgParamPin;case"Spatial":case"Spatial[]":return rt.pcgSpatialPin;case"Any[]":case"Point[]":case"Surface[]":case"Volume[]":if(this.element.isOutput())return rt.pcgPin;case"Point":case"Surface":case"Volume":return rt.pcgStackPin}switch(this.element.entity.PinType?.ContainerType?.toString()){case"Array":return rt.arrayPin;case"Set":return rt.setPin;case"Map":return rt.mapPin}return"delegate"===this.element.entity.PinType?.PinCategory?.toLocaleLowerCase()?rt.delegate:this.element.nodeElement?.template instanceof Zt?rt.operationPin:rt.genericPin}renderName(){let e=this.element.getPinDisplayName();const t=this.element.nodeElement,i=this.element.getPinName();return t.getType()==ne.paths.makeStruct&&i==t.entity.StructType.getName()&&(e=i),D`${e}`}isInputRendered(){return this.element.isInput()&&!this.element.entity.bDefaultValueIsIgnored&&!this.element.entity.PinType.bIsReference}renderInput(){return D``}updated(e){if(super.updated(e),this.element.isInput()&&e.has("isLinked")){const e=this.element.nodeElement;this.element.requestUpdate(),this.element.updateComplete.then((()=>e.acknowledgeReflow()))}}firstUpdated(e){super.firstUpdated(e),this.element.style.setProperty("--ueb-pin-color-rgb",this.element.entity.pinColor().cssText),this.#Fe=this.element.querySelector(".ueb-pin-icon svg")??this.element,this.#je=this.element.querySelector(".ueb-pin-wrapper")}getLinkLocation(){const e=this.iconElement.getBoundingClientRect(),t=[this.element.isInput()?e.left:e.right+1,(e.top+e.bottom)/2],i=Ae.convertLocation(t,this.blueprint.template.gridElement);return this.blueprint.compensateTranslation(i[0],i[1])}getClickableElement(){return this.#je??this.element}}class qt extends Xt{render(){return D`
${this.renderIcon()}
`}}class Qt extends Ft{static nodeStyleClasses=[...super.nodeStyleClasses,"ueb-node-style-event"];firstUpdated(e){super.firstUpdated(e),this.element.querySelector(".ueb-node-top").appendChild(this.createDelegatePinElement())}renderTop(){const e=this.renderNodeIcon(),t=this.renderNodeName(),i=this.element.getType()===ne.paths.customEvent&&(this.element.entity.CustomFunctionName||this.element.entity.FunctionReference.MemberParent);return D`
${e?D`
${e}
`:V} ${t?D`
${t} ${i?D`
Custom Event
`:V}
`:V}
`}createDelegatePinElement(){const e=xt.getConstructor("ueb-pin").newObject(this.element.getPinEntities().find((e=>!e.isHidden()&&"delegate"===e.PinType.PinCategory)),new qt,this.element);return e.template.isNameRendered=!1,e}createPinElements(){return this.element.getPinEntities().filter((e=>!e.isHidden()&&"delegate"!==e.PinType.PinCategory)).map((e=>xt.getConstructor("ueb-pin").newObject(e,void 0,this.element)))}}class Jt extends St{static properties={...super.properties,selected:{type:Boolean,attribute:"data-selected",reflect:!0,converter:Ae.booleanConverter}};dragHandler=e=>this.addLocation(...e.detail.value);constructor(){super(),this.selected=!1,this.listeningDrag=!1}setup(){super.setup(),this.setSelected(this.selected)}cleanup(){super.cleanup(),this.blueprint.removeEventListener(ne.nodeDragGeneralEventName,this.dragHandler)}setSelected(e=!0){this.selected=e,this.blueprint&&(this.selected?(this.listeningDrag=!0,this.blueprint.addEventListener(ne.nodeDragGeneralEventName,this.dragHandler)):(this.blueprint.removeEventListener(ne.nodeDragGeneralEventName,this.dragHandler),this.listeningDrag=!1))}}class ei extends qt{render(){return this.element.isOutput()?super.render():D``}getOppositePin(){const e=this.element.nodeElement.template;return this.element.isOutput()?e.inputPin:e.outputPin}getLinkLocation(){const e=(this.element.isInput()?this.element.nodeElement.template.outputPin.template:this).iconElement.getBoundingClientRect(),t=[this.element.isInput()?e.left:e.right+1,(e.top+e.bottom)/2],i=Ae.convertLocation(t,this.blueprint.template.gridElement);return this.blueprint.compensateTranslation(i[0],i[1])}}class ti extends Ft{static#Ue=new Set;#We=null;#Ke;get inputPin(){return this.#Ke}#Ye;get outputPin(){return this.#Ye}initialize(e){super.initialize(e),this.element.classList.add("ueb-node-style-minimal")}findDirectionaPin(e){if(e.nodeElement.getType()!==ne.paths.knot||ti.#Ue.has(e))return ti.#Ue.clear(),!0;ti.#Ue.add(e);for(let t of e.getLinks().map((e=>this.blueprint.getPin(e))))if(this.findDirectionaPin(t))return!0;return!1}render(){return D`
`}setupPins(){this.element.getPinElements().forEach((e=>this.element.querySelector(".ueb-node-border").appendChild(e)))}getPinElements(e){return e.querySelectorAll("ueb-pin")}createPinElements(){const e=this.element.getPinEntities().filter((e=>!e.isHidden())),t=e[e[0].isInput()?0:1],i=e[e[0].isOutput()?0:1],s=xt.getConstructor("ueb-pin");return[this.#Ke=s.newObject(t,new ei,this.element),this.#Ye=s.newObject(i,new ei,this.element)]}linksChanged(){}}class ii extends Kt{initialize(e){super.initialize(e),e.getType()===ne.paths.variableGet?this.element.classList.add("ueb-node-style-getter"):e.getType()===ne.paths.variableSet&&this.element.classList.add("ueb-node-style-setter")}setupPins(){super.setupPins();let e=this.element.getPinElements().find((e=>!e.entity.isHidden()&&!e.entity.isExecution()));this.element.style.setProperty("--ueb-node-color",e.getColor().cssText)}}class si extends Jt{static properties={...Jt.properties,typePath:{type:String,attribute:"data-type",reflect:!0},nodeTitle:{type:String,attribute:"data-title",reflect:!0},advancedPinDisplay:{type:String,attribute:"data-advanced-display",converter:$e.attributeConverter,reflect:!0},enabledState:{type:String,attribute:"data-enabled-state",reflect:!0},nodeDisplayName:{type:String,attribute:!1},pureFunction:{type:Boolean,converter:Ae.booleanConverter,attribute:"data-pure-function",reflect:!0}};static dragEventName=ne.nodeDragEventName;static dragGeneralEventName=ne.nodeDragGeneralEventName;get blueprint(){return super.blueprint}set blueprint(e){super.blueprint=e,this.#Ze.forEach((t=>t.blueprint=e))}#Xe;get nodeNameElement(){return this.#Xe}set nodeNameElement(e){this.#Xe=e}#Ze=[];boundComments=[];#qe=!1;#Qe=e=>{this.selected||this.#qe||(this.#qe=!0,this.requestUpdate(),this.updateComplete.then((()=>this.#qe=!1)),this.addLocation(...e.detail.value))};static getTypeTemplate(e){if(e.getClass()===ne.paths.callFunction||e.getClass()===ne.paths.commutativeAssociativeBinaryOperator||e.getClass()===ne.paths.callArrayFunction){const t=e.FunctionReference?.MemberParent?.path??"",i=e.FunctionReference?.MemberName;if(i&&(t===ne.paths.kismetMathLibrary||t===ne.paths.kismetArrayLibrary)){if(i.startsWith("Conv_"))return Yt;if(i.startsWith("And_")||i.startsWith("Boolean")||i.startsWith("Cross_")||i.startsWith("Dot_")||i.startsWith("Not_")||i.startsWith("Or_")||i.startsWith("Percent_")||i.startsWith("Xor_"))return Zt;switch(i){case"Abs":case"Array_Add":case"Array_AddUnique":case"Array_Identical":case"BMax":case"BMin":case"CrossProduct2D":case"DotProduct2D":case"Exp":case"FMax":case"FMin":case"GetPI":case"Max":case"MaxInt64":case"Min":case"MinInt64":case"Sqrt":case"Square":case"Vector4_CrossProduct3":case"Vector4_DotProduct":case"Vector4_DotProduct3":case"Acos":case"Asin":case"Cos":case"DegAcos":case"DegCos":case"DegSin":case"DegTan":case"Sin":case"Tan":return Zt}}if(t===ne.paths.blueprintSetLibrary)return Zt;if(t===ne.paths.blueprintMapLibrary)return Zt}switch(e.getClass()){case ne.paths.comment:case ne.paths.materialGraphNodeComment:return Ut;case ne.paths.createDelegate:return Ft;case ne.paths.promotableOperator:return Zt;case ne.paths.knot:return ti;case ne.paths.literal:case ne.paths.variableGet:case ne.paths.variableSet:return ii}return e.isEvent()?Qt:Ft}static fromSerializedObject(e){e=e.trim();let t=Ne.getSerializer(ot).read(e);return si.newObject(t)}static newObject(e=new ot,t=new(si.getTypeTemplate(e))){const i=new si;return i.initialize(e,t),i}initialize(e=new ot,t=new(si.getTypeTemplate(e))){super.initialize(e,t),this.#Ze=this.template.createPinElements(),this.typePath=this.entity.getType(),this.nodeTitle=this.entity.getObjectName(),this.advancedPinDisplay=this.entity.AdvancedPinDisplay?.toString(),this.enabledState=this.entity.EnabledState,this.nodeDisplayName=this.getNodeDisplayName(),this.pureFunction=this.entity.bIsPureFunc,this.dragLinkObjects=[],super.setLocation(this.entity.getNodePosX(),this.entity.getNodePosY()),this.entity.NodeWidth&&this.entity.NodeHeight?(this.sizeX=this.entity.NodeWidth.value,this.sizeY=this.entity.NodeHeight.value):this.updateComplete.then((()=>this.computeSizes()))}async getUpdateComplete(){let e=await super.getUpdateComplete();for(const t of this.getPinElements())e&&=await t.updateComplete;return e}bindToComment(e){e==this||this.boundComments.includes(e)||(e.addEventListener(ne.nodeDragEventName,this.#Qe),this.boundComments.push(e))}unbindFromComment(e){const t=this.boundComments.indexOf(e);t>=0&&(e.removeEventListener(ne.nodeDragEventName,this.#Qe),this.boundComments[t]=this.boundComments[this.boundComments.length-1],this.boundComments.pop())}isInsideComment(e){return this.topBoundary()>=e.topBoundary()&&this.rightBoundary()<=e.rightBoundary()&&this.bottomBoundary()<=e.bottomBoundary()&&this.leftBoundary()>=e.leftBoundary()}getType(){return this.entity.getType()}getNodeName(){return this.entity.getObjectName()}getNodeDisplayName(){return this.entity.nodeDisplayName()}setNodeWidth(e){this.entity.setNodeWidth(e),this.sizeX=e,this.acknowledgeReflow()}setNodeHeight(e){this.entity.setNodeHeight(e),this.sizeY=e,this.acknowledgeReflow()}sanitizeLinks(e=[]){this.getPinElements().forEach((t=>t.sanitizeLinks(e)))}rename(e){if(this.entity.Name==e)return!1;for(let t of this.getPinElements())for(let i of t.getLinks())this.blueprint.getPin(i).redirectLink(t,new Ye({objectName:e,pinGuid:t.entity.PinId}));this.entity.Name=e,this.nodeTitle=this.entity.Name}getPinElements(){return this.#Ze}getPinEntities(){return this.entity.getPinEntities()}setLocation(e=0,t=0,i=!0){this.entity.setNodePosX(e),this.entity.setNodePosY(t),super.setLocation(e,t,i)}acknowledgeReflow(){this.requestUpdate(),this.updateComplete.then((()=>this.computeSizes()));let e=new CustomEvent(ne.nodeReflowEventName);this.dispatchEvent(e)}setShowAdvancedPinDisplay(e){this.entity.AdvancedPinDisplay=new $e(e?"Shown":"Hidden"),this.advancedPinDisplay=this.entity.AdvancedPinDisplay}toggleShowAdvancedPinDisplay(){this.setShowAdvancedPinDisplay("Shown"!=this.entity.AdvancedPinDisplay?.toString())}}class ri extends wt{static properties={selecting:{type:Boolean,attribute:"data-selecting",reflect:!0,converter:Ae.booleanConverter},scrolling:{type:Boolean,attribute:"data-scrolling",reflect:!0,converter:Ae.booleanConverter},focused:{type:Boolean,attribute:"data-focused",reflect:!0,converter:Ae.booleanConverter},zoom:{type:Number,attribute:"data-zoom",reflect:!0},scrollX:{type:Number,attribute:!1},scrollY:{type:Number,attribute:!1},additionalX:{type:Number,attribute:!1},additionalY:{type:Number,attribute:!1},translateX:{type:Number,attribute:!1},translateY:{type:Number,attribute:!1}};static nodeBoundariesSupplier=e=>({primaryInf:e.leftBoundary(!0),primarySup:e.rightBoundary(!0),secondaryInf:e.topBoundary(!0),secondarySup:e.bottomBoundary(!0)});static nodeSelectToggleFunction=(e,t)=>{e.setSelected(t)};#Je=new Map;#et=0;#tt=0;nodes=[];links=[];nodesNames=new Map;mousePosition=[0,0];waitingExpandUpdate=!1;constructor(){super(),this.selecting=!1,this.scrolling=!1,this.focused=!1,this.zoom=0,this.scrollX=ne.expandGridSize,this.scrollY=ne.expandGridSize,this.translateX=ne.expandGridSize,this.translateY=ne.expandGridSize,super.initialize({},new Lt)}initialize(){}getGridDOMElement(){return this.template.gridElement}getScroll(){return[this.scrollX,this.scrollY]}setScroll(e,t){this.scrollX=e,this.scrollY=t}scrollDelta(e=0,t=0,i=!1,s=ne.smoothScrollTime){if(i){let i=[0,0];this.#et&&cancelAnimationFrame(this.#et),this.#tt&&cancelAnimationFrame(this.#tt),Ae.animate(0,e,s,(e=>{this.scrollDelta(e-i[0],0,!1),i[0]=e}),(e=>this.#et=e)),Ae.animate(0,t,s,(e=>{this.scrollDelta(0,e-i[1],!1),i[1]=e}),(e=>this.#tt=e))}else{const i=[2*ne.expandGridSize,2*ne.expandGridSize];let s=this.getScroll(),r=[s[0]+e,s[1]+t],n=[0,0];for(let e=0;e<2;++e)r[e]i[e]-ne.gridExpandThreshold*ne.expandGridSize&&(n[e]=1);0==n[0]&&0==n[1]||this.seamlessExpand(n[0],n[1]),s=this.getScroll(),r=[s[0]+e,s[1]+t],this.setScroll(r[0],r[1])}}scrollCenter(e=!1){const t=this.getScroll(),i=[this.translateX-t[0],this.translateY-t[1]],s=this.getViewportSize().map((e=>e/2)),r=[i[0]-s[0],i[1]-s[1]];this.scrollDelta(r[0],r[1],e)}getViewportSize(){return[this.template.viewportElement.clientWidth,this.template.viewportElement.clientHeight]}getScrollMax(){return[this.template.viewportElement.scrollWidth-this.template.viewportElement.clientWidth,this.template.viewportElement.scrollHeight-this.template.viewportElement.clientHeight]}snapToGrid(e,t){return Ae.snapToGrid(e,t,ne.gridSize)}seamlessExpand(e,t){e=Math.round(e),t=Math.round(t);let i=this.getScale();[e,t]=[-e*ne.expandGridSize,-t*ne.expandGridSize],0!=e&&(this.scrollX+=e,e/=i),0!=t&&(this.scrollY+=t,t/=i),this.translateX+=e,this.translateY+=t}progressiveSnapToGrid(e){return ne.expandGridSize*Math.round(e/ne.expandGridSize+.5*Math.sign(e))}getZoom(){return this.zoom}setZoom(e,t){if((e=Ae.clamp(e,ne.minZoom,ne.maxZoom))==this.zoom)return;let i=this.getScale();if(this.zoom=e,t){t[0]+=this.translateX,t[1]+=this.translateY;let e=this.getScale()/i,s=[e*t[0],e*t[1]];this.scrollDelta((s[0]-t[0])*i,(s[1]-t[1])*i)}}getScale(){return ne.scale[this.getZoom()]}scaleCorrect(e){return e/this.getScale()}scaleCorrectReverse(e){return e*this.getScale()}compensateTranslation(e,t){return[e-=this.translateX,t-=this.translateY]}getNodes(e=!1,[t,i,s,r]=[Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER]){let n=this.nodes;return e&&(n=n.filter((e=>e.selected))),(t>Number.MIN_SAFE_INTEGER||iNumber.MIN_SAFE_INTEGER)&&(n=n.filter((e=>e.topBoundary()>=t&&e.rightBoundary()<=i&&e.bottomBoundary()<=s&&e.leftBoundary()>=r))),n}getCommentNodes(e=!1){let t=[...this.template.getCommentNodes(e)];return 0===t.length&&(t=this.nodes.filter((t=>t.getType()===ne.paths.comment&&(!e||t.selected)))),t}getPin(e){let t=this.template.getPin(e);return t&&t.nodeElement.getNodeName()==e.objectName.toString()||(t=[...this.nodes.find((t=>e.objectName.toString()==t.getNodeName()))?.getPinElements()??[]].find((t=>e.pinGuid.toString()==t.getPinId().toString()))),t}getLinks(e=null,t=null){if(null==e!=(null==t)){const i=e??t;return this.links.filter((e=>e.source==i||e.destination==i))}return null!=e&&null!=t?this.links.filter((i=>i.source==e&&i.destination==t||i.source==t&&i.destination==e)):this.links}getLink(e,t,i=!1){return this.links.find((s=>s.source==e&&s.destination==t||!i&&s.source==t&&s.destination==e))}selectAll(){this.getNodes().forEach((e=>ri.nodeSelectToggleFunction(e,!0)))}unselectAll(){this.getNodes().forEach((e=>ri.nodeSelectToggleFunction(e,!1)))}addGraphElement(...e){const t=e=>{const i=e.currentTarget;i.removeEventListener(ne.removeEventName,t);const s=i instanceof si?this.nodes:i instanceof Gt?this.links:null,r=s?.indexOf(i);if(r>=0){const e=s.pop();rt.entity.getObjectName()==e));if(s){let e=s.entity.getObjectName(!0);this.#Je[e]=this.#Je[e]??-1;do{++this.#Je[e]}while(this.nodes.find((t=>t.entity.getObjectName()==ne.nodeTitle(e,this.#Je[e]))));s.rename(ne.nodeTitle(e,this.#Je[e]))}this.nodes.push(i),i.addEventListener(ne.removeEventName,t),this.template.nodesContainerElement?.appendChild(i)}else i instanceof Gt&&!this.links.includes(i)&&(this.links.push(i),i.addEventListener(ne.removeEventName,t),this.template.linksContainerElement&&!this.template.linksContainerElement.contains(i)&&this.template.linksContainerElement.appendChild(i));e.filter((e=>e instanceof si)).forEach((t=>t.sanitizeLinks(e))),e.filter((e=>e instanceof si&&e.getType()==ne.paths.comment)).forEach((e=>e.updateComplete.then((()=>e.template.manageNodesBind()))))}removeGraphElement(...e){for(let t of e){if(t.closest("ueb-blueprint")!==this)return;t.remove()}}setFocused(e=!0){if(this.focused==e)return;let t=new CustomEvent(e?ne.focusEventName.begin:ne.focusEventName.end);this.focused=e,this.focused||this.unselectAll(),this.dispatchEvent(t)}acknowledgeEditText(e){const t=new CustomEvent(e?ne.editTextEventName.begin:ne.editTextEventName.end);this.dispatchEvent(t)}}customElements.define("ueb-blueprint",ri);class ni extends Vt{#it;get locationChangeCallback(){return this.#it}set locationChangeCallback(e){this.#it=e}movementSpace;movementSpaceSize=[0,0];firstUpdated(e){super.firstUpdated(e),this.movementSpace=this.element.parentElement}setup(){super.setup();const e=this.movementSpace.getBoundingClientRect();this.movementSpaceSize=[e.width,e.height]}createDraggableObject(){return new Dt(this.element,this.blueprint,{draggableElement:this.movementSpace,ignoreTranslateCompensate:!0,moveEverywhere:!0,movementSpace:this.movementSpace,repositionOnClick:!0,stepSize:1})}adjustLocation(e,t){return this.locationChangeCallback?.(e,t),[e,t]}}class ai extends ni{adjustLocation(e,t){const i=Math.round(this.movementSpaceSize[0]/2);e-=i,t=-(t-i);let[s,r]=Ae.getPolarCoordinates(e,t);return s=Math.min(s,i),[e,t]=Ae.getCartesianCoordinates(s,r),this.locationChangeCallback?.(e/i,t/i),[e=Math.round(e+i),t=Math.round(-t+i)]}}class oi extends St{windowElement;setup(){super.setup(),this.windowElement=this.closest("ueb-window")}setLocation(e,t){super.setLocation(...this.template.adjustLocation(e,t))}}class li extends oi{constructor(){super(),super.initialize({},new ai)}static newObject(){return new li}initialize(){}}class ui extends ni{adjustLocation(e,t){return e=Ae.clamp(e,0,this.movementSpaceSize[0]),t=Ae.clamp(t,0,this.movementSpaceSize[1]),this.locationChangeCallback?.(e/this.movementSpaceSize[0],1-t/this.movementSpaceSize[1]),[e,t]}}class ci extends oi{constructor(){super(),super.initialize({},new ui)}static newObject(){return new ci}initialize(){}}class hi extends Et{constructor(e,t,i={}){i.consumeEvent=!0,super(e,t,i)}}class pi extends pt{#st;#rt;#nt=e=>this.element.selectedOption=e.target.selectedOptions[0].value;render(){return D` `}firstUpdated(e){super.firstUpdated(e),this.#st=this.element.querySelector("select:first-child"),this.#rt=this.element.querySelector("select:last-child");const t=new Event("input",{bubbles:!0});this.#st.dispatchEvent(t)}updated(e){super.updated(e);const t=this.#rt.getBoundingClientRect();this.element.style.setProperty("--ueb-dropdown-width",t.width+"px")}createInputObjects(){return[...super.createInputObjects(),new hi(this.element,this.blueprint)]}setSelectedValue(e){this.element.querySelector(`option[value="${e}"]`).defaultSelected=!0}getSelectedValue(){return this.#st.value}}class di extends wt{static properties={...super.properties,options:{type:Object},selectedOption:{type:String}};constructor(){super(),super.initialize({},new pi),this.options=[],this.selectedOption=""}static newObject(e){return new di}initialize(){}getValue(){return this.template.getSelectedValue()}}class mi extends pt{#at=()=>{this.blueprint.acknowledgeEditText(!0),this.element.selectOnFocus&&getSelection().selectAllChildren(this.element)};#ot=()=>{this.blueprint.acknowledgeEditText(!1),getSelection().removeAllRanges()};#lt=e=>e.target.querySelectorAll("br").forEach((e=>e.remove()));#ut=e=>{"Enter"!=e.code||e.shiftKey||e.target.blur()};initialize(e){super.initialize(e),this.element.classList.add("ueb-pin-input-content"),this.element.setAttribute("role","textbox"),this.element.contentEditable="true"}firstUpdated(e){super.firstUpdated(e);const t=new Event("input",{bubbles:!0});this.element.dispatchEvent(t)}createInputObjects(){return[...super.createInputObjects(),new hi(this.element,this.blueprint)]}setup(){super.setup(),this.element.addEventListener("focus",this.#at),this.element.addEventListener("focusout",this.#ot),this.element.singleLine&&this.element.addEventListener("input",this.#lt),this.element.blurOnEnter&&this.element.addEventListener("keydown",this.#ut)}cleanup(){super.cleanup(),this.element.removeEventListener("focus",this.#at),this.element.removeEventListener("focusout",this.#ot),this.element.removeEventListener("input",this.#lt),this.element.removeEventListener("keydown",this.#ut)}}class gi extends wt{static properties={...super.properties,singleLine:{type:Boolean,attribute:"data-single-line",converter:Ae.booleanConverter,reflect:!0},selectOnFocus:{type:Boolean,attribute:"data-select-focus",converter:Ae.booleanConverter,reflect:!0},blurOnEnter:{type:Boolean,attribute:"data-blur-enter",converter:Ae.booleanConverter,reflect:!0}};constructor(){super(),this.singleLine=!1,this.selectOnFocus=!0,this.blurOnEnter=!0,super.initialize({},new mi)}static newObject(){return new gi}initialize(){}}class bi extends Xt{#ct;#ht=()=>this.element.setDefaultValue(this.#ct.checked);firstUpdated(e){super.firstUpdated(e),this.#ct=this.element.querySelector(".ueb-pin-input")}setup(){super.setup(),this.#ct?.addEventListener("change",this.#ht)}cleanup(){super.cleanup(),this.#ct?.removeEventListener("change",this.#ht)}createInputObjects(){return[...super.createInputObjects(),new hi(this.#ct,this.blueprint)]}renderInput(){return D``}}class vi extends Xt{static singleLineInput=!1;static selectOnFocus=!0;static saveEachInputChange=!1;#pt;get inputWrapper(){return this.#pt}#dt;static stringFromInputToUE(e){return e.replace(/(?=\n\s*)\n$/,"")}static stringFromUEToInput(e){return e.replaceAll(/(?:\r|(?<=(?:^|[^\\])(?:\\\\)*)\\r)(?=\n)/g,"").replace(/(?<=\n\s*)$/,"\n")}#mt=()=>this.setInputs(this.getInputs(),!0);#gt=e=>this.#bt(e.target);#bt(e){const t=this.blueprint.scaleCorrect(this.#pt.getBoundingClientRect().width)+this.nameWidth,i=this.element.classList.contains("ueb-pin-input-wrap");!i&&t>ne.pinInputWrapWidth?this.element.classList.add("ueb-pin-input-wrap"):i&&t<=ne.pinInputWrapWidth&&this.element.classList.remove("ueb-pin-input-wrap")}firstUpdated(e){super.firstUpdated(e);this.constructor.canWrapInput&&this.isInputRendered()&&(this.element.addEventListener("input",this.#gt),this.nameWidth=this.blueprint.scaleCorrect(this.element.querySelector(".ueb-pin-name")?.getBoundingClientRect().width??0)),this.#pt=this.element.querySelector(".ueb-pin-input-wrapper"),this.#dt=[...this.element.querySelectorAll("ueb-input")]}setup(){super.setup();const e=this.constructor;e.saveEachInputChange?this.element.addEventListener("input",this.#mt):this.element.addEventListener("focusout",this.#mt),e.canWrapInput&&this.isInputRendered()&&(this.element.addEventListener("input",this.#gt),this.element.nodeElement.addEventListener(ne.nodeReflowEventName,this.#gt))}cleanup(){super.cleanup(),this.element.nodeElement.removeEventListener(ne.nodeReflowEventName,this.#gt),this.element.removeEventListener("input",this.#gt),this.element.removeEventListener("input",this.#mt),this.element.removeEventListener("focusout",this.#mt)}getInput(){return this.getInputs().reduce(((e,t)=>e+t),"")}getInputs(){return this.#dt.map((e=>Ae.clearHTMLWhitespace(e.innerHTML)))}setInputs(e=[],t=!0){this.#dt.forEach(this.constructor.singleLineInput?(t,i)=>t.innerText=e[i]:(t,i)=>t.innerText=e[i].replaceAll("\n","")),t&&this.setDefaultValue(e.map((e=>vi.stringFromInputToUE(e))),e),this.element.requestUpdate(),this.element.nodeElement.acknowledgeReflow()}setDefaultValue(e=[],t=e){this.element.setDefaultValue(e.join(""))}renderInput(){const e=this.constructor,t=e.singleLineInput,i=e.selectOnFocus;return D`
`}}class yi extends vi{static saveEachInputChange=!0;#vt;#yt=[];setup(){super.setup();const e=this.element.nodeElement.entity.EnumEntries;this.#yt=e?.map((e=>(""===e&&(e="None"),[e,this.element.nodeElement.getPinEntities().find((t=>e===t.PinName))?.PinFriendlyName.toString()??e])))??ne.CommonEnums[this.element.entity.getSubCategory()]?.map((e=>e instanceof Array?e:[e,Ae.formatStringName(e)]))??[];const t=this.element.getDefaultValue().toString();this.#yt.find((([e,i])=>e===t))||this.#yt.push([t,Ae.formatStringName(t)]),this.element.requestUpdate()}renderInput(){return this.element.nodeElement.entity,D``}firstUpdated(e){super.firstUpdated(e),this.#vt=this.element.querySelector("ueb-dropdown")}getInputs(){return[this.#vt.getValue()]}}class fi extends Xt{renderIcon(){return rt.execPin}renderName(){let e=this.element.entity.PinName;if(this.element.entity.PinFriendlyName)e=this.element.entity.PinFriendlyName.toString();else if("execute"===e||"then"===e)return D``;return D`${this.element.getPinDisplayName()}`}}class wi extends vi{static singleLineInput=!0;setInputs(e=[],t=!1){if(e&&0!=e.length||(e=[this.getInput()]),super.setInputs(e,!1),t){let i=[];for(const s of e){let e=parseFloat(s);isNaN(e)&&(e=0,t=!1),i.push(e)}this.setDefaultValue(i,e)}}setDefaultValue(e=[],t){this.element.setDefaultValue(e[0])}}class Si extends wi{setDefaultValue(e=[],t=e){this.element.getDefaultValue(!0).value=e[0],this.element.requestUpdate()}renderInput(){return D`
`}}class Ei extends Si{setInputs(e=[],t=!1){if(e&&0!=e.length||(e=[this.getInput()]),super.setInputs(e,!1),t){if(!e[0].match(/[\-\+]?[0-9]+/))return;const t=[BigInt(e[0])];this.setDefaultValue(t,e)}}} +var te,ie;class se extends b{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){var e,t;const i=super.createRenderRoot();return null!==(e=(t=this.renderOptions).renderBefore)&&void 0!==e||(t.renderBefore=i.firstChild),i}update(e){const t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=((e,t,i)=>{var s,r;const n=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:t;let a=n._$litPart$;if(void 0===a){const e=null!==(r=null==i?void 0:i.renderBefore)&&void 0!==r?r:null;n._$litPart$=a=new K(t.insertBefore(N(),e),e,void 0,null!=i?i:{})}return a._$AI(e),a})(t,this.renderRoot,this.renderOptions)}connectedCallback(){var e;super.connectedCallback(),null===(e=this._$Do)||void 0===e||e.setConnected(!0)}disconnectedCallback(){var e;super.disconnectedCallback(),null===(e=this._$Do)||void 0===e||e.setConnected(!1)}render(){return D}}se.finalized=!0,se._$litElement$=!0,null===(te=globalThis.litElementHydrateSupport)||void 0===te||te.call(globalThis,{LitElement:se});const re=globalThis.litElementPolyfillSupport;null==re||re({LitElement:se}),(null!==(ie=globalThis.litElementVersions)&&void 0!==ie?ie:globalThis.litElementVersions=[]).push("3.3.3");class ne{static nodeColors={black:n``,blue:n``,darkBlue:n``,darkTurquoise:n``,gray:n``,green:n``,lime:n``,red:n``,turquoise:n``,violet:n``,yellow:n``};static alphaPattern="repeating-conic-gradient(#7c8184 0% 25%, #c2c3c4 0% 50%) 50% / 10px 10px";static colorDragEventName="ueb-color-drag";static colorPickEventName="ueb-color-pick";static colorWindowEventName="ueb-color-window";static colorWindowName="Color Picker";static defaultCommentHeight=96;static defaultCommentWidth=400;static distanceThreshold=5;static dragEventName="ueb-drag";static dragGeneralEventName="ueb-drag-general";static edgeScrollThreshold=50;static editTextEventName={begin:"ueb-edit-text-begin",end:"ueb-edit-text-end"};static expandGridSize=400;static focusEventName={begin:"blueprint-focus",end:"blueprint-unfocus"};static fontSize=n``;static gridAxisLineColor=n``;static gridExpandThreshold=.25;static gridLineColor=n``;static gridLineWidth=1;static gridSet=8;static gridSetLineColor=n``;static gridShrinkThreshold=4;static gridSize=16;static hexColorRegex=/^\s*#(?[0-9a-fA-F]{2})(?[0-9a-fA-F]{2})(?[0-9a-fA-F]{2})([0-9a-fA-F]{2})?|#(?[0-9a-fA-F])(?[0-9a-fA-F])(?[0-9a-fA-F])\s*$/;static indentation=" ";static keysSeparator=/[\.\(\)]/;static knotOffset=[-ne.gridSize,-.5*ne.gridSize];static lineTracePattern=/LineTrace(Single|Multi)(\w*)/;static linkCurveHeight=15;static linkCurveWidth=80;static linkMinWidth=100;static nameRegexSpaceReplacement=new RegExp("^K2(?:[Nn]ode)?_|(?<=[a-z])(?=[A-Z0-9])|(?<=[A-Z])(?{let s=100-e;return`M ${e} 0 C ${t.toFixed(3)} 0, ${i.toFixed(3)} 0, 50 50 S ${(s-t+e).toFixed(3)} 100, ${s.toFixed(3)} 100`};static maxZoom=7;static minZoom=-12;static mouseClickButton=0;static mouseRightClickButton=2;static mouseWheelZoomThreshold=80;static nodeDragEventName="ueb-node-drag";static nodeDragGeneralEventName="ueb-node-drag-general";static nodeTitle=(e,t)=>`${e}_${t}`;static nodeRadius=8;static nodeReflowEventName="ueb-node-reflow";static paths={actorBoundEvent:"/Script/BlueprintGraph.K2Node_ActorBoundEvent",addDelegate:"/Script/BlueprintGraph.K2Node_AddDelegate",ambientSound:"/Script/Engine.AmbientSound",asyncAction:"/Script/BlueprintGraph.K2Node_AsyncAction",blueprint:"/Script/Engine.Blueprint",blueprintGameplayTagLibrary:"/Script/GameplayTags.BlueprintGameplayTagLibrary",blueprintMapLibrary:"/Script/Engine.BlueprintMapLibrary",blueprintSetLibrary:"/Script/Engine.BlueprintSetLibrary",callArrayFunction:"/Script/BlueprintGraph.K2Node_CallArrayFunction",callDelegate:"/Script/BlueprintGraph.K2Node_CallDelegate",callFunction:"/Script/BlueprintGraph.K2Node_CallFunction",comment:"/Script/UnrealEd.EdGraphNode_Comment",commutativeAssociativeBinaryOperator:"/Script/BlueprintGraph.K2Node_CommutativeAssociativeBinaryOperator",componentBoundEvent:"/Script/BlueprintGraph.K2Node_ComponentBoundEvent",createDelegate:"/Script/BlueprintGraph.K2Node_CreateDelegate",customEvent:"/Script/BlueprintGraph.K2Node_CustomEvent",doN:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:Do N",doOnce:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:DoOnce",dynamicCast:"/Script/BlueprintGraph.K2Node_DynamicCast",eAttachmentRule:"/Script/Engine.EAttachmentRule",edGraph:"/Script/Engine.EdGraph",edGraphPinDeprecated:"/Script/Engine.EdGraphPin_Deprecated",eDrawDebugTrace:"/Script/Engine.EDrawDebugTrace",eMaterialSamplerType:"/Script/Engine.EMaterialSamplerType",enum:"/Script/CoreUObject.Enum",enumLiteral:"/Script/BlueprintGraph.K2Node_EnumLiteral",eSamplerSourceMode:"/Script/Engine.ESamplerSourceMode",eSearchCase:"/Script/CoreUObject.ESearchCase",eSearchDir:"/Script/CoreUObject.ESearchDir",eSpawnActorCollisionHandlingMethod:"/Script/Engine.ESpawnActorCollisionHandlingMethod",eTextureMipValueMode:"/Script/Engine.ETextureMipValueMode",eTraceTypeQuery:"/Script/Engine.ETraceTypeQuery",event:"/Script/BlueprintGraph.K2Node_Event",executionSequence:"/Script/BlueprintGraph.K2Node_ExecutionSequence",flipflop:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:FlipFlop",forEachElementInEnum:"/Script/BlueprintGraph.K2Node_ForEachElementInEnum",forEachLoop:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:ForEachLoop",forEachLoopWithBreak:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:ForEachLoopWithBreak",forLoop:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:ForLoop",forLoopWithBreak:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:ForLoopWithBreak",functionEntry:"/Script/BlueprintGraph.K2Node_FunctionEntry",functionResult:"/Script/BlueprintGraph.K2Node_FunctionResult",gameplayTag:"/Script/GameplayTags.GameplayTag",getInputAxisKeyValue:"/Script/BlueprintGraph.K2Node_GetInputAxisKeyValue",ifThenElse:"/Script/BlueprintGraph.K2Node_IfThenElse",inputAxisKeyEvent:"/Script/BlueprintGraph.K2Node_InputAxisKeyEvent",inputDebugKey:"/Script/InputBlueprintNodes.K2Node_InputDebugKey",inputKey:"/Script/BlueprintGraph.K2Node_InputKey",inputVectorAxisEvent:"/Script/BlueprintGraph.K2Node_InputVectorAxisEvent",isValid:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:IsValid",kismetArrayLibrary:"/Script/Engine.KismetArrayLibrary",kismetMathLibrary:"/Script/Engine.KismetMathLibrary",knot:"/Script/BlueprintGraph.K2Node_Knot",linearColor:"/Script/CoreUObject.LinearColor",literal:"/Script/BlueprintGraph.K2Node_Literal",macro:"/Script/BlueprintGraph.K2Node_MacroInstance",makeArray:"/Script/BlueprintGraph.K2Node_MakeArray",makeMap:"/Script/BlueprintGraph.K2Node_MakeMap",makeSet:"/Script/BlueprintGraph.K2Node_MakeSet",makeStruct:"/Script/BlueprintGraph.K2Node_MakeStruct",materialExpressionComponentMask:"/Script/Engine.MaterialExpressionComponentMask",materialExpressionConstant:"/Script/Engine.MaterialExpressionConstant",materialExpressionConstant2Vector:"/Script/Engine.MaterialExpressionConstant2Vector",materialExpressionConstant3Vector:"/Script/Engine.MaterialExpressionConstant3Vector",materialExpressionConstant4Vector:"/Script/Engine.MaterialExpressionConstant4Vector",materialExpressionFunctionInput:"/Script/Engine.MaterialExpressionFunctionInput",materialExpressionLogarithm:"/Script/InterchangeImport.MaterialExpressionLogarithm",materialExpressionLogarithm10:"/Script/Engine.MaterialExpressionLogarithm10",materialExpressionLogarithm2:"/Script/Engine.MaterialExpressionLogarithm2",materialExpressionMaterialFunctionCall:"/Script/Engine.MaterialExpressionMaterialFunctionCall",materialExpressionSquareRoot:"/Script/Engine.MaterialExpressionSquareRoot",materialExpressionTextureCoordinate:"/Script/Engine.MaterialExpressionTextureCoordinate",materialExpressionTextureSample:"/Script/Engine.MaterialExpressionTextureSample",materialGraphNode:"/Script/UnrealEd.MaterialGraphNode",materialGraphNodeComment:"/Script/UnrealEd.MaterialGraphNode_Comment",multiGate:"/Script/BlueprintGraph.K2Node_MultiGate",pawn:"/Script/Engine.Pawn",pcgEditorGraphNode:"/Script/PCGEditor.PCGEditorGraphNode",pcgEditorGraphNodeInput:"/Script/PCGEditor.PCGEditorGraphNodeInput",pcgEditorGraphNodeOutput:"/Script/PCGEditor.PCGEditorGraphNodeOutput",pcgHiGenGridSizeSettings:"/Script/PCG.PCGHiGenGridSizeSettings",pcgSubgraphSettings:"/Script/PCG.PCGSubgraphSettings",promotableOperator:"/Script/BlueprintGraph.K2Node_PromotableOperator",reverseForEachLoop:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:ReverseForEachLoop",rotator:"/Script/CoreUObject.Rotator",select:"/Script/BlueprintGraph.K2Node_Select",slateBlueprintLibrary:"/Script/UMG.SlateBlueprintLibrary",spawnActorFromClass:"/Script/BlueprintGraph.K2Node_SpawnActorFromClass",switchEnum:"/Script/BlueprintGraph.K2Node_SwitchEnum",switchGameplayTag:"/Script/GameplayTagsEditor.GameplayTagsK2Node_SwitchGameplayTag",switchInteger:"/Script/BlueprintGraph.K2Node_SwitchInteger",switchName:"/Script/BlueprintGraph.K2Node_SwitchName",switchString:"/Script/BlueprintGraph.K2Node_SwitchString",timeline:"/Script/BlueprintGraph.K2Node_Timeline",timeManagementBlueprintLibrary:"/Script/TimeManagement.TimeManagementBlueprintLibrary",transform:"/Script/CoreUObject.Transform",userDefinedEnum:"/Script/Engine.UserDefinedEnum",variableGet:"/Script/BlueprintGraph.K2Node_VariableGet",variableSet:"/Script/BlueprintGraph.K2Node_VariableSet",vector:"/Script/CoreUObject.Vector",vector2D:"/Script/CoreUObject.Vector2D",whileLoop:"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:WhileLoop"};static pinColor={[this.paths.rotator]:n``,[this.paths.transform]:n``,[this.paths.vector]:n``,Any:n``,"Any[]":n``,blue:n``,bool:n``,byte:n``,class:n``,default:n``,delegate:n``,enum:n``,exec:n``,green:n``,int:n``,int64:n``,interface:n``,name:n``,object:n``,Param:n``,"Param[]":n``,Point:n``,"Point[]":n``,real:n``,red:n``,string:n``,struct:n``,Surface:n``,"Surface[]":n``,text:n``,Volume:n``,"Volume[]":n``,wildcard:n``};static pinColorMaterial=n``;static pinInputWrapWidth=143;static removeEventName="ueb-element-delete";static scale={[-12]:.133333,[-11]:.166666,[-10]:.2,[-9]:.233333,[-8]:.266666,[-7]:.3,[-6]:.333333,[-5]:.375,[-4]:.5,[-3]:.675,[-2]:.75,[-1]:.875,0:1,1:1.25,2:1.375,3:1.5,4:1.675,5:1.75,6:1.875,7:2};static smoothScrollTime=1e3;static stringEscapedCharacters=/['"\\]/g;static subObjectAttributeNamePrefix="#SubObject";static subObjectAttributeNameFromEntity=(e,t=!1)=>this.subObjectAttributeNamePrefix+(!t&&e.Class?`_${e.Class.type}`:"")+"_"+e.Name;static subObjectAttributeNameFromReference=(e,t=!1)=>this.subObjectAttributeNamePrefix+(t?"":"_"+e.type)+"_"+e.path;static subObjectAttributeNameFromName=e=>this.subObjectAttributeNamePrefix+"_"+e;static switchTargetPattern=/\/Script\/[\w\.\/\:]+K2Node_Switch([A-Z]\w+)+/;static trackingMouseEventName={begin:"ueb-tracking-mouse-begin",end:"ueb-tracking-mouse-end"};static unescapedBackslash=/(?<=(?:[^\\]|^)(?:\\\\)*)\\(?!\\)/;static windowApplyEventName="ueb-window-apply";static windowApplyButtonText="OK";static windowCancelEventName="ueb-window-cancel";static windowCancelButtonText="Cancel";static windowCloseEventName="ueb-window-close";static CommonEnums={[this.paths.eAttachmentRule]:["KeepRelative","KeepWorld","SnapToTarget"],[this.paths.eMaterialSamplerType]:["Color","Grayscale","Alpha","Normal","Masks","Distance Field Font","Linear Color","Linear Grayscale","Data","External","Virtual Color","Virtual Grayscale","Virtual Alpha","Virtual Normal","Virtual Mask","Virtual Linear Color","Virtual Linear Grayscal"],[this.paths.eSamplerSourceMode]:["From texture asset","Shared: Wrap","Shared: Clamp","Hidden"],[this.paths.eSpawnActorCollisionHandlingMethod]:[["Undefined","Default"],["AlwaysSpawn","Always Spawn, Ignore Collisions"],["AdjustIfPossibleButAlwaysSpawn","Try To Adjust Location, But Always Spawn"],["AdjustIfPossibleButDontSpawnIfColliding","Try To Adjust Location, Don't Spawn If Still Colliding"],["DontSpawnIfColliding","Do Not Spawn"]],[this.paths.eSearchCase]:["CaseSensitive","IgnoreCase"],[this.paths.eSearchDir]:["FromStart","FromEnd"],[this.paths.eDrawDebugTrace]:["None","ForOneFrame","ForDuration","Persistent"],[this.paths.eTextureMipValueMode]:["None (use computed mip level)","MipLevel (absolute, 0 is full resolution)","MipBias (relative to the computed mip level)","Derivative (explicit derivative to compute mip level)"],[this.paths.eTraceTypeQuery]:[["TraceTypeQuery1","Visibility"],["TraceTypeQuery2","Camera"]]};static ModifierKeys=["Ctrl","Shift","Alt","Meta"];static rgba=["R","G","B","A"];static Keys={Backspace:"Backspace",Tab:"Tab",LeftControl:"ControlLeft",RightControl:"ControlRight",LeftShift:"ShiftLeft",RightShift:"ShiftRight",LeftAlt:"AltLeft",RightAlt:"AltRight",Enter:"Enter",Pause:"Pause",CapsLock:"CapsLock",Escape:"Escape",Space:"Space",PageUp:"PageUp",PageDown:"PageDown",End:"End",Home:"Home",ArrowLeft:"ArrowLeft",ArrowUp:"ArrowUp",ArrowRight:"ArrowRight",ArrowDown:"ArrowDown",PrintScreen:"PrintScreen",Insert:"Insert",Delete:"Delete",Zero:"Digit0",One:"Digit1",Two:"Digit2",Three:"Digit3",Four:"Digit4",Five:"Digit5",Six:"Digit6",Seven:"Digit7",Eight:"Digit8",Nine:"Digit9",A:"KeyA",B:"KeyB",C:"KeyC",D:"KeyD",E:"KeyE",F:"KeyF",G:"KeyG",H:"KeyH",I:"KeyI",K:"KeyK",L:"KeyL",M:"KeyM",N:"KeyN",O:"KeyO",P:"KeyP",Q:"KeyQ",R:"KeyR",S:"KeyS",T:"KeyT",U:"KeyU",V:"KeyV",W:"KeyW",X:"KeyX",Y:"KeyY",Z:"KeyZ",NumPadZero:"Numpad0",NumPadOne:"Numpad1",NumPadTwo:"Numpad2",NumPadThree:"Numpad3",NumPadFour:"Numpad4",NumPadFive:"Numpad5",NumPadSix:"Numpad6",NumPadSeven:"Numpad7",NumPadEight:"Numpad8",NumPadNine:"Numpad9",Multiply:"NumpadMultiply",Add:"NumpadAdd",Subtract:"NumpadSubtract",Decimal:"NumpadDecimal",Divide:"NumpadDivide",F1:"F1",F2:"F2",F3:"F3",F4:"F4",F5:"F5",F6:"F6",F7:"F7",F8:"F8",F9:"F9",F10:"F10",F11:"F11",F12:"F12",NumLock:"NumLock",ScrollLock:"ScrollLock"}}class ae{static deleteNodes="Delete";static duplicateNodes="(bCtrl=True,Key=D)";static enableLinkDelete="LeftAlt";static enableZoomIn=["LeftControl","RightControl"];static selectAllNodes="(bCtrl=True,Key=A)"}class oe{#e;constructor(e){this.#e=e}compute(e){return this.#e(e)}}class le{static#t={nullable:!1,ignored:!1,serialized:!1,expected:!1,inlined:!1,quoted:!1,silent:!1};constructor(e){this.type=e.type??e.default?.constructor,this.default=e.default,this.nullable=e.nullable??null===e.default,this.ignored=e.ignored,this.serialized=e.serialized,this.expected=e.expected,this.inlined=e.inlined,this.quoted=e.quoted,this.silent=e.silent,this.predicate=e.predicate,this.type===Array&&this.default instanceof Array&&this.default.length>0&&(this.type=this.default.map((e=>e.constructor)).reduce(((e,t)=>(e.includes(t)||e.push(t),e)),[]))}static createType(e){return new le({type:e})}static createValue(e){return new le({default:e})}static hasAttribute(e,t,i,s=e.constructor){const r=e,n=r.attributes[t]?.[i];return n??s?.attributes?.[t]?.[i]??le.#t[i]}static getAttribute(e,t,i,s=e.constructor){let r=e.attributes?.[t]?.[i];return void 0!==r?r:(r=(s?.attributes)?.[t]?.[i],void 0!==r?r:(r=le.#t[i],void 0!==r?r:void 0))}get(e){return this[e]??le.#t[e]}}class ce{static attributes={type:new le({ignored:!0}),getter:new le({ignored:!0})};constructor(e,t=null){this.type=e,this.getter=t}get(){return this.getter()}getTargetType(){const e=this.type;return e instanceof ce?e.getTargetType():e}}class ue{#i;get values(){return this.#i}constructor(...e){this.#i=e}}class he{static booleanConverter={fromAttribute:(e,t)=>{},toAttribute:(e,t)=>!0===e?"true":!1===e?"false":""};static sigmoid(e,t=1.7){return 1/(1+e/(1-e)**-t)}static sigmoidPositive(e,t=3.7,i=1.1){return 1-Math.exp(-((e/i)**t))}static clamp(e,t=-1/0,i=1/0){return Math.min(Math.max(e,t),i)}static getScale(e){const t=e.blueprint?.getScale()??getComputedStyle(e).getPropertyValue("--ueb-scale");return""!=t?parseFloat(t):1}static minDecimals(e,t=1,i=1e-8){const s=e*10**t;return Math.abs(s%1)>i?e.toString():e.toFixed(t)}static numberFromText(e=""){switch(e=e.toLowerCase()){case"zero":return 0;case"one":return 1;case"two":return 2;case"three":return 3;case"four":return 4;case"five":return 5;case"six":return 6;case"seven":return 7;case"eight":return 8;case"nine":return 9}}static roundDecimals(e,t=1){const i=10**t;return Math.round(e*i)/i}static printNumber(e){return e==Number.POSITIVE_INFINITY?"inf":e==Number.NEGATIVE_INFINITY?"-inf":he.minDecimals(e)}static printExponential(e){if(e==Number.POSITIVE_INFINITY)return"inf";if(e==Number.NEGATIVE_INFINITY)return"-inf";const t=Math.round(e);if(t>=1e3){const i=Math.floor(Math.log10(t));return`${Math.round(e/10**(i-2))/100}e+${i<10?"0":""}${i}`}return 0==Math.floor(e)?e.toString():this.roundDecimals(e,Math.max(0,3-Math.floor(e).toString().length)).toString()}static approximatelyEqual(e,t,i=1e-8){return!(Math.abs(e-t)>i)}static convertLocation(e,t,i=!1){const s=i?1:1/he.getScale(t),r=t.getBoundingClientRect();return[Math.round((e[0]-r.x)*s),Math.round((e[1]-r.y)*s)]}static isSerialized(e,t){return e.attributes?.[t]?.serialized??e.constructor.attributes?.[t]?.serialized??!1}static objectGet(e,t,i=void 0){if(void 0!==e){if(!(t instanceof Array))throw new TypeError("UEBlueprint: Expected keys to be an array");return 0!=t.length&&t[0]in e&&void 0!==e[t[0]]?1==t.length?e[t[0]]:he.objectGet(e[t[0]],t.slice(1),i):i}}static objectSet(e,t,i,s=Object){if(!(t instanceof Array))throw new TypeError("Expected keys to be an array.");if(1==t.length){if(t[0]in e||void 0===e[t[0]])return e[t[0]]=i,!0}else if(t.length>0)return e[t[0]]instanceof Object||(e[t[0]]=new s),he.objectSet(e[t[0]],t.slice(1),i,s);return!1}static equals(e,t){for(;e instanceof ce;)e=e.get();for(;t instanceof ce;)t=t.get();return e?.equals&&t?.equals?e.equals(t):(e=he.sanitize(e),t=he.sanitize(t),e?.constructor===BigInt&&t?.constructor===Number?t=BigInt(t):e?.constructor===Number&&t?.constructor===BigInt&&(e=BigInt(e)),e===t||e instanceof Array&&t instanceof Array&&(e.length===t.length&&e.every(((e,i)=>he.equals(e,t[i])))))}static getType(e){return null===e?null:e?.constructor===Object&&e?.type instanceof Function?e.type:e?.constructor}static isValueOfType(e,t,i=!1){return t instanceof ce&&(t=t.getTargetType()),i&&null===e||e instanceof t||e?.constructor===t}static sanitize(e,t=e?.constructor){if(t instanceof Array&&(t=t[0]),t instanceof oe)return e;if(t instanceof ue){let i=t.values.find((t=>he.isValueOfType(e,t,!1)));i||(i=t.values[0]),t=i}return t instanceof ce?e instanceof ce?e:he.sanitize(e,t.getTargetType()):(t&&!he.isValueOfType(e,t,!0)&&(e=t===BigInt?BigInt(e):new t(e)),(e instanceof Boolean||e instanceof Number||e instanceof String)&&(e=e.valueOf()),e)}static snapToGrid(e,t,i){return 1===i?[e,t]:[i*Math.floor(e/i),i*Math.floor(t/i)]}static mergeArrays(e=[],t=[]){let i=[];e=[...e],t=[...t];e:for(;;){for(let s=0;s|
/g,"\n").replaceAll(/(\)/g,"")}static encodeHTMLWhitespace(e){return e.replaceAll(" "," ")}static capitalFirstLetter(e){return 0===e.length?e:e.charAt(0).toUpperCase()+e.slice(1)}static formatStringName(e=""){return e.replace(/^\s*b(?=[A-Z])/,"").replaceAll(ne.nameRegexSpaceReplacement," ").trim().split(" ").map((e=>he.capitalFirstLetter(e))).join(" ")}static getIdFromReference(e){return e.replace(/(?:.+\.)?([^\.]+)$/,"$1").replaceAll(/(?<=[a-z\d])(?=[A-Z])|(?<=[a-zA-Z])(?=\d)|(?<=[A-Z]{2})(?=[A-Z][a-z])/g,"-").toLowerCase()}static getNameFromPath(e){return e.match(/[^\.\/]+$/)?.[0]??""}static printLinearColor(e){return`${Math.round(255*e.R.valueOf())}, ${Math.round(255*e.G.valueOf())}, ${Math.round(255*e.B.valueOf())}`}static getPolarCoordinates(e,t,i=!1){let s=Math.atan2(t,e);return i&&s<0&&(s=2*Math.PI+s),[Math.sqrt(e*e+t*t),s]}static getCartesianCoordinates(e,t){return[e*Math.cos(t),e*Math.sin(t)]}static range(e=0,t=0,i=(t>=e?1:-1)){return Array.from({length:Math.ceil((t-e)/i)},((t,s)=>e+s*i))}static getFirstWordOrder(e){return new RegExp(/\s*/.source+e.join(/[^\n]+\n\s*/.source)+/\s*/.source)}static paste(e,t){const i=new ClipboardEvent("paste",{bubbles:!0,cancelable:!0,clipboardData:new DataTransfer});i.clipboardData.setData("text",t),e.dispatchEvent(i)}static async copy(e){const t=new ClipboardEvent("copy",{bubbles:!0,cancelable:!0,clipboardData:new DataTransfer});e.dispatchEvent(t)}static animate(e,t,i,s,r=(e=>{}),n=(e=>{const t=e**3.5;return t/(t+(1-e)**3.5)})){let a;const o=l=>{void 0===a&&(a=l);let c=(l-a)/i;he.approximatelyEqual(c,1)||c>1?c=1:r(requestAnimationFrame(o));const u=e+(t-e)*n(c);s(u)};r(requestAnimationFrame(o))}}class pe{#s;get target(){return this.#s}#r;get blueprint(){return this.#r}consumeEvent;options;listenHandler=()=>this.listenEvents();unlistenHandler=()=>this.unlistenEvents();constructor(e,t,i={}){i.consumeEvent??=!1,i.listenOnFocus??=!1,i.unlistenOnTextEdit??=!1,this.#s=e,this.#r=t,this.consumeEvent=i.consumeEvent,this.options=i}setup(){this.options.listenOnFocus&&(this.blueprint.addEventListener(ne.focusEventName.begin,this.listenHandler),this.blueprint.addEventListener(ne.focusEventName.end,this.unlistenHandler)),this.options.unlistenOnTextEdit&&(this.blueprint.addEventListener(ne.editTextEventName.begin,this.unlistenHandler),this.blueprint.addEventListener(ne.editTextEventName.end,this.listenHandler)),this.blueprint.focused&&this.listenEvents()}cleanup(){this.unlistenEvents(),this.blueprint.removeEventListener(ne.focusEventName.begin,this.listenHandler),this.blueprint.removeEventListener(ne.focusEventName.end,this.unlistenHandler),this.blueprint.removeEventListener(ne.editTextEventName.begin,this.unlistenHandler),this.blueprint.removeEventListener(ne.editTextEventName.end,this.listenHandler)}listenEvents(){}unlistenEvents(){}}class de{static makeSuccess(e,t,i=null,s=0){return{status:!0,value:t,position:e,bestParser:i,bestPosition:s}}static makeFailure(e=0,t=null,i=0){return{status:!1,value:null,position:e,bestParser:t,bestPosition:i}}static makeContext(e=null,t=""){return{parsernostrum:e,input:t,highlighted:null}}static makePathNode(e,t=0,i=null){return{parent:i,parser:e,index:t}}}class me{static indentation=" ";static highlight="Last valid parser";Self;static appendBeforeHighlight(e,t){return e.endsWith(me.highlight)?e=e.replace(/(?=(?:\n|^).+$)/,t):e+=t,e}static lastRowLength(e,t=0){const i=e.match(/(?:\n|(^))([^\n]*)$/),s=void 0!==i[1]?t:0;return i[2].length+s}isHighlighted(e,t){if(e.highlighted instanceof me)return e.highlighted===this;if(!e.highlighted||!t)return!1;let i,s,r,n;e:for(i=t,r=e.highlighted;i&&r;s=i,i=i.parent,n=r,r=r.parent)if(i.parser!==r.parser||i.index!==r.index){if(!s||!n)return!1;let e,t;for(e=i,t=r;e||t;e=e?.parent,t=t?.parent){const a=e?.parser===s.parser,o=t?.parser===n.parser;if(a||o){a&&(s=e),o&&(n=t),i=s,r=n;continue e}}return!1}return!0}isVisited(e){if(!e)return!1;for(e=e.parent;null!=e;e=e.parent)if(e.parser===this)return!0;return!1}parse(e,t,i){return null}toString(e=de.makeContext(null,""),t=0,i=null){if(this.isVisited(i))return"<...>";return this.doToString(e,t,i)}doToString(e,t,i){return`${this.constructor.name} does not implement toString()`}}class ge extends me{#n;get value(){return this.#n}constructor(e){super(),this.#n=e}parse(e,t,i){const s=t+this.#n.length,r=e.input.substring(t,s);return this.#n===r?de.makeSuccess(s,this.#n,i,s):de.makeFailure()}doToString(e,t,i){const s=this.value.replaceAll("\n","\\n");let r=this.value.match(/^[a-zA-Z]$/)?s:`"${s.replaceAll('"','\\"')}"`;return this.isHighlighted(e,i)&&(r+="\n"+me.indentation.repeat(t)+"^".repeat(r.length)+" "+me.highlight),r}}class be extends me{static instance=new be;parse(e,t,i){return de.makeSuccess(t,"",i,0)}doToString(e,t,i){return""+(this.isHighlighted(e,i)?`\n${me.indentation.repeat(t)}^^^^^^^^^ ${me.highlight}`:"")}}class ve extends me{static highlightRegexp=new RegExp(String.raw`(?<=[^\S\n]*\| .*\n)^(?=[^\S\n]*\^+ ${me.highlight}(?:\n|$))`,"m");#a;get parsers(){return this.#a}constructor(...e){super(),this.#a=e}parse(e,t,i){const s=de.makeSuccess(0,"");for(let r=0;rs.bestPosition&&(s.bestParser=n.bestParser,s.bestPosition=n.bestPosition),n.status)return s.value=n.value,s.position=n.position,s}return s.status=!1,s.value=null,s}doToString(e,t,i){const s=me.indentation.repeat(t),r=me.indentation.repeat(t+1);if(2===this.#a.length&&this.#a[1]instanceof be){let s=this.#a[0].toString(e,t,{parent:i,parser:this.#a[0],index:0});return this.#a[0]instanceof ge||(s="<"+s+">"),s+="?",s}let n=this.#a.map(((s,r)=>s.toString(e,t+1,{parent:i,parser:s,index:r}))).join("\n"+r+"| ");return e.highlighted&&(n=n.replace(ve.highlightRegexp," ")),"ALT<\n"+(this.isHighlighted(e,i)?`${s}^^^ ${me.highlight}\n`:"")+r+n+"\n"+s+">"}}class ye extends me{#o;get parser(){return this.#o}#l;constructor(e,t){super(),this.#o=e,this.#l=t}parse(e,t,i){const s=this.#o.parse(e,t,{parent:i,parser:this.#o,index:0});if(!s.status)return s;const r=this.#l(s.value,e.input,s.position).getParser().parse(e,s.position);return s.bestPosition>r.bestPosition&&(r.bestParser=s.bestParser,r.bestPosition=s.bestPosition),r}doToString(e,t,i){const s="chained";let r=this.#o.toString(e,t,{parent:i,parser:this.#o,index:0});return this.isHighlighted(e,i)?r+=" => "+s+"\n"+me.indentation.repeat(t)+" ".repeat(r.match(/(?:\n|^)([^\n]+)$/)?.[1].length+4)+"^".repeat(12)+" "+me.highlight:r=me.appendBeforeHighlight(r," => "+s),r}}class fe extends me{static instance=new fe;parse(e,t,i){return de.makeFailure()}doToString(e,t,i){return""+(this.isHighlighted(e,i)?`\n${me.indentation.repeat(t)}^^^^^^^^^ ${me.highlight}`:"")}}class we extends me{#o;#c;constructor(e){super(),this.#o=e}resolve(){return this.#c||(this.#c=this.#o().getParser()),this.#c}parse(e,t,i){return this.resolve(),this.#c.parse(e,t,{parent:i,parser:this.#c,index:0})}doToString(e,t,i){const s={parent:i,parser:this.#c,index:0};return this.isHighlighted(e,i)&&(e.highlighted=e.highlighted instanceof me?this.#c:s),this.resolve().toString(e,t,s)}}class Se extends me{#o;get parser(){return this.#o}#u;get type(){return this.#u}static Type={NEGATIVE_AHEAD:"?!",NEGATIVE_BEHIND:"?String.raw`[^${e}\\]*(?:\\.[^${e}\\]*)*`;static#g=/[-\+]?(?:\d*\.)?\d+/;static common={number:new RegExp(this.#g.source+String.raw`(?!\.)`),numberInteger:/[\-\+]?\d+(?!\.\d)/,numberNatural:/\d+/,numberExponential:new RegExp(this.#g.source+String.raw`(?:[eE][\+\-]?\d+)?(?!\.)`),numberUnit:/\+?(?:0(?:\.\d+)?|1(?:\.0+)?)(?![\.\d])/,numberByte:/0*(?:25[0-5]|2[0-4]\d|1?\d?\d)(?!\d|\.)/,whitespace:/\s+/,whitespaceOpt:/\s*/,whitespaceInline:/[^\S\n]+/,whitespaceInlineOpt:/[^\S\n]*/,whitespaceMultiline:/\s*?\n\s*/,doubleQuotedString:new RegExp(`"(${this.#m('"')})"`),singleQuotedString:new RegExp(`'(${this.#m("'")})'`),backtickQuotedString:new RegExp("`("+this.#m("`")+")`")};constructor(e,t){super(),this.#h=e,this.#p=new RegExp(`^(?:${e.source})`,e.flags),this.#d=t}parse(e,t,i){const s=this.#p.exec(e.input.substring(t));s&&(t+=s[0].length);return s?de.makeSuccess(t,this.#d(s),i,t):de.makeFailure()}doToString(e,t,i){let s="/"+this.#h.source+"/";const r=Object.entries(Ee.common).find((([e,t])=>t.source===this.#h.source))?.[0];return r&&(s="P."+r),this.isHighlighted(e,i)&&(s+="\n"+me.indentation.repeat(t)+"^".repeat(s.length)+" "+me.highlight),s}}class Ce extends me{#o;get parser(){return this.#o}#b;get mapper(){return this.#b}constructor(e,t){super(),this.#o=e,this.#b=t}parse(e,t,i){const s=this.#o.parse(e,t,{parent:i,parser:this.#o,index:0});return s.status&&(s.value=this.#b(s.value)),s}doToString(e,t,i){const s={parent:i,parser:this.#o,index:0};this.isHighlighted(e,i)&&(e.highlighted=e.highlighted instanceof me?this.#o:s);let r=this.#o.toString(e,t,s);if(this.#o instanceof Ee&&Object.values(Ee.common).includes(this.#o.regexp))return this.#o.regexp===Ee.common.numberInteger&&this.#b===BigInt?"P.numberBigInteger":r;let n=this.#b.toString();return(n.length>60||n.includes("\n"))&&(n="(...) => { ... }"),n=` -> map<${n}>`,r=me.appendBeforeHighlight(r,n),r}}class xe extends Ee{static#b=e=>e;constructor(e){super(e,xe.#b)}}class Pe extends Ee{constructor(e,t=0){super(e,(e=>e[t]))}}class Ne extends me{#a;get parsers(){return this.#a}constructor(...e){super(),this.#a=e}parse(e,t,i){const s=new Array(this.#a.length),r=de.makeSuccess(t,s);for(let t=0;tr.bestPosition&&(r.bestParser=s.bestParser,r.bestPosition=s.bestPosition),!s.status){r.status=!1,r.value=null;break}r.value[t]=s.value,r.position=s.position}return r}doToString(e,t,i){const s=me.indentation.repeat(t),r=me.indentation.repeat(t+1);return"SEQ<\n"+(this.isHighlighted(e,i)?`${s}^^^ ${me.highlight}\n`:"")+this.#a.map(((s,n)=>r+s.toString(e,t+1,{parent:i,parser:s,index:n}))).join("\n")+"\n"+s+">"}}class ke extends me{#o;get parser(){return this.#o}#v;get min(){return this.#v}#y;get max(){return this.#y}constructor(e,t=0,i=Number.POSITIVE_INFINITY){if(super(),t>i)throw new Error("Min is greater than max");this.#o=e,this.#v=t,this.#y=i}parse(e,t,i){const s=de.makeSuccess(t,[],i);for(let t=0;ts.bestPosition&&(s.bestParser=r.bestParser,s.bestPosition=r.bestPosition),!r.status){te;static#w=([e,t])=>t;static#S=([e,t])=>[e,...t];static#E=e=>e instanceof Array?e.join(""):e;static#m=e=>String.raw`[^${e}\\]*(?:\\.[^${e}\\]*)*`;static number=this.reg(Ee.common.number).map(Number);static numberInteger=this.reg(Ee.common.numberInteger).map(Number);static numberBigInteger=this.reg(this.numberInteger.getParser().parser.regexp).map(BigInt);static numberNatural=this.reg(Ee.common.numberNatural).map(Number);static numberExponential=this.reg(Ee.common.numberExponential).map(Number);static numberUnit=this.reg(Ee.common.numberUnit).map(Number);static numberByte=this.reg(Ee.common.numberByte).map(Number);static whitespace=this.reg(Ee.common.whitespace);static whitespaceOpt=this.reg(Ee.common.whitespaceOpt);static whitespaceInline=this.reg(Ee.common.whitespaceInline);static whitespaceInlineOpt=this.reg(Ee.common.whitespaceInlineOpt);static whitespaceMultiline=this.reg(Ee.common.whitespaceMultiline);static doubleQuotedString=this.reg(Ee.common.doubleQuotedString,1);static singleQuotedString=this.reg(Ee.common.singleQuotedString,1);static backtickQuotedString=this.reg(Ee.common.backtickQuotedString,1);constructor(e,t=!1){this.#o=e}getParser(){return this.#o}run(e){const t=this.#o.parse(de.makeContext(this,e),0,de.makePathNode(this.#o));return t.position!==e.length&&(t.status=!1),t}parse(e){const t=this.run(e);if(!t.status){const i=60,s=[Math.ceil(i/2),Math.floor(i/2)],r=Te.lineColumnFromOffset(e,t.bestPosition);let n=t.bestPosition;const a=e.replaceAll(/^(\s)+|\s{6,}|\s*?\n\s*/g,((e,i,s)=>{let r=i?"...":" ... ";return s<=t.bestPosition&&(t.bestPosition0&&(u="..."+u,c+=3),s[1]e.getParser()))));return t}static alt(...e){return new this(new ve(...e.map((e=>e.getParser()))))}static lookahead(e){return new this(new Se(e.getParser(),Se.Type.POSITIVE_AHEAD))}static lazy(e){return new this(new we(e))}times(e,t=e){return new Te(new ke(this.#o,e,t))}many(){return this.times(0,Number.POSITIVE_INFINITY)}atLeast(e){return this.times(e,Number.POSITIVE_INFINITY)}atMost(e){return this.times(0,e)}opt(){return Te.alt(this,Te.success())}sepBy(e,t=!1){return Te.seq(this,Te.seq(e,this).map(Te.#w).many()).map(Te.#S)}skipSpace(){return Te.seq(this,Te.whitespaceOpt).map(Te.#f)}map(e){return new Te(new Ce(this.#o,e))}chain(e){return new Te(new ye(this.#o,e))}assert(e){return this.chain(((t,i,s)=>e(t,i,s)?Te.success().map((()=>t)):Te.failure()))}join(e=""){return this.map(Te.#E)}toString(e=0,t=!1,i=null){i instanceof Te&&(i=i.getParser());const s=de.makeContext(this,"");return s.highlighted=i,(t?"\n"+me.indentation.repeat(e):"")+this.#o.toString(s,e,de.makePathNode(this.#o))}}class Ae{static arrayPin=G``;static branchNode=G``;static breakStruct=G``;static cast=G``;static close=G``;static convert=G``;static correct=G``;static delegate=G``;static doN=G``;static doOnce=G``;static enum=G``;static event=G``;static execPin=G``;static expandIcon=G``;static flipflop=G``;static forEachLoop=G``;static functionSymbol=G``;static gamepad=G``;static genericPin=G``;static keyboard=G``;static loop=G``;static macro=G``;static mapPin=G``;static makeArray=G``;static makeMap=G``;static makeSet=G``;static makeStruct=G``;static mouse=G``;static node=G``;static operationPin=G``;static pcgStackPin=G``;static pcgPin=G``;static pcgParamPin=G``;static pcgSpatialPin=G``;static plusCircle=G``;static questionMark=G``;static referencePin=G``;static reject=G``;static setPin=G``;static select=G``;static sequence=G``;static sound=G``;static spawnActor=G``;static switch=G``;static timer=G``;static touchpad=G``}class Le{static grammar=this.createGrammar();static createGrammar(){return Te.failure()}}class Me{static#C=new Map;static registerSerializer(e,t){Me.#C.set(e,t)}static getSerializer(e){return Me.#C.get(e)}}class Ie extends Le{static attributes={attributes:new le({ignored:!0}),lookbehind:new le({default:"",ignored:!0})};constructor(e={},t=!1){super();const i=this.constructor;this.attributes,this.lookbehind;const s=Object.keys(e),r=e.attributes?he.mergeArrays(Object.keys(e.attributes),Object.keys(i.attributes)):Object.keys(i.attributes),n=he.mergeArrays(s,r);for(const s of n){let r=e[s];if(!(t||s in e||s in i.attributes||s.startsWith(ne.subObjectAttributeNamePrefix))){const e=r instanceof Array?`[${r[0]?.constructor.name}]`:r.constructor.name;console.warn(`UEBlueprint: Attribute ${s} (of type ${e}) in the serialized data is not defined in ${i.name}.attributes`)}if(!(s in i.attributes)){this[s]=r;continue}i.attributes.lookbehind;const n=le.getAttribute(e,s,"predicate",i),a=n?e=>{Object.defineProperties(this,{["#"+s]:{writable:!0,enumerable:!1},[s]:{enumerable:!0,get(){return this["#"+s]},set(e){n(e)?this["#"+s]=e:console.warn(`UEBlueprint: Tried to assign attribute ${s} to ${i.name} not satisfying the predicate`)}}}),this[s]=e}:e=>this[s]=e;let o=le.getAttribute(e,s,"default",i);o instanceof Function&&(o=o(this));let l=le.getAttribute(e,s,"type",i);if(l instanceof oe&&(l=l.compute(this)),l instanceof Array&&(l=Array),void 0===l&&(l=he.getType(o)),void 0===r)void 0!==o&&a(o);else{if(r?.constructor===String&&le.getAttribute(e,s,"serialized",i)&&l!==String)try{r=Me.getSerializer(l).read(r)}catch(e){a(r);continue}a(he.sanitize(r,l))}}}static defaultValueProviderFromType(e){return e!==Boolean&&(e===Number?0:e===BigInt?0n:e===String?"":e===Array||e instanceof Array?()=>[]:e instanceof ue?this.defaultValueProviderFromType(e.values[0]):e instanceof ce?()=>new ce(e.type,e.getter):e instanceof oe?void 0:()=>new e)}static isValueOfType(e,t){return null!=e&&(e instanceof t||e.constructor===t)}static expectsAllKeys(){return!Object.values(this.attributes).filter((e=>!e.ignored)).some((e=>!e.expected))}static getAttribute(e,t){return this.getAttributes(e)[t]}static getAttributes(e){return e.attributes??e.constructor?.attributes??{}}static defineAttributes(e,t){Object.defineProperty(e,"attributes",{writable:!0,configurable:!1}),e.attributes=t}getLookbehind(){let e=this.lookbehind??le.getAttribute(this,"lookbehind","default");return e=e instanceof ue?e.values[0]:e,e}unexpectedKeys(){return Object.keys(this).length-Object.keys(this.constructor.attributes).length}equals(e){const t=Object.keys(this),i=Object.keys(e);if(t.length!=i.length)return!1;for(const i of t){if(this[i]instanceof Ie&&!this[i].equals(e[i]))return!1;if(!he.equals(this[i],e[i]))return!1}return!0}}class Be{static separatedBy=(e,t,i=1)=>new RegExp(e+"(?:"+t+e+")"+(1===i?"*":2===i?"+":`{${i},}`));static Regex=class{static HexDigit=/[0-9a-fA-F]/;static InsideString=/(?:[^"\\]|\\.)*/;static InsideSingleQuotedString=/(?:[^'\\]|\\.)*/;static Integer=/[\-\+]?\d+(?!\d|\.)/;static Number=/[-\+]?(?:\d*\.)?\d+(?!\d|\.)/;static RealUnit=/\+?(?:0(?:\.\d+)?|1(?:\.0+)?)(?![\.\d])/;static Word=Be.separatedBy("[a-zA-Z]","_");static Symbol=/[a-zA-Z_]\w*/;static DotSeparatedSymbols=Be.separatedBy(this.Symbol.source,"\\.");static PathFragment=Be.separatedBy(this.Symbol.source,"[\\.:]");static PathSpaceFragment=Be.separatedBy(this.Symbol.source,"[\\.:\\ ]");static Path=new RegExp(`(?:\\/${this.PathFragment.source}){2,}`)};static null=Te.reg(/\(\s*\)/).map((()=>null));static true=Te.reg(/true/i).map((()=>!0));static false=Te.reg(/false/i).map((()=>!1));static boolean=Te.regArray(/(true)|false/i).map((e=>!!e[1]));static number=Te.regArray(new RegExp(`(${Te.number.getParser().parser.regexp.source})|(\\+?inf)|(-inf)`)).map((([e,t,i,s])=>t?Number(t):i?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY));static bigInt=Te.reg(new RegExp(Te.number.getParser().parser.regexp.source)).map(BigInt).map((e=>void 0!==e[2]?Number.POSITIVE_INFINITY:void 0!==e[3]?Number.NEGATIVE_INFINITY:Number(e[1])));static naturalNumber=Te.lazy((()=>Te.reg(/\d+/).map(Number)));static string=Te.doubleQuotedString.map((e=>he.unescapeString(e)));static colorValue=Te.numberByte;static word=Te.reg(Be.Regex.Word);static symbol=Te.reg(Be.Regex.Symbol);static symbolQuoted=Te.reg(new RegExp('"('+Be.Regex.Symbol.source+')"'),1);static attributeName=Te.reg(Be.Regex.DotSeparatedSymbols);static attributeNameQuoted=Te.reg(new RegExp('"('+Be.Regex.DotSeparatedSymbols.source+')"'),1);static guid=Te.reg(new RegExp(`${Be.Regex.HexDigit.source}{32}`));static commaSeparation=Te.reg(/\s*,\s*(?!\))/);static commaOrSpaceSeparation=Te.reg(/\s*,\s*(?!\))|\s+/);static equalSeparation=Te.reg(/\s*=\s*/);static hexColorChannel=Te.reg(new RegExp(Be.Regex.HexDigit.source+"{2}"));static grammarFor(e,t=e?.type,i=this.unknownValue){let s=i;if(t instanceof Array){if(e?.inlined)return this.grammarFor(void 0,t[0]);s=Te.seq(Te.reg(/\(\s*/),this.grammarFor(void 0,t[0]).sepBy(this.commaSeparation),Te.reg(/\s*(?:,\s*)?\)/)).map((([e,t,i])=>t))}else if(t instanceof ue)s=t.values.map((e=>this.grammarFor(void 0,e))).reduce(((e,t)=>t&&t!==this.unknownValue&&e!==this.unknownValue?Te.alt(e,t):this.unknownValue));else{if(t instanceof ce)return this.grammarFor(void 0,t.getTargetType()).map((e=>new ce(t.type,(()=>e))));if(e?.constructor===Object)s=this.grammarFor(void 0,t);else switch(t){case Boolean:s=this.boolean;break;case null:s=this.null;break;case Number:s=this.number;break;case BigInt:s=this.bigInt;break;case String:s=this.string;break;default:t?.prototype instanceof Le&&(s=t.grammar)}}return e&&(e.serialized&&t.constructor!==String&&(s=s==this.unknownValue?this.string:Te.seq(Te.str('"'),s,Te.str('"'))),e.nullable&&(s=Te.alt(s,this.null))),s}static getAttribute(e,t){let i,s;if(e instanceof ue)for(let s of e.values)if(i=this.getAttribute(s,t))return i;return e instanceof Ie.constructor?(i=e.attributes[t[0]],s=i?.type):e instanceof Array&&(i=e[t[0]],s=i),t.length>1?this.getAttribute(s,t.slice(1)):i}static createAttributeGrammar(e,t=this.attributeName,i=this.equalSeparation,s=((e,t,i)=>{})){return Te.seq(t,i).chain((([t,i])=>{const r=t.split(ne.keysSeparator),n=this.getAttribute(e,r);return this.grammarFor(n).map((e=>t=>{s(t,r,e),he.objectSet(t,r,e)}))}))}static createEntityGrammar(e,t=!0,i=this.commaSeparation){const s=e.attributes.lookbehind.default;return Te.seq(Te.reg(s instanceof ue?new RegExp(`(${s.values.reduce(((e,t)=>e+"|"+t))})\\s*\\(\\s*`):s.constructor==String&&s.length>0?new RegExp(`(${s})\\s*\\(\\s*`):/()\(\s*/,1),this.createAttributeGrammar(e).sepBy(i),Te.reg(/\s*(?:,\s*)?\)/)).map((([e,t,i])=>{let s={};return t.forEach((e=>e(s))),e.length&&(s.lookbehind=e),s})).chain((i=>{let s=Object.keys(i);if(Object.keys(e.attributes).filter((t=>e.attributes[t].expected)).find((e=>!s.includes(e)&&e)))return Te.failure();const r=Object.keys(i).filter((t=>!(t in e.attributes))).length;return!t&&r>0?Te.failure():Te.success().map((()=>new e(i)))}))}static unknownValue}var $e;"undefined"==typeof window?import("crypto").then((e=>$e=e.default)).catch():$e=window.crypto;class He extends Ie{static attributes={...super.attributes,value:le.createValue("")};static grammar=this.createGrammar();static createGrammar(){return Be.guid.map((e=>new this(e)))}static generateGuid(e=!0){let t=new Uint32Array(4);!0===e&&$e.getRandomValues(t);let i="";return t.forEach((e=>{i+=("0".repeat(8)+e.toString(16).toUpperCase()).slice(-8)})),new He({value:i})}constructor(e){e||(e=He.generateGuid().value),e.constructor!==Object&&(e={value:e}),super(e),this.value}valueOf(){return this.value}toString(){return this.value}}class Ve extends Ie{static attributes={...super.attributes,type:new le({default:"",serialized:!0}),path:new le({default:"",serialized:!0})};static quoted=Te.regArray(new RegExp("'\"("+Be.Regex.InsideString.source+")\"'|'("+Be.Regex.InsideSingleQuotedString.source+")'|\"("+Be.Regex.InsideString.source+')"')).map((([e,t,i,s])=>t??i??s));static path=this.quoted.getParser().parser.regexp.source+"|"+Be.Regex.Path.source;static typeReference=Te.reg(new RegExp(Be.Regex.Path.source+"|"+Be.symbol.getParser().regexp.source));static fullReferenceGrammar=Te.regArray(new RegExp("("+this.typeReference.getParser().regexp.source+")"+/\s*/.source+"(?:"+this.quoted.getParser().parser.regexp.source+")")).map((([e,t,...i])=>new this({type:t,path:i.find((e=>e))})));static fullReferenceSerializedGrammar=Te.regArray(new RegExp("("+this.typeReference.getParser().regexp.source+")"+/\s*/.source+"'("+Be.Regex.InsideSingleQuotedString.source+")'")).map((([e,t,...i])=>new this({type:t,path:i.find((e=>e))})));static typeReferenceGrammar=this.typeReference.map((e=>new this({type:e,path:""})));static grammar=this.createGrammar();static createGrammar(){return Te.alt(Te.seq(Te.str('"'),Te.alt(this.fullReferenceSerializedGrammar,this.typeReferenceGrammar),Te.str('"')).map((([e,t,i])=>t)),this.fullReferenceGrammar.map((e=>(he.objectSet(e,["attributes","type","serialized"],!1),e))),this.typeReferenceGrammar.map((e=>(he.objectSet(e,["attributes","type","serialized"],!1),e))))}constructor(e={}){e.constructor===String&&(e={path:e}),super(e),this.type,this.path}static createNoneInstance(){return new Ve({type:"None",path:""})}sanitize(){if(this.type&&!this.type.startsWith("/")){let e=this.type+"_Deprecated",t=Object.keys(ne.paths).find((t=>{const i=he.getNameFromPath(ne.paths[t]);return i===this.type||i===e}));t&&(this.type=ne.paths[t])}}getName(){return he.getNameFromPath(this.path.replace(/_C$/,""))}toString(){return this.type+(this.path?`'${this.path}'`:"")}}class Ge extends Ie{static attributes={...super.attributes,MemberParent:le.createType(Ve),MemberName:le.createType(String),MemberGuid:le.createType(He)};static grammar=this.createGrammar();static createGrammar(){return Be.createEntityGrammar(this)}constructor(e){super(e),this.MemberParent,this.MemberName,this.MemberGuid}}class De extends Ie{static attributes={...super.attributes,value:le.createValue("")};static attributeConverter={fromAttribute:(e,t)=>new De(e),toAttribute:(e,t)=>e.toString()};static grammar=this.createGrammar();static createGrammar(){return Be.symbol.map((e=>new this(e)))}constructor(e){e.constructor!==Object&&(e={value:e}),super(e),this.value}valueOf(){return this.value}toString(){return this.value}}class Oe extends Ie{static attributes={...super.attributes,value:new le({default:0,predicate:e=>e%1==0&&e>1<<31&&e<-(1<<31)})};static grammar=this.createGrammar();static createGrammar(){return Te.numberInteger.map((e=>new this(e)))}constructor(e=0){-0===e&&(e=0),super(e.constructor===Object?e:{value:e}),this.value}valueOf(){return this.value}toString(){return this.value.toString()}}class Re extends Ie{static attributes={...super.attributes,value:le.createValue(0)};static grammar=this.createGrammar();static createGrammar(){return Te.number.map((e=>new this(e)))}constructor(e=0){e.constructor!==Object&&(e={value:e}),super(e),this.value}valueOf(){return this.value}toString(){return this.value.toFixed(6)}}class ze extends Ie{static attributes={...super.attributes,R:new le({type:Re,default:()=>new Re,expected:!0}),G:new le({type:Re,default:()=>new Re,expected:!0}),B:new le({type:Re,default:()=>new Re,expected:!0}),A:new le({type:Re,default:()=>new Re(1)}),H:new le({type:Re,default:()=>new Re,ignored:!0}),S:new le({type:Re,default:()=>new Re,ignored:!0}),V:new le({type:Re,default:()=>new Re,ignored:!0})};static grammar=this.createGrammar();static linearToSRGB(e){return e<=0?0:e>=1?1:e<.0031308?12.92*e:1.055*Math.pow(e,1/2.4)-.055}static sRGBtoLinear(e){return e<=0?0:e>=1?1:e<.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)}static getWhite(){return new ze({R:1,G:1,B:1})}static createGrammar(){return Be.createEntityGrammar(this,!1)}static getLinearColorFromHexGrammar(){return Te.regArray(new RegExp("#("+Be.Regex.HexDigit.source+"{2})("+Be.Regex.HexDigit.source+"{2})("+Be.Regex.HexDigit.source+"{2})("+Be.Regex.HexDigit.source+"{2})?")).map((([e,t,i,s,r])=>new this({R:parseInt(t,16)/255,G:parseInt(i,16)/255,B:parseInt(s,16)/255,A:parseInt(r??"FF",16)/255})))}static getLinearColorRGBListGrammar(){return Te.seq(Te.numberByte,Be.commaSeparation,Te.numberByte,Be.commaSeparation,Te.numberByte).map((([e,t,i,s,r])=>new this({R:e/255,G:i/255,B:r/255,A:1})))}static getLinearColorRGBGrammar(){return Te.seq(Te.reg(/rgb\s*\(\s*/),this.getLinearColorRGBListGrammar(),Te.reg(/\s*\)/)).map((([e,t,i])=>t))}static getLinearColorRGBAGrammar(){return Te.seq(Te.reg(/rgba\s*\(\s*/),this.getLinearColorRGBListGrammar(),Te.reg(/\s*\)/)).map((([e,t,i])=>t))}static getLinearColorFromAnyFormat(){return Te.alt(this.getLinearColorFromHexGrammar(),this.getLinearColorRGBAGrammar(),this.getLinearColorRGBGrammar(),this.getLinearColorRGBListGrammar())}constructor(e){e instanceof Array&&(e={R:e[0]??0,G:e[1]??0,B:e[2]??0,A:e[3]??1}),super(e),this.R,this.G,this.B,this.A,this.H,this.S,this.V,this.#x()}#x(){const e=this.R.value,t=this.G.value,i=this.B.value;if(he.approximatelyEqual(e,t)&&he.approximatelyEqual(e,i)&&he.approximatelyEqual(t,i))return this.S.value=0,void(this.V.value=e);const s=Math.max(e,t,i),r=Math.min(e,t,i),n=s-r;let a;switch(s){case r:a=0;break;case e:a=(t-i)/n+(te.toString(16).toUpperCase().padStart(2,"0"))).join("")}toSRGBAString(){return this.toSRGBA().map((e=>e.toString(16).toUpperCase().padStart(2,"0"))).join("")}toHSVA(){return[this.H.value,this.S.value,this.V.value,this.A.value]}toNumber(){return(Math.round(255*this.R.value)<<24)+(Math.round(255*this.G.value)<<16)+(Math.round(255*this.B.value)<<8)+Math.round(255*this.A.value)}setFromRGBANumber(e){this.A.value=(255&e)/255,this.B.value=(e>>8&255)/255,this.G.value=(e>>16&255)/255,this.R.value=(e>>24&255)/255,this.#x()}setFromSRGBANumber(e){this.A.value=(255&e)/255,this.B.value=ze.sRGBtoLinear((e>>8&255)/255),this.G.value=ze.sRGBtoLinear((e>>16&255)/255),this.R.value=ze.sRGBtoLinear((e>>24&255)/255),this.#x()}toArray(){return[this.R.value,this.G.value,this.B.value,this.A.value]}toString(){return he.printLinearColor(this)}}class _e extends Ie{static attributes={...super.attributes,MacroGraph:new le({type:Ve,default:()=>new Ve}),GraphBlueprint:new le({type:Ve,default:()=>new Ve}),GraphGuid:new le({type:He,default:()=>new He})};static grammar=this.createGrammar();static createGrammar(){return Be.createEntityGrammar(this)}constructor(e){super(e),this.MacroGraph,this.GraphBlueprint,this.GuidEntity}getMacroName(){const e=this.MacroGraph.path.search(":");return this.MacroGraph.path.substring(e+1)}}class Fe extends Oe{static attributes={...super.attributes,value:new le({...super.attributes.value,predicate:e=>e%1==0&&e>=0&&e<256})};static grammar=this.createGrammar();static createGrammar(){return Te.numberByte.map((e=>new this(e)))}constructor(e=0){super(e)}}class je extends Ie{static attributes={...super.attributes,value:le.createValue("")};static grammar=this.createGrammar();static createGrammar(){return Be.symbol.map((e=>new this(e)))}constructor(e){e.constructor!==Object&&(e={value:e}),super(e),this.value}valueOf(){return this.value}toString(){return this.value}}class Ue extends je{static grammar=this.createGrammar();static createGrammar(){return Be.symbol.map((e=>new this(e)))}}class We extends Ue{static grammar=this.createGrammar();static createGrammar(){return Te.reg(Be.Regex.InsideString).map((e=>new this(e)))}}class Ke extends Ie{static attributes={...super.attributes,value:le.createValue(""),lookbehind:new le({...super.attributes.lookbehind,default:"INVTEXT"})};static grammar=this.createGrammar();static createGrammar(){return Te.alt(Te.seq(Te.reg(new RegExp(`${this.attributes.lookbehind.default}\\s*\\(`)),Be.grammarFor(this.attributes.value),Te.reg(/\s*\)/)).map((([e,t,i])=>t)),Te.reg(new RegExp(this.attributes.lookbehind.default)).map((()=>""))).map((e=>new this(e)))}constructor(e){e.constructor!==Object&&(e={value:e}),super(e),this.value}}class Ye extends Ie{static attributes={...super.attributes,namespace:le.createValue(""),key:le.createValue(""),value:le.createValue(""),lookbehind:new le({...super.attributes.lookbehind,default:"NSLOCTEXT"})};static grammar=this.createGrammar();static createGrammar(){return Te.regArray(new RegExp(String.raw`${this.attributes.lookbehind.default}\s*\(`+String.raw`\s*"(${Be.Regex.InsideString.source})"\s*,`+String.raw`\s*"(${Be.Regex.InsideString.source})"\s*,`+String.raw`\s*"(${Be.Regex.InsideString.source})"\s*`+String.raw`(?:,\s+)?`+String.raw`\)`,"m")).map((e=>new this({namespace:he.unescapeString(e[1]),key:he.unescapeString(e[2]),value:he.unescapeString(e[3])})))}constructor(e){super(e),this.namespace,this.key,this.value}toString(){return he.capitalFirstLetter(this.value)}}class Ze extends Ie{static attributes={...super.attributes,value:new le({type:[new ue(String,Ye,Ke,Ze)],default:[]}),lookbehind:new le({...super.attributes.lookbehind,default:new ue("LOCGEN_FORMAT_NAMED","LOCGEN_FORMAT_ORDERED")})};static grammar=this.createGrammar();static createGrammar(){return Te.seq(Te.reg(new RegExp(`(${this.attributes.lookbehind.default.values.reduce(((e,t)=>e+"|"+t))})\\s*`),1),Be.grammarFor(this.attributes.value)).map((([e,t])=>new this({value:t,lookbehind:e})))}constructor(e){super(e),this.value}toString(){const e=this.value?.[0]?.toString();if(!e)return"";const t=this.value.slice(1).map((e=>e.toString()));return"LOCGEN_FORMAT_NAMED"==this.lookbehind?e.replaceAll(/\{([a-zA-Z]\w*)\}/g,((e,i)=>{const s=t.indexOf(i)+1;return s>0&&s{const s=Number(i);return se>=-(1n<<63n)&&e<1n<<63n})};static grammar=this.createGrammar();static createGrammar(){return Te.numberBigInteger.map((e=>new this(e)))}constructor(e=0){e.constructor!==Object&&(e={value:e}),super(e),this.value}valueOf(){return this.value}toString(){return this.value.toString()}}class qe extends Ie{static attributes={...super.attributes,value:new le({default:""})};static grammar=this.createGrammar();static createGrammar(){return Be.symbol.map((e=>new this(e)))}constructor(e){e.constructor!==Object&&(e={value:e}),super(e),this.value}valueOf(){return this.value}toString(){return this.value}}class Qe extends Ie{static attributes={...super.attributes,objectName:le.createType(qe),pinGuid:le.createType(He)};static grammar=this.createGrammar();static createGrammar(){return Te.seq(qe.createGrammar(),Te.whitespace,He.createGrammar()).map((([e,t,i])=>new this({objectName:e,pinGuid:i})))}constructor(e){super(e),this.objectName,this.pinGuid}}class Je extends Ie{static attributes={...super.attributes,PinCategory:le.createValue(""),PinSubCategory:le.createValue(""),PinSubCategoryObject:new le({type:Ve,default:()=>Ve.createNoneInstance()}),PinSubCategoryMemberReference:new le({type:Ge,default:null}),PinValueType:new le({type:Je,default:null}),ContainerType:le.createType(qe),bIsReference:le.createValue(!1),bIsConst:le.createValue(!1),bIsWeakPointer:le.createValue(!1),bIsUObjectWrapper:le.createValue(!1),bSerializeAsSinglePrecisionFloat:le.createValue(!1)};static grammar=this.createGrammar();static createGrammar(){return Be.createEntityGrammar(this)}constructor(e={},t=!1){super(e,t),this.PinCategory,this.PinSubCategory,this.PinSubCategoryObject,this.PinSubCategoryMemberReference,this.PinValueType,this.ContainerType,this.bIsReference,this.bIsConst,this.bIsWeakPointer,this.bIsUObjectWrapper,this.bIsUObjectWrapper,this.bSerializeAsSinglePrecisionFloat}copyTypeFrom(e){this.PinCategory=e.PinCategory,this.PinSubCategory=e.PinSubCategory,this.PinSubCategoryObject=e.PinSubCategoryObject,this.PinSubCategoryMemberReference=e.PinSubCategoryMemberReference,this.PinValueType=e.PinValueType,this.ContainerType=e.ContainerType,this.bIsReference=e.bIsReference,this.bIsConst=e.bIsConst,this.bIsWeakPointer=e.bIsWeakPointer,this.bIsUObjectWrapper=e.bIsUObjectWrapper,this.bSerializeAsSinglePrecisionFloat=e.bSerializeAsSinglePrecisionFloat}}class et extends Ie{static attributes={...super.attributes,X:new le({default:0,expected:!0}),Y:new le({default:0,expected:!0})};static grammar=this.createGrammar();static createGrammar(){return Be.createEntityGrammar(this,!1)}constructor(e){super(e),this.X,this.Y}toArray(){return[this.X,this.Y]}}class tt extends et{static grammar=this.createGrammar();static createGrammar(){return Te.alt(Te.regArray(new RegExp(/X\s*=\s*/.source+"(?"+Te.number.getParser().parser.regexp.source+")\\s+"+/Y\s*=\s*/.source+"(?"+Te.number.getParser().parser.regexp.source+")")).map((({groups:{x:e,y:t}})=>new this({X:Number(e),Y:Number(t)}))),et.createGrammar())}}class it extends Ie{static attributes={...super.attributes,R:new le({default:0,expected:!0}),P:new le({default:0,expected:!0}),Y:new le({default:0,expected:!0})};static grammar=this.createGrammar();static createGrammar(){return Be.createEntityGrammar(this,!1)}constructor(e){super(e),this.R,this.P,this.Y}getRoll(){return this.R}getPitch(){return this.P}getYaw(){return this.Y}}class st extends it{static grammar=this.createGrammar();static createGrammar(){const e=Te.number.getParser().parser.regexp.source;return Te.alt(Te.reg(new RegExp("("+e+")\\s*,\\s("+e+")\\s*,\\s("+e+")")).map((([e,t,i])=>new this({R:Number(i),P:Number(e),Y:Number(t)}))),it.createGrammar())}}class rt extends et{static grammar=this.createGrammar();static createGrammar(){const e=Te.number.getParser().parser.regexp.source;return Te.alt(Te.reg(new RegExp("("+e+")\\s*,\\s("+e+")")).map((([e,t])=>new this({X:Number(e),Y:Number(t)}))),et.createGrammar())}}class nt extends Ie{static attributes={...super.attributes,X:new le({default:0,expected:!0}),Y:new le({default:0,expected:!0}),Z:new le({default:0,expected:!0})};static grammar=this.createGrammar();static createGrammar(){return Be.createEntityGrammar(nt,!1)}constructor(e){super(e),this.X,this.Y,this.Z}toArray(){return[this.X,this.Y,this.Z]}}class at extends nt{static grammar=this.createGrammar();static createGrammar(){const e=Te.number.getParser().parser.regexp.source;return Te.alt(Te.regArray(new RegExp("("+e+")\\s*,\\s*("+e+")\\s*,\\s*("+e+")")).map((([e,t,i,s])=>new this({X:Number(t),Y:Number(i),Z:Number(s)}))),nt.createGrammar())}}class ot extends Ie{static#P={[ne.paths.linearColor]:ze,[ne.paths.rotator]:it,[ne.paths.vector]:nt,[ne.paths.vector2D]:et,bool:Boolean,byte:Fe,enum:Ue,exec:String,int:Oe,int64:Xe,name:String,real:Number,string:String};static#N={enum:We,rg:tt,[ne.paths.rotator]:st,[ne.paths.vector]:at,[ne.paths.vector2D]:rt};static attributes={...super.attributes,lookbehind:new le({default:"Pin",ignored:!0}),objectEntity:new le({ignored:!0}),pinIndex:new le({type:Number,ignored:!0}),PinId:new le({type:He,default:()=>new He}),PinName:le.createValue(""),PinFriendlyName:le.createType(new ue(Ye,Ze,String)),PinToolTip:le.createType(String),Direction:le.createType(String),PinType:new le({type:Je,default:()=>new Je,inlined:!0}),LinkedTo:le.createType([Qe]),SubPins:le.createType([Qe]),ParentPin:le.createType(Qe),DefaultValue:new le({type:new oe((e=>e.getEntityType(!0)??String)),serialized:!0}),AutogeneratedDefaultValue:le.createType(String),DefaultObject:le.createType(Ve),PersistentGuid:le.createType(He),bHidden:le.createValue(!1),bNotConnectable:le.createValue(!1),bDefaultValueIsReadOnly:le.createValue(!1),bDefaultValueIsIgnored:le.createValue(!1),bAdvancedView:le.createValue(!1),bOrphanedPin:le.createValue(!1)};static grammar=this.createGrammar();#k=!1;set recomputesNodeTitleOnChange(e){this.#k=e}get recomputesNodeTitleOnChange(){return this.#k}static createGrammar(){return Be.createEntityGrammar(this)}constructor(e={},t=!1){super(e,t),this.objectEntity,this.pinIndex,this.PinId,this.PinName,this.PinFriendlyName,this.PinToolTip,this.Direction,this.PinType,this.LinkedTo,this.DefaultValue,this.AutogeneratedDefaultValue,this.DefaultObject,this.PersistentGuid,this.bHidden,this.bNotConnectable,this.bDefaultValueIsReadOnly,this.bDefaultValueIsIgnored,this.bAdvancedView,this.bOrphanedPin}static fromLegacyObject(e){return new ot(e,!0)}getType(){const e=this.PinType.PinCategory;if("struct"===e||"object"===e)return this.PinType.PinSubCategoryObject.path;if(this.isEnum())return"enum";if(this.objectEntity?.isPcg()){const e=this.objectEntity.getPcgSubobject(),t=this.isInput()?e.InputPins?.[this.pinIndex]:e.OutputPins?.[this.pinIndex];if(t){const i=e[ne.subObjectAttributeNameFromReference(t,!0)];let s=i.Properties?.AllowedTypes?.toString()??"";if(""==s&&(s=this.PinType.PinCategory??"",""==s&&(s="Any")),s)return!1!==i.Properties.bAllowMultipleData&&!1!==i.Properties.bAllowMultipleConnections&&(s+="[]"),s}}if("optional"===e)switch(this.PinType.PinSubCategory){case"red":return"real";case"rg":return"rg";case"rgb":return ne.paths.vector;case"rgba":return ne.paths.linearColor;default:return this.PinType.PinSubCategory}return e}getEntityType(e=!1){const t=this.getType(),i=ot.#P[t],s=ot.#N[t];return e&&void 0!==s?s:i}pinDisplayName(){let e,t=this.PinFriendlyName?this.PinFriendlyName.toString():he.formatStringName(this.PinName??"");return this.PinToolTip&&(e=this.PinToolTip.match(/\s*(.+?(?=\n)|.+\S)\s*/))&&e[1].toLowerCase()===t.toLowerCase()?e[1]:t}copyTypeFrom(e){this.PinType.PinCategory=e.PinType.PinCategory,this.PinType.PinSubCategory=e.PinType.PinSubCategory,this.PinType.PinSubCategoryObject=e.PinType.PinSubCategoryObject,this.PinType.PinSubCategoryMemberReference=e.PinType.PinSubCategoryMemberReference,this.PinType.PinValueType=e.PinType.PinValueType,this.PinType.ContainerType=e.PinType.ContainerType,this.PinType.bIsReference=e.PinType.bIsReference,this.PinType.bIsConst=e.PinType.bIsConst,this.PinType.bIsWeakPointer=e.PinType.bIsWeakPointer,this.PinType.bIsUObjectWrapper=e.PinType.bIsUObjectWrapper,this.PinType.bSerializeAsSinglePrecisionFloat=e.PinType.bSerializeAsSinglePrecisionFloat}getDefaultValue(e=!1){return void 0===this.DefaultValue&&e&&(this.DefaultValue=new(this.getEntityType(!0))),this.DefaultValue}isEnum(){const e=this.PinType.PinSubCategoryObject.type;return e===ne.paths.enum||e===ne.paths.userDefinedEnum||"enum"===e.toLowerCase()}isExecution(){return"exec"===this.PinType.PinCategory}isHidden(){return this.bHidden}isInput(){return!this.bHidden&&"EGPD_Output"!=this.Direction}isOutput(){return!this.bHidden&&"EGPD_Output"==this.Direction}isLinked(){return this.LinkedTo?.length>0??!1}linkTo(e,t){const i=this.LinkedTo?.some((i=>i.objectName.toString()==e&&i.pinGuid.valueOf()==t.PinId.valueOf()));return!i&&((this.LinkedTo??=[]).push(new Qe({objectName:e,pinGuid:t.PinId})),!0)}unlinkFrom(e,t){const i=this.LinkedTo?.findIndex((i=>i.objectName.toString()==e&&i.pinGuid.valueOf()==t.PinId.valueOf()));return i>=0&&(this.LinkedTo.splice(i,1),0===this.LinkedTo.length&&void 0===ot.attributes.LinkedTo.default&&(this.LinkedTo=void 0),!0)}getSubCategory(){return this.PinType.PinSubCategoryObject.path}pinColor(){if("mask"==this.PinType.PinCategory){const e=ne.pinColor[this.PinType.PinSubCategory];if(e)return e}else if("optional"==this.PinType.PinCategory)return ne.pinColorMaterial;return ne.pinColor[this.getType()]??ne.pinColor[this.PinType.PinCategory.toLowerCase()]??ne.pinColor.default}}class lt extends ot{static grammar=this.createGrammar();static createGrammar(){return Te.seq(Te.reg(new RegExp(`(${Be.Regex.Symbol.source})\\s*\\(\\s*`),1),Be.createAttributeGrammar(this).sepBy(Be.commaSeparation),Te.reg(/\s*(?:,\s*)?\)/)).map((([e,t,i])=>{e??="";let s={};return e.length&&(s.lookbehind=e),t.forEach((e=>e(s))),new this(s)}))}constructor(e={}){super(e,!0)}}class ct extends Ie{static attributes={...super.attributes,MemberScope:le.createType(String),MemberName:le.createValue(""),MemberGuid:le.createType(He),bSelfContext:le.createType(Boolean)};static grammar=this.createGrammar();static createGrammar(){return Be.createEntityGrammar(this)}constructor(e){super(e),this.MemberName,this.GuidEntity,this.bSelfContext}}class ut extends Ie{static#T={A_AccentGrave:"à",Add:"Num +",C_Cedille:"ç",Decimal:"Num .",Divide:"Num /",E_AccentAigu:"é",E_AccentGrave:"è",F1:"F1",F10:"F10",F11:"F11",F12:"F12",F2:"F2",F3:"F3",F4:"F4",F5:"F5",F6:"F6",F7:"F7",F8:"F8",F9:"F9",Gamepad_Special_Left_X:"Touchpad Button X Axis",Gamepad_Special_Left_Y:"Touchpad Button Y Axis",Mouse2D:"Mouse XY 2D-Axis",Multiply:"Num *",Section:"§",Subtract:"Num -",Tilde:"`"};static attributes={...super.attributes,R:new le({default:!1,silent:!0}),G:new le({default:!1,silent:!0}),B:new le({default:!1,silent:!0}),A:new le({default:!1,silent:!0}),AdvancedPinDisplay:le.createType(De),Archetype:le.createType(Ve),AxisKey:le.createType(je),bAlt:le.createType(Boolean),bCanRenameNode:le.createType(Boolean),bColorCommentBubble:le.createType(Boolean),bCommand:le.createType(Boolean),bCommentBubblePinned:le.createType(Boolean),bCommentBubbleVisible_InDetailsPanel:le.createType(Boolean),bCommentBubbleVisible:le.createType(Boolean),bConsumeInput:le.createType(Boolean),bControl:le.createType(Boolean),bExecuteWhenPaused:le.createType(Boolean),bExposeToLibrary:le.createType(Boolean),bInternalEvent:le.createType(Boolean),bIsCaseSensitive:le.createType(Boolean),bIsConstFunc:le.createType(Boolean),bIsPureFunc:le.createType(Boolean),BlueprintElementInstance:le.createType(Ve),BlueprintElementType:le.createType(Ve),bOverrideFunction:le.createType(Boolean),bOverrideParentBinding:le.createType(Boolean),bShift:le.createType(Boolean),Class:le.createType(Ve),CommentColor:le.createType(ze),ComponentPropertyName:le.createType(String),CustomFunctionName:le.createType(String),CustomProperties:le.createType([new ue(ot,lt)]),DelegateOwnerClass:le.createType(Ve),DelegatePropertyName:le.createType(String),DelegateReference:le.createType(ct),EnabledState:le.createType(De),Enum:le.createType(Ve),EnumEntries:new le({type:[String],inlined:!0}),ErrorMsg:le.createType(String),ErrorType:le.createType(Oe),EventReference:le.createType(Ge),ExportPath:le.createType(Ve),FunctionReference:le.createType(Ge),Graph:le.createType(Ve),HiGenGridSize:le.createType(je),InputAxisKey:le.createType(je),InputKey:le.createType(je),InputName:le.createType(String),InputPins:new le({type:[Ve],inlined:!0}),InputType:le.createType(je),MacroGraphReference:le.createType(_e),MaterialExpression:le.createType(Ve),MaterialExpressionComment:le.createType(Ve),MaterialExpressionEditorX:le.createType(new ce(Oe)),MaterialExpressionEditorY:le.createType(new ce(Oe)),MaterialFunction:le.createType(Ve),MoveMode:le.createType(je),Name:le.createType(String),Node:le.createType(new ce(Ve)),NodeComment:le.createType(String),NodeGuid:le.createType(He),NodeHeight:le.createType(Oe),NodePosX:le.createType(Oe),NodePosY:le.createType(Oe),NodeTitle:le.createType(String),NodeTitleColor:le.createType(ze),NodeWidth:le.createType(Oe),NumAdditionalInputs:le.createType(Number),ObjectRef:le.createType(Ve),Operation:le.createType(je),OutputPins:new le({type:[Ve],inlined:!0}),PCGNode:le.createType(Ve),PinNames:new le({type:[String],inlined:!0}),PinTags:new le({type:[null],inlined:!0}),PositionX:le.createType(new ce(Oe)),PositionY:le.createType(new ce(Oe)),ProxyClass:le.createType(Ve),ProxyFactoryClass:le.createType(Ve),ProxyFactoryFunctionName:le.createType(String),SelfContextInfo:le.createType(je),SettingsInterface:le.createType(Ve),SizeX:le.createType(new ce(Oe)),SizeY:le.createType(new ce(Oe)),StructType:le.createType(Ve),SubgraphInstance:le.createType(String),TargetType:le.createType(Ve),Text:le.createType(new ce(String)),TimelineGuid:le.createType(He),TimelineName:le.createType(String),VariableReference:le.createType(ct)};static nameRegex=/^(\w+?)(?:_(\d+))?$/;static sequencerScriptingNameRegex=/\/Script\/SequencerScripting\.MovieSceneScripting(.+)Channel/;static customPropertyGrammar=Te.seq(Te.reg(/CustomProperties\s+/),Be.grammarFor(void 0,this.attributes.CustomProperties.type[0])).map((([e,t])=>e=>{e.CustomProperties||(e.CustomProperties=[]),e.CustomProperties.push(t)}));static inlinedArrayEntryGrammar=Te.seq(Te.alt(Be.symbolQuoted.map((e=>[e,!0])),Be.symbol.map((e=>[e,!1]))),Te.reg(new RegExp("\\s*\\(\\s*(\\d+)\\s*\\)\\s*\\=\\s*"),1).map(Number)).chain((([[e,t],i])=>Be.grammarFor(this.attributes[e]).map((s=>r=>{(r[e]??=[])[i]=s,he.objectSet(r,["attributes",e,"quoted"],t),this.attributes[e]?.inlined||(r.attributes||Ie.defineAttributes(r,{}),he.objectSet(r,["attributes",e,"inlined"],!0))}))));static grammar=this.createGrammar();static createSubObjectGrammar(){return Te.lazy((()=>this.grammar)).map((e=>t=>t[ne.subObjectAttributeNameFromEntity(e)]=e))}static createGrammar(){return Te.seq(Te.reg(/Begin\s+Object/),Te.seq(Te.whitespace,Te.alt(this.customPropertyGrammar,Be.createAttributeGrammar(this),Be.createAttributeGrammar(this,Be.attributeNameQuoted,void 0,((e,t,i)=>he.objectSet(e,["attributes",...t,"quoted"],!0))),this.inlinedArrayEntryGrammar,this.createSubObjectGrammar())).map((([e,t])=>t)).many(),Te.reg(/\s+End\s+Object/)).map((([e,t,i])=>{const s={};return t.forEach((e=>e(s))),new this(s)}))}static keyName(e){let t=ut.#T[e];if(t)return t;if(t=he.numberFromText(e)?.toString(),t)return t;const i=e.match(/NumPad([a-zA-Z]+)/);return i&&(t=he.numberFromText(i[1]).toString(),t)?"Num "+t:void 0}static getMultipleObjectsGrammar(){return Te.seq(Te.whitespaceOpt,this.createGrammar(),Te.seq(Te.whitespace,this.createGrammar()).map((([e,t])=>t)).many(),Te.whitespaceOpt).map((([e,t,i,s])=>[t,...i]))}constructor(e={},t=!1){let i=Object.keys(e);if(i.some((e=>e.startsWith(ne.subObjectAttributeNamePrefix)))){let t=i.filter((e=>e.startsWith(ne.subObjectAttributeNamePrefix))).reduce(((t,i)=>(t[i]=e[i],t)),{});e={...t,...e}}super(e,t),this.R,this.G,this.B,this.A,this.CustomProperties,this.bIsPureFunc,this.ComponentPropertyName,this.EventReference,this.FunctionReference,this.AdvancedPinDisplay,this.EnabledState,this.NodeHeight,this.NodePosX,this.NodePosY,this.NodeWidth,this.CommentColor,this.NodeTitleColor,this.MacroGraphReference,this.MaterialExpressionEditorX,this.MaterialExpressionEditorY,this.SizeX,this.SizeY,this.Text,this.PositionX,this.PositionY,this.Node,this.PinTags,this.NumAdditionalInputs,this.InputPins,this.OutputPins,this.Archetype,this.BlueprintElementInstance,this.BlueprintElementType,this.Class,this.Enum,this.ExportPath,this.Graph,this.MaterialExpression,this.MaterialExpressionComment,this.MaterialFunction,this.ObjectRef,this.PCGNode,this.SettingsInterface,this.StructType,this.TargetType,this.EnumEntries,this.PinNames,this.CustomFunctionName,this.DelegatePropertyName,this.InputName,this.Name,this.NodeComment,this.NodeTitle,this.Operation,this.ProxyFactoryFunctionName,this.SubgraphInstance,this.Text,this.AxisKey,this.HiGenGridSize,this.InputAxisKey,this.InputKey,this.InputType,this.DelegateReference,this.VariableReference,this.Pins instanceof Array&&(this.Pins.forEach((e=>{const t=this[ne.subObjectAttributeNameFromReference(e,!0)];if(t){const e=ot.fromLegacyObject(t);e.LinkedTo=[],this.getCustomproperties(!0).push(e)}})),delete this.Pins),this.Class?.sanitize(),this.MacroGraphReference&&(this.MacroGraphReference.MacroGraph?.sanitize(),this.MacroGraphReference.GraphBlueprint?.sanitize());const s=this.getMaterialSubobject();if(s){const e=s;if(void 0!==e.SizeX&&(e.SizeX.getter=()=>this.NodeWidth),e.SizeY&&(e.SizeY.getter=()=>this.NodeHeight),e.Text&&(e.Text.getter=()=>this.NodeComment),e.MaterialExpressionEditorX&&(e.MaterialExpressionEditorX.getter=()=>this.NodePosX),e.MaterialExpressionEditorY&&(e.MaterialExpressionEditorY.getter=()=>this.NodePosY),this.getType()===ne.paths.materialExpressionComponentMask){const t=ne.rgba.map((e=>this.getPinEntities().find((t=>t.PinName===e&&(t.recomputesNodeTitleOnChange=!0)))));e.R=new ce(Boolean,(()=>t[0].DefaultValue)),e.G=new ce(Boolean,(()=>t[1].DefaultValue)),e.B=new ce(Boolean,(()=>t[2].DefaultValue)),e.A=new ce(Boolean,(()=>t[3].DefaultValue))}}const r=this.getPcgSubobject();r&&(r.PositionX&&(r.PositionX.getter=()=>this.NodePosX),r.PositionY&&(r.PositionY.getter=()=>this.NodePosY),r.getSubobjects().forEach((e=>{if(void 0!==e.Node){const t=e.Node.get();t.type===this.PCGNode.type&&t.path===`${this.Name}.${this.PCGNode.path}`&&(e.Node.getter=()=>new Ve({type:this.PCGNode.type,path:`${this.Name}.${this.PCGNode.path}`}))}})));let n=0,a=0;this.CustomProperties?.forEach(((e,t)=>{e.objectEntity=this,e.pinIndex=e.isInput()?n++:e.isOutput()?a++:t}))}getClass(){return(this.Class?.path?this.Class.path:this.Class?.type)??(this.ExportPath?.path?this.ExportPath.path:this.ExportPath?.type)??""}getType(){let e=this.getClass();return this.MacroGraphReference?.MacroGraph?.path?this.MacroGraphReference.MacroGraph.path:this.MaterialExpression?this.MaterialExpression.type:e}getObjectName(e=!1){return e?this.getNameAndCounter()[0]:this.Name}getNameAndCounter(){const e=this.getObjectName(!1).match(ut.nameRegex);let t="",i=null;return e?(e.length>1&&(t=e[1]),e.length>2&&(i=parseInt(e[2])),[t,i]):["",0]}getCounter(){return this.getNameAndCounter()[1]}getNodeWidth(){return this.NodeWidth??this.isComment()?ne.defaultCommentWidth:void 0}setNodeWidth(e){this.NodeWidth||(this.NodeWidth=new Oe),this.NodeWidth.value=e}getNodeHeight(){return this.NodeHeight??this.isComment()?ne.defaultCommentHeight:void 0}setNodeHeight(e){this.NodeHeight||(this.NodeHeight=new Oe),this.NodeHeight.value=e}getNodePosX(){return this.NodePosX?.value??0}setNodePosX(e){this.NodePosX||(this.NodePosX=new Oe),this.NodePosX.value=Math.round(e)}getNodePosY(){return this.NodePosY?.value??0}setNodePosY(e){this.NodePosY||(this.NodePosY=new Oe),this.NodePosY.value=Math.round(e)}getCustomproperties(e=!1){return e&&!this.CustomProperties&&(this.CustomProperties=[]),this.CustomProperties??[]}getPinEntities(){return this.getCustomproperties().filter((e=>e.constructor===ot))}getSubobjects(){return Object.keys(this).filter((e=>e.startsWith(ne.subObjectAttributeNamePrefix))).flatMap((e=>[this[e],...this[e].getSubobjects()]))}switchTarget(){const e=this.getClass().match(ne.switchTargetPattern);if(e)return e[1]}isEvent(){switch(this.getClass()){case ne.paths.actorBoundEvent:case ne.paths.componentBoundEvent:case ne.paths.customEvent:case ne.paths.event:case ne.paths.inputAxisKeyEvent:case ne.paths.inputVectorAxisEvent:return!0}return!1}isComment(){switch(this.getClass()){case ne.paths.comment:case ne.paths.materialGraphNodeComment:return!0}return!1}isMaterial(){return this.getClass()===ne.paths.materialGraphNode}getMaterialSubobject(){const e=this.MaterialExpression??this.MaterialExpressionComment;return e?this[ne.subObjectAttributeNameFromReference(e,!0)]:null}isPcg(){return this.getClass()===ne.paths.pcgEditorGraphNode||this.getPcgSubobject()}getPcgSubobject(){const e=this.PCGNode;return e?this[ne.subObjectAttributeNameFromReference(e,!0)]:null}getSettingsObject(){const e=this.SettingsInterface;return e?this[ne.subObjectAttributeNameFromReference(e,!0)]:null}getSubgraphObject(){const e=this.SubgraphInstance;return e?this[ne.subObjectAttributeNameFromName(e)]:null}isDevelopmentOnly(){const e=this.getClass();return"DevelopmentOnly"===this.EnabledState?.toString()||e.includes("Debug",Math.max(0,e.lastIndexOf(".")))}getHIDAttribute(){return this.InputKey??this.AxisKey??this.InputAxisKey}getDelegatePin(){return this.getCustomproperties().find((e=>"delegate"===e.PinType.PinCategory))}nodeDisplayName(){let e;switch(this.getType()){case ne.paths.asyncAction:if(this.ProxyFactoryFunctionName)return he.formatStringName(this.ProxyFactoryFunctionName);case ne.paths.actorBoundEvent:case ne.paths.componentBoundEvent:return`${he.formatStringName(this.DelegatePropertyName)} (${this.ComponentPropertyName??"Unknown"})`;case ne.paths.callDelegate:return`Call ${this.DelegateReference?.MemberName??"None"}`;case ne.paths.createDelegate:return"Create Event";case ne.paths.customEvent:if(this.CustomFunctionName)return this.CustomFunctionName;case ne.paths.dynamicCast:return this.TargetType?`Cast To ${this.TargetType?.getName()}`:"Bad cast node";case ne.paths.enumLiteral:return`Literal enum ${this.Enum?.getName()}`;case ne.paths.event:return`Event ${(this.EventReference?.MemberName??"").replace(/^Receive/,"")}`;case ne.paths.executionSequence:return"Sequence";case ne.paths.forEachElementInEnum:return`For Each ${this.Enum?.getName()}`;case ne.paths.forEachLoopWithBreak:return"For Each Loop with Break";case ne.paths.functionEntry:return"UserConstructionScript"===this.FunctionReference?.MemberName?"Construction Script":this.FunctionReference?.MemberName;case ne.paths.functionResult:return"Return Node";case ne.paths.ifThenElse:return"Branch";case ne.paths.makeStruct:if(this.StructType)return`Make ${this.StructType.getName()}`;case ne.paths.materialExpressionComponentMask:{const e=this.getMaterialSubobject();return`Mask ( ${ne.rgba.filter((t=>!0===e[t].get())).map((e=>e+" ")).join("")})`}case ne.paths.materialExpressionConstant:e??=[this.getCustomproperties().find((e=>"Value"==e.PinName))?.DefaultValue];case ne.paths.materialExpressionConstant2Vector:e??=[this.getCustomproperties().find((e=>"X"==e.PinName))?.DefaultValue,this.getCustomproperties().find((e=>"Y"==e.PinName))?.DefaultValue];case ne.paths.materialExpressionConstant3Vector:if(!e){const t=this.getCustomproperties().find((e=>"Constant"==e.PinName))?.DefaultValue;e=[t.X,t.Y,t.Z]}case ne.paths.materialExpressionConstant4Vector:if(!e){const t=this.getCustomproperties().find((e=>"Constant"==e.PinName))?.DefaultValue;e=[t.R,t.G,t.B,t.A].map((e=>e.valueOf()))}if(e.length>0)return e.map((e=>he.printExponential(e))).reduce(((e,t)=>e+","+t));break;case ne.paths.materialExpressionFunctionInput:{const e=this.getMaterialSubobject();return`Input ${e?.InputName??"In"} (${e?.InputType?.value.match(/^.+?_(\w+)$/)?.[1]??"Vector3"})`}case ne.paths.materialExpressionLogarithm:return"Ln";case ne.paths.materialExpressionLogarithm10:return"Log10";case ne.paths.materialExpressionLogarithm2:return"Log2";case ne.paths.materialExpressionMaterialFunctionCall:const t=this.getMaterialSubobject()?.MaterialFunction;if(t)return t.getName();break;case ne.paths.materialExpressionSquareRoot:return"Sqrt";case ne.paths.pcgEditorGraphNodeInput:return"Input";case ne.paths.pcgEditorGraphNodeOutput:return"Output";case ne.paths.spawnActorFromClass:return`SpawnActor ${he.formatStringName(this.getCustomproperties().find((e=>"class"==e.getType()))?.DefaultObject?.getName()??"NONE")}`;case ne.paths.switchEnum:return`Switch on ${this.Enum?.getName()??"Enum"}`;case ne.paths.switchInteger:return"Switch on Int";case ne.paths.variableGet:return"";case ne.paths.variableSet:return"SET"}let t=this.switchTarget();if(t)return"E"!==t[0]&&(t=he.formatStringName(t)),`Switch on ${t}`;if(this.isComment())return this.NodeComment;const i=this.getHIDAttribute();if(i){const e=i.toString();let t=ut.keyName(e)??he.formatStringName(e);return this.getClass()===ne.paths.inputDebugKey?t="Debug Key "+t:this.getClass()===ne.paths.getInputAxisKeyValue&&(t="Get "+t),t}if(this.getClass()===ne.paths.macro)return he.formatStringName(this.MacroGraphReference?.getMacroName());if(this.isMaterial()&&this.getMaterialSubobject()){let e=this.getMaterialSubobject().nodeDisplayName();return e=e.match(/Material Expression (.+)/)?.[1]??e,e}if(this.isPcg()&&this.getPcgSubobject()){let e=this.getPcgSubobject();return e.NodeTitle?e.NodeTitle:e.nodeDisplayName()}const s=this.getSubgraphObject();if(s)return s.Graph.getName();const r=this.getSettingsObject();if(r){if(r.ExportPath.type===ne.paths.pcgHiGenGridSizeSettings)return`Grid Size: ${r.HiGenGridSize?.toString().match(/\d+/)?.[0]?.concat("00")??r.HiGenGridSize?.toString().match(/^\w+$/)?.[0]??"256"}`;if(r.BlueprintElementInstance)return he.formatStringName(r.BlueprintElementType.getName());if(r.Operation){const e=r.Name.match(/PCGMetadata(\w+)Settings_\d+/);if(e)return he.formatStringName(e[1]+": "+r.Operation)}const e=r.getSubgraphObject();if(e&&e.Graph)return e.Graph.getName()}let n=this.FunctionReference?.MemberName;if(n){const e=this.FunctionReference.MemberParent?.path??"";switch(n){case"AddKey":let t=e.match(ut.sequencerScriptingNameRegex);if(t)return`Add Key (${he.formatStringName(t[1])})`;case"Concat_StrStr":return"Append"}const t=n.match(ne.lineTracePattern);if(t)return"Line Trace"+("Multi"===t[1]?" Multi ":" ")+(""===t[2]?"By Channel":he.formatStringName(t[2]));switch(e){case ne.paths.blueprintGameplayTagLibrary:case ne.paths.kismetMathLibrary:case ne.paths.slateBlueprintLibrary:case ne.paths.timeManagementBlueprintLibrary:const e=n.match(/[BF]([A-Z]\w+)/);switch(e&&(n=e[1]),n){case"Abs":return"ABS";case"BooleanAND":return"AND";case"BooleanNAND":return"NAND";case"BooleanOR":return"OR";case"Exp":return"e";case"LineTraceSingle":return"Line Trace By Channel";case"Max":case"MaxInt64":return"MAX";case"Min":case"MinInt64":return"MIN";case"Not_PreBool":return"NOT";case"Sin":return"SIN";case"Sqrt":return"SQRT";case"Square":return"^2";case"CrossProduct2D":return"cross";case"Vector4_CrossProduct3":return"cross3";case"DotProduct2D":case"Vector4_DotProduct":return"dot";case"Vector4_DotProduct3":return"dot3"}if(n.startsWith("Add_"))return"+";if(n.startsWith("And_"))return"&";if(n.startsWith("Conv_"))return"";if(n.startsWith("Cross_"))return"cross";if(n.startsWith("Divide_"))return String.fromCharCode(247);if(n.startsWith("Dot_"))return"dot";if(n.startsWith("EqualEqual_"))return"==";if(n.startsWith("Greater_"))return">";if(n.startsWith("GreaterEqual_"))return">=";if(n.startsWith("Less_"))return"<";if(n.startsWith("LessEqual_"))return"<=";if(n.startsWith("Multiply_"))return String.fromCharCode(10799);if(n.startsWith("Not_"))return"~";if(n.startsWith("NotEqual_"))return"!=";if(n.startsWith("Or_"))return"|";if(n.startsWith("Percent_"))return"%";if(n.startsWith("Subtract_"))return"-";if(n.startsWith("Xor_"))return"^";break;case ne.paths.blueprintSetLibrary:{const e=n.match(/Set_(\w+)/);if(e)return he.formatStringName(e[1]).toUpperCase()}break;case ne.paths.blueprintMapLibrary:{const e=n.match(/Map_(\w+)/);if(e)return he.formatStringName(e[1]).toUpperCase()}break;case ne.paths.kismetArrayLibrary:{const e=n.match(/Array_(\w+)/);if(e)return e[1].toUpperCase()}}return he.formatStringName(n)}return this.ObjectRef?this.ObjectRef.getName():he.formatStringName(this.getNameAndCounter()[0])}nodeColor(){switch(this.getType()){case ne.paths.materialExpressionConstant2Vector:case ne.paths.materialExpressionConstant3Vector:case ne.paths.materialExpressionConstant4Vector:return ne.nodeColors.yellow;case ne.paths.makeStruct:return ne.nodeColors.darkBlue;case ne.paths.materialExpressionMaterialFunctionCall:return ne.nodeColors.blue;case ne.paths.materialExpressionFunctionInput:return ne.nodeColors.red;case ne.paths.materialExpressionTextureSample:return ne.nodeColors.darkTurquoise;case ne.paths.materialExpressionTextureCoordinate:case ne.paths.pcgEditorGraphNodeInput:case ne.paths.pcgEditorGraphNodeOutput:return ne.nodeColors.red}switch(this.getClass()){case ne.paths.callFunction:return this.bIsPureFunc?ne.nodeColors.green:ne.nodeColors.blue;case ne.paths.dynamicCast:return ne.nodeColors.turquoise;case ne.paths.inputDebugKey:case ne.paths.inputKey:return ne.nodeColors.red;case ne.paths.createDelegate:case ne.paths.enumLiteral:case ne.paths.makeArray:case ne.paths.makeMap:case ne.paths.materialGraphNode:case ne.paths.select:return ne.nodeColors.green;case ne.paths.executionSequence:case ne.paths.ifThenElse:case ne.paths.macro:case ne.paths.multiGate:return ne.nodeColors.gray;case ne.paths.functionEntry:case ne.paths.functionResult:return ne.nodeColors.violet;case ne.paths.timeline:return ne.nodeColors.yellow}if(this.switchTarget())return ne.nodeColors.lime;if(this.isEvent())return ne.nodeColors.red;if(this.isComment())return(this.CommentColor?this.CommentColor:ze.getWhite()).toDimmedColor().toCSSRGBValues();const e=this.getPcgSubobject();return e&&e.NodeTitleColor?e.NodeTitleColor.toDimmedColor(.1).toCSSRGBValues():this.bIsPureFunc?ne.nodeColors.green:ne.nodeColors.blue}nodeIcon(){if(this.isMaterial()||this.isPcg())return null;switch(this.getType()){case ne.paths.addDelegate:case ne.paths.asyncAction:case ne.paths.callDelegate:case ne.paths.createDelegate:case ne.paths.functionEntry:case ne.paths.functionResult:return Ae.node;case ne.paths.customEvent:return Ae.event;case ne.paths.doN:return Ae.doN;case ne.paths.doOnce:return Ae.doOnce;case ne.paths.dynamicCast:return Ae.cast;case ne.paths.enumLiteral:return Ae.enum;case ne.paths.event:return Ae.event;case ne.paths.executionSequence:case ne.paths.multiGate:return Ae.sequence;case ne.paths.flipflop:return Ae.flipflop;case ne.paths.forEachElementInEnum:case ne.paths.forLoop:case ne.paths.forLoopWithBreak:case ne.paths.whileLoop:return Ae.loop;case ne.paths.forEachLoop:case ne.paths.forEachLoopWithBreak:return Ae.forEachLoop;case ne.paths.ifThenElse:return Ae.branchNode;case ne.paths.isValid:return Ae.questionMark;case ne.paths.makeArray:return Ae.makeArray;case ne.paths.makeMap:return Ae.makeMap;case ne.paths.makeSet:return Ae.makeSet;case ne.paths.makeStruct:return Ae.makeStruct;case ne.paths.select:return Ae.select;case ne.paths.spawnActorFromClass:return Ae.spawnActor;case ne.paths.timeline:return Ae.timer}if(this.switchTarget())return Ae.switch;if(this.nodeDisplayName().startsWith("Break"))return Ae.breakStruct;if(this.getClass()===ne.paths.macro)return Ae.macro;const e=this.getHIDAttribute()?.toString();return e?e.includes("Mouse")?Ae.mouse:e.includes("Gamepad_Special")?Ae.keyboard:e.includes("Gamepad")||e.includes("Steam")?Ae.gamepad:e.includes("Touch")?Ae.touchpad:Ae.keyboard:this.getDelegatePin()?Ae.event:this.ObjectRef?.type===ne.paths.ambientSound?Ae.sound:Ae.functionSymbol}additionalPinInserter(){let e,t,i;switch(this.getType()){case ne.paths.commutativeAssociativeBinaryOperator:case ne.paths.promotableOperator:switch(this.FunctionReference?.MemberName){default:if(!(this.FunctionReference?.MemberName?.startsWith("Add_")||this.FunctionReference?.MemberName?.startsWith("Subtract_")||this.FunctionReference?.MemberName?.startsWith("Multiply_")||this.FunctionReference?.MemberName?.startsWith("Divide_")))break;case"And_Int64Int64":case"And_IntInt":case"BMax":case"BMin":case"BooleanAND":case"BooleanNAND":case"BooleanOR":case"Concat_StrStr":case"FMax":case"FMin":case"Max":case"MaxInt64":case"Min":case"MinInt64":case"Or_Int64Int64":case"Or_IntInt":e??=()=>this.getPinEntities().filter((e=>e.isInput())),t??=e=>e.PinName.match(/^\s*([A-Z])\s*$/)?.[1]?.charCodeAt(0)-"A".charCodeAt(0),i??=(t,i=-1,s=-1)=>{const r=String.fromCharCode(t>=0?t:s+"A".charCodeAt(0)+1);return this.NumAdditionalInputs=e().length-1,r}}break;case ne.paths.multiGate:e??=()=>this.getPinEntities().filter((e=>e.isOutput())),t??=e=>Number(e.PinName.match(/^\s*Out[_\s]+(\d+)\s*$/i)?.[1]),i??=(e,t=-1,i=-1)=>`Out ${e>=0?e:t>0?"Out 0":i+1}`;break;case ne.paths.switchInteger:e??=()=>this.getPinEntities().filter((e=>e.isOutput())),t??=e=>Number(e.PinName.match(/^\s*(\d+)\s*$/)?.[1]),i??=(e,t=-1,i=-1)=>(e<0?i+1:e).toString();break;case ne.paths.switchGameplayTag:i??=(e,t=-1,i=-1)=>{const s=`Case_${e>=0?e:t>0?"0":i+1}`;return this.PinNames??=[],this.PinNames.push(s),delete this.PinTags[this.PinTags.length-1],this.PinTags[this.PinTags.length]=null,s};case ne.paths.switchName:case ne.paths.switchString:e??=()=>this.getPinEntities().filter((e=>e.isOutput())),t??=e=>Number(e.PinName.match(/^\s*Case[_\s]+(\d+)\s*$/i)?.[1]),i??=(e,t=-1,i=-1)=>{const s=`Case_${e>=0?e:t>0?"0":i+1}`;return this.PinNames??=[],this.PinNames.push(s),s}}if(e)return()=>{let s=Number.MAX_SAFE_INTEGER,r=Number.MIN_SAFE_INTEGER,n=[];const a=e().reduce(((e,i)=>{const a=t(i);if(isNaN(a)){if(void 0===e)return i}else if(n.push(a),s=Math.min(a,s),a>r)return r=a,i;return e}),void 0);if(s!==Number.MAX_SAFE_INTEGER&&r!==Number.MIN_SAFE_INTEGER||(s=void 0,r=void 0),!a)return null;n.sort(((e,t)=>e{const t=e-o>1;return o=e,t}));const c=new ot(a);return c.PinId=He.generateGuid(),c.PinName=i(l,s,r),c.PinToolTip=void 0,this.CustomProperties.push(c),c}}}class ht{static same=e=>e;static notWrapped=(e,t)=>t;static bracketsWrapped=(e,t)=>`(${t})`;constructor(e,t=((e,t)=>t),i=",",s=!1,r="=",n=ht.same){this.entityType=e,this.wrap=t,this.attributeSeparator=i,this.trailingSeparator=s,this.attributeValueConjunctionSign=r,this.attributeKeyPrinter=n}read(e){return this.doRead(e.trim())}write(e,t=!1){return this.doWrite(e,t)}doRead(e){const t=Be.grammarFor(void 0,this.entityType).run(e);if(!t.status)throw new Error(this.entityType?`Error when trying to parse the entity ${this.entityType.prototype.constructor.name}`:"Error when trying to parse null");return t.value}doWrite(e,t=!1,i="",s=this.wrap,r=this.attributeSeparator,n=this.trailingSeparator,a=this.attributeValueConjunctionSign,o=this.attributeKeyPrinter){let l="";const c=Ie.getAttributes(e),u=Object.keys(e);let h=!0;for(const s of u){const n=e[s];if(void 0!==n&&this.showProperty(e,s)){let u=e instanceof Array?`(${s})`:s;c[s]?.quoted&&(u=`"${u}"`);const p=le.getAttribute(e,s,"serialized");if(h?h=!1:l+=r,c[s]?.inlined){l+=this.doWrite(n,t,i,ht.notWrapped,r,!1,a,c[s].type instanceof Array?e=>o(`${u}${e}`):e=>o(`${u}.${e}`));continue}const d=o(u),m=r.includes("\n")?i:"";l+=(d.length?m+d+this.attributeValueConjunctionSign:"")+(p?`"${this.doWriteValue(n,!0,i)}"`:this.doWriteValue(n,t,i))}}return n&&l.length&&(l+=r),s(e,l)}doWriteValue(e,t,i=""){const s=he.getType(e),r=Me.getSerializer(s);if(!r)throw new Error(`Unknown value type "${s.name}", a serializer must be registered in the SerializerFactory class, check initializeSerializerFactory.js`);return r.doWrite(e,t,i)}showProperty(e,t){return!(e instanceof Ie&&(le.getAttribute(e,t,"ignored")||le.getAttribute(e,t,"silent")&&he.equals(le.getAttribute(e,t,"default"),e[t])))}}class pt extends ht{constructor(e=ut){super(e,void 0,"\n",!0,void 0,ht.same)}showProperty(e,t){switch(t){case"Class":case"Name":case"Archetype":case"ExportPath":case"CustomProperties":return!1}return super.showProperty(e,t)}write(e,t=!1){return this.doWrite(e,t)+"\n"}doRead(e){return Be.grammarFor(void 0,this.entityType).parse(e)}readMultiple(e){return ut.getMultipleObjectsGrammar().parse(e)}doWrite(e,t,i="",s=this.wrap,r=this.attributeSeparator,n=this.trailingSeparator,a=this.attributeValueConjunctionSign,o=this.attributeKeyPrinter){const l=i+ne.indentation;if(!(e instanceof ut))return super.doWrite(e,t,i,s,r,n,a,(t=>e[t]instanceof ut?"":o(t)));return i+"Begin Object"+(e.Class?.type||e.Class?.path?` Class=${this.doWriteValue(e.Class,t)}`:"")+(e.Name?` Name=${this.doWriteValue(e.Name,t)}`:"")+(e.Archetype?` Archetype=${this.doWriteValue(e.Archetype,t)}`:"")+(e.ExportPath?.type||e.ExportPath?.path?` ExportPath=${this.doWriteValue(e.ExportPath,t)}`:"")+"\n"+super.doWrite(e,t,l,s,r,!0,a,(t=>e[t]instanceof ut?"":o(t)))+e.getCustomproperties().map((e=>l+o("CustomProperties ")+Me.getSerializer(ot).doWrite(e,t)+this.attributeSeparator)).join("")+i+"End Object"}}class dt extends pe{static#A=new pt;#L;constructor(e,t,i={}){i.listenOnFocus??=!0,i.unlistenOnTextEdit??=!0,super(e,t,i);let s=this;this.#L=()=>s.copied()}listenEvents(){window.addEventListener("copy",this.#L)}unlistenEvents(){window.removeEventListener("copy",this.#L)}getSerializedText(){return this.blueprint.getNodes(!0).map((e=>dt.#A.write(e.entity,!1))).join("")}copied(){const e=this.getSerializedText();return navigator.clipboard.writeText(e),e}}class mt extends pe{static#A=new pt;#M;constructor(e,t,i={}){i.listenOnFocus??=!0,i.unlistenOnTextEdit??=!0,super(e,t,i);let s=this;this.#M=()=>s.cut()}listenEvents(){window.addEventListener("cut",this.#M)}unlistenEvents(){window.removeEventListener("cut",this.#M)}getSerializedText(){return this.blueprint.getNodes(!0).map((e=>mt.#A.write(e.entity,!1))).join("")}cut(){this.blueprint.template.getCopyInputObject().copied(),this.blueprint.removeGraphElement(...this.blueprint.getNodes(!0))}}class gt{static#I=new Map;static registerElement(e,t){gt.#I.set(e,t)}static getConstructor(e){return gt.#I.get(e)}}class bt extends pe{static#A=new pt;#B;constructor(e,t,i={}){i.listenOnFocus??=!0,i.unlistenOnTextEdit??=!0,super(e,t,i);let s=this;this.#B=e=>s.pasted(e.clipboardData.getData("Text"))}listenEvents(){window.addEventListener("paste",this.#B)}unlistenEvents(){window.removeEventListener("paste",this.#B)}pasted(e){let t=0,i=0,s=0,r=bt.#A.readMultiple(e).map((e=>{let r=gt.getConstructor("ueb-node").newObject(e);return t+=r.locationY,i+=r.locationX,++s,r}));t/=s,i/=s,r.length>0&&this.blueprint.unselectAll();let n=this.blueprint.mousePosition;return r.forEach((e=>{e.addLocation(n[0]-i,n[1]-t),e.snapToGrid(),e.setSelected(!0)})),this.blueprint.addGraphElement(...r),!0}}class vt extends Ie{static attributes={...super.attributes,ActionName:le.createValue(""),bShift:le.createValue(!1),bCtrl:le.createValue(!1),bAlt:le.createValue(!1),bCmd:le.createValue(!1),Key:le.createType(De)};static grammar=this.createGrammar();static createGrammar(){return Te.alt(De.grammar.map((e=>new this({Key:e}))),Be.createEntityGrammar(this))}constructor(e={}){super(e,!0),this.ActionName,this.bShift,this.bCtrl,this.bAlt,this.bCmd,this.Key}}class yt extends pe{static#$=e=>{};#H;pressedKey="";constructor(e,t,i={},s=yt.#$,r=yt.#$){i.activationKeys??=[],i.consumeEvent??=!0,i.listenOnFocus??=!0,i.unlistenOnTextEdit??=!0,i.activationKeys instanceof Array||(i.activationKeys=[i.activationKeys]),i.activationKeys=i.activationKeys.map((e=>{if(e instanceof vt)return e;if(e.constructor===String){const t=vt.grammar.run(e);if(t.status)return t.value}throw new Error("Unexpected key value")})),super(e,t,i),this.onKeyDown=s,this.onKeyUp=r,this.#H=this.options.activationKeys??[];let n=this;this.keyDownHandler=e=>{n.#H.some((t=>(e=>e.bShift||"LeftShift"==e.Key||"RightShift"==e.Key)(t)==e.shiftKey&&(e=>e.bCtrl||"LeftControl"==e.Key||"RightControl"==e.Key)(t)==e.ctrlKey&&(e=>e.bAlt||"LeftAlt"==e.Key||"RightAlt"==e.Key)(t)==e.altKey&&ne.Keys[t.Key.value]==e.code))&&(this.consumeEvent&&(e.preventDefault(),e.stopImmediatePropagation()),this.pressedKey=e.code,n.fire(),document.removeEventListener("keydown",n.keyDownHandler),document.addEventListener("keyup",n.keyUpHandler))},this.keyUpHandler=e=>{n.#H.some((t=>t.bShift&&"Shift"==e.key||t.bCtrl&&"Control"==e.key||t.bAlt&&"Alt"==e.key||t.bCmd&&"Meta"==e.key||ne.Keys[t.Key.value]==e.code))&&(this.consumeEvent&&e.stopImmediatePropagation(),n.unfire(),this.pressedKey="",document.removeEventListener("keyup",this.keyUpHandler),document.addEventListener("keydown",this.keyDownHandler))}}listenEvents(){document.addEventListener("keydown",this.keyDownHandler)}unlistenEvents(){document.removeEventListener("keydown",this.keyDownHandler)}fire(){this.onKeyDown(this)}unfire(){this.onKeyUp(this)}}class ft extends pe{#V=[0,0];get location(){return this.#V}#G;get enablerKey(){return this.#G}#D=!0;get enablerActivated(){return this.#D}constructor(e,t,i={}){i.ignoreTranslateCompensate??=!1,i.ignoreScale??=!1,i.movementSpace??=t.getGridDOMElement()??document.documentElement,super(e,t,i),this.movementSpace=i.movementSpace,i.enablerKey&&(this.#G=i.enablerKey,this.#G.onKeyDown=()=>this.#D=!0,this.#G.onKeyUp=()=>this.#D=!1,this.#G.consumeEvent=!1,this.#G.listenEvents(),this.#D=!1)}setLocationFromEvent(e){let t=he.convertLocation([e.clientX,e.clientY],this.movementSpace,this.options.ignoreScale);return t=this.options.ignoreTranslateCompensate?t:this.blueprint.compensateTranslation(t[0],t[1]),this.#V=[...t],this.#V}}class wt extends ft{static#$=e=>{};#O=0;get variation(){return this.#O}#R=e=>{this.enablerKey&&!this.enablerActivated||(e.preventDefault(),this.#O=e.deltaY,this.setLocationFromEvent(e),this.wheel())};#z=e=>e.preventDefault();constructor(e,t,i={},s=wt.#$){i.listenOnFocus=!0,i.strictTarget??=!1,super(e,t,i),this.strictTarget=i.strictTarget,this.onWheel=s}listenEvents(){this.movementSpace.addEventListener("wheel",this.#R,!1),this.movementSpace.parentElement?.addEventListener("wheel",this.#z)}unlistenEvents(){this.movementSpace.removeEventListener("wheel",this.#R,!1),this.movementSpace.parentElement?.removeEventListener("wheel",this.#z)}wheel(){this.onWheel(this)}}class St extends wt{#_=0;#F=!1;get enableZoonIn(){return this.#F}set enableZoonIn(e){e!=this.#F&&(this.#F=e)}wheel(){if(this.#_+=-this.variation,Math.abs(this.#_)0||(e+=Math.sign(this.#_),this.blueprint.setZoom(e,this.location),this.#_=0)}}class Et extends yt{#j;constructor(e,t,i={}){i.activationKeys=ae.enableZoomIn,super(e,t,i)}fire(){this.#j=this.blueprint.template.getZoomInputObject(),this.#j.enableZoonIn=!0}unfire(){this.#j.enableZoonIn=!1}}class Ct extends se{#r;get blueprint(){return this.#r}set blueprint(e){this.#r=e}#U;get entity(){return this.#U}set entity(e){this.#U=e}#W;get template(){return this.#W}isInitialized=!1;isSetup=!1;inputObjects=[];initialize(e,t){this.requestUpdate(),this.#U=e,this.#W=t,this.#W.initialize(this),this.isConnected&&this.updateComplete.then((()=>this.setup())),this.isInitialized=!0}connectedCallback(){super.connectedCallback(),this.blueprint=this.closest("ueb-blueprint"),this.isInitialized&&(this.requestUpdate(),this.updateComplete.then((()=>this.setup())))}disconnectedCallback(){super.disconnectedCallback(),this.isSetup&&this.updateComplete.then((()=>this.cleanup())),this.acknowledgeDelete()}createRenderRoot(){return this}setup(){this.template.setup(),this.isSetup=!0}cleanup(){this.template.cleanup(),this.isSetup=!1}willUpdate(e){super.willUpdate(e),this.template.willUpdate(e)}update(e){super.update(e),this.template.update(e)}render(){return this.template.render()}firstUpdated(e){super.firstUpdated(e),this.template.firstUpdated(e),this.template.inputSetup()}updated(e){super.updated(e),this.template.updated(e)}acknowledgeDelete(){let e=new CustomEvent(ne.removeEventName);this.dispatchEvent(e)}isSameGraph(e){return this.blueprint&&this.blueprint==e?.blueprint}}class xt extends Ct{static properties={...super.properties,locationX:{type:Number,attribute:!1},locationY:{type:Number,attribute:!1},sizeX:{type:Number,attribute:!1},sizeY:{type:Number,attribute:!1}};static dragEventName=ne.dragEventName;static dragGeneralEventName=ne.dragGeneralEventName;constructor(){super(),this.locationX=0,this.locationY=0,this.sizeX=0,this.sizeY=0}computeSizes(){const e=this.getBoundingClientRect();this.sizeX=this.blueprint.scaleCorrect(e.width),this.sizeY=this.blueprint.scaleCorrect(e.height)}firstUpdated(e){super.firstUpdated(e),this.computeSizes()}setLocation(e,t,i=!0){const s=e-this.locationX,r=t-this.locationY;if(this.locationX=e,this.locationY=t,this.blueprint&&i){const e=new CustomEvent(this.constructor.dragEventName,{detail:{value:[s,r]},bubbles:!1,cancelable:!0});this.dispatchEvent(e)}}addLocation(e,t,i=!0){this.setLocation(this.locationX+e,this.locationY+t,i)}acknowledgeDrag(e){const t=new CustomEvent(this.constructor.dragGeneralEventName,{detail:{value:e},bubbles:!0,cancelable:!0});this.dispatchEvent(t)}snapToGrid(){const e=he.snapToGrid(this.locationX,this.locationY,ne.gridSize);this.locationX==e[0]&&this.locationY==e[1]||this.setLocation(e[0],e[1])}topBoundary(e=!1){return this.template.topBoundary(e)}rightBoundary(e=!1){return this.template.rightBoundary(e)}bottomBoundary(e=!1){return this.template.bottomBoundary(e)}leftBoundary(e=!1){return this.template.leftBoundary(e)}}class Pt extends ft{#K=e=>{if(this.blueprint.setFocused(!0),e.button===this.options.clickButton)this.options.strictTarget&&e.target!=e.currentTarget||(this.consumeEvent&&e.stopImmediatePropagation(),this.#Y.addEventListener("mousemove",this.#Z),document.addEventListener("mouseup",this.#X),this.setLocationFromEvent(e),this.clickedPosition[0]=this.location[0],this.clickedPosition[1]=this.location[1],this.blueprint.mousePosition[0]=this.location[0],this.blueprint.mousePosition[1]=this.location[1],this.target instanceof xt&&(this.clickedOffset=[this.clickedPosition[0]-this.target.locationX,this.clickedPosition[1]-this.target.locationY]),this.clicked(this.clickedPosition));else this.options.exitAnyButton||this.#X(e)};#Z=e=>{this.consumeEvent&&e.stopImmediatePropagation(),this.#Y.removeEventListener("mousemove",this.#Z),this.#Y.addEventListener("mousemove",this.#q);const t=this.getEvent(ne.trackingMouseEventName.begin);this.#Q=0==this.target.dispatchEvent(t),this.setLocationFromEvent(e),this.lastLocation=he.snapToGrid(this.clickedPosition[0],this.clickedPosition[1],this.stepSize),this.startDrag(this.location),this.started=!0,this.#q(e)};#q=e=>{this.consumeEvent&&e.stopImmediatePropagation();const t=this.setLocationFromEvent(e),i=[e.movementX,e.movementY];if(this.dragTo(t,i),this.#Q&&(this.blueprint.mousePosition=t),this.options.scrollGraphEdge){const e=Math.sqrt(i[0]*i[0]+i[1]*i[1]),s=this.blueprint.scaleCorrect(ne.edgeScrollThreshold),r=this.blueprint.template.gridLeftVisibilityBoundary()+s,n=this.blueprint.template.gridRightVisibilityBoundary()-s;let a=0;t[0]n&&(a=t[0]-n);const o=this.blueprint.template.gridTopVisibilityBoundary()+s,l=this.blueprint.template.gridBottomVisibilityBoundary()-s;let c=0;t[1]l&&(c=t[1]-l),a=he.clamp(this.blueprint.scaleCorrectReverse(a)**3*e*.6,-20,20),c=he.clamp(this.blueprint.scaleCorrectReverse(c)**3*e*.6,-20,20),this.blueprint.scrollDelta(a,c)}};#X=e=>{if(!this.options.exitAnyButton||e.button==this.options.clickButton){if(this.consumeEvent&&e.stopImmediatePropagation(),this.#Y.removeEventListener("mousemove",this.#Z),this.#Y.removeEventListener("mousemove",this.#q),document.removeEventListener("mouseup",this.#X),this.started&&this.endDrag(),this.unclicked(),this.#Q){const e=this.getEvent(ne.trackingMouseEventName.end);this.target.dispatchEvent(e),this.#Q=!1}this.started=!1}};#Q=!1;#Y;#J;clickedOffset=[0,0];clickedPosition=[0,0];lastLocation=[0,0];started=!1;stepSize=1;constructor(e,t,i={}){i.clickButton??=ne.mouseClickButton,i.consumeEvent??=!0,i.draggableElement??=e,i.exitAnyButton??=!0,i.moveEverywhere??=!1,i.movementSpace??=t?.getGridDOMElement(),i.repositionOnClick??=!1,i.scrollGraphEdge??=!1,i.strictTarget??=!1,super(e,t,i),this.stepSize=Number(i.stepSize??ne.gridSize),this.#Y=this.options.moveEverywhere?document.documentElement:this.movementSpace,this.#J=this.options.draggableElement,this.listenEvents()}listenEvents(){super.listenEvents(),this.#J.addEventListener("mousedown",this.#K),this.options.clickButton===ne.mouseRightClickButton&&this.#J.addEventListener("contextmenu",(e=>e.preventDefault()))}unlistenEvents(){super.unlistenEvents(),this.#J.removeEventListener("mousedown",this.#K)}getEvent(e){return new CustomEvent(e,{detail:{tracker:this},bubbles:!0,cancelable:!0})}clicked(e){}startDrag(e){}dragTo(e,t){}endDrag(){}unclicked(e){}}class Nt extends Pt{startDrag(){this.blueprint.scrolling=!0}dragTo(e,t){this.blueprint.scrollDelta(-t[0],-t[1])}endDrag(){this.blueprint.scrolling=!1}}class kt extends ft{#ee=null;#te=e=>{e.preventDefault(),this.setLocationFromEvent(e),this.blueprint.mousePosition=[...this.location]};#ie=e=>{this.#ee||(e.preventDefault(),this.#ee=e.detail.tracker,this.unlistenMouseMove())};#se=e=>{this.#ee==e.detail.tracker&&(e.preventDefault(),this.#ee=null,this.listenMouseMove())};constructor(e,t,i={}){i.listenOnFocus=!0,super(e,t,i)}listenMouseMove(){this.target.addEventListener("mousemove",this.#te)}unlistenMouseMove(){this.target.removeEventListener("mousemove",this.#te)}listenEvents(){this.listenMouseMove(),this.blueprint.addEventListener(ne.trackingMouseEventName.begin,this.#ie),this.blueprint.addEventListener(ne.trackingMouseEventName.end,this.#se)}unlistenEvents(){this.unlistenMouseMove(),this.blueprint.removeEventListener(ne.trackingMouseEventName.begin,this.#ie),this.blueprint.removeEventListener(ne.trackingMouseEventName.end,this.#se)}}class Tt extends Pt{constructor(e,t,i={}){i.scrollGraphEdge??=!0,super(e,t,i),this.selectorElement=this.blueprint.template.selectorElement}startDrag(){this.selectorElement.beginSelect(this.clickedPosition)}dragTo(e,t){this.selectorElement.selectTo(e)}endDrag(){this.started&&this.selectorElement.endSelect()}unclicked(){this.started||this.blueprint.unselectAll()}}class At extends pe{#re=e=>this.clickedSomewhere(e.target);constructor(e,t,i={}){i.listenOnFocus=!0,super(e,t,i),this.blueprint.focus&&document.addEventListener("click",this.#re)}clickedSomewhere(e){e.closest("ueb-blueprint")||this.blueprint.setFocused(!1)}listenEvents(){document.addEventListener("click",this.#re)}unlistenEvents(){document.removeEventListener("click",this.#re)}}class Lt{element;get blueprint(){return this.element.blueprint}#ne=[];get inputObjects(){return this.#ne}initialize(e){this.element=e}createInputObjects(){return[]}setup(){this.#ne.forEach((e=>e.setup()))}cleanup(){this.#ne.forEach((e=>e.cleanup()))}willUpdate(e){}update(e){}render(){return G``}firstUpdated(e){}updated(e){}inputSetup(){this.#ne=this.createInputObjects()}}class Mt extends Lt{static styleVariables={"--ueb-font-size":`${ne.fontSize}`,"--ueb-grid-axis-line-color":`${ne.gridAxisLineColor}`,"--ueb-grid-expand":`${ne.expandGridSize}px`,"--ueb-grid-line-color":`${ne.gridLineColor}`,"--ueb-grid-line-width":`${ne.gridLineWidth}px`,"--ueb-grid-set-line-color":`${ne.gridSetLineColor}`,"--ueb-grid-set":`${ne.gridSet}`,"--ueb-grid-size":`${ne.gridSize}px`,"--ueb-link-min-width":`${ne.linkMinWidth}`,"--ueb-node-radius":`${ne.nodeRadius}px`};#ae=new ResizeObserver((e=>{const t=e.find((e=>e.target===this.viewportElement))?.devicePixelContentBoxSize?.[0];t&&(this.viewportSize[0]=t.inlineSize,this.viewportSize[1]=t.blockSize)}));#oe;#le;#j;headerElement;overlayElement;viewportElement;selectorElement;gridElement;linksContainerElement;nodesContainerElement;viewportSize=[0,0];#ce(){}initialize(e){super.initialize(e),this.element.style.cssText=Object.entries(Mt.styleVariables).map((([e,t])=>`${e}:${t};`)).join("");const t=this.element.querySelector(":scope > template")?.content.textContent;t&&(this.element.requestUpdate(),this.element.updateComplete.then((()=>{this.blueprint.mousePosition=[Math.round(this.viewportSize[0]/2),Math.round(this.viewportSize[1]/2)],this.getPasteInputObject().pasted(t),this.blueprint.unselectAll()})))}setup(){super.setup(),this.#ae.observe(this.viewportElement,{box:"device-pixel-content-box"});const e=this.viewportElement.getBoundingClientRect();this.viewportSize[0]=e.width,this.viewportSize[1]=e.height,this.blueprint.nodes.length>0&&(this.blueprint.requestUpdate(),this.blueprint.updateComplete.then((()=>this.centerContentInViewport())))}cleanup(){super.cleanup(),this.#ae.unobserve(this.viewportElement)}createInputObjects(){const e=this.element.getGridDOMElement();return this.#oe=new dt(e,this.blueprint),this.#le=new bt(e,this.blueprint),this.#j=new St(e,this.blueprint),[...super.createInputObjects(),this.#oe,this.#le,this.#j,new mt(e,this.blueprint),new yt(e,this.blueprint,{activationKeys:ae.duplicateNodes},(()=>this.blueprint.template.getPasteInputObject().pasted(this.blueprint.template.getCopyInputObject().copied()))),new yt(e,this.blueprint,{activationKeys:ae.deleteNodes},(()=>this.blueprint.removeGraphElement(...this.blueprint.getNodes(!0)))),new yt(e,this.blueprint,{activationKeys:ae.selectAllNodes},(()=>this.blueprint.selectAll())),new Tt(e,this.blueprint,{clickButton:ne.mouseClickButton,exitAnyButton:!0,moveEverywhere:!0}),new Nt(e,this.blueprint,{clickButton:ne.mouseRightClickButton,exitAnyButton:!1,moveEverywhere:!0}),new At(e,this.blueprint),new kt(e,this.blueprint),new Et(e,this.blueprint)]}render(){return G`
Zoom ${0==this.blueprint.zoom?"1:1":(this.blueprint.zoom>0?"+":"")+this.blueprint.zoom}
`}firstUpdated(e){super.firstUpdated(e),this.headerElement=this.blueprint.querySelector(".ueb-viewport-header"),this.overlayElement=this.blueprint.querySelector(".ueb-viewport-overlay"),this.viewportElement=this.blueprint.querySelector(".ueb-viewport-body"),this.selectorElement=this.blueprint.querySelector("ueb-selector"),this.gridElement=this.viewportElement.querySelector(".ueb-grid"),this.linksContainerElement=this.blueprint.querySelector("[data-links]"),this.linksContainerElement.append(...this.blueprint.getLinks()),this.nodesContainerElement=this.blueprint.querySelector("[data-nodes]"),this.nodesContainerElement.append(...this.blueprint.getNodes()),this.viewportElement.scroll(ne.expandGridSize,ne.expandGridSize)}willUpdate(e){super.willUpdate(e),this.headerElement&&e.has("zoom")&&(this.headerElement.classList.add("ueb-zoom-changed"),this.headerElement.addEventListener("animationend",(()=>this.headerElement.classList.remove("ueb-zoom-changed"))))}updated(e){if(super.updated(e),(e.has("scrollX")||e.has("scrollY"))&&this.viewportElement.scroll(this.blueprint.scrollX,this.blueprint.scrollY),e.has("zoom")){this.blueprint.style.setProperty("--ueb-scale",this.blueprint.getScale());const t=e.get("zoom"),i=Math.min(t,this.blueprint.zoom),s=Math.max(t,this.blueprint.zoom),r=he.range(i,s),n=e=>`ueb-zoom-${e}`;te<0)).map(n)),this.blueprint.classList.add(...r.filter((e=>e>0)).map(n))):(this.blueprint.classList.remove(...r.filter((e=>e>0)).map(n)),this.blueprint.classList.add(...r.filter((e=>e<0)).map(n)))}}getCommentNodes(e=!1){return this.blueprint.querySelectorAll(`ueb-node[data-type="${ne.paths.comment}"]${e?'[data-selected="true"]':""}, ueb-node[data-type="${ne.paths.materialGraphNodeComment}"]${e?'[data-selected="true"]':""}`)}getPin(e){return this.blueprint.querySelector(`ueb-node[data-title="${e.objectName}"] ueb-pin[data-id="${e.pinGuid}"]`)}getCopyInputObject(){return this.#oe}getPasteInputObject(){return this.#le}getZoomInputObject(){return this.#j}isPointVisible(e,t){return!1}gridTopVisibilityBoundary(){return this.blueprint.scaleCorrect(this.blueprint.scrollY)-this.blueprint.translateY}gridRightVisibilityBoundary(){return this.gridLeftVisibilityBoundary()+this.blueprint.scaleCorrect(this.viewportSize[0])}gridBottomVisibilityBoundary(){return this.gridTopVisibilityBoundary()+this.blueprint.scaleCorrect(this.viewportSize[1])}gridLeftVisibilityBoundary(){return this.blueprint.scaleCorrect(this.blueprint.scrollX)-this.blueprint.translateX}centerViewport(e=0,t=0,i=!0){const s=this.gridLeftVisibilityBoundary()+this.blueprint.scaleCorrect(this.viewportSize[0]/2),r=this.gridTopVisibilityBoundary()+this.blueprint.scaleCorrect(this.viewportSize[1]/2);this.blueprint.scrollDelta(this.blueprint.scaleCorrectReverse(e-s),this.blueprint.scaleCorrectReverse(t-r),i)}centerContentInViewport(e=!0){let t=0,i=0,s=Number.MAX_SAFE_INTEGER,r=Number.MIN_SAFE_INTEGER,n=Number.MAX_SAFE_INTEGER,a=Number.MIN_SAFE_INTEGER;const o=this.blueprint.getNodes();for(const e of o)t+=e.leftBoundary()+e.rightBoundary(),i+=e.topBoundary()+e.bottomBoundary(),s=Math.min(s,e.leftBoundary()),r=Math.max(r,e.rightBoundary()),n=Math.min(n,e.topBoundary()),a=Math.max(a,e.bottomBoundary());t=Math.round(r-s<=this.viewportSize[0]?(r+s)/2:t/(2*o.length)),i=Math.round(a-n<=this.viewportSize[1]?(a+n)/2:i/(2*o.length)),this.centerViewport(t,i,e)}}class It extends Ct{static properties={...super.properties,fromX:{type:Number,attribute:!1},fromY:{type:Number,attribute:!1},toX:{type:Number,attribute:!1},toY:{type:Number,attribute:!1}};constructor(){super(),this.fromX=0,this.fromY=0,this.toX=0,this.toY=0}setBothLocations([e,t]){this.fromX=e,this.fromY=t,this.toX=e,this.toY=t}addSourceLocation(e,t){this.fromX+=e,this.fromY+=t}addDestinationLocation(e,t){this.toX+=e,this.toY+=t}}class Bt extends ut{constructor(e={},t=void 0){e.Class=new Ve(ne.paths.knot),e.Name="K2Node_Knot";const i=new ot({PinName:"InputPin"},!0),s=new ot({PinName:"OutputPin",Direction:"EGPD_Output"},!0);t&&(i.copyTypeFrom(t),s.copyTypeFrom(t)),e.CustomProperties=[i,s],super(e,!0)}}class $t extends ft{static#$=e=>{};#K=e=>{if(this.blueprint.setFocused(!0),!this.enablerKey||this.enablerActivated)if(e.button===this.options.clickButton)this.options.strictTarget&&e.target!==e.currentTarget||(this.consumeEvent&&e.stopImmediatePropagation(),document.addEventListener("mouseup",this.#X),this.setLocationFromEvent(e),this.clickedPosition[0]=this.location[0],this.clickedPosition[1]=this.location[1],this.blueprint.mousePosition[0]=this.location[0],this.blueprint.mousePosition[1]=this.location[1],this.clicked(this.clickedPosition));else this.options.exitAnyButton||this.#X(e)};#X=e=>{this.options.exitAnyButton&&e.button!=this.options.clickButton||(this.consumeEvent&&e.stopImmediatePropagation(),document.removeEventListener("mouseup",this.#X),this.unclicked())};clickedPosition=[0,0];constructor(e,t,i={},s=$t.#$,r=$t.#$){i.clickButton??=ne.mouseClickButton,i.consumeEvent??=!0,i.exitAnyButton??=!0,i.strictTarget??=!1,super(e,t,i),this.onClick=s,this.onUnclick=r,this.listenEvents()}listenEvents(){this.target.addEventListener("mousedown",this.#K),this.options.clickButton===ne.mouseRightClickButton&&this.target.addEventListener("contextmenu",(e=>e.preventDefault()))}unlistenEvents(){this.target.removeEventListener("mousedown",this.#K)}clicked(e){this.onClick(this)}unclicked(e){this.onUnclick(this)}}class Ht extends ft{static ignoreDbClick=e=>{};#ue=e=>{this.options.strictTarget&&e.target!==e.currentTarget||(this.consumeEvent&&e.stopImmediatePropagation(),this.clickedPosition=this.setLocationFromEvent(e),this.blueprint.mousePosition=[...this.clickedPosition],this.dbclicked(this.clickedPosition))};#he;get onDbClick(){return this.#he}set onDbClick(e){this.#he=e}clickedPosition=[0,0];constructor(e,t,i={},s=Ht.ignoreDbClick){i.consumeEvent??=!0,i.strictTarget??=!1,super(e,t,i),this.#he=s,this.listenEvents()}listenEvents(){this.target.addEventListener("dblclick",this.#ue)}unlistenEvents(){this.target.removeEventListener("dblclick",this.#ue)}dbclicked(e){this.onDbClick(e)}}class Vt extends Lt{update(e){super.update(e);const[t,i,s,r]=[Math.round(this.element.fromX),Math.round(this.element.fromY),Math.round(this.element.toX),Math.round(this.element.toY)],[n,a,o,l]=[Math.min(t,s),Math.min(i,r),Math.abs(t-s),Math.abs(i-r)];(e.has("fromX")||e.has("toX"))&&(this.element.style.left=`${n}px`,this.element.style.width=`${o}px`),(e.has("fromY")||e.has("toY"))&&(this.element.style.top=`${a}px`,this.element.style.height=`${l}px`)}}class Gt extends Vt{static decreasingValue(e,t){const i=-e*t[0]**2,s=t[1]-i/t[0];return e=>i/e+s}static clampedLine(e,t){if(e[0]>t[0]){const i=e;e=t,t=i}const i=(t[1]-e[1])/(t[0]-e[0]),s=e[1]-i*e[0];return r=>rt[0]?t[1]:i*r+s}static c1DecreasingValue=Gt.decreasingValue(-.15,[100,15]);static c2DecreasingValue=Gt.decreasingValue(-.05,[500,130]);static c2Clamped=Gt.clampedLine([0,80],[200,40]);#pe=`ueb-id-${Math.floor(1e12*Math.random())}`;#de=e=>{const t=new Bt({},this.element.source.entity),i=gt.getConstructor("ueb-node").newObject(t);i.setLocation(...this.blueprint.snapToGrid(...e));const s=i.template;this.blueprint.addGraphElement(i);const r=this.element.getInputPin(),n=this.element.getOutputPin();this.element.source=null,this.element.destination=null;const a=gt.getConstructor("ueb-link").newObject(n,s.inputPin);this.blueprint.addGraphElement(a),this.element.source=s.outputPin,this.element.destination=r};createInputObjects(){const e=this.element.querySelector(".ueb-link-area");return[...super.createInputObjects(),new Ht(e,this.blueprint,void 0,(e=>{e[0]+=ne.knotOffset[0],e[1]+=ne.knotOffset[1],e=he.snapToGrid(e[0],e[1],ne.gridSize),this.#de(e)})),new $t(e,this.blueprint,{enablerKey:new yt(this.blueprint,this.blueprint,{activationKeys:ae.enableLinkDelete})},(()=>this.blueprint.removeGraphElement(this.element)))]}willUpdate(e){super.willUpdate(e);const t=this.element.source,i=this.element.destination;if(e.has("fromX")||e.has("toX")){const e=this.element.fromX,s=this.element.toX,r=t?.nodeElement.getType()==ne.paths.knot,n=i?.nodeElement.getType()==ne.paths.knot;!r||i&&!n||(t?.isInput()&&s>e+ne.distanceThreshold?this.element.source=t.nodeElement.template.outputPin:t?.isOutput()&&se+ne.distanceThreshold&&(this.element.destination=i.nodeElement.template.inputPin))}const s=Math.max(Math.abs(this.element.fromX-this.element.toX),1),r=Math.max(Math.abs(this.element.fromY-this.element.toY),1),n=Math.max(s,ne.linkMinWidth),a=s/n,o=this.element.originatesFromInput?this.element.fromXthis.element.toY?1:0)),this.element.style.setProperty("--ueb-start-percentage",`${Math.round(this.element.startPercentage)}%`),this.element.style.setProperty("--ueb-link-start",`${Math.round(this.element.startPixels)}`)}render(){return G` ${this.element.linkMessageIcon||this.element.linkMessageText?G``:O}`}}class Dt extends It{static properties={...super.properties,dragging:{type:Boolean,attribute:"data-dragging",converter:he.booleanConverter,reflect:!0},originatesFromInput:{type:Boolean,attribute:!1},svgPathD:{type:String,attribute:!1},linkMessageIcon:{type:String,attribute:!1},linkMessageText:{type:String,attribute:!1}};#me;get source(){return this.#me}set source(e){this.#ge(e,!1)}#be;get destination(){return this.#be}set destination(e){this.#ge(e,!0)}#ve=()=>this.remove();#ye=e=>this.addSourceLocation(...e.detail.value);#fe=e=>this.addDestinationLocation(...e.detail.value);#we=e=>this.setSourceLocation();#Se=e=>this.setDestinationLocation();linkMessageIcon=O;linkMessageText=O;pathElement;constructor(){super(),this.dragging=!1,this.originatesFromInput=!1,this.startPercentage=0,this.svgPathD="",this.startPixels=0}static newObject(e,t){const i=new Dt;return i.initialize(e,t),i}initialize(e,t){super.initialize({},new Gt),e&&(this.source=e,t||(this.toX=this.fromX,this.toY=this.fromY)),t&&(this.destination=t,e||(this.fromX=this.toX,this.fromY=this.toY))}#ge(e,t){const i=()=>t?this.destination:this.source;if(i()!=e){if(i()){const e=i().getNodeElement();e.removeEventListener(ne.removeEventName,this.#ve),e.removeEventListener(ne.nodeDragEventName,t?this.#fe:this.#ye),e.removeEventListener(ne.nodeReflowEventName,t?this.#Se:this.#we),this.#Ee()}if(t?this.#be=e:this.#me=e,i()){const e=i().getNodeElement();e.addEventListener(ne.removeEventName,this.#ve),e.addEventListener(ne.nodeDragEventName,t?this.#fe:this.#ye),e.addEventListener(ne.nodeReflowEventName,t?this.#Se:this.#we),t?this.setDestinationLocation():(this.setSourceLocation(),this.originatesFromInput=this.source.isInput()),this.#Ce()}}}#Ce(){this.source&&this.destination&&(this.source.linkTo(this.destination),this.destination.linkTo(this.source))}#Ee(){this.source&&this.destination&&(this.source.unlinkFrom(this.destination,!1),this.destination.unlinkFrom(this.source,!1))}cleanup(){super.cleanup(),this.#Ee(),this.source=null,this.destination=null}setSourceLocation(e=null,t=!0){if(null==e){const i=this;if(t&&(!this.hasUpdated||!this.source.hasUpdated))return void Promise.all([this.updateComplete,this.source.updateComplete]).then((()=>i.setSourceLocation(null,!1)));e=this.source.template.getLinkLocation()}const[i,s]=e;this.fromX=i,this.fromY=s}setDestinationLocation(e=null,t=!0){if(null==e){const i=this;if(t&&(!this.hasUpdated||!this.destination.hasUpdated))return void Promise.all([this.updateComplete,this.destination.updateComplete]).then((()=>i.setDestinationLocation(null,!1)));e=this.destination.template.getLinkLocation()}this.toX=e[0],this.toY=e[1]}getInputPin(){return this.source?.isInput()?this.source:this.destination}setInputPin(e){this.source?.isInput()&&(this.source=e),this.destination=e}getOutputPin(){return this.destination?.isOutput()?this.destination:this.source}setOutputPin(e){this.destination?.isOutput()&&(this.destination=e),this.source=e}startDragging(){this.dragging=!0}finishDragging(){this.dragging=!1}removeMessage(){this.linkMessageIcon=O,this.linkMessageText=O}setMessageConvertType(){this.linkMessageIcon=Ae.convert,this.linkMessageText=G`Convert ${this.source.pinType} to ${this.destination.pinType}.`}setMessageCorrect(){this.linkMessageIcon=Ae.correct,this.linkMessageText=O}setMessageReplace(){this.linkMessageIcon=Ae.correct,this.linkMessageText=O}setMessageDirectionsIncompatible(){this.linkMessageIcon=Ae.reject,this.linkMessageText=G`Directions are not compatbile.`}setMessagePlaceNode(){this.linkMessageIcon=O,this.linkMessageText=G`Place a new node.`}setMessageReplaceLink(){this.linkMessageIcon=Ae.correct,this.linkMessageText=G`Replace existing input connections.`}setMessageReplaceOutputLink(){this.linkMessageIcon=Ae.correct,this.linkMessageText=G`Replace existing output connections.`}setMessageSameNode(){this.linkMessageIcon=Ae.reject,this.linkMessageText=G`Both are on the same node.`}setMessageTypesIncompatible(e,t){this.linkMessageIcon=Ae.reject,this.linkMessageText=G`${he.capitalFirstLetter(e.pinType)} is not compatible with ${he.capitalFirstLetter(t.pinType)}.`}}class Ot extends Pt{clicked(e){this.options.repositionOnClick&&(this.target.setLocation(...this.stepSize>1?he.snapToGrid(e[0],e[1],this.stepSize):e),this.clickedOffset=[0,0])}dragTo(e,t){const i=[this.target.locationX??this.lastLocation[0],this.target.locationY??this.lastLocation[1]],[s,r]=this.stepSize>1?[he.snapToGrid(e[0],e[1],this.stepSize),he.snapToGrid(i[0],i[1],this.stepSize)]:[e,i];0==(t=[s[0]-this.lastLocation[0],s[1]-this.lastLocation[1]])[0]&&0==t[1]||(t[0]+=r[0]-i[0],t[1]+=r[1]-i[1],this.dragAction(s,t),this.lastLocation=s)}dragAction(e,t){this.target.setLocation(e[0]-this.clickedOffset[0],e[1]-this.clickedOffset[1])}}class Rt extends Ot{#xe;#Pe;#Ne;#ke;constructor(e,t,i={}){super(e,t,i),i.onClicked&&(this.#xe=i.onClicked),i.onStartDrag&&(this.#Pe=i.onStartDrag),i.onDrag&&(this.#Ne=i.onDrag),i.onEndDrag&&(this.#ke=i.onEndDrag)}clicked(e){super.clicked(e),this.#xe?.()}startDrag(){super.startDrag(),this.#Pe?.()}dragAction(e,t){this.#Ne?.(e,t)}endDrag(){super.endDrag(),this.#ke?.()}}class zt extends Ot{startDrag(){this.target.selected||(this.blueprint.unselectAll(),this.target.setSelected(!0))}dragAction(e,t){this.target.acknowledgeDrag(t)}unclicked(){this.started?(this.blueprint.getNodes(!0).forEach((e=>e.boundComments.filter((t=>!e.isInsideComment(t))).forEach((t=>e.unbindFromComment(t))))),this.blueprint.getCommentNodes().forEach((e=>e.template.manageNodesBind()))):(this.blueprint.unselectAll(),this.target.setSelected(!0))}}class _t extends Lt{getDraggableElement(){return this.element}createDraggableObject(){return new Ot(this.element,this.blueprint,{draggableElement:this.getDraggableElement()})}createInputObjects(){return[...super.createInputObjects(),this.createDraggableObject(),new yt(this.element,this.blueprint,{activationKeys:[ne.Keys.ArrowUp,ne.Keys.ArrowRight,ne.Keys.ArrowDown,ne.Keys.ArrowLeft]},(e=>e.target.acknowledgeDrag([e.pressedKey===ne.Keys.ArrowLeft?-ne.gridSize:e.pressedKey===ne.Keys.ArrowRight?ne.gridSize:0,e.pressedKey===ne.Keys.ArrowUp?-ne.gridSize:e.pressedKey===ne.Keys.ArrowDown?ne.gridSize:0])))]}topBoundary(e=!1){return this.element.locationY}rightBoundary(e=!1){return this.element.locationX+this.element.sizeX}bottomBoundary(e=!1){return this.element.locationY+this.element.sizeY}leftBoundary(e=!1){return this.element.locationX}centerInViewport(){const e=Math.min(this.blueprint.template.viewportSize[0]/10,this.blueprint.template.viewportSize[1]/10),t=this.leftBoundary()-this.blueprint.template.gridLeftVisibilityBoundary(),i=this.blueprint.template.gridRightVisibilityBoundary()-this.rightBoundary();let s=Math.max((t+i)/2,e);const r=this.topBoundary()-this.blueprint.template.gridTopVisibilityBoundary(),n=this.blueprint.template.gridBottomVisibilityBoundary()-this.bottomBoundary();let a=Math.max((r+n)/2,e);this.blueprint.scrollDelta(t-s,r-a,!0)}}class Ft extends _t{update(e){super.update(e),e.has("locationX")&&(this.element.style.left=`${this.element.locationX}px`),e.has("locationY")&&(this.element.style.top=`${this.element.locationY}px`)}}class jt extends Ft{getDraggableElement(){return this.element}createDraggableObject(){return new zt(this.element,this.blueprint,{draggableElement:this.getDraggableElement(),scrollGraphEdge:!0})}firstUpdated(e){super.firstUpdated(e),this.element.selected&&!this.element.listeningDrag&&this.element.setSelected(!0)}}class Ut extends jt{static nodeStyleClasses=["ueb-node-style-default"];#Te=!1;pinInserter;inputContainer;outputContainer;pinElement;addPinHandler=()=>{const e=this.pinInserter?.();e&&(this.defaultPin&&this.defaultPin.isInput()===e.isInput()?this.defaultPin.before(this.createPinElement(e)):(e.isInput()?this.inputContainer:this.outputContainer).appendChild(this.createPinElement(e)),this.element.acknowledgeReflow())};toggleAdvancedDisplayHandler=()=>{this.element.toggleShowAdvancedPinDisplay(),this.element.requestUpdate(),this.element.updateComplete.then((()=>this.element.acknowledgeReflow()))};createPinElement(e){const t=gt.getConstructor("ueb-pin").newObject(e,void 0,this.element);return this.pinInserter&&!this.defaultPin&&"Default"===t.getPinName()&&(this.defaultPin=t,this.defaultPin.classList.add("ueb-node-variadic-default")),t}initialize(e){super.initialize(e),this.element.classList.add(...this.constructor.nodeStyleClasses),this.element.style.setProperty("--ueb-node-color",this.getColor().cssText),this.pinInserter=this.element.entity.additionalPinInserter(),this.pinInserter&&this.element.classList.add("ueb-node-is-variadic")}getColor(){return this.element.entity.nodeColor()}render(){return G`
${this.renderTop()}
${this.pinInserter?G`
Add pin ${Ae.plusCircle}
`:O} ${this.element.entity.isDevelopmentOnly()?G`
Development Only
`:O} ${this.element.advancedPinDisplay?G`
${Ae.expandIcon}
`:O}
`}renderNodeIcon(){return this.element.entity.nodeIcon()}renderNodeName(){return this.element.nodeDisplayName}renderTop(){const e=this.renderNodeIcon(),t=this.renderNodeName();return G`
${e?G`
${e}
`:O} ${t?G`
${t} ${this.#Te&&this.getTargetType().length>0?G`
Target is ${he.formatStringName(this.getTargetType())}
`:O}
`:O}
`}firstUpdated(e){super.firstUpdated(e),this.inputContainer=this.element.querySelector(".ueb-node-inputs"),this.outputContainer=this.element.querySelector(".ueb-node-outputs"),this.setupPins(),this.element.updateComplete.then((()=>this.element.acknowledgeReflow()))}setupPins(){this.element.nodeNameElement=this.element.querySelector(".ueb-node-name-text");let e=!1,t=!1;for(const i of this.element.getPinElements())i!==this.defaultPin&&(i.isInput()?(this.inputContainer.appendChild(i),e=!0):i.isOutput()&&(this.outputContainer.appendChild(i),t=!0));this.defaultPin&&(this.defaultPin.isInput()?this.inputContainer:this.outputContainer).appendChild(this.defaultPin),e&&this.element.classList.add("ueb-node-has-inputs"),t&&this.element.classList.add("ueb-node-has-outputs")}createPinElements(){return this.element.getPinEntities().filter((e=>!e.isHidden())).map((e=>(this.#Te=this.#Te||"self"===e.PinName&&"Target"===e.pinDisplayName(),this.createPinElement(e))))}getTargetType(){return this.element.entity.FunctionReference?.MemberParent?.getName()??"Untitled"}getPinElements(e){return e.querySelectorAll("ueb-pin")}linksChanged(){}}class Wt extends Ut{#Ae=document.createElement("div");#Le=document.createElement("div");#Me=document.createElement("div");#Ie=document.createElement("div");#Be=document.createElement("div");#$e=document.createElement("div");#He=document.createElement("div");#Ve=document.createElement("div");initialize(e){super.initialize(e),this.element.classList.add("ueb-resizeable"),this.#Ae.classList.add("ueb-resizeable-top"),this.#Le.classList.add("ueb-resizeable-right"),this.#Me.classList.add("ueb-resizeable-bottom"),this.#Ie.classList.add("ueb-resizeable-left"),this.#Be.classList.add("ueb-resizeable-top-right"),this.#$e.classList.add("ueb-resizeable-bottom-right"),this.#He.classList.add("ueb-resizeable-bottom-left"),this.#Ve.classList.add("ueb-resizeable-top-left")}update(e){super.update(e),this.element.sizeX>=0&&e.has("sizeX")&&(this.element.style.width=`${this.element.sizeX}px`),this.element.sizeY>=0&&e.has("sizeY")&&(this.element.style.height=`${this.element.sizeY}px`)}firstUpdated(e){super.firstUpdated(e),this.element.append(this.#Ae,this.#Le,this.#Me,this.#Ie,this.#Be,this.#$e,this.#He,this.#Ve)}createInputObjects(){return[...super.createInputObjects(),new Rt(this.#Ae,this.blueprint,{onDrag:(e,t)=>{t[1]=e[1]-this.element.topBoundary(),this.setSizeY(this.element.sizeY-t[1])&&this.element.addLocation(0,t[1],!1)},onEndDrag:()=>this.endResize()}),new Rt(this.#Le,this.blueprint,{onDrag:(e,t)=>{t[0]=e[0]-this.element.rightBoundary(),this.setSizeX(this.element.sizeX+t[0])},onEndDrag:()=>this.endResize()}),new Rt(this.#Me,this.blueprint,{onDrag:(e,t)=>{t[1]=e[1]-this.element.bottomBoundary(),this.setSizeY(this.element.sizeY+t[1])},onEndDrag:()=>this.endResize()}),new Rt(this.#Ie,this.blueprint,{onDrag:(e,t)=>{t[0]=e[0]-this.element.leftBoundary(),this.setSizeX(this.element.sizeX-t[0])&&this.element.addLocation(t[0],0,!1)},onEndDrag:()=>this.endResize()}),new Rt(this.#Be,this.blueprint,{onDrag:(e,t)=>{t[0]=e[0]-this.element.rightBoundary(),t[1]=e[1]-this.element.topBoundary(),this.setSizeX(this.element.sizeX+t[0]),this.setSizeY(this.element.sizeY-t[1])&&this.element.addLocation(0,t[1],!1)},onEndDrag:()=>this.endResize()}),new Rt(this.#$e,this.blueprint,{onDrag:(e,t)=>{t[0]=e[0]-this.element.rightBoundary(),t[1]=e[1]-this.element.bottomBoundary(),this.setSizeX(this.element.sizeX+t[0]),this.setSizeY(this.element.sizeY+t[1])},onEndDrag:()=>this.endResize()}),new Rt(this.#He,this.blueprint,{onDrag:(e,t)=>{t[0]=e[0]-this.element.leftBoundary(),t[1]=e[1]-this.element.bottomBoundary(),this.setSizeX(this.element.sizeX-t[0])&&this.element.addLocation(t[0],0,!1),this.setSizeY(this.element.sizeY+t[1])},onEndDrag:()=>this.endResize()}),new Rt(this.#Ve,this.blueprint,{onDrag:(e,t)=>{t[0]=e[0]-this.element.leftBoundary(),t[1]=e[1]-this.element.topBoundary(),this.setSizeX(this.element.sizeX-t[0])&&this.element.addLocation(t[0],0,!1),this.setSizeY(this.element.sizeY-t[1])&&this.element.addLocation(0,t[1],!1)},onEndDrag:()=>this.endResize()})]}setSizeX(e){return this.element.setNodeWidth(e),!0}setSizeY(e){return this.element.setNodeHeight(e),!0}endResize(){}}class Kt extends Wt{#Ge=0;initialize(e){super.initialize(e),e.classList.add("ueb-node-style-comment","ueb-node-resizeable"),e.sizeX=25*ne.gridSize,e.sizeY=6*ne.gridSize,super.initialize(e)}getDraggableElement(){return this.element.querySelector(".ueb-node-top")}render(){return G`
`}firstUpdated(e){super.firstUpdated(e);const t=this.getDraggableElement().getBoundingClientRect();this.#Ge=t.height}manageNodesBind(){let e=this.blueprint.getNodes();for(let t of e)t.topBoundary()>=this.element.topBoundary()&&t.rightBoundary()<=this.element.rightBoundary()&&t.bottomBoundary()<=this.element.bottomBoundary()&&t.leftBoundary()>=this.element.leftBoundary()?t.bindToComment(this.element):t.unbindFromComment(this.element)}setSizeX(e){return(e=Math.round(e))>=2*ne.gridSize&&(this.element.setNodeWidth(e),!0)}setSizeY(e){return(e=Math.round(e))>=2*ne.gridSize&&(this.element.setNodeHeight(e),!0)}endResize(){this.manageNodesBind()}topBoundary(e=!1){return this.element.locationY}rightBoundary(e=!1){return this.element.locationX+this.element.sizeX}bottomBoundary(e=!1){return e?this.element.locationY+this.#Ge:super.bottomBoundary()}leftBoundary(e=!1){return this.element.locationX}}class Yt extends Pt{#De;#Oe=null;#Re=e=>{if(!this.enteredPin){this.linkValid=!1,this.enteredPin=e.target;const t=this.link.source??this.target,i=this.enteredPin,s=t.isOutput()?t:i;t.nodeElement.getType()===ne.paths.knot||i.nodeElement.getType()===ne.paths.knot?(this.link.setMessageCorrect(),this.linkValid=!0):t.getNodeElement()===i.getNodeElement()?this.link.setMessageSameNode():t.isOutput()===i.isOutput()?this.link.setMessageDirectionsIncompatible():this.blueprint.getLinks(t,i).length?(this.link.setMessageReplaceLink(),this.linkValid=!0):"exec"===s.entity.getType()&&s.isLinked?(this.link.setMessageReplaceOutputLink(),this.linkValid=!0):"object"==t.entity.PinType.PinCategory&&"object"==i.entity.PinType.PinCategory||t.pinType==i.pinType?(this.link.setMessageCorrect(),this.linkValid=!0):(this.link.setMessageTypesIncompatible(t,i),this.linkValid=!1)}};#ze=e=>{this.enteredPin==e.target&&(this.enteredPin=null,this.linkValid=!1,this.link?.setMessagePlaceNode())};link;enteredPin;linkValid=!1;constructor(e,t,i={}){i.scrollGraphEdge??=!0,super(e,t,i)}startDrag(e){this.target.nodeElement.getType()==ne.paths.knot&&(this.#Oe=this.target),this.link=gt.getConstructor("ueb-link").newObject(this.target,null),this.blueprint.template.linksContainerElement.prepend(this.link),this.link.setMessagePlaceNode(),this.#De=this.blueprint.querySelectorAll("ueb-pin"),this.#De.forEach((e=>{e!=this.target&&(e.addEventListener("mouseenter",this.#Re),e.addEventListener("mouseleave",this.#ze))})),this.link.startDragging(),this.link.setDestinationLocation(e)}dragTo(e,t){this.link.setDestinationLocation(e)}endDrag(){if(this.#De.forEach((e=>{e.removeEventListener("mouseenter",this.#Re),e.removeEventListener("mouseleave",this.#ze)})),this.#De=null,this.enteredPin&&this.linkValid){if(this.#Oe){const e=this.#Oe!==this.link.source?this.link.source:this.enteredPin;if(this.#Oe.isInput()&&e.isInput()||this.#Oe.isOutput()&&e.isOutput()){const e=this.#Oe.template.getOppositePin();this.#Oe===this.link.source?this.link.source=e:this.enteredPin=e}}else this.enteredPin.nodeElement.getType()===ne.paths.knot&&(this.enteredPin=this.enteredPin.template.getOppositePin());this.link.source.getLinks().find((e=>e.equals(this.enteredPin.createPinReference())))?this.link.remove():(this.blueprint.addGraphElement(this.link),this.link.destination=this.enteredPin)}else this.link.remove();this.enteredPin=null,this.link.removeMessage(),this.link.finishDragging(),this.link=null}}class Zt extends Ut{#_e=!1;#Fe=!1;#je="";static nodeStyleClasses=["ueb-node-style-glass"];initialize(e){super.initialize(e),this.#je=this.element.nodeDisplayName}render(){return G`
${this.#je?G`
${this.#je}
`:O} ${this.#_e?G`
`:O} ${this.#Fe?G`
`:O} ${this.pinInserter?G`
Add pin ${Ae.plusCircle}
`:O}
`}createPinElements(){return this.element.getPinEntities().filter((e=>!e.isHidden())).map((e=>{this.#_e||=e.isInput(),this.#Fe||=e.isOutput();return gt.getConstructor("ueb-pin").newObject(e,void 0,this.element)}))}}class Xt extends Zt{static nodeStyleClasses=[...super.nodeStyleClasses,"ueb-node-style-conversion"]}class qt extends Zt{static nodeStyleClasses=[...super.nodeStyleClasses,"ueb-node-style-operation"]}class Qt extends Lt{static canWrapInput=!0;#Ue;get iconElement(){return this.#Ue}#We;get wrapperElement(){return this.#We}isNameRendered=!0;initialize(e){if(super.initialize(e),this.element.nodeElement){const e=this.element.nodeElement.template;this.isNameRendered=!(e instanceof Xt||e instanceof qt)}}setup(){super.setup(),this.element.nodeElement=this.element.closest("ueb-node");const e=this.element.nodeElement.template;(e instanceof Xt||e instanceof qt)&&(this.isNameRendered=!1,this.element.requestUpdate())}createInputObjects(){return[new Yt(this.element,this.blueprint,{moveEverywhere:!0,draggableElement:this.getClickableElement()})]}render(){const e=G`
${this.renderIcon()}
`,t=G`
${this.isNameRendered?this.renderName():O} ${this.isInputRendered()?this.renderInput():G``}
`;return G`
${this.element.isInput()?G`${e}${t}`:G`${t}${e}`}
`}renderIcon(){if(this.element.nodeElement.entity.isPcg())switch(this.element.entity.getType()){case"Any":return Ae.pcgPin;case"Param":case"Param[]":return Ae.pcgParamPin;case"Spatial":case"Spatial[]":return Ae.pcgSpatialPin;case"Any[]":case"Point[]":case"Surface[]":case"Volume[]":if(this.element.isOutput())return Ae.pcgPin;case"Point":case"Surface":case"Volume":return Ae.pcgStackPin}switch(this.element.entity.PinType?.ContainerType?.toString()){case"Array":return Ae.arrayPin;case"Set":return Ae.setPin;case"Map":return Ae.mapPin}return"delegate"===this.element.entity.PinType?.PinCategory?.toLocaleLowerCase()?Ae.delegate:this.element.nodeElement?.template instanceof qt?Ae.operationPin:Ae.genericPin}renderName(){let e=this.element.getPinDisplayName();const t=this.element.nodeElement,i=this.element.getPinName();return t.getType()==ne.paths.makeStruct&&i==t.entity.StructType.getName()&&(e=i),G`${e}`}isInputRendered(){return this.element.isInput()&&!this.element.entity.bDefaultValueIsIgnored&&!this.element.entity.PinType.bIsReference}renderInput(){return G``}updated(e){if(super.updated(e),this.element.isInput()&&e.has("isLinked")){const e=this.element.nodeElement;this.element.requestUpdate(),this.element.updateComplete.then((()=>e.acknowledgeReflow()))}}firstUpdated(e){super.firstUpdated(e),this.element.style.setProperty("--ueb-pin-color-rgb",this.element.entity.pinColor().cssText),this.#Ue=this.element.querySelector(".ueb-pin-icon svg")??this.element,this.#We=this.element.querySelector(".ueb-pin-wrapper")}getLinkLocation(){const e=this.iconElement.getBoundingClientRect(),t=[this.element.isInput()?e.left:e.right+1,(e.top+e.bottom)/2],i=he.convertLocation(t,this.blueprint.template.gridElement);return this.blueprint.compensateTranslation(i[0],i[1])}getClickableElement(){return this.#We??this.element}}class Jt extends Qt{render(){return G`
${this.renderIcon()}
`}}class ei extends Ut{static nodeStyleClasses=[...super.nodeStyleClasses,"ueb-node-style-event"];firstUpdated(e){super.firstUpdated(e),this.element.querySelector(".ueb-node-top").appendChild(this.createDelegatePinElement())}renderTop(){const e=this.renderNodeIcon(),t=this.renderNodeName(),i=this.element.getType()===ne.paths.customEvent&&(this.element.entity.CustomFunctionName||this.element.entity.FunctionReference.MemberParent);return G`
${e?G`
${e}
`:O} ${t?G`
${t} ${i?G`
Custom Event
`:O}
`:O}
`}createDelegatePinElement(){const e=gt.getConstructor("ueb-pin").newObject(this.element.getPinEntities().find((e=>!e.isHidden()&&"delegate"===e.PinType.PinCategory)),new Jt,this.element);return e.template.isNameRendered=!1,e}createPinElements(){return this.element.getPinEntities().filter((e=>!e.isHidden()&&"delegate"!==e.PinType.PinCategory)).map((e=>gt.getConstructor("ueb-pin").newObject(e,void 0,this.element)))}}class ti extends Jt{render(){return this.element.isOutput()?super.render():G``}getOppositePin(){const e=this.element.nodeElement.template;return this.element.isOutput()?e.inputPin:e.outputPin}getLinkLocation(){const e=(this.element.isInput()?this.element.nodeElement.template.outputPin.template:this).iconElement.getBoundingClientRect(),t=[this.element.isInput()?e.left:e.right+1,(e.top+e.bottom)/2],i=he.convertLocation(t,this.blueprint.template.gridElement);return this.blueprint.compensateTranslation(i[0],i[1])}}class ii extends Ut{static#Ke=new Set;#Ye=null;#Ze;get inputPin(){return this.#Ze}#Xe;get outputPin(){return this.#Xe}initialize(e){super.initialize(e),this.element.classList.add("ueb-node-style-minimal")}findDirectionaPin(e){if(e.nodeElement.getType()!==ne.paths.knot||ii.#Ke.has(e))return ii.#Ke.clear(),!0;ii.#Ke.add(e);for(let t of e.getLinks().map((e=>this.blueprint.getPin(e))))if(this.findDirectionaPin(t))return!0;return!1}render(){return G`
`}setupPins(){this.element.getPinElements().forEach((e=>this.element.querySelector(".ueb-node-border").appendChild(e)))}getPinElements(e){return e.querySelectorAll("ueb-pin")}createPinElements(){const e=this.element.getPinEntities().filter((e=>!e.isHidden())),t=e[e[0].isInput()?0:1],i=e[e[0].isOutput()?0:1],s=gt.getConstructor("ueb-pin");return[this.#Ze=s.newObject(t,new ti,this.element),this.#Xe=s.newObject(i,new ti,this.element)]}linksChanged(){}}class si extends Zt{initialize(e){super.initialize(e),e.getType()===ne.paths.variableGet?this.element.classList.add("ueb-node-style-getter"):e.getType()===ne.paths.variableSet&&this.element.classList.add("ueb-node-style-setter")}setupPins(){super.setupPins();let e=this.element.getPinElements().find((e=>!e.entity.isHidden()&&!e.entity.isExecution()));this.element.style.setProperty("--ueb-node-color",e.getColor().cssText)}}class ri extends xt{static properties={...super.properties,selected:{type:Boolean,attribute:"data-selected",reflect:!0,converter:he.booleanConverter}};dragHandler=e=>this.addLocation(...e.detail.value);constructor(){super(),this.selected=!1,this.listeningDrag=!1}setup(){super.setup(),this.setSelected(this.selected)}cleanup(){super.cleanup(),this.blueprint.removeEventListener(ne.nodeDragGeneralEventName,this.dragHandler)}setSelected(e=!0){this.selected=e,this.blueprint&&(this.selected?(this.listeningDrag=!0,this.blueprint.addEventListener(ne.nodeDragGeneralEventName,this.dragHandler)):(this.blueprint.removeEventListener(ne.nodeDragGeneralEventName,this.dragHandler),this.listeningDrag=!1))}}class ni extends ri{static properties={...ri.properties,typePath:{type:String,attribute:"data-type",reflect:!0},nodeTitle:{type:String,attribute:"data-title",reflect:!0},advancedPinDisplay:{type:String,attribute:"data-advanced-display",converter:De.attributeConverter,reflect:!0},enabledState:{type:String,attribute:"data-enabled-state",reflect:!0},nodeDisplayName:{type:String,attribute:!1},pureFunction:{type:Boolean,converter:he.booleanConverter,attribute:"data-pure-function",reflect:!0}};static dragEventName=ne.nodeDragEventName;static dragGeneralEventName=ne.nodeDragGeneralEventName;get blueprint(){return super.blueprint}set blueprint(e){super.blueprint=e,this.#qe.forEach((t=>t.blueprint=e))}#Qe;get nodeNameElement(){return this.#Qe}set nodeNameElement(e){this.#Qe=e}#qe=[];boundComments=[];#Je=!1;#et=e=>{this.selected||this.#Je||(this.#Je=!0,this.requestUpdate(),this.updateComplete.then((()=>this.#Je=!1)),this.addLocation(...e.detail.value))};static getTypeTemplate(e){if(e.getClass()===ne.paths.callFunction||e.getClass()===ne.paths.commutativeAssociativeBinaryOperator||e.getClass()===ne.paths.callArrayFunction){const t=e.FunctionReference?.MemberParent?.path??"",i=e.FunctionReference?.MemberName;if(i&&(t===ne.paths.kismetMathLibrary||t===ne.paths.kismetArrayLibrary)){if(i.startsWith("Conv_"))return Xt;if(i.startsWith("And_")||i.startsWith("Boolean")||i.startsWith("Cross_")||i.startsWith("Dot_")||i.startsWith("Not_")||i.startsWith("Or_")||i.startsWith("Percent_")||i.startsWith("Xor_"))return qt;switch(i){case"Abs":case"Array_Add":case"Array_AddUnique":case"Array_Identical":case"BMax":case"BMin":case"CrossProduct2D":case"DotProduct2D":case"Exp":case"FMax":case"FMin":case"GetPI":case"Max":case"MaxInt64":case"Min":case"MinInt64":case"Sqrt":case"Square":case"Vector4_CrossProduct3":case"Vector4_DotProduct":case"Vector4_DotProduct3":case"Acos":case"Asin":case"Cos":case"DegAcos":case"DegCos":case"DegSin":case"DegTan":case"Sin":case"Tan":return qt}}if(t===ne.paths.blueprintSetLibrary)return qt;if(t===ne.paths.blueprintMapLibrary)return qt}switch(e.getClass()){case ne.paths.comment:case ne.paths.materialGraphNodeComment:return Kt;case ne.paths.createDelegate:return Ut;case ne.paths.promotableOperator:return qt;case ne.paths.knot:return ii;case ne.paths.literal:case ne.paths.variableGet:case ne.paths.variableSet:return si}return e.isEvent()?ei:Ut}static fromSerializedObject(e){e=e.trim();let t=Me.getSerializer(ut).read(e);return ni.newObject(t)}static newObject(e=new ut,t=new(ni.getTypeTemplate(e))){const i=new ni;return i.initialize(e,t),i}initialize(e=new ut,t=new(ni.getTypeTemplate(e))){this.typePath=e.getType(),this.nodeTitle=e.getObjectName(),this.advancedPinDisplay=e.AdvancedPinDisplay?.toString(),this.enabledState=e.EnabledState,this.nodeDisplayName=e.nodeDisplayName(),this.pureFunction=e.bIsPureFunc,this.dragLinkObjects=[],super.initialize(e,t),this.#qe=this.template.createPinElements(),super.setLocation(this.entity.getNodePosX(),this.entity.getNodePosY()),this.entity.NodeWidth&&this.entity.NodeHeight?(this.sizeX=this.entity.NodeWidth.value,this.sizeY=this.entity.NodeHeight.value):this.updateComplete.then((()=>this.computeSizes()))}async getUpdateComplete(){let e=await super.getUpdateComplete();for(const t of this.getPinElements())e&&=await t.updateComplete;return e}bindToComment(e){e==this||this.boundComments.includes(e)||(e.addEventListener(ne.nodeDragEventName,this.#et),this.boundComments.push(e))}unbindFromComment(e){const t=this.boundComments.indexOf(e);t>=0&&(e.removeEventListener(ne.nodeDragEventName,this.#et),this.boundComments[t]=this.boundComments[this.boundComments.length-1],this.boundComments.pop())}isInsideComment(e){return this.topBoundary()>=e.topBoundary()&&this.rightBoundary()<=e.rightBoundary()&&this.bottomBoundary()<=e.bottomBoundary()&&this.leftBoundary()>=e.leftBoundary()}getType(){return this.entity.getType()}getNodeName(){return this.entity.getObjectName()}computeNodeDisplayName(){this.nodeDisplayName=this.entity.nodeDisplayName()}setNodeWidth(e){this.entity.setNodeWidth(e),this.sizeX=e,this.acknowledgeReflow()}setNodeHeight(e){this.entity.setNodeHeight(e),this.sizeY=e,this.acknowledgeReflow()}sanitizeLinks(e=[]){this.getPinElements().forEach((t=>t.sanitizeLinks(e)))}rename(e){if(this.entity.Name==e)return!1;for(let t of this.getPinElements())for(let i of t.getLinks())this.blueprint.getPin(i).redirectLink(t,new Qe({objectName:e,pinGuid:t.entity.PinId}));this.entity.Name=e,this.nodeTitle=this.entity.Name}getPinElements(){return this.#qe}getPinEntities(){return this.entity.getPinEntities()}setLocation(e=0,t=0,i=!0){this.entity.setNodePosX(e),this.entity.setNodePosY(t),super.setLocation(e,t,i)}acknowledgeReflow(){this.requestUpdate(),this.updateComplete.then((()=>this.computeSizes()));let e=new CustomEvent(ne.nodeReflowEventName);this.dispatchEvent(e)}setShowAdvancedPinDisplay(e){this.entity.AdvancedPinDisplay=new De(e?"Shown":"Hidden"),this.advancedPinDisplay=this.entity.AdvancedPinDisplay}toggleShowAdvancedPinDisplay(){this.setShowAdvancedPinDisplay("Shown"!=this.entity.AdvancedPinDisplay?.toString())}}class ai extends Ct{static properties={selecting:{type:Boolean,attribute:"data-selecting",reflect:!0,converter:he.booleanConverter},scrolling:{type:Boolean,attribute:"data-scrolling",reflect:!0,converter:he.booleanConverter},focused:{type:Boolean,attribute:"data-focused",reflect:!0,converter:he.booleanConverter},zoom:{type:Number,attribute:"data-zoom",reflect:!0},scrollX:{type:Number,attribute:!1},scrollY:{type:Number,attribute:!1},additionalX:{type:Number,attribute:!1},additionalY:{type:Number,attribute:!1},translateX:{type:Number,attribute:!1},translateY:{type:Number,attribute:!1}};static nodeBoundariesSupplier=e=>({primaryInf:e.leftBoundary(!0),primarySup:e.rightBoundary(!0),secondaryInf:e.topBoundary(!0),secondarySup:e.bottomBoundary(!0)});static nodeSelectToggleFunction=(e,t)=>{e.setSelected(t)};#tt=new Map;#it=0;#st=0;nodes=[];links=[];nodesNames=new Map;mousePosition=[0,0];waitingExpandUpdate=!1;constructor(){super(),this.selecting=!1,this.scrolling=!1,this.focused=!1,this.zoom=0,this.scrollX=ne.expandGridSize,this.scrollY=ne.expandGridSize,this.translateX=ne.expandGridSize,this.translateY=ne.expandGridSize,super.initialize({},new Mt)}initialize(){}getGridDOMElement(){return this.template.gridElement}getScroll(){return[this.scrollX,this.scrollY]}setScroll(e,t){this.scrollX=e,this.scrollY=t}scrollDelta(e=0,t=0,i=!1,s=ne.smoothScrollTime){if(i){let i=[0,0];this.#it&&cancelAnimationFrame(this.#it),this.#st&&cancelAnimationFrame(this.#st),he.animate(0,e,s,(e=>{this.scrollDelta(e-i[0],0,!1),i[0]=e}),(e=>this.#it=e)),he.animate(0,t,s,(e=>{this.scrollDelta(0,e-i[1],!1),i[1]=e}),(e=>this.#st=e))}else{const i=[2*ne.expandGridSize,2*ne.expandGridSize];let s=this.getScroll(),r=[s[0]+e,s[1]+t],n=[0,0];for(let e=0;e<2;++e)r[e]i[e]-ne.gridExpandThreshold*ne.expandGridSize&&(n[e]=1);0==n[0]&&0==n[1]||this.seamlessExpand(n[0],n[1]),s=this.getScroll(),r=[s[0]+e,s[1]+t],this.setScroll(r[0],r[1])}}scrollCenter(e=!1){const t=this.getScroll(),i=[this.translateX-t[0],this.translateY-t[1]],s=this.getViewportSize().map((e=>e/2)),r=[i[0]-s[0],i[1]-s[1]];this.scrollDelta(r[0],r[1],e)}getViewportSize(){return[this.template.viewportElement.clientWidth,this.template.viewportElement.clientHeight]}getScrollMax(){return[this.template.viewportElement.scrollWidth-this.template.viewportElement.clientWidth,this.template.viewportElement.scrollHeight-this.template.viewportElement.clientHeight]}snapToGrid(e,t){return he.snapToGrid(e,t,ne.gridSize)}seamlessExpand(e,t){e=Math.round(e),t=Math.round(t);let i=this.getScale();[e,t]=[-e*ne.expandGridSize,-t*ne.expandGridSize],0!=e&&(this.scrollX+=e,e/=i),0!=t&&(this.scrollY+=t,t/=i),this.translateX+=e,this.translateY+=t}progressiveSnapToGrid(e){return ne.expandGridSize*Math.round(e/ne.expandGridSize+.5*Math.sign(e))}getZoom(){return this.zoom}setZoom(e,t){if((e=he.clamp(e,ne.minZoom,ne.maxZoom))==this.zoom)return;let i=this.getScale();if(this.zoom=e,t){t[0]+=this.translateX,t[1]+=this.translateY;let e=this.getScale()/i,s=[e*t[0],e*t[1]];this.scrollDelta((s[0]-t[0])*i,(s[1]-t[1])*i)}}getScale(){return ne.scale[this.getZoom()]}scaleCorrect(e){return e/this.getScale()}scaleCorrectReverse(e){return e*this.getScale()}compensateTranslation(e,t){return[e-=this.translateX,t-=this.translateY]}getNodes(e=!1,[t,i,s,r]=[Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER]){let n=this.nodes;return e&&(n=n.filter((e=>e.selected))),(t>Number.MIN_SAFE_INTEGER||iNumber.MIN_SAFE_INTEGER)&&(n=n.filter((e=>e.topBoundary()>=t&&e.rightBoundary()<=i&&e.bottomBoundary()<=s&&e.leftBoundary()>=r))),n}getCommentNodes(e=!1){let t=[...this.template.getCommentNodes(e)];return 0===t.length&&(t=this.nodes.filter((t=>t.getType()===ne.paths.comment&&(!e||t.selected)))),t}getPin(e){let t=this.template.getPin(e);return t&&t.nodeElement.getNodeName()==e.objectName.toString()||(t=[...this.nodes.find((t=>e.objectName.toString()==t.getNodeName()))?.getPinElements()??[]].find((t=>e.pinGuid.toString()==t.getPinId().toString()))),t}getLinks(e=null,t=null){if(null==e!=(null==t)){const i=e??t;return this.links.filter((e=>e.source==i||e.destination==i))}return null!=e&&null!=t?this.links.filter((i=>i.source==e&&i.destination==t||i.source==t&&i.destination==e)):this.links}getLink(e,t,i=!1){return this.links.find((s=>s.source==e&&s.destination==t||!i&&s.source==t&&s.destination==e))}selectAll(){this.getNodes().forEach((e=>ai.nodeSelectToggleFunction(e,!0)))}unselectAll(){this.getNodes().forEach((e=>ai.nodeSelectToggleFunction(e,!1)))}addGraphElement(...e){const t=e=>{const i=e.currentTarget;i.removeEventListener(ne.removeEventName,t);const s=i instanceof ni?this.nodes:i instanceof Dt?this.links:null,r=s?.indexOf(i);if(r>=0){const e=s.pop();rt.entity.getObjectName()==e));if(s){let e=s.entity.getObjectName(!0);this.#tt[e]=this.#tt[e]??-1;do{++this.#tt[e]}while(this.nodes.find((t=>t.entity.getObjectName()==ne.nodeTitle(e,this.#tt[e]))));s.rename(ne.nodeTitle(e,this.#tt[e]))}this.nodes.push(i),i.addEventListener(ne.removeEventName,t),this.template.nodesContainerElement?.appendChild(i)}else i instanceof Dt&&!this.links.includes(i)&&(this.links.push(i),i.addEventListener(ne.removeEventName,t),this.template.linksContainerElement&&!this.template.linksContainerElement.contains(i)&&this.template.linksContainerElement.appendChild(i));e.filter((e=>e instanceof ni)).forEach((t=>t.sanitizeLinks(e))),e.filter((e=>e instanceof ni&&e.getType()==ne.paths.comment)).forEach((e=>e.updateComplete.then((()=>e.template.manageNodesBind()))))}removeGraphElement(...e){for(let t of e){if(t.closest("ueb-blueprint")!==this)return;t.remove()}}setFocused(e=!0){if(this.focused==e)return;let t=new CustomEvent(e?ne.focusEventName.begin:ne.focusEventName.end);this.focused=e,this.focused||this.unselectAll(),this.dispatchEvent(t)}acknowledgeEditText(e){const t=new CustomEvent(e?ne.editTextEventName.begin:ne.editTextEventName.end);this.dispatchEvent(t)}}customElements.define("ueb-blueprint",ai);class oi extends _t{#rt;get locationChangeCallback(){return this.#rt}set locationChangeCallback(e){this.#rt=e}movementSpace;movementSpaceSize=[0,0];firstUpdated(e){super.firstUpdated(e),this.movementSpace=this.element.parentElement}setup(){super.setup();const e=this.movementSpace.getBoundingClientRect();this.movementSpaceSize=[e.width,e.height]}createDraggableObject(){return new Ot(this.element,this.blueprint,{draggableElement:this.movementSpace,ignoreTranslateCompensate:!0,moveEverywhere:!0,movementSpace:this.movementSpace,repositionOnClick:!0,stepSize:1})}adjustLocation(e,t){return this.locationChangeCallback?.(e,t),[e,t]}}class li extends oi{adjustLocation(e,t){const i=Math.round(this.movementSpaceSize[0]/2);e-=i,t=-(t-i);let[s,r]=he.getPolarCoordinates(e,t);return s=Math.min(s,i),[e,t]=he.getCartesianCoordinates(s,r),this.locationChangeCallback?.(e/i,t/i),[e=Math.round(e+i),t=Math.round(-t+i)]}}class ci extends xt{windowElement;setup(){super.setup(),this.windowElement=this.closest("ueb-window")}setLocation(e,t){super.setLocation(...this.template.adjustLocation(e,t))}}class ui extends ci{constructor(){super(),super.initialize({},new li)}static newObject(){return new ui}initialize(){}}class hi extends oi{adjustLocation(e,t){return e=he.clamp(e,0,this.movementSpaceSize[0]),t=he.clamp(t,0,this.movementSpaceSize[1]),this.locationChangeCallback?.(e/this.movementSpaceSize[0],1-t/this.movementSpaceSize[1]),[e,t]}}class pi extends ci{constructor(){super(),super.initialize({},new hi)}static newObject(){return new pi}initialize(){}}class di extends Pt{constructor(e,t,i={}){i.consumeEvent=!0,super(e,t,i)}}class mi extends Lt{#nt;#at;#ot=e=>this.element.selectedOption=e.target.selectedOptions[0].value;render(){return G` `}firstUpdated(e){super.firstUpdated(e),this.#nt=this.element.querySelector("select:first-child"),this.#at=this.element.querySelector("select:last-child");const t=new Event("input",{bubbles:!0});this.#nt.dispatchEvent(t)}updated(e){super.updated(e);const t=this.#at.getBoundingClientRect();this.element.style.setProperty("--ueb-dropdown-width",t.width+"px")}createInputObjects(){return[...super.createInputObjects(),new di(this.element,this.blueprint)]}setSelectedValue(e){this.element.querySelector(`option[value="${e}"]`).defaultSelected=!0}getSelectedValue(){return this.#nt.value}}class gi extends Ct{static properties={...super.properties,options:{type:Object},selectedOption:{type:String}};constructor(){super(),super.initialize({},new mi),this.options=[],this.selectedOption=""}static newObject(e){return new gi}initialize(){}getValue(){return this.template.getSelectedValue()}}class bi extends Lt{#lt=()=>{this.blueprint.acknowledgeEditText(!0),this.element.selectOnFocus&&getSelection().selectAllChildren(this.element)};#ct=()=>{this.blueprint.acknowledgeEditText(!1),getSelection().removeAllRanges()};#ut=e=>e.target.querySelectorAll("br").forEach((e=>e.remove()));#ht=e=>{"Enter"!=e.code||e.shiftKey||e.target.blur()};initialize(e){super.initialize(e),this.element.classList.add("ueb-pin-input-content"),this.element.setAttribute("role","textbox"),this.element.contentEditable="true"}firstUpdated(e){super.firstUpdated(e);const t=new Event("input",{bubbles:!0});this.element.dispatchEvent(t)}createInputObjects(){return[...super.createInputObjects(),new di(this.element,this.blueprint)]}setup(){super.setup(),this.element.addEventListener("focus",this.#lt),this.element.addEventListener("focusout",this.#ct),this.element.singleLine&&this.element.addEventListener("input",this.#ut),this.element.blurOnEnter&&this.element.addEventListener("keydown",this.#ht)}cleanup(){super.cleanup(),this.element.removeEventListener("focus",this.#lt),this.element.removeEventListener("focusout",this.#ct),this.element.removeEventListener("input",this.#ut),this.element.removeEventListener("keydown",this.#ht)}}class vi extends Ct{static properties={...super.properties,singleLine:{type:Boolean,attribute:"data-single-line",converter:he.booleanConverter,reflect:!0},selectOnFocus:{type:Boolean,attribute:"data-select-focus",converter:he.booleanConverter,reflect:!0},blurOnEnter:{type:Boolean,attribute:"data-blur-enter",converter:he.booleanConverter,reflect:!0}};constructor(){super(),this.singleLine=!1,this.selectOnFocus=!0,this.blurOnEnter=!0,super.initialize({},new bi)}static newObject(){return new vi}initialize(){}}class yi extends Qt{#pt;#dt=()=>this.element.setDefaultValue(this.#pt.checked);firstUpdated(e){super.firstUpdated(e),this.#pt=this.element.querySelector(".ueb-pin-input")}setup(){super.setup(),this.#pt?.addEventListener("change",this.#dt)}cleanup(){super.cleanup(),this.#pt?.removeEventListener("change",this.#dt)}createInputObjects(){return[...super.createInputObjects(),new di(this.#pt,this.blueprint)]}renderInput(){return G``}}class fi extends Qt{static singleLineInput=!1;static selectOnFocus=!0;static saveEachInputChange=!1;#mt;get inputWrapper(){return this.#mt}#gt;static stringFromInputToUE(e){return e.replace(/(?=\n\s*)\n$/,"")}static stringFromUEToInput(e){return e.replaceAll(/(?:\r|(?<=(?:^|[^\\])(?:\\\\)*)\\r)(?=\n)/g,"").replace(/(?<=\n\s*)$/,"\n")}#bt=()=>this.setInputs(this.getInputs(),!0);#vt=e=>this.#yt(e.target);#yt(e){const t=this.blueprint.scaleCorrect(this.#mt.getBoundingClientRect().width)+this.nameWidth,i=this.element.classList.contains("ueb-pin-input-wrap");!i&&t>ne.pinInputWrapWidth?this.element.classList.add("ueb-pin-input-wrap"):i&&t<=ne.pinInputWrapWidth&&this.element.classList.remove("ueb-pin-input-wrap")}firstUpdated(e){super.firstUpdated(e);this.constructor.canWrapInput&&this.isInputRendered()&&(this.element.addEventListener("input",this.#vt),this.nameWidth=this.blueprint.scaleCorrect(this.element.querySelector(".ueb-pin-name")?.getBoundingClientRect().width??0)),this.#mt=this.element.querySelector(".ueb-pin-input-wrapper"),this.#gt=[...this.element.querySelectorAll("ueb-input")]}setup(){super.setup();const e=this.constructor;e.saveEachInputChange?this.element.addEventListener("input",this.#bt):this.element.addEventListener("focusout",this.#bt),e.canWrapInput&&this.isInputRendered()&&(this.element.addEventListener("input",this.#vt),this.element.nodeElement.addEventListener(ne.nodeReflowEventName,this.#vt))}cleanup(){super.cleanup(),this.element.nodeElement.removeEventListener(ne.nodeReflowEventName,this.#vt),this.element.removeEventListener("input",this.#vt),this.element.removeEventListener("input",this.#bt),this.element.removeEventListener("focusout",this.#bt)}getInput(){return this.getInputs().reduce(((e,t)=>e+t),"")}getInputs(){return this.#gt.map((e=>he.clearHTMLWhitespace(e.innerHTML)))}setInputs(e=[],t=!0){this.#gt.forEach(this.constructor.singleLineInput?(t,i)=>t.innerText=e[i]:(t,i)=>t.innerText=e[i].replaceAll("\n","")),t&&this.setDefaultValue(e.map((e=>fi.stringFromInputToUE(e))),e),this.element.requestUpdate(),this.element.nodeElement.acknowledgeReflow()}setDefaultValue(e=[],t=e){this.element.setDefaultValue(e.join(""))}renderInput(){const e=this.constructor,t=e.singleLineInput,i=e.selectOnFocus;return G`
`}}class wi extends fi{static saveEachInputChange=!0;#ft;#wt=[];setup(){super.setup();const e=this.element.nodeElement.entity.EnumEntries;this.#wt=e?.map((e=>(""===e&&(e="None"),[e,this.element.nodeElement.getPinEntities().find((t=>e===t.PinName))?.PinFriendlyName.toString()??e])))??ne.CommonEnums[this.element.entity.getSubCategory()]?.map((e=>e instanceof Array?e:[e,he.formatStringName(e)]))??[];const t=this.element.getDefaultValue().toString();this.#wt.find((([e,i])=>e===t))||this.#wt.push([t,he.formatStringName(t)]),this.element.requestUpdate()}renderInput(){return this.element.nodeElement.entity,G``}firstUpdated(e){super.firstUpdated(e),this.#ft=this.element.querySelector("ueb-dropdown")}getInputs(){return[this.#ft.getValue()]}}class Si extends Qt{renderIcon(){return Ae.execPin}renderName(){let e=this.element.entity.PinName;if(this.element.entity.PinFriendlyName)e=this.element.entity.PinFriendlyName.toString();else if("execute"===e||"then"===e)return G``;return G`${this.element.getPinDisplayName()}`}}class Ei extends fi{static singleLineInput=!0;setInputs(e=[],t=!1){if(e&&0!=e.length||(e=[this.getInput()]),super.setInputs(e,!1),t){let i=[];for(const s of e){let e=parseFloat(s);isNaN(e)&&(e=0,t=!1),i.push(e)}this.setDefaultValue(i,e)}}setDefaultValue(e=[],t){this.element.setDefaultValue(e[0])}}class Ci extends Ei{setDefaultValue(e=[],t=e){this.element.getDefaultValue(!0).value=e[0],this.element.requestUpdate()}renderInput(){return G`
`}}class xi extends Ci{setInputs(e=[],t=!1){if(e&&0!=e.length||(e=[this.getInput()]),super.setInputs(e,!1),t){if(!e[0].match(/[\-\+]?[0-9]+/))return;const t=[BigInt(e[0])];this.setDefaultValue(t,e)}}} /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */const Ci=1;class Pi{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,i){this._$Ct=e,this._$AM=t,this._$Ci=i}_$AS(e,t){return this.update(e,t)}update(e,t){return this.render(...t)}} + */const Pi=1;class Ni{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,i){this._$Ct=e,this._$AM=t,this._$Ci=i}_$AS(e,t){return this.update(e,t)}update(e,t){return this.render(...t)}} /** * @license * Copyright 2018 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */const xi="important",Ni=" !"+xi,ki=(e=>(...t)=>({_$litDirective$:e,values:t}))(class extends Pi{constructor(e){var t;if(super(e),e.type!==Ci||"style"!==e.name||(null===(t=e.strings)||void 0===t?void 0:t.length)>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(e){return Object.keys(e).reduce(((t,i)=>{const s=e[i];return null==s?t:t+`${i=i.includes("-")?i:i.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${s};`}),"")}update(e,[t]){const{style:i}=e.element;if(void 0===this.ht){this.ht=new Set;for(const e in t)this.ht.add(e);return this.render(t)}this.ht.forEach((e=>{null==t[e]&&(this.ht.delete(e),e.includes("-")?i.removeProperty(e):i[e]="")}));for(const e in t){const s=t[e];if(null!=s){this.ht.add(e);const t="string"==typeof s&&s.endsWith(Ni);e.includes("-")||t?i.setProperty(e,t?s.slice(0,-11):s,t?xi:""):i[e]=s}}return O}});class Ai extends Rt{toggleAdvancedDisplayHandler;getDraggableElement(){return this.element.querySelector(".ueb-window-top")}createDraggableObject(){return new Dt(this.element,this.blueprint,{draggableElement:this.getDraggableElement(),ignoreScale:!0,ignoreTranslateCompensate:!1,movementSpace:this.blueprint,stepSize:1})}setup(){const e=this.blueprint.template.gridLeftVisibilityBoundary(),t=this.blueprint.template.gridTopVisibilityBoundary();this.element.locationX=this.blueprint.scaleCorrectReverse(this.blueprint.mousePosition[0]-e),this.element.locationY=this.blueprint.scaleCorrectReverse(this.blueprint.mousePosition[1]-t),this.element.updateComplete.then((()=>{const e=this.blueprint.getBoundingClientRect();this.element.locationX+this.element.sizeX>e.width&&(this.element.locationX=e.width-this.element.sizeX),this.element.locationX=Math.max(0,this.element.locationX),this.element.locationY+this.element.sizeY>e.height&&(this.element.locationY=e.height-this.element.sizeY),this.element.locationY=Math.max(0,this.element.locationY)}))}render(){return D`
${this.renderWindowName()}
${rt.close}
${this.renderContent()}
`}renderWindowName(){return D`Window`}renderContent(){return D``}apply(){this.element.dispatchEvent(new CustomEvent(ne.windowApplyEventName)),this.element.remove()}cancel(){this.element.dispatchEvent(new CustomEvent(ne.windowCancelEventName)),this.element.remove()}}class Li extends Ai{#ft;#wt;#St;#Et;#Ct;#Pt;#xt;#Nt;#kt;#At;#Lt=e=>{const t=Ae.clearHTMLWhitespace(e.target.innerHTML),i=parseInt(t,16);isNaN(i)||(this.color.setFromRGBANumber(i),this.element.requestUpdate())};#Mt=e=>{const t=Ae.clearHTMLWhitespace(e.target.innerHTML),i=parseInt(t,16);isNaN(i)||(this.color.setFromSRGBANumber(i),this.element.requestUpdate())};#Tt=e=>t=>{"Enter"==t.code&&(t.preventDefault(),e(t))};#It=new De;get color(){return this.#It}set color(e){e.toNumber()!=this.color?.toNumber()&&(this.element.requestUpdate("color",this.#It),this.#It=e)}#Bt=new De;get fullColor(){return this.#Bt}#$t;get initialColor(){return this.#$t}#Ht=new De;#Gt(e,t,i=!1){const s=this.color.toRGBAString(),r=`${s.substring(0,2*e)}${t}${s.substring(2+2*e)}`;return i?`${r.substring(0,6)}FF`:r}initialize(e){super.initialize(e),this.#$t=this.element.windowOptions.getPinColor(),this.color.setFromHSVA(this.initialColor.H.value,this.initialColor.S.value,this.initialColor.V.value,this.initialColor.A.value),this.fullColor.setFromHSVA(this.color.H.value,1,1,1)}firstUpdated(e){this.#ft=this.element.querySelector(".ueb-color-picker-wheel ueb-color-handler"),this.#wt=this.element.querySelector(".ueb-color-picker-saturation ueb-ui-slider"),this.#St=this.element.querySelector(".ueb-color-picker-value ueb-ui-slider"),this.#Et=this.element.querySelector(".ueb-color-picker-r ueb-ui-slider"),this.#Ct=this.element.querySelector(".ueb-color-picker-g ueb-ui-slider"),this.#Pt=this.element.querySelector(".ueb-color-picker-b ueb-ui-slider"),this.#xt=this.element.querySelector(".ueb-color-picker-a ueb-ui-slider"),this.#Nt=this.element.querySelector(".ueb-color-picker-h ueb-ui-slider"),this.#kt=this.element.querySelector(".ueb-color-picker-s ueb-ui-slider"),this.#At=this.element.querySelector(".ueb-color-picker-v ueb-ui-slider"),this.#ft.template.locationChangeCallback=(e,t)=>{this.color.setFromWheelLocation(e,t,this.color.V.value,this.color.A.value),this.fullColor.setFromHSVA(this.color.H.value,1,1,1),this.element.requestUpdate()},this.#wt.template.locationChangeCallback=(e,t)=>{this.color.setFromHSVA(this.color.H.value,t,this.color.V.value,this.color.A.value),this.element.requestUpdate()},this.#St.template.locationChangeCallback=(e,t)=>{this.color.setFromHSVA(this.color.H.value,this.color.S.value,t,this.color.A.value),this.element.requestUpdate()},this.#Et.template.locationChangeCallback=(e,t)=>{this.color.setFromRGBA(e,this.color.G.value,this.color.B.value,this.color.A.value),this.element.requestUpdate()},this.#Ct.template.locationChangeCallback=(e,t)=>{this.color.setFromRGBA(this.color.R.value,e,this.color.B.value,this.color.A.value),this.element.requestUpdate()},this.#Pt.template.locationChangeCallback=(e,t)=>{this.color.setFromRGBA(this.color.R.value,this.color.G.value,e,this.color.A.value),this.element.requestUpdate()},this.#xt.template.locationChangeCallback=(e,t)=>{this.color.setFromRGBA(this.color.R.value,this.color.G.value,this.color.B.value,e),this.element.requestUpdate()},this.#Nt.template.locationChangeCallback=(e,t)=>{this.color.setFromHSVA(e,this.color.S.value,this.color.V.value,this.color.A.value),this.element.requestUpdate()},this.#kt.template.locationChangeCallback=(e,t)=>{this.color.setFromHSVA(this.color.H.value,e,this.color.V.value,this.color.A.value),this.element.requestUpdate()},this.#At.template.locationChangeCallback=(e,t)=>{this.color.setFromHSVA(this.color.H.value,this.color.S.value,e,this.color.A.value),this.element.requestUpdate()}}renderSlider(e){let t="",i=0,s="";const r=e=>`linear-gradient(to right, #${this.#Gt(e,"00",!0)}, #${this.#Gt(e,"ff",!0)})`;switch(e){case 0:t="r",i=this.color.R.value,s=r(e);break;case 1:t="g",i=this.color.G.value,s=r(e);break;case 2:t="b",i=this.color.B.value,s=r(e);break;case 3:t="a",i=this.color.A.value,s=`${ne.alphaPattern}, ${r(e)}`;break;case 4:t="h",i=360*this.color.H.value,s="linear-gradient(to right, #f00 0%, #ff0 16.666%, #0f0 33.333%, #0ff 50%, #00f 66.666%, #f0f 83.333%, #f00 100%)";break;case 5:t="s",i=this.color.S.value,s=`linear-gradient(to right,#${this.#Ht.setFromHSVA(this.color.H.value,0,this.color.V.value,1),this.#Ht.toRGBAString()},#${this.#Ht.setFromHSVA(this.color.H.value,1,this.color.V.value,1),this.#Ht.toRGBAString()})`;break;case 6:t="v",i=this.color.V.value,s=`linear-gradient(to right, #000, #${this.fullColor.toRGBAString()})`}return s=`background: ${s};`,D`
${t.toUpperCase()}
`}renderContent(){const e=2*this.color.H.value*Math.PI,t={"--ueb-color-r":this.color.R.toString(),"--ueb-color-g":this.color.G.toString(),"--ueb-color-b":this.color.B.toString(),"--ueb-color-a":this.color.A.toString(),"--ueb-color-h":this.color.H.toString(),"--ueb-color-s":this.color.S.toString(),"--ueb-color-v":this.color.V.toString(),"--ueb-color-wheel-x":100*(this.color.S.value*Math.cos(e)*.5+.5)+"%","--ueb-color-wheel-y":100*(this.color.S.value*Math.sin(e)*.5+.5)+"%"},i=this.color.toRGBAString(),s=this.color.toSRGBAString(),r=this.fullColor.toRGBAString();return D`
Old
New
Advanced
${this.renderSlider(0)} ${this.renderSlider(1)} ${this.renderSlider(2)} ${this.renderSlider(3)}
${this.renderSlider(4)} ${this.renderSlider(5)} ${this.renderSlider(6)}
Hex Linear
Hex sRGB
${ne.windowApplyButtonText}
${ne.windowCancelButtonText}
`}renderWindowName(){return D`${ne.colorWindowName}`}}class Mi extends Xt{#Dt;#Ot=e=>{e.preventDefault(),this.blueprint.setFocused(!0),this.#Dt=xt.getConstructor("ueb-window").newObject({type:new Li,windowOptions:{getPinColor:()=>this.element.defaultValue,setPinColor:e=>this.element.setDefaultValue(e)}}),this.blueprint.append(this.#Dt);const t=()=>{this.element.setDefaultValue(this.#Dt.template.color)},i=()=>{this.#Dt.removeEventListener(ne.windowApplyEventName,t),this.#Dt.removeEventListener(ne.windowCloseEventName,i),this.#Dt=null};this.#Dt.addEventListener(ne.windowApplyEventName,t),this.#Dt.addEventListener(ne.windowCloseEventName,i)};renderInput(){return D``}}class Ti extends vi{static singleLineInput=!0}class Ii extends wi{setDefaultValue(e=[],t=e){this.element.setDefaultValue(e[0])}renderInput(){return D`
`}}class Bi extends Xt{renderIcon(){return rt.referencePin}}class $i extends wi{#Vt(){return Ae.printNumber(this.element.getDefaultValue()?.R??0)}#Rt(){return Ae.printNumber(this.element.getDefaultValue()?.P??0)}#zt(){return Ae.printNumber(this.element.getDefaultValue()?.Y??0)}setDefaultValue(e=[],t=e){const i=this.element.getDefaultValue(!0);if(!(i instanceof Qe))throw new TypeError("Expected DefaultValue to be a RotatorEntity");i.R=e[0],i.P=e[1],i.Y=e[2],this.element.requestUpdate("DefaultValue",i)}renderInput(){return D`
X
Y
Z
`}}class Hi extends vi{}class Gi extends wi{#_t(){return Ae.printNumber(this.element.getDefaultValue()?.X??0)}#zt(){return Ae.printNumber(this.element.getDefaultValue()?.Y??0)}setDefaultValue(e,t){const i=this.element.getDefaultValue(!0);if(!(i instanceof Xe))throw new TypeError("Expected DefaultValue to be a Vector2DEntity");i.X=e[0],i.Y=e[1],this.element.requestUpdate("DefaultValue",i)}renderInput(){return D`
X
Y
`}}class Di extends wi{#_t(){return Ae.printNumber(this.element.getDefaultValue()?.X??0)}#zt(){return Ae.printNumber(this.element.getDefaultValue()?.Y??0)}#Ft(){return Ae.printNumber(this.element.getDefaultValue()?.Z??0)}setDefaultValue(e,t){const i=this.element.getDefaultValue(!0);if(!(i instanceof tt))throw new TypeError("Expected DefaultValue to be a VectorEntity");i.X=e[0],i.Y=e[1],i.Z=e[2],this.element.requestUpdate("DefaultValue",i)}renderInput(){return D`
X
Y
Z
`}}class Oi extends wt{static#jt={bool:bi,byte:Si,enum:yi,int:Si,int64:Ei,MUTABLE_REFERENCE:Bi,name:Ti,rg:Gi,real:Ii,string:Hi,[ne.paths.linearColor]:Mi,[ne.paths.rotator]:$i,[ne.paths.vector]:Di,[ne.paths.vector2D]:Gi};static properties={pinId:{type:Te,converter:{fromAttribute:(e,t)=>e?Te.grammar.parse(e):null,toAttribute:(e,t)=>e?.toString()},attribute:"data-id",reflect:!0},pinType:{type:String,attribute:"data-type",reflect:!0},advancedView:{type:String,attribute:"data-advanced-view",reflect:!0},color:{type:De,converter:{fromAttribute:(e,t)=>e?De.getLinearColorFromAnyFormat().parse(e):null,toAttribute:(e,t)=>e?Ae.printLinearColor(e):null},attribute:"data-color",reflect:!0},defaultValue:{type:String,attribute:!1},isLinked:{type:Boolean,converter:Ae.booleanConverter,attribute:"data-linked",reflect:!0},pinDirection:{type:String,attribute:"data-direction",reflect:!0},connectable:{type:Boolean,converter:Ae.booleanConverter,attribute:"data-connectable",reflect:!0}};nodeElement;static getTypeTemplate(e){return"Array"===e.PinType.ContainerType?.toString()?Xt:e.PinType.bIsReference&&!e.PinType.bIsConst?Oi.#jt.MUTABLE_REFERENCE:"exec"===e.getType()?fi:(e.isInput()?Oi.#jt[e.getType()]:Xt)??Xt}static newObject(e=new st,t=new(Oi.getTypeTemplate(e)),i=void 0){const s=new Oi;return s.initialize(e,t,i),s}initialize(e=new st,t=new(Oi.getTypeTemplate(e)),i=void 0){this.nodeElement=i,this.advancedView=e.bAdvancedView,this.isLinked=!1,this.connectable=!e.bNotConnectable,super.initialize(e,t),this.pinType=this.entity.getType(),this.defaultValue=this.entity.getDefaultValue(),this.color=Oi.properties.color.converter.fromAttribute(this.getColor().toString()),this.pinDirection=e.isInput()?"input":e.isOutput()?"output":"hidden"}setup(){super.setup(),this.nodeElement=this.closest("ueb-node")}createPinReference(){return new Ye({objectName:this.nodeElement.getNodeName(),pinGuid:this.getPinId()})}getPinId(){return this.entity.PinId}getPinName(){return this.entity.PinName}getPinDisplayName(){return this.entity.pinDisplayName()}getColor(){return this.entity.pinColor()}isInput(){return this.entity.isInput()}isOutput(){return this.entity.isOutput()}getLinkLocation(){return this.template.getLinkLocation()}getNodeElement(){return this.nodeElement}getLinks(){return this.entity.LinkedTo??[]}getDefaultValue(e=!1){return this.defaultValue=this.entity.getDefaultValue(e)}setDefaultValue(e){this.entity.DefaultValue=e,this.defaultValue=e}sanitizeLinks(e=[]){this.entity.LinkedTo=this.entity.LinkedTo?.filter((t=>{let i=this.blueprint.getPin(t);if(i){if(e.length&&!e.includes(i.nodeElement))return!1;let t=this.blueprint.getLink(this,i);t||(t=xt.getConstructor("ueb-link").newObject(this,i),this.blueprint.addGraphElement(t))}return i})),this.isLinked=this.entity.isLinked()}linkTo(e){const t=this.createPinReference();!this.isLinked||!this.isOutput()||"exec"!==this.pinType&&"exec"!==e.pinType||this.getLinks().some((e=>t.equals(e)))||this.unlinkFromAll(),this.entity.linkTo(e.getNodeElement().getNodeName(),e.entity)&&(this.isLinked=this.entity.isLinked(),this.nodeElement?.template.linksChanged())}unlinkFrom(e,t=!0){this.entity.unlinkFrom(e.getNodeElement().getNodeName(),e.entity)&&(this.isLinked=this.entity.isLinked(),this.nodeElement?.template.linksChanged(),t&&this.blueprint.getLink(this,e)?.remove())}unlinkFromAll(){const e=this.getLinks().length;this.getLinks().map((e=>this.blueprint.getPin(e))).forEach((e=>this.unlinkFrom(e))),e&&this.nodeElement?.template.linksChanged()}redirectLink(e,t){const i=this.getLinks().findIndex((t=>t.objectName.toString()==e.getNodeElement().getNodeName()&&t.pinGuid.valueOf()==e.entity.PinId.valueOf()));return i>=0&&(this.entity.LinkedTo[i]=t,!0)}}class Vi{constructor(e=(e=>e),t=null){this.array=new Uint32Array(t),this.comparisonValueSupplier=e,this.length=0,this.currentPosition=0}get(e){return e>=0&&e=0&&this.currentPosition=0&&this.currentPosition0?this.get(this.currentPosition-1):null}getPrevValue(){return this.currentPosition>0?this.comparisonValueSupplier(this.get(this.currentPosition-1)):Number.MIN_SAFE_INTEGER}shiftLeft(e,t=1){this.array.set(this.array.subarray(e+t),e)}shiftRight(e,t=1){this.array.set(this.array.subarray(e,-t),e+t)}}class Ri{constructor(e,t,i,s){this.initialPosition=e,this.finalPosition=e,this.metadata=new Array(t.length),this.primaryOrder=new Vi((e=>this.metadata[e].primaryBoundary)),this.secondaryOrder=new Vi((e=>this.metadata[e].secondaryBoundary)),this.selectFunc=s,this.rectangles=t,this.primaryOrder.reserve(this.rectangles.length),this.secondaryOrder.reserve(this.rectangles.length),t.forEach(((e,t)=>{let r={primaryBoundary:this.initialPosition[0],secondaryBoundary:this.initialPosition[1],rectangle:t,onSecondaryAxis:!1};this.metadata[t]=r,s(e,!1);const n=i(e);this.initialPosition[1]{if(this.metadata[i].onSecondaryAxis)this.selectFunc(this.rectangles[i],s);else if(s){this.secondaryOrder.insert(i,e[1]);const s=this.metadata[i].secondaryBoundary;Math.sign(e[1]-s)==t[1]&&Math.sign(s-this.initialPosition[1])==t[1]&&this.selectFunc(this.rectangles[i],!0)}else this.selectFunc(this.rectangles[i],!1),this.secondaryOrder.remove(i);this.computeBoundaries(),this.selectTo(e)};e[0]this.boundaries.primaryN.v&&e[0]this.boundaries.primaryP.v&&(++this.primaryOrder.currentPosition,i(this.boundaries.primaryP.i,this.initialPosition[0]{this.selectFunc(this.rectangles[t],i),this.computeBoundaries(),this.selectTo(e)};e[1]this.boundaries.secondaryN.v&&e[1]this.boundaries.secondaryP.v&&(++this.secondaryOrder.currentPosition,s(this.boundaries.secondaryP.i,this.initialPosition[1]Fi.#Ut[e],toAttribute:(e,t)=>Object.entries(Fi.#Ut).find((([t,i])=>e.constructor===i))?.[0]}}};static newObject(e={},t=e.type??new Ai){const i=new Fi;return i.initialize(e,t),i}initialize(e={},t=e.type??new Ai){e.windowOptions??={},this.type=e.type,this.windowOptions=e.windowOptions,super.initialize(e,t)}computeSizes(){const e=this.getBoundingClientRect();this.sizeX=e.width,this.sizeY=e.height}cleanup(){super.cleanup(),this.acknowledgeClose()}acknowledgeClose(){let e=new CustomEvent(ne.windowCloseEventName);this.dispatchEvent(e)}}class ji extends lt{#Wt;constructor(e,t){super(t),this.#Wt=e}doWrite(e,t,i=""){return this.#Wt(e,t)}}class Ui extends Le{static attributes={...super.attributes,TerminalCategory:{type:String},TerminalSubCategory:{type:String},bTerminalIsConst:{type:Boolean},bTerminalIsWeakPointer:{type:Boolean},bTerminalIsUObjectWrapper:{type:Boolean}};static{this.cleanupAttributes(this.attributes)}constructor(e){super(e),this.TerminalCategory,this.TerminalSubCategory,this.bTerminalIsConst,this.bTerminalIsWeakPointer,this.bTerminalIsUObjectWrapper}}class Wi extends lt{constructor(e){super(e)}doWrite(e,t,i=""){return t||e.constructor!==String?Ae.escapeString(e.toString()):`"${Ae.escapeString(e.toString())}"`}}class Ki extends Le{static attributes={...super.attributes,lookbehind:{default:"",ignored:!0}};static{this.cleanupAttributes(this.attributes)}static grammar=this.createGrammar();static createGrammar(){return Pe.seq(Pe.reg(new RegExp(`(${Me.Regex.Path.source}|${Me.Regex.Symbol.source}\\s*)?\\(\\s*`),1),Pe.seq(Me.attributeName,Me.equalSeparation).map((([e,t])=>e)).chain((e=>Me.unknownValue.map((t=>i=>i[e]=t)))).sepBy(Me.commaSeparation),Pe.reg(/\s*(?:,\s*)?\)/)).map((([e,t,i])=>{e??="";let s={};return e.length&&(s.lookbehind=e),t.forEach((e=>e(s))),new this(s)}))}constructor(e){super(e,!0),this.lookbehind}}Me.unknownValue=Pe.alt(Me.boolean,Te.createGrammar(),Pe.str("None").map((()=>new Ie({type:"None"}))),Me.null,Me.number,Me.string,Ie.fullReferenceGrammar,je.createGrammar(),Fe.createGrammar(),Ue.createGrammar(),Ye.createGrammar(),tt.createGrammar(),Qe.createGrammar(),De.createGrammar(),Xe.createGrammar(),Ki.createGrammar(),Re.createGrammar(),Me.grammarFor(void 0,[Ye]),Me.grammarFor(void 0,[new ke(Number,String,Re)])),Ne.registerSerializer(null,new ji(((e,t)=>"()"),null)),Ne.registerSerializer(Array,new ji(((e,t)=>`(${e.map((e=>Ne.getSerializer(Ae.getType(e)).write(e,t)+",")).join("")})`),Array)),Ne.registerSerializer(BigInt,new Wi(BigInt)),Ne.registerSerializer(Boolean,new ji(((e,t)=>e?t?"true":"True":t?"false":"False"),Boolean)),Ne.registerSerializer(Ve,new Wi(Ve)),Ne.registerSerializer(Ge,new Wi(Ge)),Ne.registerSerializer(_e,new Wi(_e)),Ne.registerSerializer(ze,new Wi(ze)),Ne.registerSerializer(Ue,new ji(((e,t)=>e.getLookbehind()+"("+e.value.map((e=>Ne.getSerializer(Ae.getType(e)).write(e,t))).join(", ")+")"),Ue)),Ne.registerSerializer(Be,new lt(Be,lt.bracketsWrapped)),Ne.registerSerializer(Te,new Wi(Te)),Ne.registerSerializer($e,new Wi($e)),Ne.registerSerializer(We,new Wi(We)),Ne.registerSerializer(He,new Wi(He)),Ne.registerSerializer(Fe,new lt(Fe,((e,t)=>`${e.getLookbehind()}(${t})`),", ",!1,"",(()=>""))),Ne.registerSerializer(dt,new lt(dt,lt.bracketsWrapped)),Ne.registerSerializer(De,new lt(De,lt.bracketsWrapped)),Ne.registerSerializer(je,new lt(je,((e,t)=>`${e.getLookbehind()}(${t})`),", ",!1,"",(()=>""))),Ne.registerSerializer(Oe,new lt(Oe,lt.bracketsWrapped)),Ne.registerSerializer(le,new ji(((e,t)=>Ne.getSerializer(e.getTargetType()).write(e.get(),t)),le)),Ne.registerSerializer(Number,new Wi(Number)),Ne.registerSerializer(ot,new ut),Ne.registerSerializer(Ie,new ji((e=>{let t=e.type??"",i=e.path??"";t&&i&&Ae.isSerialized(e,"path")&&(i=`'${i}'`);let s=t+i;return Ae.isSerialized(e,"type")&&(s=`"${s}"`),s}),Ie)),Ne.registerSerializer(Ke,new Wi(Ke)),Ne.registerSerializer(st,new lt(st,((e,t)=>`${e.getLookbehind()} (${t})`),",",!0)),Ne.registerSerializer(Ye,new lt(Ye,void 0," ",!1,"",(()=>""))),Ne.registerSerializer(Ui,new lt(Ui,lt.bracketsWrapped)),Ne.registerSerializer(qe,new ji(((e,t)=>`X=${e.X} Y=${e.Y}`),qe)),Ne.registerSerializer(Qe,new lt(Qe,lt.bracketsWrapped)),Ne.registerSerializer(String,new ji(((e,t)=>t?Ae.escapeString(e):`"${Ae.escapeString(e)}"`),String)),Ne.registerSerializer(Je,new ji(((e,t)=>`${e.P}, ${e.Y}, ${e.R}`),Je)),Ne.registerSerializer(et,new ji(((e,t)=>`${e.X}, ${e.Y}`),et)),Ne.registerSerializer(it,new ji(((e,t)=>`${e.X}, ${e.Y}, ${e.Z}`),it)),Ne.registerSerializer(Re,new Wi(Re)),Ne.registerSerializer(Ki,new lt(Ki,((e,t)=>`${e.getLookbehind()??""}(${t})`))),Ne.registerSerializer(at,new lt(at,lt.bracketsWrapped)),Ne.registerSerializer(Xe,new lt(Xe,lt.bracketsWrapped)),Ne.registerSerializer(tt,new lt(tt,lt.bracketsWrapped)),function(){const e=(e,t)=>{customElements.define(e,t),xt.registerElement(e,t)};e("ueb-color-handler",li),e("ueb-dropdown",di),e("ueb-input",gi),e("ueb-link",Gt),e("ueb-node",si),e("ueb-pin",Oi),e("ueb-selector",_i),e("ueb-ui-slider",ci),e("ueb-window",Fi)}();export{ri as Blueprint,ne as Configuration,Gt as LinkElement,si as NodeElement,Ae as Utility}; + */const ki="important",Ti=" !"+ki,Ai=(e=>(...t)=>({_$litDirective$:e,values:t}))(class extends Ni{constructor(e){var t;if(super(e),e.type!==Pi||"style"!==e.name||(null===(t=e.strings)||void 0===t?void 0:t.length)>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(e){return Object.keys(e).reduce(((t,i)=>{const s=e[i];return null==s?t:t+`${i=i.includes("-")?i:i.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${s};`}),"")}update(e,[t]){const{style:i}=e.element;if(void 0===this.ht){this.ht=new Set;for(const e in t)this.ht.add(e);return this.render(t)}this.ht.forEach((e=>{null==t[e]&&(this.ht.delete(e),e.includes("-")?i.removeProperty(e):i[e]="")}));for(const e in t){const s=t[e];if(null!=s){this.ht.add(e);const t="string"==typeof s&&s.endsWith(Ti);e.includes("-")||t?i.setProperty(e,t?s.slice(0,-11):s,t?ki:""):i[e]=s}}return D}});class Li extends Ft{toggleAdvancedDisplayHandler;getDraggableElement(){return this.element.querySelector(".ueb-window-top")}createDraggableObject(){return new Ot(this.element,this.blueprint,{draggableElement:this.getDraggableElement(),ignoreScale:!0,ignoreTranslateCompensate:!1,movementSpace:this.blueprint,stepSize:1})}setup(){const e=this.blueprint.template.gridLeftVisibilityBoundary(),t=this.blueprint.template.gridTopVisibilityBoundary();this.element.locationX=this.blueprint.scaleCorrectReverse(this.blueprint.mousePosition[0]-e),this.element.locationY=this.blueprint.scaleCorrectReverse(this.blueprint.mousePosition[1]-t),this.element.updateComplete.then((()=>{const e=this.blueprint.getBoundingClientRect();this.element.locationX+this.element.sizeX>e.width&&(this.element.locationX=e.width-this.element.sizeX),this.element.locationX=Math.max(0,this.element.locationX),this.element.locationY+this.element.sizeY>e.height&&(this.element.locationY=e.height-this.element.sizeY),this.element.locationY=Math.max(0,this.element.locationY)}))}render(){return G`
${this.renderWindowName()}
${Ae.close}
${this.renderContent()}
`}renderWindowName(){return G`Window`}renderContent(){return G``}apply(){this.element.dispatchEvent(new CustomEvent(ne.windowApplyEventName)),this.element.remove()}cancel(){this.element.dispatchEvent(new CustomEvent(ne.windowCancelEventName)),this.element.remove()}}class Mi extends Li{#St;#Et;#Ct;#xt;#Pt;#Nt;#kt;#Tt;#At;#Lt;#Mt=e=>{const t=he.clearHTMLWhitespace(e.target.innerHTML),i=parseInt(t,16);isNaN(i)||(this.color.setFromRGBANumber(i),this.element.requestUpdate())};#It=e=>{const t=he.clearHTMLWhitespace(e.target.innerHTML),i=parseInt(t,16);isNaN(i)||(this.color.setFromSRGBANumber(i),this.element.requestUpdate())};#Bt=e=>t=>{"Enter"==t.code&&(t.preventDefault(),e(t))};#$t=new ze;get color(){return this.#$t}set color(e){e.toNumber()!=this.color?.toNumber()&&(this.element.requestUpdate("color",this.#$t),this.#$t=e)}#Ht=new ze;get fullColor(){return this.#Ht}#Vt;get initialColor(){return this.#Vt}#Gt=new ze;#Dt(e,t,i=!1){const s=this.color.toRGBAString(),r=`${s.substring(0,2*e)}${t}${s.substring(2+2*e)}`;return i?`${r.substring(0,6)}FF`:r}initialize(e){super.initialize(e),this.#Vt=this.element.windowOptions.getPinColor(),this.color.setFromHSVA(this.initialColor.H.value,this.initialColor.S.value,this.initialColor.V.value,this.initialColor.A.value),this.fullColor.setFromHSVA(this.color.H.value,1,1,1)}firstUpdated(e){this.#St=this.element.querySelector(".ueb-color-picker-wheel ueb-color-handler"),this.#Et=this.element.querySelector(".ueb-color-picker-saturation ueb-ui-slider"),this.#Ct=this.element.querySelector(".ueb-color-picker-value ueb-ui-slider"),this.#xt=this.element.querySelector(".ueb-color-picker-r ueb-ui-slider"),this.#Pt=this.element.querySelector(".ueb-color-picker-g ueb-ui-slider"),this.#Nt=this.element.querySelector(".ueb-color-picker-b ueb-ui-slider"),this.#kt=this.element.querySelector(".ueb-color-picker-a ueb-ui-slider"),this.#Tt=this.element.querySelector(".ueb-color-picker-h ueb-ui-slider"),this.#At=this.element.querySelector(".ueb-color-picker-s ueb-ui-slider"),this.#Lt=this.element.querySelector(".ueb-color-picker-v ueb-ui-slider"),this.#St.template.locationChangeCallback=(e,t)=>{this.color.setFromWheelLocation(e,t,this.color.V.value,this.color.A.value),this.fullColor.setFromHSVA(this.color.H.value,1,1,1),this.element.requestUpdate()},this.#Et.template.locationChangeCallback=(e,t)=>{this.color.setFromHSVA(this.color.H.value,t,this.color.V.value,this.color.A.value),this.element.requestUpdate()},this.#Ct.template.locationChangeCallback=(e,t)=>{this.color.setFromHSVA(this.color.H.value,this.color.S.value,t,this.color.A.value),this.element.requestUpdate()},this.#xt.template.locationChangeCallback=(e,t)=>{this.color.setFromRGBA(e,this.color.G.value,this.color.B.value,this.color.A.value),this.element.requestUpdate()},this.#Pt.template.locationChangeCallback=(e,t)=>{this.color.setFromRGBA(this.color.R.value,e,this.color.B.value,this.color.A.value),this.element.requestUpdate()},this.#Nt.template.locationChangeCallback=(e,t)=>{this.color.setFromRGBA(this.color.R.value,this.color.G.value,e,this.color.A.value),this.element.requestUpdate()},this.#kt.template.locationChangeCallback=(e,t)=>{this.color.setFromRGBA(this.color.R.value,this.color.G.value,this.color.B.value,e),this.element.requestUpdate()},this.#Tt.template.locationChangeCallback=(e,t)=>{this.color.setFromHSVA(e,this.color.S.value,this.color.V.value,this.color.A.value),this.element.requestUpdate()},this.#At.template.locationChangeCallback=(e,t)=>{this.color.setFromHSVA(this.color.H.value,e,this.color.V.value,this.color.A.value),this.element.requestUpdate()},this.#Lt.template.locationChangeCallback=(e,t)=>{this.color.setFromHSVA(this.color.H.value,this.color.S.value,e,this.color.A.value),this.element.requestUpdate()}}renderSlider(e){let t="",i=0,s="";const r=e=>`linear-gradient(to right, #${this.#Dt(e,"00",!0)}, #${this.#Dt(e,"ff",!0)})`;switch(e){case 0:t="r",i=this.color.R.value,s=r(e);break;case 1:t="g",i=this.color.G.value,s=r(e);break;case 2:t="b",i=this.color.B.value,s=r(e);break;case 3:t="a",i=this.color.A.value,s=`${ne.alphaPattern}, ${r(e)}`;break;case 4:t="h",i=360*this.color.H.value,s="linear-gradient(to right, #f00 0%, #ff0 16.666%, #0f0 33.333%, #0ff 50%, #00f 66.666%, #f0f 83.333%, #f00 100%)";break;case 5:t="s",i=this.color.S.value,s=`linear-gradient(to right,#${this.#Gt.setFromHSVA(this.color.H.value,0,this.color.V.value,1),this.#Gt.toRGBAString()},#${this.#Gt.setFromHSVA(this.color.H.value,1,this.color.V.value,1),this.#Gt.toRGBAString()})`;break;case 6:t="v",i=this.color.V.value,s=`linear-gradient(to right, #000, #${this.fullColor.toRGBAString()})`}return s=`background: ${s};`,G`
${t.toUpperCase()}
`}renderContent(){const e=2*this.color.H.value*Math.PI,t={"--ueb-color-r":this.color.R.toString(),"--ueb-color-g":this.color.G.toString(),"--ueb-color-b":this.color.B.toString(),"--ueb-color-a":this.color.A.toString(),"--ueb-color-h":this.color.H.toString(),"--ueb-color-s":this.color.S.toString(),"--ueb-color-v":this.color.V.toString(),"--ueb-color-wheel-x":100*(this.color.S.value*Math.cos(e)*.5+.5)+"%","--ueb-color-wheel-y":100*(this.color.S.value*Math.sin(e)*.5+.5)+"%"},i=this.color.toRGBAString(),s=this.color.toSRGBAString(),r=this.fullColor.toRGBAString();return G`
Old
New
Advanced
${this.renderSlider(0)} ${this.renderSlider(1)} ${this.renderSlider(2)} ${this.renderSlider(3)}
${this.renderSlider(4)} ${this.renderSlider(5)} ${this.renderSlider(6)}
Hex Linear
Hex sRGB
${ne.windowApplyButtonText}
${ne.windowCancelButtonText}
`}renderWindowName(){return G`${ne.colorWindowName}`}}class Ii extends Qt{#Ot;#Rt=e=>{e.preventDefault(),this.blueprint.setFocused(!0),this.#Ot=gt.getConstructor("ueb-window").newObject({type:new Mi,windowOptions:{getPinColor:()=>this.element.defaultValue,setPinColor:e=>this.element.setDefaultValue(e)}}),this.blueprint.append(this.#Ot);const t=()=>{this.element.setDefaultValue(this.#Ot.template.color)},i=()=>{this.#Ot.removeEventListener(ne.windowApplyEventName,t),this.#Ot.removeEventListener(ne.windowCloseEventName,i),this.#Ot=null};this.#Ot.addEventListener(ne.windowApplyEventName,t),this.#Ot.addEventListener(ne.windowCloseEventName,i)};renderInput(){return G``}}class Bi extends fi{static singleLineInput=!0}class $i extends Ei{setDefaultValue(e=[],t=e){this.element.setDefaultValue(e[0])}renderInput(){return G`
`}}class Hi extends Qt{renderIcon(){return Ae.referencePin}}class Vi extends Ei{#zt(){return he.printNumber(this.element.getDefaultValue()?.R??0)}#_t(){return he.printNumber(this.element.getDefaultValue()?.P??0)}#Ft(){return he.printNumber(this.element.getDefaultValue()?.Y??0)}setDefaultValue(e=[],t=e){const i=this.element.getDefaultValue(!0);if(!(i instanceof it))throw new TypeError("Expected DefaultValue to be a RotatorEntity");i.R=e[0],i.P=e[1],i.Y=e[2],this.element.requestUpdate("DefaultValue",i)}renderInput(){return G`
X
Y
Z
`}}class Gi extends fi{}class Di extends Ei{#jt(){return he.printNumber(this.element.getDefaultValue()?.X??0)}#Ft(){return he.printNumber(this.element.getDefaultValue()?.Y??0)}setDefaultValue(e,t){const i=this.element.getDefaultValue(!0);if(!(i instanceof et))throw new TypeError("Expected DefaultValue to be a Vector2DEntity");i.X=e[0],i.Y=e[1],this.element.requestUpdate("DefaultValue",i)}renderInput(){return G`
X
Y
`}}class Oi extends Ei{#jt(){return he.printNumber(this.element.getDefaultValue()?.X??0)}#Ft(){return he.printNumber(this.element.getDefaultValue()?.Y??0)}#Ut(){return he.printNumber(this.element.getDefaultValue()?.Z??0)}setDefaultValue(e,t){const i=this.element.getDefaultValue(!0);if(!(i instanceof nt))throw new TypeError("Expected DefaultValue to be a VectorEntity");i.X=e[0],i.Y=e[1],i.Z=e[2],this.element.requestUpdate("DefaultValue",i)}renderInput(){return G`
X
Y
Z
`}}class Ri extends Ct{static#Wt={bool:yi,byte:Ci,enum:wi,int:Ci,int64:xi,MUTABLE_REFERENCE:Hi,name:Bi,rg:Di,real:$i,string:Gi,[ne.paths.linearColor]:Ii,[ne.paths.rotator]:Vi,[ne.paths.vector]:Oi,[ne.paths.vector2D]:Di};static properties={pinId:{type:He,converter:{fromAttribute:(e,t)=>e?He.grammar.parse(e):null,toAttribute:(e,t)=>e?.toString()},attribute:"data-id",reflect:!0},pinType:{type:String,attribute:"data-type",reflect:!0},advancedView:{type:String,attribute:"data-advanced-view",reflect:!0},color:{type:ze,converter:{fromAttribute:(e,t)=>e?ze.getLinearColorFromAnyFormat().parse(e):null,toAttribute:(e,t)=>e?he.printLinearColor(e):null},attribute:"data-color",reflect:!0},defaultValue:{type:String,attribute:!1},isLinked:{type:Boolean,converter:he.booleanConverter,attribute:"data-linked",reflect:!0},pinDirection:{type:String,attribute:"data-direction",reflect:!0},connectable:{type:Boolean,converter:he.booleanConverter,attribute:"data-connectable",reflect:!0}};nodeElement;static getTypeTemplate(e){return"Array"===e.PinType.ContainerType?.toString()?Qt:e.PinType.bIsReference&&!e.PinType.bIsConst?Ri.#Wt.MUTABLE_REFERENCE:"exec"===e.getType()?Si:(e.isInput()?Ri.#Wt[e.getType()]:Qt)??Qt}static newObject(e=new ot,t=new(Ri.getTypeTemplate(e)),i=void 0){const s=new Ri;return s.initialize(e,t,i),s}initialize(e=new ot,t=new(Ri.getTypeTemplate(e)),i=void 0){this.nodeElement=i,this.advancedView=e.bAdvancedView,this.isLinked=!1,this.connectable=!e.bNotConnectable,super.initialize(e,t),this.pinType=this.entity.getType(),this.defaultValue=this.entity.getDefaultValue(),this.color=Ri.properties.color.converter.fromAttribute(this.getColor().toString()),this.pinDirection=e.isInput()?"input":e.isOutput()?"output":"hidden"}setup(){super.setup(),this.nodeElement=this.closest("ueb-node")}createPinReference(){return new Qe({objectName:this.nodeElement.getNodeName(),pinGuid:this.getPinId()})}getPinId(){return this.entity.PinId}getPinName(){return this.entity.PinName}getPinDisplayName(){return this.entity.pinDisplayName()}getColor(){return this.entity.pinColor()}isInput(){return this.entity.isInput()}isOutput(){return this.entity.isOutput()}getLinkLocation(){return this.template.getLinkLocation()}getNodeElement(){return this.nodeElement}getLinks(){return this.entity.LinkedTo??[]}getDefaultValue(e=!1){return this.defaultValue=this.entity.getDefaultValue(e)}setDefaultValue(e){this.entity.DefaultValue=e,this.defaultValue=e,this.entity.recomputesNodeTitleOnChange&&this.nodeElement?.computeNodeDisplayName()}sanitizeLinks(e=[]){this.entity.LinkedTo=this.entity.LinkedTo?.filter((t=>{let i=this.blueprint.getPin(t);if(i){if(e.length&&!e.includes(i.nodeElement))return!1;let t=this.blueprint.getLink(this,i);t||(t=gt.getConstructor("ueb-link").newObject(this,i),this.blueprint.addGraphElement(t))}return i})),this.isLinked=this.entity.isLinked()}linkTo(e){const t=this.createPinReference();!this.isLinked||!this.isOutput()||"exec"!==this.pinType&&"exec"!==e.pinType||this.getLinks().some((e=>t.equals(e)))||this.unlinkFromAll(),this.entity.linkTo(e.getNodeElement().getNodeName(),e.entity)&&(this.isLinked=this.entity.isLinked(),this.nodeElement?.template.linksChanged(),this.entity.recomputesNodeTitleOnChange&&this.nodeElement?.computeNodeDisplayName())}unlinkFrom(e,t=!0){this.entity.unlinkFrom(e.getNodeElement().getNodeName(),e.entity)&&(this.isLinked=this.entity.isLinked(),this.nodeElement?.template.linksChanged(),t&&this.blueprint.getLink(this,e)?.remove(),this.entity.recomputesNodeTitleOnChange&&this.nodeElement?.computeNodeDisplayName())}unlinkFromAll(){const e=this.getLinks().length;this.getLinks().map((e=>this.blueprint.getPin(e))).forEach((e=>this.unlinkFrom(e))),e&&this.nodeElement?.template.linksChanged()}redirectLink(e,t){const i=this.getLinks().findIndex((t=>t.objectName.toString()==e.getNodeElement().getNodeName()&&t.pinGuid.valueOf()==e.entity.PinId.valueOf()));return i>=0&&(this.entity.LinkedTo[i]=t,!0)}}class zi{constructor(e=(e=>e),t=null){this.array=new Uint32Array(t),this.comparisonValueSupplier=e,this.length=0,this.currentPosition=0}get(e){return e>=0&&e=0&&this.currentPosition=0&&this.currentPosition0?this.get(this.currentPosition-1):null}getPrevValue(){return this.currentPosition>0?this.comparisonValueSupplier(this.get(this.currentPosition-1)):Number.MIN_SAFE_INTEGER}shiftLeft(e,t=1){this.array.set(this.array.subarray(e+t),e)}shiftRight(e,t=1){this.array.set(this.array.subarray(e,-t),e+t)}}class _i{constructor(e,t,i,s){this.initialPosition=e,this.finalPosition=e,this.metadata=new Array(t.length),this.primaryOrder=new zi((e=>this.metadata[e].primaryBoundary)),this.secondaryOrder=new zi((e=>this.metadata[e].secondaryBoundary)),this.selectFunc=s,this.rectangles=t,this.primaryOrder.reserve(this.rectangles.length),this.secondaryOrder.reserve(this.rectangles.length),t.forEach(((e,t)=>{let r={primaryBoundary:this.initialPosition[0],secondaryBoundary:this.initialPosition[1],rectangle:t,onSecondaryAxis:!1};this.metadata[t]=r,s(e,!1);const n=i(e);this.initialPosition[1]{if(this.metadata[i].onSecondaryAxis)this.selectFunc(this.rectangles[i],s);else if(s){this.secondaryOrder.insert(i,e[1]);const s=this.metadata[i].secondaryBoundary;Math.sign(e[1]-s)==t[1]&&Math.sign(s-this.initialPosition[1])==t[1]&&this.selectFunc(this.rectangles[i],!0)}else this.selectFunc(this.rectangles[i],!1),this.secondaryOrder.remove(i);this.computeBoundaries(),this.selectTo(e)};e[0]this.boundaries.primaryN.v&&e[0]this.boundaries.primaryP.v&&(++this.primaryOrder.currentPosition,i(this.boundaries.primaryP.i,this.initialPosition[0]{this.selectFunc(this.rectangles[t],i),this.computeBoundaries(),this.selectTo(e)};e[1]this.boundaries.secondaryN.v&&e[1]this.boundaries.secondaryP.v&&(++this.secondaryOrder.currentPosition,s(this.boundaries.secondaryP.i,this.initialPosition[1]Ui.#Kt[e],toAttribute:(e,t)=>Object.entries(Ui.#Kt).find((([t,i])=>e.constructor===i))?.[0]}}};static newObject(e={},t=e.type??new Li){const i=new Ui;return i.initialize(e,t),i}initialize(e={},t=e.type??new Li){e.windowOptions??={},this.type=e.type,this.windowOptions=e.windowOptions,super.initialize(e,t)}computeSizes(){const e=this.getBoundingClientRect();this.sizeX=e.width,this.sizeY=e.height}cleanup(){super.cleanup(),this.acknowledgeClose()}acknowledgeClose(){let e=new CustomEvent(ne.windowCloseEventName);this.dispatchEvent(e)}}class Wi extends Ie{static attributes={...super.attributes,TerminalCategory:le.createType(String),TerminalSubCategory:le.createType(String),bTerminalIsConst:le.createType(Boolean),bTerminalIsWeakPointer:le.createType(Boolean),bTerminalIsUObjectWrapper:le.createType(Boolean)};constructor(e){super(e),this.TerminalCategory,this.TerminalSubCategory,this.bTerminalIsConst,this.bTerminalIsWeakPointer,this.bTerminalIsUObjectWrapper}}class Ki extends Ie{static grammar=this.createGrammar();static createGrammar(){return Te.seq(Te.reg(new RegExp(`(${Be.Regex.Path.source}|${Be.Regex.Symbol.source}\\s*)?\\(\\s*`),1),Te.seq(Be.attributeName,Be.equalSeparation).map((([e,t])=>e)).chain((e=>Be.unknownValue.map((t=>i=>i[e]=t)))).sepBy(Be.commaSeparation),Te.reg(/\s*(?:,\s*)?\)/)).map((([e,t,i])=>{e??="";let s={};return e.length&&(s.lookbehind=e),t.forEach((e=>e(s))),new this(s)}))}constructor(e){super(e,!0)}}class Yi extends ht{#Yt;constructor(e,t){super(t),this.#Yt=e}doWrite(e,t,i=""){return this.#Yt(e,t)}}class Zi extends ht{constructor(e){super(e)}doWrite(e,t,i=""){return t||e.constructor!==String?he.escapeString(e.toString()):`"${he.escapeString(e.toString())}"`}}Be.unknownValue=Te.alt(Be.boolean,He.createGrammar(),Te.str("None").map((()=>new Ve({type:"None"}))),Be.null,Be.number,Ve.fullReferenceGrammar,Be.string,Ye.createGrammar(),Ke.createGrammar(),Ze.createGrammar(),Qe.createGrammar(),nt.createGrammar(),it.createGrammar(),ze.createGrammar(),et.createGrammar(),Ki.createGrammar(),je.createGrammar(),Be.grammarFor(void 0,[Qe]),Be.grammarFor(void 0,[new ue(Number,String,je)])),Me.registerSerializer(null,new Yi(((e,t)=>"()"),null)),Me.registerSerializer(Array,new Yi(((e,t)=>`(${e.map((e=>Me.getSerializer(he.getType(e)).write(e,t)+",")).join("")})`),Array)),Me.registerSerializer(BigInt,new Zi(BigInt)),Me.registerSerializer(Boolean,new Yi(((e,t)=>e?t?"true":"True":t?"false":"False"),Boolean)),Me.registerSerializer(Fe,new Zi(Fe)),Me.registerSerializer(Re,new Zi(Re)),Me.registerSerializer(We,new Zi(We)),Me.registerSerializer(Ue,new Zi(Ue)),Me.registerSerializer(Ze,new Yi(((e,t)=>e.getLookbehind()+"("+e.value.map((e=>Me.getSerializer(he.getType(e)).write(e,t))).join(", ")+")"),Ze)),Me.registerSerializer(Ge,new ht(Ge,ht.bracketsWrapped)),Me.registerSerializer(He,new Zi(He)),Me.registerSerializer(De,new Zi(De)),Me.registerSerializer(Xe,new Zi(Xe)),Me.registerSerializer(Oe,new Zi(Oe)),Me.registerSerializer(Ke,new ht(Ke,((e,t)=>`${e.getLookbehind()}(${t})`),", ",!1,"",(()=>""))),Me.registerSerializer(vt,new ht(vt,ht.bracketsWrapped)),Me.registerSerializer(ze,new ht(ze,ht.bracketsWrapped)),Me.registerSerializer(Ye,new ht(Ye,((e,t)=>`${e.getLookbehind()}(${t})`),", ",!1,"",(()=>""))),Me.registerSerializer(_e,new ht(_e,ht.bracketsWrapped)),Me.registerSerializer(ce,new Yi(((e,t)=>Me.getSerializer(e.getTargetType()).write(e.get(),t)),ce)),Me.registerSerializer(Number,new Zi(Number)),Me.registerSerializer(ut,new pt),Me.registerSerializer(Ve,new Yi((e=>{let t=e.type??"",i=e.path??"";t&&i&&he.isSerialized(e,"path")&&(i=`'${i}'`);let s=t+i;return he.isSerialized(e,"type")&&(s=`"${s}"`),s}),Ve)),Me.registerSerializer(qe,new Zi(qe)),Me.registerSerializer(ot,new ht(ot,((e,t)=>`${e.getLookbehind()} (${t})`),",",!0)),Me.registerSerializer(Qe,new ht(Qe,void 0," ",!1,"",(()=>""))),Me.registerSerializer(Je,new ht(Je)),Me.registerSerializer(Wi,new ht(Wi,ht.bracketsWrapped)),Me.registerSerializer(tt,new Yi(((e,t)=>`X=${e.X} Y=${e.Y}`),tt)),Me.registerSerializer(it,new ht(it,ht.bracketsWrapped)),Me.registerSerializer(String,new Yi(((e,t)=>t?he.escapeString(e):`"${he.escapeString(e)}"`),String)),Me.registerSerializer(st,new Yi(((e,t)=>`${e.P}, ${e.Y}, ${e.R}`),st)),Me.registerSerializer(rt,new Yi(((e,t)=>`${e.X}, ${e.Y}`),rt)),Me.registerSerializer(at,new Yi(((e,t)=>`${e.X}, ${e.Y}, ${e.Z}`),at)),Me.registerSerializer(je,new Zi(je)),Me.registerSerializer(Ki,new ht(Ki,((e,t)=>`${e.getLookbehind()??""}(${t})`))),Me.registerSerializer(ct,new ht(ct,ht.bracketsWrapped)),Me.registerSerializer(et,new ht(et,ht.bracketsWrapped)),Me.registerSerializer(nt,new ht(nt,ht.bracketsWrapped)),function(){const e=(e,t)=>{customElements.define(e,t),gt.registerElement(e,t)};e("ueb-color-handler",ui),e("ueb-dropdown",gi),e("ueb-input",vi),e("ueb-link",Dt),e("ueb-node",ni),e("ueb-pin",Ri),e("ueb-selector",ji),e("ueb-ui-slider",pi),e("ueb-window",Ui)}();export{ai as Blueprint,ne as Configuration,Dt as LinkElement,ni as NodeElement,he as Utility}; diff --git a/js/Configuration.js b/js/Configuration.js index eb3db99..ac47b8b 100755 --- a/js/Configuration.js +++ b/js/Configuration.js @@ -153,6 +153,7 @@ export default class Configuration { makeMap: "/Script/BlueprintGraph.K2Node_MakeMap", makeSet: "/Script/BlueprintGraph.K2Node_MakeSet", makeStruct: "/Script/BlueprintGraph.K2Node_MakeStruct", + materialExpressionComponentMask: "/Script/Engine.MaterialExpressionComponentMask", materialExpressionConstant: "/Script/Engine.MaterialExpressionConstant", materialExpressionConstant2Vector: "/Script/Engine.MaterialExpressionConstant2Vector", materialExpressionConstant3Vector: "/Script/Engine.MaterialExpressionConstant3Vector", @@ -328,6 +329,8 @@ export default class Configuration { "Alt", "Meta", ] + /** @type {["R", "G", "B", "A"]} */ + static rgba = ["R", "G", "B", "A"] static Keys = { /* UE name: JS name */ "Backspace": "Backspace", diff --git a/js/Utility.js b/js/Utility.js index 528c5a4..5d52f08 100755 --- a/js/Utility.js +++ b/js/Utility.js @@ -189,6 +189,12 @@ export default class Utility { * @param {Attribute} b */ static equals(a, b) { + while (a instanceof MirroredEntity) { + a = a.get() + } + while (b instanceof MirroredEntity) { + b = b.get() + } // Here we cannot check both instanceof IEntity because this would introduce a circular include dependency if (/** @type {IEntity?} */(a)?.equals && /** @type {IEntity?} */(b)?.equals) { return /** @type {IEntity} */(a).equals(/** @type {IEntity} */(b)) @@ -423,6 +429,11 @@ export default class Utility { return Array.from({ length: Math.ceil((end - begin) / step) }, (_, i) => begin + (i * step)) } + /** @param {String[]} words */ + static getFirstWordOrder(words) { + return new RegExp(/\s*/.source + words.join(/[^\n]+\n\s*/.source) + /\s*/.source) + } + /** * @param {HTMLElement} element * @param {String} value diff --git a/js/element/NodeElement.js b/js/element/NodeElement.js index 0c1b31a..a1a2b98 100644 --- a/js/element/NodeElement.js +++ b/js/element/NodeElement.js @@ -1,18 +1,18 @@ -import CommentNodeTemplate from "../template/node/CommentNodeTemplate.js" import Configuration from "../Configuration.js" -import EventNodeTemplate from "../template/node/EventNodeTemplate.js" +import Utility from "../Utility.js" import IdentifierEntity from "../entity/IdentifierEntity.js" -import ISelectableDraggableElement from "./ISelectableDraggableElement.js" -import KnotNodeTemplate from "../template/node/KnotNodeTemplate.js" -import NodeTemplate from "../template/node/NodeTemplate.js" import ObjectEntity from "../entity/ObjectEntity.js" import PinEntity from "../entity/PinEntity.js" import PinReferenceEntity from "../entity/PinReferenceEntity.js" import SerializerFactory from "../serialization/SerializerFactory.js" -import Utility from "../Utility.js" +import CommentNodeTemplate from "../template/node/CommentNodeTemplate.js" +import EventNodeTemplate from "../template/node/EventNodeTemplate.js" +import KnotNodeTemplate from "../template/node/KnotNodeTemplate.js" +import NodeTemplate from "../template/node/NodeTemplate.js" import VariableAccessNodeTemplate from "../template/node/VariableAccessNodeTemplate.js" import VariableConversionNodeTemplate from "../template/node/VariableConversionNodeTemplate.js" import VariableOperationNodeTemplate from "../template/node/VariableOperationNodeTemplate.js" +import ISelectableDraggableElement from "./ISelectableDraggableElement.js" /** @extends {ISelectableDraggableElement} */ export default class NodeElement extends ISelectableDraggableElement { @@ -200,15 +200,15 @@ export default class NodeElement extends ISelectableDraggableElement { } initialize(entity = new ObjectEntity(), template = new (NodeElement.getTypeTemplate(entity))()) { + this.typePath = entity.getType() + this.nodeTitle = entity.getObjectName() + this.advancedPinDisplay = entity.AdvancedPinDisplay?.toString() + this.enabledState = entity.EnabledState + this.nodeDisplayName = entity.nodeDisplayName() + this.pureFunction = entity.bIsPureFunc + this.dragLinkObjects = [] super.initialize(entity, template) this.#pins = this.template.createPinElements() - this.typePath = this.entity.getType() - this.nodeTitle = this.entity.getObjectName() - this.advancedPinDisplay = this.entity.AdvancedPinDisplay?.toString() - this.enabledState = this.entity.EnabledState - this.nodeDisplayName = this.getNodeDisplayName() - this.pureFunction = this.entity.bIsPureFunc - this.dragLinkObjects = [] super.setLocation(this.entity.getNodePosX(), this.entity.getNodePosY()) if (this.entity.NodeWidth && this.entity.NodeHeight) { this.sizeX = this.entity.NodeWidth.value @@ -260,8 +260,8 @@ export default class NodeElement extends ISelectableDraggableElement { return this.entity.getObjectName() } - getNodeDisplayName() { - return this.entity.nodeDisplayName() + computeNodeDisplayName() { + this.nodeDisplayName = this.entity.nodeDisplayName() } /** @param {Number} value */ diff --git a/js/element/PinElement.js b/js/element/PinElement.js index 5d5afb5..c9952ad 100644 --- a/js/element/PinElement.js +++ b/js/element/PinElement.js @@ -1,25 +1,25 @@ -import BoolPinTemplate from "../template/pin/BoolPinTemplate.js" import Configuration from "../Configuration.js" -import ElementFactory from "./ElementFactory.js" -import EnumPinTemplate from "../template/pin/EnumPinTemplate.js" -import ExecPinTemplate from "../template/pin/ExecPinTemplate.js" +import Utility from "../Utility.js" import GuidEntity from "../entity/GuidEntity.js" -import IElement from "./IElement.js" -import Int64PinTemplate from "../template/pin/Int64PinTemplate.js" -import IntPinTemplate from "../template/pin/IntPinTemplate.js" import LinearColorEntity from "../entity/LinearColorEntity.js" -import LinearColorPinTemplate from "../template/pin/LinearColorPinTemplate.js" -import NamePinTemplate from "../template/pin/NamePinTemplate.js" import PinEntity from "../entity/PinEntity.js" import PinReferenceEntity from "../entity/PinReferenceEntity.js" +import BoolPinTemplate from "../template/pin/BoolPinTemplate.js" +import EnumPinTemplate from "../template/pin/EnumPinTemplate.js" +import ExecPinTemplate from "../template/pin/ExecPinTemplate.js" +import Int64PinTemplate from "../template/pin/Int64PinTemplate.js" +import IntPinTemplate from "../template/pin/IntPinTemplate.js" +import LinearColorPinTemplate from "../template/pin/LinearColorPinTemplate.js" +import NamePinTemplate from "../template/pin/NamePinTemplate.js" import PinTemplate from "../template/pin/PinTemplate.js" import RealPinTemplate from "../template/pin/RealPinTemplate.js" import ReferencePinTemplate from "../template/pin/ReferencePinTemplate.js" import RotatorPinTemplate from "../template/pin/RotatorPinTemplate.js" import StringPinTemplate from "../template/pin/StringPinTemplate.js" -import Utility from "../Utility.js" import Vector2DPinTemplate from "../template/pin/Vector2DPinTemplate.js" import VectorPinTemplate from "../template/pin/VectorPinTemplate.js" +import ElementFactory from "./ElementFactory.js" +import IElement from "./IElement.js" /** * @template {TerminalAttribute} T @@ -202,6 +202,9 @@ export default class PinElement extends IElement { setDefaultValue(value) { this.entity.DefaultValue = value this.defaultValue = value + if (this.entity.recomputesNodeTitleOnChange) { + this.nodeElement?.computeNodeDisplayName() + } } /** @param {IElement[]} nodesWhitelist */ @@ -237,6 +240,9 @@ export default class PinElement extends IElement { if (this.entity.linkTo(targetPinElement.getNodeElement().getNodeName(), targetPinElement.entity)) { this.isLinked = this.entity.isLinked() this.nodeElement?.template.linksChanged() + if (this.entity.recomputesNodeTitleOnChange) { + this.nodeElement?.computeNodeDisplayName() + } } } @@ -248,6 +254,9 @@ export default class PinElement extends IElement { if (removeLink) { this.blueprint.getLink(this, targetPinElement)?.remove() // Might be called after the link is removed } + if (this.entity.recomputesNodeTitleOnChange) { + this.nodeElement?.computeNodeDisplayName() + } } } diff --git a/js/entity/AttributeInfo.js b/js/entity/AttributeInfo.js new file mode 100644 index 0000000..79f1f7c --- /dev/null +++ b/js/entity/AttributeInfo.js @@ -0,0 +1,114 @@ +/** + * @template T + * @typedef {{ + * type?: AttributeTypeDescription, + * default?: T, + * nullable?: Boolean, + * ignored?: Boolean, + * serialized?: Boolean, + * expected?: Boolean, + * inlined?: Boolean, + * quoted?: Boolean, + * silent?: Boolean, + * predicate?: (value: T) => Boolean, + * }} AttributeInfoSource + */ + +/** @template T */ +export default class AttributeInfo { + + /** @typedef {keyof AttributeInfo} AttributeKey */ + + static #default = { + nullable: false, + ignored: false, // Never serialize or deserialize + serialized: false, // Value is written and read as string + expected: false, // Must be there + inlined: false, // The key is a subobject or array and printed as inlined (A.B=123, A(0)=123) + quoted: false, // Key is serialized with quotes + silent: false, // Do not serialize if default + } + + /** @param {AttributeInfoSource} source */ + constructor(source) { + this.type = source.type ?? source.default?.constructor + this.default = source.default + this.nullable = source.nullable ?? source.default === null + this.ignored = source.ignored + this.serialized = source.serialized + this.expected = source.expected + this.inlined = source.inlined + this.quoted = source.quoted + this.silent = source.silent + this.predicate = source.predicate + if (this.type === Array && this.default instanceof Array && this.default.length > 0) { + this.type = this.default + .map(v => v.constructor) + .reduce((acc, cur) => acc.includes(cur) ? acc : (acc.push(cur), acc), []) + } + } + + /** + * @template {AttributeTypeDescription} D + * @param {D} type + * @returns {AttributeInfo>} + */ + static createType(type) { + return new AttributeInfo({ type }) + } + + /** + * @template V + * @param {V} value + */ + static createValue(value) { + return new AttributeInfo({ default: value }) + } + + /** + * @param {IEntity | Object} source + * @param {String} attribute + * @param {AttributeKey} key + */ + static hasAttribute(source, attribute, key, type = /** @type {EntityConstructor} */(source.constructor)) { + const entity = /** @type {IEntity} */(source) + const result = entity.attributes[attribute]?.[key] + return /** @type {result} */( + result + ?? type?.attributes?.[attribute]?.[key] + ?? AttributeInfo.#default[key] + ) + } + + /** + * @template {IEntity | Object} S + * @template {EntityConstructor} C + * @template {keyof C["attributes"]} A + * @template {keyof C["attributes"][attribute]} K + * @param {S} source + * @param {A} attribute + * @param {K} key + * @param {C} type + * @returns {C["attributes"][attribute][key]} + */ + static getAttribute(source, attribute, key, type = /** @type {C} */(source.constructor)) { + let result = source["attributes"]?.[attribute]?.[key] + // Remember null is a valid asignment value for some attributes + if (result !== undefined) { + return result + } + result = /** @type {C["attributes"]} */(type?.attributes)?.[attribute]?.[key] + if (result !== undefined) { + return result + } + result = /** @type {C["attributes"][attribute]} */(AttributeInfo.#default)[key] + if (result !== undefined) { + return result + } + } + + /** @param {AttributeKey} key */ + get(key) { + return this[key] ?? AttributeInfo.#default[key] + } +} diff --git a/js/entity/Base64ObjectsEncoded.js b/js/entity/Base64ObjectsEncoded.js index a347cfe..b6b338c 100644 --- a/js/entity/Base64ObjectsEncoded.js +++ b/js/entity/Base64ObjectsEncoded.js @@ -1,15 +1,14 @@ +import AttributeInfo from "./AttributeInfo.js" import IEntity from "./IEntity.js" export default class Base64ObjectsEncoded extends IEntity { static attributes = { ...super.attributes, - value: { - type: String, - }, - objects: { + value: AttributeInfo.createType(String), + objects: new AttributeInfo({ ignored: true, - }, + }), } constructor(values) { diff --git a/js/entity/ByteEntity.js b/js/entity/ByteEntity.js index 0c05018..1660d21 100755 --- a/js/entity/ByteEntity.js +++ b/js/entity/ByteEntity.js @@ -1,17 +1,15 @@ -import IntegerEntity from "./IntegerEntity.js" import Parsernostrum from "parsernostrum" +import AttributeInfo from "./AttributeInfo.js" +import IntegerEntity from "./IntegerEntity.js" export default class ByteEntity extends IntegerEntity { static attributes = { ...super.attributes, - value: { + value: new AttributeInfo({ ...super.attributes.value, predicate: v => v % 1 == 0 && v >= 0 && v < 1 << 8, - }, - } - static { - this.cleanupAttributes(this.attributes) + }), } static grammar = this.createGrammar() diff --git a/js/entity/ColorChannelEntity.js b/js/entity/ColorChannelEntity.js index e4fc328..e58d5f3 100644 --- a/js/entity/ColorChannelEntity.js +++ b/js/entity/ColorChannelEntity.js @@ -1,16 +1,12 @@ -import IEntity from "./IEntity.js" import Parsernostrum from "parsernostrum" +import AttributeInfo from "./AttributeInfo.js" +import IEntity from "./IEntity.js" export default class ColorChannelEntity extends IEntity { static attributes = { ...super.attributes, - value: { - default: 0, - }, - } - static { - this.cleanupAttributes(this.attributes) + value: AttributeInfo.createValue(0), } static grammar = this.createGrammar() diff --git a/js/entity/EnumDisplayValueEntity.js b/js/entity/EnumDisplayValueEntity.js index 6968838..76d6031 100755 --- a/js/entity/EnumDisplayValueEntity.js +++ b/js/entity/EnumDisplayValueEntity.js @@ -1,6 +1,6 @@ -import EnumEntity from "./EnumEntity.js" -import Grammar from "../serialization/Grammar.js" import Parsernostrum from "parsernostrum" +import Grammar from "../serialization/Grammar.js" +import EnumEntity from "./EnumEntity.js" export default class EnumDisplayValueEntity extends EnumEntity { diff --git a/js/entity/FormatTextEntity.js b/js/entity/FormatTextEntity.js index d5e3e84..a31fd0a 100644 --- a/js/entity/FormatTextEntity.js +++ b/js/entity/FormatTextEntity.js @@ -1,22 +1,23 @@ +import Parsernostrum from "parsernostrum" import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" import IEntity from "./IEntity.js" import InvariantTextEntity from "./InvariantTextEntity.js" import LocalizedTextEntity from "./LocalizedTextEntity.js" -import Parsernostrum from "parsernostrum" import Union from "./Union.js" export default class FormatTextEntity extends IEntity { - static lookbehind = new Union("LOCGEN_FORMAT_NAMED", "LOCGEN_FORMAT_ORDERED") static attributes = { ...super.attributes, - value: { + value: new AttributeInfo({ type: [new Union(String, LocalizedTextEntity, InvariantTextEntity, FormatTextEntity)], default: [], - }, - } - static { - this.cleanupAttributes(this.attributes) + }), + lookbehind: /** @type {AttributeInfo>} */(new AttributeInfo({ + ...super.attributes.lookbehind, + default: new Union("LOCGEN_FORMAT_NAMED", "LOCGEN_FORMAT_ORDERED"), + })), } static grammar = this.createGrammar() @@ -24,7 +25,7 @@ export default class FormatTextEntity extends IEntity { return Parsernostrum.seq( Parsernostrum.reg( // Resulting regex: /(LOCGEN_FORMAT_NAMED|LOCGEN_FORMAT_ORDERED)\s*/ - new RegExp(`(${this.lookbehind.values.reduce((acc, cur) => acc + "|" + cur)})\\s*`), + new RegExp(`(${this.attributes.lookbehind.default.values.reduce((acc, cur) => acc + "|" + cur)})\\s*`), 1 ), Grammar.grammarFor(this.attributes.value) @@ -32,8 +33,8 @@ export default class FormatTextEntity extends IEntity { .map(([lookbehind, values]) => { const result = new this({ value: values, + lookbehind, }) - result.lookbehind = lookbehind return result }) } diff --git a/js/entity/FunctionReferenceEntity.js b/js/entity/FunctionReferenceEntity.js index e9e2d01..e97040f 100755 --- a/js/entity/FunctionReferenceEntity.js +++ b/js/entity/FunctionReferenceEntity.js @@ -1,4 +1,5 @@ import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" import GuidEntity from "./GuidEntity.js" import IEntity from "./IEntity.js" import ObjectReferenceEntity from "./ObjectReferenceEntity.js" @@ -7,18 +8,9 @@ export default class FunctionReferenceEntity extends IEntity { static attributes = { ...super.attributes, - MemberParent: { - type: ObjectReferenceEntity, - }, - MemberName: { - type: String, - }, - MemberGuid: { - type: GuidEntity, - }, - } - static { - this.cleanupAttributes(this.attributes) + MemberParent: AttributeInfo.createType(ObjectReferenceEntity), + MemberName: AttributeInfo.createType(String), + MemberGuid: AttributeInfo.createType(GuidEntity), } static grammar = this.createGrammar() diff --git a/js/entity/GuidEntity.js b/js/entity/GuidEntity.js index c3dbc11..06b312f 100755 --- a/js/entity/GuidEntity.js +++ b/js/entity/GuidEntity.js @@ -1,16 +1,19 @@ import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" import IEntity from "./IEntity.js" +var crypto +if (typeof window === "undefined") { + import("crypto").then(mod => crypto = mod.default).catch() +} else { + crypto = window.crypto +} + export default class GuidEntity extends IEntity { static attributes = { ...super.attributes, - value: { - default: "", - }, - } - static { - this.cleanupAttributes(this.attributes) + value: AttributeInfo.createValue(""), } static grammar = this.createGrammar() diff --git a/js/entity/IEntity.js b/js/entity/IEntity.js index a28fee1..0c4681b 100644 --- a/js/entity/IEntity.js +++ b/js/entity/IEntity.js @@ -1,121 +1,85 @@ -import ComputedType from "./ComputedType.js" import Configuration from "../Configuration.js" -import MirroredEntity from "./MirroredEntity.js" +import Utility from "../Utility.js" import Serializable from "../serialization/Serializable.js" import SerializerFactory from "../serialization/SerializerFactory.js" +import AttributeInfo from "./AttributeInfo.js" +import ComputedType from "./ComputedType.js" +import MirroredEntity from "./MirroredEntity.js" import Union from "./Union.js" -import Utility from "../Utility.js" /** @abstract */ export default class IEntity extends Serializable { - /** @type {String | Union} */ - static lookbehind = "" - /** @type {AttributeDeclarations} */ static attributes = { - lookbehind: { + attributes: new AttributeInfo({ ignored: true, - } - } - static defaultAttribute = { - nullable: false, - ignored: false, - serialized: false, // Value is written and read as string - expected: false, // Must be there - inlined: false, // The key is a subobject or array and printed as inlined (A.B=123, A(0)=123) - quoted: false, // Key is serialized with quotes + }), + lookbehind: new AttributeInfo({ + default: /** @type {String | Union} */(""), + ignored: true, + }), } constructor(values = {}, suppressWarns = false) { super() - /** @type {String} */ this.lookbehind const Self = /** @type {typeof IEntity} */(this.constructor) - let attributes = Self.attributes - if (values.attributes) { - attributes = { ...Self.attributes } - Utility.mergeArrays(Object.keys(values.attributes), Object.keys(attributes)) - .forEach(k => { - attributes[k] = { - ...IEntity.defaultAttribute, - ...attributes[k], - ...values.attributes[k], - } - if (!attributes[k].type) { - attributes[k].type = values[k] instanceof Array - ? [Utility.getType(values[k][0])] - : Utility.getType(values[k]) - } - }) - IEntity.defineAttributes(this, attributes) - } /** @type {AttributeDeclarations?} */ this.attributes - const valuesNames = Object.keys(values) - const attributesNames = Object.keys(attributes) - const allAttributesNames = Utility.mergeArrays(valuesNames, attributesNames) - if (valuesNames.includes("lookbehind")) { - this.lookbehind = undefined // To keep it first - } - for (const attributeName of allAttributesNames) { - if (attributeName == "attributes") { - // Ignore this special attribute describing all the attributes - continue - } - let value = values[attributeName] - let attribute = attributes[attributeName] - - if (!suppressWarns && value !== undefined) { - if ( - !(attributeName in attributes) - && !attributeName.startsWith(Configuration.subObjectAttributeNamePrefix) - ) { + /** @type {String} */ this.lookbehind + const valuesKeys = Object.keys(values) + const attributesKeys = values.attributes + ? Utility.mergeArrays(Object.keys(values.attributes), Object.keys(Self.attributes)) + : Object.keys(Self.attributes) + const allAttributesKeys = Utility.mergeArrays(valuesKeys, attributesKeys) + for (const key of allAttributesKeys) { + let value = values[key] + if (!suppressWarns && !(key in values)) { + if (!(key in Self.attributes) && !key.startsWith(Configuration.subObjectAttributeNamePrefix)) { const typeName = value instanceof Array ? `[${value[0]?.constructor.name}]` : value.constructor.name console.warn( - `UEBlueprint: Attribute ${attributeName} (of type ${typeName}) in the serialized data is not ` - + `defined in ${Self.name}.attributes` + `UEBlueprint: Attribute ${key} (of type ${typeName}) in the serialized data is not defined in ${Self.name}.attributes` ) } } - - if (!attribute) { + if (!(key in Self.attributes)) { // Remember attributeName can come from the values and be not defined in the attributes. // In that case just assign it and skip the rest. - this[attributeName] = value + this[key] = value continue } - - const assignAttribute = !attribute.predicate - ? v => this[attributeName] = v + Self.attributes.lookbehind + const predicate = AttributeInfo.getAttribute(values, key, "predicate", Self) + const assignAttribute = !predicate + ? v => this[key] = v : v => { Object.defineProperties(this, { - ["#" + attributeName]: { + ["#" + key]: { writable: true, enumerable: false, }, - [attributeName]: { + [key]: { enumerable: true, get() { - return this["#" + attributeName] + return this["#" + key] }, set(v) { - if (!attribute.predicate?.(v)) { + if (!predicate(v)) { console.warn( - `UEBlueprint: Tried to assign attribute ${attributeName} to ${Self.name} not ` - + "satisfying the predicate" + `UEBlueprint: Tried to assign attribute ${key} to ${Self.name} not satisfying the predicate` ) return } - this["#" + attributeName] = v + this["#" + key] = v } }, }) - this[attributeName] = v + this[key] = v } - let defaultValue = attribute.default + let defaultValue = AttributeInfo.getAttribute(values, key, "default", Self) if (defaultValue instanceof Function) { defaultValue = defaultValue(this) } - let defaultType = attribute.type + let defaultType = AttributeInfo.getAttribute(values, key, "type", Self) if (defaultType instanceof ComputedType) { defaultType = defaultType.compute(this) } @@ -128,16 +92,24 @@ export default class IEntity extends Serializable { if (value !== undefined) { // Remember value can still be null - if (value?.constructor === String && attribute.serialized && defaultType !== String) { - value = SerializerFactory - // @ts-expect-error - .getSerializer(defaultType) - .read(/** @type {String} */(value)) + if ( + value?.constructor === String + && AttributeInfo.getAttribute(values, key, "serialized", Self) + && defaultType !== String + ) { + try { + value = SerializerFactory + .getSerializer(defaultType) + .read(/** @type {String} */(value)) + } catch (e) { + assignAttribute(value) + continue + } } assignAttribute(Utility.sanitize(value, /** @type {AttributeConstructor} */(defaultType))) continue // We have a value, need nothing more } - if (Object.hasOwn(attribute, "default")) { // Accept also explicit undefined + if (defaultValue !== undefined) { assignAttribute(defaultValue) } } @@ -166,31 +138,6 @@ export default class IEntity extends Serializable { } } - /** @param {AttributeDeclarations} attributes */ - static cleanupAttributes(attributes, prefix = "") { - for (const attributeName in attributes) { - attributes[attributeName] = { - ...IEntity.defaultAttribute, - ...attributes[attributeName], - } - const attribute = /** @type {AttributeInformation} */(attributes[attributeName]) - if (attribute.type === undefined && !(attribute.default instanceof Function)) { - attribute.type = attribute.default instanceof Array - ? [Utility.getType(attribute.default[0])] - : Utility.getType(attribute.default) - } - if (!attribute.ignored && attribute.default === undefined && attribute.type === undefined) { - throw new Error( - `UEBlueprint: Expected either "type" or "value" property in ${this.name} attribute ${prefix}` - + attributeName - ) - } - if (attribute.default === null) { - attribute.nullable = true - } - } - } - /** * @template {new (...args: any) => any} C * @param {C} type @@ -224,7 +171,7 @@ export default class IEntity extends Serializable { } getLookbehind() { - let lookbehind = this.lookbehind ?? /** @type {EntityConstructor} */(this.constructor).lookbehind + let lookbehind = this.lookbehind ?? AttributeInfo.getAttribute(this, "lookbehind", "default") lookbehind = lookbehind instanceof Union ? lookbehind.values[0] : lookbehind return lookbehind } diff --git a/js/entity/IdentifierEntity.js b/js/entity/IdentifierEntity.js index 784eac6..f4a1fbe 100644 --- a/js/entity/IdentifierEntity.js +++ b/js/entity/IdentifierEntity.js @@ -1,16 +1,12 @@ import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" import IEntity from "./IEntity.js" export default class IdentifierEntity extends IEntity { static attributes = { ...super.attributes, - value: { - default: "", - }, - } - static { - this.cleanupAttributes(this.attributes) + value: AttributeInfo.createValue(""), } static attributeConverter = { fromAttribute: (value, type) => new IdentifierEntity(value), diff --git a/js/entity/Integer64Entity.js b/js/entity/Integer64Entity.js index f5228c2..28d0e22 100755 --- a/js/entity/Integer64Entity.js +++ b/js/entity/Integer64Entity.js @@ -1,17 +1,15 @@ -import IEntity from "./IEntity.js" import Parsernostrum from "parsernostrum" +import AttributeInfo from "./AttributeInfo.js" +import IEntity from "./IEntity.js" export default class Integer64Entity extends IEntity { static attributes = { ...super.attributes, - value: { + value: new AttributeInfo({ default: 0n, predicate: v => v >= -(1n << 63n) && v < 1n << 63n, - }, - } - static { - this.cleanupAttributes(this.attributes) + }), } static grammar = this.createGrammar() diff --git a/js/entity/IntegerEntity.js b/js/entity/IntegerEntity.js index 5ef770c..aca2daa 100755 --- a/js/entity/IntegerEntity.js +++ b/js/entity/IntegerEntity.js @@ -1,17 +1,15 @@ -import IEntity from "./IEntity.js" import Parsernostrum from "parsernostrum" +import AttributeInfo from "./AttributeInfo.js" +import IEntity from "./IEntity.js" export default class IntegerEntity extends IEntity { static attributes = { ...super.attributes, - value: { + value: new AttributeInfo({ default: 0, predicate: v => v % 1 == 0 && v > 1 << 31 && v < -(1 << 31), - }, - } - static { - this.cleanupAttributes(this.attributes) + }), } static grammar = this.createGrammar() @@ -19,7 +17,7 @@ export default class IntegerEntity extends IEntity { return Parsernostrum.numberInteger.map(v => new this(v)) } - /** @param {Number | AttributeInformation} value */ + /** @param {Number | AttributeInfo} value */ constructor(value = 0) { if (value === -0) { value = 0 diff --git a/js/entity/InvariantTextEntity.js b/js/entity/InvariantTextEntity.js index 51912de..7c5ca74 100644 --- a/js/entity/InvariantTextEntity.js +++ b/js/entity/InvariantTextEntity.js @@ -1,30 +1,29 @@ -import Grammar from "../serialization/Grammar.js" -import IEntity from "./IEntity.js" import Parsernostrum from "parsernostrum" +import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" +import IEntity from "./IEntity.js" export default class InvariantTextEntity extends IEntity { - static lookbehind = "INVTEXT" static attributes = { ...super.attributes, - value: { - default: "", - }, - } - static { - this.cleanupAttributes(this.attributes) + value: AttributeInfo.createValue(""), + lookbehind: new AttributeInfo({ + ...super.attributes.lookbehind, + default: "INVTEXT", + }), } static grammar = this.createGrammar() static createGrammar() { return Parsernostrum.alt( Parsernostrum.seq( - Parsernostrum.reg(new RegExp(`${this.lookbehind}\\s*\\(`)), + Parsernostrum.reg(new RegExp(`${this.attributes.lookbehind.default}\\s*\\(`)), Grammar.grammarFor(this.attributes.value), Parsernostrum.reg(/\s*\)/) ) .map(([_0, value, _2]) => value), - Parsernostrum.reg(new RegExp(this.lookbehind)) // InvariantTextEntity can not have arguments + Parsernostrum.reg(new RegExp(this.attributes.lookbehind.default)) // InvariantTextEntity can not have arguments .map(() => "") ).map(value => new this(value)) } diff --git a/js/entity/KeyBindingEntity.js b/js/entity/KeyBindingEntity.js index 0be0616..6ae25f9 100644 --- a/js/entity/KeyBindingEntity.js +++ b/js/entity/KeyBindingEntity.js @@ -1,33 +1,19 @@ -import Grammar from "../serialization/Grammar.js" -import IdentifierEntity from "./IdentifierEntity.js" -import IEntity from "./IEntity.js" import Parsernostrum from "parsernostrum" +import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" +import IEntity from "./IEntity.js" +import IdentifierEntity from "./IdentifierEntity.js" export default class KeyBindingEntity extends IEntity { static attributes = { ...super.attributes, - ActionName: { - default: "", - }, - bShift: { - default: false, - }, - bCtrl: { - default: false, - }, - bAlt: { - default: false, - }, - bCmd: { - default: false, - }, - Key: { - type: IdentifierEntity, - }, - } - static { - this.cleanupAttributes(this.attributes) + ActionName: AttributeInfo.createValue(""), + bShift: AttributeInfo.createValue(false), + bCtrl: AttributeInfo.createValue(false), + bAlt: AttributeInfo.createValue(false), + bCmd: AttributeInfo.createValue(false), + Key: AttributeInfo.createType(IdentifierEntity), } static grammar = this.createGrammar() diff --git a/js/entity/LinearColorEntity.js b/js/entity/LinearColorEntity.js index 47d211a..03cb146 100644 --- a/js/entity/LinearColorEntity.js +++ b/js/entity/LinearColorEntity.js @@ -1,51 +1,49 @@ import { css } from "lit" -import ColorChannelEntity from "./ColorChannelEntity.js" -import Grammar from "../serialization/Grammar.js" -import IEntity from "./IEntity.js" import Parsernostrum from "parsernostrum" import Utility from "../Utility.js" +import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" +import ColorChannelEntity from "./ColorChannelEntity.js" +import IEntity from "./IEntity.js" export default class LinearColorEntity extends IEntity { static attributes = { ...super.attributes, - R: { + R: new AttributeInfo({ type: ColorChannelEntity, default: () => new ColorChannelEntity(), expected: true, - }, - G: { + }), + G: new AttributeInfo({ type: ColorChannelEntity, default: () => new ColorChannelEntity(), expected: true, - }, - B: { + }), + B: new AttributeInfo({ type: ColorChannelEntity, default: () => new ColorChannelEntity(), expected: true, - }, - A: { + }), + A: new AttributeInfo({ type: ColorChannelEntity, default: () => new ColorChannelEntity(1), - }, - H: { + }), + H: new AttributeInfo({ type: ColorChannelEntity, default: () => new ColorChannelEntity(), ignored: true, - }, - S: { + }), + S: new AttributeInfo({ type: ColorChannelEntity, default: () => new ColorChannelEntity(), ignored: true, - }, - V: { + }), + V: new AttributeInfo({ type: ColorChannelEntity, default: () => new ColorChannelEntity(), ignored: true, - }, - } - static { - this.cleanupAttributes(this.attributes) + }), } static grammar = this.createGrammar() diff --git a/js/entity/LocalizedTextEntity.js b/js/entity/LocalizedTextEntity.js index aa0137b..c9cd0ac 100755 --- a/js/entity/LocalizedTextEntity.js +++ b/js/entity/LocalizedTextEntity.js @@ -1,31 +1,26 @@ -import Grammar from "../serialization/Grammar.js" -import IEntity from "./IEntity.js" import Parsernostrum from "parsernostrum" import Utility from "../Utility.js" +import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" +import IEntity from "./IEntity.js" export default class LocalizedTextEntity extends IEntity { - static lookbehind = "NSLOCTEXT" static attributes = { ...super.attributes, - namespace: { - default: "", - }, - key: { - default: "", - }, - value: { - default: "", - }, - } - static { - this.cleanupAttributes(this.attributes) + namespace: AttributeInfo.createValue(""), + key: AttributeInfo.createValue(""), + value: AttributeInfo.createValue(""), + lookbehind: new AttributeInfo({ + ...super.attributes.lookbehind, + default: "NSLOCTEXT", + }), } static grammar = this.createGrammar() static createGrammar() { return Parsernostrum.regArray(new RegExp( - String.raw`${this.lookbehind}\s*\(` + String.raw`${this.attributes.lookbehind.default}\s*\(` + String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*,` + String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*,` + String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*` diff --git a/js/entity/MacroGraphReferenceEntity.js b/js/entity/MacroGraphReferenceEntity.js index be0668c..38f920d 100755 --- a/js/entity/MacroGraphReferenceEntity.js +++ b/js/entity/MacroGraphReferenceEntity.js @@ -1,4 +1,5 @@ import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" import GuidEntity from "./GuidEntity.js" import IEntity from "./IEntity.js" import ObjectReferenceEntity from "./ObjectReferenceEntity.js" @@ -7,21 +8,18 @@ export default class MacroGraphReferenceEntity extends IEntity { static attributes = { ...super.attributes, - MacroGraph: { + MacroGraph: new AttributeInfo({ type: ObjectReferenceEntity, default: () => new ObjectReferenceEntity(), - }, - GraphBlueprint: { + }), + GraphBlueprint: new AttributeInfo({ type: ObjectReferenceEntity, default: () => new ObjectReferenceEntity(), - }, - GraphGuid: { + }), + GraphGuid: new AttributeInfo({ type: GuidEntity, default: () => new GuidEntity(), - }, - } - static { - this.cleanupAttributes(this.attributes) + }), } static grammar = this.createGrammar() diff --git a/js/entity/MirroredEntity.js b/js/entity/MirroredEntity.js index b8427f9..8bf71d2 100644 --- a/js/entity/MirroredEntity.js +++ b/js/entity/MirroredEntity.js @@ -1,13 +1,15 @@ +import AttributeInfo from "./AttributeInfo.js" + /** @template {Attribute} T */ export default class MirroredEntity { static attributes = { - type: { + type: new AttributeInfo({ ignored: true, - }, - getter: { + }), + getter: new AttributeInfo({ ignored: true, - }, + }), } /** diff --git a/js/entity/ObjectEntity.js b/js/entity/ObjectEntity.js index 686e3cf..3b35775 100755 --- a/js/entity/ObjectEntity.js +++ b/js/entity/ObjectEntity.js @@ -1,22 +1,23 @@ +import Parsernostrum from "parsernostrum" import Configuration from "../Configuration.js" -import FunctionReferenceEntity from "./FunctionReferenceEntity.js" +import SVGIcon from "../SVGIcon.js" +import Utility from "../Utility.js" import Grammar from "../serialization/Grammar.js" +import FunctionReferenceEntity from "./FunctionReferenceEntity.js" import GuidEntity from "./GuidEntity.js" -import IdentifierEntity from "./IdentifierEntity.js" import IEntity from "./IEntity.js" +import IdentifierEntity from "./IdentifierEntity.js" import IntegerEntity from "./IntegerEntity.js" import LinearColorEntity from "./LinearColorEntity.js" import MacroGraphReferenceEntity from "./MacroGraphReferenceEntity.js" import MirroredEntity from "./MirroredEntity.js" import ObjectReferenceEntity from "./ObjectReferenceEntity.js" -import Parsernostrum from "parsernostrum" import PinEntity from "./PinEntity.js" -import SVGIcon from "../SVGIcon.js" import SymbolEntity from "./SymbolEntity.js" import Union from "./Union.js" import UnknownPinEntity from "./UnknownPinEntity.js" -import Utility from "../Utility.js" import VariableReferenceEntity from "./VariableReferenceEntity.js" +import AttributeInfo from "./AttributeInfo.js" export default class ObjectEntity extends IEntity { @@ -50,112 +51,123 @@ export default class ObjectEntity extends IEntity { } static attributes = { ...super.attributes, - AdvancedPinDisplay: { type: IdentifierEntity }, - Archetype: { type: ObjectReferenceEntity }, - AxisKey: { type: SymbolEntity }, - bAlt: { type: Boolean }, - bCanRenameNode: { type: Boolean }, - bColorCommentBubble: { type: Boolean }, - bCommand: { type: Boolean }, - bCommentBubblePinned: { type: Boolean }, - bCommentBubbleVisible_InDetailsPanel: { type: Boolean }, - bCommentBubbleVisible: { type: Boolean }, - bConsumeInput: { type: Boolean }, - bControl: { type: Boolean }, - bExecuteWhenPaused: { type: Boolean }, - bExposeToLibrary: { type: Boolean }, - bInternalEvent: { type: Boolean }, - bIsCaseSensitive: { type: Boolean }, - bIsConstFunc: { type: Boolean }, - bIsPureFunc: { type: Boolean }, - BlueprintElementInstance: { type: ObjectReferenceEntity }, - BlueprintElementType: { type: ObjectReferenceEntity }, - bOverrideFunction: { type: Boolean }, - bOverrideParentBinding: { type: Boolean }, - bShift: { type: Boolean }, - Class: { type: ObjectReferenceEntity }, - CommentColor: { type: LinearColorEntity }, - ComponentPropertyName: { type: String }, - CustomFunctionName: { type: String }, - CustomProperties: { type: [new Union(PinEntity, UnknownPinEntity)] }, - DelegateOwnerClass: { type: ObjectReferenceEntity }, - DelegatePropertyName: { type: String }, - DelegateReference: { type: VariableReferenceEntity }, - EnabledState: { type: IdentifierEntity }, - Enum: { type: ObjectReferenceEntity }, - EnumEntries: { + R: new AttributeInfo({ + default: false, + silent: true, + }), + G: new AttributeInfo({ + default: false, + silent: true, + }), + B: new AttributeInfo({ + default: false, + silent: true, + }), + A: new AttributeInfo({ + default: false, + silent: true, + }), + AdvancedPinDisplay: AttributeInfo.createType(IdentifierEntity), + Archetype: AttributeInfo.createType(ObjectReferenceEntity), + AxisKey: AttributeInfo.createType(SymbolEntity), + bAlt: AttributeInfo.createType(Boolean), + bCanRenameNode: AttributeInfo.createType(Boolean), + bColorCommentBubble: AttributeInfo.createType(Boolean), + bCommand: AttributeInfo.createType(Boolean), + bCommentBubblePinned: AttributeInfo.createType(Boolean), + bCommentBubbleVisible_InDetailsPanel: AttributeInfo.createType(Boolean), + bCommentBubbleVisible: AttributeInfo.createType(Boolean), + bConsumeInput: AttributeInfo.createType(Boolean), + bControl: AttributeInfo.createType(Boolean), + bExecuteWhenPaused: AttributeInfo.createType(Boolean), + bExposeToLibrary: AttributeInfo.createType(Boolean), + bInternalEvent: AttributeInfo.createType(Boolean), + bIsCaseSensitive: AttributeInfo.createType(Boolean), + bIsConstFunc: AttributeInfo.createType(Boolean), + bIsPureFunc: AttributeInfo.createType(Boolean), + BlueprintElementInstance: AttributeInfo.createType(ObjectReferenceEntity), + BlueprintElementType: AttributeInfo.createType(ObjectReferenceEntity), + bOverrideFunction: AttributeInfo.createType(Boolean), + bOverrideParentBinding: AttributeInfo.createType(Boolean), + bShift: AttributeInfo.createType(Boolean), + Class: AttributeInfo.createType(ObjectReferenceEntity), + CommentColor: AttributeInfo.createType(LinearColorEntity), + ComponentPropertyName: AttributeInfo.createType(String), + CustomFunctionName: AttributeInfo.createType(String), + CustomProperties: AttributeInfo.createType([new Union(PinEntity, UnknownPinEntity)]), + DelegateOwnerClass: AttributeInfo.createType(ObjectReferenceEntity), + DelegatePropertyName: AttributeInfo.createType(String), + DelegateReference: AttributeInfo.createType(VariableReferenceEntity), + EnabledState: AttributeInfo.createType(IdentifierEntity), + Enum: AttributeInfo.createType(ObjectReferenceEntity), + EnumEntries: new AttributeInfo({ type: [String], inlined: true, - }, - ErrorMsg: { type: String }, - ErrorType: { type: IntegerEntity }, - EventReference: { type: FunctionReferenceEntity }, - ExportPath: { type: ObjectReferenceEntity }, - FunctionReference: { type: FunctionReferenceEntity }, - G: { type: Number }, - Graph: { type: ObjectReferenceEntity }, - HiGenGridSize: { type: SymbolEntity }, - InputAxisKey: { type: SymbolEntity }, - InputKey: { type: SymbolEntity }, - InputName: { type: String }, - InputPins: { + }), + ErrorMsg: AttributeInfo.createType(String), + ErrorType: AttributeInfo.createType(IntegerEntity), + EventReference: AttributeInfo.createType(FunctionReferenceEntity), + ExportPath: AttributeInfo.createType(ObjectReferenceEntity), + FunctionReference: AttributeInfo.createType(FunctionReferenceEntity), + Graph: AttributeInfo.createType(ObjectReferenceEntity), + HiGenGridSize: AttributeInfo.createType(SymbolEntity), + InputAxisKey: AttributeInfo.createType(SymbolEntity), + InputKey: AttributeInfo.createType(SymbolEntity), + InputName: AttributeInfo.createType(String), + InputPins: new AttributeInfo({ type: [ObjectReferenceEntity], inlined: true, - }, - InputType: { type: SymbolEntity }, - MacroGraphReference: { type: MacroGraphReferenceEntity }, - MaterialExpression: { type: ObjectReferenceEntity }, - MaterialExpressionComment: { type: ObjectReferenceEntity }, - MaterialExpressionEditorX: { type: new MirroredEntity(IntegerEntity) }, - MaterialExpressionEditorY: { type: new MirroredEntity(IntegerEntity) }, - MaterialFunction: { type: ObjectReferenceEntity }, - MoveMode: { type: SymbolEntity }, - Name: { type: String }, - Node: { type: new MirroredEntity(ObjectReferenceEntity) }, - NodeComment: { type: String }, - NodeGuid: { type: GuidEntity }, - NodeHeight: { type: IntegerEntity }, - NodePosX: { type: IntegerEntity }, - NodePosY: { type: IntegerEntity }, - NodeTitle: { type: String }, - NodeTitleColor: { type: LinearColorEntity }, - NodeWidth: { type: IntegerEntity }, - NumAdditionalInputs: { type: Number }, - ObjectRef: { type: ObjectReferenceEntity }, - Operation: { type: SymbolEntity }, - OutputPins: { + }), + InputType: AttributeInfo.createType(SymbolEntity), + MacroGraphReference: AttributeInfo.createType(MacroGraphReferenceEntity), + MaterialExpression: AttributeInfo.createType(ObjectReferenceEntity), + MaterialExpressionComment: AttributeInfo.createType(ObjectReferenceEntity), + MaterialExpressionEditorX: AttributeInfo.createType(new MirroredEntity(IntegerEntity)), + MaterialExpressionEditorY: AttributeInfo.createType(new MirroredEntity(IntegerEntity)), + MaterialFunction: AttributeInfo.createType(ObjectReferenceEntity), + MoveMode: AttributeInfo.createType(SymbolEntity), + Name: AttributeInfo.createType(String), + Node: AttributeInfo.createType(new MirroredEntity(ObjectReferenceEntity)), + NodeComment: AttributeInfo.createType(String), + NodeGuid: AttributeInfo.createType(GuidEntity), + NodeHeight: AttributeInfo.createType(IntegerEntity), + NodePosX: AttributeInfo.createType(IntegerEntity), + NodePosY: AttributeInfo.createType(IntegerEntity), + NodeTitle: AttributeInfo.createType(String), + NodeTitleColor: AttributeInfo.createType(LinearColorEntity), + NodeWidth: AttributeInfo.createType(IntegerEntity), + NumAdditionalInputs: AttributeInfo.createType(Number), + ObjectRef: AttributeInfo.createType(ObjectReferenceEntity), + Operation: AttributeInfo.createType(SymbolEntity), + OutputPins: new AttributeInfo({ type: [ObjectReferenceEntity], inlined: true, - }, - PCGNode: { type: ObjectReferenceEntity }, - PinNames: { + }), + PCGNode: AttributeInfo.createType(ObjectReferenceEntity), + PinNames: new AttributeInfo({ type: [String], inlined: true, - }, - PinTags: { + }), + PinTags: new AttributeInfo({ type: [null], inlined: true, - }, - PositionX: { type: new MirroredEntity(IntegerEntity) }, - PositionY: { type: new MirroredEntity(IntegerEntity) }, - ProxyClass: { type: ObjectReferenceEntity }, - ProxyFactoryClass: { type: ObjectReferenceEntity }, - ProxyFactoryFunctionName: { type: String }, - R: { type: Number }, - SelfContextInfo: { type: SymbolEntity }, - SettingsInterface: { type: ObjectReferenceEntity }, - SizeX: { type: new MirroredEntity(IntegerEntity) }, - SizeY: { type: new MirroredEntity(IntegerEntity) }, - StructType: { type: ObjectReferenceEntity }, - SubgraphInstance: { type: String }, - TargetType: { type: ObjectReferenceEntity }, - Text: { type: new MirroredEntity(String) }, - TimelineGuid: { type: GuidEntity }, - TimelineName: { type: String }, - VariableReference: { type: VariableReferenceEntity }, - } - static { - this.cleanupAttributes(this.attributes) + }), + PositionX: AttributeInfo.createType(new MirroredEntity(IntegerEntity)), + PositionY: AttributeInfo.createType(new MirroredEntity(IntegerEntity)), + ProxyClass: AttributeInfo.createType(ObjectReferenceEntity), + ProxyFactoryClass: AttributeInfo.createType(ObjectReferenceEntity), + ProxyFactoryFunctionName: AttributeInfo.createType(String), + SelfContextInfo: AttributeInfo.createType(SymbolEntity), + SettingsInterface: AttributeInfo.createType(ObjectReferenceEntity), + SizeX: AttributeInfo.createType(new MirroredEntity(IntegerEntity)), + SizeY: AttributeInfo.createType(new MirroredEntity(IntegerEntity)), + StructType: AttributeInfo.createType(ObjectReferenceEntity), + SubgraphInstance: AttributeInfo.createType(String), + TargetType: AttributeInfo.createType(ObjectReferenceEntity), + Text: AttributeInfo.createType(new MirroredEntity(String)), + TimelineGuid: AttributeInfo.createType(GuidEntity), + TimelineName: AttributeInfo.createType(String), + VariableReference: AttributeInfo.createType(VariableReferenceEntity), } static nameRegex = /^(\w+?)(?:_(\d+))?$/ static sequencerScriptingNameRegex = /\/Script\/SequencerScripting\.MovieSceneScripting(.+)Channel/ @@ -287,33 +299,21 @@ export default class ObjectEntity extends IEntity { } } super(values, suppressWarns) + + // Attributes not assigned a strong type in attributes because the names are too generic + /** @type {Number | MirroredEntity} */ this.R + /** @type {Number | MirroredEntity} */ this.G + /** @type {Number | MirroredEntity} */ this.B + /** @type {Number | MirroredEntity} */ this.A + + // Attributes /** @type {(PinEntity | UnknownPinEntity)[]} */ this.CustomProperties - /** @type {Boolean} */ this.bAlt - /** @type {Boolean} */ this.bCanRenameNode - /** @type {Boolean} */ this.bColorCommentBubble - /** @type {Boolean} */ this.bCommand - /** @type {Boolean} */ this.bCommentBubblePinned - /** @type {Boolean} */ this.bCommentBubbleVisible - /** @type {Boolean} */ this.bCommentBubbleVisible_InDetailsPanel - /** @type {Boolean} */ this.bConsumeInput - /** @type {Boolean} */ this.bControl - /** @type {Boolean} */ this.bExecuteWhenPaused - /** @type {Boolean} */ this.bExposeToLibrary - /** @type {Boolean} */ this.bInternalEvent - /** @type {Boolean} */ this.bIsCaseSensitive - /** @type {Boolean} */ this.bIsConstFunc /** @type {Boolean} */ this.bIsPureFunc - /** @type {Boolean} */ this.bOverrideFunction - /** @type {Boolean} */ this.bOverrideParentBinding - /** @type {Boolean} */ this.bShift /** @type {FunctionReferenceEntity} */ this.ComponentPropertyName /** @type {FunctionReferenceEntity} */ this.EventReference /** @type {FunctionReferenceEntity} */ this.FunctionReference - /** @type {GuidEntity} */ this.NodeGuid - /** @type {GuidEntity} */ this.TimelineGuid /** @type {IdentifierEntity} */ this.AdvancedPinDisplay /** @type {IdentifierEntity} */ this.EnabledState - /** @type {IntegerEntity} */ this.ErrorType /** @type {IntegerEntity} */ this.NodeHeight /** @type {IntegerEntity} */ this.NodePosX /** @type {IntegerEntity} */ this.NodePosY @@ -330,16 +330,13 @@ export default class ObjectEntity extends IEntity { /** @type {MirroredEntity} */ this.PositionY /** @type {MirroredEntity} */ this.Node /** @type {null[]} */ this.PinTags - /** @type {Number} */ this.G /** @type {Number} */ this.NumAdditionalInputs - /** @type {Number} */ this.R /** @type {ObjectReferenceEntity[]} */ this.InputPins /** @type {ObjectReferenceEntity[]} */ this.OutputPins /** @type {ObjectReferenceEntity} */ this.Archetype /** @type {ObjectReferenceEntity} */ this.BlueprintElementInstance /** @type {ObjectReferenceEntity} */ this.BlueprintElementType /** @type {ObjectReferenceEntity} */ this.Class - /** @type {ObjectReferenceEntity} */ this.DelegateOwnerClass /** @type {ObjectReferenceEntity} */ this.Enum /** @type {ObjectReferenceEntity} */ this.ExportPath /** @type {ObjectReferenceEntity} */ this.Graph @@ -348,8 +345,6 @@ export default class ObjectEntity extends IEntity { /** @type {ObjectReferenceEntity} */ this.MaterialFunction /** @type {ObjectReferenceEntity} */ this.ObjectRef /** @type {ObjectReferenceEntity} */ this.PCGNode - /** @type {ObjectReferenceEntity} */ this.ProxyClass - /** @type {ObjectReferenceEntity} */ this.ProxyFactoryClass /** @type {ObjectReferenceEntity} */ this.SettingsInterface /** @type {ObjectReferenceEntity} */ this.StructType /** @type {ObjectReferenceEntity} */ this.TargetType @@ -357,7 +352,6 @@ export default class ObjectEntity extends IEntity { /** @type {String[]} */ this.PinNames /** @type {String} */ this.CustomFunctionName /** @type {String} */ this.DelegatePropertyName - /** @type {String} */ this.ErrorMsg /** @type {String} */ this.InputName /** @type {String} */ this.Name /** @type {String} */ this.NodeComment @@ -366,14 +360,11 @@ export default class ObjectEntity extends IEntity { /** @type {String} */ this.ProxyFactoryFunctionName /** @type {String} */ this.SubgraphInstance /** @type {String} */ this.Text - /** @type {String} */ this.TimelineName /** @type {SymbolEntity} */ this.AxisKey /** @type {SymbolEntity} */ this.HiGenGridSize /** @type {SymbolEntity} */ this.InputAxisKey /** @type {SymbolEntity} */ this.InputKey /** @type {SymbolEntity} */ this.InputType - /** @type {SymbolEntity} */ this.MoveMode - /** @type {SymbolEntity} */ this.SelfContextInfo /** @type {VariableReferenceEntity} */ this.DelegateReference /** @type {VariableReferenceEntity} */ this.VariableReference @@ -401,11 +392,22 @@ export default class ObjectEntity extends IEntity { const materialSubobject = this.getMaterialSubobject() if (materialSubobject) { const obj = materialSubobject - obj.SizeX && (obj.SizeX.getter = () => this.NodeWidth) + obj.SizeX !== undefined && (obj.SizeX.getter = () => this.NodeWidth) obj.SizeY && (obj.SizeY.getter = () => this.NodeHeight) obj.Text && (obj.Text.getter = () => this.NodeComment) obj.MaterialExpressionEditorX && (obj.MaterialExpressionEditorX.getter = () => this.NodePosX) obj.MaterialExpressionEditorY && (obj.MaterialExpressionEditorY.getter = () => this.NodePosY) + if (this.getType() === Configuration.paths.materialExpressionComponentMask) { + // The following attributes are too generic therefore not assigned a MirroredEntity + const rgbaPins = Configuration.rgba.map(pinName => + this.getPinEntities().find(pin => pin.PinName === pinName && (pin.recomputesNodeTitleOnChange = true)) + ) + const attribute = {} + obj.R = new MirroredEntity(Boolean, () => rgbaPins[0].DefaultValue) + obj.G = new MirroredEntity(Boolean, () => rgbaPins[1].DefaultValue) + obj.B = new MirroredEntity(Boolean, () => rgbaPins[2].DefaultValue) + obj.A = new MirroredEntity(Boolean, () => rgbaPins[3].DefaultValue) + } } /** @type {ObjectEntity} */ const pcgObject = this.getPcgSubobject() @@ -705,6 +707,13 @@ export default class ObjectEntity extends IEntity { if (this.StructType) { return `Make ${this.StructType.getName()}` } + case Configuration.paths.materialExpressionComponentMask: { + const materialObject = this.getMaterialSubobject() + return `Mask ( ${Configuration.rgba + .filter(k => /** @type {MirroredEntity} */(materialObject[k]).get() === true) + .map(v => v + " ") + .join("")})` + } case Configuration.paths.materialExpressionConstant: input ??= [this.getCustomproperties().find(pinEntity => pinEntity.PinName == "Value")?.DefaultValue] case Configuration.paths.materialExpressionConstant2Vector: @@ -732,11 +741,12 @@ export default class ObjectEntity extends IEntity { return input.map(v => Utility.printExponential(v)).reduce((acc, cur) => acc + "," + cur) } break - case Configuration.paths.materialExpressionFunctionInput: + case Configuration.paths.materialExpressionFunctionInput: { const materialObject = this.getMaterialSubobject() const inputName = materialObject?.InputName ?? "In" const inputType = materialObject?.InputType?.value.match(/^.+?_(\w+)$/)?.[1] ?? "Vector3" return `Input ${inputName} (${inputType})` + } case Configuration.paths.materialExpressionLogarithm: return "Ln" case Configuration.paths.materialExpressionLogarithm10: diff --git a/js/entity/ObjectReferenceEntity.js b/js/entity/ObjectReferenceEntity.js index e46255c..9e4fc6d 100755 --- a/js/entity/ObjectReferenceEntity.js +++ b/js/entity/ObjectReferenceEntity.js @@ -1,24 +1,22 @@ -import Configuration from "../Configuration.js" -import Grammar from "../serialization/Grammar.js" -import IEntity from "./IEntity.js" import Parsernostrum from "parsernostrum" +import Configuration from "../Configuration.js" import Utility from "../Utility.js" +import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" +import IEntity from "./IEntity.js" export default class ObjectReferenceEntity extends IEntity { static attributes = { ...super.attributes, - type: { + type: new AttributeInfo({ default: "", serialized: true, - }, - path: { + }), + path: new AttributeInfo({ default: "", serialized: true, - }, - } - static { - this.cleanupAttributes(this.attributes) + }), } static quoted = Parsernostrum.regArray(new RegExp( `'"(` + Grammar.Regex.InsideString.source + `)"'` diff --git a/js/entity/PathSymbolEntity.js b/js/entity/PathSymbolEntity.js index 53073e4..df60e30 100755 --- a/js/entity/PathSymbolEntity.js +++ b/js/entity/PathSymbolEntity.js @@ -1,16 +1,14 @@ import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" import IEntity from "./IEntity.js" export default class PathSymbolEntity extends IEntity { static attributes = { ...super.attributes, - value: { + value: new AttributeInfo({ default: "", - }, - } - static { - this.cleanupAttributes(this.attributes) + }), } static grammar = this.createGrammar() diff --git a/js/entity/PinEntity.js b/js/entity/PinEntity.js index d37f47d..733625f 100755 --- a/js/entity/PinEntity.js +++ b/js/entity/PinEntity.js @@ -1,10 +1,12 @@ +import Configuration from "../Configuration.js" +import Utility from "../Utility.js" +import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" import ByteEntity from "./ByteEntity.js" import ComputedType from "./ComputedType.js" -import Configuration from "../Configuration.js" import EnumDisplayValueEntity from "./EnumDisplayValueEntity.js" import EnumEntity from "./EnumEntity.js" import FormatTextEntity from "./FormatTextEntity.js" -import Grammar from "../serialization/Grammar.js" import GuidEntity from "./GuidEntity.js" import IEntity from "./IEntity.js" import Integer64Entity from "./Integer64Entity.js" @@ -20,7 +22,6 @@ import SimpleSerializationRotatorEntity from "./SimpleSerializationRotatorEntity import SimpleSerializationVector2DEntity from "./SimpleSerializationVector2DEntity.js" import SimpleSerializationVectorEntity from "./SimpleSerializationVectorEntity.js" import Union from "./Union.js" -import Utility from "../Utility.js" import Vector2DEntity from "./Vector2DEntity.js" import VectorEntity from "./VectorEntity.js" @@ -49,86 +50,62 @@ export default class PinEntity extends IEntity { [Configuration.paths.vector]: SimpleSerializationVectorEntity, [Configuration.paths.vector2D]: SimpleSerializationVector2DEntity, } - static lookbehind = "Pin" static attributes = { ...super.attributes, - objectEntity: { + lookbehind: new AttributeInfo({ + default: "Pin", ignored: true, - }, - pinIndex: { + }), + objectEntity: new AttributeInfo({ + ignored: true, + }), + pinIndex: new AttributeInfo({ type: Number, ignored: true, - }, - PinId: { + }), + PinId: new AttributeInfo({ type: GuidEntity, default: () => new GuidEntity() - }, - PinName: { - default: "", - }, - PinFriendlyName: { - type: new Union(LocalizedTextEntity, FormatTextEntity, String), - }, - PinToolTip: { - type: String, - }, - Direction: { - type: String, - }, - PinType: { + }), + PinName: AttributeInfo.createValue(""), + PinFriendlyName: AttributeInfo.createType(new Union(LocalizedTextEntity, FormatTextEntity, String)), + PinToolTip: AttributeInfo.createType(String), + Direction: AttributeInfo.createType(String), + PinType: new AttributeInfo({ type: PinTypeEntity, default: () => new PinTypeEntity(), inlined: true, - }, - LinkedTo: { - type: [PinReferenceEntity], - }, - SubPins: { - type: [PinReferenceEntity], - }, - ParentPin: { - type: PinReferenceEntity, - }, - DefaultValue: { + }), + LinkedTo: AttributeInfo.createType([PinReferenceEntity]), + SubPins: AttributeInfo.createType([PinReferenceEntity]), + ParentPin: AttributeInfo.createType(PinReferenceEntity), + DefaultValue: new AttributeInfo({ type: new ComputedType( /** @param {PinEntity} pinEntity */ pinEntity => pinEntity.getEntityType(true) ?? String ), serialized: true, - }, - AutogeneratedDefaultValue: { - type: String, - }, - DefaultObject: { - type: ObjectReferenceEntity, - }, - PersistentGuid: { - type: GuidEntity, - }, - bHidden: { - default: false, - }, - bNotConnectable: { - default: false, - }, - bDefaultValueIsReadOnly: { - default: false, - }, - bDefaultValueIsIgnored: { - default: false, - }, - bAdvancedView: { - default: false, - }, - bOrphanedPin: { - default: false, - }, - } - static { - this.cleanupAttributes(this.attributes) + }), + AutogeneratedDefaultValue: AttributeInfo.createType(String), + DefaultObject: AttributeInfo.createType(ObjectReferenceEntity), + PersistentGuid: AttributeInfo.createType(GuidEntity), + bHidden: AttributeInfo.createValue(false), + bNotConnectable: AttributeInfo.createValue(false), + bDefaultValueIsReadOnly: AttributeInfo.createValue(false), + bDefaultValueIsIgnored: AttributeInfo.createValue(false), + bAdvancedView: AttributeInfo.createValue(false), + bOrphanedPin: AttributeInfo.createValue(false), } static grammar = this.createGrammar() + #recomputesNodeTitleOnChange = false + set recomputesNodeTitleOnChange(value) { + this.#recomputesNodeTitleOnChange = value + } + get recomputesNodeTitleOnChange() { + return this.#recomputesNodeTitleOnChange + } + static createGrammar() { return Grammar.createEntityGrammar(this) } @@ -166,20 +143,6 @@ export default class PinEntity extends IEntity { if (category === "struct" || category === "object") { return this.PinType.PinSubCategoryObject.path } - if (category === "optional") { - switch (this.PinType.PinSubCategory) { - case "int": - return "int" - case "red": - return "real" - case "rg": - return "rg" - case "rgb": - return Configuration.paths.vector - case "rgba": - return Configuration.paths.linearColor - } - } if (this.isEnum()) { return "enum" } @@ -209,6 +172,20 @@ export default class PinEntity extends IEntity { } } } + if (category === "optional") { + switch (this.PinType.PinSubCategory) { + case "red": + return "real" + case "rg": + return "rg" + case "rgb": + return Configuration.paths.vector + case "rgba": + return Configuration.paths.linearColor + default: + return this.PinType.PinSubCategory + } + } return category } @@ -291,6 +268,7 @@ export default class PinEntity extends IEntity { /** * @param {String} targetObjectName * @param {PinEntity} targetPinEntity + * @returns true if it was not already linked to the tarket */ linkTo(targetObjectName, targetPinEntity) { const linkFound = this.LinkedTo?.some(pinReferenceEntity => @@ -310,6 +288,7 @@ export default class PinEntity extends IEntity { /** * @param {String} targetObjectName * @param {PinEntity} targetPinEntity + * @returns true if it was linked to the target */ unlinkFrom(targetObjectName, targetPinEntity) { const indexElement = this.LinkedTo?.findIndex(pinReferenceEntity => { diff --git a/js/entity/PinReferenceEntity.js b/js/entity/PinReferenceEntity.js index 50f012c..e0a09f2 100755 --- a/js/entity/PinReferenceEntity.js +++ b/js/entity/PinReferenceEntity.js @@ -1,21 +1,15 @@ +import Parsernostrum from "parsernostrum" import GuidEntity from "./GuidEntity.js" import IEntity from "./IEntity.js" -import Parsernostrum from "parsernostrum" import PathSymbolEntity from "./PathSymbolEntity.js" +import AttributeInfo from "./AttributeInfo.js" export default class PinReferenceEntity extends IEntity { static attributes = { ...super.attributes, - objectName: { - type: PathSymbolEntity, - }, - pinGuid: { - type: GuidEntity, - }, - } - static { - this.cleanupAttributes(this.attributes) + objectName: AttributeInfo.createType(PathSymbolEntity), + pinGuid: AttributeInfo.createType(GuidEntity), } static grammar = this.createGrammar() diff --git a/js/entity/PinTypeEntity.js b/js/entity/PinTypeEntity.js index 47ba4ee..0227342 100755 --- a/js/entity/PinTypeEntity.js +++ b/js/entity/PinTypeEntity.js @@ -1,5 +1,6 @@ -import FunctionReferenceEntity from "./FunctionReferenceEntity.js" import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" +import FunctionReferenceEntity from "./FunctionReferenceEntity.js" import IEntity from "./IEntity.js" import ObjectReferenceEntity from "./ObjectReferenceEntity.js" import PathSymbolEntity from "./PathSymbolEntity.js" @@ -8,45 +9,26 @@ export default class PinTypeEntity extends IEntity { static attributes = { ...super.attributes, - PinCategory: { - default: "", - }, - PinSubCategory: { - default: "", - }, - PinSubCategoryObject: { + PinCategory: AttributeInfo.createValue(""), + PinSubCategory: AttributeInfo.createValue(""), + PinSubCategoryObject: new AttributeInfo({ type: ObjectReferenceEntity, default: () => ObjectReferenceEntity.createNoneInstance(), - }, - PinSubCategoryMemberReference: { + }), + PinSubCategoryMemberReference: new AttributeInfo({ type: FunctionReferenceEntity, default: null, - }, - PinValueType: { + }), + PinValueType: new AttributeInfo({ type: PinTypeEntity, default: null, - }, - ContainerType: { - type: PathSymbolEntity, - }, - bIsReference: { - default: false, - }, - bIsConst: { - default: false, - }, - bIsWeakPointer: { - default: false, - }, - bIsUObjectWrapper: { - default: false, - }, - bSerializeAsSinglePrecisionFloat: { - default: false, - }, - } - static { - this.cleanupAttributes(this.attributes) + }), + ContainerType: AttributeInfo.createType(PathSymbolEntity), + bIsReference: AttributeInfo.createValue(false), + bIsConst: AttributeInfo.createValue(false), + bIsWeakPointer: AttributeInfo.createValue(false), + bIsUObjectWrapper: AttributeInfo.createValue(false), + bSerializeAsSinglePrecisionFloat: AttributeInfo.createValue(false), } static grammar = this.createGrammar() diff --git a/js/entity/RotatorEntity.js b/js/entity/RotatorEntity.js index 5d98757..36746d5 100644 --- a/js/entity/RotatorEntity.js +++ b/js/entity/RotatorEntity.js @@ -1,25 +1,23 @@ import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" import IEntity from "./IEntity.js" export default class RotatorEntity extends IEntity { static attributes = { ...super.attributes, - R: { + R: new AttributeInfo({ default: 0, expected: true, - }, - P: { + }), + P: new AttributeInfo({ default: 0, expected: true, - }, - Y: { + }), + Y: new AttributeInfo({ default: 0, expected: true, - }, - } - static { - this.cleanupAttributes(this.attributes) + }), } static grammar = this.createGrammar() diff --git a/js/entity/SymbolEntity.js b/js/entity/SymbolEntity.js index 6953cfa..fc0fd7e 100644 --- a/js/entity/SymbolEntity.js +++ b/js/entity/SymbolEntity.js @@ -1,16 +1,12 @@ import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" import IEntity from "./IEntity.js" export default class SymbolEntity extends IEntity { static attributes = { ...super.attributes, - value: { - default: "", - }, - } - static { - this.cleanupAttributes(this.attributes) + value: AttributeInfo.createValue(""), } static grammar = this.createGrammar() diff --git a/js/entity/TerminalTypeEntity.js b/js/entity/TerminalTypeEntity.js index 08eaf4b..ce206e9 100644 --- a/js/entity/TerminalTypeEntity.js +++ b/js/entity/TerminalTypeEntity.js @@ -1,28 +1,15 @@ +import AttributeInfo from "./AttributeInfo.js" import IEntity from "./IEntity.js" export default class TerminalTypeEntity extends IEntity { static attributes = { ...super.attributes, - TerminalCategory: { - type: String, - }, - TerminalSubCategory: { - type: String, - }, - bTerminalIsConst: { - type: Boolean, - }, - bTerminalIsWeakPointer: { - type: Boolean, - }, - bTerminalIsUObjectWrapper: { - type: Boolean, - }, - } - - static { - this.cleanupAttributes(this.attributes) + TerminalCategory: AttributeInfo.createType(String), + TerminalSubCategory: AttributeInfo.createType(String), + bTerminalIsConst: AttributeInfo.createType(Boolean), + bTerminalIsWeakPointer: AttributeInfo.createType(Boolean), + bTerminalIsUObjectWrapper: AttributeInfo.createType(Boolean), } constructor(values) { diff --git a/js/entity/Union.js b/js/entity/Union.js index ddcdb56..67db27b 100644 --- a/js/entity/Union.js +++ b/js/entity/Union.js @@ -1,7 +1,4 @@ -/** - * @template {[...U]} T - * @template {any[]} U - */ +/** @template {any[]} T */ export default class Union { /** @type {T} */ diff --git a/js/entity/UnknownKeysEntity.js b/js/entity/UnknownKeysEntity.js index 3baed10..d1de1b7 100644 --- a/js/entity/UnknownKeysEntity.js +++ b/js/entity/UnknownKeysEntity.js @@ -1,19 +1,11 @@ -import Grammar from "../serialization/Grammar.js" -import IEntity from "./IEntity.js" import Parsernostrum from "parsernostrum" +import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" +import IEntity from "./IEntity.js" export default class UnknownKeysEntity extends IEntity { - static attributes = { - ...super.attributes, - lookbehind: { - default: "", - ignored: true, - }, - } - static { - this.cleanupAttributes(this.attributes) - } + static grammar = this.createGrammar() static createGrammar() { @@ -44,6 +36,5 @@ export default class UnknownKeysEntity extends IEntity { constructor(values) { super(values, true) - /** @type {String} */ this.lookbehind } } diff --git a/js/entity/UnknownPinEntity.js b/js/entity/UnknownPinEntity.js index ca7ac6b..1f49d2c 100755 --- a/js/entity/UnknownPinEntity.js +++ b/js/entity/UnknownPinEntity.js @@ -4,13 +4,12 @@ import PinEntity from "./PinEntity.js" export default class UnknownPinEntity extends PinEntity { - static lookbehind = "" static grammar = this.createGrammar() static createGrammar() { return Parsernostrum.seq( Parsernostrum.reg( - new RegExp(`${Grammar.Regex.Symbol.source}\\s*\\(\\s*`), + new RegExp(`(${Grammar.Regex.Symbol.source})\\s*\\(\\s*`), 1 ), Grammar.createAttributeGrammar(this).sepBy(Grammar.commaSeparation), diff --git a/js/entity/VariableReferenceEntity.js b/js/entity/VariableReferenceEntity.js index 894593b..03dd0bc 100755 --- a/js/entity/VariableReferenceEntity.js +++ b/js/entity/VariableReferenceEntity.js @@ -1,4 +1,5 @@ import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" import GuidEntity from "./GuidEntity.js" import IEntity from "./IEntity.js" @@ -6,21 +7,10 @@ export default class VariableReferenceEntity extends IEntity { static attributes = { ...super.attributes, - MemberScope: { - type: String, - }, - MemberName: { - default: "", - }, - MemberGuid: { - type: GuidEntity, - }, - bSelfContext: { - type: Boolean, - }, - } - static { - this.cleanupAttributes(this.attributes) + MemberScope: AttributeInfo.createType(String), + MemberName: AttributeInfo.createValue(""), + MemberGuid: AttributeInfo.createType(GuidEntity), + bSelfContext: AttributeInfo.createType(Boolean), } static grammar = this.createGrammar() diff --git a/js/entity/Vector2DEntity.js b/js/entity/Vector2DEntity.js index d07d197..89ac06d 100644 --- a/js/entity/Vector2DEntity.js +++ b/js/entity/Vector2DEntity.js @@ -1,21 +1,19 @@ import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" import IEntity from "./IEntity.js" export default class Vector2DEntity extends IEntity { static attributes = { ...super.attributes, - X: { + X: new AttributeInfo({ default: 0, expected: true, - }, - Y: { + }), + Y: new AttributeInfo({ default: 0, expected: true, - }, - } - static { - this.cleanupAttributes(this.attributes) + }), } static grammar = this.createGrammar() diff --git a/js/entity/VectorEntity.js b/js/entity/VectorEntity.js index cc1388c..8be55f9 100644 --- a/js/entity/VectorEntity.js +++ b/js/entity/VectorEntity.js @@ -1,25 +1,23 @@ import Grammar from "../serialization/Grammar.js" +import AttributeInfo from "./AttributeInfo.js" import IEntity from "./IEntity.js" export default class VectorEntity extends IEntity { static attributes = { ...super.attributes, - X: { + X: new AttributeInfo({ default: 0, expected: true, - }, - Y: { + }), + Y: new AttributeInfo({ default: 0, expected: true, - }, - Z: { + }), + Z: new AttributeInfo({ default: 0, expected: true, - }, - } - static { - this.cleanupAttributes(this.attributes) + }), } static grammar = this.createGrammar() diff --git a/js/serialization/Grammar.js b/js/serialization/Grammar.js index 1a51a6f..0b81bf7 100755 --- a/js/serialization/Grammar.js +++ b/js/serialization/Grammar.js @@ -1,10 +1,11 @@ +import Parsernostrum from "parsernostrum" import Configuration from "../Configuration.js" +import Utility from "../Utility.js" +import AttributeInfo from "../entity/AttributeInfo.js" import IEntity from "../entity/IEntity.js" import MirroredEntity from "../entity/MirroredEntity.js" -import Parsernostrum from "parsernostrum" -import Serializable from "./Serializable.js" import Union from "../entity/Union.js" -import Utility from "../Utility.js" +import Serializable from "./Serializable.js" export default class Grammar { @@ -66,16 +67,10 @@ export default class Grammar { /* --- Factory --- */ /** - * @template {AttributeTypeDescription} T - * @param {T} type + * @template T + * @param {AttributeInfo} attribute */ - static grammarFor( - attribute, - type = attribute?.constructor === Object - ? attribute.type - : attribute?.constructor, - defaultGrammar = this.unknownValue - ) { + static grammarFor(attribute, type = attribute?.type, defaultGrammar = this.unknownValue) { let result = defaultGrammar if (type instanceof Array) { if (attribute?.inlined) { @@ -103,6 +98,9 @@ export default class Grammar { case Boolean: result = this.boolean break + case null: + result = this.null + break case Number: result = this.number break @@ -114,11 +112,11 @@ export default class Grammar { break default: if (/** @type {AttributeConstructor} */(type)?.prototype instanceof Serializable) { - return /** @type {typeof Serializable} */(type).grammar + result = /** @type {typeof Serializable} */(type).grammar } } } - if (attribute?.constructor === Object) { + if (attribute) { if (attribute.serialized && type.constructor !== String) { if (result == this.unknownValue) { result = this.string @@ -137,7 +135,7 @@ export default class Grammar { * @template {AttributeConstructor} T * @param {T} entityType * @param {String[]} key - * @returns {AttributeInformation} + * @returns {AttributeInfo} */ static getAttribute(entityType, key) { let result @@ -191,13 +189,14 @@ export default class Grammar { * @param {(new (...args: any) => T) & EntityConstructor} entityType * @param {Boolean | Number} acceptUnknownKeys Number to specify the limit or true, to let it be a reasonable value */ - static createEntityGrammar = (entityType, acceptUnknownKeys = true, entriesSeparator = this.commaSeparation) => - Parsernostrum.seq( + static createEntityGrammar(entityType, acceptUnknownKeys = true, entriesSeparator = this.commaSeparation) { + const lookbehind = entityType.attributes.lookbehind.default + return Parsernostrum.seq( Parsernostrum.reg( - entityType.lookbehind instanceof Union - ? new RegExp(`(${entityType.lookbehind.values.reduce((acc, cur) => acc + "|" + cur)})\\s*\\(\\s*`) - : entityType.lookbehind.constructor == String && entityType.lookbehind.length - ? new RegExp(`(${entityType.lookbehind})\\s*\\(\\s*`) + lookbehind instanceof Union + ? new RegExp(`(${lookbehind.values.reduce((acc, cur) => acc + "|" + cur)})\\s*\\(\\s*`) + : lookbehind.constructor == String && lookbehind.length > 0 + ? new RegExp(`(${lookbehind})\\s*\\(\\s*`) : /()\(\s*/, 1 ), @@ -218,7 +217,7 @@ export default class Grammar { let missingKey // Check missing values if ( - Object.keys(/** @type {AttributeInformation} */(entityType.attributes)) + Object.keys(/** @type {AttributeDeclarations} */(entityType.attributes)) .filter(key => entityType.attributes[key].expected) .find(key => !totalKeys.includes(key) && (missingKey = key)) ) { @@ -230,6 +229,7 @@ export default class Grammar { } return Parsernostrum.success().map(() => new entityType(values)) }) + } /* --- Entity --- */ diff --git a/js/serialization/ObjectSerializer.js b/js/serialization/ObjectSerializer.js index 91a8f77..567b52b 100755 --- a/js/serialization/ObjectSerializer.js +++ b/js/serialization/ObjectSerializer.js @@ -1,7 +1,7 @@ import Configuration from "../Configuration.js" -import Grammar from "./Grammar.js" import ObjectEntity from "../entity/ObjectEntity.js" import PinEntity from "../entity/PinEntity.js" +import Grammar from "./Grammar.js" import Serializer from "./Serializer.js" import SerializerFactory from "./SerializerFactory.js" diff --git a/js/serialization/Serializer.js b/js/serialization/Serializer.js index ed7a002..0325118 100644 --- a/js/serialization/Serializer.js +++ b/js/serialization/Serializer.js @@ -1,7 +1,8 @@ -import Grammar from "./Grammar.js" -import IEntity from "../entity/IEntity.js" -import SerializerFactory from "./SerializerFactory.js" import Utility from "../Utility.js" +import AttributeInfo from "../entity/AttributeInfo.js" +import IEntity from "../entity/IEntity.js" +import Grammar from "./Grammar.js" +import SerializerFactory from "./SerializerFactory.js" /** @template {AttributeConstructor} T */ export default class Serializer { @@ -54,7 +55,11 @@ export default class Serializer { let grammar = Grammar.grammarFor(undefined, this.entityType) const parseResult = grammar.run(value) if (!parseResult.status) { - throw new Error(`Error when trying to parse the entity ${this.entityType.prototype.constructor.name}.`) + throw new Error( + this.entityType + ? `Error when trying to parse the entity ${this.entityType.prototype.constructor.name}` + : "Error when trying to parse null" + ) } return parseResult.value } @@ -85,7 +90,7 @@ export default class Serializer { if (attributes[key]?.quoted) { keyValue = `"${keyValue}"` } - const isSerialized = Utility.isSerialized(entity, key) + const isSerialized = AttributeInfo.getAttribute(entity, key, "serialized") if (first) { first = false } else { @@ -140,10 +145,21 @@ export default class Serializer { return serializer.doWrite(value, insideString, indentation) } + /** + * @param {IEntity} entity + * @param {String} key + */ showProperty(entity, key) { - const attribute = /** @type {EntityConstructor} */(this.entityType).attributes[key] - if (attribute?.constructor === Object && attribute.ignored) { - return false + if (entity instanceof IEntity) { + if ( + AttributeInfo.getAttribute(entity, key, "ignored") + || AttributeInfo.getAttribute(entity, key, "silent") && Utility.equals( + AttributeInfo.getAttribute(entity, key, "default"), + entity[key] + ) + ) { + return false + } } return true } diff --git a/js/serialization/ToStringSerializer.js b/js/serialization/ToStringSerializer.js index fee33e3..9ed9e36 100755 --- a/js/serialization/ToStringSerializer.js +++ b/js/serialization/ToStringSerializer.js @@ -1,5 +1,5 @@ -import Serializer from "./Serializer.js" import Utility from "../Utility.js" +import Serializer from "./Serializer.js" /** * @template {AttributeConstructor} T diff --git a/js/serialization/initializeSerializerFactory.js b/js/serialization/initializeSerializerFactory.js index 939b9c2..ce7188e 100755 --- a/js/serialization/initializeSerializerFactory.js +++ b/js/serialization/initializeSerializerFactory.js @@ -1,11 +1,11 @@ +import Parsernostrum from "parsernostrum" +import Utility from "../Utility.js" import ByteEntity from "../entity/ByteEntity.js" import ColorChannelEntity from "../entity/ColorChannelEntity.js" -import CustomSerializer from "./CustomSerializer.js" import EnumDisplayValueEntity from "../entity/EnumDisplayValueEntity.js" import EnumEntity from "../entity/EnumEntity.js" import FormatTextEntity from "../entity/FormatTextEntity.js" import FunctionReferenceEntity from "../entity/FunctionReferenceEntity.js" -import Grammar from "./Grammar.js" import GuidEntity from "../entity/GuidEntity.js" import IdentifierEntity from "../entity/IdentifierEntity.js" import Integer64Entity from "../entity/Integer64Entity.js" @@ -18,27 +18,28 @@ import MacroGraphReferenceEntity from "../entity/MacroGraphReferenceEntity.js" import MirroredEntity from "../entity/MirroredEntity.js" import ObjectEntity from "../entity/ObjectEntity.js" import ObjectReferenceEntity from "../entity/ObjectReferenceEntity.js" -import ObjectSerializer from "./ObjectSerializer.js" -import Parsernostrum from "parsernostrum" import PathSymbolEntity from "../entity/PathSymbolEntity.js" import PinEntity from "../entity/PinEntity.js" import PinReferenceEntity from "../entity/PinReferenceEntity.js" import RBSerializationVector2DEntity from "../entity/RBSerializationVector2DEntity.js" import RotatorEntity from "../entity/RotatorEntity.js" -import Serializer from "./Serializer.js" -import SerializerFactory from "./SerializerFactory.js" import SimpleSerializationRotatorEntity from "../entity/SimpleSerializationRotatorEntity.js" import SimpleSerializationVector2DEntity from "../entity/SimpleSerializationVector2DEntity.js" import SimpleSerializationVectorEntity from "../entity/SimpleSerializationVectorEntity.js" import SymbolEntity from "../entity/SymbolEntity.js" import TerminalTypeEntity from "../entity/TerminalTypeEntity.js" -import ToStringSerializer from "./ToStringSerializer.js" import Union from "../entity/Union.js" import UnknownKeysEntity from "../entity/UnknownKeysEntity.js" -import Utility from "../Utility.js" import VariableReferenceEntity from "../entity/VariableReferenceEntity.js" import Vector2DEntity from "../entity/Vector2DEntity.js" import VectorEntity from "../entity/VectorEntity.js" +import CustomSerializer from "./CustomSerializer.js" +import Grammar from "./Grammar.js" +import ObjectSerializer from "./ObjectSerializer.js" +import Serializer from "./Serializer.js" +import SerializerFactory from "./SerializerFactory.js" +import ToStringSerializer from "./ToStringSerializer.js" +import PinTypeEntity from "../entity/PinTypeEntity.js" Grammar.unknownValue = Parsernostrum.alt( @@ -48,8 +49,8 @@ Grammar.unknownValue = Parsernostrum.str("None").map(() => new ObjectReferenceEntity({ type: "None" })), Grammar.null, Grammar.number, - Grammar.string, ObjectReferenceEntity.fullReferenceGrammar, + Grammar.string, LocalizedTextEntity.createGrammar(), InvariantTextEntity.createGrammar(), FormatTextEntity.createGrammar(), @@ -244,6 +245,11 @@ export default function initializeSerializerFactory() { new Serializer(PinReferenceEntity, undefined, " ", false, "", () => "") ) + SerializerFactory.registerSerializer( + PinTypeEntity, + new Serializer(PinTypeEntity) + ) + SerializerFactory.registerSerializer( TerminalTypeEntity, new Serializer(TerminalTypeEntity, Serializer.bracketsWrapped) diff --git a/js/template/BlueprintTemplate.js b/js/template/BlueprintTemplate.js index 65f782d..b4a6c64 100755 --- a/js/template/BlueprintTemplate.js +++ b/js/template/BlueprintTemplate.js @@ -1,18 +1,18 @@ import { html } from "lit" import Configuration from "../Configuration.js" +import Shortcuts from "../Shortcuts.js" +import Utility from "../Utility.js" import Copy from "../input/common/Copy.js" import Cut from "../input/common/Cut.js" -import ITemplate from "./ITemplate.js" +import Paste from "../input/common/Paste.js" import KeyboardEnableZoom from "../input/keyboard/KeyboardEnableZoom.js" import KeyboardShortcut from "../input/keyboard/KeyboardShortcut.js" import MouseScrollGraph from "../input/mouse/MouseScrollGraph.js" import MouseTracking from "../input/mouse/MouseTracking.js" -import Paste from "../input/common/Paste.js" import Select from "../input/mouse/Select.js" -import Shortcuts from "../Shortcuts.js" import Unfocus from "../input/mouse/Unfocus.js" -import Utility from "../Utility.js" import Zoom from "../input/mouse/Zoom.js" +import ITemplate from "./ITemplate.js" /** @extends ITemplate */ export default class BlueprintTemplate extends ITemplate { @@ -37,10 +37,13 @@ export default class BlueprintTemplate extends ITemplate { this.viewportSize[1] = size.blockSize } }) + /** @type {Copy} */ #copyInputObject + /** @type {Paste} */ #pasteInputObject + /** @type {Zoom} */ #zoomInputObject diff --git a/js/template/ColorHandlerTemplate.js b/js/template/ColorHandlerTemplate.js index fc8bf09..4a3d475 100755 --- a/js/template/ColorHandlerTemplate.js +++ b/js/template/ColorHandlerTemplate.js @@ -1,5 +1,5 @@ -import IDraggableControlTemplate from "./IDraggableControlTemplate.js" import Utility from "../Utility.js" +import IDraggableControlTemplate from "./IDraggableControlTemplate.js" /** @extends {IDraggableControlTemplate} */ export default class ColorHandlerTemplate extends IDraggableControlTemplate { diff --git a/js/template/ColorSliderTemplate.js b/js/template/ColorSliderTemplate.js index 8bce4fd..956ab80 100755 --- a/js/template/ColorSliderTemplate.js +++ b/js/template/ColorSliderTemplate.js @@ -1,5 +1,5 @@ -import IDraggableControlTemplate from "./IDraggableControlTemplate.js" import Utility from "../Utility.js" +import IDraggableControlTemplate from "./IDraggableControlTemplate.js" /** @extends {IDraggableControlTemplate} */ export default class ColorSliderTemplate extends IDraggableControlTemplate { diff --git a/js/template/IDraggableControlTemplate.js b/js/template/IDraggableControlTemplate.js index 8628e6f..9499eb7 100644 --- a/js/template/IDraggableControlTemplate.js +++ b/js/template/IDraggableControlTemplate.js @@ -1,5 +1,5 @@ -import IDraggableTemplate from "./IDraggableTemplate.js" import MouseMoveDraggable from "../input/mouse/MouseMoveDraggable.js" +import IDraggableTemplate from "./IDraggableTemplate.js" /** * @template {IDraggableElement} T diff --git a/js/template/IDraggableTemplate.js b/js/template/IDraggableTemplate.js index c4a45e5..7614152 100755 --- a/js/template/IDraggableTemplate.js +++ b/js/template/IDraggableTemplate.js @@ -1,7 +1,7 @@ import Configuration from "../Configuration.js" -import ITemplate from "./ITemplate.js" import KeyboardShortcut from "../input/keyboard/KeyboardShortcut.js" import MouseMoveDraggable from "../input/mouse/MouseMoveDraggable.js" +import ITemplate from "./ITemplate.js" /** * @template {IDraggableElement} T diff --git a/js/template/ISelectableDraggableTemplate.js b/js/template/ISelectableDraggableTemplate.js index de1b2bc..fe7c116 100755 --- a/js/template/ISelectableDraggableTemplate.js +++ b/js/template/ISelectableDraggableTemplate.js @@ -1,5 +1,5 @@ -import IDraggablePositionedTemplate from "./IDraggablePositionedTemplate.js" import MouseMoveNodes from "../input/mouse/MouseMoveNodes.js" +import IDraggablePositionedTemplate from "./IDraggablePositionedTemplate.js" /** * @template {NodeElement} T diff --git a/js/template/LinkTemplate.js b/js/template/LinkTemplate.js index 21d5a4d..4f90a98 100755 --- a/js/template/LinkTemplate.js +++ b/js/template/LinkTemplate.js @@ -1,13 +1,13 @@ import { html, nothing } from "lit" import Configuration from "../Configuration.js" -import ElementFactory from "../element/ElementFactory.js" -import IFromToPositionedTemplate from "./IFromToPositionedTemplate.js" -import KeyboardShortcut from "../input/keyboard/KeyboardShortcut.js" -import KnotEntity from "../entity/objects/KnotEntity.js" -import MouseClick from "../input/mouse/MouseClick.js" -import MouseDbClick from "../input/mouse/MouseDbClick.js" import Shortcuts from "../Shortcuts.js" import Utility from "../Utility.js" +import ElementFactory from "../element/ElementFactory.js" +import KnotEntity from "../entity/objects/KnotEntity.js" +import KeyboardShortcut from "../input/keyboard/KeyboardShortcut.js" +import MouseClick from "../input/mouse/MouseClick.js" +import MouseDbClick from "../input/mouse/MouseDbClick.js" +import IFromToPositionedTemplate from "./IFromToPositionedTemplate.js" /** @extends {IFromToPositionedTemplate} */ export default class LinkTemplate extends IFromToPositionedTemplate { diff --git a/js/template/node/NodeTemplate.js b/js/template/node/NodeTemplate.js index b7e0c0c..060e562 100755 --- a/js/template/node/NodeTemplate.js +++ b/js/template/node/NodeTemplate.js @@ -1,8 +1,8 @@ import { html, nothing } from "lit" -import ElementFactory from "../../element/ElementFactory.js" -import ISelectableDraggableTemplate from "../ISelectableDraggableTemplate.js" import SVGIcon from "../../SVGIcon.js" import Utility from "../../Utility.js" +import ElementFactory from "../../element/ElementFactory.js" +import ISelectableDraggableTemplate from "../ISelectableDraggableTemplate.js" /** @extends {ISelectableDraggableTemplate} */ export default class NodeTemplate extends ISelectableDraggableTemplate { @@ -99,7 +99,7 @@ export default class NodeTemplate extends ISelectableDraggableTemplate { } renderNodeName() { - return this.element.getNodeDisplayName() + return this.element.nodeDisplayName } renderTop() { diff --git a/js/template/node/VariableMangementNodeTemplate.js b/js/template/node/VariableMangementNodeTemplate.js index 3d4d3a9..0d436cc 100644 --- a/js/template/node/VariableMangementNodeTemplate.js +++ b/js/template/node/VariableMangementNodeTemplate.js @@ -1,7 +1,7 @@ import { html, nothing } from "lit" +import SVGIcon from "../../SVGIcon.js" import ElementFactory from "../../element/ElementFactory.js" import NodeTemplate from "./NodeTemplate.js" -import SVGIcon from "../../SVGIcon.js" export default class VariableManagementNodeTemplate extends NodeTemplate { @@ -14,7 +14,7 @@ export default class VariableManagementNodeTemplate extends NodeTemplate { /** @param {NodeElement} element */ initialize(element) { super.initialize(element) - this.#displayName = this.element.getNodeDisplayName() + this.#displayName = this.element.nodeDisplayName } render() { diff --git a/js/template/pin/BoolPinTemplate.js b/js/template/pin/BoolPinTemplate.js index 81ffa3c..43ff10d 100644 --- a/js/template/pin/BoolPinTemplate.js +++ b/js/template/pin/BoolPinTemplate.js @@ -35,7 +35,7 @@ export default class BoolPinTemplate extends PinTemplate { renderInput() { return html` - + ` } } diff --git a/js/template/pin/DropdownTemplate.js b/js/template/pin/DropdownTemplate.js index ec0b620..f902518 100644 --- a/js/template/pin/DropdownTemplate.js +++ b/js/template/pin/DropdownTemplate.js @@ -1,6 +1,6 @@ import { html } from "lit" -import ITemplate from "../ITemplate.js" import MouseIgnore from "../../input/mouse/MouseIgnore.js" +import ITemplate from "../ITemplate.js" /** @extends {ITemplate} */ export default class DropdownTemplate extends ITemplate { diff --git a/js/template/pin/EnumPinTemplate.js b/js/template/pin/EnumPinTemplate.js index cfed0f7..da8e845 100644 --- a/js/template/pin/EnumPinTemplate.js +++ b/js/template/pin/EnumPinTemplate.js @@ -1,7 +1,7 @@ import { html } from "lit" import Configuration from "../../Configuration.js" -import IInputPinTemplate from "./IInputPinTemplate.js" import Utility from "../../Utility.js" +import IInputPinTemplate from "./IInputPinTemplate.js" /** @extends IInputPinTemplate */ export default class EnumPinTemplate extends IInputPinTemplate { diff --git a/js/template/pin/ExecPinTemplate.js b/js/template/pin/ExecPinTemplate.js index b2dedba..8bb7678 100644 --- a/js/template/pin/ExecPinTemplate.js +++ b/js/template/pin/ExecPinTemplate.js @@ -1,7 +1,6 @@ import { html } from "lit" -import PinTemplate from "./PinTemplate.js" import SVGIcon from "../../SVGIcon.js" -import Utility from "../../Utility.js" +import PinTemplate from "./PinTemplate.js" export default class ExecPinTemplate extends PinTemplate { diff --git a/js/template/pin/IInputPinTemplate.js b/js/template/pin/IInputPinTemplate.js index c3a083f..2ba5754 100644 --- a/js/template/pin/IInputPinTemplate.js +++ b/js/template/pin/IInputPinTemplate.js @@ -1,7 +1,7 @@ import { html } from "lit" import Configuration from "../../Configuration.js" -import PinTemplate from "./PinTemplate.js" import Utility from "../../Utility.js" +import PinTemplate from "./PinTemplate.js" /** * @template {TerminalAttribute} T diff --git a/js/template/pin/InputTemplate.js b/js/template/pin/InputTemplate.js index 066b2f1..11d4cec 100644 --- a/js/template/pin/InputTemplate.js +++ b/js/template/pin/InputTemplate.js @@ -1,5 +1,5 @@ -import ITemplate from "../ITemplate.js" import MouseIgnore from "../../input/mouse/MouseIgnore.js" +import ITemplate from "../ITemplate.js" /** @extends {ITemplate} */ export default class InputTemplate extends ITemplate { diff --git a/js/template/pin/KnotPinTemplate.js b/js/template/pin/KnotPinTemplate.js index 109cc29..48d3068 100644 --- a/js/template/pin/KnotPinTemplate.js +++ b/js/template/pin/KnotPinTemplate.js @@ -1,6 +1,6 @@ import { html } from "lit" -import MinimalPinTemplate from "./MinimalPinTemplate.js" import Utility from "../../Utility.js" +import MinimalPinTemplate from "./MinimalPinTemplate.js" /** @extends MinimalPinTemplate */ export default class KnotPinTemplate extends MinimalPinTemplate { @@ -21,6 +21,7 @@ export default class KnotPinTemplate extends MinimalPinTemplate { : this ) .iconElement.getBoundingClientRect() + /** @type {Coordinates} */ const boundingLocation = [this.element.isInput() ? rect.left : rect.right + 1, (rect.top + rect.bottom) / 2] const location = Utility.convertLocation(boundingLocation, this.blueprint.template.gridElement) return this.blueprint.compensateTranslation(location[0], location[1]) diff --git a/js/template/pin/LinearColorPinTemplate.js b/js/template/pin/LinearColorPinTemplate.js index 7b1dfac..4422317 100644 --- a/js/template/pin/LinearColorPinTemplate.js +++ b/js/template/pin/LinearColorPinTemplate.js @@ -1,7 +1,7 @@ import { html, nothing } from "lit" -import ColorPickerWindowTemplate from "../window/ColorPickerWindowTemplate.js" import Configuration from "../../Configuration.js" import ElementFactory from "../../element/ElementFactory.js" +import ColorPickerWindowTemplate from "../window/ColorPickerWindowTemplate.js" import PinTemplate from "./PinTemplate.js" /** @extends PinTemplate */ diff --git a/js/template/pin/PinTemplate.js b/js/template/pin/PinTemplate.js index 15c4b4b..1733d30 100755 --- a/js/template/pin/PinTemplate.js +++ b/js/template/pin/PinTemplate.js @@ -1,9 +1,9 @@ import { html, nothing } from "lit" import Configuration from "../../Configuration.js" -import ITemplate from "../ITemplate.js" -import MouseCreateLink from "../../input/mouse/MouseCreateLink.js" import SVGIcon from "../../SVGIcon.js" import Utility from "../../Utility.js" +import MouseCreateLink from "../../input/mouse/MouseCreateLink.js" +import ITemplate from "../ITemplate.js" import VariableConversionNodeTemplate from "../node/VariableConversionNodeTemplate.js" import VariableOperationNodeTemplate from "../node/VariableOperationNodeTemplate.js" diff --git a/js/template/pin/RealPinTemplate.js b/js/template/pin/RealPinTemplate.js index 85531a1..c264c96 100644 --- a/js/template/pin/RealPinTemplate.js +++ b/js/template/pin/RealPinTemplate.js @@ -1,6 +1,6 @@ import { html } from "lit" -import INumericPinTemplate from "./INumericPinTemplate.js" import Utility from "../../Utility.js" +import INumericPinTemplate from "./INumericPinTemplate.js" /** * @template {Number} T diff --git a/js/template/pin/ReferencePinTemplate.js b/js/template/pin/ReferencePinTemplate.js index 96779de..baf686c 100644 --- a/js/template/pin/ReferencePinTemplate.js +++ b/js/template/pin/ReferencePinTemplate.js @@ -1,5 +1,5 @@ -import PinTemplate from "./PinTemplate.js" import SVGIcon from "../../SVGIcon.js" +import PinTemplate from "./PinTemplate.js" export default class ReferencePinTemplate extends PinTemplate { diff --git a/js/template/pin/RotatorPinTemplate.js b/js/template/pin/RotatorPinTemplate.js index a5922f0..e6f6168 100644 --- a/js/template/pin/RotatorPinTemplate.js +++ b/js/template/pin/RotatorPinTemplate.js @@ -1,7 +1,7 @@ import { html } from "lit" -import INumericPinTemplate from "./INumericPinTemplate.js" -import RotatorEntity from "../../entity/RotatorEntity.js" import Utility from "../../Utility.js" +import RotatorEntity from "../../entity/RotatorEntity.js" +import INumericPinTemplate from "./INumericPinTemplate.js" /** @extends INumericPinTemplate */ export default class RotatorPinTemplate extends INumericPinTemplate { diff --git a/js/template/pin/Vector2DPinTemplate.js b/js/template/pin/Vector2DPinTemplate.js index b50a0ec..558ea28 100644 --- a/js/template/pin/Vector2DPinTemplate.js +++ b/js/template/pin/Vector2DPinTemplate.js @@ -1,7 +1,7 @@ import { html } from "lit" -import INumericPinTemplate from "./INumericPinTemplate.js" import Utility from "../../Utility.js" import Vector2DEntity from "../../entity/Vector2DEntity.js" +import INumericPinTemplate from "./INumericPinTemplate.js" /** * @extends INumericPinTemplate diff --git a/js/template/pin/VectorPinTemplate.js b/js/template/pin/VectorPinTemplate.js index fae2157..e4c790d 100644 --- a/js/template/pin/VectorPinTemplate.js +++ b/js/template/pin/VectorPinTemplate.js @@ -1,7 +1,7 @@ import { html } from "lit" -import INumericPinTemplate from "./INumericPinTemplate.js" import Utility from "../../Utility.js" import VectorEntity from "../../entity/VectorEntity.js" +import INumericPinTemplate from "./INumericPinTemplate.js" /** @extends INumericPinTemplate */ export default class VectorPinTemplate extends INumericPinTemplate { diff --git a/package.json b/package.json index 53fb2c8..3d95098 100755 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "ueblueprint", "version": "1.0.0", - "description": "UE's Blueprint visualisation library", "type": "module", + "description": "UE's Blueprint visualisation library", "main": "dist/ueblueprint.js", "types": "types.js", "scripts": { diff --git a/tests/colorPicker.spec.js b/tests/colorPicker.spec.js index d158155..09f5f2c 100644 --- a/tests/colorPicker.spec.js +++ b/tests/colorPicker.spec.js @@ -1,6 +1,6 @@ -import { test, expect } from "./fixtures/test.js" -import BlueprintFixture from "./fixtures/BlueprintFixture.js" import Configuration from "../js/Configuration.js" +import BlueprintFixture from "./fixtures/BlueprintFixture.js" +import { expect, test } from "./fixtures/test.js" test.describe("Color picker", () => { diff --git a/tests/entities.spec.js b/tests/entities.spec.js index 1772a8a..021806f 100644 --- a/tests/entities.spec.js +++ b/tests/entities.spec.js @@ -1,22 +1,22 @@ // @ts-nocheck -import { test, expect } from "./fixtures/test.js" -import Entity1 from "./resources/Entity1.js" -import Entity2 from "./resources/Entity2.js" -import entity2Value from "./resources/serializedEntity2.js" -import Entity3 from "./resources/Entity3.js" -import entity3Value from "./resources/serializedEntity3.js" -import Entity4 from "./resources/Entity4.js" -import entity4Value from "./resources/serializedEntity4.js" -import Entity5 from "./resources/Entity5.js" -import entity5Value1 from "./resources/serializedEntity5-1.js" -import EntityF from "./resources/EntityF.js" +import UnknownKeysEntity from "../js/entity/UnknownKeysEntity.js" import Grammar from "../js/serialization/Grammar.js" -import initializeSerializerFactory from "../js/serialization/initializeSerializerFactory.js" import ObjectSerializer from "../js/serialization/ObjectSerializer.js" import Serializer from "../js/serialization/Serializer.js" import SerializerFactory from "../js/serialization/SerializerFactory.js" -import UnknownKeysEntity from "../js/entity/UnknownKeysEntity.js" +import initializeSerializerFactory from "../js/serialization/initializeSerializerFactory.js" +import { expect, test } from "./fixtures/test.js" +import Entity1 from "./resources/Entity1.js" +import Entity2 from "./resources/Entity2.js" +import Entity3 from "./resources/Entity3.js" +import Entity4 from "./resources/Entity4.js" +import Entity5 from "./resources/Entity5.js" +import EntityF from "./resources/EntityF.js" +import entity2Value from "./resources/serializedEntity2.js" +import entity3Value from "./resources/serializedEntity3.js" +import entity4Value from "./resources/serializedEntity4.js" +import entity5Value1 from "./resources/serializedEntity5-1.js" test.describe.configure({ mode: "parallel" }) @@ -31,7 +31,7 @@ test("Entity2", () => { Entity1, new Serializer(Entity1, (entity, v) => `Entity1(${v})`, ", ", false, "=",) ) - expect(Object.keys(entity)).toHaveLength(8) + expect(Object.keys(entity)).toHaveLength(9) expect(entity.someNumber).toBe(567) expect(entity.someString).toBe("alpha") expect(entity.someString2).toBe("beta") @@ -39,6 +39,7 @@ test("Entity2", () => { expect(entity.someBoolean2).toBe(false) expect(entity.someObjectString).toBe("gamma") expect(entity.someArray).toStrictEqual([400, 500, 600, 700, 800]) + expect(entity.someArray2).toStrictEqual([400, 500, 600, 700, 800]) expect(entity.equals(new Entity2())).toBeTruthy() diff --git a/tests/nodes.spec.js b/tests/nodes.spec.js index 91f0381..2e45523 100644 --- a/tests/nodes.spec.js +++ b/tests/nodes.spec.js @@ -1,8 +1,10 @@ -import { test, expect } from "./fixtures/test.js" +import Utility from "../js/Utility.js" import Configuration from "./../js/Configuration.js" +import { expect, test } from "./fixtures/test.js" import EventNodes from "./resources/EventNodes.js" import FlowControlNodes from "./resources/FlowControlNodes.js" import InputNodes from "./resources/InputNodes.js" +import IssuesNodes1 from "./resources/IssuesNodes1.js" import LegacyNodes from "./resources/LegacyNodes.js" import MaterialNodes from "./resources/MaterialNodes.js" import OperationsNodes from "./resources/OperationsNodes.js" @@ -17,15 +19,10 @@ const nodeTests = [ ...MaterialNodes.get(), ...OperationsNodes.get(), ...OtherNodes.get(), - ...PCGNodes.get() + ...PCGNodes.get(), + ...IssuesNodes1.get(), ] -/** @param {String[]} words */ -function getFirstWordOrder(words) { - return new RegExp(/\s*/.source + words.join(/[^\n]+\n\s*/.source) + /\s*/.source) -} - - test.describe.configure({ mode: "parallel" }) for (const nodeTest of nodeTests) { @@ -63,7 +60,7 @@ for (const nodeTest of nodeTests) { test( `${nodeTest.name}: Has title ${nodeTest.title}`, async ({ blueprintPage }) => expect( - await blueprintPage.node.evaluate(node => node.getNodeDisplayName()) + await blueprintPage.node.evaluate(node => node.nodeDisplayName) ).toBe(nodeTest.title) ) } @@ -136,15 +133,15 @@ for (const nodeTest of nodeTests) { test( `${nodeTest.name}: Maintains the order of attributes`, async ({ blueprintPage }) => { - const value = await blueprintPage.blueprintLocator.evaluate(blueprint => { + const serialized = await blueprintPage.blueprintLocator.evaluate(blueprint => { blueprint.selectAll() return blueprint.template.getCopyInputObject().getSerializedText() }) - const words = value + const words = nodeTest.value .split("\n") .map(row => row.match(/\s*("?\w+(\s+\w+)*).+/)?.[1]) .filter(v => v?.length > 0) - expect(value).toMatch(getFirstWordOrder(words)) + expect(serialized).toMatch(Utility.getFirstWordOrder(words)) } ) if (nodeTest.variadic) { @@ -162,7 +159,11 @@ for (const nodeTest of nodeTests) { test( `${nodeTest.name}: Additional tests`, async ({ blueprintPage }) => - nodeTest.additionalTest(blueprintPage.node, await blueprintPage.node.locator("ueb-pin").all()) + nodeTest.additionalTest( + blueprintPage.node, + await blueprintPage.node.locator("ueb-pin").all(), + blueprintPage, + ) ) } }) diff --git a/tests/parsing.spec.js b/tests/parsing.spec.js index a25322b..bbabf64 100644 --- a/tests/parsing.spec.js +++ b/tests/parsing.spec.js @@ -1,21 +1,23 @@ -import { test, expect } from "@playwright/test" +import { expect, test } from "@playwright/test" +import Utility from "../js/Utility.js" import FormatTextEntity from "../js/entity/FormatTextEntity.js" -import Grammar from "../js/serialization/Grammar.js" import GuidEntity from "../js/entity/GuidEntity.js" -import initializeSerializerFactory from "../js/serialization/initializeSerializerFactory.js" import IntegerEntity from "../js/entity/IntegerEntity.js" import KeyBindingEntity from "../js/entity/KeyBindingEntity.js" import LinearColorEntity from "../js/entity/LinearColorEntity.js" import ObjectReferenceEntity from "../js/entity/ObjectReferenceEntity.js" +import PinTypeEntity from "../js/entity/PinTypeEntity.js" import RotatorEntity from "../js/entity/RotatorEntity.js" -import SerializerFactory from "../js/serialization/SerializerFactory.js" import SymbolEntity from "../js/entity/SymbolEntity.js" import UnknownKeysEntity from "../js/entity/UnknownKeysEntity.js" -import Utility from "../js/Utility.js" import Vector2DEntity from "../js/entity/Vector2DEntity.js" import VectorEntity from "../js/entity/VectorEntity.js" +import Grammar from "../js/serialization/Grammar.js" +import SerializerFactory from "../js/serialization/SerializerFactory.js" +import initializeSerializerFactory from "../js/serialization/initializeSerializerFactory.js" +import PinEntity from "../js/entity/PinEntity.js" -initializeSerializerFactory() +test.beforeAll(() => initializeSerializerFactory()) test.describe.configure({ mode: "parallel" }) @@ -168,6 +170,15 @@ test("LinearColorEntity", () => { expect(() => serializer.read("(R=0.000000,G=\"hello\",A=1.000000)")).toThrow() }) +test("Null", () => { + const serializer = SerializerFactory.getSerializer(null) + + expect(serializer.read("()")).toBeNull() + expect(() => serializer.read("123")).toThrow() + expect(() => serializer.read("(a)")).toThrow() + expect(() => serializer.read("(")).toThrow() +}) + test("Number", () => { const serializer = SerializerFactory.getSerializer(Number) @@ -280,6 +291,14 @@ test("ObjectReferenceEntity", () => { }) }) +test("PinEntity", () => { + const serializer = SerializerFactory.getSerializer(PinEntity) + + expect(serializer.read("Pin (PinType.PinSubCategoryMemberReference=())")).toMatchObject({ + "PinType": { "PinSubCategoryMemberReference": null } + }) +}) + test("String", () => { const serializer = SerializerFactory.getSerializer(String) diff --git a/tests/resources/Entity1.js b/tests/resources/Entity1.js index ab301e1..eeee542 100644 --- a/tests/resources/Entity1.js +++ b/tests/resources/Entity1.js @@ -1,16 +1,17 @@ +import AttributeInfo from "../../js/entity/AttributeInfo.js" import IEntity from "../../js/entity/IEntity.js" export default class Entity1 extends IEntity { static attributes = { - a: { + a: new AttributeInfo({ type: Number, default: 8, - }, - b: { + }), + b: new AttributeInfo({ type: Number, default: 9, - }, + }), } constructor(values = {}) { diff --git a/tests/resources/Entity2.js b/tests/resources/Entity2.js index 014a25d..fcfa340 100644 --- a/tests/resources/Entity2.js +++ b/tests/resources/Entity2.js @@ -1,37 +1,21 @@ -import Entity1 from "./Entity1.js" +import AttributeInfo from "../../js/entity/AttributeInfo.js" import IEntity from "../../js/entity/IEntity.js" +import Entity1 from "./Entity1.js" export default class Entity2 extends IEntity { static attributes = { - someNumber: { - default: 567, - }, - someString: { - default: "alpha", - }, - someString2: { - default: "beta", - }, - someBoolean: { - default: true, - }, - someBoolean2: { - default: false, - }, - someObjectString: { - default: "gamma", - }, - someArray: { - default: [400, 500, 600, 700, 800], - }, - someEntity: { + someNumber: AttributeInfo.createValue(567), + someString: AttributeInfo.createValue("alpha"), + someString2: AttributeInfo.createValue("beta"), + someBoolean: AttributeInfo.createValue(true), + someBoolean2: AttributeInfo.createValue(false), + someObjectString: AttributeInfo.createValue("gamma"), + someArray: AttributeInfo.createValue([400, 500, 600, 700, 800]), + someArray2: AttributeInfo.createValue(() => [400, 500, 600, 700, 800]), + someEntity: new AttributeInfo({ type: Entity1, default: new Entity1() - }, - } - - static { - this.cleanupAttributes(this.attributes) + }), } } diff --git a/tests/resources/Entity3.js b/tests/resources/Entity3.js index 3510af2..2aa95b0 100644 --- a/tests/resources/Entity3.js +++ b/tests/resources/Entity3.js @@ -1,87 +1,74 @@ -import Entity1 from "./Entity1.js" -import Entity2 from "./Entity2.js" +import AttributeInfo from "../../js/entity/AttributeInfo.js" import IEntity from "../../js/entity/IEntity.js" import Union from "../../js/entity/Union.js" +import Entity1 from "./Entity1.js" +import Entity2 from "./Entity2.js" export default class Entity3 extends IEntity { static attributes = { - alpha: { - default: 32, - }, - bravo: { + alpha: AttributeInfo.createValue(32), + bravo: new AttributeInfo({ type: Number, default: 78, - }, - charlie: { + }), + charlie: new AttributeInfo({ type: String, default: "Charlie", - }, - delta: { + }), + delta: new AttributeInfo({ type: String, default: null, - }, - echo: { - default: "echo", - }, - foxtrot: { - default: false, - }, - golf: { - default: [], - }, - hotel: { + }), + echo: AttributeInfo.createValue("echo"), + foxtrot: AttributeInfo.createValue(false), + golf: AttributeInfo.createValue([]), + hotel: new AttributeInfo({ type: Array, default: null, - }, - india: { + }), + india: new AttributeInfo({ type: [Number], default: () => [], - }, - juliett: { + }), + juliett: new AttributeInfo({ type: [String], default: ["a", "b", "c", "d", "e"], - }, - kilo: { + }), + kilo: new AttributeInfo({ type: [Boolean], default: () => [true, false, false, true, true], - }, - lima: { - type: String, - }, - mike: { + }), + lima: AttributeInfo.createType(String), + mike: new AttributeInfo({ type: new Union(Number, String, Array), default: "Bar", - }, - november: { + }), + november: new AttributeInfo({ type: new Union(Number, String, Array), default: 0, - }, - oscar: { + }), + oscar: new AttributeInfo({ type: Entity1, default: () => new Entity1() - }, - papa: { + }), + papa: new AttributeInfo({ type: Entity1, default: () => new Entity1({ a: 12, b: 13 }), - }, - quebec: { + }), + quebec: new AttributeInfo({ default: 0, // will assign undefined because it does not satisfy the predicate predicate: v => v >= 1 && v <= 10, - }, - romeo: { + }), + romeo: new AttributeInfo({ type: Entity1, default: new Entity1(), inlined: true, - }, - sierra: { + }), + sierra: new AttributeInfo({ type: Entity2, default: new Entity2(), inlined: true, - } - } - - static { - this.cleanupAttributes(this.attributes) + }), } } diff --git a/tests/resources/Entity4.js b/tests/resources/Entity4.js index e93d0e2..287fdab 100644 --- a/tests/resources/Entity4.js +++ b/tests/resources/Entity4.js @@ -1,19 +1,24 @@ +import AttributeInfo from "../../js/entity/AttributeInfo.js" +import IEntity from "../../js/entity/IEntity.js" import Entity1 from "./Entity1.js" import Entity3 from "./Entity3.js" -import IEntity from "../../js/entity/IEntity.js" export default class Entity4 extends IEntity { static attributes = { - first: { + first: new AttributeInfo({ type: Entity3, default: new Entity3(), inlined: true, - }, - second: { + }), + second: new AttributeInfo({ default: [new Entity1({ a: 1, b: 2 }), new Entity1({ a: 11, b: 22 })], inlined: true, - }, + }), + third: new AttributeInfo({ + type: Array, + default: null, + }) } constructor() { @@ -25,8 +30,4 @@ export default class Entity4 extends IEntity { }, }) } - - static { - this.cleanupAttributes(this.attributes) - } } diff --git a/tests/resources/Entity5.js b/tests/resources/Entity5.js index b20b3a4..350e767 100644 --- a/tests/resources/Entity5.js +++ b/tests/resources/Entity5.js @@ -1,18 +1,13 @@ -import EntityF from "./EntityF.js" +import AttributeInfo from "../../js/entity/AttributeInfo.js" import ObjectEntity from "../../js/entity/ObjectEntity.js" +import EntityF from "./EntityF.js" +// @ts-expect-error export default class Entity5 extends ObjectEntity { static attributes = { - key1: { - type: String, - }, - key2: { - type: EntityF, - }, - } - static { - this.cleanupAttributes(this.attributes) + key1: AttributeInfo.createType(String), + key2: AttributeInfo.createType(EntityF), } static grammar = this.createGrammar() } diff --git a/tests/resources/EntityF.js b/tests/resources/EntityF.js index b632531..9d19ef5 100644 --- a/tests/resources/EntityF.js +++ b/tests/resources/EntityF.js @@ -1,18 +1,18 @@ -import Grammar from "../../js/serialization/Grammar.js" +import AttributeInfo from "../../js/entity/AttributeInfo.js" import IEntity from "../../js/entity/IEntity.js" import Union from "../../js/entity/Union.js" +import Grammar from "../../js/serialization/Grammar.js" export default class EntityF extends IEntity { - static lookbehind = new Union("Foo", "Bar") static attributes = { ...super.attributes, - arg1: { - type: Number, - }, - arg2: { - type: String, - }, + arg1: AttributeInfo.createType(Number), + arg2: AttributeInfo.createType(String), + lookbehind: new AttributeInfo({ + ...super.attributes.lookbehind, + default: new Union("Foo", "Bar"), + }) } static grammar = this.createGrammar() diff --git a/tests/resources/EventNodes.js b/tests/resources/EventNodes.js index e997201..2392c0b 100644 --- a/tests/resources/EventNodes.js +++ b/tests/resources/EventNodes.js @@ -1,6 +1,6 @@ import Configuration from "../../js/Configuration.js" -import NodeTests from "./NodeTests.js" import SVGIcon from "../../js/SVGIcon.js" +import NodeTests from "./NodeTests.js" export default class EventNodes extends NodeTests { static { diff --git a/tests/resources/IssuesNodes1.js b/tests/resources/IssuesNodes1.js new file mode 100644 index 0000000..e2b3448 --- /dev/null +++ b/tests/resources/IssuesNodes1.js @@ -0,0 +1,102 @@ +import Configuration from "../../js/Configuration.js" +import Utility from "../../js/Utility.js" +import { expect } from "../fixtures/test.js" +import NodeTests from "./NodeTests.js" + +export default class IssuesNodes1 extends NodeTests { + static { + this.set([ + { + name: "Issue 18", + title: "Mask ( R )", + value: String.raw` + Begin Object Class=/Script/UnrealEd.MaterialGraphNode Name="MaterialGraphNode_37" ExportPath="/Script/UnrealEd.MaterialGraphNode'/Engine/Transient.NewMaterial:MaterialGraph_0.MaterialGraphNode_37'" + Begin Object Class=/Script/Engine.MaterialExpressionComponentMask Name="MaterialExpressionComponentMask_0" ExportPath="/Script/Engine.MaterialExpressionComponentMask'/Engine/Transient.NewMaterial:MaterialGraph_0.MaterialGraphNode_37.MaterialExpressionComponentMask_0'" + End Object + Begin Object Name="MaterialExpressionComponentMask_0" ExportPath="/Script/Engine.MaterialExpressionComponentMask'/Engine/Transient.NewMaterial:MaterialGraph_0.MaterialGraphNode_37.MaterialExpressionComponentMask_0'" + R=True + MaterialExpressionEditorX=-544 + MaterialExpressionEditorY=32 + MaterialExpressionGuid=8EFA535CAE3A4DAF9DAE27B200E06EDC + Material="/Script/UnrealEd.PreviewMaterial'/Engine/Transient.NewMaterial'" + End Object + MaterialExpression="/Script/Engine.MaterialExpressionComponentMask'MaterialExpressionComponentMask_0'" + NodePosX=-544 + NodePosY=32 + AdvancedPinDisplay=Shown + NodeGuid=54A40610EEC646A0954F310727D1B888 + CustomProperties Pin (PinId=DC3859AB4C8C12645EEA1AA4E500A637,PinName="Input",PinFriendlyName=NSLOCTEXT("MaterialGraphNode", "Space", " "),PinType.PinCategory="required",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) + CustomProperties Pin (PinId=D5C8F4DF4AFE5EEB605ED382CD5744DE,PinName="R",PinType.PinCategory="optional",PinType.PinSubCategory="bool",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="true",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=True,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) + CustomProperties Pin (PinId=7E43455B4D2232C4E99BB098631CAFCE,PinName="G",PinType.PinCategory="optional",PinType.PinSubCategory="bool",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="false",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=True,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) + CustomProperties Pin (PinId=46CEC6754365CB39F9FC39944B40D5C6,PinName="B",PinType.PinCategory="optional",PinType.PinSubCategory="bool",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="false",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=True,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) + CustomProperties Pin (PinId=F658E76C400B0AF242DFE292C92702C8,PinName="A",PinType.PinCategory="optional",PinType.PinSubCategory="bool",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="false",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=True,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) + CustomProperties Pin (PinId=2EC8C8234D570AB2A03DB59A1FF65987,PinName="Output",PinFriendlyName=NSLOCTEXT("MaterialGraphNode", "Space", " "),Direction="EGPD_Output",PinType.PinCategory="",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) + End Object + `, + size: [7, 14.5], + color: Configuration.nodeColors.green, + icon: null, + pins: 6, + pinNames: Configuration.rgba, + delegate: false, + development: false, + additionalTest: async (node, pins, blueprintPage) => { + const relevantPins = (await Promise.all( + pins.map(async p => { + const innerText = await p.innerText() + // @ts-expect-error + return [Configuration.rgba.includes(innerText), p] + }) + )) + .filter(([flag, value]) => flag) + .map(([flag, value]) => /** @type {Locator} */(value)) + expect(await Promise.all(relevantPins.map(async pin => await pin.innerText()))).toStrictEqual(Configuration.rgba) + for (const p of relevantPins) { + const pinName = await p.innerText() + expect(p.locator('input[type="checkbox"]')).toBeChecked({ checked: pinName === "R" }) + } + await relevantPins[0].locator('input[type="checkbox"]').uncheck() // Uncheck "R" + await relevantPins[2].locator('input[type="checkbox"]').check() // Check "B" + await relevantPins[4].locator('input[type="checkbox"]').check() // Check "A" + await relevantPins[2].locator('input[type="checkbox"]').uncheck() // Uncheck "B" + await relevantPins[2].locator('input[type="checkbox"]').check() // Check "B" + expect(node.locator(".ueb-node-name")).toHaveText("Mask ( B A )") + const resultSerialization = await blueprintPage.blueprintLocator.evaluate(blueprint => { + blueprint.selectAll() + return blueprint.template.getCopyInputObject().getSerializedText() + }) + const expectedSerialization = String.raw` + Begin Object Class=/Script/UnrealEd.MaterialGraphNode Name="MaterialGraphNode_37" ExportPath="/Script/UnrealEd.MaterialGraphNode'/Engine/Transient.NewMaterial:MaterialGraph_0.MaterialGraphNode_37'" + Begin Object Class=/Script/Engine.MaterialExpressionComponentMask Name="MaterialExpressionComponentMask_0" ExportPath="/Script/Engine.MaterialExpressionComponentMask'/Engine/Transient.NewMaterial:MaterialGraph_0.MaterialGraphNode_37.MaterialExpressionComponentMask_0'" + End Object + Begin Object Name="MaterialExpressionComponentMask_0" ExportPath="/Script/Engine.MaterialExpressionComponentMask'/Engine/Transient.NewMaterial:MaterialGraph_0.MaterialGraphNode_37.MaterialExpressionComponentMask_0'" + B=True + A=True + MaterialExpressionEditorX=-544 + MaterialExpressionEditorY=32 + MaterialExpressionGuid=8EFA535CAE3A4DAF9DAE27B200E06EDC + Material="/Script/UnrealEd.PreviewMaterial'/Engine/Transient.NewMaterial'" + End Object + MaterialExpression="/Script/Engine.MaterialExpressionComponentMask'MaterialExpressionComponentMask_0'" + NodePosX=-544 + NodePosY=32 + AdvancedPinDisplay=Shown + NodeGuid=54A40610EEC646A0954F310727D1B888 + CustomProperties Pin (PinId=DC3859AB4C8C12645EEA1AA4E500A637,PinName="Input",PinFriendlyName=NSLOCTEXT("MaterialGraphNode", "Space", " "),PinType.PinCategory="required",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) + CustomProperties Pin (PinId=D5C8F4DF4AFE5EEB605ED382CD5744DE,PinName="R",PinType.PinCategory="optional",PinType.PinSubCategory="bool",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="true",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=True,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) + CustomProperties Pin (PinId=7E43455B4D2232C4E99BB098631CAFCE,PinName="G",PinType.PinCategory="optional",PinType.PinSubCategory="bool",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="false",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=True,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) + CustomProperties Pin (PinId=46CEC6754365CB39F9FC39944B40D5C6,PinName="B",PinType.PinCategory="optional",PinType.PinSubCategory="bool",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="false",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=True,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) + CustomProperties Pin (PinId=F658E76C400B0AF242DFE292C92702C8,PinName="A",PinType.PinCategory="optional",PinType.PinSubCategory="bool",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="false",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=True,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=True,bOrphanedPin=False,) + CustomProperties Pin (PinId=2EC8C8234D570AB2A03DB59A1FF65987,PinName="Output",PinFriendlyName=NSLOCTEXT("MaterialGraphNode", "Space", " "),Direction="EGPD_Output",PinType.PinCategory="",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) + End Object + ` + const words = expectedSerialization + .split("\n") + .map(row => row.match(/\s*("?\w+(\s+\w+)*).+/)?.[1]) + .filter(v => v?.length > 0) + expect(resultSerialization).toMatch(Utility.getFirstWordOrder(words)) + } + }, + ]) + } +} diff --git a/tests/resources/LegacyNodes.js b/tests/resources/LegacyNodes.js index 2c08255..d7b1fb5 100644 --- a/tests/resources/LegacyNodes.js +++ b/tests/resources/LegacyNodes.js @@ -1,6 +1,6 @@ -import { expect } from "../fixtures/test.js" import Configuration from "../../js/Configuration.js" import SVGIcon from "../../js/SVGIcon.js" +import { expect } from "../fixtures/test.js" import NodeTests from "./NodeTests.js" export default class LegacyNodes extends NodeTests { diff --git a/tests/resources/MaterialNodes.js b/tests/resources/MaterialNodes.js index 0fe285f..85f7260 100644 --- a/tests/resources/MaterialNodes.js +++ b/tests/resources/MaterialNodes.js @@ -1,11 +1,11 @@ -import { expect } from "../fixtures/test.js" import Configuration from "../../js/Configuration.js" -import IntegerEntity from "../../js/entity/IntegerEntity.js" -import NodeTests from "./NodeTests.js" -import PinElement from "../../js/element/PinElement.js" -import RBSerializationVector2DEntity from "../../js/entity/RBSerializationVector2DEntity.js" import Utility from "../../js/Utility.js" +import PinElement from "../../js/element/PinElement.js" +import IntegerEntity from "../../js/entity/IntegerEntity.js" +import RBSerializationVector2DEntity from "../../js/entity/RBSerializationVector2DEntity.js" import VectorEntity from "../../js/entity/VectorEntity.js" +import { expect } from "../fixtures/test.js" +import NodeTests from "./NodeTests.js" export default class MaterialNodes extends NodeTests { static { diff --git a/tests/resources/NodeTests.js b/tests/resources/NodeTests.js index c4a5731..b7332f5 100644 --- a/tests/resources/NodeTests.js +++ b/tests/resources/NodeTests.js @@ -12,7 +12,7 @@ * delegate: Boolean, * development: Boolean, * variadic?: Boolean, - * additionalTest?: (node: Locator, pins: Locator[]) => void, + * additionalTest?: (node: Locator, pins: Locator[], blueprintPage: BlueprintFixture) => void, * }} TestData */ diff --git a/tests/resources/OperationsNodes.js b/tests/resources/OperationsNodes.js index e323c88..fd0185e 100644 --- a/tests/resources/OperationsNodes.js +++ b/tests/resources/OperationsNodes.js @@ -1,7 +1,7 @@ +import SVGIcon from "../../js/SVGIcon.js" +import PinElement from "../../js/element/PinElement.js" import { expect } from "../fixtures/test.js" import NodeTests from "./NodeTests.js" -import PinElement from "../../js/element/PinElement.js" -import SVGIcon from "../../js/SVGIcon.js" export default class OperationsNodes extends NodeTests { static { diff --git a/tests/resources/OtherNodes.js b/tests/resources/OtherNodes.js index 0124370..cb190ca 100644 --- a/tests/resources/OtherNodes.js +++ b/tests/resources/OtherNodes.js @@ -1,6 +1,6 @@ import Configuration from "../../js/Configuration.js" -import NodeTests from "./NodeTests.js" import SVGIcon from "../../js/SVGIcon.js" +import NodeTests from "./NodeTests.js" export default class OtherNodes extends NodeTests { static { diff --git a/tests/resources/PCGNodes.js b/tests/resources/PCGNodes.js index e2dfb22..55e7abb 100644 --- a/tests/resources/PCGNodes.js +++ b/tests/resources/PCGNodes.js @@ -1,7 +1,6 @@ -import { expect } from "../fixtures/test.js" -import Configuration from "../../js/Configuration.js" -import NodeTests from "./NodeTests.js" import SVGIcon from "../../js/SVGIcon.js" +import { expect } from "../fixtures/test.js" +import NodeTests from "./NodeTests.js" export default class PCGNodes extends NodeTests { static { diff --git a/tests/resources/serializedEntity2.js b/tests/resources/serializedEntity2.js index 180554d..3773477 100644 --- a/tests/resources/serializedEntity2.js +++ b/tests/resources/serializedEntity2.js @@ -6,5 +6,6 @@ export default `{ someBoolean2: False someObjectString: "gamma" someArray: (400,500,600,700,800,) + someArray2: (400,500,600,700,800,) someEntity: Entity1(a=8, b=9) }` diff --git a/tests/resources/serializedEntity3.js b/tests/resources/serializedEntity3.js index 7239bfe..c5812dd 100644 --- a/tests/resources/serializedEntity3.js +++ b/tests/resources/serializedEntity3.js @@ -24,5 +24,6 @@ export default `[[ sierra.someBoolean2: False sierra.someObjectString: "gamma" sierra.someArray: (400,500,600,700,800,) + sierra.someArray2: (400,500,600,700,800,) sierra.someEntity: Entity1(a=8, b=9) ]]` diff --git a/tests/resources/serializedEntity4.js b/tests/resources/serializedEntity4.js index 2c7320d..1b476c1 100644 --- a/tests/resources/serializedEntity4.js +++ b/tests/resources/serializedEntity4.js @@ -23,8 +23,10 @@ export default `Begin \${first.sierra.someBoolean2} => False \${first.sierra.someObjectString} => "gamma" \${first.sierra.someArray} => (400,500,600,700,800,) + \${first.sierra.someArray2} => (400,500,600,700,800,) \${first.sierra.someEntity} => E1[A:8 - B:9] \${second(0).a} => 1 \${second(0).b} => 2 \${second(1)} => E1[A:11 - B:22] + \${third} => () End` diff --git a/tests/utility.spec.js b/tests/utility.spec.js index ca4db5d..6e389c3 100644 --- a/tests/utility.spec.js +++ b/tests/utility.spec.js @@ -1,5 +1,5 @@ -import { expect, test } from "./fixtures/test.js" import Utility from "../js/Utility.js" +import { expect, test } from "./fixtures/test.js" test.describe.configure({ mode: "parallel" }) diff --git a/types.js b/types.js index 310e92b..de48dc8 100644 --- a/types.js +++ b/types.js @@ -1,13 +1,3 @@ -/** @typedef {[Number, Number]} Coordinates */ -/** - * @typedef {IEntity | String | Number | BigInt | Boolean | Array} TerminalAttribute - * @typedef {TerminalAttribute | MirroredEntity} Attribute - * @typedef {( - * AttributeConstructor | AttributeConstructor[] - * | MirroredEntity | Union | Union[] | ComputedType - * )} AttributeTypeDescription - * @typedef {(entity: IEntity) => Attribute} ValueSupplier - */ /** * @template T * @typedef {new (...args: any) => T} AnyConstructor @@ -15,7 +5,17 @@ /** * @template {Attribute} T * @typedef {AnyConstructor & EntityConstructor | StringConstructor | NumberConstructor | BigIntConstructor - * | BooleanConstructor | ArrayConstructor | MirroredEntityConstructor} AttributeConstructor +* | BooleanConstructor | ArrayConstructor | MirroredEntityConstructor} AttributeConstructor +*/ +/** + * @typedef {[Number, Number]} Coordinates + * @typedef {IEntity | String | Number | BigInt | Boolean | Array} TerminalAttribute + * @typedef {TerminalAttribute | MirroredEntity} Attribute + * @typedef {( + * AttributeConstructor | AttributeConstructor[] + * | MirroredEntity | Union | Union[] | ComputedType + * )} AttributeTypeDescription + * @typedef {(entity: IEntity) => Attribute} ValueSupplier */ /** * @template {Attribute} T @@ -38,7 +38,9 @@ */ /** * @template T - * @typedef {T extends StringConstructor + * @typedef {T extends AnyConstructor + * ? R + * : T extends StringConstructor * ? String * : T extends NumberConstructor * ? Number @@ -48,26 +50,40 @@ * ? Boolean * : T extends ArrayConstructor * ? Array - * : T extends MirroredEntity - * ? MirroredEntity - * : T extends AnyConstructor - * ? R * : any * } ConstructedType */ /** - * @typedef {{ - * type?: AttributeTypeDescription, - * default?: Attribute | ValueSupplier, - * nullable?: Boolean, - * ignored?: Boolean, - * serialized?: Boolean, - * expected?: Boolean, - * inlined?: Boolean, - * quoted?: Boolean, - * predicate?: (value: Attribute) => Boolean, - * }} AttributeInformation - * @typedef {{ [key: String]: AttributeInformation }} AttributeDeclarations + * @template T + * @typedef {T extends [infer A] ? DescribedType +* : T extends [infer A, ...infer B] ? (DescribedType | DescribedTypesFromArray) +* : any +* } DescribedTypesFromArray +**/ +/** + * @template T + * @typedef {T extends AnyConstructor + * ? R + * : T extends StringConstructor + * ? String + * : T extends NumberConstructor + * ? Number + * : T extends BigIntConstructor + * ? BigInt + * : T extends BooleanConstructor + * ? Boolean + * : T extends Array + * ? DescribedType[] + * : T extends MirroredEntity + * ? DescribedType + * : T extends Union + * ? DescribedTypesFromArray + * : T + * } DescribedType + */ +/** + * @typedef {import("./js/entity/AttributeInfo.js").default} AttributeInfo + * @typedef {{ [key: String]: AttributeInfo }} AttributeDeclarations */ /** * @typedef {CustomEvent<{ value: Coordinates }>} UEBDragEvent @@ -82,6 +98,10 @@ * (value: T): typeof value.constructor, * }} TypeGetter */ +/** + * @template {any[]} T + * @typedef {import("./js/entity/Union.js").default} Union + */ /** * @typedef {typeof import("./js/Blueprint.js").default} BlueprintConstructor * @typedef {typeof import("./js/element/LinkElement.js").default} LinkElementConstructor @@ -141,7 +161,6 @@ * @typedef {import("./js/entity/SimpleSerializationVectorEntity.js").default} SimpleSerializationVectorEntity * @typedef {import("./js/entity/SymbolEntity.js").default} SymbolEntity * @typedef {import("./js/entity/TerminalTypeEntity.js").default} TerminalTypeEntity - * @typedef {import("./js/entity/Union.js").default} Union * @typedef {import("./js/entity/UnknownKeysEntity.js").default} UnknownKeysEntity * @typedef {import("./js/entity/UnknownPinEntity.js").default} UnknownPinEntity * @typedef {import("./js/entity/VariableReferenceEntity.js").default} VariableReferenceEntity @@ -191,6 +210,7 @@ * @typedef {import("./js/template/SelectorTemplate.js").default} SelectorTemplate * @typedef {import("./js/template/window/ColorPickerWindowTemplate.js").default} ColorPickerWindowTemplate * @typedef {import("./js/template/window/WindowTemplate.js").default} WindowTemplate + * @typedef {import ("./tests/fixtures/BlueprintFixture.js").default} BlueprintFixture * @typedef {import("lit").CSSResult} CSSResult * @typedef {import("lit").PropertyValues} PropertyValues * @typedef {import("lit").TemplateResult} TemplateResult @@ -210,7 +230,7 @@ /** * @template T * @typedef {{ -* evaluate(pageFunction: (node: T, arg: Arg) => R, arg: Arg, options?: { timeout?: number }): Promise -* evaluate(pageFunction: (node: T) => R, options?: { timeout?: number }): Promise -* } & import("@playwright/test").Locator} Locator -*/ + * evaluate(pageFunction: (node: T, arg: Arg) => R, arg: Arg, options?: { timeout?: number }): Promise + * evaluate(pageFunction: (node: T) => R, options?: { timeout?: number }): Promise + * } & import("@playwright/test").Locator} Locator + */