Attributes initialization refactoring (#19)

This commit is contained in:
barsdeveloper
2024-03-24 17:30:50 +01:00
committed by GitHub
parent 5973570911
commit cc9e3d833a
93 changed files with 4134 additions and 4082 deletions

2
.gitignore vendored
View File

@@ -2,8 +2,6 @@ node_modules/
package-lock.json
localhost*
*.git
cypress/screenshots
cypress/videos
/test-results/
/playwright-report/
/blob-report/

View File

@@ -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,
}

6295
dist/ueblueprint.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -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",

View File

@@ -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

View File

@@ -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<ObjectEntity, NodeTemplate>} */
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 */

View File

@@ -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()
}
}
}

114
js/entity/AttributeInfo.js Normal file
View File

@@ -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<number>} 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<T>} 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<DescribedType<type>>}
*/
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]
}
}

View File

@@ -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) {

View File

@@ -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()

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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<Union<String[]>>} */(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
})
}

View File

@@ -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()

View File

@@ -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()

View File

@@ -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<String[]>} */
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<String[]>} */(""),
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<Attribute>} */(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
}

View File

@@ -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),

View File

@@ -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()

View File

@@ -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<IntegerEntity>} value */
constructor(value = 0) {
if (value === -0) {
value = 0

View File

@@ -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))
}

View File

@@ -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()

View File

@@ -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()

View File

@@ -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*`

View File

@@ -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()

View File

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

View File

@@ -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<Boolean>} */ this.R
/** @type {Number | MirroredEntity<Boolean>} */ this.G
/** @type {Number | MirroredEntity<Boolean>} */ this.B
/** @type {Number | MirroredEntity<Boolean>} */ 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<IntegerEntity>} */ this.PositionY
/** @type {MirroredEntity<ObjectReferenceEntity>} */ 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:

View File

@@ -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 + `)"'`

View File

@@ -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()

View File

@@ -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 => {

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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) {

View File

@@ -1,7 +1,4 @@
/**
* @template {[...U]} T
* @template {any[]} U
*/
/** @template {any[]} T */
export default class Union {
/** @type {T} */

View File

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

View File

@@ -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),

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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<T>} 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<any>} */(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<Attribute>} 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 --- */

View File

@@ -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"

View File

@@ -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<Attribute>} 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
}

View File

@@ -1,5 +1,5 @@
import Serializer from "./Serializer.js"
import Utility from "../Utility.js"
import Serializer from "./Serializer.js"
/**
* @template {AttributeConstructor<Attribute>} T

View File

@@ -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)

View File

@@ -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<Blueprint> */
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

View File

@@ -1,5 +1,5 @@
import IDraggableControlTemplate from "./IDraggableControlTemplate.js"
import Utility from "../Utility.js"
import IDraggableControlTemplate from "./IDraggableControlTemplate.js"
/** @extends {IDraggableControlTemplate<ColorHandlerElement>} */
export default class ColorHandlerTemplate extends IDraggableControlTemplate {

View File

@@ -1,5 +1,5 @@
import IDraggableControlTemplate from "./IDraggableControlTemplate.js"
import Utility from "../Utility.js"
import IDraggableControlTemplate from "./IDraggableControlTemplate.js"
/** @extends {IDraggableControlTemplate<ColorHandlerElement>} */
export default class ColorSliderTemplate extends IDraggableControlTemplate {

View File

@@ -1,5 +1,5 @@
import IDraggableTemplate from "./IDraggableTemplate.js"
import MouseMoveDraggable from "../input/mouse/MouseMoveDraggable.js"
import IDraggableTemplate from "./IDraggableTemplate.js"
/**
* @template {IDraggableElement} T

View File

@@ -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

View File

@@ -1,5 +1,5 @@
import IDraggablePositionedTemplate from "./IDraggablePositionedTemplate.js"
import MouseMoveNodes from "../input/mouse/MouseMoveNodes.js"
import IDraggablePositionedTemplate from "./IDraggablePositionedTemplate.js"
/**
* @template {NodeElement} T

View File

@@ -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<LinkElement>} */
export default class LinkTemplate extends IFromToPositionedTemplate {

View File

@@ -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<NodeElement>} */
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() {

View File

@@ -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() {

View File

@@ -35,7 +35,7 @@ export default class BoolPinTemplate extends PinTemplate {
renderInput() {
return html`
<input type="checkbox" class="ueb-pin-input-wrapper ueb-pin-input" ?checked="${this.element.defaultValue}" />
<input type="checkbox" class="ueb-pin-input-wrapper ueb-pin-input" ?checked="${this.element.defaultValue === true}" />
`
}
}

View File

@@ -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<DropdownElement>} */
export default class DropdownTemplate extends ITemplate {

View File

@@ -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<EnumEntity> */
export default class EnumPinTemplate extends IInputPinTemplate {

View File

@@ -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 {

View File

@@ -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

View File

@@ -1,5 +1,5 @@
import ITemplate from "../ITemplate.js"
import MouseIgnore from "../../input/mouse/MouseIgnore.js"
import ITemplate from "../ITemplate.js"
/** @extends {ITemplate<InputElement>} */
export default class InputTemplate extends ITemplate {

View File

@@ -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<KnotEntity> */
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])

View File

@@ -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<LinearColorEntity> */

View File

@@ -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"

View File

@@ -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

View File

@@ -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 {

View File

@@ -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<RotatorEntity> */
export default class RotatorPinTemplate extends INumericPinTemplate {

View File

@@ -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<Vector2DEntity>

View File

@@ -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<VectorEntity> */
export default class VectorPinTemplate extends INumericPinTemplate {

View File

@@ -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": {

View File

@@ -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", () => {

View File

@@ -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()

View File

@@ -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,
)
)
}
})

View File

@@ -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)

View File

@@ -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 = {}) {

View File

@@ -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)
}),
}
}

View File

@@ -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)
}),
}
}

View File

@@ -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)
}
}

View File

@@ -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()
}

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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<PinElement>} */(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))
}
},
])
}
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -12,7 +12,7 @@
* delegate: Boolean,
* development: Boolean,
* variadic?: Boolean,
* additionalTest?: (node: Locator<NodeElement>, pins: Locator<PinElement>[]) => void,
* additionalTest?: (node: Locator<NodeElement>, pins: Locator<PinElement>[], blueprintPage: BlueprintFixture) => void,
* }} TestData
*/

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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)
}`

View File

@@ -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)
]]`

View File

@@ -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`

View File

@@ -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" })

View File

@@ -1,13 +1,3 @@
/** @typedef {[Number, Number]} Coordinates */
/**
* @typedef {IEntity | String | Number | BigInt | Boolean | Array} TerminalAttribute
* @typedef {TerminalAttribute | MirroredEntity<TerminalAttribute>} Attribute
* @typedef {(
* AttributeConstructor<Attribute> | AttributeConstructor<Attribute>[]
* | MirroredEntity<Attribute> | 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<T> & EntityConstructor | StringConstructor | NumberConstructor | BigIntConstructor
* | BooleanConstructor | ArrayConstructor | MirroredEntityConstructor<T>} AttributeConstructor
* | BooleanConstructor | ArrayConstructor | MirroredEntityConstructor<T>} AttributeConstructor
*/
/**
* @typedef {[Number, Number]} Coordinates
* @typedef {IEntity | String | Number | BigInt | Boolean | Array} TerminalAttribute
* @typedef {TerminalAttribute | MirroredEntity<TerminalAttribute>} Attribute
* @typedef {(
* AttributeConstructor<Attribute> | AttributeConstructor<Attribute>[]
* | MirroredEntity<Attribute> | Union<any> | Union<any>[] | ComputedType
* )} AttributeTypeDescription
* @typedef {(entity: IEntity) => Attribute} ValueSupplier
*/
/**
* @template {Attribute} T
@@ -38,7 +38,9 @@
*/
/**
* @template T
* @typedef {T extends StringConstructor
* @typedef {T extends AnyConstructor<infer R>
* ? R
* : T extends StringConstructor
* ? String
* : T extends NumberConstructor
* ? Number
@@ -48,26 +50,40 @@
* ? Boolean
* : T extends ArrayConstructor
* ? Array
* : T extends MirroredEntity<infer R>
* ? MirroredEntity<R>
* : T extends AnyConstructor<infer R>
* ? 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<A>
* : T extends [infer A, ...infer B] ? (DescribedType<A> | DescribedTypesFromArray<B>)
* : any
* } DescribedTypesFromArray
**/
/**
* @template T
* @typedef {T extends AnyConstructor<infer R>
* ? R
* : T extends StringConstructor
* ? String
* : T extends NumberConstructor
* ? Number
* : T extends BigIntConstructor
* ? BigInt
* : T extends BooleanConstructor
* ? Boolean
* : T extends Array<infer R>
* ? DescribedType<R>[]
* : T extends MirroredEntity<infer R>
* ? DescribedType<R>
* : T extends Union<infer R>
* ? DescribedTypesFromArray<R>
* : 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<T>} 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<R, Arg>(pageFunction: (node: T, arg: Arg) => R, arg: Arg, options?: { timeout?: number }): Promise<R>
* evaluate<R>(pageFunction: (node: T) => R, options?: { timeout?: number }): Promise<R>
* } & import("@playwright/test").Locator} Locator
*/
* evaluate<R, Arg>(pageFunction: (node: T, arg: Arg) => R, arg: Arg, options?: { timeout?: number }): Promise<R>
* evaluate<R>(pageFunction: (node: T) => R, options?: { timeout?: number }): Promise<R>
* } & import("@playwright/test").Locator} Locator
*/