mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-02-03 23:55:04 +08:00
Inline attributes semantics and tests
This commit is contained in:
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@@ -2,7 +2,6 @@
|
||||
"files.trimFinalNewlines": true,
|
||||
"files.insertFinalNewline": true,
|
||||
"javascript.format.semicolons": "remove",
|
||||
"editor.formatOnSaveMode": "modificationsIfAvailable",
|
||||
"editor.rulers": [
|
||||
120
|
||||
],
|
||||
|
||||
@@ -1,26 +1,31 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
import ComplexEntity from "../fixtures/ComplexEntity"
|
||||
import Entity1 from "../fixtures/Entity1"
|
||||
import Entity2 from "../fixtures/Entity2"
|
||||
import entity2Value from "../fixtures/serializedEntity2.js"
|
||||
import Entity3 from "../fixtures/Entity3"
|
||||
import entity3Value from "../fixtures/serializedEntity3.js"
|
||||
import Entity4 from "../fixtures/Entity4.js"
|
||||
import entity4Value from "../fixtures/serializedEntity4.js"
|
||||
import Grammar from "../../js/serialization/Grammar.js"
|
||||
import initializeSerializerFactory from "../../js/serialization/initializeSerializerFactory.js"
|
||||
import Serializer from "../../js/serialization/Serializer.js"
|
||||
import SerializerFactory from "../../js/serialization/SerializerFactory.js"
|
||||
import SimpleEntity from "../fixtures/SimpleEntity"
|
||||
import SimpleObject from "../fixtures/SimpleObject"
|
||||
|
||||
describe("Entity initialization", () => {
|
||||
before(() => {
|
||||
expect(SimpleEntity).to.be.a("function")
|
||||
expect(ComplexEntity).to.be.a("function")
|
||||
expect(Entity2).to.be.a("function")
|
||||
expect(Entity3).to.be.a("function")
|
||||
})
|
||||
|
||||
context("SimpleEntity", () => {
|
||||
const entity = new SimpleEntity()
|
||||
context("Entity2", () => {
|
||||
const entity = new Entity2()
|
||||
before(() => {
|
||||
initializeSerializerFactory()
|
||||
SerializerFactory.registerSerializer(
|
||||
SimpleEntity,
|
||||
Entity2,
|
||||
new Serializer(
|
||||
SimpleEntity,
|
||||
Entity2,
|
||||
v => `{\n${v}\n}`,
|
||||
" ",
|
||||
"\n",
|
||||
@@ -29,8 +34,20 @@ describe("Entity initialization", () => {
|
||||
undefined
|
||||
)
|
||||
)
|
||||
SerializerFactory.registerSerializer(
|
||||
Entity1,
|
||||
new Serializer(
|
||||
Entity1,
|
||||
v => `Entity1(${v})`,
|
||||
"",
|
||||
", ",
|
||||
false,
|
||||
"=",
|
||||
undefined
|
||||
)
|
||||
)
|
||||
})
|
||||
it("has 7 keys", () => expect(Object.keys(entity).length).to.equal(7))
|
||||
it("has 8 keys", () => expect(Object.keys(entity).length).to.equal(8))
|
||||
it("has someNumber equal to 567", () => expect(entity)
|
||||
.to.have.property("someNumber")
|
||||
.which.is.a("number")
|
||||
@@ -66,16 +83,16 @@ describe("Entity initialization", () => {
|
||||
.which.is.an("array")
|
||||
.and.is.deep.equal([400, 500, 600, 700, 800])
|
||||
)
|
||||
it("is equal to another empty SimpleEntity", () => expect(entity.equals(new SimpleEntity()))
|
||||
.to.be.true
|
||||
it("is equal to another empty Entity2", () =>
|
||||
expect(entity.equals(new Entity2())).to.be.true
|
||||
)
|
||||
const other = new SimpleEntity({
|
||||
const other = new Entity2({
|
||||
someString2: "gamma"
|
||||
})
|
||||
it("is not equal to another empty SimpleEntity", () => expect(entity.equals(other))
|
||||
.to.be.false
|
||||
it("is not equal to another empty Entity2", () =>
|
||||
expect(entity.equals(other)).to.be.false
|
||||
)
|
||||
const other1 = new SimpleEntity({
|
||||
const other1 = new Entity2({
|
||||
someNumber: 123,
|
||||
someString: "a",
|
||||
someString2: "b",
|
||||
@@ -84,7 +101,7 @@ describe("Entity initialization", () => {
|
||||
someObjectString: new String("delta"),
|
||||
someArray: [-1, -2, -3],
|
||||
})
|
||||
const other2 = new SimpleEntity({
|
||||
const other2 = new Entity2({
|
||||
someNumber: 123,
|
||||
someString: "a",
|
||||
someString2: "b",
|
||||
@@ -93,26 +110,19 @@ describe("Entity initialization", () => {
|
||||
someObjectString: "delta",
|
||||
someArray: [-1, -2, -3],
|
||||
})
|
||||
it("compares equal entities as equal", () => expect(other1.equals(other2))
|
||||
.to.be.true
|
||||
it("compares equal entities as equal", () =>
|
||||
expect(other1.equals(other2)).to.be.true
|
||||
)
|
||||
it("can serialize", () =>
|
||||
expect(SerializerFactory.getSerializer(Entity2).write(entity)).to.equal(entity2Value)
|
||||
)
|
||||
it("has correct nested property", () =>
|
||||
expect(Grammar.getAttribute(Entity2, ["someEntity", "a"]).type).to.equal(Number)
|
||||
)
|
||||
it("can serialize", () => {
|
||||
expect(SerializerFactory.getSerializer(SimpleEntity).write(entity))
|
||||
.to.equal(`{
|
||||
someNumber: 567
|
||||
someString: "alpha"
|
||||
someString2: "beta"
|
||||
someBoolean: True
|
||||
someBoolean2: False
|
||||
someObjectString: "gamma"
|
||||
someArray: (400,500,600,700,800,)
|
||||
}`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
context("ComplexEntity", () => {
|
||||
const entity = new ComplexEntity()
|
||||
context("Entity3", () => {
|
||||
const entity = new Entity3()
|
||||
const keys = [
|
||||
"alpha",
|
||||
"bravo",
|
||||
@@ -132,13 +142,14 @@ describe("Entity initialization", () => {
|
||||
"papa",
|
||||
"quebec",
|
||||
"romeo",
|
||||
"sierra",
|
||||
]
|
||||
before(() => {
|
||||
initializeSerializerFactory()
|
||||
SerializerFactory.registerSerializer(
|
||||
ComplexEntity,
|
||||
Entity3,
|
||||
new Serializer(
|
||||
ComplexEntity,
|
||||
Entity3,
|
||||
v => `[[\n${v}\n]]`,
|
||||
" ",
|
||||
"\n",
|
||||
@@ -148,10 +159,10 @@ describe("Entity initialization", () => {
|
||||
)
|
||||
)
|
||||
SerializerFactory.registerSerializer(
|
||||
SimpleObject,
|
||||
Entity1,
|
||||
new Serializer(
|
||||
SimpleObject,
|
||||
v => `SimpleObject(${v})`,
|
||||
Entity1,
|
||||
v => `Entity1(${v})`,
|
||||
"",
|
||||
", ",
|
||||
false,
|
||||
@@ -229,14 +240,14 @@ describe("Entity initialization", () => {
|
||||
.which.is.a("number")
|
||||
.and.is.equal(0)
|
||||
)
|
||||
it("has oscar a SimpleObject", () => expect(entity)
|
||||
it("has oscar a Entity1", () => expect(entity)
|
||||
.to.have.property("oscar")
|
||||
.which.is.instanceOf(SimpleObject)
|
||||
.which.is.instanceOf(Entity1)
|
||||
.and.is.deep.equal({ a: 8, b: 9 })
|
||||
)
|
||||
it("has papa a SimpleObject", () => expect(entity)
|
||||
it("has papa a Entity1", () => expect(entity)
|
||||
.to.have.property("papa")
|
||||
.which.is.instanceOf(SimpleObject)
|
||||
.which.is.instanceOf(Entity1)
|
||||
.and.is.deep.equal({ a: 12, b: 13 })
|
||||
)
|
||||
it("has quebec undefined", () => expect(entity)
|
||||
@@ -244,7 +255,7 @@ describe("Entity initialization", () => {
|
||||
.which.is.undefined
|
||||
)
|
||||
it("quebec can be assigned and it always filtered", () => {
|
||||
const entity = new ComplexEntity()
|
||||
const entity = new Entity3()
|
||||
entity.quebec = 2
|
||||
expect(entity.quebec, "assigned 2").to.be.equal(2)
|
||||
entity["quebec"] = 7
|
||||
@@ -262,28 +273,40 @@ describe("Entity initialization", () => {
|
||||
entity.quebec = 6
|
||||
expect(entity.quebec, "assigned 6").to.be.equal(6)
|
||||
})
|
||||
it("can serialize", () => {
|
||||
expect(SerializerFactory.getSerializer(ComplexEntity).write(entity))
|
||||
.to.equal(`[[
|
||||
alpha: 32
|
||||
bravo: 78
|
||||
charlie: "Charlie"
|
||||
delta: ()
|
||||
echo: "echo"
|
||||
foxtrot: False
|
||||
golf: ()
|
||||
hotel: ()
|
||||
india: ()
|
||||
juliett: ("a","b","c","d","e",)
|
||||
kilo: (True,False,False,True,True,)
|
||||
mike: "Bar"
|
||||
november: 0
|
||||
oscar: SimpleObject(a=8, b=9)
|
||||
papa: SimpleObject(a=12, b=13)
|
||||
romeo.a: 8
|
||||
romeo.b: 9
|
||||
]]`
|
||||
)
|
||||
it("can serialize", () =>
|
||||
expect(SerializerFactory.getSerializer(Entity3).write(entity)).to.equal(entity3Value)
|
||||
)
|
||||
it("has correct nested property", () => {
|
||||
expect(Grammar.getAttribute(Entity3, ["romeo", "b"]).type).to.equal(Number)
|
||||
expect(Grammar.getAttribute(Entity3, ["sierra", "someString2"]).type).to.equal(String)
|
||||
expect(Grammar.getAttribute(Entity3, ["sierra", "someObjectString"]).type).to.equal(String)
|
||||
expect(Grammar.getAttribute(Entity3, ["sierra", "someObjectString"]).type).to.equal(String)
|
||||
expect(Grammar.getAttribute(Entity3, ["sierra", "someEntity", "b"]).type).to.equal(Number)
|
||||
})
|
||||
})
|
||||
|
||||
context("Entity4", () => {
|
||||
const entity = new Entity4()
|
||||
before(() => {
|
||||
initializeSerializerFactory()
|
||||
SerializerFactory.registerSerializer(
|
||||
Entity4,
|
||||
new Serializer(
|
||||
Entity4,
|
||||
v => `Begin\n${v}\nEnd`,
|
||||
" ",
|
||||
"\n",
|
||||
false,
|
||||
" => ",
|
||||
k => `\${${k}}`
|
||||
)
|
||||
)
|
||||
})
|
||||
it("has array of Entity1", () =>
|
||||
expect(Entity4.attributes.second.type).to.deep.equal([Entity1])
|
||||
)
|
||||
it("can serialize", () =>
|
||||
expect(SerializerFactory.getSerializer(Entity4).write(entity)).to.equal(entity4Value)
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import IEntity from "../../js/entity/IEntity.js"
|
||||
|
||||
export default class SimpleObject extends IEntity {
|
||||
export default class Entity1 extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
a: {
|
||||
@@ -1,6 +1,7 @@
|
||||
import Entity1 from "./Entity1.js"
|
||||
import IEntity from "../../js/entity/IEntity"
|
||||
|
||||
export default class SimpleEntity extends IEntity {
|
||||
export default class Entity2 extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
someNumber: {
|
||||
@@ -24,6 +25,9 @@ export default class SimpleEntity extends IEntity {
|
||||
someArray: {
|
||||
default: [400, 500, 600, 700, 800],
|
||||
},
|
||||
someEntity: {
|
||||
type: Entity1,
|
||||
},
|
||||
}
|
||||
|
||||
static {
|
||||
@@ -1,8 +1,9 @@
|
||||
import Entity1 from "./Entity1"
|
||||
import Entity2 from "./Entity2.js"
|
||||
import IEntity from "../../js/entity/IEntity"
|
||||
import SimpleObject from "./SimpleObject"
|
||||
import UnionType from "../../js/entity/UnionType"
|
||||
|
||||
export default class ComplexEntity extends IEntity {
|
||||
export default class Entity3 extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
alpha: {
|
||||
@@ -57,19 +58,23 @@ export default class ComplexEntity extends IEntity {
|
||||
type: new UnionType(Number, String, Array),
|
||||
},
|
||||
oscar: {
|
||||
type: SimpleObject,
|
||||
type: Entity1,
|
||||
},
|
||||
papa: {
|
||||
default: () => new SimpleObject({ a: 12, b: 13 }),
|
||||
default: () => new Entity1({ a: 12, b: 13 }),
|
||||
},
|
||||
quebec: {
|
||||
default: 0, // will assign undefined because it does not satisfy the predicate
|
||||
predicate: v => v >= 1 && v <= 10,
|
||||
},
|
||||
romeo: {
|
||||
type: SimpleObject,
|
||||
type: Entity1,
|
||||
inlined: true,
|
||||
},
|
||||
sierra: {
|
||||
type: Entity2,
|
||||
inlined: true,
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
29
cypress/fixtures/Entity4.js
Normal file
29
cypress/fixtures/Entity4.js
Normal file
@@ -0,0 +1,29 @@
|
||||
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: {
|
||||
type: Entity3,
|
||||
inlined: true,
|
||||
},
|
||||
second: {
|
||||
default: [new Entity1({ a: 1, b: 2 }), new Entity1({ a: 11, b: 22 })],
|
||||
inlined: true,
|
||||
},
|
||||
third: {
|
||||
type: [{
|
||||
type: Entity1,
|
||||
inlined: true,
|
||||
}],
|
||||
default: [new Entity1({ a: -1, b: -2 })],
|
||||
inlined: true,
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
this.cleanupAttributes(this.attributes)
|
||||
}
|
||||
}
|
||||
10
cypress/fixtures/serializedEntity2.js
Normal file
10
cypress/fixtures/serializedEntity2.js
Normal file
@@ -0,0 +1,10 @@
|
||||
export default `{
|
||||
someNumber: 567
|
||||
someString: "alpha"
|
||||
someString2: "beta"
|
||||
someBoolean: True
|
||||
someBoolean2: False
|
||||
someObjectString: "gamma"
|
||||
someArray: (400,500,600,700,800,)
|
||||
someEntity: Entity1(a=8, b=9)
|
||||
}`
|
||||
27
cypress/fixtures/serializedEntity3.js
Normal file
27
cypress/fixtures/serializedEntity3.js
Normal file
@@ -0,0 +1,27 @@
|
||||
export default `[[
|
||||
alpha: 32
|
||||
bravo: 78
|
||||
charlie: "Charlie"
|
||||
delta: ()
|
||||
echo: "echo"
|
||||
foxtrot: False
|
||||
golf: ()
|
||||
hotel: ()
|
||||
india: ()
|
||||
juliett: ("a","b","c","d","e",)
|
||||
kilo: (True,False,False,True,True,)
|
||||
mike: "Bar"
|
||||
november: 0
|
||||
oscar: Entity1(a=8, b=9)
|
||||
papa: Entity1(a=12, b=13)
|
||||
romeo.a: 8
|
||||
romeo.b: 9
|
||||
sierra.someNumber: 567
|
||||
sierra.someString: "alpha"
|
||||
sierra.someString2: "beta"
|
||||
sierra.someBoolean: True
|
||||
sierra.someBoolean2: False
|
||||
sierra.someObjectString: "gamma"
|
||||
sierra.someArray: (400,500,600,700,800,)
|
||||
sierra.someEntity: Entity1(a=8, b=9)
|
||||
]]`
|
||||
27
cypress/fixtures/serializedEntity4.js
Normal file
27
cypress/fixtures/serializedEntity4.js
Normal file
@@ -0,0 +1,27 @@
|
||||
export default `[[
|
||||
alpha: 32
|
||||
bravo: 78
|
||||
charlie: "Charlie"
|
||||
delta: ()
|
||||
echo: "echo"
|
||||
foxtrot: False
|
||||
golf: ()
|
||||
hotel: ()
|
||||
india: ()
|
||||
juliett: ("a","b","c","d","e",)
|
||||
kilo: (True,False,False,True,True,)
|
||||
mike: "Bar"
|
||||
november: 0
|
||||
oscar: Entity1(a=8, b=9)
|
||||
papa: Entity1(a=12, b=13)
|
||||
romeo.a: 8
|
||||
romeo.b: 9
|
||||
sierra.someNumber: 567
|
||||
sierra.someString: "alpha"
|
||||
sierra.someString2: "beta"
|
||||
sierra.someBoolean: True
|
||||
sierra.someBoolean2: False
|
||||
sierra.someObjectString: "gamma"
|
||||
sierra.someArray: (400,500,600,700,800,)
|
||||
sierra.someEntity: Entity1(a=8, b=9)
|
||||
]]`
|
||||
379
dist/ueblueprint.js
vendored
379
dist/ueblueprint.js
vendored
@@ -71,7 +71,7 @@ class Configuration {
|
||||
static gridShrinkThreshold = 4 // exceding size factor threshold to cause a shrink event
|
||||
static gridSize = 16 // px
|
||||
static hexColorRegex = /^\s*#(?<r>[0-9a-fA-F]{2})(?<g>[0-9a-fA-F]{2})(?<b>[0-9a-fA-F]{2})([0-9a-fA-F]{2})?|#(?<rs>[0-9a-fA-F])(?<gs>[0-9a-fA-F])(?<bs>[0-9a-fA-F])\s*$/
|
||||
static keysSeparator = "+"
|
||||
static keysSeparator = /[\.\(\)]/
|
||||
static knotOffset = [-26, -16]
|
||||
static linkCurveHeight = 15 // px
|
||||
static linkCurveWidth = 80 // px
|
||||
@@ -419,7 +419,7 @@ class SerializerFactory {
|
||||
|
||||
/**
|
||||
* @template {AnyValue} T
|
||||
* @param {new () => T} entity
|
||||
* @param {new (...any) => T} entity
|
||||
* @returns {Serializer<T>}
|
||||
*/
|
||||
static getSerializer(entity) {
|
||||
@@ -881,13 +881,9 @@ class Utility {
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {(entity: IEntity) => AnyValue} ValueSupplier
|
||||
* @typedef {IEntity | String | Number | BigInt | Boolean} AnySimpleValue
|
||||
* @typedef {AnySimpleValue | AnySimpleValue[]} AnyValue
|
||||
* @typedef {{
|
||||
* [key: String]: AttributeInformation
|
||||
* }} AttributeDeclarations
|
||||
* @typedef {typeof IEntity} EntityConstructor
|
||||
* @typedef {(entity: IEntity) => AnyValue} ValueSupplier
|
||||
* @typedef {{
|
||||
* type?: AnyValueConstructor<AnyValue> | AnyValueConstructor<AnyValue>[] | UnionType | ComputedType,
|
||||
* default?: AnyValue | ValueSupplier,
|
||||
@@ -899,6 +895,10 @@ class Utility {
|
||||
* inlined?: Boolean,
|
||||
* predicate?: (value: AnyValue) => Boolean,
|
||||
* }} AttributeInformation
|
||||
* @typedef {{
|
||||
* [key: String]: AttributeInformation
|
||||
* }} AttributeDeclarations
|
||||
* @typedef {typeof IEntity} EntityConstructor
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -922,7 +922,8 @@ class IEntity {
|
||||
}
|
||||
|
||||
constructor(values = {}, suppressWarns = false) {
|
||||
const attributes = /** @type {typeof IEntity} */(this.constructor).attributes;
|
||||
const Self = /** @type {EntityConstructor} */(this.constructor);
|
||||
const attributes = Self.attributes;
|
||||
if (values.constructor !== Object && Object.keys(attributes).length === 1) {
|
||||
// Where there is just one attribute, option can be the value of that attribute
|
||||
values = {
|
||||
@@ -934,14 +935,14 @@ class IEntity {
|
||||
const allAttributesNames = Utility.mergeArrays(attributesNames, valuesNames);
|
||||
for (let attributeName of allAttributesNames) {
|
||||
let value = values[attributeName];
|
||||
let attribute = /** @type {AttributeInformation} */(attributes[attributeName]);
|
||||
let attribute = attributes[attributeName];
|
||||
|
||||
if (!suppressWarns) {
|
||||
if (!(attributeName in attributes)) {
|
||||
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 `
|
||||
+ `${this.constructor.name}.attributes`
|
||||
`UEBlueprint: Attribute ${attributeName} (of type ${typeName}) in the serialized data is not `
|
||||
+ `defined in ${Self.name}.attributes`
|
||||
);
|
||||
} else if (
|
||||
valuesNames.length > 0
|
||||
@@ -949,8 +950,7 @@ class IEntity {
|
||||
&& !(!attribute.showDefault || attribute.ignored)
|
||||
) {
|
||||
console.warn(
|
||||
`UEBlueprint: ${this.constructor.name} will add attribute ${attributeName} not `
|
||||
+ "defined in the serialized data"
|
||||
`UEBlueprint: ${Self.name} will add attribute ${attributeName} missing from the serialized data`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -992,8 +992,8 @@ class IEntity {
|
||||
set(v) {
|
||||
if (!attribute.predicate?.(v)) {
|
||||
console.warn(
|
||||
`UEBlueprint: Tried to assign attribute ${attributeName} to `
|
||||
+ `${this.constructor.name} not satisfying the predicate`
|
||||
`UEBlueprint: Tried to assign attribute ${attributeName} to`
|
||||
+ `${Self.name} not satisfying the predicate`
|
||||
);
|
||||
return
|
||||
}
|
||||
@@ -1049,7 +1049,9 @@ class IEntity {
|
||||
for (const attributeName in attributes) {
|
||||
const attribute = /** @type {AttributeInformation} */(attributes[attributeName]);
|
||||
if (attribute.type === undefined && !(attribute.default instanceof Function)) {
|
||||
attribute.type = Utility.getType(attribute.default);
|
||||
attribute.type = attribute.default instanceof Array
|
||||
? [Utility.getType(attribute.default[0])]
|
||||
: Utility.getType(attribute.default);
|
||||
}
|
||||
attributes[attributeName] = {
|
||||
...IEntity.defaultAttribute,
|
||||
@@ -1381,24 +1383,6 @@ class IdentifierEntity extends IEntity {
|
||||
}
|
||||
}
|
||||
|
||||
/** @typedef {import("./IEntity").AnyValueConstructor<*>} AnyValueConstructor */
|
||||
|
||||
class IndexedArray {
|
||||
|
||||
#type
|
||||
get type() {
|
||||
return this.#type
|
||||
}
|
||||
|
||||
value = []
|
||||
|
||||
/** @param {AnyValueConstructor} type */
|
||||
constructor(type, value = []) {
|
||||
this.#type = type;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
class Integer64Entity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
@@ -1821,6 +1805,81 @@ class PinReferenceEntity extends IEntity {
|
||||
}
|
||||
}
|
||||
|
||||
class PinTypeEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
PinCategory: {
|
||||
default: "",
|
||||
},
|
||||
PinSubCategory: {
|
||||
default: "",
|
||||
},
|
||||
PinSubCategoryObject: {
|
||||
type: ObjectReferenceEntity,
|
||||
},
|
||||
PinSubCategoryMemberReference: {
|
||||
type: FunctionReferenceEntity,
|
||||
default: null,
|
||||
},
|
||||
PinValueType: {
|
||||
type: PinTypeEntity,
|
||||
default: null,
|
||||
},
|
||||
ContainerType: {
|
||||
type: PathSymbolEntity,
|
||||
},
|
||||
bIsReference: {
|
||||
default: false,
|
||||
},
|
||||
bIsConst: {
|
||||
default: false,
|
||||
},
|
||||
bIsWeakPointer: {
|
||||
default: false,
|
||||
},
|
||||
bIsUObjectWrapper: {
|
||||
default: false,
|
||||
},
|
||||
bSerializeAsSinglePrecisionFloat: {
|
||||
default: false,
|
||||
},
|
||||
}
|
||||
|
||||
static {
|
||||
this.cleanupAttributes(this.attributes);
|
||||
}
|
||||
|
||||
constructor(values = {}, suppressWarns = false) {
|
||||
super(values, suppressWarns);
|
||||
/** @type {String} */ this.PinCategory;
|
||||
/** @type {String} */ this.PinSubCategory;
|
||||
/** @type {ObjectReferenceEntity} */ this.PinSubCategoryObject;
|
||||
/** @type {FunctionReferenceEntity} */ this.PinSubCategoryMemberReference;
|
||||
/** @type {PinTypeEntity} */ this.PinValueType;
|
||||
/** @type {PathSymbolEntity} */ this.ContainerType;
|
||||
/** @type {Boolean} */ this.bIsReference;
|
||||
/** @type {Boolean} */ this.bIsConst;
|
||||
/** @type {Boolean} */ this.bIsWeakPointer;
|
||||
/** @type {Boolean} */ this.bIsUObjectWrapper;
|
||||
/** @type {Boolean} */ this.bIsUObjectWrapper;
|
||||
}
|
||||
|
||||
/** @param {PinTypeEntity} other */
|
||||
copyTypeFrom(other) {
|
||||
this.PinCategory = other.PinCategory;
|
||||
this.PinSubCategory = other.PinSubCategory;
|
||||
this.PinSubCategoryObject = other.PinSubCategoryObject;
|
||||
this.PinSubCategoryMemberReference = other.PinSubCategoryMemberReference;
|
||||
this.PinValueType = other.PinValueType;
|
||||
this.ContainerType = other.ContainerType;
|
||||
this.bIsReference = other.bIsReference;
|
||||
this.bIsConst = other.bIsConst;
|
||||
this.bIsWeakPointer = other.bIsWeakPointer;
|
||||
this.bIsUObjectWrapper = other.bIsUObjectWrapper;
|
||||
this.bSerializeAsSinglePrecisionFloat = other.bSerializeAsSinglePrecisionFloat;
|
||||
}
|
||||
}
|
||||
|
||||
class RotatorEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
@@ -1921,45 +1980,6 @@ class VectorEntity extends IEntity {
|
||||
class SimpleSerializationVectorEntity extends VectorEntity {
|
||||
}
|
||||
|
||||
class TerminalTypeEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
TerminalCategory: {
|
||||
default: "",
|
||||
showDefault: false,
|
||||
},
|
||||
TerminalSubCategory: {
|
||||
default: "",
|
||||
showDefault: false,
|
||||
},
|
||||
bTerminalIsConst: {
|
||||
default: false,
|
||||
showDefault: false,
|
||||
},
|
||||
bTerminalIsWeakPointer: {
|
||||
default: false,
|
||||
showDefault: false,
|
||||
},
|
||||
bTerminalIsUObjectWrapper: {
|
||||
default: false,
|
||||
showDefault: false,
|
||||
},
|
||||
}
|
||||
|
||||
static {
|
||||
this.cleanupAttributes(this.attributes);
|
||||
}
|
||||
|
||||
constructor(values) {
|
||||
super(values);
|
||||
/** @type {String} */ this.TerminalCategory;
|
||||
/** @type {String} */ this.TerminalSubCategory;
|
||||
/** @type {Boolean} */ this.bTerminalIsConst;
|
||||
/** @type {Boolean} */ this.bTerminalIsWeakPointer;
|
||||
/** @type {Boolean} */ this.bTerminalIsUObjectWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {import("./IEntity").AnyValue} AnyValue
|
||||
* @typedef {import("lit").CSSResult} CSSResult
|
||||
@@ -2008,40 +2028,9 @@ class PinEntity extends IEntity {
|
||||
type: String,
|
||||
showDefault: false,
|
||||
},
|
||||
PinType$PinCategory: {
|
||||
default: "",
|
||||
},
|
||||
PinType$PinSubCategory: {
|
||||
default: "",
|
||||
},
|
||||
PinType$PinSubCategoryObject: {
|
||||
type: ObjectReferenceEntity,
|
||||
},
|
||||
PinType$PinSubCategoryMemberReference: {
|
||||
type: FunctionReferenceEntity,
|
||||
default: null,
|
||||
},
|
||||
PinType$PinValueType: {
|
||||
type: TerminalTypeEntity,
|
||||
default: null,
|
||||
},
|
||||
PinType$ContainerType: {
|
||||
type: PathSymbolEntity,
|
||||
},
|
||||
PinType$bIsReference: {
|
||||
default: false,
|
||||
},
|
||||
PinType$bIsConst: {
|
||||
default: false,
|
||||
},
|
||||
PinType$bIsWeakPointer: {
|
||||
default: false,
|
||||
},
|
||||
PinType$bIsUObjectWrapper: {
|
||||
default: false,
|
||||
},
|
||||
PinType$bSerializeAsSinglePrecisionFloat: {
|
||||
default: false,
|
||||
PinType: {
|
||||
type: PinTypeEntity,
|
||||
inlined: true,
|
||||
},
|
||||
LinkedTo: {
|
||||
type: [PinReferenceEntity],
|
||||
@@ -2104,17 +2093,7 @@ class PinEntity extends IEntity {
|
||||
/** @type {LocalizedTextEntity | String} */ this.PinFriendlyName;
|
||||
/** @type {String} */ this.PinToolTip;
|
||||
/** @type {String} */ this.Direction;
|
||||
/** @type {String} */ this.PinType$PinCategory;
|
||||
/** @type {String} */ this.PinType$PinSubCategory;
|
||||
/** @type {ObjectReferenceEntity} */ this.PinType$PinSubCategoryObject;
|
||||
/** @type {FunctionReferenceEntity} */ this.PinType$PinSubCategoryMemberReference;
|
||||
/** @type {TerminalTypeEntity} */ this.PinType$PinValueType;
|
||||
/** @type {PathSymbolEntity} */ this.PinType$ContainerType;
|
||||
/** @type {Boolean} */ this.PinType$bIsReference;
|
||||
/** @type {Boolean} */ this.PinType$bIsConst;
|
||||
/** @type {Boolean} */ this.PinType$bIsWeakPointer;
|
||||
/** @type {Boolean} */ this.PinType$bIsUObjectWrapper;
|
||||
/** @type {Boolean} */ this.PinType$bIsUObjectWrapper;
|
||||
/** @type {PinTypeEntity} */ this.PinType;
|
||||
/** @type {PinReferenceEntity[]} */ this.LinkedTo;
|
||||
/** @type {T} */ this.DefaultValue;
|
||||
/** @type {String} */ this.AutogeneratedDefaultValue;
|
||||
@@ -2129,12 +2108,12 @@ class PinEntity extends IEntity {
|
||||
}
|
||||
|
||||
getType() {
|
||||
const subCategory = this.PinType$PinSubCategoryObject;
|
||||
if (this.PinType$PinCategory === "struct" || this.PinType$PinCategory === "object") {
|
||||
const subCategory = this.PinType.PinSubCategoryObject;
|
||||
if (this.PinType.PinCategory === "struct" || this.PinType.PinCategory === "object") {
|
||||
return subCategory.path
|
||||
}
|
||||
if (
|
||||
this.PinType$PinCategory === "byte"
|
||||
this.PinType.PinCategory === "byte"
|
||||
&& (
|
||||
subCategory.type === Configuration.nodeType.enum
|
||||
|| subCategory.type === Configuration.nodeType.userDefinedEnum
|
||||
@@ -2142,7 +2121,7 @@ class PinEntity extends IEntity {
|
||||
) {
|
||||
return "enum"
|
||||
}
|
||||
return this.PinType$PinCategory
|
||||
return this.PinType.PinCategory
|
||||
}
|
||||
|
||||
getEntityType(alternative = false) {
|
||||
@@ -2171,16 +2150,16 @@ class PinEntity extends IEntity {
|
||||
|
||||
/** @param {PinEntity} other */
|
||||
copyTypeFrom(other) {
|
||||
this.PinType$PinCategory = other.PinType$PinCategory;
|
||||
this.PinType$PinSubCategory = other.PinType$PinSubCategory;
|
||||
this.PinType$PinSubCategoryObject = other.PinType$PinSubCategoryObject;
|
||||
this.PinType$PinSubCategoryMemberReference = other.PinType$PinSubCategoryMemberReference;
|
||||
this.PinType$PinValueType = other.PinType$PinValueType;
|
||||
this.PinType$ContainerType = other.PinType$ContainerType;
|
||||
this.PinType$bIsReference = other.PinType$bIsReference;
|
||||
this.PinType$bIsConst = other.PinType$bIsConst;
|
||||
this.PinType$bIsWeakPointer = other.PinType$bIsWeakPointer;
|
||||
this.PinType$bIsUObjectWrapper = other.PinType$bIsUObjectWrapper;
|
||||
this.PinType.PinCategory = other.PinType.PinCategory;
|
||||
this.PinType.PinSubCategory = other.PinType.PinSubCategory;
|
||||
this.PinType.PinSubCategoryObject = other.PinType.PinSubCategoryObject;
|
||||
this.PinType.PinSubCategoryMemberReference = other.PinType.PinSubCategoryMemberReference;
|
||||
this.PinType.PinValueType = other.PinType.PinValueType;
|
||||
this.PinType.ContainerType = other.PinType.ContainerType;
|
||||
this.PinType.bIsReference = other.PinType.bIsReference;
|
||||
this.PinType.bIsConst = other.PinType.bIsConst;
|
||||
this.PinType.bIsWeakPointer = other.PinType.bIsWeakPointer;
|
||||
this.PinType.bIsUObjectWrapper = other.PinType.bIsUObjectWrapper;
|
||||
this.PinType$bSerializeAsSinglePrecisionFloat = other.PinType$bSerializeAsSinglePrecisionFloat;
|
||||
}
|
||||
|
||||
@@ -2192,7 +2171,7 @@ class PinEntity extends IEntity {
|
||||
}
|
||||
|
||||
isExecution() {
|
||||
return this.PinType$PinCategory === "exec"
|
||||
return this.PinType.PinCategory === "exec"
|
||||
}
|
||||
|
||||
isHidden() {
|
||||
@@ -2250,13 +2229,13 @@ class PinEntity extends IEntity {
|
||||
}
|
||||
|
||||
getSubCategory() {
|
||||
return this.PinType$PinSubCategoryObject.path
|
||||
return this.PinType.PinSubCategoryObject.path
|
||||
}
|
||||
|
||||
/** @return {CSSResult} */
|
||||
pinColor() {
|
||||
return Configuration.pinColor[this.getType()]
|
||||
?? Configuration.pinColor[this.PinType$PinCategory.toLowerCase()]
|
||||
?? Configuration.pinColor[this.PinType.PinCategory.toLowerCase()]
|
||||
?? Configuration.pinColor["default"]
|
||||
}
|
||||
}
|
||||
@@ -3017,7 +2996,7 @@ class ObjectEntity extends IEntity {
|
||||
}
|
||||
|
||||
getDelegatePin() {
|
||||
return this.CustomProperties?.find(pin => pin.PinType$PinCategory === "delegate")
|
||||
return this.CustomProperties?.find(pin => pin.PinType.PinCategory === "delegate")
|
||||
}
|
||||
|
||||
nodeDisplayName() {
|
||||
@@ -3238,6 +3217,45 @@ var parsimmon_umd_min = {exports: {}};
|
||||
|
||||
var Parsimmon = /*@__PURE__*/getDefaultExportFromCjs(parsimmon_umd_min.exports);
|
||||
|
||||
class TerminalTypeEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
TerminalCategory: {
|
||||
default: "",
|
||||
showDefault: false,
|
||||
},
|
||||
TerminalSubCategory: {
|
||||
default: "",
|
||||
showDefault: false,
|
||||
},
|
||||
bTerminalIsConst: {
|
||||
default: false,
|
||||
showDefault: false,
|
||||
},
|
||||
bTerminalIsWeakPointer: {
|
||||
default: false,
|
||||
showDefault: false,
|
||||
},
|
||||
bTerminalIsUObjectWrapper: {
|
||||
default: false,
|
||||
showDefault: false,
|
||||
},
|
||||
}
|
||||
|
||||
static {
|
||||
this.cleanupAttributes(this.attributes);
|
||||
}
|
||||
|
||||
constructor(values) {
|
||||
super(values);
|
||||
/** @type {String} */ this.TerminalCategory;
|
||||
/** @type {String} */ this.TerminalSubCategory;
|
||||
/** @type {Boolean} */ this.bTerminalIsConst;
|
||||
/** @type {Boolean} */ this.bTerminalIsWeakPointer;
|
||||
/** @type {Boolean} */ this.bTerminalIsUObjectWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
class UnknownKeysEntity extends IEntity {
|
||||
|
||||
static attributes = {
|
||||
@@ -3497,16 +3515,44 @@ class Grammar {
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EntityConstructor} entityType
|
||||
* @param {String[]} key
|
||||
* @returns {AttributeInformation}
|
||||
*/
|
||||
static getAttribute(entityType, key) {
|
||||
let result;
|
||||
let type;
|
||||
if (entityType instanceof UnionType) {
|
||||
for (let t of entityType.types) {
|
||||
if (result = this.getAttribute(t, key)) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
if (entityType instanceof IEntity.constructor) {
|
||||
result = entityType.attributes[key[0]];
|
||||
type = result?.type;
|
||||
} else if (entityType instanceof Array) {
|
||||
result = entityType[key[0]];
|
||||
type = result;
|
||||
}
|
||||
if (key.length > 1) {
|
||||
return this.getAttribute(type, key.slice(1))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
static createAttributeGrammar(entityType, valueSeparator = this.equalSeparation) {
|
||||
return P.seq(
|
||||
this.attributeName,
|
||||
valueSeparator,
|
||||
).chain(([attributeName, _1]) => {
|
||||
attributeName = Utility.encodeKeyName(attributeName);
|
||||
const attributeKey = attributeName.split(Configuration.keysSeparator);
|
||||
return this
|
||||
.grammarFor(entityType.attributes[attributeName], undefined)
|
||||
.grammarFor(this.getAttribute(entityType, attributeKey))
|
||||
.map(attributeValue =>
|
||||
values => values[attributeName] = attributeValue
|
||||
values => Utility.objectSet(values, attributeKey, attributeValue, true)
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -3787,7 +3833,7 @@ class Grammar {
|
||||
})
|
||||
)
|
||||
|
||||
static indexedArrayEntry = P.lazy(() => {
|
||||
static inlinedArrayEntry = P.lazy(() => {
|
||||
return P.seq(
|
||||
this.symbol,
|
||||
this.regexMap(
|
||||
@@ -3798,8 +3844,7 @@ class Grammar {
|
||||
.chain(([symbol, _1]) =>
|
||||
this.grammarFor(ObjectEntity.attributes[symbol])
|
||||
.map(currentValue =>
|
||||
values => (values[symbol] ??= new IndexedArray(currentValue.constructor))
|
||||
.value.push(currentValue)
|
||||
values => (values[symbol] ??= []).push(currentValue)
|
||||
)
|
||||
)
|
||||
})
|
||||
@@ -3812,7 +3857,7 @@ class Grammar {
|
||||
P.alt(
|
||||
this.customProperty,
|
||||
this.createAttributeGrammar(ObjectEntity),
|
||||
this.indexedArrayEntry
|
||||
this.inlinedArrayEntry
|
||||
)
|
||||
)
|
||||
.map(([_0, entry]) => entry)
|
||||
@@ -3929,13 +3974,13 @@ class Serializer {
|
||||
|
||||
/** @type {(v: String, entityType: AnyValueConstructor) => String} */
|
||||
static bracketsWrapped = ((v, entityType) => `(${v})`)
|
||||
/** @type {(v: String, entityType: AnyValueConstructor) => String} */
|
||||
static notWrapped = ((v, entityType) => v)
|
||||
/** @type {(v: String) => String} */
|
||||
static same = (v => v)
|
||||
|
||||
/** @param {AnyValueConstructor} entityType */
|
||||
constructor(
|
||||
entityType,
|
||||
wrap = Serializer.bracketsWrapped,
|
||||
wrap = Serializer.same,
|
||||
attributePrefix = "",
|
||||
attributeSeparator = ",",
|
||||
trailingSeparator = false,
|
||||
@@ -4000,40 +4045,34 @@ class Serializer {
|
||||
Object.keys(attributes),
|
||||
Object.keys(entity)
|
||||
);
|
||||
let first = true;
|
||||
for (const key of keys) {
|
||||
const value = entity[key];
|
||||
if (value !== undefined && this.showProperty(entity, key)) {
|
||||
const isSerialized = Utility.isSerialized(entity, key);
|
||||
result += (result.length ? attributeSeparator : "");
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
result += attributeSeparator;
|
||||
}
|
||||
if (attributes[key]?.inlined) {
|
||||
result += this.doWrite(
|
||||
value,
|
||||
insideString,
|
||||
Serializer.notWrapped,
|
||||
`${attributePrefix}${key}.`,
|
||||
attributeSeparator,
|
||||
trailingSeparator,
|
||||
attributeValueConjunctionSign,
|
||||
attributeKeyPrinter
|
||||
);
|
||||
continue
|
||||
}
|
||||
if (value instanceof IndexedArray) {
|
||||
result += this.doWrite(
|
||||
value,
|
||||
insideString,
|
||||
wrap,
|
||||
Serializer.same,
|
||||
attributePrefix,
|
||||
attributeSeparator,
|
||||
trailingSeparator,
|
||||
false,
|
||||
attributeValueConjunctionSign,
|
||||
index => `(${index})`
|
||||
attributes[key].type instanceof Array
|
||||
? k => attributeKeyPrinter(`${key}(${k})`)
|
||||
: k => attributeKeyPrinter(`${key}.${k}`),
|
||||
);
|
||||
continue
|
||||
}
|
||||
result +=
|
||||
attributePrefix
|
||||
+ Utility.decodeKeyName(this.attributeKeyPrinter(key))
|
||||
+ attributeKeyPrinter(key)
|
||||
+ this.attributeValueConjunctionSign
|
||||
+ (
|
||||
isSerialized
|
||||
@@ -4042,7 +4081,7 @@ class Serializer {
|
||||
);
|
||||
}
|
||||
}
|
||||
if (this.trailingSeparator && result.length) {
|
||||
if (trailingSeparator && result.length) {
|
||||
// append separator at the end if asked and there was printed content
|
||||
result += this.attributeSeparator;
|
||||
}
|
||||
@@ -7078,12 +7117,12 @@ class PinTemplate extends ITemplate {
|
||||
}
|
||||
|
||||
renderIcon() {
|
||||
switch (this.element.entity.PinType$ContainerType.toString()) {
|
||||
switch (this.element.entity.PinType.ContainerType.toString()) {
|
||||
case "Array": return SVGIcon.array
|
||||
case "Set": return SVGIcon.set
|
||||
case "Map": return SVGIcon.map
|
||||
}
|
||||
if (this.element.entity.PinType$PinCategory.toLocaleLowerCase() === "delegate") {
|
||||
if (this.element.entity.PinType.PinCategory.toLocaleLowerCase() === "delegate") {
|
||||
return SVGIcon.delegate
|
||||
}
|
||||
return SVGIcon.genericPin
|
||||
@@ -7191,7 +7230,7 @@ class EventNodeTemplate extends NodeTemplate {
|
||||
|
||||
createDelegatePinElement() {
|
||||
const pin = /** @type {PinElementConstructor} */(ElementFactory.getConstructor("ueb-pin")).newObject(
|
||||
this.element.getPinEntities().find(v => !v.isHidden() && v.PinType$PinCategory === "delegate"),
|
||||
this.element.getPinEntities().find(v => !v.isHidden() && v.PinType.PinCategory === "delegate"),
|
||||
new MinimalPinTemplate(),
|
||||
this.element
|
||||
);
|
||||
@@ -7201,7 +7240,7 @@ class EventNodeTemplate extends NodeTemplate {
|
||||
|
||||
createPinElements() {
|
||||
return this.element.getPinEntities()
|
||||
.filter(v => !v.isHidden() && v.PinType$PinCategory !== "delegate")
|
||||
.filter(v => !v.isHidden() && v.PinType.PinCategory !== "delegate")
|
||||
.map(pinEntity => /** @type {PinElementConstructor} */(ElementFactory.getConstructor("ueb-pin"))
|
||||
.newObject(pinEntity, undefined, this.element)
|
||||
)
|
||||
@@ -9456,7 +9495,7 @@ class PinElement extends IElement {
|
||||
* @return {new () => PinTemplate}
|
||||
*/
|
||||
static getTypeTemplate(pinEntity) {
|
||||
if (pinEntity.PinType$bIsReference && !pinEntity.PinType$bIsConst) {
|
||||
if (pinEntity.PinType.bIsReference && !pinEntity.PinType.bIsConst) {
|
||||
return PinElement.#inputPinTemplates["MUTABLE_REFERENCE"]
|
||||
}
|
||||
if (pinEntity.getType() === "exec") {
|
||||
|
||||
6
dist/ueblueprint.min.js
vendored
6
dist/ueblueprint.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -47,7 +47,7 @@ export default class Configuration {
|
||||
static gridShrinkThreshold = 4 // exceding size factor threshold to cause a shrink event
|
||||
static gridSize = 16 // px
|
||||
static hexColorRegex = /^\s*#(?<r>[0-9a-fA-F]{2})(?<g>[0-9a-fA-F]{2})(?<b>[0-9a-fA-F]{2})([0-9a-fA-F]{2})?|#(?<rs>[0-9a-fA-F])(?<gs>[0-9a-fA-F])(?<bs>[0-9a-fA-F])\s*$/
|
||||
static keysSeparator = "+"
|
||||
static keysSeparator = /[\.\(\)]/
|
||||
static knotOffset = [-26, -16]
|
||||
static linkCurveHeight = 15 // px
|
||||
static linkCurveWidth = 80 // px
|
||||
|
||||
@@ -111,7 +111,7 @@ export default class PinElement extends IElement {
|
||||
* @return {new () => PinTemplate}
|
||||
*/
|
||||
static getTypeTemplate(pinEntity) {
|
||||
if (pinEntity.PinType$bIsReference && !pinEntity.PinType$bIsConst) {
|
||||
if (pinEntity.PinType.bIsReference && !pinEntity.PinType.bIsConst) {
|
||||
return PinElement.#inputPinTemplates["MUTABLE_REFERENCE"]
|
||||
}
|
||||
if (pinEntity.getType() === "exec") {
|
||||
|
||||
@@ -4,13 +4,9 @@ import UnionType from "./UnionType.js"
|
||||
import Utility from "../Utility.js"
|
||||
|
||||
/**
|
||||
* @typedef {(entity: IEntity) => AnyValue} ValueSupplier
|
||||
* @typedef {IEntity | String | Number | BigInt | Boolean} AnySimpleValue
|
||||
* @typedef {AnySimpleValue | AnySimpleValue[]} AnyValue
|
||||
* @typedef {{
|
||||
* [key: String]: AttributeInformation
|
||||
* }} AttributeDeclarations
|
||||
* @typedef {typeof IEntity} EntityConstructor
|
||||
* @typedef {(entity: IEntity) => AnyValue} ValueSupplier
|
||||
* @typedef {{
|
||||
* type?: AnyValueConstructor<AnyValue> | AnyValueConstructor<AnyValue>[] | UnionType | ComputedType,
|
||||
* default?: AnyValue | ValueSupplier,
|
||||
@@ -22,6 +18,10 @@ import Utility from "../Utility.js"
|
||||
* inlined?: Boolean,
|
||||
* predicate?: (value: AnyValue) => Boolean,
|
||||
* }} AttributeInformation
|
||||
* @typedef {{
|
||||
* [key: String]: AttributeInformation
|
||||
* }} AttributeDeclarations
|
||||
* @typedef {typeof IEntity} EntityConstructor
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -45,7 +45,8 @@ export default class IEntity {
|
||||
}
|
||||
|
||||
constructor(values = {}, suppressWarns = false) {
|
||||
const attributes = /** @type {typeof IEntity} */(this.constructor).attributes
|
||||
const Self = /** @type {EntityConstructor} */(this.constructor)
|
||||
const attributes = Self.attributes
|
||||
if (values.constructor !== Object && Object.keys(attributes).length === 1) {
|
||||
// Where there is just one attribute, option can be the value of that attribute
|
||||
values = {
|
||||
@@ -57,14 +58,14 @@ export default class IEntity {
|
||||
const allAttributesNames = Utility.mergeArrays(attributesNames, valuesNames)
|
||||
for (let attributeName of allAttributesNames) {
|
||||
let value = values[attributeName]
|
||||
let attribute = /** @type {AttributeInformation} */(attributes[attributeName])
|
||||
let attribute = attributes[attributeName]
|
||||
|
||||
if (!suppressWarns) {
|
||||
if (!(attributeName in attributes)) {
|
||||
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 `
|
||||
+ `${this.constructor.name}.attributes`
|
||||
`UEBlueprint: Attribute ${attributeName} (of type ${typeName}) in the serialized data is not `
|
||||
+ `defined in ${Self.name}.attributes`
|
||||
)
|
||||
} else if (
|
||||
valuesNames.length > 0
|
||||
@@ -72,8 +73,7 @@ export default class IEntity {
|
||||
&& !(!attribute.showDefault || attribute.ignored)
|
||||
) {
|
||||
console.warn(
|
||||
`UEBlueprint: ${this.constructor.name} will add attribute ${attributeName} not `
|
||||
+ "defined in the serialized data"
|
||||
`UEBlueprint: ${Self.name} will add attribute ${attributeName} missing from the serialized data`
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -115,8 +115,8 @@ export default class IEntity {
|
||||
set(v) {
|
||||
if (!attribute.predicate?.(v)) {
|
||||
console.warn(
|
||||
`UEBlueprint: Tried to assign attribute ${attributeName} to `
|
||||
+ `${this.constructor.name} not satisfying the predicate`
|
||||
`UEBlueprint: Tried to assign attribute ${attributeName} to`
|
||||
+ `${Self.name} not satisfying the predicate`
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -172,7 +172,9 @@ export default class IEntity {
|
||||
for (const attributeName in attributes) {
|
||||
const attribute = /** @type {AttributeInformation} */(attributes[attributeName])
|
||||
if (attribute.type === undefined && !(attribute.default instanceof Function)) {
|
||||
attribute.type = Utility.getType(attribute.default)
|
||||
attribute.type = attribute.default instanceof Array
|
||||
? [Utility.getType(attribute.default[0])]
|
||||
: Utility.getType(attribute.default)
|
||||
}
|
||||
attributes[attributeName] = {
|
||||
...IEntity.defaultAttribute,
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/** @typedef {import("./IEntity").AnyValueConstructor<*>} AnyValueConstructor */
|
||||
|
||||
export default class IndexedArray {
|
||||
|
||||
#type
|
||||
get type() {
|
||||
return this.#type
|
||||
}
|
||||
|
||||
value = []
|
||||
|
||||
/** @param {AnyValueConstructor} type */
|
||||
constructor(type, value = []) {
|
||||
this.#type = type
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
@@ -414,7 +414,7 @@ export default class ObjectEntity extends IEntity {
|
||||
}
|
||||
|
||||
getDelegatePin() {
|
||||
return this.CustomProperties?.find(pin => pin.PinType$PinCategory === "delegate")
|
||||
return this.CustomProperties?.find(pin => pin.PinType.PinCategory === "delegate")
|
||||
}
|
||||
|
||||
nodeDisplayName() {
|
||||
|
||||
@@ -3,7 +3,6 @@ import ComputedType from "./ComputedType.js"
|
||||
import Configuration from "../Configuration.js"
|
||||
import EnumEntity from "./EnumEntity.js"
|
||||
import FormatTextEntity from "./FormatTextEntity.js"
|
||||
import FunctionReferenceEntity from "./FunctionReferenceEntity.js"
|
||||
import GuidEntity from "./GuidEntity.js"
|
||||
import IEntity from "./IEntity.js"
|
||||
import Integer64Entity from "./Integer64Entity.js"
|
||||
@@ -11,13 +10,12 @@ import IntegerEntity from "./IntegerEntity.js"
|
||||
import LinearColorEntity from "./LinearColorEntity.js"
|
||||
import LocalizedTextEntity from "./LocalizedTextEntity.js"
|
||||
import ObjectReferenceEntity from "./ObjectReferenceEntity.js"
|
||||
import PathSymbolEntity from "./PathSymbolEntity.js"
|
||||
import PinReferenceEntity from "./PinReferenceEntity.js"
|
||||
import PinTypeEntity from "./PinTypeEntity.js"
|
||||
import RotatorEntity from "./RotatorEntity.js"
|
||||
import SimpleSerializationRotatorEntity from "./SimpleSerializationRotatorEntity.js"
|
||||
import SimpleSerializationVector2DEntity from "./SimpleSerializationVector2DEntity.js"
|
||||
import SimpleSerializationVectorEntity from "./SimpleSerializationVectorEntity.js"
|
||||
import TerminalTypeEntity from "./TerminalTypeEntity.js"
|
||||
import UnionType from "./UnionType.js"
|
||||
import Utility from "../Utility.js"
|
||||
import Vector2DEntity from "./Vector2DEntity.js"
|
||||
@@ -71,40 +69,9 @@ export default class PinEntity extends IEntity {
|
||||
type: String,
|
||||
showDefault: false,
|
||||
},
|
||||
PinType$PinCategory: {
|
||||
default: "",
|
||||
},
|
||||
PinType$PinSubCategory: {
|
||||
default: "",
|
||||
},
|
||||
PinType$PinSubCategoryObject: {
|
||||
type: ObjectReferenceEntity,
|
||||
},
|
||||
PinType$PinSubCategoryMemberReference: {
|
||||
type: FunctionReferenceEntity,
|
||||
default: null,
|
||||
},
|
||||
PinType$PinValueType: {
|
||||
type: TerminalTypeEntity,
|
||||
default: null,
|
||||
},
|
||||
PinType$ContainerType: {
|
||||
type: PathSymbolEntity,
|
||||
},
|
||||
PinType$bIsReference: {
|
||||
default: false,
|
||||
},
|
||||
PinType$bIsConst: {
|
||||
default: false,
|
||||
},
|
||||
PinType$bIsWeakPointer: {
|
||||
default: false,
|
||||
},
|
||||
PinType$bIsUObjectWrapper: {
|
||||
default: false,
|
||||
},
|
||||
PinType$bSerializeAsSinglePrecisionFloat: {
|
||||
default: false,
|
||||
PinType: {
|
||||
type: PinTypeEntity,
|
||||
inlined: true,
|
||||
},
|
||||
LinkedTo: {
|
||||
type: [PinReferenceEntity],
|
||||
@@ -167,17 +134,7 @@ export default class PinEntity extends IEntity {
|
||||
/** @type {LocalizedTextEntity | String} */ this.PinFriendlyName
|
||||
/** @type {String} */ this.PinToolTip
|
||||
/** @type {String} */ this.Direction
|
||||
/** @type {String} */ this.PinType$PinCategory
|
||||
/** @type {String} */ this.PinType$PinSubCategory
|
||||
/** @type {ObjectReferenceEntity} */ this.PinType$PinSubCategoryObject
|
||||
/** @type {FunctionReferenceEntity} */ this.PinType$PinSubCategoryMemberReference
|
||||
/** @type {TerminalTypeEntity} */ this.PinType$PinValueType
|
||||
/** @type {PathSymbolEntity} */ this.PinType$ContainerType
|
||||
/** @type {Boolean} */ this.PinType$bIsReference
|
||||
/** @type {Boolean} */ this.PinType$bIsConst
|
||||
/** @type {Boolean} */ this.PinType$bIsWeakPointer
|
||||
/** @type {Boolean} */ this.PinType$bIsUObjectWrapper
|
||||
/** @type {Boolean} */ this.PinType$bIsUObjectWrapper
|
||||
/** @type {PinTypeEntity} */ this.PinType
|
||||
/** @type {PinReferenceEntity[]} */ this.LinkedTo
|
||||
/** @type {T} */ this.DefaultValue
|
||||
/** @type {String} */ this.AutogeneratedDefaultValue
|
||||
@@ -192,12 +149,12 @@ export default class PinEntity extends IEntity {
|
||||
}
|
||||
|
||||
getType() {
|
||||
const subCategory = this.PinType$PinSubCategoryObject
|
||||
if (this.PinType$PinCategory === "struct" || this.PinType$PinCategory === "object") {
|
||||
const subCategory = this.PinType.PinSubCategoryObject
|
||||
if (this.PinType.PinCategory === "struct" || this.PinType.PinCategory === "object") {
|
||||
return subCategory.path
|
||||
}
|
||||
if (
|
||||
this.PinType$PinCategory === "byte"
|
||||
this.PinType.PinCategory === "byte"
|
||||
&& (
|
||||
subCategory.type === Configuration.nodeType.enum
|
||||
|| subCategory.type === Configuration.nodeType.userDefinedEnum
|
||||
@@ -205,7 +162,7 @@ export default class PinEntity extends IEntity {
|
||||
) {
|
||||
return "enum"
|
||||
}
|
||||
return this.PinType$PinCategory
|
||||
return this.PinType.PinCategory
|
||||
}
|
||||
|
||||
getEntityType(alternative = false) {
|
||||
@@ -234,16 +191,16 @@ export default class PinEntity extends IEntity {
|
||||
|
||||
/** @param {PinEntity} other */
|
||||
copyTypeFrom(other) {
|
||||
this.PinType$PinCategory = other.PinType$PinCategory
|
||||
this.PinType$PinSubCategory = other.PinType$PinSubCategory
|
||||
this.PinType$PinSubCategoryObject = other.PinType$PinSubCategoryObject
|
||||
this.PinType$PinSubCategoryMemberReference = other.PinType$PinSubCategoryMemberReference
|
||||
this.PinType$PinValueType = other.PinType$PinValueType
|
||||
this.PinType$ContainerType = other.PinType$ContainerType
|
||||
this.PinType$bIsReference = other.PinType$bIsReference
|
||||
this.PinType$bIsConst = other.PinType$bIsConst
|
||||
this.PinType$bIsWeakPointer = other.PinType$bIsWeakPointer
|
||||
this.PinType$bIsUObjectWrapper = other.PinType$bIsUObjectWrapper
|
||||
this.PinType.PinCategory = other.PinType.PinCategory
|
||||
this.PinType.PinSubCategory = other.PinType.PinSubCategory
|
||||
this.PinType.PinSubCategoryObject = other.PinType.PinSubCategoryObject
|
||||
this.PinType.PinSubCategoryMemberReference = other.PinType.PinSubCategoryMemberReference
|
||||
this.PinType.PinValueType = other.PinType.PinValueType
|
||||
this.PinType.ContainerType = other.PinType.ContainerType
|
||||
this.PinType.bIsReference = other.PinType.bIsReference
|
||||
this.PinType.bIsConst = other.PinType.bIsConst
|
||||
this.PinType.bIsWeakPointer = other.PinType.bIsWeakPointer
|
||||
this.PinType.bIsUObjectWrapper = other.PinType.bIsUObjectWrapper
|
||||
this.PinType$bSerializeAsSinglePrecisionFloat = other.PinType$bSerializeAsSinglePrecisionFloat
|
||||
}
|
||||
|
||||
@@ -255,7 +212,7 @@ export default class PinEntity extends IEntity {
|
||||
}
|
||||
|
||||
isExecution() {
|
||||
return this.PinType$PinCategory === "exec"
|
||||
return this.PinType.PinCategory === "exec"
|
||||
}
|
||||
|
||||
isHidden() {
|
||||
@@ -313,13 +270,13 @@ export default class PinEntity extends IEntity {
|
||||
}
|
||||
|
||||
getSubCategory() {
|
||||
return this.PinType$PinSubCategoryObject.path
|
||||
return this.PinType.PinSubCategoryObject.path
|
||||
}
|
||||
|
||||
/** @return {CSSResult} */
|
||||
pinColor() {
|
||||
return Configuration.pinColor[this.getType()]
|
||||
?? Configuration.pinColor[this.PinType$PinCategory.toLowerCase()]
|
||||
?? Configuration.pinColor[this.PinType.PinCategory.toLowerCase()]
|
||||
?? Configuration.pinColor["default"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import ByteEntity from "../entity/ByteEntity.js"
|
||||
import Configuration from "../Configuration.js"
|
||||
import EnumEntity from "../entity/EnumEntity.js"
|
||||
import FormatTextEntity from "../entity/FormatTextEntity.js"
|
||||
import FunctionReferenceEntity from "../entity/FunctionReferenceEntity.js"
|
||||
import GuidEntity from "../entity/GuidEntity.js"
|
||||
import IdentifierEntity from "../entity/IdentifierEntity.js"
|
||||
import IndexedArray from "../entity/IndexedArray.js"
|
||||
import IEntity from "../entity/IEntity.js"
|
||||
import Integer64Entity from "../entity/Integer64Entity.js"
|
||||
import IntegerEntity from "../entity/IntegerEntity.js"
|
||||
import InvariantTextEntity from "../entity/InvariantTextEntity.js"
|
||||
@@ -273,16 +274,44 @@ export default class Grammar {
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EntityConstructor} entityType
|
||||
* @param {String[]} key
|
||||
* @returns {AttributeInformation}
|
||||
*/
|
||||
static getAttribute(entityType, key) {
|
||||
let result
|
||||
let type
|
||||
if (entityType instanceof UnionType) {
|
||||
for (let t of entityType.types) {
|
||||
if (result = this.getAttribute(t, key)) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
if (entityType instanceof IEntity.constructor) {
|
||||
result = entityType.attributes[key[0]]
|
||||
type = result?.type
|
||||
} else if (entityType instanceof Array) {
|
||||
result = entityType[key[0]]
|
||||
type = result
|
||||
}
|
||||
if (key.length > 1) {
|
||||
return this.getAttribute(type, key.slice(1))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
static createAttributeGrammar(entityType, valueSeparator = this.equalSeparation) {
|
||||
return P.seq(
|
||||
this.attributeName,
|
||||
valueSeparator,
|
||||
).chain(([attributeName, _1]) => {
|
||||
attributeName = Utility.encodeKeyName(attributeName)
|
||||
const attributeKey = attributeName.split(Configuration.keysSeparator)
|
||||
return this
|
||||
.grammarFor(entityType.attributes[attributeName], undefined)
|
||||
.grammarFor(this.getAttribute(entityType, attributeKey))
|
||||
.map(attributeValue =>
|
||||
values => values[attributeName] = attributeValue
|
||||
values => Utility.objectSet(values, attributeKey, attributeValue, true)
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -563,7 +592,7 @@ export default class Grammar {
|
||||
})
|
||||
)
|
||||
|
||||
static indexedArrayEntry = P.lazy(() => {
|
||||
static inlinedArrayEntry = P.lazy(() => {
|
||||
return P.seq(
|
||||
this.symbol,
|
||||
this.regexMap(
|
||||
@@ -574,8 +603,7 @@ export default class Grammar {
|
||||
.chain(([symbol, _1]) =>
|
||||
this.grammarFor(ObjectEntity.attributes[symbol])
|
||||
.map(currentValue =>
|
||||
values => (values[symbol] ??= new IndexedArray(currentValue.constructor))
|
||||
.value.push(currentValue)
|
||||
values => (values[symbol] ??= []).push(currentValue)
|
||||
)
|
||||
)
|
||||
})
|
||||
@@ -588,7 +616,7 @@ export default class Grammar {
|
||||
P.alt(
|
||||
this.customProperty,
|
||||
this.createAttributeGrammar(ObjectEntity),
|
||||
this.indexedArrayEntry
|
||||
this.inlinedArrayEntry
|
||||
)
|
||||
)
|
||||
.map(([_0, entry]) => entry)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Grammar from "./Grammar.js"
|
||||
import IndexedArray from "../entity/IndexedArray.js"
|
||||
import SerializerFactory from "./SerializerFactory.js"
|
||||
import Utility from "../Utility.js"
|
||||
|
||||
@@ -14,13 +13,13 @@ export default class Serializer {
|
||||
|
||||
/** @type {(v: String, entityType: AnyValueConstructor) => String} */
|
||||
static bracketsWrapped = ((v, entityType) => `(${v})`)
|
||||
/** @type {(v: String, entityType: AnyValueConstructor) => String} */
|
||||
static notWrapped = ((v, entityType) => v)
|
||||
/** @type {(v: String) => String} */
|
||||
static same = (v => v)
|
||||
|
||||
/** @param {AnyValueConstructor} entityType */
|
||||
constructor(
|
||||
entityType,
|
||||
wrap = Serializer.bracketsWrapped,
|
||||
wrap = Serializer.same,
|
||||
attributePrefix = "",
|
||||
attributeSeparator = ",",
|
||||
trailingSeparator = false,
|
||||
@@ -85,40 +84,34 @@ export default class Serializer {
|
||||
Object.keys(attributes),
|
||||
Object.keys(entity)
|
||||
)
|
||||
let first = true
|
||||
for (const key of keys) {
|
||||
const value = entity[key]
|
||||
if (value !== undefined && this.showProperty(entity, key)) {
|
||||
const isSerialized = Utility.isSerialized(entity, key)
|
||||
result += (result.length ? attributeSeparator : "")
|
||||
if (first) {
|
||||
first = false
|
||||
} else {
|
||||
result += attributeSeparator
|
||||
}
|
||||
if (attributes[key]?.inlined) {
|
||||
result += this.doWrite(
|
||||
value,
|
||||
insideString,
|
||||
Serializer.notWrapped,
|
||||
`${attributePrefix}${key}.`,
|
||||
attributeSeparator,
|
||||
trailingSeparator,
|
||||
attributeValueConjunctionSign,
|
||||
attributeKeyPrinter
|
||||
)
|
||||
continue
|
||||
}
|
||||
if (value instanceof IndexedArray) {
|
||||
result += this.doWrite(
|
||||
value,
|
||||
insideString,
|
||||
wrap,
|
||||
Serializer.same,
|
||||
attributePrefix,
|
||||
attributeSeparator,
|
||||
trailingSeparator,
|
||||
false,
|
||||
attributeValueConjunctionSign,
|
||||
index => `(${index})`
|
||||
attributes[key].type instanceof Array
|
||||
? k => attributeKeyPrinter(`${key}(${k})`)
|
||||
: k => attributeKeyPrinter(`${key}.${k}`),
|
||||
)
|
||||
continue
|
||||
}
|
||||
result +=
|
||||
attributePrefix
|
||||
+ Utility.decodeKeyName(this.attributeKeyPrinter(key))
|
||||
+ attributeKeyPrinter(key)
|
||||
+ this.attributeValueConjunctionSign
|
||||
+ (
|
||||
isSerialized
|
||||
@@ -127,7 +120,7 @@ export default class Serializer {
|
||||
)
|
||||
}
|
||||
}
|
||||
if (this.trailingSeparator && result.length) {
|
||||
if (trailingSeparator && result.length) {
|
||||
// append separator at the end if asked and there was printed content
|
||||
result += this.attributeSeparator
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ export default class SerializerFactory {
|
||||
|
||||
/**
|
||||
* @template {AnyValue} T
|
||||
* @param {new () => T} entity
|
||||
* @param {new (...any) => T} entity
|
||||
* @returns {Serializer<T>}
|
||||
*/
|
||||
static getSerializer(entity) {
|
||||
|
||||
@@ -45,7 +45,7 @@ export default class EventNodeTemplate extends NodeTemplate {
|
||||
|
||||
createDelegatePinElement() {
|
||||
const pin = /** @type {PinElementConstructor} */(ElementFactory.getConstructor("ueb-pin")).newObject(
|
||||
this.element.getPinEntities().find(v => !v.isHidden() && v.PinType$PinCategory === "delegate"),
|
||||
this.element.getPinEntities().find(v => !v.isHidden() && v.PinType.PinCategory === "delegate"),
|
||||
new MinimalPinTemplate(),
|
||||
this.element
|
||||
)
|
||||
@@ -55,7 +55,7 @@ export default class EventNodeTemplate extends NodeTemplate {
|
||||
|
||||
createPinElements() {
|
||||
return this.element.getPinEntities()
|
||||
.filter(v => !v.isHidden() && v.PinType$PinCategory !== "delegate")
|
||||
.filter(v => !v.isHidden() && v.PinType.PinCategory !== "delegate")
|
||||
.map(pinEntity => /** @type {PinElementConstructor} */(ElementFactory.getConstructor("ueb-pin"))
|
||||
.newObject(pinEntity, undefined, this.element)
|
||||
)
|
||||
|
||||
@@ -76,12 +76,12 @@ export default class PinTemplate extends ITemplate {
|
||||
}
|
||||
|
||||
renderIcon() {
|
||||
switch (this.element.entity.PinType$ContainerType.toString()) {
|
||||
switch (this.element.entity.PinType.ContainerType.toString()) {
|
||||
case "Array": return SVGIcon.array
|
||||
case "Set": return SVGIcon.set
|
||||
case "Map": return SVGIcon.map
|
||||
}
|
||||
if (this.element.entity.PinType$PinCategory.toLocaleLowerCase() === "delegate") {
|
||||
if (this.element.entity.PinType.PinCategory.toLocaleLowerCase() === "delegate") {
|
||||
return SVGIcon.delegate
|
||||
}
|
||||
return SVGIcon.genericPin
|
||||
|
||||
Reference in New Issue
Block a user